ddraw/tests: Test specular lighting with zero shininess in ddraw2.
[wine.git] / dlls / ddraw / tests / ddraw2.c
blob4ae04d12ec5b6f7ac10f1db8b56dc091fe7f6007
1 /*
2 * Copyright 2005 Antoine Chavasse (a.chavasse@gmail.com)
3 * Copyright 2008, 2011, 2012-2014 Stefan Dösinger for CodeWeavers
4 * Copyright 2011-2014 Henri Verbeet for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <math.h>
23 #define COBJMACROS
24 #include "wine/test.h"
25 #include <limits.h>
26 #include <math.h>
27 #include "ddrawi.h"
28 #include "d3dhal.h"
30 static BOOL is_ddraw64 = sizeof(DWORD) != sizeof(DWORD *);
31 static DEVMODEW registry_mode;
33 static HRESULT (WINAPI *pDwmIsCompositionEnabled)(BOOL *);
35 struct vec2
37 float x, y;
40 struct vec4
42 float x, y, z, w;
45 struct create_window_thread_param
47 HWND window;
48 HANDLE window_created;
49 HANDLE destroy_window;
50 HANDLE thread;
53 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
55 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
56 c1 >>= 8; c2 >>= 8;
57 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
58 c1 >>= 8; c2 >>= 8;
59 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
60 c1 >>= 8; c2 >>= 8;
61 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
62 return TRUE;
65 static BOOL compare_float(float f, float g, unsigned int ulps)
67 int x = *(int *)&f;
68 int y = *(int *)&g;
70 if (x < 0)
71 x = INT_MIN - x;
72 if (y < 0)
73 y = INT_MIN - y;
75 if (abs(x - y) > ulps)
76 return FALSE;
78 return TRUE;
81 static BOOL compare_vec4(const struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
83 return compare_float(vec->x, x, ulps)
84 && compare_float(vec->y, y, ulps)
85 && compare_float(vec->z, z, ulps)
86 && compare_float(vec->w, w, ulps);
89 static BOOL ddraw_get_identifier(IDirectDraw2 *ddraw, DDDEVICEIDENTIFIER *identifier)
91 IDirectDraw4 *ddraw4;
92 HRESULT hr;
94 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirectDraw4, (void **)&ddraw4);
95 ok(SUCCEEDED(hr), "Failed to get IDirectDraw4 interface, hr %#x.\n", hr);
96 hr = IDirectDraw4_GetDeviceIdentifier(ddraw4, identifier, 0);
97 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#x.\n", hr);
98 IDirectDraw4_Release(ddraw4);
100 return SUCCEEDED(hr);
103 static BOOL ddraw_is_warp(IDirectDraw2 *ddraw)
105 DDDEVICEIDENTIFIER identifier;
107 return strcmp(winetest_platform, "wine")
108 && ddraw_get_identifier(ddraw, &identifier)
109 && strstr(identifier.szDriver, "warp");
112 static BOOL ddraw_is_vendor(IDirectDraw2 *ddraw, DWORD vendor)
114 DDDEVICEIDENTIFIER identifier;
116 return strcmp(winetest_platform, "wine")
117 && ddraw_get_identifier(ddraw, &identifier)
118 && identifier.dwVendorId == vendor;
121 static BOOL ddraw_is_intel(IDirectDraw2 *ddraw)
123 return ddraw_is_vendor(ddraw, 0x8086);
126 static BOOL ddraw_is_nvidia(IDirectDraw2 *ddraw)
128 return ddraw_is_vendor(ddraw, 0x10de);
131 static BOOL ddraw_is_vmware(IDirectDraw2 *ddraw)
133 return ddraw_is_vendor(ddraw, 0x15ad);
136 static IDirectDrawSurface *create_overlay(IDirectDraw2 *ddraw,
137 unsigned int width, unsigned int height, DWORD format)
139 IDirectDrawSurface *surface;
140 DDSURFACEDESC desc;
142 memset(&desc, 0, sizeof(desc));
143 desc.dwSize = sizeof(desc);
144 desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
145 desc.dwWidth = width;
146 desc.dwHeight = height;
147 desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
148 desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
149 desc.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
150 desc.ddpfPixelFormat.dwFourCC = format;
152 if (FAILED(IDirectDraw2_CreateSurface(ddraw, &desc, &surface, NULL)))
153 return NULL;
154 return surface;
157 static HWND create_window(void)
159 RECT r = {0, 0, 640, 480};
161 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
163 return CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
164 CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
167 static DWORD WINAPI create_window_thread_proc(void *param)
169 struct create_window_thread_param *p = param;
170 DWORD res;
171 BOOL ret;
173 p->window = create_window();
174 ret = SetEvent(p->window_created);
175 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
177 for (;;)
179 MSG msg;
181 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
182 DispatchMessageA(&msg);
183 res = WaitForSingleObject(p->destroy_window, 100);
184 if (res == WAIT_OBJECT_0)
185 break;
186 if (res != WAIT_TIMEOUT)
188 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
189 break;
193 DestroyWindow(p->window);
195 return 0;
198 static void create_window_thread(struct create_window_thread_param *p)
200 DWORD res, tid;
202 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
203 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
204 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
205 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
206 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
207 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
208 res = WaitForSingleObject(p->window_created, INFINITE);
209 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
212 static void destroy_window_thread(struct create_window_thread_param *p)
214 SetEvent(p->destroy_window);
215 WaitForSingleObject(p->thread, INFINITE);
216 CloseHandle(p->destroy_window);
217 CloseHandle(p->window_created);
218 CloseHandle(p->thread);
221 static IDirectDrawSurface *get_depth_stencil(IDirect3DDevice2 *device)
223 IDirectDrawSurface *rt, *ret;
224 DDSCAPS caps = {DDSCAPS_ZBUFFER};
225 HRESULT hr;
227 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
228 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
229 hr = IDirectDrawSurface_GetAttachedSurface(rt, &caps, &ret);
230 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
231 IDirectDrawSurface_Release(rt);
232 return ret;
235 static HRESULT set_display_mode(IDirectDraw2 *ddraw, DWORD width, DWORD height)
237 if (SUCCEEDED(IDirectDraw2_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
238 return DD_OK;
239 return IDirectDraw2_SetDisplayMode(ddraw, width, height, 24, 0, 0);
242 static D3DCOLOR get_surface_color(IDirectDrawSurface *surface, UINT x, UINT y)
244 RECT rect = {x, y, x + 1, y + 1};
245 DDSURFACEDESC surface_desc;
246 D3DCOLOR color;
247 HRESULT hr;
249 memset(&surface_desc, 0, sizeof(surface_desc));
250 surface_desc.dwSize = sizeof(surface_desc);
252 hr = IDirectDrawSurface_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
253 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
254 if (FAILED(hr))
255 return 0xdeadbeef;
257 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
259 hr = IDirectDrawSurface_Unlock(surface, NULL);
260 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
262 return color;
265 static void check_rect(IDirectDrawSurface *surface, RECT r, const char *message)
267 LONG x_coords[2][2] =
269 {r.left - 1, r.left + 1},
270 {r.right + 1, r.right - 1},
272 LONG y_coords[2][2] =
274 {r.top - 1, r.top + 1},
275 {r.bottom + 1, r.bottom - 1}
277 unsigned int i, j, x_side, y_side;
278 DWORD color;
279 LONG x, y;
281 for (i = 0; i < 2; ++i)
283 for (j = 0; j < 2; ++j)
285 for (x_side = 0; x_side < 2; ++x_side)
287 for (y_side = 0; y_side < 2; ++y_side)
289 DWORD expected = (x_side == 1 && y_side == 1) ? 0x00ffffff : 0x00000000;
291 x = x_coords[i][x_side];
292 y = y_coords[j][y_side];
293 if (x < 0 || x >= 640 || y < 0 || y >= 480)
294 continue;
295 color = get_surface_color(surface, x, y);
296 ok(color == expected, "%s: Pixel (%d, %d) has color %08x, expected %08x\n",
297 message, x, y, color, expected);
304 static DWORD get_device_z_depth(IDirect3DDevice2 *device)
306 DDSCAPS caps = {DDSCAPS_ZBUFFER};
307 IDirectDrawSurface *ds, *rt;
308 DDSURFACEDESC desc;
309 HRESULT hr;
311 if (FAILED(IDirect3DDevice2_GetRenderTarget(device, &rt)))
312 return 0;
314 hr = IDirectDrawSurface_GetAttachedSurface(rt, &caps, &ds);
315 IDirectDrawSurface_Release(rt);
316 if (FAILED(hr))
317 return 0;
319 desc.dwSize = sizeof(desc);
320 hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
321 IDirectDrawSurface_Release(ds);
322 if (FAILED(hr))
323 return 0;
325 return U2(desc).dwZBufferBitDepth;
328 static IDirectDraw2 *create_ddraw(void)
330 IDirectDraw2 *ddraw2;
331 IDirectDraw *ddraw1;
332 HRESULT hr;
334 if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
335 return NULL;
337 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2);
338 IDirectDraw_Release(ddraw1);
339 if (FAILED(hr))
340 return NULL;
342 return ddraw2;
345 static IDirect3DDevice2 *create_device(IDirectDraw2 *ddraw, HWND window, DWORD coop_level)
347 /* Prefer 16 bit depth buffers because Nvidia gives us an unpadded D24 buffer if we ask
348 * for 24 bit and handles such buffers incorrectly in DDBLT_DEPTHFILL. AMD only supports
349 * 16 bit buffers in ddraw1/2. Stencil was added in ddraw4, so we cannot create a D24S8
350 * buffer here. */
351 static const DWORD z_depths[] = {16, 32, 24};
352 IDirectDrawSurface *surface, *ds;
353 IDirect3DDevice2 *device = NULL;
354 DDSURFACEDESC surface_desc;
355 IDirect3D2 *d3d;
356 unsigned int i;
357 HRESULT hr;
359 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, coop_level);
360 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
362 memset(&surface_desc, 0, sizeof(surface_desc));
363 surface_desc.dwSize = sizeof(surface_desc);
364 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
365 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
366 surface_desc.dwWidth = 640;
367 surface_desc.dwHeight = 480;
369 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
370 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
372 if (coop_level & DDSCL_NORMAL)
374 IDirectDrawClipper *clipper;
376 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
377 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
378 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
379 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
380 hr = IDirectDrawSurface_SetClipper(surface, clipper);
381 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
382 IDirectDrawClipper_Release(clipper);
385 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
386 if (FAILED(hr))
388 IDirectDrawSurface_Release(surface);
389 return NULL;
392 /* We used to use EnumDevices() for this, but it seems
393 * D3DDEVICEDESC.dwDeviceZBufferBitDepth only has a very casual
394 * relationship with reality. */
395 for (i = 0; i < ARRAY_SIZE(z_depths); ++i)
397 memset(&surface_desc, 0, sizeof(surface_desc));
398 surface_desc.dwSize = sizeof(surface_desc);
399 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
400 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
401 U2(surface_desc).dwZBufferBitDepth = z_depths[i];
402 surface_desc.dwWidth = 640;
403 surface_desc.dwHeight = 480;
404 if (FAILED(IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL)))
405 continue;
407 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
408 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
409 IDirectDrawSurface_Release(ds);
410 if (FAILED(hr))
411 continue;
413 if (SUCCEEDED(IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device)))
414 break;
416 IDirectDrawSurface_DeleteAttachedSurface(surface, 0, ds);
419 IDirect3D2_Release(d3d);
420 IDirectDrawSurface_Release(surface);
421 return device;
424 static IDirect3DViewport2 *create_viewport(IDirect3DDevice2 *device, UINT x, UINT y, UINT w, UINT h)
426 IDirect3DViewport2 *viewport;
427 D3DVIEWPORT2 vp;
428 IDirect3D2 *d3d;
429 HRESULT hr;
431 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
432 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
433 hr = IDirect3D2_CreateViewport(d3d, &viewport, NULL);
434 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
435 hr = IDirect3DDevice2_AddViewport(device, viewport);
436 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
437 memset(&vp, 0, sizeof(vp));
438 vp.dwSize = sizeof(vp);
439 vp.dwX = x;
440 vp.dwY = y;
441 vp.dwWidth = w;
442 vp.dwHeight = h;
443 vp.dvClipX = -1.0f;
444 vp.dvClipY = 1.0f;
445 vp.dvClipWidth = 2.0f;
446 vp.dvClipHeight = 2.0f;
447 vp.dvMinZ = 0.0f;
448 vp.dvMaxZ = 1.0f;
449 hr = IDirect3DViewport2_SetViewport2(viewport, &vp);
450 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
451 IDirect3D2_Release(d3d);
453 return viewport;
456 static void viewport_set_background(IDirect3DDevice2 *device, IDirect3DViewport2 *viewport,
457 IDirect3DMaterial2 *material)
459 D3DMATERIALHANDLE material_handle;
460 HRESULT hr;
462 hr = IDirect3DMaterial2_GetHandle(material, device, &material_handle);
463 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
464 hr = IDirect3DViewport2_SetBackground(viewport, material_handle);
465 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
468 static void destroy_viewport(IDirect3DDevice2 *device, IDirect3DViewport2 *viewport)
470 HRESULT hr;
472 hr = IDirect3DDevice2_DeleteViewport(device, viewport);
473 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
474 IDirect3DViewport2_Release(viewport);
477 static IDirect3DMaterial2 *create_material(IDirect3DDevice2 *device, D3DMATERIAL *mat)
479 IDirect3DMaterial2 *material;
480 IDirect3D2 *d3d;
481 HRESULT hr;
483 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
484 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
485 hr = IDirect3D2_CreateMaterial(d3d, &material, NULL);
486 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
487 hr = IDirect3DMaterial2_SetMaterial(material, mat);
488 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
489 IDirect3D2_Release(d3d);
491 return material;
494 static IDirect3DMaterial2 *create_diffuse_material(IDirect3DDevice2 *device, float r, float g, float b, float a)
496 D3DMATERIAL mat;
498 memset(&mat, 0, sizeof(mat));
499 mat.dwSize = sizeof(mat);
500 U1(U(mat).diffuse).r = r;
501 U2(U(mat).diffuse).g = g;
502 U3(U(mat).diffuse).b = b;
503 U4(U(mat).diffuse).a = a;
505 return create_material(device, &mat);
508 static IDirect3DMaterial2 *create_diffuse_and_ambient_material(IDirect3DDevice2 *device,
509 float r, float g, float b, float a)
511 D3DMATERIAL mat;
513 memset(&mat, 0, sizeof(mat));
514 mat.dwSize = sizeof(mat);
515 U1(U(mat).diffuse).r = r;
516 U2(U(mat).diffuse).g = g;
517 U3(U(mat).diffuse).b = b;
518 U4(U(mat).diffuse).a = a;
520 U1(U(mat).ambient).r = r;
521 U2(U(mat).ambient).g = g;
522 U3(U(mat).ambient).b = b;
523 U4(U(mat).ambient).a = a;
525 return create_material(device, &mat);
528 static IDirect3DMaterial2 *create_specular_material(IDirect3DDevice2 *device,
529 float r, float g, float b, float a, float power)
531 D3DMATERIAL mat;
533 memset(&mat, 0, sizeof(mat));
534 mat.dwSize = sizeof(mat);
535 U1(U2(mat).specular).r = r;
536 U2(U2(mat).specular).g = g;
537 U3(U2(mat).specular).b = b;
538 U4(U2(mat).specular).a = a;
539 U4(mat).power = power;
541 return create_material(device, &mat);
544 static IDirect3DMaterial2 *create_emissive_material(IDirect3DDevice2 *device, float r, float g, float b, float a)
546 D3DMATERIAL mat;
548 memset(&mat, 0, sizeof(mat));
549 mat.dwSize = sizeof(mat);
550 U1(U3(mat).emissive).r = r;
551 U2(U3(mat).emissive).g = g;
552 U3(U3(mat).emissive).b = b;
553 U4(U3(mat).emissive).a = a;
555 return create_material(device, &mat);
558 static void destroy_material(IDirect3DMaterial2 *material)
560 IDirect3DMaterial2_Release(material);
563 struct message
565 UINT message;
566 BOOL check_wparam;
567 WPARAM expect_wparam;
570 static const struct message *expect_messages;
572 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
574 if (expect_messages && message == expect_messages->message)
576 if (expect_messages->check_wparam)
577 ok (wparam == expect_messages->expect_wparam,
578 "Got unexpected wparam %lx for message %x, expected %lx.\n",
579 wparam, message, expect_messages->expect_wparam);
581 ++expect_messages;
584 return DefWindowProcA(hwnd, message, wparam, lparam);
587 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
588 * interface. This prevents subsequent SetCooperativeLevel() calls on a
589 * different window from failing with DDERR_HWNDALREADYSET. */
590 static void fix_wndproc(HWND window, LONG_PTR proc)
592 IDirectDraw2 *ddraw;
593 HRESULT hr;
595 if (!(ddraw = create_ddraw()))
596 return;
598 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
599 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
600 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
601 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
602 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
604 IDirectDraw2_Release(ddraw);
607 static HRESULT CALLBACK restore_callback(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
609 HRESULT hr = IDirectDrawSurface_Restore(surface);
610 ok(SUCCEEDED(hr) || hr == DDERR_IMPLICITLYCREATED, "Failed to restore surface, hr %#x.\n", hr);
611 IDirectDrawSurface_Release(surface);
613 return DDENUMRET_OK;
616 static HRESULT restore_surfaces(IDirectDraw2 *ddraw)
618 return IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
619 NULL, NULL, restore_callback);
622 static void test_coop_level_create_device_window(void)
624 HWND focus_window, device_window;
625 IDirectDraw2 *ddraw;
626 HRESULT hr;
628 focus_window = create_window();
629 ddraw = create_ddraw();
630 ok(!!ddraw, "Failed to create a ddraw object.\n");
632 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
633 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
634 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
635 ok(!device_window, "Unexpected device window found.\n");
636 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
637 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
638 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
639 ok(!device_window, "Unexpected device window found.\n");
640 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
641 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
642 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
643 ok(!device_window, "Unexpected device window found.\n");
644 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
645 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
646 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
647 ok(!device_window, "Unexpected device window found.\n");
648 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
649 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
650 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
651 ok(!device_window, "Unexpected device window found.\n");
653 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
654 if (broken(hr == DDERR_INVALIDPARAMS))
656 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
657 IDirectDraw2_Release(ddraw);
658 DestroyWindow(focus_window);
659 return;
662 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
663 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
664 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
665 ok(!device_window, "Unexpected device window found.\n");
666 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
667 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
668 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
669 ok(!device_window, "Unexpected device window found.\n");
671 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
672 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
673 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
674 ok(!device_window, "Unexpected device window found.\n");
675 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
676 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
677 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
678 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
679 ok(!!device_window, "Device window not found.\n");
681 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
682 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
683 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
684 ok(!device_window, "Unexpected device window found.\n");
685 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
686 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
687 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
688 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
689 ok(!!device_window, "Device window not found.\n");
691 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
692 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
693 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
694 ok(!device_window, "Unexpected device window found.\n");
695 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
696 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
697 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
698 ok(!device_window, "Unexpected device window found.\n");
699 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
700 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
701 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
702 ok(!device_window, "Unexpected device window found.\n");
703 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
704 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
705 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
706 ok(!!device_window, "Device window not found.\n");
708 IDirectDraw2_Release(ddraw);
709 DestroyWindow(focus_window);
712 static void test_clipper_blt(void)
714 IDirectDrawSurface *src_surface, *dst_surface;
715 RECT client_rect, src_rect;
716 IDirectDrawClipper *clipper;
717 DDSURFACEDESC surface_desc;
718 unsigned int i, j, x, y;
719 IDirectDraw2 *ddraw;
720 RGNDATA *rgn_data;
721 D3DCOLOR color;
722 ULONG refcount;
723 HRGN r1, r2;
724 HWND window;
725 DDBLTFX fx;
726 HRESULT hr;
727 DWORD *ptr;
728 DWORD ret;
730 static const DWORD src_data[] =
732 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
733 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
734 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
736 static const D3DCOLOR expected1[] =
738 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
739 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
740 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
741 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
743 /* Nvidia on Windows seems to have an off-by-one error
744 * when processing source rectangles. Our left = 1 and
745 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
746 * read as well, but only for the edge pixels on the
747 * output image. The bug happens on the y axis as well,
748 * but we only read one row there, and all source rows
749 * contain the same data. This bug is not dependent on
750 * the presence of a clipper. */
751 static const D3DCOLOR expected1_broken[] =
753 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
754 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
755 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
756 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
758 static const D3DCOLOR expected2[] =
760 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
761 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
762 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
763 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
766 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
767 10, 10, 640, 480, 0, 0, 0, 0);
768 ShowWindow(window, SW_SHOW);
769 ddraw = create_ddraw();
770 ok(!!ddraw, "Failed to create a ddraw object.\n");
772 ret = GetClientRect(window, &client_rect);
773 ok(ret, "Failed to get client rect.\n");
774 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
775 ok(ret, "Failed to map client rect.\n");
777 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
778 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
780 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
781 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
782 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
783 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
784 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
785 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
786 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
787 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
788 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
789 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
790 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
791 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
792 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
793 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
794 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
795 "Got unexpected bounding rect %s, expected %s.\n",
796 wine_dbgstr_rect(&rgn_data->rdh.rcBound), wine_dbgstr_rect(&client_rect));
797 HeapFree(GetProcessHeap(), 0, rgn_data);
799 r1 = CreateRectRgn(0, 0, 320, 240);
800 ok(!!r1, "Failed to create region.\n");
801 r2 = CreateRectRgn(320, 240, 640, 480);
802 ok(!!r2, "Failed to create region.\n");
803 CombineRgn(r1, r1, r2, RGN_OR);
804 ret = GetRegionData(r1, 0, NULL);
805 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
806 ret = GetRegionData(r1, ret, rgn_data);
807 ok(!!ret, "Failed to get region data.\n");
809 DeleteObject(r2);
810 DeleteObject(r1);
812 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
813 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
814 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
815 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
816 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
817 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
819 HeapFree(GetProcessHeap(), 0, rgn_data);
821 memset(&surface_desc, 0, sizeof(surface_desc));
822 surface_desc.dwSize = sizeof(surface_desc);
823 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
824 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
825 surface_desc.dwWidth = 640;
826 surface_desc.dwHeight = 480;
827 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
828 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
829 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
830 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
831 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
832 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
834 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
835 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
836 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
837 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
839 memset(&fx, 0, sizeof(fx));
840 fx.dwSize = sizeof(fx);
841 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
842 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
843 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
844 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
846 hr = IDirectDrawSurface_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
847 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
848 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
849 ptr = surface_desc.lpSurface;
850 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
851 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
852 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
853 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
854 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
856 hr = IDirectDrawSurface_SetClipper(dst_surface, clipper);
857 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
859 SetRect(&src_rect, 1, 1, 5, 2);
860 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
861 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
862 for (i = 0; i < 4; ++i)
864 for (j = 0; j < 4; ++j)
866 x = 80 * ((2 * j) + 1);
867 y = 60 * ((2 * i) + 1);
868 color = get_surface_color(dst_surface, x, y);
869 ok(compare_color(color, expected1[i * 4 + j], 1)
870 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
871 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
875 U5(fx).dwFillColor = 0xff0000ff;
876 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
877 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
878 for (i = 0; i < 4; ++i)
880 for (j = 0; j < 4; ++j)
882 x = 80 * ((2 * j) + 1);
883 y = 60 * ((2 * i) + 1);
884 color = get_surface_color(dst_surface, x, y);
885 ok(compare_color(color, expected2[i * 4 + j], 1),
886 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
890 hr = IDirectDrawSurface_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
891 ok(hr == DDERR_BLTFASTCANTCLIP || broken(hr == E_NOTIMPL /* NT4 */), "Got unexpected hr %#x.\n", hr);
893 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
894 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
895 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
896 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
897 DestroyWindow(window);
898 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
899 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
900 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
901 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
902 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
903 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
904 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
905 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
906 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
907 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
908 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
909 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
911 IDirectDrawSurface_Release(dst_surface);
912 IDirectDrawSurface_Release(src_surface);
913 refcount = IDirectDrawClipper_Release(clipper);
914 ok(!refcount, "Clipper has %u references left.\n", refcount);
915 IDirectDraw2_Release(ddraw);
918 static void test_coop_level_d3d_state(void)
920 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
921 IDirectDrawSurface *rt, *surface;
922 IDirect3DMaterial2 *background;
923 IDirect3DViewport2 *viewport;
924 IDirect3DDevice2 *device;
925 D3DMATERIAL material;
926 IDirectDraw2 *ddraw;
927 D3DCOLOR color;
928 DWORD value;
929 HWND window;
930 HRESULT hr;
932 window = create_window();
933 ddraw = create_ddraw();
934 ok(!!ddraw, "Failed to create a ddraw object.\n");
935 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
937 skip("Failed to create a 3D device, skipping test.\n");
938 IDirectDraw2_Release(ddraw);
939 DestroyWindow(window);
940 return;
943 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
944 viewport = create_viewport(device, 0, 0, 640, 480);
945 viewport_set_background(device, viewport, background);
947 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
948 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
949 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
950 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
951 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
952 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
953 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
954 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
955 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
956 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
957 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
958 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
959 color = get_surface_color(rt, 320, 240);
960 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
962 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
963 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
964 hr = IDirectDrawSurface_IsLost(rt);
965 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
966 hr = restore_surfaces(ddraw);
967 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
969 memset(&material, 0, sizeof(material));
970 material.dwSize = sizeof(material);
971 U1(U(material).diffuse).r = 0.0f;
972 U2(U(material).diffuse).g = 1.0f;
973 U3(U(material).diffuse).b = 0.0f;
974 U4(U(material).diffuse).a = 1.0f;
975 hr = IDirect3DMaterial2_SetMaterial(background, &material);
976 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
978 hr = IDirect3DDevice2_GetRenderTarget(device, &surface);
979 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
980 ok(surface == rt, "Got unexpected surface %p.\n", surface);
981 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
982 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
983 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
984 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
985 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
986 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
987 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
988 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
989 color = get_surface_color(rt, 320, 240);
990 ok(compare_color(color, 0x0000ff00, 1) || broken(compare_color(color, 0x00000000, 1)),
991 "Got unexpected color 0x%08x.\n", color);
993 destroy_viewport(device, viewport);
994 destroy_material(background);
995 IDirectDrawSurface_Release(surface);
996 IDirectDrawSurface_Release(rt);
997 IDirect3DDevice2_Release(device);
998 IDirectDraw2_Release(ddraw);
999 DestroyWindow(window);
1002 static void test_surface_interface_mismatch(void)
1004 IDirectDraw2 *ddraw = NULL;
1005 IDirect3D2 *d3d = NULL;
1006 IDirectDrawSurface *surface = NULL, *ds;
1007 IDirectDrawSurface3 *surface3 = NULL;
1008 IDirect3DDevice2 *device = NULL;
1009 IDirect3DViewport2 *viewport = NULL;
1010 IDirect3DMaterial2 *background = NULL;
1011 DDSURFACEDESC surface_desc;
1012 DWORD z_depth = 0;
1013 ULONG refcount;
1014 HRESULT hr;
1015 D3DCOLOR color;
1016 HWND window;
1017 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1019 window = create_window();
1020 ddraw = create_ddraw();
1021 ok(!!ddraw, "Failed to create a ddraw object.\n");
1022 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1024 skip("Failed to create a 3D device, skipping test.\n");
1025 IDirectDraw2_Release(ddraw);
1026 DestroyWindow(window);
1027 return;
1029 z_depth = get_device_z_depth(device);
1030 ok(!!z_depth, "Failed to get device z depth.\n");
1031 IDirect3DDevice2_Release(device);
1032 device = NULL;
1034 memset(&surface_desc, 0, sizeof(surface_desc));
1035 surface_desc.dwSize = sizeof(surface_desc);
1036 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1037 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1038 surface_desc.dwWidth = 640;
1039 surface_desc.dwHeight = 480;
1041 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1042 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1044 hr = IDirectDrawSurface2_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
1045 if (FAILED(hr))
1047 skip("Failed to get the IDirectDrawSurface3 interface, skipping test.\n");
1048 goto cleanup;
1051 if (FAILED(IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d)))
1053 skip("D3D interface is not available, skipping test.\n");
1054 goto cleanup;
1057 memset(&surface_desc, 0, sizeof(surface_desc));
1058 surface_desc.dwSize = sizeof(surface_desc);
1059 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
1060 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1061 U2(surface_desc).dwZBufferBitDepth = z_depth;
1062 surface_desc.dwWidth = 640;
1063 surface_desc.dwHeight = 480;
1064 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
1065 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
1066 if (FAILED(hr))
1067 goto cleanup;
1069 /* Using a different surface interface version still works */
1070 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
1071 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
1072 refcount = IDirectDrawSurface_Release(ds);
1073 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
1074 if (FAILED(hr))
1075 goto cleanup;
1077 /* Here too */
1078 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface *)surface3, &device);
1079 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
1080 if (FAILED(hr))
1081 goto cleanup;
1083 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1084 viewport = create_viewport(device, 0, 0, 640, 480);
1085 viewport_set_background(device, viewport, background);
1087 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1088 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1089 color = get_surface_color(surface, 320, 240);
1090 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1092 cleanup:
1093 if (viewport)
1094 destroy_viewport(device, viewport);
1095 if (background)
1096 destroy_material(background);
1097 if (surface3) IDirectDrawSurface3_Release(surface3);
1098 if (surface) IDirectDrawSurface_Release(surface);
1099 if (device) IDirect3DDevice2_Release(device);
1100 if (d3d) IDirect3D2_Release(d3d);
1101 if (ddraw) IDirectDraw2_Release(ddraw);
1102 DestroyWindow(window);
1105 static void test_coop_level_threaded(void)
1107 struct create_window_thread_param p;
1108 IDirectDraw2 *ddraw;
1109 HRESULT hr;
1111 ddraw = create_ddraw();
1112 ok(!!ddraw, "Failed to create a ddraw object.\n");
1113 create_window_thread(&p);
1115 hr = IDirectDraw2_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1116 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1118 IDirectDraw2_Release(ddraw);
1119 destroy_window_thread(&p);
1122 static void test_depth_blit(void)
1124 static D3DLVERTEX quad1[] =
1126 {{-1.0}, { 1.0}, {0.50f}, 0, {0xff00ff00}},
1127 {{ 1.0}, { 1.0}, {0.50f}, 0, {0xff00ff00}},
1128 {{-1.0}, {-1.0}, {0.50f}, 0, {0xff00ff00}},
1129 {{ 1.0}, {-1.0}, {0.50f}, 0, {0xff00ff00}},
1131 static const D3DCOLOR expected_colors[4][4] =
1133 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1134 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1135 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1136 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1138 DDSURFACEDESC ddsd_new, ddsd_existing;
1140 IDirect3DDevice2 *device;
1141 IDirectDrawSurface *ds1, *ds2, *ds3, *rt;
1142 IDirect3DViewport2 *viewport;
1143 RECT src_rect, dst_rect;
1144 unsigned int i, j;
1145 D3DCOLOR color;
1146 HRESULT hr;
1147 IDirectDraw2 *ddraw;
1148 DDBLTFX fx;
1149 HWND window;
1150 D3DRECT d3drect;
1151 IDirect3DMaterial2 *background;
1153 window = create_window();
1154 ddraw = create_ddraw();
1155 ok(!!ddraw, "Failed to create a ddraw object.\n");
1156 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1158 skip("Failed to create a 3D device, skipping test.\n");
1159 IDirectDraw2_Release(ddraw);
1160 DestroyWindow(window);
1161 return;
1164 ds1 = get_depth_stencil(device);
1166 memset(&ddsd_new, 0, sizeof(ddsd_new));
1167 ddsd_new.dwSize = sizeof(ddsd_new);
1168 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1169 ddsd_existing.dwSize = sizeof(ddsd_existing);
1170 hr = IDirectDrawSurface_GetSurfaceDesc(ds1, &ddsd_existing);
1171 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
1172 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1173 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1174 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1175 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1176 ddsd_new.ddpfPixelFormat = ddsd_existing.ddpfPixelFormat;
1177 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1178 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1179 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1180 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1182 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1183 viewport = create_viewport(device, 0, 0, ddsd_existing.dwWidth, ddsd_existing.dwHeight);
1184 viewport_set_background(device, viewport, background);
1185 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1186 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
1188 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1189 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
1190 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1191 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
1193 U1(d3drect).x1 = U2(d3drect).y1 = 0;
1194 U3(d3drect).x2 = ddsd_existing.dwWidth; U4(d3drect).y2 = ddsd_existing.dwHeight;
1195 hr = IDirect3DViewport2_Clear(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER);
1196 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
1198 /* Partial blit. */
1199 SetRect(&src_rect, 0, 0, 320, 240);
1200 SetRect(&dst_rect, 0, 0, 320, 240);
1201 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1202 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1203 /* Different locations. */
1204 SetRect(&src_rect, 0, 0, 320, 240);
1205 SetRect(&dst_rect, 320, 240, 640, 480);
1206 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1207 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1208 /* Stretched. */
1209 SetRect(&src_rect, 0, 0, 320, 240);
1210 SetRect(&dst_rect, 0, 0, 640, 480);
1211 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1212 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1213 /* Flipped. */
1214 SetRect(&src_rect, 0, 480, 640, 0);
1215 SetRect(&dst_rect, 0, 0, 640, 480);
1216 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1217 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1218 SetRect(&src_rect, 0, 0, 640, 480);
1219 SetRect(&dst_rect, 0, 480, 640, 0);
1220 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1221 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1222 /* Full, explicit. */
1223 SetRect(&src_rect, 0, 0, 640, 480);
1224 SetRect(&dst_rect, 0, 0, 640, 480);
1225 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1226 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1227 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1229 /* Depth blit inside a BeginScene / EndScene pair */
1230 hr = IDirect3DDevice2_BeginScene(device);
1231 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1232 /* From the current depth stencil */
1233 hr = IDirectDrawSurface_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1234 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1235 /* To the current depth stencil */
1236 hr = IDirectDrawSurface_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1237 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1238 /* Between unbound surfaces */
1239 hr = IDirectDrawSurface_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1240 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1241 hr = IDirect3DDevice2_EndScene(device);
1242 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1244 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1245 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1246 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1247 * a reliable result(z = 0.0) */
1248 memset(&fx, 0, sizeof(fx));
1249 fx.dwSize = sizeof(fx);
1250 U5(fx).dwFillDepth = 0;
1251 hr = IDirectDrawSurface_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1252 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1254 /* This clears the Z buffer with 1.0 */
1255 hr = IDirect3DViewport2_Clear(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET);
1256 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1258 SetRect(&dst_rect, 0, 0, 320, 240);
1259 hr = IDirectDrawSurface_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1260 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1261 IDirectDrawSurface_Release(ds3);
1262 IDirectDrawSurface_Release(ds2);
1263 IDirectDrawSurface_Release(ds1);
1265 hr = IDirect3DDevice2_BeginScene(device);
1266 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1267 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad1, 4, 0);
1268 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1269 hr = IDirect3DDevice2_EndScene(device);
1270 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1272 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1273 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1274 for (i = 0; i < 4; ++i)
1276 for (j = 0; j < 4; ++j)
1278 unsigned int x = 80 * ((2 * j) + 1);
1279 unsigned int y = 60 * ((2 * i) + 1);
1280 color = get_surface_color(rt, x, y);
1281 ok(compare_color(color, expected_colors[i][j], 1),
1282 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1285 IDirectDrawSurface_Release(rt);
1287 destroy_viewport(device, viewport);
1288 destroy_material(background);
1289 IDirect3DDevice2_Release(device);
1290 IDirectDraw2_Release(ddraw);
1291 DestroyWindow(window);
1294 static void test_texture_load_ckey(void)
1296 IDirectDraw2 *ddraw = NULL;
1297 IDirectDrawSurface *src = NULL;
1298 IDirectDrawSurface *dst = NULL;
1299 IDirect3DTexture *src_tex = NULL;
1300 IDirect3DTexture *dst_tex = NULL;
1301 DDSURFACEDESC ddsd;
1302 HRESULT hr;
1303 DDCOLORKEY ckey;
1305 ddraw = create_ddraw();
1306 ok(!!ddraw, "Failed to create a ddraw object.\n");
1307 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
1308 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1310 memset(&ddsd, 0, sizeof(ddsd));
1311 ddsd.dwSize = sizeof(ddsd);
1312 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1313 ddsd.dwHeight = 128;
1314 ddsd.dwWidth = 128;
1315 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1316 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &src, NULL);
1317 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1318 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1319 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &dst, NULL);
1320 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1322 hr = IDirectDrawSurface_QueryInterface(src, &IID_IDirect3DTexture, (void **)&src_tex);
1323 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get Direct3DTexture interface, hr %#x.\n", hr);
1324 if (FAILED(hr))
1326 /* 64 bit ddraw does not support d3d */
1327 skip("Could not get Direct3DTexture interface, skipping texture::Load color keying tests.\n");
1328 goto done;
1330 hr = IDirectDrawSurface_QueryInterface(dst, &IID_IDirect3DTexture, (void **)&dst_tex);
1331 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture interface, hr %#x.\n", hr);
1333 /* No surface has a color key */
1334 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1335 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDCAPS), "Got unexpected hr %#x.\n", hr);
1336 if (FAILED(hr))
1338 /* Testbot Windows NT VMs */
1339 skip("IDirect3DTexture::Load does not work, skipping color keying tests.\n");
1340 goto done;
1343 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1344 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1345 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1346 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1347 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1349 /* Source surface has a color key */
1350 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1351 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1352 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1353 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1354 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1355 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1356 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1357 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1358 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1360 /* Both surfaces have a color key: Dest ckey is overwritten */
1361 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1362 hr = IDirectDrawSurface_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1363 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1364 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1365 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1366 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1367 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1368 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1369 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1371 /* Only the destination has a color key: It is not deleted */
1372 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1373 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1374 hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1375 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1376 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1377 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1378 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1379 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1380 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1381 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1383 done:
1384 if (dst_tex) IDirect3DTexture_Release(dst_tex);
1385 if (src_tex) IDirect3DTexture_Release(src_tex);
1386 if (dst) IDirectDrawSurface_Release(dst);
1387 if (src) IDirectDrawSurface_Release(src);
1388 if (ddraw) IDirectDraw2_Release(ddraw);
1391 static ULONG get_refcount(IUnknown *test_iface)
1393 IUnknown_AddRef(test_iface);
1394 return IUnknown_Release(test_iface);
1397 static void test_viewport_object(void)
1399 IDirectDraw2 *ddraw;
1400 IDirect3D2 *d3d;
1401 HRESULT hr;
1402 ULONG ref, old_d3d_ref;
1403 D3DVIEWPORT vp;
1404 D3DVIEWPORT2 vp2;
1405 IDirect3DViewport *viewport;
1406 IDirect3DViewport2 *viewport2, *another_vp, *test_vp;
1407 IDirect3DViewport3 *viewport3;
1408 IDirectDrawGammaControl *gamma;
1409 IUnknown *unknown;
1410 IDirect3DDevice2 *device;
1411 HWND window;
1412 union
1414 D3DVIEWPORT2 vp2;
1415 D3DVIEWPORT vp1;
1416 BYTE blob[1024];
1417 } desc;
1419 window = create_window();
1420 ddraw = create_ddraw();
1421 ok(!!ddraw, "Failed to create a ddraw object.\n");
1422 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1424 skip("Failed to create a 3D device, skipping test.\n");
1425 IDirectDraw_Release(ddraw);
1426 DestroyWindow(window);
1427 return;
1430 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
1431 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get d3d interface, hr %#x.\n", hr);
1432 if (FAILED(hr))
1434 skip("D3D interface is not available, skipping test.\n");
1435 IDirectDraw2_Release(ddraw);
1436 return;
1438 old_d3d_ref = get_refcount((IUnknown *)d3d);
1440 hr = IDirect3D2_CreateViewport(d3d, &viewport2, NULL);
1441 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1442 ref = get_refcount((IUnknown *)viewport2);
1443 ok(ref == 1, "Got unexpected refcount %u.\n", ref);
1444 ref = get_refcount((IUnknown *)d3d);
1445 ok(ref == old_d3d_ref, "Got unexpected refcount %u.\n", ref);
1447 memset(&desc, 0, sizeof(desc));
1448 hr = IDirect3DViewport2_GetViewport(viewport2, &desc.vp1);
1449 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1450 desc.vp1.dwSize = sizeof(desc.vp1) + 1;
1451 hr = IDirect3DViewport2_GetViewport(viewport2, &desc.vp1);
1452 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1453 desc.vp1.dwSize = sizeof(desc.vp1) - 1;
1454 hr = IDirect3DViewport2_GetViewport(viewport2, &desc.vp1);
1455 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1456 desc.vp1.dwSize = sizeof(desc.vp1);
1457 hr = IDirect3DViewport2_GetViewport(viewport2, &desc.vp1);
1458 ok(hr == D3DERR_VIEWPORTDATANOTSET, "Got unexpected hr %#x.\n", hr);
1459 ok(desc.vp1.dwSize == sizeof(desc.vp1), "Got unexpected dwSize %u.\n", desc.vp1.dwSize);
1460 hr = IDirect3DViewport2_GetViewport2(viewport2, &desc.vp2);
1461 ok(hr == D3DERR_VIEWPORTDATANOTSET, "Got unexpected hr %#x.\n", hr);
1462 ok(desc.vp2.dwSize == sizeof(desc.vp2), "Got unexpected dwSize %u.\n", desc.vp2.dwSize);
1463 desc.vp2.dwSize = sizeof(desc.vp2) + 1;
1464 hr = IDirect3DViewport2_GetViewport2(viewport2, &desc.vp2);
1465 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1467 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1468 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirectDrawGammaControl, (void **)&gamma);
1469 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
1470 ok(!gamma, "Interface not set to NULL by failed QI call: %p\n", gamma);
1471 /* NULL iid: Segfaults */
1473 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirect3DViewport, (void **)&viewport);
1474 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport, hr %#x.\n", hr);
1475 ref = get_refcount((IUnknown *)viewport);
1476 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1477 ref = get_refcount((IUnknown *)viewport2);
1478 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1479 IDirect3DViewport_Release(viewport);
1480 viewport = NULL;
1482 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirect3DViewport3, (void **)&viewport3);
1483 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1484 if (viewport3)
1486 ref = get_refcount((IUnknown *)viewport2);
1487 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1488 ref = get_refcount((IUnknown *)viewport3);
1489 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1490 IDirect3DViewport3_Release(viewport3);
1493 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IUnknown, (void **)&unknown);
1494 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1495 ref = get_refcount((IUnknown *)viewport2);
1496 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1497 ref = get_refcount(unknown);
1498 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1499 IUnknown_Release(unknown);
1501 hr = IDirect3DDevice2_DeleteViewport(device, NULL);
1502 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1503 hr = IDirect3DDevice2_GetCurrentViewport(device, NULL);
1504 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1506 hr = IDirect3D2_CreateViewport(d3d, &another_vp, NULL);
1507 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1509 /* Setting a viewport not in the viewport list fails */
1510 hr = IDirect3DDevice2_SetCurrentViewport(device, another_vp);
1511 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1513 /* AddViewport(NULL): Segfault */
1514 hr = IDirect3DDevice2_AddViewport(device, viewport2);
1515 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1516 ref = get_refcount((IUnknown *) viewport2);
1517 ok(ref == 2, "viewport2 refcount is %u.\n", ref);
1518 hr = IDirect3DDevice2_AddViewport(device, another_vp);
1519 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1520 ref = get_refcount((IUnknown *) another_vp);
1521 ok(ref == 2, "another_vp refcount is %u.\n", ref);
1523 test_vp = (IDirect3DViewport2 *) 0xbaadc0de;
1524 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1525 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1526 ok(test_vp == (IDirect3DViewport2 *) 0xbaadc0de, "Got unexpected pointer %p\n", test_vp);
1528 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport2);
1529 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1530 ref = get_refcount((IUnknown *) viewport2);
1531 ok(ref == 3, "Got unexpected refcount %u.\n", ref);
1532 ref = get_refcount((IUnknown *) device);
1533 ok(ref == 1, "Got unexpected refcount %u.\n", ref);
1535 test_vp = NULL;
1536 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1537 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1538 ok(test_vp == viewport2, "Got unexpected viewport %p\n", test_vp);
1539 ref = get_refcount((IUnknown *) viewport2);
1540 ok(ref == 4, "Got unexpected refcount %u.\n", ref);
1541 if (test_vp)
1542 IDirect3DViewport2_Release(test_vp);
1544 /* GetCurrentViewport with a viewport set and NULL input param: Segfault */
1546 /* Cannot set the viewport to NULL */
1547 hr = IDirect3DDevice2_SetCurrentViewport(device, NULL);
1548 ok(hr == DDERR_INVALIDPARAMS, "Failed to set viewport to NULL, hr %#x.\n", hr);
1549 test_vp = NULL;
1550 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1551 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1552 ok(test_vp == viewport2, "Got unexpected viewport %p\n", test_vp);
1553 if (test_vp)
1554 IDirect3DViewport2_Release(test_vp);
1556 /* SetCurrentViewport properly releases the old viewport's reference */
1557 hr = IDirect3DDevice2_SetCurrentViewport(device, another_vp);
1558 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1559 ref = get_refcount((IUnknown *) viewport2);
1560 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1561 ref = get_refcount((IUnknown *) another_vp);
1562 ok(ref == 3, "Got unexpected refcount %u.\n", ref);
1564 /* Deleting the viewport removes the reference added by AddViewport, but not
1565 * the one added by SetCurrentViewport. */
1566 hr = IDirect3DDevice2_DeleteViewport(device, another_vp);
1567 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1568 ref = get_refcount((IUnknown *) another_vp);
1569 todo_wine ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1571 /* GetCurrentViewport fails though */
1572 test_vp = NULL;
1573 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1574 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1575 ok(!test_vp, "Got unexpected viewport %p\n", test_vp);
1577 /* Setting a different viewport does not free the leaked reference. How
1578 * do I get rid of it? Leak the viewport for now. */
1579 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport2);
1580 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1581 ref = get_refcount((IUnknown *) viewport2);
1582 ok(ref == 3, "Got unexpected refcount %u.\n", ref);
1583 ref = get_refcount((IUnknown *) another_vp);
1584 todo_wine ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1586 memset(&vp, 0, sizeof(vp));
1587 memset(&vp, 0, sizeof(vp2));
1588 vp.dwX = vp2.dwX = 0;
1589 vp.dwY = vp2.dwY = 0;
1590 vp.dwWidth = vp2.dwWidth = 640;
1591 vp.dwHeight = vp2.dwHeight = 480;
1592 vp.dvMinZ = vp2.dvMinZ = 0.0f;
1593 vp.dvMaxZ = vp2.dvMaxZ = 1.0f;
1594 vp.dvScaleX = vp.dwWidth / 2.0f;
1595 vp.dvScaleY = vp.dwHeight / 2.0f;
1596 vp.dvMaxX = 1.0f;
1597 vp.dvMaxY = 1.0f;
1598 vp2.dvClipX = -1.0f;
1599 vp2.dvClipY = 1.0f;
1600 vp2.dvClipWidth = 2.0f;
1601 vp2.dvClipHeight = 2.0f;
1602 hr = IDirect3DViewport2_SetViewport(viewport2, &vp);
1603 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1604 hr = IDirect3DViewport2_SetViewport2(viewport2, &vp2);
1605 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1607 vp.dwSize = sizeof(vp);
1608 hr = IDirect3DViewport2_SetViewport(viewport2, &vp);
1609 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
1610 vp2.dwSize = sizeof(vp2);
1611 hr = IDirect3DViewport2_SetViewport2(viewport2, &vp2);
1612 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
1614 /* Destroying the device removes the viewport, but does not free the reference
1615 * added by SetCurrentViewport. */
1616 IDirect3DDevice2_Release(device);
1617 ref = get_refcount((IUnknown *) viewport2);
1618 todo_wine ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1620 vp.dwSize = sizeof(vp);
1621 hr = IDirect3DViewport2_SetViewport(viewport2, &vp);
1622 ok(hr == D3DERR_VIEWPORTHASNODEVICE, "Got unexpected hr %#x.\n", hr);
1623 vp2.dwSize = sizeof(vp2);
1624 hr = IDirect3DViewport2_SetViewport2(viewport2, &vp2);
1625 ok(hr == D3DERR_VIEWPORTHASNODEVICE, "Got unexpected hr %#x.\n", hr);
1627 IDirect3DViewport2_Release(another_vp);
1628 IDirect3DViewport2_Release(viewport2);
1629 IDirect3D2_Release(d3d);
1630 DestroyWindow(window);
1631 IDirectDraw2_Release(ddraw);
1634 static void test_zenable(void)
1636 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1637 static D3DTLVERTEX tquad[] =
1639 {{ 0.0f}, {480.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1640 {{ 0.0f}, { 0.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1641 {{640.0f}, {480.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1642 {{640.0f}, { 0.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1644 IDirect3DMaterial2 *background;
1645 IDirect3DViewport2 *viewport;
1646 IDirect3DDevice2 *device;
1647 IDirectDrawSurface *rt;
1648 IDirectDraw2 *ddraw;
1649 D3DCOLOR color;
1650 HWND window;
1651 HRESULT hr;
1652 UINT x, y;
1653 UINT i, j;
1655 window = create_window();
1656 ddraw = create_ddraw();
1657 ok(!!ddraw, "Failed to create a ddraw object.\n");
1658 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1660 skip("Failed to create a 3D device, skipping test.\n");
1661 IDirectDraw2_Release(ddraw);
1662 DestroyWindow(window);
1663 return;
1666 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1667 viewport = create_viewport(device, 0, 0, 640, 480);
1668 viewport_set_background(device, viewport, background);
1669 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1670 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1672 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1673 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1675 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1676 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1677 hr = IDirect3DDevice2_BeginScene(device);
1678 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1679 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, tquad, 4, 0);
1680 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1681 hr = IDirect3DDevice2_EndScene(device);
1682 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1684 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1685 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1686 for (i = 0; i < 4; ++i)
1688 for (j = 0; j < 4; ++j)
1690 x = 80 * ((2 * j) + 1);
1691 y = 60 * ((2 * i) + 1);
1692 color = get_surface_color(rt, x, y);
1693 ok(compare_color(color, 0x0000ff00, 1),
1694 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1697 IDirectDrawSurface_Release(rt);
1699 destroy_viewport(device, viewport);
1700 destroy_material(background);
1701 IDirect3DDevice2_Release(device);
1702 IDirectDraw2_Release(ddraw);
1703 DestroyWindow(window);
1706 static void test_ck_rgba(void)
1708 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1709 static D3DTLVERTEX tquad[] =
1711 {{ 0.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1712 {{ 0.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1713 {{640.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1714 {{640.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1715 {{ 0.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1716 {{ 0.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1717 {{640.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1718 {{640.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1720 static const struct
1722 D3DCOLOR fill_color;
1723 BOOL color_key;
1724 BOOL blend;
1725 D3DCOLOR result1, result1_broken;
1726 D3DCOLOR result2, result2_broken;
1728 tests[] =
1730 /* r200 on Windows doesn't check the alpha component when applying the color
1731 * key, so the key matches on every texel. */
1732 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1733 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1734 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1735 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1736 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00ff0000, 0x00807f00, 0x000000ff},
1737 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x00ff0000, 0x0000ff00, 0x000000ff},
1738 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00, 0x00807f00, 0x00807f00},
1739 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1742 D3DTEXTUREHANDLE texture_handle;
1743 IDirect3DMaterial2 *background;
1744 IDirectDrawSurface *surface;
1745 IDirect3DViewport2 *viewport;
1746 IDirect3DTexture2 *texture;
1747 DDSURFACEDESC surface_desc;
1748 IDirect3DDevice2 *device;
1749 IDirectDrawSurface *rt;
1750 IDirectDraw2 *ddraw;
1751 D3DCOLOR color;
1752 HWND window;
1753 DDBLTFX fx;
1754 HRESULT hr;
1755 UINT i;
1757 window = create_window();
1758 ddraw = create_ddraw();
1759 ok(!!ddraw, "Failed to create a ddraw object.\n");
1760 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1762 skip("Failed to create a 3D device, skipping test.\n");
1763 IDirectDraw2_Release(ddraw);
1764 DestroyWindow(window);
1765 return;
1768 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1769 viewport = create_viewport(device, 0, 0, 640, 480);
1770 viewport_set_background(device, viewport, background);
1771 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1772 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1774 memset(&surface_desc, 0, sizeof(surface_desc));
1775 surface_desc.dwSize = sizeof(surface_desc);
1776 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1777 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1778 surface_desc.dwWidth = 256;
1779 surface_desc.dwHeight = 256;
1780 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1781 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1782 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1783 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1784 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1785 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1786 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1787 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1788 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1789 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1790 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1791 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1792 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1793 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
1794 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1795 IDirect3DTexture2_Release(texture);
1797 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1798 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1799 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1800 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1801 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1802 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1804 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1805 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1807 for (i = 0; i < ARRAY_SIZE(tests); ++i)
1809 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1810 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1811 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1812 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1814 memset(&fx, 0, sizeof(fx));
1815 fx.dwSize = sizeof(fx);
1816 U5(fx).dwFillColor = tests[i].fill_color;
1817 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1818 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1820 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
1821 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1822 hr = IDirect3DDevice2_BeginScene(device);
1823 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1824 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
1825 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1826 hr = IDirect3DDevice2_EndScene(device);
1827 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1829 color = get_surface_color(rt, 320, 240);
1830 ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
1831 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1832 tests[i].result1, i, color);
1834 U5(fx).dwFillColor = 0xff0000ff;
1835 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1836 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1838 hr = IDirect3DDevice2_BeginScene(device);
1839 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1840 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[4], 4, 0);
1841 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1842 hr = IDirect3DDevice2_EndScene(device);
1843 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1845 /* This tests that fragments that are masked out by the color key are
1846 * discarded, instead of just fully transparent. */
1847 color = get_surface_color(rt, 320, 240);
1848 ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
1849 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1850 tests[i].result2, i, color);
1853 IDirectDrawSurface_Release(rt);
1854 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1855 ok(SUCCEEDED(hr), "Failed to unset texture, hr %#x.\n", hr);
1856 IDirectDrawSurface_Release(surface);
1857 destroy_viewport(device, viewport);
1858 destroy_material(background);
1859 IDirect3DDevice2_Release(device);
1860 IDirectDraw2_Release(ddraw);
1861 DestroyWindow(window);
1864 static void test_ck_default(void)
1866 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1867 static D3DTLVERTEX tquad[] =
1869 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1870 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1871 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1872 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1874 IDirectDrawSurface *surface, *rt;
1875 D3DTEXTUREHANDLE texture_handle;
1876 IDirect3DMaterial2 *background;
1877 IDirect3DViewport2 *viewport;
1878 DDSURFACEDESC surface_desc;
1879 IDirect3DTexture2 *texture;
1880 IDirect3DDevice2 *device;
1881 IDirectDraw2 *ddraw;
1882 D3DCOLOR color;
1883 DWORD value;
1884 HWND window;
1885 DDBLTFX fx;
1886 HRESULT hr;
1888 window = create_window();
1889 ddraw = create_ddraw();
1890 ok(!!ddraw, "Failed to create a ddraw object.\n");
1891 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1893 skip("Failed to create a 3D device, skipping test.\n");
1894 IDirectDraw2_Release(ddraw);
1895 DestroyWindow(window);
1896 return;
1899 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1900 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1902 background = create_diffuse_material(device, 0.0, 1.0f, 0.0f, 1.0f);
1903 viewport = create_viewport(device, 0, 0, 640, 480);
1904 viewport_set_background(device, viewport, background);
1905 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1906 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1908 memset(&surface_desc, 0, sizeof(surface_desc));
1909 surface_desc.dwSize = sizeof(surface_desc);
1910 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1911 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1912 surface_desc.dwWidth = 256;
1913 surface_desc.dwHeight = 256;
1914 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1915 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
1916 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1917 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1918 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1919 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1920 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1921 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1922 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1923 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1924 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1925 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1926 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
1927 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1928 IDirect3DTexture_Release(texture);
1930 memset(&fx, 0, sizeof(fx));
1931 fx.dwSize = sizeof(fx);
1932 U5(fx).dwFillColor = 0x000000ff;
1933 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1934 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1936 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1937 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1938 hr = IDirect3DDevice2_BeginScene(device);
1939 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1940 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1941 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
1942 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1943 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1944 ok(!value, "Got unexpected color keying state %#x.\n", value);
1945 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
1946 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1947 hr = IDirect3DDevice2_EndScene(device);
1948 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1949 color = get_surface_color(rt, 320, 240);
1950 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1952 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1953 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1954 hr = IDirect3DDevice2_BeginScene(device);
1955 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1956 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1957 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1958 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
1959 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1960 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1961 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1962 ok(!!value, "Got unexpected color keying state %#x.\n", value);
1963 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1964 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
1965 hr = IDirect3DDevice2_EndScene(device);
1966 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1967 color = get_surface_color(rt, 320, 240);
1968 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1970 IDirectDrawSurface_Release(surface);
1971 destroy_viewport(device, viewport);
1972 destroy_material(background);
1973 IDirectDrawSurface_Release(rt);
1974 IDirect3DDevice2_Release(device);
1975 IDirectDraw2_Release(ddraw);
1976 DestroyWindow(window);
1979 static void test_ck_complex(void)
1981 IDirectDrawSurface *surface, *mipmap, *tmp;
1982 DDSCAPS caps = {DDSCAPS_COMPLEX};
1983 DDSURFACEDESC surface_desc;
1984 IDirect3DDevice2 *device;
1985 DDCOLORKEY color_key;
1986 IDirectDraw2 *ddraw;
1987 unsigned int i;
1988 ULONG refcount;
1989 HWND window;
1990 HRESULT hr;
1992 window = create_window();
1993 ddraw = create_ddraw();
1994 ok(!!ddraw, "Failed to create a ddraw object.\n");
1995 if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
1997 skip("Failed to create a 3D device, skipping test.\n");
1998 DestroyWindow(window);
1999 IDirectDraw2_Release(ddraw);
2000 return;
2002 IDirect3DDevice2_Release(device);
2004 memset(&surface_desc, 0, sizeof(surface_desc));
2005 surface_desc.dwSize = sizeof(surface_desc);
2006 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2007 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2008 surface_desc.dwWidth = 128;
2009 surface_desc.dwHeight = 128;
2010 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2011 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2013 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2014 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
2015 color_key.dwColorSpaceLowValue = 0x0000ff00;
2016 color_key.dwColorSpaceHighValue = 0x0000ff00;
2017 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2018 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2019 memset(&color_key, 0, sizeof(color_key));
2020 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2021 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2022 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2023 color_key.dwColorSpaceLowValue);
2024 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2025 color_key.dwColorSpaceHighValue);
2027 mipmap = surface;
2028 IDirectDrawSurface_AddRef(mipmap);
2029 for (i = 0; i < 7; ++i)
2031 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
2032 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
2034 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2035 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
2036 color_key.dwColorSpaceLowValue = 0x000000ff;
2037 color_key.dwColorSpaceHighValue = 0x000000ff;
2038 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2039 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x, i %u.\n", hr, i);
2040 memset(&color_key, 0, sizeof(color_key));
2041 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2042 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x, i %u.\n", hr, i);
2043 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
2044 color_key.dwColorSpaceLowValue, i);
2045 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
2046 color_key.dwColorSpaceHighValue, i);
2048 IDirectDrawSurface_Release(mipmap);
2049 mipmap = tmp;
2052 memset(&color_key, 0, sizeof(color_key));
2053 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2054 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2055 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2056 color_key.dwColorSpaceLowValue);
2057 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2058 color_key.dwColorSpaceHighValue);
2060 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
2061 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
2062 IDirectDrawSurface_Release(mipmap);
2063 refcount = IDirectDrawSurface_Release(surface);
2064 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2066 memset(&surface_desc, 0, sizeof(surface_desc));
2067 surface_desc.dwSize = sizeof(surface_desc);
2068 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
2069 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
2070 surface_desc.dwBackBufferCount = 1;
2071 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2072 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2074 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2075 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
2076 color_key.dwColorSpaceLowValue = 0x0000ff00;
2077 color_key.dwColorSpaceHighValue = 0x0000ff00;
2078 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2079 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2080 memset(&color_key, 0, sizeof(color_key));
2081 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2082 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2083 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2084 color_key.dwColorSpaceLowValue);
2085 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2086 color_key.dwColorSpaceHighValue);
2088 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &tmp);
2089 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
2091 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2092 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
2093 color_key.dwColorSpaceLowValue = 0x0000ff00;
2094 color_key.dwColorSpaceHighValue = 0x0000ff00;
2095 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2096 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2097 memset(&color_key, 0, sizeof(color_key));
2098 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2099 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2100 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2101 color_key.dwColorSpaceLowValue);
2102 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2103 color_key.dwColorSpaceHighValue);
2105 IDirectDrawSurface_Release(tmp);
2107 refcount = IDirectDrawSurface_Release(surface);
2108 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2109 refcount = IDirectDraw2_Release(ddraw);
2110 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2111 DestroyWindow(window);
2114 struct qi_test
2116 REFIID iid;
2117 REFIID refcount_iid;
2118 HRESULT hr;
2121 static void test_qi(const char *test_name, IUnknown *base_iface,
2122 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
2124 ULONG refcount, expected_refcount;
2125 IUnknown *iface1, *iface2;
2126 HRESULT hr;
2127 UINT i, j;
2129 for (i = 0; i < entry_count; ++i)
2131 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
2132 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
2133 if (SUCCEEDED(hr))
2135 for (j = 0; j < entry_count; ++j)
2137 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
2138 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
2139 if (SUCCEEDED(hr))
2141 expected_refcount = 0;
2142 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
2143 ++expected_refcount;
2144 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
2145 ++expected_refcount;
2146 refcount = IUnknown_Release(iface2);
2147 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
2148 refcount, test_name, i, j, expected_refcount);
2152 expected_refcount = 0;
2153 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
2154 ++expected_refcount;
2155 refcount = IUnknown_Release(iface1);
2156 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
2157 refcount, test_name, i, expected_refcount);
2162 static void test_surface_qi(void)
2164 static const struct qi_test tests[] =
2166 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
2167 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
2168 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
2169 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2170 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
2171 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
2172 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
2173 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
2174 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
2175 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
2176 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
2177 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
2178 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
2179 {&IID_IDirect3D7, NULL, E_INVALIDARG },
2180 {&IID_IDirect3D3, NULL, E_INVALIDARG },
2181 {&IID_IDirect3D2, NULL, E_INVALIDARG },
2182 {&IID_IDirect3D, NULL, E_INVALIDARG },
2183 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
2184 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
2185 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
2186 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
2187 {&IID_IDirectDraw, NULL, E_INVALIDARG },
2188 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
2189 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
2190 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
2191 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
2192 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
2193 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
2194 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
2195 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
2196 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
2197 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
2198 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
2199 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
2200 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
2201 {NULL, NULL, E_INVALIDARG },
2204 IDirectDrawSurface *surface;
2205 DDSURFACEDESC surface_desc;
2206 IDirect3DDevice2 *device;
2207 IDirectDraw2 *ddraw;
2208 HWND window;
2209 HRESULT hr;
2211 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
2213 win_skip("DirectDrawCreateEx not available, skipping test.\n");
2214 return;
2217 window = create_window();
2218 ddraw = create_ddraw();
2219 ok(!!ddraw, "Failed to create a ddraw object.\n");
2220 /* Try to create a D3D device to see if the ddraw implementation supports
2221 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
2222 * doesn't support e.g. the IDirect3DTexture interfaces. */
2223 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2225 skip("Failed to create a 3D device, skipping test.\n");
2226 IDirectDraw2_Release(ddraw);
2227 DestroyWindow(window);
2228 return;
2230 IDirect3DDevice_Release(device);
2232 memset(&surface_desc, 0, sizeof(surface_desc));
2233 surface_desc.dwSize = sizeof(surface_desc);
2234 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2235 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2236 surface_desc.dwWidth = 512;
2237 surface_desc.dwHeight = 512;
2238 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, (IDirectDrawSurface **)0xdeadbeef, NULL);
2239 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
2240 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2241 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2243 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface, tests, ARRAY_SIZE(tests));
2245 IDirectDrawSurface_Release(surface);
2246 IDirectDraw2_Release(ddraw);
2247 DestroyWindow(window);
2250 static void test_device_qi(void)
2252 static const struct qi_test tests[] =
2254 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
2255 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
2256 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
2257 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2258 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
2259 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
2260 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
2261 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
2262 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
2263 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
2264 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
2265 {&IID_IDirect3DDevice2, &IID_IDirect3DDevice2, S_OK },
2266 {&IID_IDirect3DDevice, &IID_IDirect3DDevice2, S_OK },
2267 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2268 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2269 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2270 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2271 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2272 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2273 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2274 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2275 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2276 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2277 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2278 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2279 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2280 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2281 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2282 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2283 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2284 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2285 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2286 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2287 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2288 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2289 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2290 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2291 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2292 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2293 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2294 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2295 {&IID_IUnknown, &IID_IDirect3DDevice2, S_OK },
2298 IDirect3DDevice2 *device;
2299 IDirectDraw2 *ddraw;
2300 HWND window;
2302 window = create_window();
2303 ddraw = create_ddraw();
2304 ok(!!ddraw, "Failed to create a ddraw object.\n");
2305 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2307 skip("Failed to create a 3D device, skipping test.\n");
2308 IDirectDraw2_Release(ddraw);
2309 DestroyWindow(window);
2310 return;
2313 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice2, tests, ARRAY_SIZE(tests));
2315 IDirect3DDevice2_Release(device);
2316 IDirectDraw2_Release(ddraw);
2317 DestroyWindow(window);
2320 static void test_wndproc(void)
2322 LONG_PTR proc, ddraw_proc;
2323 IDirectDraw2 *ddraw;
2324 WNDCLASSA wc = {0};
2325 HWND window;
2326 HRESULT hr;
2327 ULONG ref;
2329 static struct message messages[] =
2331 {WM_WINDOWPOSCHANGING, FALSE, 0},
2332 {WM_MOVE, FALSE, 0},
2333 {WM_SIZE, FALSE, 0},
2334 {WM_WINDOWPOSCHANGING, FALSE, 0},
2335 {WM_ACTIVATE, FALSE, 0},
2336 {WM_SETFOCUS, FALSE, 0},
2337 {0, FALSE, 0},
2340 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2341 ddraw = create_ddraw();
2342 ok(!!ddraw, "Failed to create a ddraw object.\n");
2344 wc.lpfnWndProc = test_proc;
2345 wc.lpszClassName = "ddraw_test_wndproc_wc";
2346 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2348 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2349 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2351 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2352 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2353 (LONG_PTR)test_proc, proc);
2354 expect_messages = messages;
2355 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2356 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2357 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2358 expect_messages = NULL;
2359 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2360 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2361 (LONG_PTR)test_proc, proc);
2362 ref = IDirectDraw2_Release(ddraw);
2363 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2364 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2365 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2366 (LONG_PTR)test_proc, proc);
2368 /* DDSCL_NORMAL doesn't. */
2369 ddraw = create_ddraw();
2370 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2371 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2372 (LONG_PTR)test_proc, proc);
2373 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2374 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2375 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2376 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2377 (LONG_PTR)test_proc, proc);
2378 ref = IDirectDraw2_Release(ddraw);
2379 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2380 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2381 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2382 (LONG_PTR)test_proc, proc);
2384 /* The original window proc is only restored by ddraw if the current
2385 * window proc matches the one ddraw set. This also affects switching
2386 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2387 ddraw = create_ddraw();
2388 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2389 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2390 (LONG_PTR)test_proc, proc);
2391 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2392 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2393 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2394 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2395 (LONG_PTR)test_proc, proc);
2396 ddraw_proc = proc;
2397 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2398 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2399 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2400 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2401 (LONG_PTR)test_proc, proc);
2402 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2403 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2404 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2405 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2406 (LONG_PTR)test_proc, proc);
2407 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2408 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2409 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2410 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2411 (LONG_PTR)DefWindowProcA, proc);
2412 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2413 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2414 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, ddraw_proc);
2415 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2416 (LONG_PTR)DefWindowProcA, proc);
2417 ref = IDirectDraw2_Release(ddraw);
2418 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2419 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2420 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2421 (LONG_PTR)test_proc, proc);
2423 ddraw = create_ddraw();
2424 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2425 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2426 (LONG_PTR)test_proc, proc);
2427 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2428 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2429 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2430 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2431 (LONG_PTR)test_proc, proc);
2432 ref = IDirectDraw2_Release(ddraw);
2433 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2434 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2435 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2436 (LONG_PTR)DefWindowProcA, proc);
2438 fix_wndproc(window, (LONG_PTR)test_proc);
2439 expect_messages = NULL;
2440 DestroyWindow(window);
2441 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2444 static void test_window_style(void)
2446 LONG style, exstyle, tmp, expected_style;
2447 RECT fullscreen_rect, r;
2448 IDirectDraw2 *ddraw;
2449 HWND window;
2450 HRESULT hr;
2451 ULONG ref;
2452 BOOL ret;
2454 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2455 0, 0, 100, 100, 0, 0, 0, 0);
2456 ddraw = create_ddraw();
2457 ok(!!ddraw, "Failed to create a ddraw object.\n");
2459 style = GetWindowLongA(window, GWL_STYLE);
2460 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2461 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2463 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2464 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2466 tmp = GetWindowLongA(window, GWL_STYLE);
2467 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2468 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2469 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2471 GetWindowRect(window, &r);
2472 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2473 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2474 GetClientRect(window, &r);
2475 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2477 ret = SetForegroundWindow(GetDesktopWindow());
2478 ok(ret, "Failed to set foreground window.\n");
2480 tmp = GetWindowLongA(window, GWL_STYLE);
2481 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2482 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2483 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2485 ret = SetForegroundWindow(window);
2486 ok(ret, "Failed to set foreground window.\n");
2487 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2488 * the next tests expect this. */
2489 ShowWindow(window, SW_HIDE);
2491 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2492 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2494 tmp = GetWindowLongA(window, GWL_STYLE);
2495 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2496 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2497 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2499 ShowWindow(window, SW_SHOW);
2500 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2501 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2503 tmp = GetWindowLongA(window, GWL_STYLE);
2504 expected_style = style | WS_VISIBLE;
2505 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2506 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2507 expected_style = exstyle | WS_EX_TOPMOST;
2508 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2510 ret = SetForegroundWindow(GetDesktopWindow());
2511 ok(ret, "Failed to set foreground window.\n");
2512 tmp = GetWindowLongA(window, GWL_STYLE);
2513 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
2514 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2515 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2516 expected_style = exstyle | WS_EX_TOPMOST;
2517 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2519 ref = IDirectDraw2_Release(ddraw);
2520 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2522 DestroyWindow(window);
2525 static void test_redundant_mode_set(void)
2527 DDSURFACEDESC surface_desc = {0};
2528 IDirectDraw2 *ddraw;
2529 RECT q, r, s;
2530 HWND window;
2531 HRESULT hr;
2532 ULONG ref;
2534 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2535 0, 0, 100, 100, 0, 0, 0, 0);
2536 ddraw = create_ddraw();
2537 ok(!!ddraw, "Failed to create a ddraw object.\n");
2539 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2540 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2542 surface_desc.dwSize = sizeof(surface_desc);
2543 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
2544 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
2546 hr = IDirectDraw2_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2547 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, 0, 0);
2548 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2550 GetWindowRect(window, &q);
2551 r = q;
2552 r.right /= 2;
2553 r.bottom /= 2;
2554 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2555 GetWindowRect(window, &s);
2556 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2558 hr = IDirectDraw2_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2559 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, 0, 0);
2560 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2562 GetWindowRect(window, &s);
2563 ok(EqualRect(&r, &s) || broken(EqualRect(&q, &s) /* Windows 10 */),
2564 "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2566 ref = IDirectDraw2_Release(ddraw);
2567 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2569 DestroyWindow(window);
2572 static SIZE screen_size, screen_size2;
2574 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2576 if (message == WM_SIZE)
2578 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2579 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2582 return test_proc(hwnd, message, wparam, lparam);
2585 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2587 if (message == WM_SIZE)
2589 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
2590 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
2593 return test_proc(hwnd, message, wparam, lparam);
2596 struct test_coop_level_mode_set_enum_param
2598 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
2601 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC *surface_desc, void *context)
2603 struct test_coop_level_mode_set_enum_param *param = context;
2605 if (U1(surface_desc->ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
2606 return DDENUMRET_OK;
2607 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
2608 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
2609 return DDENUMRET_OK;
2611 if (!param->ddraw_width)
2613 param->ddraw_width = surface_desc->dwWidth;
2614 param->ddraw_height = surface_desc->dwHeight;
2615 return DDENUMRET_OK;
2617 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
2618 return DDENUMRET_OK;
2620 param->user32_width = surface_desc->dwWidth;
2621 param->user32_height = surface_desc->dwHeight;
2622 return DDENUMRET_CANCEL;
2625 static void test_coop_level_mode_set(void)
2627 IDirectDrawSurface *primary;
2628 RECT registry_rect, ddraw_rect, user32_rect, r;
2629 IDirectDraw2 *ddraw;
2630 DDSURFACEDESC ddsd;
2631 WNDCLASSA wc = {0};
2632 HWND window, window2;
2633 HRESULT hr;
2634 ULONG ref;
2635 MSG msg;
2636 struct test_coop_level_mode_set_enum_param param;
2637 DEVMODEW devmode;
2638 BOOL ret;
2639 LONG change_ret;
2641 static const struct message exclusive_messages[] =
2643 {WM_WINDOWPOSCHANGING, FALSE, 0},
2644 {WM_WINDOWPOSCHANGED, FALSE, 0},
2645 {WM_SIZE, FALSE, 0},
2646 {WM_DISPLAYCHANGE, FALSE, 0},
2647 {0, FALSE, 0},
2649 static const struct message exclusive_focus_loss_messages[] =
2651 {WM_ACTIVATE, TRUE, WA_INACTIVE},
2652 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Window resize due to mode change. */
2653 {WM_WINDOWPOSCHANGED, FALSE, 0},
2654 {WM_SIZE, TRUE, SIZE_RESTORED}, /* Generated by DefWindowProc. */
2655 {WM_DISPLAYCHANGE, FALSE, 0},
2656 {WM_KILLFOCUS, FALSE, 0},
2657 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Window minimized. */
2658 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
2659 * SW_MINIMIZED, causing a recursive window activation that does not
2660 * produce the same result in Wine yet. Ignore the difference for now.
2661 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
2662 {WM_WINDOWPOSCHANGED, FALSE, 0},
2663 {WM_MOVE, FALSE, 0},
2664 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2665 {WM_ACTIVATEAPP, TRUE, FALSE},
2666 {0, FALSE, 0},
2668 static const struct message exclusive_focus_restore_messages[] =
2670 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
2671 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
2672 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
2673 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
2674 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
2675 /* Native redundantly sets the window size here. */
2676 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
2677 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
2678 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
2679 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
2680 {0, FALSE, 0},
2682 static const struct message sc_restore_messages[] =
2684 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
2685 {WM_WINDOWPOSCHANGING, FALSE, 0},
2686 {WM_WINDOWPOSCHANGED, FALSE, 0},
2687 {WM_SIZE, TRUE, SIZE_RESTORED},
2688 {0, FALSE, 0},
2690 static const struct message sc_minimize_messages[] =
2692 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
2693 {WM_WINDOWPOSCHANGING, FALSE, 0},
2694 {WM_WINDOWPOSCHANGED, FALSE, 0},
2695 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2696 {0, FALSE, 0},
2698 static const struct message sc_maximize_messages[] =
2700 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
2701 {WM_WINDOWPOSCHANGING, FALSE, 0},
2702 {WM_WINDOWPOSCHANGED, FALSE, 0},
2703 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
2704 {0, FALSE, 0},
2707 static const struct message normal_messages[] =
2709 {WM_DISPLAYCHANGE, FALSE, 0},
2710 {0, FALSE, 0},
2713 ddraw = create_ddraw();
2714 ok(!!ddraw, "Failed to create a ddraw object.\n");
2716 memset(&param, 0, sizeof(param));
2717 hr = IDirectDraw2_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
2718 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2719 ref = IDirectDraw2_Release(ddraw);
2720 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2722 if (!param.user32_height)
2724 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
2725 return;
2728 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2729 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
2730 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
2732 memset(&devmode, 0, sizeof(devmode));
2733 devmode.dmSize = sizeof(devmode);
2734 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2735 devmode.dmPelsWidth = param.user32_width;
2736 devmode.dmPelsHeight = param.user32_height;
2737 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2738 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2740 ddraw = create_ddraw();
2741 ok(!!ddraw, "Failed to create a ddraw object.\n");
2743 wc.lpfnWndProc = mode_set_proc;
2744 wc.lpszClassName = "ddraw_test_wndproc_wc";
2745 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2746 wc.lpfnWndProc = mode_set_proc2;
2747 wc.lpszClassName = "ddraw_test_wndproc_wc2";
2748 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2750 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2751 0, 0, 100, 100, 0, 0, 0, 0);
2752 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
2753 0, 0, 100, 100, 0, 0, 0, 0);
2755 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2756 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2758 GetWindowRect(window, &r);
2759 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2760 wine_dbgstr_rect(&r));
2762 memset(&ddsd, 0, sizeof(ddsd));
2763 ddsd.dwSize = sizeof(ddsd);
2764 ddsd.dwFlags = DDSD_CAPS;
2765 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2767 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2768 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2769 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2770 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2771 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2772 param.user32_width, ddsd.dwWidth);
2773 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2774 param.user32_height, ddsd.dwHeight);
2776 GetWindowRect(window, &r);
2777 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2778 wine_dbgstr_rect(&r));
2780 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2781 expect_messages = exclusive_messages;
2782 screen_size.cx = 0;
2783 screen_size.cy = 0;
2785 hr = IDirectDrawSurface_IsLost(primary);
2786 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2787 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2788 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2789 hr = IDirectDrawSurface_IsLost(primary);
2790 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2792 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2793 expect_messages = NULL;
2794 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
2795 "Expected screen size %ux%u, got %ux%u.\n",
2796 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
2798 GetWindowRect(window, &r);
2799 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2800 wine_dbgstr_rect(&r));
2802 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2803 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2804 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2805 param.user32_width, ddsd.dwWidth);
2806 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2807 param.user32_height, ddsd.dwHeight);
2808 IDirectDrawSurface_Release(primary);
2810 memset(&ddsd, 0, sizeof(ddsd));
2811 ddsd.dwSize = sizeof(ddsd);
2812 ddsd.dwFlags = DDSD_CAPS;
2813 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2815 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2816 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2817 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2818 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2819 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2820 param.ddraw_width, ddsd.dwWidth);
2821 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2822 param.ddraw_height, ddsd.dwHeight);
2824 GetWindowRect(window, &r);
2825 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2826 wine_dbgstr_rect(&r));
2828 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2829 expect_messages = exclusive_messages;
2830 screen_size.cx = 0;
2831 screen_size.cy = 0;
2833 hr = IDirectDrawSurface_IsLost(primary);
2834 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2835 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2836 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2837 hr = IDirectDrawSurface_IsLost(primary);
2838 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2840 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2841 expect_messages = NULL;
2842 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
2843 "Expected screen size %ux%u, got %ux%u.\n",
2844 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
2846 GetWindowRect(window, &r);
2847 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2848 wine_dbgstr_rect(&r));
2850 expect_messages = exclusive_focus_loss_messages;
2851 ret = SetForegroundWindow(GetDesktopWindow());
2852 ok(ret, "Failed to set foreground window.\n");
2853 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2854 memset(&devmode, 0, sizeof(devmode));
2855 devmode.dmSize = sizeof(devmode);
2856 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2857 ok(ret, "Failed to get display mode.\n");
2858 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2859 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
2860 devmode.dmPelsWidth, devmode.dmPelsHeight);
2862 expect_messages = exclusive_focus_restore_messages;
2863 ShowWindow(window, SW_RESTORE);
2864 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2866 GetWindowRect(window, &r);
2867 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2868 wine_dbgstr_rect(&r));
2869 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2870 ok(ret, "Failed to get display mode.\n");
2871 ok(devmode.dmPelsWidth == param.ddraw_width
2872 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpect screen size %ux%u.\n",
2873 devmode.dmPelsWidth, devmode.dmPelsHeight);
2875 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2876 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2877 /* Normally the primary should be restored here. Unfortunately this causes the
2878 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
2879 * testbot. Another Restore call would presumably avoid the crash, but it also moots
2880 * the point of the GetSurfaceDesc call. */
2882 expect_messages = sc_minimize_messages;
2883 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
2884 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2885 expect_messages = NULL;
2887 expect_messages = sc_restore_messages;
2888 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
2889 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2890 expect_messages = NULL;
2892 expect_messages = sc_maximize_messages;
2893 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
2894 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2895 expect_messages = NULL;
2897 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2898 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2900 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2901 expect_messages = exclusive_messages;
2902 screen_size.cx = 0;
2903 screen_size.cy = 0;
2905 hr = IDirectDrawSurface_IsLost(primary);
2906 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2907 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
2908 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2909 hr = IDirectDrawSurface_IsLost(primary);
2910 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2912 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2913 expect_messages = NULL;
2914 ok(screen_size.cx == registry_mode.dmPelsWidth
2915 && screen_size.cy == registry_mode.dmPelsHeight,
2916 "Expected screen size %ux%u, got %ux%u.\n",
2917 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
2919 GetWindowRect(window, &r);
2920 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2921 wine_dbgstr_rect(&r));
2923 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2924 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2925 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2926 param.ddraw_width, ddsd.dwWidth);
2927 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2928 param.ddraw_height, ddsd.dwHeight);
2929 IDirectDrawSurface_Release(primary);
2931 /* For Wine. */
2932 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2933 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2935 memset(&ddsd, 0, sizeof(ddsd));
2936 ddsd.dwSize = sizeof(ddsd);
2937 ddsd.dwFlags = DDSD_CAPS;
2938 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2940 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2941 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2942 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2943 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2944 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2945 registry_mode.dmPelsWidth, ddsd.dwWidth);
2946 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2947 registry_mode.dmPelsHeight, ddsd.dwHeight);
2949 GetWindowRect(window, &r);
2950 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2951 wine_dbgstr_rect(&r));
2953 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2954 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2956 GetWindowRect(window, &r);
2957 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2958 wine_dbgstr_rect(&r));
2960 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2961 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2962 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2963 registry_mode.dmPelsWidth, ddsd.dwWidth);
2964 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2965 registry_mode.dmPelsHeight, ddsd.dwHeight);
2966 IDirectDrawSurface_Release(primary);
2968 memset(&ddsd, 0, sizeof(ddsd));
2969 ddsd.dwSize = sizeof(ddsd);
2970 ddsd.dwFlags = DDSD_CAPS;
2971 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2973 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2974 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2975 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2976 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2977 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2978 registry_mode.dmPelsWidth, ddsd.dwWidth);
2979 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2980 registry_mode.dmPelsHeight, ddsd.dwHeight);
2982 GetWindowRect(window, &r);
2983 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2984 wine_dbgstr_rect(&r));
2986 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2987 expect_messages = normal_messages;
2988 screen_size.cx = 0;
2989 screen_size.cy = 0;
2991 hr = IDirectDrawSurface_IsLost(primary);
2992 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2993 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2994 devmode.dmPelsWidth = param.user32_width;
2995 devmode.dmPelsHeight = param.user32_height;
2996 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2997 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2998 hr = IDirectDrawSurface_IsLost(primary);
2999 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3001 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3002 expect_messages = NULL;
3003 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3005 GetWindowRect(window, &r);
3006 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3007 wine_dbgstr_rect(&r));
3009 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3010 expect_messages = normal_messages;
3011 screen_size.cx = 0;
3012 screen_size.cy = 0;
3014 hr = IDirectDrawSurface_Restore(primary);
3015 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3016 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3017 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
3019 win_skip("Broken SetDisplayMode(), skipping remaining tests.\n");
3020 IDirectDrawSurface_Release(primary);
3021 IDirectDraw2_Release(ddraw);
3022 goto done;
3024 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3025 hr = IDirectDrawSurface_Restore(primary);
3026 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3027 hr = IDirectDrawSurface_IsLost(primary);
3028 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3030 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3031 expect_messages = NULL;
3032 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3034 GetWindowRect(window, &r);
3035 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3036 wine_dbgstr_rect(&r));
3038 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3039 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3040 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3041 registry_mode.dmPelsWidth, ddsd.dwWidth);
3042 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3043 registry_mode.dmPelsHeight, ddsd.dwHeight);
3044 IDirectDrawSurface_Release(primary);
3046 memset(&ddsd, 0, sizeof(ddsd));
3047 ddsd.dwSize = sizeof(ddsd);
3048 ddsd.dwFlags = DDSD_CAPS;
3049 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3051 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3052 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3053 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3054 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3055 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3056 param.ddraw_width, ddsd.dwWidth);
3057 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3058 param.ddraw_height, ddsd.dwHeight);
3060 GetWindowRect(window, &r);
3061 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3062 wine_dbgstr_rect(&r));
3064 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3065 expect_messages = normal_messages;
3066 screen_size.cx = 0;
3067 screen_size.cy = 0;
3069 hr = IDirectDrawSurface_IsLost(primary);
3070 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3071 hr = IDirectDraw_RestoreDisplayMode(ddraw);
3072 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3073 hr = IDirectDrawSurface_IsLost(primary);
3074 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3076 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3077 expect_messages = NULL;
3078 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3080 GetWindowRect(window, &r);
3081 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3082 wine_dbgstr_rect(&r));
3084 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3085 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3086 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3087 param.ddraw_width, ddsd.dwWidth);
3088 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3089 param.ddraw_height, ddsd.dwHeight);
3090 IDirectDrawSurface_Release(primary);
3092 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3093 ok(ret, "Failed to get display mode.\n");
3094 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3095 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3096 "Expected resolution %ux%u, got %ux%u.\n",
3097 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3098 devmode.dmPelsWidth, devmode.dmPelsHeight);
3099 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3100 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3102 memset(&ddsd, 0, sizeof(ddsd));
3103 ddsd.dwSize = sizeof(ddsd);
3104 ddsd.dwFlags = DDSD_CAPS;
3105 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3107 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3108 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3109 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3110 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3111 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3112 registry_mode.dmPelsWidth, ddsd.dwWidth);
3113 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3114 registry_mode.dmPelsHeight, ddsd.dwHeight);
3116 GetWindowRect(window, &r);
3117 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3118 wine_dbgstr_rect(&r));
3120 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
3121 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
3122 * not DDSCL_FULLSCREEN. */
3123 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3124 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3126 GetWindowRect(window, &r);
3127 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3128 wine_dbgstr_rect(&r));
3130 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3131 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3132 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3133 registry_mode.dmPelsWidth, ddsd.dwWidth);
3134 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3135 registry_mode.dmPelsHeight, ddsd.dwHeight);
3136 IDirectDrawSurface_Release(primary);
3138 memset(&ddsd, 0, sizeof(ddsd));
3139 ddsd.dwSize = sizeof(ddsd);
3140 ddsd.dwFlags = DDSD_CAPS;
3141 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3143 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3144 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3145 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3146 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3147 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3148 registry_mode.dmPelsWidth, ddsd.dwWidth);
3149 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3150 registry_mode.dmPelsHeight, ddsd.dwHeight);
3152 GetWindowRect(window, &r);
3153 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3154 wine_dbgstr_rect(&r));
3156 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3157 expect_messages = normal_messages;
3158 screen_size.cx = 0;
3159 screen_size.cy = 0;
3161 hr = IDirectDrawSurface_IsLost(primary);
3162 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3163 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3164 devmode.dmPelsWidth = param.user32_width;
3165 devmode.dmPelsHeight = param.user32_height;
3166 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3167 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3168 hr = IDirectDrawSurface_IsLost(primary);
3169 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3171 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3172 expect_messages = NULL;
3173 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3175 GetWindowRect(window, &r);
3176 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3177 wine_dbgstr_rect(&r));
3179 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3180 expect_messages = normal_messages;
3181 screen_size.cx = 0;
3182 screen_size.cy = 0;
3184 hr = IDirectDrawSurface_Restore(primary);
3185 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3186 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3187 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3188 hr = IDirectDrawSurface_Restore(primary);
3189 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3190 hr = IDirectDrawSurface_IsLost(primary);
3191 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3193 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3194 expect_messages = NULL;
3195 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3197 GetWindowRect(window, &r);
3198 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3199 wine_dbgstr_rect(&r));
3201 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3202 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3203 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3204 registry_mode.dmPelsWidth, ddsd.dwWidth);
3205 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3206 registry_mode.dmPelsHeight, ddsd.dwHeight);
3207 IDirectDrawSurface_Release(primary);
3209 memset(&ddsd, 0, sizeof(ddsd));
3210 ddsd.dwSize = sizeof(ddsd);
3211 ddsd.dwFlags = DDSD_CAPS;
3212 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3214 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3215 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3216 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3217 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3218 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3219 param.ddraw_width, ddsd.dwWidth);
3220 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3221 param.ddraw_height, ddsd.dwHeight);
3223 GetWindowRect(window, &r);
3224 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3225 wine_dbgstr_rect(&r));
3227 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3228 expect_messages = normal_messages;
3229 screen_size.cx = 0;
3230 screen_size.cy = 0;
3232 hr = IDirectDrawSurface_IsLost(primary);
3233 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3234 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
3235 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3236 hr = IDirectDrawSurface_IsLost(primary);
3237 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3239 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3240 expect_messages = NULL;
3241 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3243 GetWindowRect(window, &r);
3244 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3245 wine_dbgstr_rect(&r));
3247 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3248 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3249 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3250 param.ddraw_width, ddsd.dwWidth);
3251 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3252 param.ddraw_height, ddsd.dwHeight);
3253 IDirectDrawSurface_Release(primary);
3255 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3256 ok(ret, "Failed to get display mode.\n");
3257 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3258 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3259 "Expected resolution %ux%u, got %ux%u.\n",
3260 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3261 devmode.dmPelsWidth, devmode.dmPelsHeight);
3262 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3263 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3265 memset(&ddsd, 0, sizeof(ddsd));
3266 ddsd.dwSize = sizeof(ddsd);
3267 ddsd.dwFlags = DDSD_CAPS;
3268 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3270 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3271 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3272 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3273 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3274 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3275 registry_mode.dmPelsWidth, ddsd.dwWidth);
3276 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3277 registry_mode.dmPelsHeight, ddsd.dwHeight);
3278 IDirectDrawSurface_Release(primary);
3280 GetWindowRect(window, &r);
3281 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3282 wine_dbgstr_rect(&r));
3284 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
3285 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3286 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3287 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3288 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3290 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3291 expect_messages = exclusive_messages;
3292 screen_size.cx = 0;
3293 screen_size.cy = 0;
3295 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3296 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3298 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3299 expect_messages = NULL;
3300 ok(screen_size.cx == registry_mode.dmPelsWidth
3301 && screen_size.cy == registry_mode.dmPelsHeight,
3302 "Expected screen size %ux%u, got %ux%u.\n",
3303 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3304 screen_size.cx, screen_size.cy);
3306 GetWindowRect(window, &r);
3307 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3308 wine_dbgstr_rect(&r));
3310 memset(&ddsd, 0, sizeof(ddsd));
3311 ddsd.dwSize = sizeof(ddsd);
3312 ddsd.dwFlags = DDSD_CAPS;
3313 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3315 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3316 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3317 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3318 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3319 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3320 registry_mode.dmPelsWidth, ddsd.dwWidth);
3321 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3322 registry_mode.dmPelsHeight, ddsd.dwHeight);
3323 IDirectDrawSurface_Release(primary);
3325 /* The screen restore is a property of DDSCL_EXCLUSIVE */
3326 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3327 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3328 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3329 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3331 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3332 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3334 memset(&ddsd, 0, sizeof(ddsd));
3335 ddsd.dwSize = sizeof(ddsd);
3336 ddsd.dwFlags = DDSD_CAPS;
3337 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3339 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3340 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3341 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3342 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3343 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3344 param.ddraw_width, ddsd.dwWidth);
3345 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3346 param.ddraw_height, ddsd.dwHeight);
3347 IDirectDrawSurface_Release(primary);
3349 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
3350 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3352 /* If the window is changed at the same time, messages are sent to the new window. */
3353 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3354 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3355 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3356 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3358 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3359 expect_messages = exclusive_messages;
3360 screen_size.cx = 0;
3361 screen_size.cy = 0;
3362 screen_size2.cx = 0;
3363 screen_size2.cy = 0;
3365 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3366 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3368 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3369 expect_messages = NULL;
3370 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n",
3371 screen_size.cx, screen_size.cy);
3372 ok(screen_size2.cx == registry_mode.dmPelsWidth && screen_size2.cy == registry_mode.dmPelsHeight,
3373 "Expected screen size 2 %ux%u, got %ux%u.\n",
3374 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size2.cx, screen_size2.cy);
3376 GetWindowRect(window, &r);
3377 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3378 wine_dbgstr_rect(&r));
3379 GetWindowRect(window2, &r);
3380 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3381 wine_dbgstr_rect(&r));
3383 memset(&ddsd, 0, sizeof(ddsd));
3384 ddsd.dwSize = sizeof(ddsd);
3385 ddsd.dwFlags = DDSD_CAPS;
3386 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3388 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3389 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3390 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3391 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3392 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3393 registry_mode.dmPelsWidth, ddsd.dwWidth);
3394 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3395 registry_mode.dmPelsHeight, ddsd.dwHeight);
3396 IDirectDrawSurface_Release(primary);
3398 ref = IDirectDraw2_Release(ddraw);
3399 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3401 GetWindowRect(window, &r);
3402 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3403 wine_dbgstr_rect(&r));
3405 done:
3406 expect_messages = NULL;
3407 DestroyWindow(window);
3408 DestroyWindow(window2);
3409 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3410 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
3413 static void test_coop_level_mode_set_multi(void)
3415 IDirectDraw2 *ddraw1, *ddraw2;
3416 UINT w, h;
3417 HWND window;
3418 HRESULT hr;
3419 ULONG ref;
3421 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3422 0, 0, 100, 100, 0, 0, 0, 0);
3423 ddraw1 = create_ddraw();
3424 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3426 /* With just a single ddraw object, the display mode is restored on
3427 * release. */
3428 hr = set_display_mode(ddraw1, 800, 600);
3429 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
3431 win_skip("Broken SetDisplayMode(), skipping test.\n");
3432 IDirectDraw2_Release(ddraw1);
3433 DestroyWindow(window);
3434 return;
3436 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3437 w = GetSystemMetrics(SM_CXSCREEN);
3438 ok(w == 800, "Got unexpected screen width %u.\n", w);
3439 h = GetSystemMetrics(SM_CYSCREEN);
3440 ok(h == 600, "Got unexpected screen height %u.\n", h);
3442 ref = IDirectDraw2_Release(ddraw1);
3443 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3444 w = GetSystemMetrics(SM_CXSCREEN);
3445 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3446 h = GetSystemMetrics(SM_CYSCREEN);
3447 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3449 /* When there are multiple ddraw objects, the display mode is restored to
3450 * the initial mode, before the first SetDisplayMode() call. */
3451 ddraw1 = create_ddraw();
3452 hr = set_display_mode(ddraw1, 800, 600);
3453 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3454 w = GetSystemMetrics(SM_CXSCREEN);
3455 ok(w == 800, "Got unexpected screen width %u.\n", w);
3456 h = GetSystemMetrics(SM_CYSCREEN);
3457 ok(h == 600, "Got unexpected screen height %u.\n", h);
3459 ddraw2 = create_ddraw();
3460 hr = set_display_mode(ddraw2, 640, 480);
3461 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3462 w = GetSystemMetrics(SM_CXSCREEN);
3463 ok(w == 640, "Got unexpected screen width %u.\n", w);
3464 h = GetSystemMetrics(SM_CYSCREEN);
3465 ok(h == 480, "Got unexpected screen height %u.\n", h);
3467 ref = IDirectDraw2_Release(ddraw2);
3468 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3469 w = GetSystemMetrics(SM_CXSCREEN);
3470 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3471 h = GetSystemMetrics(SM_CYSCREEN);
3472 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3474 ref = IDirectDraw2_Release(ddraw1);
3475 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3476 w = GetSystemMetrics(SM_CXSCREEN);
3477 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3478 h = GetSystemMetrics(SM_CYSCREEN);
3479 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3481 /* Regardless of release ordering. */
3482 ddraw1 = create_ddraw();
3483 hr = set_display_mode(ddraw1, 800, 600);
3484 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3485 w = GetSystemMetrics(SM_CXSCREEN);
3486 ok(w == 800, "Got unexpected screen width %u.\n", w);
3487 h = GetSystemMetrics(SM_CYSCREEN);
3488 ok(h == 600, "Got unexpected screen height %u.\n", h);
3490 ddraw2 = create_ddraw();
3491 hr = set_display_mode(ddraw2, 640, 480);
3492 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3493 w = GetSystemMetrics(SM_CXSCREEN);
3494 ok(w == 640, "Got unexpected screen width %u.\n", w);
3495 h = GetSystemMetrics(SM_CYSCREEN);
3496 ok(h == 480, "Got unexpected screen height %u.\n", h);
3498 ref = IDirectDraw2_Release(ddraw1);
3499 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3500 w = GetSystemMetrics(SM_CXSCREEN);
3501 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3502 h = GetSystemMetrics(SM_CYSCREEN);
3503 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3505 ref = IDirectDraw2_Release(ddraw2);
3506 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3507 w = GetSystemMetrics(SM_CXSCREEN);
3508 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3509 h = GetSystemMetrics(SM_CYSCREEN);
3510 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3512 /* But only for ddraw objects that called SetDisplayMode(). */
3513 ddraw1 = create_ddraw();
3514 ddraw2 = create_ddraw();
3515 hr = set_display_mode(ddraw2, 640, 480);
3516 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3517 w = GetSystemMetrics(SM_CXSCREEN);
3518 ok(w == 640, "Got unexpected screen width %u.\n", w);
3519 h = GetSystemMetrics(SM_CYSCREEN);
3520 ok(h == 480, "Got unexpected screen height %u.\n", h);
3522 ref = IDirectDraw2_Release(ddraw1);
3523 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3524 w = GetSystemMetrics(SM_CXSCREEN);
3525 ok(w == 640, "Got unexpected screen width %u.\n", w);
3526 h = GetSystemMetrics(SM_CYSCREEN);
3527 ok(h == 480, "Got unexpected screen height %u.\n", h);
3529 ref = IDirectDraw2_Release(ddraw2);
3530 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3531 w = GetSystemMetrics(SM_CXSCREEN);
3532 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3533 h = GetSystemMetrics(SM_CYSCREEN);
3534 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3536 /* If there's a ddraw object that's currently in exclusive mode, it blocks
3537 * restoring the display mode. */
3538 ddraw1 = create_ddraw();
3539 hr = set_display_mode(ddraw1, 800, 600);
3540 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3541 w = GetSystemMetrics(SM_CXSCREEN);
3542 ok(w == 800, "Got unexpected screen width %u.\n", w);
3543 h = GetSystemMetrics(SM_CYSCREEN);
3544 ok(h == 600, "Got unexpected screen height %u.\n", h);
3546 ddraw2 = create_ddraw();
3547 hr = set_display_mode(ddraw2, 640, 480);
3548 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3549 w = GetSystemMetrics(SM_CXSCREEN);
3550 ok(w == 640, "Got unexpected screen width %u.\n", w);
3551 h = GetSystemMetrics(SM_CYSCREEN);
3552 ok(h == 480, "Got unexpected screen height %u.\n", h);
3554 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3555 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3557 ref = IDirectDraw2_Release(ddraw1);
3558 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3559 w = GetSystemMetrics(SM_CXSCREEN);
3560 ok(w == 640, "Got unexpected screen width %u.\n", w);
3561 h = GetSystemMetrics(SM_CYSCREEN);
3562 ok(h == 480, "Got unexpected screen height %u.\n", h);
3564 ref = IDirectDraw2_Release(ddraw2);
3565 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3566 w = GetSystemMetrics(SM_CXSCREEN);
3567 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3568 h = GetSystemMetrics(SM_CYSCREEN);
3569 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3571 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3572 ddraw1 = create_ddraw();
3573 hr = set_display_mode(ddraw1, 800, 600);
3574 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3575 w = GetSystemMetrics(SM_CXSCREEN);
3576 ok(w == 800, "Got unexpected screen width %u.\n", w);
3577 h = GetSystemMetrics(SM_CYSCREEN);
3578 ok(h == 600, "Got unexpected screen height %u.\n", h);
3580 hr = IDirectDraw2_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3581 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3583 ddraw2 = create_ddraw();
3584 hr = set_display_mode(ddraw2, 640, 480);
3585 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3587 ref = IDirectDraw2_Release(ddraw1);
3588 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3589 w = GetSystemMetrics(SM_CXSCREEN);
3590 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3591 h = GetSystemMetrics(SM_CYSCREEN);
3592 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3594 ref = IDirectDraw2_Release(ddraw2);
3595 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3596 w = GetSystemMetrics(SM_CXSCREEN);
3597 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3598 h = GetSystemMetrics(SM_CYSCREEN);
3599 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3601 DestroyWindow(window);
3604 static void test_initialize(void)
3606 IDirectDraw2 *ddraw;
3607 HRESULT hr;
3609 ddraw = create_ddraw();
3610 ok(!!ddraw, "Failed to create a ddraw object.\n");
3612 hr = IDirectDraw2_Initialize(ddraw, NULL);
3613 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
3614 IDirectDraw2_Release(ddraw);
3616 CoInitialize(NULL);
3617 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw2, (void **)&ddraw);
3618 ok(SUCCEEDED(hr), "Failed to create IDirectDraw2 instance, hr %#x.\n", hr);
3619 hr = IDirectDraw2_Initialize(ddraw, NULL);
3620 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
3621 hr = IDirectDraw2_Initialize(ddraw, NULL);
3622 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
3623 IDirectDraw2_Release(ddraw);
3624 CoUninitialize();
3627 static void test_coop_level_surf_create(void)
3629 IDirectDrawSurface *surface;
3630 IDirectDraw2 *ddraw;
3631 DDSURFACEDESC ddsd;
3632 HRESULT hr;
3634 ddraw = create_ddraw();
3635 ok(!!ddraw, "Failed to create a ddraw object.\n");
3637 memset(&ddsd, 0, sizeof(ddsd));
3638 ddsd.dwSize = sizeof(ddsd);
3639 ddsd.dwFlags = DDSD_CAPS;
3640 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3641 surface = (void *)0xdeadbeef;
3642 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
3643 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3644 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3646 surface = (void *)0xdeadbeef;
3647 hr = IDirectDraw2_CreateSurface(ddraw, NULL, &surface, NULL);
3648 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3649 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3651 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3652 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3654 surface = (void *)0xdeadbeef;
3655 hr = IDirectDraw2_CreateSurface(ddraw, NULL, &surface, NULL);
3656 ok(hr == DDERR_INVALIDPARAMS, "Unexpected hr %#x.\n", hr);
3657 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3659 IDirectDraw2_Release(ddraw);
3662 static void test_coop_level_multi_window(void)
3664 HWND window1, window2;
3665 IDirectDraw2 *ddraw;
3666 HRESULT hr;
3668 window1 = create_window();
3669 window2 = create_window();
3670 ddraw = create_ddraw();
3671 ok(!!ddraw, "Failed to create a ddraw object.\n");
3673 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
3674 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3675 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3676 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3677 ok(IsWindow(window1), "Window 1 was destroyed.\n");
3678 ok(IsWindow(window2), "Window 2 was destroyed.\n");
3680 IDirectDraw2_Release(ddraw);
3681 DestroyWindow(window2);
3682 DestroyWindow(window1);
3685 static void test_clear_rect_count(void)
3687 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3688 IDirect3DMaterial2 *white, *red, *green, *blue;
3689 IDirect3DViewport2 *viewport;
3690 IDirect3DDevice2 *device;
3691 IDirectDrawSurface *rt;
3692 IDirectDraw2 *ddraw;
3693 D3DCOLOR color;
3694 HWND window;
3695 HRESULT hr;
3697 window = create_window();
3698 ddraw = create_ddraw();
3699 ok(!!ddraw, "Failed to create a ddraw object.\n");
3700 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3702 skip("Failed to create a 3D device, skipping test.\n");
3703 IDirectDraw2_Release(ddraw);
3704 DestroyWindow(window);
3705 return;
3708 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
3709 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3711 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
3712 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
3713 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
3714 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
3716 viewport = create_viewport(device, 0, 0, 640, 480);
3717 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
3718 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
3720 viewport_set_background(device, viewport, white);
3721 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
3722 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3723 viewport_set_background(device, viewport, red);
3724 hr = IDirect3DViewport2_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
3725 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3726 viewport_set_background(device, viewport, green);
3727 hr = IDirect3DViewport2_Clear(viewport, 0, NULL, D3DCLEAR_TARGET);
3728 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3729 viewport_set_background(device, viewport, blue);
3730 hr = IDirect3DViewport2_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
3731 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3733 color = get_surface_color(rt, 320, 240);
3734 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x000000ff, 1)),
3735 "Got unexpected color 0x%08x.\n", color);
3737 IDirectDrawSurface_Release(rt);
3738 destroy_viewport(device, viewport);
3739 destroy_material(white);
3740 destroy_material(red);
3741 destroy_material(green);
3742 destroy_material(blue);
3743 IDirect3DDevice2_Release(device);
3744 IDirectDraw2_Release(ddraw);
3745 DestroyWindow(window);
3748 static BOOL test_mode_restored(IDirectDraw2 *ddraw, HWND window)
3750 DDSURFACEDESC ddsd1, ddsd2;
3751 HRESULT hr;
3753 memset(&ddsd1, 0, sizeof(ddsd1));
3754 ddsd1.dwSize = sizeof(ddsd1);
3755 hr = IDirectDraw2_GetDisplayMode(ddraw, &ddsd1);
3756 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
3758 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3759 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3760 hr = set_display_mode(ddraw, 640, 480);
3761 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3762 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3763 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3765 memset(&ddsd2, 0, sizeof(ddsd2));
3766 ddsd2.dwSize = sizeof(ddsd2);
3767 hr = IDirectDraw2_GetDisplayMode(ddraw, &ddsd2);
3768 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
3769 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
3770 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3772 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
3775 static void test_coop_level_versions(void)
3777 HWND window;
3778 IDirectDraw *ddraw;
3779 HRESULT hr;
3780 BOOL restored;
3781 IDirectDrawSurface *surface;
3782 IDirectDraw2 *ddraw2;
3783 DDSURFACEDESC ddsd;
3785 window = create_window();
3786 ddraw2 = create_ddraw();
3787 ok(!!ddraw2, "Failed to create a ddraw object.\n");
3788 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
3789 restored = test_mode_restored(ddraw2, window);
3790 ok(restored, "Display mode not restored in new ddraw object\n");
3792 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
3793 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
3794 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3796 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
3797 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
3798 restored = test_mode_restored(ddraw2, window);
3799 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
3801 /* A successful one does */
3802 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3803 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3804 restored = test_mode_restored(ddraw2, window);
3805 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
3807 IDirectDraw_Release(ddraw);
3808 IDirectDraw2_Release(ddraw2);
3810 ddraw2 = create_ddraw();
3811 ok(!!ddraw2, "Failed to create a ddraw object.\n");
3812 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
3813 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3815 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
3816 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3817 restored = test_mode_restored(ddraw2, window);
3818 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
3820 IDirectDraw_Release(ddraw);
3821 IDirectDraw2_Release(ddraw2);
3823 /* A failing call does not restore the ddraw2+ behavior */
3824 ddraw2 = create_ddraw();
3825 ok(!!ddraw2, "Failed to create a ddraw object.\n");
3826 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
3827 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3829 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3830 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3831 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
3832 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
3833 restored = test_mode_restored(ddraw2, window);
3834 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
3836 IDirectDraw_Release(ddraw);
3837 IDirectDraw2_Release(ddraw2);
3839 /* Neither does a sequence of successful calls with the new interface */
3840 ddraw2 = create_ddraw();
3841 ok(!!ddraw2, "Failed to create a ddraw object.\n");
3842 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
3843 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3845 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3846 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3847 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
3848 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3849 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_NORMAL);
3850 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3852 restored = test_mode_restored(ddraw2, window);
3853 ok(!restored, "Display mode restored after ddraw1-ddraw2 SetCooperativeLevel() call sequence\n");
3854 IDirectDraw_Release(ddraw);
3855 IDirectDraw2_Release(ddraw2);
3857 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
3858 ddraw2 = create_ddraw();
3859 ok(!!ddraw2, "Failed to create a ddraw object.\n");
3860 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
3861 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3863 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_NORMAL);
3864 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3866 memset(&ddsd, 0, sizeof(ddsd));
3867 ddsd.dwSize = sizeof(ddsd);
3868 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
3869 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
3870 ddsd.dwWidth = ddsd.dwHeight = 8;
3871 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3872 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
3873 IDirectDrawSurface_Release(surface);
3874 restored = test_mode_restored(ddraw2, window);
3875 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
3877 IDirectDraw_Release(ddraw);
3878 IDirectDraw2_Release(ddraw2);
3879 DestroyWindow(window);
3882 static void test_lighting_interface_versions(void)
3884 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3885 IDirect3DMaterial2 *emissive, *background;
3886 IDirect3DViewport2 *viewport;
3887 IDirect3DDevice2 *device;
3888 IDirectDrawSurface *rt;
3889 IDirectDraw2 *ddraw;
3890 D3DCOLOR color;
3891 HWND window;
3892 HRESULT hr;
3893 D3DMATERIALHANDLE mat_handle;
3894 DWORD rs;
3895 unsigned int i;
3896 ULONG ref;
3897 static D3DVERTEX quad[] =
3899 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3900 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3901 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3902 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3904 static D3DLVERTEX lquad[] =
3906 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3907 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3908 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3909 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3911 static D3DTLVERTEX tlquad[] =
3913 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3914 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3915 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3916 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3918 static const struct
3920 D3DVERTEXTYPE vertextype;
3921 void *data;
3922 DWORD d3drs_lighting, d3drs_specular;
3923 DWORD draw_flags;
3924 D3DCOLOR color;
3926 tests[] =
3928 /* Lighting is enabled when D3DVT_VERTEX is used and D3DDP_DONOTLIGHT is not
3929 * set. D3DVT_VERTEX has diffuse = 0xffffffff and specular = 0x00000000, as
3930 * in later d3d versions */
3931 { D3DVT_VERTEX, quad, FALSE, FALSE, 0, 0x0000ff00},
3932 { D3DVT_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
3933 { D3DVT_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
3934 { D3DVT_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
3935 { D3DVT_VERTEX, quad, FALSE, TRUE, 0, 0x0000ff00},
3936 { D3DVT_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
3937 { D3DVT_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
3938 { D3DVT_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
3940 { D3DVT_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
3941 { D3DVT_LVERTEX, lquad, TRUE, FALSE, 0, 0x00ff0000},
3942 { D3DVT_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
3943 { D3DVT_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
3944 { D3DVT_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
3945 { D3DVT_LVERTEX, lquad, TRUE, TRUE, 0, 0x00ff8080},
3946 { D3DVT_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
3947 { D3DVT_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
3949 { D3DVT_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
3950 { D3DVT_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
3951 { D3DVT_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
3952 { D3DVT_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
3953 { D3DVT_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
3954 { D3DVT_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
3955 { D3DVT_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
3956 { D3DVT_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
3959 window = create_window();
3960 ddraw = create_ddraw();
3961 ok(!!ddraw, "Failed to create a ddraw object.\n");
3962 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3964 skip("Failed to create a 3D device, skipping test.\n");
3965 IDirectDraw2_Release(ddraw);
3966 DestroyWindow(window);
3967 return;
3970 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
3971 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3973 viewport = create_viewport(device, 0, 0, 640, 480);
3974 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
3975 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
3977 emissive = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
3978 hr = IDirect3DMaterial2_GetHandle(emissive, device, &mat_handle);
3979 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
3980 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
3981 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
3982 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
3983 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr);
3985 background = create_diffuse_material(device, 0.1f, 0.1f, 0.1f, 0.1f);
3986 viewport_set_background(device, viewport, background);
3988 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
3989 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#x.\n", hr);
3990 ok(rs == TRUE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#x, expected TRUE.\n", rs);
3992 for (i = 0; i < ARRAY_SIZE(tests); i++)
3994 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
3995 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3997 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
3998 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#x.\n", hr);
3999 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
4000 tests[i].d3drs_specular);
4001 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#x.\n", hr);
4003 hr = IDirect3DDevice2_BeginScene(device);
4004 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4005 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
4006 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
4007 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4008 hr = IDirect3DDevice2_EndScene(device);
4009 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4011 color = get_surface_color(rt, 320, 240);
4012 ok(compare_color(color, tests[i].color, 1),
4013 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
4014 color, tests[i].color, i);
4017 destroy_material(background);
4018 destroy_material(emissive);
4019 destroy_viewport(device, viewport);
4020 IDirectDrawSurface_Release(rt);
4021 IDirect3DDevice2_Release(device);
4022 ref = IDirectDraw2_Release(ddraw);
4023 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
4024 DestroyWindow(window);
4027 static struct
4029 BOOL received;
4030 IDirectDraw2 *ddraw;
4031 HWND window;
4032 DWORD coop_level;
4033 } activateapp_testdata;
4035 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
4037 if (message == WM_ACTIVATEAPP)
4039 if (activateapp_testdata.ddraw)
4041 HRESULT hr;
4042 activateapp_testdata.received = FALSE;
4043 hr = IDirectDraw2_SetCooperativeLevel(activateapp_testdata.ddraw,
4044 activateapp_testdata.window, activateapp_testdata.coop_level);
4045 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
4046 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
4048 activateapp_testdata.received = TRUE;
4051 return DefWindowProcA(hwnd, message, wparam, lparam);
4054 static void test_coop_level_activateapp(void)
4056 IDirectDraw2 *ddraw;
4057 HRESULT hr;
4058 HWND window;
4059 WNDCLASSA wc = {0};
4060 DDSURFACEDESC ddsd;
4061 IDirectDrawSurface *surface;
4063 ddraw = create_ddraw();
4064 ok(!!ddraw, "Failed to create a ddraw object.\n");
4066 wc.lpfnWndProc = activateapp_test_proc;
4067 wc.lpszClassName = "ddraw_test_wndproc_wc";
4068 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4070 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
4071 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
4073 /* Exclusive with window already active. */
4074 SetForegroundWindow(window);
4075 activateapp_testdata.received = FALSE;
4076 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4077 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4078 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
4079 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4080 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4082 /* Exclusive with window not active. */
4083 SetForegroundWindow(GetDesktopWindow());
4084 activateapp_testdata.received = FALSE;
4085 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4086 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4087 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4088 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4089 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4091 /* Normal with window not active, then exclusive with the same window. */
4092 SetForegroundWindow(GetDesktopWindow());
4093 activateapp_testdata.received = FALSE;
4094 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4095 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4096 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
4097 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4098 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4099 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4100 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4101 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4103 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
4104 SetForegroundWindow(GetDesktopWindow());
4105 activateapp_testdata.received = FALSE;
4106 activateapp_testdata.ddraw = ddraw;
4107 activateapp_testdata.window = window;
4108 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
4109 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4110 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4111 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4112 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4113 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4115 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
4116 * succeeding. Another switch to exclusive and back to normal is needed to release the
4117 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
4118 * WM_ACTIVATEAPP messages. */
4119 activateapp_testdata.ddraw = NULL;
4120 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4121 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4122 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4123 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4125 /* Setting DDSCL_NORMAL with recursive invocation. */
4126 SetForegroundWindow(GetDesktopWindow());
4127 activateapp_testdata.received = FALSE;
4128 activateapp_testdata.ddraw = ddraw;
4129 activateapp_testdata.window = window;
4130 activateapp_testdata.coop_level = DDSCL_NORMAL;
4131 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4132 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4133 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4135 /* DDraw is in exclusive mode now. */
4136 memset(&ddsd, 0, sizeof(ddsd));
4137 ddsd.dwSize = sizeof(ddsd);
4138 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
4139 ddsd.dwBackBufferCount = 1;
4140 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
4141 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4142 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4143 IDirectDrawSurface_Release(surface);
4145 /* Recover again, just to be sure. */
4146 activateapp_testdata.ddraw = NULL;
4147 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4148 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4149 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4150 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4152 DestroyWindow(window);
4153 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
4154 IDirectDraw2_Release(ddraw);
4157 struct format_support_check
4159 const DDPIXELFORMAT *format;
4160 BOOL supported;
4163 static HRESULT WINAPI test_unsupported_formats_cb(DDSURFACEDESC *desc, void *ctx)
4165 struct format_support_check *format = ctx;
4167 if (!memcmp(format->format, &desc->ddpfPixelFormat, sizeof(*format->format)))
4169 format->supported = TRUE;
4170 return DDENUMRET_CANCEL;
4173 return DDENUMRET_OK;
4176 static void test_unsupported_formats(void)
4178 HRESULT hr;
4179 BOOL expect_success;
4180 HWND window;
4181 IDirectDraw2 *ddraw;
4182 IDirect3DDevice2 *device;
4183 IDirectDrawSurface *surface;
4184 DDSURFACEDESC ddsd;
4185 unsigned int i, j;
4186 DWORD expected_caps;
4187 static const struct
4189 const char *name;
4190 DDPIXELFORMAT fmt;
4192 formats[] =
4195 "D3DFMT_A8R8G8B8",
4197 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
4198 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
4202 "D3DFMT_P8",
4204 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
4205 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
4209 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
4211 window = create_window();
4212 ddraw = create_ddraw();
4213 ok(!!ddraw, "Failed to create a ddraw object.\n");
4214 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4216 skip("Failed to create a 3D device, skipping test.\n");
4217 IDirectDraw2_Release(ddraw);
4218 DestroyWindow(window);
4219 return;
4222 for (i = 0; i < ARRAY_SIZE(formats); i++)
4224 struct format_support_check check = {&formats[i].fmt, FALSE};
4225 hr = IDirect3DDevice2_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
4226 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
4228 for (j = 0; j < ARRAY_SIZE(caps); j++)
4230 memset(&ddsd, 0, sizeof(ddsd));
4231 ddsd.dwSize = sizeof(ddsd);
4232 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4233 ddsd.ddpfPixelFormat = formats[i].fmt;
4234 ddsd.dwWidth = 4;
4235 ddsd.dwHeight = 4;
4236 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
4238 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
4239 expect_success = FALSE;
4240 else
4241 expect_success = TRUE;
4243 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4244 ok(SUCCEEDED(hr) == expect_success,
4245 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
4246 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
4247 if (FAILED(hr))
4248 continue;
4250 memset(&ddsd, 0, sizeof(ddsd));
4251 ddsd.dwSize = sizeof(ddsd);
4252 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
4253 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4255 if (caps[j] & DDSCAPS_VIDEOMEMORY)
4256 expected_caps = DDSCAPS_VIDEOMEMORY;
4257 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
4258 expected_caps = DDSCAPS_SYSTEMMEMORY;
4259 else if (check.supported)
4260 expected_caps = DDSCAPS_VIDEOMEMORY;
4261 else
4262 expected_caps = DDSCAPS_SYSTEMMEMORY;
4264 ok(ddsd.ddsCaps.dwCaps & expected_caps,
4265 "Expected capability %#x, format %s, input cap %#x.\n",
4266 expected_caps, formats[i].name, caps[j]);
4268 IDirectDrawSurface_Release(surface);
4272 IDirect3DDevice2_Release(device);
4273 IDirectDraw2_Release(ddraw);
4274 DestroyWindow(window);
4277 static void test_rt_caps(void)
4279 PALETTEENTRY palette_entries[256];
4280 IDirectDrawPalette *palette;
4281 IDirect3DDevice2 *device;
4282 IDirectDraw2 *ddraw;
4283 DWORD z_depth = 0;
4284 IDirect3D2 *d3d;
4285 unsigned int i;
4286 ULONG refcount;
4287 HWND window;
4288 HRESULT hr;
4290 static const DDPIXELFORMAT p8_fmt =
4292 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
4293 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
4296 static const struct
4298 const DDPIXELFORMAT *pf;
4299 DWORD caps_in;
4300 DWORD caps_out;
4301 HRESULT create_device_hr;
4302 HRESULT set_rt_hr;
4303 HRESULT alternative_set_rt_hr;
4304 BOOL create_may_fail;
4306 test_data[] =
4309 NULL,
4310 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
4311 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4312 D3D_OK,
4313 D3D_OK,
4314 D3D_OK,
4315 FALSE,
4318 NULL,
4319 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
4320 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4321 D3D_OK,
4322 D3D_OK,
4323 D3D_OK,
4324 FALSE,
4327 NULL,
4328 DDSCAPS_OFFSCREENPLAIN,
4329 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4330 DDERR_INVALIDCAPS,
4331 DDERR_INVALIDCAPS,
4332 DDERR_INVALIDCAPS,
4333 FALSE,
4336 NULL,
4337 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4338 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4339 D3DERR_SURFACENOTINVIDMEM,
4340 D3D_OK,
4341 D3D_OK,
4342 FALSE,
4345 NULL,
4346 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4347 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4348 DDERR_INVALIDCAPS,
4349 DDERR_INVALIDCAPS,
4350 DDERR_INVALIDCAPS,
4351 FALSE,
4354 NULL,
4355 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
4356 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4357 D3D_OK,
4358 D3D_OK,
4359 D3D_OK,
4360 FALSE,
4363 NULL,
4364 DDSCAPS_3DDEVICE,
4365 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4366 D3D_OK,
4367 D3D_OK,
4368 D3D_OK,
4369 FALSE,
4372 NULL,
4374 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4375 DDERR_INVALIDCAPS,
4376 DDERR_INVALIDCAPS,
4377 DDERR_INVALIDCAPS,
4378 FALSE,
4381 NULL,
4382 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4383 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4384 D3DERR_SURFACENOTINVIDMEM,
4385 D3D_OK,
4386 D3D_OK,
4387 FALSE,
4390 NULL,
4391 DDSCAPS_SYSTEMMEMORY,
4392 DDSCAPS_SYSTEMMEMORY,
4393 DDERR_INVALIDCAPS,
4394 DDERR_INVALIDCAPS,
4395 DDERR_INVALIDCAPS,
4396 FALSE,
4399 &p8_fmt,
4401 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4402 DDERR_INVALIDCAPS,
4403 DDERR_INVALIDCAPS,
4404 DDERR_INVALIDCAPS,
4405 FALSE,
4408 &p8_fmt,
4409 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
4410 ~0U /* AMD r200 */,
4411 DDERR_NOPALETTEATTACHED,
4412 DDERR_INVALIDCAPS,
4413 DDERR_INVALIDCAPS,
4414 FALSE,
4417 &p8_fmt,
4418 DDSCAPS_OFFSCREENPLAIN,
4419 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4420 DDERR_INVALIDCAPS,
4421 DDERR_INVALIDCAPS,
4422 DDERR_INVALIDCAPS,
4423 FALSE,
4426 &p8_fmt,
4427 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4428 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4429 DDERR_NOPALETTEATTACHED,
4430 DDERR_INVALIDCAPS,
4431 DDERR_INVALIDCAPS,
4432 FALSE,
4435 &p8_fmt,
4436 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4437 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4438 DDERR_INVALIDCAPS,
4439 DDERR_INVALIDCAPS,
4440 DDERR_INVALIDCAPS,
4441 FALSE,
4444 NULL,
4445 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
4446 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
4447 DDERR_INVALIDCAPS,
4448 DDERR_INVALIDPIXELFORMAT,
4449 DDERR_INVALIDCAPS,
4450 TRUE /* AMD Evergreen */,
4453 NULL,
4454 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
4455 ~0U /* AMD Evergreen */,
4456 DDERR_INVALIDCAPS,
4457 DDERR_INVALIDPIXELFORMAT,
4458 DDERR_INVALIDCAPS,
4459 FALSE,
4462 NULL,
4463 DDSCAPS_ZBUFFER,
4464 ~0U /* AMD Evergreen */,
4465 DDERR_INVALIDCAPS,
4466 DDERR_INVALIDCAPS,
4467 DDERR_INVALIDCAPS,
4468 FALSE,
4471 NULL,
4472 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
4473 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
4474 DDERR_INVALIDCAPS,
4475 DDERR_INVALIDPIXELFORMAT,
4476 DDERR_INVALIDPIXELFORMAT,
4477 TRUE /* Nvidia Kepler */,
4480 NULL,
4481 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
4482 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
4483 DDERR_INVALIDCAPS,
4484 DDERR_INVALIDCAPS,
4485 DDERR_INVALIDCAPS,
4486 TRUE /* Nvidia Kepler */,
4490 window = create_window();
4491 ddraw = create_ddraw();
4492 ok(!!ddraw, "Failed to create a ddraw object.\n");
4493 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4495 skip("Failed to create a 3D device, skipping test.\n");
4496 IDirectDraw2_Release(ddraw);
4497 DestroyWindow(window);
4498 return;
4500 z_depth = get_device_z_depth(device);
4501 ok(!!z_depth, "Failed to get device z depth.\n");
4502 IDirect3DDevice2_Release(device);
4504 if (FAILED(IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d)))
4506 skip("D3D interface is not available, skipping test.\n");
4507 goto done;
4510 memset(palette_entries, 0, sizeof(palette_entries));
4511 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
4512 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
4514 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
4516 IDirectDrawSurface *surface, *rt, *expected_rt, *tmp;
4517 DDSURFACEDESC surface_desc;
4518 IDirect3DDevice2 *device;
4520 memset(&surface_desc, 0, sizeof(surface_desc));
4521 surface_desc.dwSize = sizeof(surface_desc);
4522 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4523 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
4524 if (test_data[i].pf)
4526 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
4527 surface_desc.ddpfPixelFormat = *test_data[i].pf;
4529 if (test_data[i].caps_in & DDSCAPS_ZBUFFER)
4531 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
4532 U2(surface_desc).dwZBufferBitDepth = z_depth;
4534 surface_desc.dwWidth = 640;
4535 surface_desc.dwHeight = 480;
4536 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4537 ok(SUCCEEDED(hr) || broken(test_data[i].create_may_fail),
4538 "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
4539 i, test_data[i].caps_in, hr);
4540 if (FAILED(hr))
4541 continue;
4543 memset(&surface_desc, 0, sizeof(surface_desc));
4544 surface_desc.dwSize = sizeof(surface_desc);
4545 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
4546 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
4547 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
4548 "Test %u: Got unexpected caps %#x, expected %#x.\n",
4549 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
4551 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
4552 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
4553 i, hr, test_data[i].create_device_hr);
4554 if (FAILED(hr))
4556 if (hr == DDERR_NOPALETTEATTACHED)
4558 hr = IDirectDrawSurface_SetPalette(surface, palette);
4559 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
4560 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
4561 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
4562 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
4563 else
4564 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
4566 IDirectDrawSurface_Release(surface);
4568 memset(&surface_desc, 0, sizeof(surface_desc));
4569 surface_desc.dwSize = sizeof(surface_desc);
4570 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4571 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
4572 surface_desc.dwWidth = 640;
4573 surface_desc.dwHeight = 480;
4574 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4575 ok(SUCCEEDED(hr), "Test %u: Failed to create surface, hr %#x.\n", i, hr);
4577 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
4578 ok(SUCCEEDED(hr), "Test %u: Failed to create device, hr %#x.\n", i, hr);
4581 memset(&surface_desc, 0, sizeof(surface_desc));
4582 surface_desc.dwSize = sizeof(surface_desc);
4583 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4584 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
4585 if (test_data[i].pf)
4587 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
4588 surface_desc.ddpfPixelFormat = *test_data[i].pf;
4590 if (test_data[i].caps_in & DDSCAPS_ZBUFFER)
4592 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
4593 U2(surface_desc).dwZBufferBitDepth = z_depth;
4595 surface_desc.dwWidth = 640;
4596 surface_desc.dwHeight = 480;
4597 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &rt, NULL);
4598 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
4599 i, test_data[i].caps_in, hr);
4601 hr = IDirect3DDevice2_SetRenderTarget(device, rt, 0);
4602 ok(hr == test_data[i].set_rt_hr || broken(hr == test_data[i].alternative_set_rt_hr),
4603 "Test %u: Got unexpected hr %#x, expected %#x.\n",
4604 i, hr, test_data[i].set_rt_hr);
4605 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
4606 expected_rt = rt;
4607 else
4608 expected_rt = surface;
4610 /* It appears the surface is set as render target in this case, but no
4611 * reference is taken. */
4612 if (hr == DDERR_INVALIDPIXELFORMAT)
4614 refcount = IDirectDrawSurface_AddRef(rt);
4615 ok(refcount == 2, "Test %u: Got unexpected refcount %u.\n", i, refcount);
4618 hr = IDirect3DDevice2_GetRenderTarget(device, &tmp);
4619 ok(SUCCEEDED(hr), "Test %u: Failed to get render target, hr %#x.\n", i, hr);
4620 ok(tmp == expected_rt, "Test %u: Got unexpected rt %p.\n", i, tmp);
4622 IDirectDrawSurface_Release(tmp);
4623 IDirectDrawSurface_Release(rt);
4624 refcount = IDirect3DDevice2_Release(device);
4625 ok(refcount == 0, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
4626 refcount = IDirectDrawSurface_Release(surface);
4627 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
4630 IDirectDrawPalette_Release(palette);
4631 IDirect3D2_Release(d3d);
4633 done:
4634 refcount = IDirectDraw2_Release(ddraw);
4635 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4636 DestroyWindow(window);
4639 static void test_primary_caps(void)
4641 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
4642 IDirectDrawSurface *surface;
4643 DDSURFACEDESC surface_desc;
4644 IDirectDraw2 *ddraw;
4645 unsigned int i;
4646 ULONG refcount;
4647 HWND window;
4648 HRESULT hr;
4650 static const struct
4652 DWORD coop_level;
4653 DWORD caps_in;
4654 DWORD back_buffer_count;
4655 HRESULT hr;
4656 DWORD caps_out;
4658 test_data[] =
4661 DDSCL_NORMAL,
4662 DDSCAPS_PRIMARYSURFACE,
4663 ~0u,
4664 DD_OK,
4665 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
4668 DDSCL_NORMAL,
4669 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
4670 ~0u,
4671 DDERR_INVALIDCAPS,
4672 ~0u,
4675 DDSCL_NORMAL,
4676 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
4677 ~0u,
4678 DDERR_INVALIDCAPS,
4679 ~0u,
4682 DDSCL_NORMAL,
4683 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
4684 ~0u,
4685 DDERR_INVALIDCAPS,
4686 ~0u,
4689 DDSCL_NORMAL,
4690 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
4691 ~0u,
4692 DDERR_INVALIDCAPS,
4693 ~0u,
4696 DDSCL_NORMAL,
4697 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
4698 ~0u,
4699 DDERR_INVALIDCAPS,
4700 ~0u,
4703 DDSCL_NORMAL,
4704 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4705 ~0u,
4706 DDERR_INVALIDCAPS,
4707 ~0u,
4710 DDSCL_NORMAL,
4711 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4713 DDERR_INVALIDCAPS,
4714 ~0u,
4717 DDSCL_NORMAL,
4718 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4720 DDERR_NOEXCLUSIVEMODE,
4721 ~0u,
4724 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4725 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4727 DDERR_INVALIDCAPS,
4728 ~0u,
4731 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4732 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4734 DD_OK,
4735 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
4738 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4739 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
4741 DDERR_INVALIDCAPS,
4742 ~0u,
4745 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4746 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
4748 DDERR_INVALIDCAPS,
4749 ~0u,
4753 window = create_window();
4754 ddraw = create_ddraw();
4755 ok(!!ddraw, "Failed to create a ddraw object.\n");
4757 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
4759 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
4760 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4762 memset(&surface_desc, 0, sizeof(surface_desc));
4763 surface_desc.dwSize = sizeof(surface_desc);
4764 surface_desc.dwFlags = DDSD_CAPS;
4765 if (test_data[i].back_buffer_count != ~0u)
4766 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
4767 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
4768 surface_desc.dwBackBufferCount = test_data[i].back_buffer_count;
4769 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4770 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
4771 if (FAILED(hr))
4772 continue;
4774 memset(&surface_desc, 0, sizeof(surface_desc));
4775 surface_desc.dwSize = sizeof(surface_desc);
4776 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
4777 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
4778 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
4779 "Test %u: Got unexpected caps %#x, expected %#x.\n",
4780 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
4782 IDirectDrawSurface_Release(surface);
4785 refcount = IDirectDraw2_Release(ddraw);
4786 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4787 DestroyWindow(window);
4790 static void test_surface_lock(void)
4792 IDirectDraw2 *ddraw;
4793 IDirectDrawSurface *surface;
4794 IDirect3DDevice2 *device;
4795 HRESULT hr;
4796 HWND window;
4797 unsigned int i;
4798 DDSURFACEDESC ddsd;
4799 ULONG refcount;
4800 DWORD z_depth = 0;
4801 static const struct
4803 DWORD caps;
4804 const char *name;
4806 tests[] =
4809 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
4810 "videomemory offscreenplain"
4813 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4814 "systemmemory offscreenplain"
4817 DDSCAPS_PRIMARYSURFACE,
4818 "primary"
4821 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
4822 "videomemory texture"
4825 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
4826 "systemmemory texture"
4829 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
4830 "render target"
4833 DDSCAPS_ZBUFFER,
4834 "Z buffer"
4838 window = create_window();
4839 ddraw = create_ddraw();
4840 ok(!!ddraw, "Failed to create a ddraw object.\n");
4841 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4843 skip("Failed to create a 3D device, skipping test.\n");
4844 IDirectDraw2_Release(ddraw);
4845 DestroyWindow(window);
4846 return;
4848 z_depth = get_device_z_depth(device);
4849 ok(!!z_depth, "Failed to get device z depth.\n");
4850 IDirect3DDevice2_Release(device);
4852 for (i = 0; i < ARRAY_SIZE(tests); i++)
4854 memset(&ddsd, 0, sizeof(ddsd));
4855 ddsd.dwSize = sizeof(ddsd);
4856 ddsd.dwFlags = DDSD_CAPS;
4857 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
4859 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
4860 ddsd.dwWidth = 64;
4861 ddsd.dwHeight = 64;
4863 if (tests[i].caps & DDSCAPS_ZBUFFER)
4865 ddsd.dwFlags |= DDSD_ZBUFFERBITDEPTH;
4866 U2(ddsd).dwZBufferBitDepth = z_depth;
4868 ddsd.ddsCaps.dwCaps = tests[i].caps;
4870 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4871 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
4873 memset(&ddsd, 0, sizeof(ddsd));
4874 ddsd.dwSize = sizeof(ddsd);
4875 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
4876 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
4877 if (SUCCEEDED(hr))
4879 hr = IDirectDrawSurface_Unlock(surface, NULL);
4880 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
4883 memset(&ddsd, 0, sizeof(ddsd));
4884 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
4885 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, tests[i].name);
4887 IDirectDrawSurface_Release(surface);
4890 refcount = IDirectDraw2_Release(ddraw);
4891 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4892 DestroyWindow(window);
4895 static void test_surface_discard(void)
4897 IDirectDraw2 *ddraw;
4898 IDirect3DDevice2 *device;
4899 HRESULT hr;
4900 HWND window;
4901 DDSURFACEDESC ddsd;
4902 IDirectDrawSurface *surface, *target;
4903 void *addr;
4904 static const struct
4906 DWORD caps;
4907 BOOL discard;
4909 tests[] =
4911 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, TRUE},
4912 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, FALSE},
4913 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, TRUE},
4914 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, FALSE},
4916 unsigned int i;
4918 window = create_window();
4919 ddraw = create_ddraw();
4920 ok(!!ddraw, "Failed to create a ddraw object.\n");
4921 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4923 skip("Failed to create a 3D device, skipping test.\n");
4924 DestroyWindow(window);
4925 IDirectDraw2_Release(ddraw);
4926 return;
4929 hr = IDirect3DDevice2_GetRenderTarget(device, &target);
4930 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4932 for (i = 0; i < ARRAY_SIZE(tests); i++)
4934 BOOL discarded;
4936 memset(&ddsd, 0, sizeof(ddsd));
4937 ddsd.dwSize = sizeof(ddsd);
4938 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4939 ddsd.ddsCaps.dwCaps = tests[i].caps;
4940 ddsd.dwWidth = 64;
4941 ddsd.dwHeight = 64;
4942 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4943 if (FAILED(hr))
4945 skip("Failed to create surface, skipping.\n");
4946 continue;
4949 memset(&ddsd, 0, sizeof(ddsd));
4950 ddsd.dwSize = sizeof(ddsd);
4951 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
4952 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4953 addr = ddsd.lpSurface;
4954 hr = IDirectDrawSurface_Unlock(surface, NULL);
4955 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4957 memset(&ddsd, 0, sizeof(ddsd));
4958 ddsd.dwSize = sizeof(ddsd);
4959 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
4960 ok(SUCCEEDED(hr) , "Failed to lock surface, hr %#x.\n", hr);
4961 discarded = ddsd.lpSurface != addr;
4962 hr = IDirectDrawSurface_Unlock(surface, NULL);
4963 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4965 hr = IDirectDrawSurface_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
4966 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
4968 memset(&ddsd, 0, sizeof(ddsd));
4969 ddsd.dwSize = sizeof(ddsd);
4970 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
4971 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4972 discarded |= ddsd.lpSurface != addr;
4973 hr = IDirectDrawSurface_Unlock(surface, NULL);
4974 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4976 IDirectDrawSurface_Release(surface);
4978 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
4979 * AMD r500, evergreen). Windows XP, at least on AMD r200, never changes the pointer. */
4980 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
4983 IDirectDrawSurface_Release(target);
4984 IDirect3DDevice2_Release(device);
4985 IDirectDraw2_Release(ddraw);
4986 DestroyWindow(window);
4989 static void fill_surface(IDirectDrawSurface *surface, D3DCOLOR color)
4991 DDSURFACEDESC surface_desc = {sizeof(surface_desc)};
4992 HRESULT hr;
4993 unsigned int x, y;
4994 DWORD *ptr;
4996 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
4997 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4999 for (y = 0; y < surface_desc.dwHeight; ++y)
5001 ptr = (DWORD *)((BYTE *)surface_desc.lpSurface + y * U1(surface_desc).lPitch);
5002 for (x = 0; x < surface_desc.dwWidth; ++x)
5004 ptr[x] = color;
5008 hr = IDirectDrawSurface_Unlock(surface, NULL);
5009 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5012 static void test_flip(void)
5014 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
5015 IDirectDrawSurface *frontbuffer, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
5016 DDSCAPS caps = {DDSCAPS_FLIP};
5017 DDSURFACEDESC surface_desc;
5018 BOOL sysmem_primary;
5019 IDirectDraw2 *ddraw;
5020 DWORD expected_caps;
5021 unsigned int i;
5022 D3DCOLOR color;
5023 ULONG refcount;
5024 HWND window;
5025 HRESULT hr;
5027 static const struct
5029 const char *name;
5030 DWORD caps;
5032 test_data[] =
5034 {"PRIMARYSURFACE", DDSCAPS_PRIMARYSURFACE},
5035 {"OFFSCREENPLAIN", DDSCAPS_OFFSCREENPLAIN},
5036 {"TEXTURE", DDSCAPS_TEXTURE},
5039 window = create_window();
5040 ddraw = create_ddraw();
5041 ok(!!ddraw, "Failed to create a ddraw object.\n");
5043 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5044 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5046 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5048 /* Creating a flippable texture induces a BSoD on some versions of the
5049 * Intel graphics driver. At least Intel GMA 950 with driver version
5050 * 6.14.10.4926 on Windows XP SP3 is affected. */
5051 if ((test_data[i].caps & DDSCAPS_TEXTURE) && ddraw_is_intel(ddraw))
5053 win_skip("Skipping flippable texture test.\n");
5054 continue;
5057 memset(&surface_desc, 0, sizeof(surface_desc));
5058 surface_desc.dwSize = sizeof(surface_desc);
5059 surface_desc.dwFlags = DDSD_CAPS;
5060 if (!(test_data[i].caps & DDSCAPS_PRIMARYSURFACE))
5061 surface_desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
5062 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
5063 surface_desc.dwWidth = 512;
5064 surface_desc.dwHeight = 512;
5065 surface_desc.dwBackBufferCount = 3;
5066 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
5067 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5069 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
5070 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
5071 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
5072 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5074 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
5075 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
5076 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
5077 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5079 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
5080 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
5081 todo_wine_if(test_data[i].caps & DDSCAPS_TEXTURE)
5082 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
5083 if (FAILED(hr))
5084 continue;
5086 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
5087 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
5088 hr = IDirectDrawSurface_IsLost(frontbuffer);
5089 ok(hr == DD_OK, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5090 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
5091 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
5092 ok(hr == DDERR_NOEXCLUSIVEMODE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5093 else
5094 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
5095 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5096 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
5097 hr = IDirectDrawSurface_IsLost(frontbuffer);
5098 todo_wine ok(hr == DDERR_SURFACELOST, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5099 hr = restore_surfaces(ddraw);
5100 ok(SUCCEEDED(hr), "%s: Failed to restore surfaces, hr %#x.\n", test_data[i].name, hr);
5102 memset(&surface_desc, 0, sizeof(surface_desc));
5103 surface_desc.dwSize = sizeof(surface_desc);
5104 hr = IDirectDrawSurface_GetSurfaceDesc(frontbuffer, &surface_desc);
5105 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
5106 expected_caps = DDSCAPS_FRONTBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
5107 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
5108 expected_caps |= DDSCAPS_VISIBLE;
5109 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
5110 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
5111 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
5113 hr = IDirectDrawSurface_GetAttachedSurface(frontbuffer, &caps, &backbuffer1);
5114 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
5115 memset(&surface_desc, 0, sizeof(surface_desc));
5116 surface_desc.dwSize = sizeof(surface_desc);
5117 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer1, &surface_desc);
5118 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
5119 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
5120 test_data[i].name, surface_desc.dwBackBufferCount);
5121 expected_caps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER);
5122 expected_caps |= DDSCAPS_BACKBUFFER;
5123 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
5124 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
5126 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
5127 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
5128 memset(&surface_desc, 0, sizeof(surface_desc));
5129 surface_desc.dwSize = sizeof(surface_desc);
5130 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer2, &surface_desc);
5131 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
5132 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
5133 test_data[i].name, surface_desc.dwBackBufferCount);
5134 expected_caps &= ~DDSCAPS_BACKBUFFER;
5135 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
5136 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
5138 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
5139 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
5140 memset(&surface_desc, 0, sizeof(surface_desc));
5141 surface_desc.dwSize = sizeof(surface_desc);
5142 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer3, &surface_desc);
5143 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
5144 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
5145 test_data[i].name, surface_desc.dwBackBufferCount);
5146 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
5147 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
5149 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer3, &caps, &surface);
5150 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
5151 ok(surface == frontbuffer, "%s: Got unexpected surface %p, expected %p.\n",
5152 test_data[i].name, surface, frontbuffer);
5153 IDirectDrawSurface_Release(surface);
5155 memset(&surface_desc, 0, sizeof(surface_desc));
5156 surface_desc.dwSize = sizeof(surface_desc);
5157 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5158 surface_desc.ddsCaps.dwCaps = 0;
5159 surface_desc.dwWidth = 640;
5160 surface_desc.dwHeight = 480;
5161 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5162 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
5163 hr = IDirectDrawSurface_Flip(frontbuffer, surface, DDFLIP_WAIT);
5164 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5165 IDirectDrawSurface_Release(surface);
5167 hr = IDirectDrawSurface_Flip(frontbuffer, frontbuffer, DDFLIP_WAIT);
5168 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5169 hr = IDirectDrawSurface_Flip(backbuffer1, NULL, DDFLIP_WAIT);
5170 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5171 hr = IDirectDrawSurface_Flip(backbuffer2, NULL, DDFLIP_WAIT);
5172 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5173 hr = IDirectDrawSurface_Flip(backbuffer3, NULL, DDFLIP_WAIT);
5174 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5176 /* The Nvidia Geforce 7 driver cannot do a color fill on a texture backbuffer after
5177 * the backbuffer has been locked or GetSurfaceDesc has been called. Do it ourselves
5178 * as a workaround. */
5179 fill_surface(backbuffer1, 0xffff0000);
5180 fill_surface(backbuffer2, 0xff00ff00);
5181 fill_surface(backbuffer3, 0xff0000ff);
5183 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
5184 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
5185 color = get_surface_color(backbuffer1, 320, 240);
5186 /* The testbot seems to just copy the contents of one surface to all the
5187 * others, instead of properly flipping. */
5188 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
5189 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5190 color = get_surface_color(backbuffer2, 320, 240);
5191 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5192 fill_surface(backbuffer3, 0xffff0000);
5194 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
5195 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
5196 color = get_surface_color(backbuffer1, 320, 240);
5197 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
5198 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5199 color = get_surface_color(backbuffer2, 320, 240);
5200 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5201 fill_surface(backbuffer3, 0xff00ff00);
5203 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
5204 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
5205 color = get_surface_color(backbuffer1, 320, 240);
5206 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
5207 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5208 color = get_surface_color(backbuffer2, 320, 240);
5209 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5210 fill_surface(backbuffer3, 0xff0000ff);
5212 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer1, DDFLIP_WAIT);
5213 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
5214 color = get_surface_color(backbuffer2, 320, 240);
5215 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
5216 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5217 color = get_surface_color(backbuffer3, 320, 240);
5218 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5219 fill_surface(backbuffer1, 0xffff0000);
5221 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer2, DDFLIP_WAIT);
5222 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
5223 color = get_surface_color(backbuffer1, 320, 240);
5224 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5225 color = get_surface_color(backbuffer3, 320, 240);
5226 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
5227 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5228 fill_surface(backbuffer2, 0xff00ff00);
5230 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer3, DDFLIP_WAIT);
5231 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
5232 color = get_surface_color(backbuffer1, 320, 240);
5233 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
5234 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5235 color = get_surface_color(backbuffer2, 320, 240);
5236 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5238 IDirectDrawSurface_Release(backbuffer3);
5239 IDirectDrawSurface_Release(backbuffer2);
5240 IDirectDrawSurface_Release(backbuffer1);
5241 IDirectDrawSurface_Release(frontbuffer);
5244 refcount = IDirectDraw2_Release(ddraw);
5245 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5246 DestroyWindow(window);
5249 static void reset_ddsd(DDSURFACEDESC *ddsd)
5251 memset(ddsd, 0, sizeof(*ddsd));
5252 ddsd->dwSize = sizeof(*ddsd);
5255 static void test_set_surface_desc(void)
5257 IDirectDraw2 *ddraw;
5258 HWND window;
5259 HRESULT hr;
5260 DDSURFACEDESC ddsd;
5261 IDirectDrawSurface *surface;
5262 IDirectDrawSurface3 *surface3;
5263 BYTE data[16*16*4];
5264 ULONG ref;
5265 unsigned int i;
5266 static const struct
5268 DWORD caps;
5269 BOOL supported;
5270 const char *name;
5272 invalid_caps_tests[] =
5274 {DDSCAPS_VIDEOMEMORY, FALSE, "videomemory plain"},
5275 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, TRUE, "systemmemory texture"},
5276 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, FALSE, "systemmemory primary"},
5279 window = create_window();
5280 ddraw = create_ddraw();
5281 ok(!!ddraw, "Failed to create a ddraw object.\n");
5282 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5283 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5285 reset_ddsd(&ddsd);
5286 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
5287 ddsd.dwWidth = 8;
5288 ddsd.dwHeight = 8;
5289 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5290 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5291 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
5292 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5293 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5294 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5295 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
5297 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
5298 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5300 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
5301 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface3 interface, hr %#x.\n", hr);
5302 IDirectDrawSurface_Release(surface);
5304 reset_ddsd(&ddsd);
5305 ddsd.dwFlags = DDSD_LPSURFACE;
5306 ddsd.lpSurface = data;
5307 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5308 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5310 /* Redundantly setting the same lpSurface is not an error. */
5311 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5312 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5313 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
5314 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5315 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
5316 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
5318 hr = IDirectDrawSurface3_Lock(surface3, NULL, &ddsd, 0, NULL);
5319 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5320 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
5321 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
5322 hr = IDirectDrawSurface3_Unlock(surface3, NULL);
5323 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5325 reset_ddsd(&ddsd);
5326 ddsd.dwFlags = DDSD_LPSURFACE;
5327 ddsd.lpSurface = data;
5328 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 1);
5329 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
5331 ddsd.lpSurface = NULL;
5332 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5333 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
5335 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, NULL, 0);
5336 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
5338 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
5339 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5340 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
5341 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
5343 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
5344 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5345 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
5347 ddsd.dwFlags = DDSD_CAPS;
5348 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5349 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
5351 /* dwCaps = 0 is allowed, but ignored. */
5352 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
5353 ddsd.lpSurface = data;
5354 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5355 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
5356 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
5357 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5358 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
5359 ddsd.ddsCaps.dwCaps = 0;
5360 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5361 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5363 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
5364 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5365 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
5366 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
5368 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
5369 reset_ddsd(&ddsd);
5370 ddsd.dwFlags = DDSD_HEIGHT;
5371 ddsd.dwHeight = 16;
5372 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5373 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
5375 ddsd.lpSurface = data;
5376 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
5377 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5378 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5380 ddsd.dwHeight = 0;
5381 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5382 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
5384 reset_ddsd(&ddsd);
5385 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
5386 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
5387 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
5388 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
5390 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0. */
5391 reset_ddsd(&ddsd);
5392 ddsd.dwFlags = DDSD_PITCH;
5393 U1(ddsd).lPitch = 8 * 4;
5394 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5395 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
5397 ddsd.dwFlags = DDSD_WIDTH;
5398 ddsd.dwWidth = 16;
5399 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5400 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
5402 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
5403 ddsd.lpSurface = data;
5404 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5405 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
5407 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
5408 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5409 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
5411 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5412 U1(ddsd).lPitch = 16 * 4;
5413 ddsd.dwWidth = 16;
5414 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5415 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5417 reset_ddsd(&ddsd);
5418 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
5419 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5420 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
5421 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
5422 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
5424 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
5426 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
5427 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5428 U1(ddsd).lPitch = 4 * 4;
5429 ddsd.lpSurface = data;
5430 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5431 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
5433 U1(ddsd).lPitch = 4;
5434 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5435 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
5437 U1(ddsd).lPitch = 16 * 4 + 1;
5438 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5439 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
5441 U1(ddsd).lPitch = 16 * 4 + 3;
5442 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5443 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
5445 U1(ddsd).lPitch = -4;
5446 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5447 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
5449 U1(ddsd).lPitch = 16 * 4;
5450 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5451 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5453 reset_ddsd(&ddsd);
5454 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5455 U1(ddsd).lPitch = 0;
5456 ddsd.dwWidth = 16;
5457 ddsd.lpSurface = data;
5458 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5459 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
5461 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5462 U1(ddsd).lPitch = 16 * 4;
5463 ddsd.dwWidth = 0;
5464 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5465 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
5467 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
5468 ddsd.dwFlags = DDSD_PIXELFORMAT;
5469 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5470 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5471 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
5472 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5473 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5474 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5475 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5476 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
5478 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
5479 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5480 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5482 /* Can't set color keys. */
5483 reset_ddsd(&ddsd);
5484 ddsd.dwFlags = DDSD_CKSRCBLT;
5485 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
5486 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
5487 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5488 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
5490 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
5491 ddsd.lpSurface = data;
5492 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5493 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
5495 IDirectDrawSurface3_Release(surface3);
5497 /* SetSurfaceDesc needs systemmemory surfaces.
5499 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing DDSD_LINEARSIZE is moot. */
5500 for (i = 0; i < ARRAY_SIZE(invalid_caps_tests); i++)
5502 reset_ddsd(&ddsd);
5503 ddsd.dwFlags = DDSD_CAPS;
5504 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
5505 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
5507 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5508 ddsd.dwWidth = 8;
5509 ddsd.dwHeight = 8;
5510 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5511 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5512 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
5513 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5514 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5515 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5518 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
5519 ok(SUCCEEDED(hr) || hr == DDERR_NODIRECTDRAWHW, "Failed to create surface, hr %#x.\n", hr);
5520 if (FAILED(hr))
5522 skip("Cannot create a %s surface, skipping vidmem SetSurfaceDesc test.\n",
5523 invalid_caps_tests[i].name);
5524 goto done;
5526 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
5527 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface3 interface, hr %#x.\n", hr);
5528 IDirectDrawSurface_Release(surface);
5530 reset_ddsd(&ddsd);
5531 ddsd.dwFlags = DDSD_LPSURFACE;
5532 ddsd.lpSurface = data;
5533 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5534 if (invalid_caps_tests[i].supported)
5536 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5538 else
5540 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
5541 invalid_caps_tests[i].name, hr);
5543 /* Check priority of error conditions. */
5544 ddsd.dwFlags = DDSD_WIDTH;
5545 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5546 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
5547 invalid_caps_tests[i].name, hr);
5550 IDirectDrawSurface3_Release(surface3);
5553 done:
5554 ref = IDirectDraw2_Release(ddraw);
5555 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
5556 DestroyWindow(window);
5559 static void test_user_memory_getdc(void)
5561 IDirectDraw2 *ddraw;
5562 HWND window;
5563 HRESULT hr;
5564 DDSURFACEDESC ddsd;
5565 IDirectDrawSurface *surface;
5566 IDirectDrawSurface3 *surface3;
5567 DWORD data[16][16];
5568 HBITMAP bitmap;
5569 DIBSECTION dib;
5570 ULONG ref;
5571 int size;
5572 HDC dc;
5573 unsigned int x, y;
5575 window = create_window();
5576 ddraw = create_ddraw();
5577 ok(!!ddraw, "Failed to create a ddraw object.\n");
5579 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5580 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5582 reset_ddsd(&ddsd);
5583 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
5584 ddsd.dwWidth = 16;
5585 ddsd.dwHeight = 16;
5586 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5587 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5588 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
5589 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5590 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5591 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5592 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
5593 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
5594 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5596 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
5597 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface3 interface, hr %#x.\n", hr);
5598 IDirectDrawSurface_Release(surface);
5600 memset(data, 0xaa, sizeof(data));
5601 reset_ddsd(&ddsd);
5602 ddsd.dwFlags = DDSD_LPSURFACE;
5603 ddsd.lpSurface = data;
5604 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5605 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5607 hr = IDirectDrawSurface3_GetDC(surface3, &dc);
5608 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
5609 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
5610 ok(!!bitmap, "Failed to get bitmap.\n");
5611 size = GetObjectA(bitmap, sizeof(dib), &dib);
5612 ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
5613 ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
5614 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
5615 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
5616 hr = IDirectDrawSurface3_ReleaseDC(surface3, dc);
5617 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
5619 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
5620 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
5622 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
5623 ddsd.lpSurface = data;
5624 ddsd.dwWidth = 4;
5625 ddsd.dwHeight = 8;
5626 U1(ddsd).lPitch = sizeof(*data);
5627 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5628 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5630 memset(data, 0xaa, sizeof(data));
5631 hr = IDirectDrawSurface3_GetDC(surface3, &dc);
5632 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
5633 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
5634 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
5635 hr = IDirectDrawSurface3_ReleaseDC(surface3, dc);
5636 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
5638 for (y = 0; y < 4; y++)
5640 for (x = 0; x < 4; x++)
5642 if ((x == 1 || x == 2) && (y == 1 || y == 2))
5643 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
5644 x, y, data[y][x]);
5645 else
5646 ok(data[y][x] == 0x00000000, "Expected color 0xaaaaaaaa on position %ux%u, got %#x.\n",
5647 x, y, data[y][x]);
5650 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
5651 data[0][5]);
5652 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
5653 data[7][3]);
5654 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
5655 data[7][4]);
5656 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
5657 data[8][0]);
5659 IDirectDrawSurface3_Release(surface3);
5660 ref = IDirectDraw2_Release(ddraw);
5661 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
5662 DestroyWindow(window);
5665 static void test_sysmem_overlay(void)
5667 IDirectDraw2 *ddraw;
5668 HWND window;
5669 HRESULT hr;
5670 DDSURFACEDESC ddsd;
5671 IDirectDrawSurface *surface;
5672 ULONG ref;
5674 window = create_window();
5675 ddraw = create_ddraw();
5676 ok(!!ddraw, "Failed to create a ddraw object.\n");
5678 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5679 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5681 reset_ddsd(&ddsd);
5682 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
5683 ddsd.dwWidth = 16;
5684 ddsd.dwHeight = 16;
5685 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
5686 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5687 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5688 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
5689 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5690 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5691 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5692 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
5693 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
5695 ref = IDirectDraw2_Release(ddraw);
5696 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
5697 DestroyWindow(window);
5700 static void test_primary_palette(void)
5702 DDSCAPS surface_caps = {DDSCAPS_FLIP};
5703 IDirectDrawSurface *primary, *backbuffer;
5704 PALETTEENTRY palette_entries[256];
5705 IDirectDrawPalette *palette, *tmp;
5706 DDSURFACEDESC surface_desc;
5707 IDirectDraw2 *ddraw;
5708 DWORD palette_caps;
5709 ULONG refcount;
5710 HWND window;
5711 HRESULT hr;
5713 window = create_window();
5714 ddraw = create_ddraw();
5715 ok(!!ddraw, "Failed to create a ddraw object.\n");
5716 if (FAILED(IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
5718 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
5719 IDirectDraw2_Release(ddraw);
5720 DestroyWindow(window);
5721 return;
5723 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5724 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5726 memset(&surface_desc, 0, sizeof(surface_desc));
5727 surface_desc.dwSize = sizeof(surface_desc);
5728 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
5729 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
5730 surface_desc.dwBackBufferCount = 1;
5731 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
5732 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5733 hr = IDirectDrawSurface_GetAttachedSurface(primary, &surface_caps, &backbuffer);
5734 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
5736 memset(palette_entries, 0, sizeof(palette_entries));
5737 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
5738 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5739 refcount = get_refcount((IUnknown *)palette);
5740 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5742 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
5743 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
5744 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
5746 hr = IDirectDrawSurface_SetPalette(primary, palette);
5747 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5749 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
5750 * and is generally somewhat broken with respect to 8 bpp / palette
5751 * handling. */
5752 if (SUCCEEDED(IDirectDrawSurface_GetPalette(backbuffer, &tmp)))
5754 win_skip("Broken palette handling detected, skipping tests.\n");
5755 IDirectDrawPalette_Release(tmp);
5756 IDirectDrawPalette_Release(palette);
5757 /* The Windows 8 testbot keeps extra references to the primary and
5758 * backbuffer while in 8 bpp mode. */
5759 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
5760 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
5761 goto done;
5764 refcount = get_refcount((IUnknown *)palette);
5765 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
5767 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
5768 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
5769 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
5770 "Got unexpected palette caps %#x.\n", palette_caps);
5772 hr = IDirectDrawSurface_SetPalette(primary, NULL);
5773 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5774 refcount = get_refcount((IUnknown *)palette);
5775 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5777 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
5778 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
5779 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
5781 hr = IDirectDrawSurface_SetPalette(primary, palette);
5782 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5783 refcount = get_refcount((IUnknown *)palette);
5784 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
5786 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
5787 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
5788 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
5789 IDirectDrawPalette_Release(tmp);
5790 hr = IDirectDrawSurface_GetPalette(backbuffer, &tmp);
5791 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
5793 refcount = IDirectDrawPalette_Release(palette);
5794 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5795 refcount = IDirectDrawPalette_Release(palette);
5796 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5798 /* Note that this only seems to work when the palette is attached to the
5799 * primary surface. When attached to a regular surface, attempting to get
5800 * the palette here will cause an access violation. */
5801 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
5802 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
5804 hr = IDirectDrawSurface_IsLost(primary);
5805 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
5807 memset(&surface_desc, 0, sizeof(surface_desc));
5808 surface_desc.dwSize = sizeof(surface_desc);
5809 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
5810 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5811 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
5812 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
5813 ok(U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == 8, "Got unexpected bit count %u.\n",
5814 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
5816 hr = set_display_mode(ddraw, 640, 480);
5817 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
5819 memset(&surface_desc, 0, sizeof(surface_desc));
5820 surface_desc.dwSize = sizeof(surface_desc);
5821 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
5822 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5823 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
5824 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
5825 ok(U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == 32
5826 || U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == 24,
5827 "Got unexpected bit count %u.\n", U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
5829 hr = IDirectDrawSurface_IsLost(primary);
5830 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
5831 hr = IDirectDrawSurface_Restore(primary);
5832 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
5833 hr = IDirectDrawSurface_IsLost(primary);
5834 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
5836 memset(&surface_desc, 0, sizeof(surface_desc));
5837 surface_desc.dwSize = sizeof(surface_desc);
5838 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
5839 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5840 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
5841 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
5842 ok(U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == 32
5843 || U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == 24,
5844 "Got unexpected bit count %u.\n", U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
5846 done:
5847 refcount = IDirectDrawSurface_Release(backbuffer);
5848 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5849 refcount = IDirectDrawSurface_Release(primary);
5850 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5851 refcount = IDirectDraw2_Release(ddraw);
5852 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5853 DestroyWindow(window);
5856 static HRESULT WINAPI surface_counter(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
5858 UINT *surface_count = context;
5860 ++(*surface_count);
5861 IDirectDrawSurface_Release(surface);
5863 return DDENUMRET_OK;
5866 static void test_surface_attachment(void)
5868 IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
5869 DDSCAPS caps = {DDSCAPS_TEXTURE};
5870 DDSURFACEDESC surface_desc;
5871 IDirectDraw2 *ddraw;
5872 UINT surface_count;
5873 ULONG refcount;
5874 HWND window;
5875 HRESULT hr;
5877 window = create_window();
5878 ddraw = create_ddraw();
5879 ok(!!ddraw, "Failed to create a ddraw object.\n");
5880 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5881 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5883 memset(&surface_desc, 0, sizeof(surface_desc));
5884 surface_desc.dwSize = sizeof(surface_desc);
5885 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
5886 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
5887 U2(surface_desc).dwMipMapCount = 3;
5888 surface_desc.dwWidth = 128;
5889 surface_desc.dwHeight = 128;
5890 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
5891 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5893 hr = IDirectDrawSurface_GetAttachedSurface(surface1, &caps, &surface2);
5894 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
5895 hr = IDirectDrawSurface_GetAttachedSurface(surface2, &caps, &surface3);
5896 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
5897 hr = IDirectDrawSurface_GetAttachedSurface(surface3, &caps, &surface4);
5898 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5900 surface_count = 0;
5901 IDirectDrawSurface_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
5902 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
5903 surface_count = 0;
5904 IDirectDrawSurface_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
5905 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
5906 surface_count = 0;
5907 IDirectDrawSurface_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
5908 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
5910 memset(&surface_desc, 0, sizeof(surface_desc));
5911 surface_desc.dwSize = sizeof(surface_desc);
5912 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5913 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5914 surface_desc.dwWidth = 16;
5915 surface_desc.dwHeight = 16;
5916 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
5917 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5919 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
5920 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5921 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
5922 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5923 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
5924 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5925 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
5926 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5927 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
5928 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5929 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
5930 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5932 IDirectDrawSurface_Release(surface4);
5934 memset(&surface_desc, 0, sizeof(surface_desc));
5935 surface_desc.dwSize = sizeof(surface_desc);
5936 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5937 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
5938 surface_desc.dwWidth = 16;
5939 surface_desc.dwHeight = 16;
5940 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
5941 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5943 if (SUCCEEDED(hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4)))
5945 skip("Running on refrast, skipping some tests.\n");
5946 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface4);
5947 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5949 else
5951 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5952 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
5953 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5954 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
5955 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5956 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
5957 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5958 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
5959 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5960 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
5961 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5964 IDirectDrawSurface_Release(surface4);
5965 IDirectDrawSurface_Release(surface3);
5966 IDirectDrawSurface_Release(surface2);
5967 IDirectDrawSurface_Release(surface1);
5969 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5970 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5972 /* Try a single primary and two offscreen plain surfaces. */
5973 memset(&surface_desc, 0, sizeof(surface_desc));
5974 surface_desc.dwSize = sizeof(surface_desc);
5975 surface_desc.dwFlags = DDSD_CAPS;
5976 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
5977 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
5978 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5980 memset(&surface_desc, 0, sizeof(surface_desc));
5981 surface_desc.dwSize = sizeof(surface_desc);
5982 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5983 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5984 surface_desc.dwWidth = registry_mode.dmPelsWidth;
5985 surface_desc.dwHeight = registry_mode.dmPelsHeight;
5986 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
5987 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5989 memset(&surface_desc, 0, sizeof(surface_desc));
5990 surface_desc.dwSize = sizeof(surface_desc);
5991 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5992 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5993 surface_desc.dwWidth = registry_mode.dmPelsWidth;
5994 surface_desc.dwHeight = registry_mode.dmPelsHeight;
5995 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
5996 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5998 /* This one has a different size. */
5999 memset(&surface_desc, 0, sizeof(surface_desc));
6000 surface_desc.dwSize = sizeof(surface_desc);
6001 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6002 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6003 surface_desc.dwWidth = 128;
6004 surface_desc.dwHeight = 128;
6005 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6006 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6008 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
6009 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6010 /* Try the reverse without detaching first. */
6011 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
6012 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
6013 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
6014 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6016 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
6017 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6018 /* Try to detach reversed. */
6019 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
6020 ok(hr == DDERR_CANNOTDETACHSURFACE, "Got unexpected hr %#x.\n", hr);
6021 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
6022 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6024 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
6025 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6026 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
6027 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6029 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
6030 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6031 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
6032 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6034 IDirectDrawSurface_Release(surface4);
6035 IDirectDrawSurface_Release(surface3);
6036 IDirectDrawSurface_Release(surface2);
6037 IDirectDrawSurface_Release(surface1);
6039 /* Test depth surfaces of different sizes. */
6040 memset(&surface_desc, 0, sizeof(surface_desc));
6041 surface_desc.dwSize = sizeof(surface_desc);
6042 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6043 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
6044 surface_desc.dwWidth = 64;
6045 surface_desc.dwHeight = 64;
6046 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6047 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
6049 memset(&surface_desc, 0, sizeof(surface_desc));
6050 surface_desc.dwSize = sizeof(surface_desc);
6051 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
6052 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
6053 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6054 surface_desc.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
6055 U1(surface_desc.ddpfPixelFormat).dwZBufferBitDepth = 16;
6056 U3(surface_desc.ddpfPixelFormat).dwZBitMask = 0x0000ffff;
6057 surface_desc.dwWidth = 32;
6058 surface_desc.dwHeight = 32;
6059 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
6060 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
6061 surface_desc.dwWidth = 64;
6062 surface_desc.dwHeight = 64;
6063 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
6064 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
6065 surface_desc.dwWidth = 128;
6066 surface_desc.dwHeight = 128;
6067 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6068 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
6070 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
6071 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6072 if (SUCCEEDED(hr))
6073 IDirectDrawSurface2_DeleteAttachedSurface(surface1, 0, surface3);
6074 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface3);
6075 ok(hr == D3D_OK, "Failed to attach depth buffer, hr %#x.\n", hr);
6076 hr = IDirectDrawSurface2_DeleteAttachedSurface(surface1, 0, surface3);
6077 ok(hr == D3D_OK, "Failed to detach depth buffer, hr %#x.\n", hr);
6078 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
6079 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6081 IDirectDrawSurface2_Release(surface4);
6082 IDirectDrawSurface2_Release(surface3);
6083 IDirectDrawSurface2_Release(surface2);
6084 IDirectDrawSurface2_Release(surface1);
6086 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
6087 memset(&surface_desc, 0, sizeof(surface_desc));
6088 surface_desc.dwSize = sizeof(surface_desc);
6089 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6090 surface_desc.dwWidth = 64;
6091 surface_desc.dwHeight = 64;
6092 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
6093 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6094 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
6095 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
6096 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xf800;
6097 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x07e0;
6098 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x001f;
6099 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6100 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6101 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
6102 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6104 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
6105 surface_desc.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
6106 U1(surface_desc.ddpfPixelFormat).dwZBufferBitDepth = 16;
6107 U3(surface_desc.ddpfPixelFormat).dwZBitMask = 0x0000ffff;
6108 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
6109 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6111 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
6112 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6113 refcount = get_refcount((IUnknown *)surface2);
6114 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6115 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
6116 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
6118 /* Attaching while already attached to other surface. */
6119 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface2);
6120 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6121 hr = IDirectDrawSurface_DeleteAttachedSurface(surface3, 0, surface2);
6122 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6123 IDirectDrawSurface_Release(surface3);
6125 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
6126 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6127 refcount = get_refcount((IUnknown *)surface2);
6128 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6130 /* Automatic detachment on release. */
6131 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
6132 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6133 refcount = get_refcount((IUnknown *)surface2);
6134 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6135 refcount = IDirectDrawSurface_Release(surface1);
6136 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6137 refcount = IDirectDrawSurface_Release(surface2);
6138 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6139 refcount = IDirectDraw2_Release(ddraw);
6140 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6141 DestroyWindow(window);
6144 static void test_pixel_format(void)
6146 HWND window, window2 = NULL;
6147 HDC hdc, hdc2 = NULL;
6148 HMODULE gl = NULL;
6149 int format, test_format;
6150 PIXELFORMATDESCRIPTOR pfd;
6151 IDirectDraw2 *ddraw = NULL;
6152 IDirectDrawClipper *clipper = NULL;
6153 DDSURFACEDESC ddsd;
6154 IDirectDrawSurface *primary = NULL;
6155 DDBLTFX fx;
6156 HRESULT hr;
6158 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
6159 100, 100, 160, 160, NULL, NULL, NULL, NULL);
6160 if (!window)
6162 skip("Failed to create window\n");
6163 return;
6166 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
6167 100, 100, 160, 160, NULL, NULL, NULL, NULL);
6169 hdc = GetDC(window);
6170 if (!hdc)
6172 skip("Failed to get DC\n");
6173 goto cleanup;
6176 if (window2)
6177 hdc2 = GetDC(window2);
6179 gl = LoadLibraryA("opengl32.dll");
6180 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
6182 format = GetPixelFormat(hdc);
6183 ok(format == 0, "new window has pixel format %d\n", format);
6185 ZeroMemory(&pfd, sizeof(pfd));
6186 pfd.nSize = sizeof(pfd);
6187 pfd.nVersion = 1;
6188 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
6189 pfd.iPixelType = PFD_TYPE_RGBA;
6190 pfd.iLayerType = PFD_MAIN_PLANE;
6191 format = ChoosePixelFormat(hdc, &pfd);
6192 if (format <= 0)
6194 skip("no pixel format available\n");
6195 goto cleanup;
6198 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
6200 skip("failed to set pixel format\n");
6201 goto cleanup;
6204 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
6206 skip("failed to set pixel format on second window\n");
6207 if (hdc2)
6209 ReleaseDC(window2, hdc2);
6210 hdc2 = NULL;
6214 ddraw = create_ddraw();
6215 ok(!!ddraw, "Failed to create a ddraw object.\n");
6217 test_format = GetPixelFormat(hdc);
6218 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6220 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6221 if (FAILED(hr))
6223 skip("Failed to set cooperative level, hr %#x.\n", hr);
6224 goto cleanup;
6227 test_format = GetPixelFormat(hdc);
6228 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6230 if (hdc2)
6232 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
6233 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
6234 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
6235 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
6237 test_format = GetPixelFormat(hdc);
6238 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6240 test_format = GetPixelFormat(hdc2);
6241 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
6244 memset(&ddsd, 0, sizeof(ddsd));
6245 ddsd.dwSize = sizeof(ddsd);
6246 ddsd.dwFlags = DDSD_CAPS;
6247 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
6249 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
6250 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
6252 test_format = GetPixelFormat(hdc);
6253 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6255 if (hdc2)
6257 test_format = GetPixelFormat(hdc2);
6258 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
6261 if (clipper)
6263 hr = IDirectDrawSurface2_SetClipper(primary, clipper);
6264 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
6266 test_format = GetPixelFormat(hdc);
6267 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6269 test_format = GetPixelFormat(hdc2);
6270 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
6273 memset(&fx, 0, sizeof(fx));
6274 fx.dwSize = sizeof(fx);
6275 hr = IDirectDrawSurface2_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6276 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
6278 test_format = GetPixelFormat(hdc);
6279 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6281 if (hdc2)
6283 test_format = GetPixelFormat(hdc2);
6284 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
6287 cleanup:
6288 if (primary) IDirectDrawSurface2_Release(primary);
6289 if (clipper) IDirectDrawClipper_Release(clipper);
6290 if (ddraw) IDirectDraw2_Release(ddraw);
6291 if (gl) FreeLibrary(gl);
6292 if (hdc) ReleaseDC(window, hdc);
6293 if (hdc2) ReleaseDC(window2, hdc2);
6294 DestroyWindow(window);
6295 if (window2) DestroyWindow(window2);
6298 static void test_create_surface_pitch(void)
6300 IDirectDrawSurface *surface;
6301 DDSURFACEDESC surface_desc;
6302 IDirectDraw2 *ddraw;
6303 unsigned int i;
6304 ULONG refcount;
6305 HWND window;
6306 HRESULT hr;
6307 void *mem;
6309 static const struct
6311 DWORD caps;
6312 DWORD flags_in;
6313 DWORD pitch_in;
6314 HRESULT hr;
6315 DWORD flags_out;
6316 DWORD pitch_out32;
6317 DWORD pitch_out64;
6319 test_data[] =
6321 /* 0 */
6322 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
6323 0, 0, DD_OK,
6324 DDSD_PITCH, 0x100, 0x100},
6325 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
6326 DDSD_PITCH, 0x104, DD_OK,
6327 DDSD_PITCH, 0x100, 0x100},
6328 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
6329 DDSD_PITCH, 0x0f8, DD_OK,
6330 DDSD_PITCH, 0x100, 0x100},
6331 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
6332 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
6333 0, 0, 0 },
6334 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6335 0, 0, DD_OK,
6336 DDSD_PITCH, 0x100, 0x0fc},
6337 /* 5 */
6338 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6339 DDSD_PITCH, 0x104, DD_OK,
6340 DDSD_PITCH, 0x100, 0x0fc},
6341 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6342 DDSD_PITCH, 0x0f8, DD_OK,
6343 DDSD_PITCH, 0x100, 0x0fc},
6344 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6345 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
6346 DDSD_PITCH, 0x100, 0x0fc},
6347 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6348 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
6349 0, 0, 0 },
6350 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6351 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDPARAMS,
6352 0, 0, 0 },
6353 /* 10 */
6354 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
6355 0, 0, DDERR_INVALIDCAPS,
6356 0, 0, 0 },
6357 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
6358 0, 0, DD_OK,
6359 DDSD_PITCH, 0x100, 0 },
6360 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
6361 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
6362 0, 0, 0 },
6363 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
6364 0, 0, DDERR_INVALIDCAPS,
6365 0, 0, 0 },
6366 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
6367 0, 0, DD_OK,
6368 DDSD_PITCH, 0x100, 0 },
6369 /* 15 */
6370 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
6371 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDPARAMS,
6372 0, 0, 0 },
6374 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
6376 window = create_window();
6377 ddraw = create_ddraw();
6378 ok(!!ddraw, "Failed to create a ddraw object.\n");
6379 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6380 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6382 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
6384 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6386 memset(&surface_desc, 0, sizeof(surface_desc));
6387 surface_desc.dwSize = sizeof(surface_desc);
6388 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
6389 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
6390 surface_desc.dwWidth = 63;
6391 surface_desc.dwHeight = 63;
6392 U1(surface_desc).lPitch = test_data[i].pitch_in;
6393 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6394 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
6395 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
6396 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6397 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6398 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
6399 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6400 if (test_data[i].flags_in & DDSD_LPSURFACE)
6402 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
6403 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, expected_hr);
6404 surface_desc.lpSurface = mem;
6405 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6407 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
6408 continue;
6409 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
6410 if (FAILED(hr))
6411 continue;
6413 memset(&surface_desc, 0, sizeof(surface_desc));
6414 surface_desc.dwSize = sizeof(surface_desc);
6415 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
6416 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
6417 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
6418 "Test %u: Got unexpected flags %#x, expected %#x.\n",
6419 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
6420 /* The pitch for textures seems to be implementation specific. */
6421 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
6423 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
6424 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
6425 "Test %u: Got unexpected pitch %u, expected %u.\n",
6426 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
6427 else
6428 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
6429 "Test %u: Got unexpected pitch %u, expected %u.\n",
6430 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
6432 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
6434 IDirectDrawSurface_Release(surface);
6437 HeapFree(GetProcessHeap(), 0, mem);
6438 refcount = IDirectDraw2_Release(ddraw);
6439 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6440 DestroyWindow(window);
6443 static void test_mipmap(void)
6445 IDirectDrawSurface *surface1;
6446 IDirectDrawSurface2 *surface, *surface_base, *surface_mip;
6447 unsigned int i, mipmap_count;
6448 DDSURFACEDESC surface_desc;
6449 IDirectDraw2 *ddraw;
6450 ULONG refcount;
6451 HWND window;
6452 HRESULT hr;
6453 DDSCAPS caps = {DDSCAPS_COMPLEX};
6454 DDCAPS hal_caps;
6456 static const struct
6458 DWORD flags;
6459 DWORD caps;
6460 DWORD width;
6461 DWORD height;
6462 DWORD mipmap_count_in;
6463 HRESULT hr;
6464 DWORD mipmap_count_out;
6466 tests[] =
6468 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
6469 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS, 0},
6470 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
6471 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS, 0},
6472 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 6},
6473 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 6},
6476 window = create_window();
6477 ddraw = create_ddraw();
6478 ok(!!ddraw, "Failed to create a ddraw object.\n");
6479 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6480 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6482 memset(&hal_caps, 0, sizeof(hal_caps));
6483 hal_caps.dwSize = sizeof(hal_caps);
6484 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
6485 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6486 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
6488 skip("Mipmapped textures not supported, skipping tests.\n");
6489 IDirectDraw2_Release(ddraw);
6490 DestroyWindow(window);
6491 return;
6494 for (i = 0; i < ARRAY_SIZE(tests); ++i)
6496 memset(&surface_desc, 0, sizeof(surface_desc));
6497 surface_desc.dwSize = sizeof(surface_desc);
6498 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
6499 surface_desc.ddsCaps.dwCaps = tests[i].caps;
6500 surface_desc.dwWidth = tests[i].width;
6501 surface_desc.dwHeight = tests[i].height;
6502 if (tests[i].flags & DDSD_MIPMAPCOUNT)
6503 U2(surface_desc).dwMipMapCount = tests[i].mipmap_count_in;
6504 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6505 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
6506 if (FAILED(hr))
6507 continue;
6509 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
6510 ok(SUCCEEDED(hr), "Test %u: Failed to get IDirectDrawSurface2 interface, hr %#x.\n", i, hr);
6511 IDirectDrawSurface_Release(surface1);
6513 memset(&surface_desc, 0, sizeof(surface_desc));
6514 surface_desc.dwSize = sizeof(surface_desc);
6515 hr = IDirectDrawSurface2_GetSurfaceDesc(surface, &surface_desc);
6516 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
6517 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
6518 "Test %u: Got unexpected flags %#x.\n", i, surface_desc.dwFlags);
6519 ok(U2(surface_desc).dwMipMapCount == tests[i].mipmap_count_out,
6520 "Test %u: Got unexpected mipmap count %u.\n", i, U2(surface_desc).dwMipMapCount);
6522 surface_base = surface;
6523 IDirectDrawSurface2_AddRef(surface_base);
6524 mipmap_count = U2(surface_desc).dwMipMapCount;
6525 while (mipmap_count > 1)
6527 hr = IDirectDrawSurface2_GetAttachedSurface(surface_base, &caps, &surface_mip);
6528 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get attached surface, hr %#x.\n", i, mipmap_count, hr);
6530 memset(&surface_desc, 0, sizeof(surface_desc));
6531 surface_desc.dwSize = sizeof(surface_desc);
6532 hr = IDirectDrawSurface2_GetSurfaceDesc(surface_base, &surface_desc);
6533 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get surface desc, hr %#x.\n", i, mipmap_count, hr);
6534 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
6535 "Test %u, %u: Got unexpected flags %#x.\n", i, mipmap_count, surface_desc.dwFlags);
6536 ok(U2(surface_desc).dwMipMapCount == mipmap_count,
6537 "Test %u, %u: Got unexpected mipmap count %u.\n",
6538 i, mipmap_count, U2(surface_desc).dwMipMapCount);
6540 memset(&surface_desc, 0, sizeof(surface_desc));
6541 surface_desc.dwSize = sizeof(surface_desc);
6542 hr = IDirectDrawSurface2_Lock(surface_base, NULL, &surface_desc, 0, NULL);
6543 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#x.\n", i, mipmap_count, hr);
6544 ok(surface_desc.dwMipMapCount == mipmap_count,
6545 "Test %u, %u: unexpected change of mipmap count %u.\n",
6546 i, mipmap_count, surface_desc.dwMipMapCount);
6547 memset(&surface_desc, 0, sizeof(surface_desc));
6548 surface_desc.dwSize = sizeof(surface_desc);
6549 hr = IDirectDrawSurface2_Lock(surface_mip, NULL, &surface_desc, 0, NULL);
6550 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#x.\n", i, mipmap_count, hr);
6551 ok(surface_desc.dwMipMapCount == mipmap_count - 1,
6552 "Test %u, %u: Child mipmap count unexpected %u\n", i, mipmap_count, surface_desc.dwMipMapCount);
6553 IDirectDrawSurface2_Unlock(surface_mip, NULL);
6554 IDirectDrawSurface2_Unlock(surface_base, NULL);
6556 IDirectDrawSurface2_Release(surface_base);
6557 surface_base = surface_mip;
6558 --mipmap_count;
6560 IDirectDrawSurface2_Release(surface_base);
6562 IDirectDrawSurface2_Release(surface);
6565 refcount = IDirectDraw2_Release(ddraw);
6566 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6567 DestroyWindow(window);
6570 static void test_palette_complex(void)
6572 IDirectDrawSurface *surface1;
6573 IDirectDrawSurface2 *surface, *mipmap, *tmp;
6574 DDSURFACEDESC surface_desc;
6575 IDirectDraw2 *ddraw;
6576 IDirectDrawPalette *palette, *palette2, *palette_mipmap;
6577 ULONG refcount;
6578 HWND window;
6579 HRESULT hr;
6580 DDSCAPS caps = {DDSCAPS_COMPLEX};
6581 DDCAPS hal_caps;
6582 PALETTEENTRY palette_entries[256];
6583 unsigned int i;
6584 HDC dc;
6585 RGBQUAD rgbquad;
6586 UINT count;
6588 window = create_window();
6589 ddraw = create_ddraw();
6590 ok(!!ddraw, "Failed to create a ddraw object.\n");
6591 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6592 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6594 memset(&hal_caps, 0, sizeof(hal_caps));
6595 hal_caps.dwSize = sizeof(hal_caps);
6596 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
6597 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6598 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
6600 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
6601 IDirectDraw2_Release(ddraw);
6602 DestroyWindow(window);
6603 return;
6606 memset(&surface_desc, 0, sizeof(surface_desc));
6607 surface_desc.dwSize = sizeof(surface_desc);
6608 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6609 surface_desc.dwWidth = 128;
6610 surface_desc.dwHeight = 128;
6611 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
6612 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6613 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
6614 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
6615 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6616 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6617 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
6618 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface2 interface, hr %#x.\n", hr);
6619 IDirectDrawSurface_Release(surface1);
6621 memset(palette_entries, 0, sizeof(palette_entries));
6622 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
6623 palette_entries, &palette, NULL);
6624 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6626 memset(palette_entries, 0, sizeof(palette_entries));
6627 palette_entries[1].peRed = 0xff;
6628 palette_entries[1].peGreen = 0x80;
6629 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
6630 palette_entries, &palette_mipmap, NULL);
6631 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6633 palette2 = (void *)0xdeadbeef;
6634 hr = IDirectDrawSurface2_GetPalette(surface, &palette2);
6635 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6636 ok(!palette2, "Got unexpected palette %p.\n", palette2);
6637 hr = IDirectDrawSurface2_SetPalette(surface, palette);
6638 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6639 hr = IDirectDrawSurface2_GetPalette(surface, &palette2);
6640 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
6641 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
6642 IDirectDrawPalette_Release(palette2);
6644 mipmap = surface;
6645 IDirectDrawSurface2_AddRef(mipmap);
6646 for (i = 0; i < 7; ++i)
6648 hr = IDirectDrawSurface2_GetAttachedSurface(mipmap, &caps, &tmp);
6649 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
6650 palette2 = (void *)0xdeadbeef;
6651 hr = IDirectDrawSurface2_GetPalette(tmp, &palette2);
6652 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
6653 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
6655 hr = IDirectDrawSurface2_SetPalette(tmp, palette_mipmap);
6656 ok(SUCCEEDED(hr), "Failed to set palette, i %u, hr %#x.\n", i, hr);
6658 hr = IDirectDrawSurface2_GetPalette(tmp, &palette2);
6659 ok(SUCCEEDED(hr), "Failed to get palette, i %u, hr %#x.\n", i, hr);
6660 ok(palette_mipmap == palette2, "Got unexpected palette %p.\n", palette2);
6661 IDirectDrawPalette_Release(palette2);
6663 hr = IDirectDrawSurface2_GetDC(tmp, &dc);
6664 ok(SUCCEEDED(hr), "Failed to get DC, i %u, hr %#x.\n", i, hr);
6665 count = GetDIBColorTable(dc, 1, 1, &rgbquad);
6666 ok(count == 1, "Expected count 1, got %u.\n", count);
6667 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x.\n", rgbquad.rgbRed);
6668 ok(rgbquad.rgbGreen == 0x80, "Expected rgbGreen = 0x80, got %#x.\n", rgbquad.rgbGreen);
6669 ok(rgbquad.rgbBlue == 0x0, "Expected rgbBlue = 0x0, got %#x.\n", rgbquad.rgbBlue);
6670 hr = IDirectDrawSurface2_ReleaseDC(tmp, dc);
6671 ok(SUCCEEDED(hr), "Failed to release DC, i %u, hr %#x.\n", i, hr);
6673 IDirectDrawSurface2_Release(mipmap);
6674 mipmap = tmp;
6677 hr = IDirectDrawSurface2_GetAttachedSurface(mipmap, &caps, &tmp);
6678 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
6679 IDirectDrawSurface2_Release(mipmap);
6680 refcount = IDirectDrawSurface2_Release(surface);
6681 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6682 refcount = IDirectDrawPalette_Release(palette_mipmap);
6683 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6684 refcount = IDirectDrawPalette_Release(palette);
6685 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6687 refcount = IDirectDraw2_Release(ddraw);
6688 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6689 DestroyWindow(window);
6692 static void test_p8_blit(void)
6694 IDirectDrawSurface *src, *dst, *dst_p8;
6695 DDSURFACEDESC surface_desc;
6696 IDirectDraw2 *ddraw;
6697 IDirectDrawPalette *palette, *palette2;
6698 ULONG refcount;
6699 HWND window;
6700 HRESULT hr;
6701 PALETTEENTRY palette_entries[256];
6702 unsigned int x;
6703 DDBLTFX fx;
6704 BOOL is_warp;
6705 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
6706 static const BYTE src_data2[] = {0x10, 0x5, 0x4, 0x3, 0x2, 0x1, 0xff, 0x80};
6707 static const BYTE expected_p8[] = {0x10, 0x1, 0x4, 0x3, 0x4, 0x5, 0xff, 0x80};
6708 static const D3DCOLOR expected[] =
6710 0x00101010, 0x00010101, 0x00020202, 0x00030303,
6711 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
6713 D3DCOLOR color;
6715 window = create_window();
6716 ddraw = create_ddraw();
6717 ok(!!ddraw, "Failed to create a ddraw object.\n");
6718 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6719 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6720 is_warp = ddraw_is_warp(ddraw);
6722 memset(palette_entries, 0, sizeof(palette_entries));
6723 palette_entries[1].peGreen = 0xff;
6724 palette_entries[2].peBlue = 0xff;
6725 palette_entries[3].peFlags = 0xff;
6726 palette_entries[4].peRed = 0xff;
6727 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
6728 palette_entries, &palette, NULL);
6729 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6730 palette_entries[1].peBlue = 0xff;
6731 palette_entries[2].peGreen = 0xff;
6732 palette_entries[3].peRed = 0xff;
6733 palette_entries[4].peFlags = 0x0;
6734 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
6735 palette_entries, &palette2, NULL);
6736 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6738 memset(&surface_desc, 0, sizeof(surface_desc));
6739 surface_desc.dwSize = sizeof(surface_desc);
6740 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6741 surface_desc.dwWidth = 8;
6742 surface_desc.dwHeight = 1;
6743 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6744 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6745 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
6746 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
6747 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src, NULL);
6748 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6749 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst_p8, NULL);
6750 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6751 hr = IDirectDrawSurface_SetPalette(dst_p8, palette2);
6752 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6754 memset(&surface_desc, 0, sizeof(surface_desc));
6755 surface_desc.dwSize = sizeof(surface_desc);
6756 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6757 surface_desc.dwWidth = 8;
6758 surface_desc.dwHeight = 1;
6759 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6760 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6761 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
6762 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
6763 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6764 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6765 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
6766 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
6767 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst, NULL);
6768 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6770 memset(&surface_desc, 0, sizeof(surface_desc));
6771 surface_desc.dwSize = sizeof(surface_desc);
6772 hr = IDirectDrawSurface_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
6773 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
6774 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
6775 hr = IDirectDrawSurface_Unlock(src, NULL);
6776 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
6778 hr = IDirectDrawSurface_Lock(dst_p8, NULL, &surface_desc, DDLOCK_WAIT, NULL);
6779 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
6780 memcpy(surface_desc.lpSurface, src_data2, sizeof(src_data2));
6781 hr = IDirectDrawSurface_Unlock(dst_p8, NULL);
6782 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
6784 hr = IDirectDrawSurface_SetPalette(src, palette);
6785 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6786 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
6787 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
6788 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
6789 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
6790 "Failed to blit, hr %#x.\n", hr);
6792 if (SUCCEEDED(hr))
6794 for (x = 0; x < ARRAY_SIZE(expected); x++)
6796 color = get_surface_color(dst, x, 0);
6797 todo_wine ok(compare_color(color, expected[x], 0),
6798 "Pixel %u: Got color %#x, expected %#x.\n",
6799 x, color, expected[x]);
6803 memset(&fx, 0, sizeof(fx));
6804 fx.dwSize = sizeof(fx);
6805 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x2;
6806 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x2;
6807 hr = IDirectDrawSurface7_Blt(dst_p8, NULL, src, NULL, DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &fx);
6808 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
6810 hr = IDirectDrawSurface_Lock(dst_p8, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
6811 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
6812 /* A color keyed P8 blit doesn't do anything on WARP - it just leaves the data in the destination
6813 * surface untouched. P8 blits without color keys work. Error checking (DDBLT_KEYSRC without a key
6814 * for example) also works as expected.
6816 * Using DDBLT_KEYSRC instead of DDBLT_KEYSRCOVERRIDE doesn't change this. Doing this blit with
6817 * the display mode set to P8 doesn't help either. */
6818 ok(!memcmp(surface_desc.lpSurface, expected_p8, sizeof(expected_p8))
6819 || broken(is_warp && !memcmp(surface_desc.lpSurface, src_data2, sizeof(src_data2))),
6820 "Got unexpected P8 color key blit result.\n");
6821 hr = IDirectDrawSurface_Unlock(dst_p8, NULL);
6822 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
6824 IDirectDrawSurface_Release(src);
6825 IDirectDrawSurface_Release(dst);
6826 IDirectDrawSurface_Release(dst_p8);
6827 IDirectDrawPalette_Release(palette);
6828 IDirectDrawPalette_Release(palette2);
6830 refcount = IDirectDraw2_Release(ddraw);
6831 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6832 DestroyWindow(window);
6835 static void test_material(void)
6837 IDirect3DMaterial2 *background, *material;
6838 D3DMATERIALHANDLE mat_handle, tmp;
6839 IDirect3DViewport2 *viewport;
6840 IDirect3DDevice2 *device;
6841 IDirectDrawSurface *rt;
6842 IDirectDraw2 *ddraw;
6843 D3DCOLOR color;
6844 ULONG refcount;
6845 unsigned int i;
6846 HWND window;
6847 HRESULT hr;
6848 BOOL valid;
6850 static D3DVERTEX quad[] =
6852 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
6853 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
6854 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
6855 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
6857 static const struct
6859 BOOL material;
6860 D3DCOLOR expected_color;
6862 test_data[] =
6864 {TRUE, 0x0000ff00},
6865 {FALSE, 0x00ffffff},
6867 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
6869 window = create_window();
6870 ddraw = create_ddraw();
6871 ok(!!ddraw, "Failed to create a ddraw object.\n");
6872 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
6874 skip("Failed to create a 3D device, skipping test.\n");
6875 DestroyWindow(window);
6876 return;
6879 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
6880 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
6882 background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
6883 viewport = create_viewport(device, 0, 0, 640, 480);
6884 viewport_set_background(device, viewport, background);
6885 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
6886 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
6888 material = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
6889 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
6890 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
6892 hr = IDirect3DDevice2_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
6893 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
6894 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
6895 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
6896 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
6897 hr = IDirect3DDevice2_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
6898 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
6899 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
6900 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, 0);
6901 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
6902 hr = IDirect3DDevice2_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
6903 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
6904 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
6906 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6908 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
6909 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
6911 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, test_data[i].material ? mat_handle : 0);
6912 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
6914 hr = IDirect3DDevice2_BeginScene(device);
6915 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6916 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_VERTEX, quad, 4, 0);
6917 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6918 hr = IDirect3DDevice2_EndScene(device);
6919 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6920 color = get_surface_color(rt, 320, 240);
6921 ok(compare_color(color, test_data[i].expected_color, 1),
6922 "Got unexpected color 0x%08x, test %u.\n", color, i);
6925 destroy_material(material);
6926 material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
6927 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
6928 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
6930 hr = IDirect3DViewport2_SetBackground(viewport, mat_handle);
6931 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
6932 hr = IDirect3DViewport2_GetBackground(viewport, &tmp, &valid);
6933 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
6934 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
6935 ok(valid, "Got unexpected valid %#x.\n", valid);
6936 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6937 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
6938 color = get_surface_color(rt, 320, 240);
6939 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
6941 hr = IDirect3DViewport2_SetBackground(viewport, 0);
6942 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6943 hr = IDirect3DViewport2_GetBackground(viewport, &tmp, &valid);
6944 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
6945 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
6946 ok(valid, "Got unexpected valid %#x.\n", valid);
6947 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6948 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
6949 color = get_surface_color(rt, 320, 240);
6950 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
6952 destroy_viewport(device, viewport);
6953 viewport = create_viewport(device, 0, 0, 640, 480);
6955 hr = IDirect3DViewport2_GetBackground(viewport, &tmp, &valid);
6956 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
6957 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
6958 ok(!valid, "Got unexpected valid %#x.\n", valid);
6959 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6960 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
6961 color = get_surface_color(rt, 320, 240);
6962 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x.\n", color);
6964 destroy_viewport(device, viewport);
6965 destroy_material(background);
6966 destroy_material(material);
6967 IDirectDrawSurface_Release(rt);
6968 refcount = IDirect3DDevice2_Release(device);
6969 ok(!refcount, "Device has %u references left.\n", refcount);
6970 refcount = IDirectDraw2_Release(ddraw);
6971 ok(!refcount, "Ddraw object has %u references left.\n", refcount);
6972 DestroyWindow(window);
6975 static void test_lighting(void)
6977 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
6978 static D3DMATRIX mat =
6980 1.0f, 0.0f, 0.0f, 0.0f,
6981 0.0f, 1.0f, 0.0f, 0.0f,
6982 0.0f, 0.0f, 1.0f, 0.0f,
6983 0.0f, 0.0f, 0.0f, 1.0f,
6985 mat_singular =
6987 1.0f, 0.0f, 1.0f, 0.0f,
6988 0.0f, 1.0f, 0.0f, 0.0f,
6989 1.0f, 0.0f, 1.0f, 0.0f,
6990 0.0f, 0.0f, 0.5f, 1.0f,
6992 mat_transf =
6994 0.0f, 0.0f, 1.0f, 0.0f,
6995 0.0f, 1.0f, 0.0f, 0.0f,
6996 -1.0f, 0.0f, 0.0f, 0.0f,
6997 10.f, 10.0f, 10.0f, 1.0f,
6999 mat_nonaffine =
7001 1.0f, 0.0f, 0.0f, 0.0f,
7002 0.0f, 1.0f, 0.0f, 0.0f,
7003 0.0f, 0.0f, 1.0f, -1.0f,
7004 10.f, 10.0f, 10.0f, 0.0f,
7006 static D3DLVERTEX unlitquad[] =
7008 {{-1.0f}, {-1.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
7009 {{-1.0f}, { 0.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
7010 {{ 0.0f}, { 0.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
7011 {{ 0.0f}, {-1.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
7013 litquad[] =
7015 {{-1.0f}, { 0.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
7016 {{-1.0f}, { 1.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
7017 {{ 0.0f}, { 1.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
7018 {{ 0.0f}, { 0.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
7020 static D3DVERTEX unlitnquad[] =
7022 {{0.0f}, {-1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
7023 {{0.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
7024 {{1.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
7025 {{1.0f}, {-1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
7027 litnquad[] =
7029 {{0.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
7030 {{0.0f}, { 1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
7031 {{1.0f}, { 1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
7032 {{1.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
7034 nquad[] =
7036 {{-1.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
7037 {{-1.0f}, { 1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
7038 {{ 1.0f}, { 1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
7039 {{ 1.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
7041 rotatedquad[] =
7043 {{-10.0f}, {-11.0f}, {11.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
7044 {{-10.0f}, { -9.0f}, {11.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
7045 {{-10.0f}, { -9.0f}, { 9.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
7046 {{-10.0f}, {-11.0f}, { 9.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
7048 translatedquad[] =
7050 {{-11.0f}, {-11.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
7051 {{-11.0f}, { -9.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
7052 {{ -9.0f}, { -9.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
7053 {{ -9.0f}, {-11.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
7055 static WORD indices[] = {0, 1, 2, 2, 3, 0};
7056 static const struct
7058 D3DMATRIX *world_matrix;
7059 void *quad;
7060 DWORD expected;
7061 const char *message;
7063 tests[] =
7065 {&mat, nquad, 0x000060ff, "Lit quad with light"},
7066 {&mat_singular, nquad, 0x00004db4, "Lit quad with singular world matrix"},
7067 {&mat_transf, rotatedquad, 0x000060ff, "Lit quad with transformation matrix"},
7068 {&mat_nonaffine, translatedquad, 0x000060ff, "Lit quad with non-affine matrix"},
7071 IDirect3DViewport2 *viewport, *viewport2;
7072 D3DMATERIALHANDLE mat_handle;
7073 IDirect3DMaterial2 *material;
7074 IDirect3DDevice2 *device;
7075 IDirectDrawSurface *rt;
7076 IDirect3DLight *light;
7077 D3DLIGHT2 light_desc;
7078 IDirectDraw2 *ddraw;
7079 IDirect3D2 *d3d;
7080 D3DCOLOR color;
7081 ULONG refcount;
7082 unsigned int i;
7083 HWND window;
7084 HRESULT hr;
7086 window = create_window();
7087 ddraw = create_ddraw();
7088 ok(!!ddraw, "Failed to create a ddraw object.\n");
7089 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
7091 skip("Failed to create a 3D device, skipping test.\n");
7092 DestroyWindow(window);
7093 return;
7096 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
7097 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7099 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
7100 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7102 viewport = create_viewport(device, 0, 0, 640, 480);
7103 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
7104 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7106 material = create_diffuse_and_ambient_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
7107 viewport_set_background(device, viewport, material);
7109 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7110 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
7112 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
7113 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
7114 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
7115 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
7116 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
7117 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
7118 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
7119 ok(SUCCEEDED(hr), "Failed to disable zbuffer, hr %#x.\n", hr);
7120 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
7121 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
7122 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
7123 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
7125 hr = IDirect3DDevice2_BeginScene(device);
7126 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
7128 /* There is no D3DRENDERSTATE_LIGHTING on ddraw < 7. */
7129 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
7130 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
7131 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_LVERTEX, unlitquad,
7132 4, indices, 6, 0);
7133 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7135 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
7136 ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
7137 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_LVERTEX, litquad,
7138 4, indices, 6, 0);
7139 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7141 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
7142 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
7143 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX, unlitnquad,
7144 4, indices, 6, 0);
7145 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7147 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
7148 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
7149 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX, litnquad,
7150 4, indices, 6, 0);
7151 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7153 hr = IDirect3DDevice2_EndScene(device);
7154 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7156 color = get_surface_color(rt, 160, 360);
7157 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x.\n", color);
7158 color = get_surface_color(rt, 160, 120);
7159 ok(color == 0x0000ff00, "Lit quad without normals has color 0x%08x.\n", color);
7160 color = get_surface_color(rt, 480, 360);
7161 ok(color == 0x00ffffff, "Unlit quad with normals has color 0x%08x.\n", color);
7162 color = get_surface_color(rt, 480, 120);
7163 ok(color == 0x00ffffff, "Lit quad with normals has color 0x%08x.\n", color);
7165 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
7166 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7167 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
7168 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7169 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_AMBIENT, 0xff002000);
7170 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7172 hr = IDirect3D2_CreateLight(d3d, &light, NULL);
7173 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7174 memset(&light_desc, 0, sizeof(light_desc));
7175 light_desc.dwSize = sizeof(light_desc);
7176 light_desc.dltType = D3DLIGHT_DIRECTIONAL;
7177 U1(light_desc.dcvColor).r = 0.0f;
7178 U2(light_desc.dcvColor).g = 0.25f;
7179 U3(light_desc.dcvColor).b = 1.0f;
7180 U4(light_desc.dcvColor).a = 1.0f;
7181 U3(light_desc.dvDirection).z = 1.0f;
7182 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
7183 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7184 hr = IDirect3DViewport2_AddLight(viewport, light);
7185 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7186 hr = IDirect3DViewport2_AddLight(viewport, light);
7187 ok(hr == D3DERR_LIGHTHASVIEWPORT, "Got unexpected hr %#x.\n", hr);
7189 viewport2 = create_viewport(device, 0, 0, 640, 480);
7190 hr = IDirect3DViewport2_AddLight(viewport2, light);
7191 ok(hr == D3DERR_LIGHTHASVIEWPORT, "Got unexpected hr %#x.\n", hr);
7192 destroy_viewport(device, viewport2);
7194 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7195 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7197 hr = IDirect3DDevice2_BeginScene(device);
7198 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7200 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX, nquad,
7201 4, indices, 6, 0);
7202 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7204 hr = IDirect3DDevice2_EndScene(device);
7205 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7207 color = get_surface_color(rt, 320, 240);
7208 ok(color == 0x00002000, "Lit quad with no light has color 0x%08x.\n", color);
7210 light_desc.dwFlags = D3DLIGHT_ACTIVE;
7211 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
7212 ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
7214 for (i = 0; i < ARRAY_SIZE(tests); ++i)
7216 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
7217 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
7219 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7220 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
7222 hr = IDirect3DDevice2_BeginScene(device);
7223 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
7225 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX,
7226 tests[i].quad, 4, indices, 6, 0);
7227 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7229 hr = IDirect3DDevice2_EndScene(device);
7230 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7232 color = get_surface_color(rt, 320, 240);
7233 ok(color == tests[i].expected, "%s has color 0x%08x.\n", tests[i].message, color);
7236 hr = IDirect3DViewport2_DeleteLight(viewport, light);
7237 ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#x.\n", hr);
7238 IDirect3DLight_Release(light);
7239 destroy_material(material);
7240 destroy_viewport(device, viewport);
7241 IDirectDrawSurface2_Release(rt);
7242 refcount = IDirect3DDevice2_Release(device);
7243 ok(!refcount, "Device has %u references left.\n", refcount);
7244 IDirect3D2_Release(d3d);
7245 refcount = IDirectDraw2_Release(ddraw);
7246 ok(!refcount, "Ddraw object has %u references left.\n", refcount);
7247 DestroyWindow(window);
7250 static void test_specular_lighting(void)
7252 static const unsigned int vertices_side = 5;
7253 const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
7254 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
7255 static D3DMATRIX mat =
7257 1.0f, 0.0f, 0.0f, 0.0f,
7258 0.0f, 1.0f, 0.0f, 0.0f,
7259 0.0f, 0.0f, 1.0f, 0.0f,
7260 0.0f, 0.0f, 0.0f, 1.0f,
7262 static D3DLIGHT2 directional =
7264 sizeof(D3DLIGHT2),
7265 D3DLIGHT_DIRECTIONAL,
7266 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
7267 {{0.0f}, {0.0f}, {0.0f}},
7268 {{0.0f}, {0.0f}, {1.0f}},
7270 point =
7272 sizeof(D3DLIGHT2),
7273 D3DLIGHT_POINT,
7274 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
7275 {{0.0f}, {0.0f}, {0.0f}},
7276 {{0.0f}, {0.0f}, {0.0f}},
7277 100.0f,
7278 0.0f,
7279 0.0f, 0.0f, 1.0f,
7281 spot =
7283 sizeof(D3DLIGHT2),
7284 D3DLIGHT_SPOT,
7285 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
7286 {{0.0f}, {0.0f}, {0.0f}},
7287 {{0.0f}, {0.0f}, {1.0f}},
7288 100.0f,
7289 1.0f,
7290 0.0f, 0.0f, 1.0f,
7291 M_PI / 12.0f, M_PI / 3.0f
7293 parallelpoint =
7295 sizeof(D3DLIGHT2),
7296 D3DLIGHT_PARALLELPOINT,
7297 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
7298 {{0.5f}, {0.0f}, {-1.0f}},
7299 {{0.0f}, {0.0f}, {0.0f}},
7301 point_side =
7303 sizeof(D3DLIGHT2),
7304 D3DLIGHT_POINT,
7305 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
7306 {{-1.1f}, {0.0f}, {1.1f}},
7307 {{0.0f}, {0.0f}, {0.0f}},
7308 100.0f,
7309 0.0f,
7310 1.0f, 0.0f, 0.0f,
7312 point_far =
7314 sizeof(D3DLIGHT2),
7315 D3DLIGHT_POINT,
7316 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
7317 {{0.0f}, {0.0f}, {0.1f}},
7318 {{0.0f}, {0.0f}, {0.0f}},
7319 1.0f,
7320 0.0f,
7321 1.0f, 0.0f, 0.0f,
7323 static const struct expected_color
7325 unsigned int x, y;
7326 D3DCOLOR color;
7328 expected_directional_local[] =
7330 {160, 120, 0x003c3c3c},
7331 {320, 120, 0x00717171},
7332 {480, 120, 0x003c3c3c},
7333 {160, 240, 0x00717171},
7334 {320, 240, 0x00ffffff},
7335 {480, 240, 0x00717171},
7336 {160, 360, 0x003c3c3c},
7337 {320, 360, 0x00717171},
7338 {480, 360, 0x003c3c3c},
7340 expected_point_local[] =
7342 {160, 120, 0x00000000},
7343 {320, 120, 0x00090909},
7344 {480, 120, 0x00000000},
7345 {160, 240, 0x00090909},
7346 {320, 240, 0x00fafafa},
7347 {480, 240, 0x00090909},
7348 {160, 360, 0x00000000},
7349 {320, 360, 0x00090909},
7350 {480, 360, 0x00000000},
7352 expected_spot_local[] =
7354 {160, 120, 0x00000000},
7355 {320, 120, 0x00020202},
7356 {480, 120, 0x00000000},
7357 {160, 240, 0x00020202},
7358 {320, 240, 0x00fafafa},
7359 {480, 240, 0x00020202},
7360 {160, 360, 0x00000000},
7361 {320, 360, 0x00020202},
7362 {480, 360, 0x00000000},
7364 expected_parallelpoint[] =
7366 {160, 120, 0x00050505},
7367 {320, 120, 0x002c2c2c},
7368 {480, 120, 0x006e6e6e},
7369 {160, 240, 0x00090909},
7370 {320, 240, 0x00717171},
7371 {480, 240, 0x00ffffff},
7372 {160, 360, 0x00050505},
7373 {320, 360, 0x002c2c2c},
7374 {480, 360, 0x006e6e6e},
7376 expected_point_far[] =
7378 {160, 120, 0x00000000},
7379 {320, 120, 0x00000000},
7380 {480, 120, 0x00000000},
7381 {160, 240, 0x00000000},
7382 {320, 240, 0x00ffffff},
7383 {480, 240, 0x00000000},
7384 {160, 360, 0x00000000},
7385 {320, 360, 0x00000000},
7386 {480, 360, 0x00000000},
7388 expected_zero[] =
7390 {160, 120, 0x00000000},
7391 {320, 120, 0x00000000},
7392 {480, 120, 0x00000000},
7393 {160, 240, 0x00000000},
7394 {320, 240, 0x00000000},
7395 {480, 240, 0x00000000},
7396 {160, 360, 0x00000000},
7397 {320, 360, 0x00000000},
7398 {480, 360, 0x00000000},
7400 static const struct
7402 D3DLIGHT2 *light;
7403 float specular_power;
7404 const struct expected_color *expected;
7405 unsigned int expected_count;
7407 tests[] =
7409 {&directional, 30.0f, expected_directional_local, ARRAY_SIZE(expected_directional_local)},
7410 {&point, 30.0f, expected_point_local, ARRAY_SIZE(expected_point_local)},
7411 {&spot, 30.0f, expected_spot_local, ARRAY_SIZE(expected_spot_local)},
7412 {&parallelpoint, 30.0f, expected_parallelpoint, ARRAY_SIZE(expected_parallelpoint)},
7413 {&point_side, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
7414 {&point_far, 1.0f, expected_point_far, ARRAY_SIZE(expected_point_far)},
7415 {&directional, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
7416 {&point, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
7417 {&spot, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
7418 {&parallelpoint, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
7419 {&point_far, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
7421 IDirect3D2 *d3d;
7422 IDirect3DDevice2 *device;
7423 IDirectDraw2 *ddraw;
7424 IDirectDrawSurface *rt;
7425 IDirect3DViewport2 *viewport;
7426 IDirect3DMaterial2 *material, *background_material;
7427 IDirect3DLight *light;
7428 D3DMATERIALHANDLE mat_handle;
7429 D3DCOLOR color;
7430 ULONG refcount;
7431 HWND window;
7432 HRESULT hr;
7433 unsigned int i, j, x, y;
7434 D3DVERTEX *quad;
7435 WORD *indices;
7437 window = create_window();
7438 ddraw = create_ddraw();
7439 ok(!!ddraw, "Failed to create a ddraw object.\n");
7440 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
7442 skip("Failed to create a 3D device, skipping test.\n");
7443 DestroyWindow(window);
7444 return;
7447 quad = HeapAlloc(GetProcessHeap(), 0, vertices_side * vertices_side * sizeof(*quad));
7448 indices = HeapAlloc(GetProcessHeap(), 0, indices_count * sizeof(*indices));
7449 for (i = 0, y = 0; y < vertices_side; ++y)
7451 for (x = 0; x < vertices_side; ++x)
7453 U1(quad[i]).x = x * 2.0f / (vertices_side - 1) - 1.0f;
7454 U2(quad[i]).y = y * 2.0f / (vertices_side - 1) - 1.0f;
7455 U3(quad[i]).z = 1.0f;
7456 U4(quad[i]).nx = 0.0f;
7457 U5(quad[i]).ny = 0.0f;
7458 U6(quad[i]).nz = -1.0f;
7459 U7(quad[i]).tu = 0.0f;
7460 U8(quad[i++]).tv = 0.0f;
7463 for (i = 0, y = 0; y < (vertices_side - 1); ++y)
7465 for (x = 0; x < (vertices_side - 1); ++x)
7467 indices[i++] = y * vertices_side + x + 1;
7468 indices[i++] = y * vertices_side + x;
7469 indices[i++] = (y + 1) * vertices_side + x;
7470 indices[i++] = y * vertices_side + x + 1;
7471 indices[i++] = (y + 1) * vertices_side + x;
7472 indices[i++] = (y + 1) * vertices_side + x + 1;
7476 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
7477 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
7479 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
7480 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
7482 viewport = create_viewport(device, 0, 0, 640, 480);
7483 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
7484 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
7486 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
7487 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
7488 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
7489 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
7490 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
7491 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
7492 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
7493 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
7494 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
7495 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
7497 background_material = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
7498 viewport_set_background(device, viewport, background_material);
7500 hr = IDirect3D2_CreateLight(d3d, &light, NULL);
7501 ok(SUCCEEDED(hr), "Failed to create a light object, hr %#x.\n", hr);
7502 hr = IDirect3DViewport2_AddLight(viewport, light);
7503 ok(SUCCEEDED(hr), "Failed to add a light to the viewport, hr %#x.\n", hr);
7505 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
7506 ok(SUCCEEDED(hr), "Failed to enable specular lighting, hr %#x.\n", hr);
7508 for (i = 0; i < ARRAY_SIZE(tests); ++i)
7510 tests[i].light->dwFlags = D3DLIGHT_ACTIVE;
7511 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)tests[i].light);
7512 ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
7514 material = create_specular_material(device, 1.0f, 1.0f, 1.0f, 1.0f, tests[i].specular_power);
7515 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
7516 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
7517 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
7518 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
7520 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7521 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
7523 hr = IDirect3DDevice2_BeginScene(device);
7524 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
7526 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX,
7527 quad, vertices_side * vertices_side, indices, indices_count, 0);
7528 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7530 hr = IDirect3DDevice2_EndScene(device);
7531 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7533 for (j = 0; j < tests[i].expected_count; ++j)
7535 color = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
7536 ok(compare_color(color, tests[i].expected[j].color, 1),
7537 "Expected color 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
7538 tests[i].expected[j].color, tests[i].expected[j].x,
7539 tests[i].expected[j].y, color, i);
7542 destroy_material(material);
7545 hr = IDirect3DViewport2_DeleteLight(viewport, light);
7546 ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#x.\n", hr);
7547 IDirect3DLight_Release(light);
7548 destroy_material(background_material);
7549 destroy_viewport(device, viewport);
7550 IDirectDrawSurface2_Release(rt);
7551 refcount = IDirect3DDevice2_Release(device);
7552 ok(!refcount, "Device has %u references left.\n", refcount);
7553 IDirect3D2_Release(d3d);
7554 refcount = IDirectDraw2_Release(ddraw);
7555 ok(!refcount, "Ddraw object has %u references left.\n", refcount);
7556 DestroyWindow(window);
7557 HeapFree(GetProcessHeap(), 0, indices);
7558 HeapFree(GetProcessHeap(), 0, quad);
7561 static void test_palette_gdi(void)
7563 IDirectDrawSurface *surface, *primary;
7564 DDSURFACEDESC surface_desc;
7565 IDirectDraw2 *ddraw;
7566 IDirectDrawPalette *palette, *palette2;
7567 ULONG refcount;
7568 HWND window;
7569 HRESULT hr;
7570 PALETTEENTRY palette_entries[256];
7571 UINT i;
7572 HDC dc;
7573 DDBLTFX fx;
7574 RECT r;
7575 COLORREF color;
7576 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
7577 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
7578 * not the point of this test. */
7579 static const RGBQUAD expected1[] =
7581 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
7582 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
7584 static const RGBQUAD expected2[] =
7586 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
7587 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
7589 static const RGBQUAD expected3[] =
7591 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
7592 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
7594 HPALETTE ddraw_palette_handle;
7595 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
7596 RGBQUAD rgbquad[255];
7597 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
7599 window = create_window();
7600 ddraw = create_ddraw();
7601 ok(!!ddraw, "Failed to create a ddraw object.\n");
7602 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7603 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7605 memset(&surface_desc, 0, sizeof(surface_desc));
7606 surface_desc.dwSize = sizeof(surface_desc);
7607 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7608 surface_desc.dwWidth = 16;
7609 surface_desc.dwHeight = 16;
7610 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7611 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
7612 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7613 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
7614 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7615 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7617 /* Avoid colors from the Windows default palette. */
7618 memset(palette_entries, 0, sizeof(palette_entries));
7619 palette_entries[1].peRed = 0x01;
7620 palette_entries[2].peGreen = 0x02;
7621 palette_entries[3].peBlue = 0x03;
7622 palette_entries[4].peRed = 0x13;
7623 palette_entries[4].peGreen = 0x14;
7624 palette_entries[4].peBlue = 0x15;
7625 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7626 palette_entries, &palette, NULL);
7627 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7629 /* If there is no palette assigned and the display mode is not 8 bpp, some
7630 * drivers refuse to create a DC while others allow it. If a DC is created,
7631 * the DIB color table is uninitialized and contains random colors. No error
7632 * is generated when trying to read pixels and random garbage is returned.
7634 * The most likely explanation is that if the driver creates a DC, it (or
7635 * the higher-level runtime) uses GetSystemPaletteEntries to find the
7636 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
7637 * contains uninitialized garbage. See comments below for the P8 case. */
7639 hr = IDirectDrawSurface_SetPalette(surface, palette);
7640 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7641 hr = IDirectDrawSurface_GetDC(surface, &dc);
7642 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7643 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
7644 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
7645 "Got unexpected palette %p, expected %p.\n",
7646 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
7648 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
7649 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
7650 for (i = 0; i < ARRAY_SIZE(expected1); i++)
7652 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
7653 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7654 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7655 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
7657 for (; i < ARRAY_SIZE(rgbquad); i++)
7659 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7660 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7661 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7664 /* Update the palette while the DC is in use. This does not modify the DC. */
7665 palette_entries[4].peRed = 0x23;
7666 palette_entries[4].peGreen = 0x24;
7667 palette_entries[4].peBlue = 0x25;
7668 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
7669 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
7671 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
7672 ok(i == 1, "Expected count 1, got %u.\n", i);
7673 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
7674 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7675 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
7676 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
7678 /* Neither does re-setting the palette. */
7679 hr = IDirectDrawSurface_SetPalette(surface, NULL);
7680 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7681 hr = IDirectDrawSurface_SetPalette(surface, palette);
7682 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7684 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
7685 ok(i == 1, "Expected count 1, got %u.\n", i);
7686 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
7687 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7688 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
7689 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
7691 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
7692 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7694 /* Refresh the DC. This updates the palette. */
7695 hr = IDirectDrawSurface_GetDC(surface, &dc);
7696 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7697 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
7698 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
7699 for (i = 0; i < ARRAY_SIZE(expected2); i++)
7701 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
7702 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7703 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7704 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
7706 for (; i < ARRAY_SIZE(rgbquad); i++)
7708 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7709 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7710 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7712 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
7713 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7715 refcount = IDirectDrawSurface_Release(surface);
7716 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7718 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
7719 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7720 if (FAILED(IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
7722 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
7723 IDirectDrawPalette_Release(palette);
7724 IDirectDraw2_Release(ddraw);
7725 DestroyWindow(window);
7726 return;
7728 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
7730 memset(&surface_desc, 0, sizeof(surface_desc));
7731 surface_desc.dwSize = sizeof(surface_desc);
7732 surface_desc.dwFlags = DDSD_CAPS;
7733 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7734 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
7735 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7737 memset(&fx, 0, sizeof(fx));
7738 fx.dwSize = sizeof(fx);
7739 U5(fx).dwFillColor = 3;
7740 SetRect(&r, 0, 0, 319, 479);
7741 hr = IDirectDrawSurface_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7742 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
7743 SetRect(&r, 320, 0, 639, 479);
7744 U5(fx).dwFillColor = 4;
7745 hr = IDirectDrawSurface_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7746 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
7748 hr = IDirectDrawSurface_SetPalette(primary, palette);
7749 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7750 hr = IDirectDrawSurface_GetDC(primary, &dc);
7751 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7753 color = GetPixel(dc, 160, 240);
7754 ok(color == 0x00030000, "Clear index 3: Got unexpected color 0x%08x.\n", color);
7755 color = GetPixel(dc, 480, 240);
7756 ok(color == 0x00252423, "Clear index 4: Got unexpected color 0x%08x.\n", color);
7758 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
7759 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
7760 "Got unexpected palette %p, expected %p.\n",
7761 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
7762 SelectPalette(dc, ddraw_palette_handle, FALSE);
7764 /* The primary uses the system palette. In exclusive mode, the system palette matches
7765 * the ddraw palette attached to the primary, so the result is what you would expect
7766 * from a regular surface. Tests for the interaction between the ddraw palette and
7767 * the system palette are not included pending an application that depends on this.
7768 * The relation between those causes problems on Windows Vista and newer for games
7769 * like Age of Empires or StarCraft. Don't emulate it without a real need. */
7770 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
7771 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
7772 for (i = 0; i < ARRAY_SIZE(expected2); i++)
7774 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
7775 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7776 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7777 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
7779 for (; i < ARRAY_SIZE(rgbquad); i++)
7781 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7782 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7783 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7785 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
7786 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7788 memset(&surface_desc, 0, sizeof(surface_desc));
7789 surface_desc.dwSize = sizeof(surface_desc);
7790 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7791 surface_desc.dwWidth = 16;
7792 surface_desc.dwHeight = 16;
7793 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7794 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7795 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7797 /* Here the offscreen surface appears to use the primary's palette,
7798 * but in all likelihood it is actually the system palette. */
7799 hr = IDirectDrawSurface_GetDC(surface, &dc);
7800 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7801 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
7802 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
7803 for (i = 0; i < ARRAY_SIZE(expected2); i++)
7805 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
7806 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7807 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7808 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
7810 for (; i < ARRAY_SIZE(rgbquad); i++)
7812 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7813 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7814 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7816 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
7817 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7819 /* On real hardware a change to the primary surface's palette applies immediately,
7820 * even on device contexts from offscreen surfaces that do not have their own
7821 * palette. On the testbot VMs this is not the case. Don't test this until we
7822 * know of an application that depends on this. */
7824 memset(palette_entries, 0, sizeof(palette_entries));
7825 palette_entries[1].peBlue = 0x40;
7826 palette_entries[2].peRed = 0x40;
7827 palette_entries[3].peGreen = 0x40;
7828 palette_entries[4].peRed = 0x12;
7829 palette_entries[4].peGreen = 0x34;
7830 palette_entries[4].peBlue = 0x56;
7831 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7832 palette_entries, &palette2, NULL);
7833 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7834 hr = IDirectDrawSurface_SetPalette(surface, palette2);
7835 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7837 /* A palette assigned to the offscreen surface overrides the primary / system
7838 * palette. */
7839 hr = IDirectDrawSurface_GetDC(surface, &dc);
7840 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7841 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
7842 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
7843 for (i = 0; i < ARRAY_SIZE(expected3); i++)
7845 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
7846 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7847 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7848 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
7850 for (; i < ARRAY_SIZE(rgbquad); i++)
7852 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7853 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7854 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7856 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
7857 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7859 refcount = IDirectDrawSurface_Release(surface);
7860 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7862 /* The Windows 8 testbot keeps extra references to the primary and
7863 * backbuffer while in 8 bpp mode. */
7864 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
7865 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
7867 refcount = IDirectDrawSurface_Release(primary);
7868 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7869 refcount = IDirectDrawPalette_Release(palette2);
7870 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7871 refcount = IDirectDrawPalette_Release(palette);
7872 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7873 refcount = IDirectDraw2_Release(ddraw);
7874 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7875 DestroyWindow(window);
7878 static void test_palette_alpha(void)
7880 IDirectDrawSurface *surface1;
7881 IDirectDrawSurface2 *surface;
7882 DDSURFACEDESC surface_desc;
7883 IDirectDraw2 *ddraw;
7884 IDirectDrawPalette *palette;
7885 ULONG refcount;
7886 HWND window;
7887 HRESULT hr;
7888 PALETTEENTRY palette_entries[256];
7889 unsigned int i;
7890 static const struct
7892 DWORD caps, flags;
7893 BOOL attach_allowed;
7894 const char *name;
7896 test_data[] =
7898 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
7899 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
7900 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
7903 window = create_window();
7904 ddraw = create_ddraw();
7905 ok(!!ddraw, "Failed to create a ddraw object.\n");
7906 if (FAILED(IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
7908 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
7909 IDirectDraw2_Release(ddraw);
7910 DestroyWindow(window);
7911 return;
7913 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7914 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7916 memset(palette_entries, 0, sizeof(palette_entries));
7917 palette_entries[1].peFlags = 0x42;
7918 palette_entries[2].peFlags = 0xff;
7919 palette_entries[3].peFlags = 0x80;
7920 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
7921 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7923 memset(palette_entries, 0x66, sizeof(palette_entries));
7924 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
7925 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
7926 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7927 palette_entries[0].peFlags);
7928 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7929 palette_entries[1].peFlags);
7930 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
7931 palette_entries[2].peFlags);
7932 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
7933 palette_entries[3].peFlags);
7935 IDirectDrawPalette_Release(palette);
7937 memset(palette_entries, 0, sizeof(palette_entries));
7938 palette_entries[1].peFlags = 0x42;
7939 palette_entries[1].peRed = 0xff;
7940 palette_entries[2].peFlags = 0xff;
7941 palette_entries[3].peFlags = 0x80;
7942 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
7943 palette_entries, &palette, NULL);
7944 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7946 memset(palette_entries, 0x66, sizeof(palette_entries));
7947 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
7948 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
7949 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7950 palette_entries[0].peFlags);
7951 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7952 palette_entries[1].peFlags);
7953 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
7954 palette_entries[2].peFlags);
7955 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
7956 palette_entries[3].peFlags);
7958 for (i = 0; i < ARRAY_SIZE(test_data); i++)
7960 memset(&surface_desc, 0, sizeof(surface_desc));
7961 surface_desc.dwSize = sizeof(surface_desc);
7962 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
7963 surface_desc.dwWidth = 128;
7964 surface_desc.dwHeight = 128;
7965 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
7966 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7967 ok(SUCCEEDED(hr), "Failed to create %s surface, hr %#x.\n", test_data[i].name, hr);
7968 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
7969 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface2 interface, hr %#x.\n", hr);
7970 IDirectDrawSurface_Release(surface1);
7972 hr = IDirectDrawSurface2_SetPalette(surface, palette);
7973 if (test_data[i].attach_allowed)
7974 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#x.\n", test_data[i].name, hr);
7975 else
7976 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x, %s surface.\n", hr, test_data[i].name);
7978 if (SUCCEEDED(hr))
7980 HDC dc;
7981 RGBQUAD rgbquad;
7982 UINT retval;
7984 hr = IDirectDrawSurface2_GetDC(surface, &dc);
7985 ok(SUCCEEDED(hr) || broken(hr == DDERR_CANTCREATEDC) /* Win2k testbot */,
7986 "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
7987 if (SUCCEEDED(hr))
7989 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
7990 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
7991 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
7992 rgbquad.rgbRed, test_data[i].name);
7993 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
7994 rgbquad.rgbGreen, test_data[i].name);
7995 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
7996 rgbquad.rgbBlue, test_data[i].name);
7997 ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
7998 rgbquad.rgbReserved, test_data[i].name);
7999 hr = IDirectDrawSurface2_ReleaseDC(surface, dc);
8000 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8003 IDirectDrawSurface2_Release(surface);
8006 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
8007 memset(&surface_desc, 0, sizeof(surface_desc));
8008 surface_desc.dwSize = sizeof(surface_desc);
8009 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8010 surface_desc.dwWidth = 128;
8011 surface_desc.dwHeight = 128;
8012 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8013 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
8014 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
8015 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
8016 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8017 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8018 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
8019 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
8020 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8021 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
8022 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface2 interface, hr %#x.\n", hr);
8023 IDirectDrawSurface_Release(surface1);
8025 hr = IDirectDrawSurface2_SetPalette(surface, palette);
8026 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
8027 IDirectDrawSurface2_Release(surface);
8029 /* The Windows 8 testbot keeps extra references to the primary
8030 * while in 8 bpp mode. */
8031 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
8032 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
8034 refcount = IDirectDrawPalette_Release(palette);
8035 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8036 refcount = IDirectDraw2_Release(ddraw);
8037 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8038 DestroyWindow(window);
8041 static void test_lost_device(void)
8043 IDirectDrawSurface *surface;
8044 DDSURFACEDESC surface_desc;
8045 HWND window1, window2;
8046 IDirectDraw2 *ddraw;
8047 ULONG refcount;
8048 HRESULT hr;
8049 BOOL ret;
8051 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8052 0, 0, 640, 480, 0, 0, 0, 0);
8053 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8054 0, 0, 640, 480, 0, 0, 0, 0);
8055 ddraw = create_ddraw();
8056 ok(!!ddraw, "Failed to create a ddraw object.\n");
8057 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8058 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8060 memset(&surface_desc, 0, sizeof(surface_desc));
8061 surface_desc.dwSize = sizeof(surface_desc);
8062 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8063 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8064 surface_desc.dwBackBufferCount = 1;
8065 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8066 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8068 hr = IDirectDrawSurface_IsLost(surface);
8069 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8070 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8071 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8073 ret = SetForegroundWindow(GetDesktopWindow());
8074 ok(ret, "Failed to set foreground window.\n");
8075 hr = IDirectDrawSurface_IsLost(surface);
8076 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8077 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8078 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8080 ret = SetForegroundWindow(window1);
8081 ok(ret, "Failed to set foreground window.\n");
8082 hr = IDirectDrawSurface_IsLost(surface);
8083 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8084 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8085 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8087 hr = restore_surfaces(ddraw);
8088 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8089 hr = IDirectDrawSurface_IsLost(surface);
8090 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8091 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8092 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8094 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
8095 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8096 hr = IDirectDrawSurface_IsLost(surface);
8097 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8098 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8099 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8101 /* Trying to restore the primary will crash, probably because flippable
8102 * surfaces can't exist in DDSCL_NORMAL. */
8103 IDirectDrawSurface_Release(surface);
8104 memset(&surface_desc, 0, sizeof(surface_desc));
8105 surface_desc.dwSize = sizeof(surface_desc);
8106 surface_desc.dwFlags = DDSD_CAPS;
8107 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8108 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8109 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8111 hr = IDirectDrawSurface_IsLost(surface);
8112 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8114 ret = SetForegroundWindow(GetDesktopWindow());
8115 ok(ret, "Failed to set foreground window.\n");
8116 hr = IDirectDrawSurface_IsLost(surface);
8117 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8119 ret = SetForegroundWindow(window1);
8120 ok(ret, "Failed to set foreground window.\n");
8121 hr = IDirectDrawSurface_IsLost(surface);
8122 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8124 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8125 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8126 hr = IDirectDrawSurface_IsLost(surface);
8127 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8129 hr = restore_surfaces(ddraw);
8130 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8131 hr = IDirectDrawSurface_IsLost(surface);
8132 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8134 IDirectDrawSurface_Release(surface);
8135 memset(&surface_desc, 0, sizeof(surface_desc));
8136 surface_desc.dwSize = sizeof(surface_desc);
8137 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8138 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8139 surface_desc.dwBackBufferCount = 1;
8140 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8141 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8143 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8144 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8145 hr = IDirectDrawSurface_IsLost(surface);
8146 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8147 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8148 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8150 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
8151 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8152 hr = IDirectDrawSurface_IsLost(surface);
8153 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8154 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8155 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8157 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
8158 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8159 hr = IDirectDrawSurface_IsLost(surface);
8160 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8161 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8162 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8164 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
8165 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8166 hr = IDirectDrawSurface_IsLost(surface);
8167 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8168 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8169 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8171 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
8172 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8173 hr = IDirectDrawSurface_IsLost(surface);
8174 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8175 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8176 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8178 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8179 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8180 hr = IDirectDrawSurface_IsLost(surface);
8181 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8182 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8183 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8185 IDirectDrawSurface_Release(surface);
8186 refcount = IDirectDraw2_Release(ddraw);
8187 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8188 DestroyWindow(window2);
8189 DestroyWindow(window1);
8192 static void test_surface_desc_lock(void)
8194 IDirectDrawSurface *surface;
8195 DDSURFACEDESC surface_desc;
8196 IDirectDraw2 *ddraw;
8197 ULONG refcount;
8198 HWND window;
8199 HRESULT hr;
8201 window = create_window();
8202 ddraw = create_ddraw();
8203 ok(!!ddraw, "Failed to create a ddraw object.\n");
8204 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8205 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8207 memset(&surface_desc, 0, sizeof(surface_desc));
8208 surface_desc.dwSize = sizeof(surface_desc);
8209 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8210 surface_desc.dwWidth = 16;
8211 surface_desc.dwHeight = 16;
8212 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8213 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8214 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8216 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8217 surface_desc.dwSize = sizeof(surface_desc);
8218 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
8219 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8220 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8222 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8223 surface_desc.dwSize = sizeof(surface_desc);
8224 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, 0, NULL);
8225 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8226 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8227 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8228 surface_desc.dwSize = sizeof(surface_desc);
8229 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
8230 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8231 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8232 hr = IDirectDrawSurface_Unlock(surface, NULL);
8233 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8235 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8236 surface_desc.dwSize = sizeof(surface_desc);
8237 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
8238 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8239 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8241 IDirectDrawSurface_Release(surface);
8242 refcount = IDirectDraw2_Release(ddraw);
8243 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8244 DestroyWindow(window);
8247 static void test_texturemapblend(void)
8249 HRESULT hr;
8250 DDSURFACEDESC ddsd;
8251 DDBLTFX fx;
8252 static RECT rect = {0, 0, 64, 128};
8253 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
8254 DDCOLORKEY ckey;
8255 IDirectDrawSurface *surface, *rt;
8256 IDirect3DTexture2 *texture;
8257 D3DTEXTUREHANDLE texture_handle;
8258 HWND window;
8259 IDirectDraw2 *ddraw;
8260 IDirect3DDevice2 *device;
8261 IDirect3DMaterial2 *material;
8262 IDirect3DViewport2 *viewport;
8263 ULONG ref;
8264 D3DCOLOR color;
8266 static D3DTLVERTEX test1_quads[] =
8268 {{0.0f}, {0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {0.0f}, {0.0f}},
8269 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {0.0f}, {1.0f}},
8270 {{640.0f}, {0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {1.0f}, {0.0f}},
8271 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {1.0f}, {1.0f}},
8272 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {0.0f}, {0.0f}},
8273 {{0.0f}, {480.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {0.0f}, {1.0f}},
8274 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {1.0f}, {0.0f}},
8275 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {1.0f}, {1.0f}},
8277 test2_quads[] =
8279 {{0.0f}, {0.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {0.0f}, {0.0f}},
8280 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {0.0f}, {1.0f}},
8281 {{640.0f}, {0.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {1.0f}, {0.0f}},
8282 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {1.0f}, {1.0f}},
8283 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {0.0f}, {0.0f}},
8284 {{0.0f}, {480.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {0.0f}, {1.0f}},
8285 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {1.0f}, {0.0f}},
8286 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {1.0f}, {1.0f}},
8289 window = create_window();
8290 ddraw = create_ddraw();
8291 ok(!!ddraw, "Failed to create a ddraw object.\n");
8292 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
8294 skip("Failed to create a 3D device, skipping test.\n");
8295 DestroyWindow(window);
8296 IDirectDraw2_Release(ddraw);
8297 return;
8300 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
8301 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8303 material = create_diffuse_material(device, 0.0f, 0.0f, 0.0f, 1.0f);
8304 viewport = create_viewport(device, 0, 0, 640, 480);
8305 viewport_set_background(device, viewport, material);
8306 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
8307 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
8309 /* Test alpha with DDPF_ALPHAPIXELS texture - should be taken from texture alpha channel.
8311 * The vertex alpha is completely ignored in this case, so case 1 and 2 combined are not
8312 * a D3DTOP_MODULATE with texture alpha = 0xff in case 2 (no alpha in texture). */
8313 memset(&ddsd, 0, sizeof(ddsd));
8314 ddsd.dwSize = sizeof(ddsd);
8315 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
8316 ddsd.dwHeight = 128;
8317 ddsd.dwWidth = 128;
8318 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
8319 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
8320 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
8321 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
8322 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8323 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8324 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
8325 U5(ddsd.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
8326 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
8327 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8329 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
8330 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
8331 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
8332 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
8333 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
8334 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8336 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8337 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
8339 memset(&fx, 0, sizeof(fx));
8340 fx.dwSize = sizeof(fx);
8341 U5(fx).dwFillColor = 0xff0000ff;
8342 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8343 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
8344 U5(fx).dwFillColor = 0x800000ff;
8345 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8346 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
8348 /* Note that the ddraw1 version of this test runs tests 1-3 with D3DRENDERSTATE_COLORKEYENABLE
8349 * enabled, whereas this version only runs test 4 with color keying on. Because no color key
8350 * is set on the texture this should not result in different behavior. */
8351 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
8352 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8353 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
8354 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8355 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
8356 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8357 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
8358 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8359 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
8360 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8361 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
8362 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8364 hr = IDirect3DDevice2_BeginScene(device);
8365 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8366 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[0], 4, 0);
8367 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8368 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[4], 4, 0);
8369 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8370 hr = IDirect3DDevice2_EndScene(device);
8371 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8373 color = get_surface_color(rt, 5, 5);
8374 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
8375 color = get_surface_color(rt, 400, 5);
8376 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
8377 color = get_surface_color(rt, 5, 245);
8378 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
8379 color = get_surface_color(rt, 400, 245);
8380 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
8382 IDirect3DTexture2_Release(texture);
8383 ref = IDirectDrawSurface_Release(surface);
8384 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
8386 /* Test alpha with texture that has no alpha channel - alpha should be taken from diffuse vertex color. */
8387 memset(&ddsd, 0, sizeof(ddsd));
8388 ddsd.dwSize = sizeof(ddsd);
8389 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
8390 ddsd.dwHeight = 128;
8391 ddsd.dwWidth = 128;
8392 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
8393 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
8394 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
8395 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
8396 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8397 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8398 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
8400 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
8401 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8403 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
8404 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
8405 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
8406 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
8407 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
8408 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8410 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8411 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
8413 U5(fx).dwFillColor = 0xff0000ff;
8414 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8415 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
8416 U5(fx).dwFillColor = 0x800000ff;
8417 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8418 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
8420 hr = IDirect3DDevice2_BeginScene(device);
8421 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8422 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[0], 4, 0);
8423 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8424 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[4], 4, 0);
8425 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8426 hr = IDirect3DDevice2_EndScene(device);
8427 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8429 color = get_surface_color(rt, 5, 5);
8430 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
8431 color = get_surface_color(rt, 400, 5);
8432 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
8433 color = get_surface_color(rt, 5, 245);
8434 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
8435 color = get_surface_color(rt, 400, 245);
8436 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
8438 IDirect3DTexture2_Release(texture);
8439 ref = IDirectDrawSurface_Release(surface);
8440 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
8442 /* Test RGB - should multiply color components from diffuse vertex color and texture. */
8443 memset(&ddsd, 0, sizeof(ddsd));
8444 ddsd.dwSize = sizeof(ddsd);
8445 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
8446 ddsd.dwHeight = 128;
8447 ddsd.dwWidth = 128;
8448 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
8449 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
8450 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
8451 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
8452 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8453 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8454 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
8455 U5(ddsd.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
8456 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
8457 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8459 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
8460 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
8461 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
8462 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
8463 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
8464 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8466 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8467 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
8469 U5(fx).dwFillColor = 0x00ffffff;
8470 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8471 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
8472 U5(fx).dwFillColor = 0x00ffff80;
8473 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8474 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
8476 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
8477 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8479 hr = IDirect3DDevice2_BeginScene(device);
8480 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8481 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test2_quads[0], 4, 0);
8482 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8483 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test2_quads[4], 4, 0);
8484 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8485 hr = IDirect3DDevice2_EndScene(device);
8486 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8488 color = get_surface_color(rt, 5, 5);
8489 ok(compare_color(color, 0x00ff0040, 2), "Got unexpected color 0x%08x.\n", color);
8490 color = get_surface_color(rt, 400, 5);
8491 ok(compare_color(color, 0x00ff0080, 2), "Got unexpected color 0x%08x.\n", color);
8492 color = get_surface_color(rt, 5, 245);
8493 ok(compare_color(color, 0x00800080, 2), "Got unexpected color 0x%08x.\n", color);
8494 color = get_surface_color(rt, 400, 245);
8495 ok(compare_color(color, 0x008000ff, 2), "Got unexpected color 0x%08x.\n", color);
8497 IDirect3DTexture2_Release(texture);
8498 ref = IDirectDrawSurface_Release(surface);
8499 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
8501 /* Test alpha again, now with color keyed texture (colorkey emulation in wine can interfere). */
8502 memset(&ddsd, 0, sizeof(ddsd));
8503 ddsd.dwSize = sizeof(ddsd);
8504 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
8505 ddsd.dwHeight = 128;
8506 ddsd.dwWidth = 128;
8507 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
8508 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
8509 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
8510 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 16;
8511 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xf800;
8512 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x07e0;
8513 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x001f;
8515 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
8516 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8518 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
8519 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
8520 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
8521 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
8522 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
8523 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8525 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8526 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
8528 U5(fx).dwFillColor = 0xf800;
8529 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8530 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
8531 U5(fx).dwFillColor = 0x001f;
8532 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8533 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
8535 ckey.dwColorSpaceLowValue = 0x001f;
8536 ckey.dwColorSpaceHighValue = 0x001f;
8537 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
8538 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
8540 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
8541 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8542 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
8543 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8545 hr = IDirect3DDevice2_BeginScene(device);
8546 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8547 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[0], 4, 0);
8548 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8549 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[4], 4, 0);
8550 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8551 hr = IDirect3DDevice2_EndScene(device);
8552 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8554 color = get_surface_color(rt, 5, 5);
8555 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
8556 color = get_surface_color(rt, 400, 5);
8557 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
8558 color = get_surface_color(rt, 5, 245);
8559 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
8560 color = get_surface_color(rt, 400, 245);
8561 ok(compare_color(color, 0x00800000, 2), "Got unexpected color 0x%08x.\n", color);
8563 IDirect3DTexture2_Release(texture);
8564 ref = IDirectDrawSurface_Release(surface);
8565 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
8567 destroy_viewport(device, viewport);
8568 ref = IDirect3DMaterial2_Release(material);
8569 ok(ref == 0, "Material not properly released, refcount %u.\n", ref);
8570 IDirectDrawSurface_Release(rt);
8571 IDirect3DDevice2_Release(device);
8572 ref = IDirectDraw2_Release(ddraw);
8573 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
8574 DestroyWindow(window);
8577 static void test_viewport_clear_rect(void)
8579 HRESULT hr;
8580 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
8581 static D3DRECT clear_rect2 = {{90}, {90}, {110}, {110}};
8582 IDirectDrawSurface *rt;
8583 HWND window;
8584 IDirectDraw2 *ddraw;
8585 IDirect3DDevice2 *device;
8586 IDirect3DMaterial2 *red, *green;
8587 IDirect3DViewport2 *viewport, *viewport2;
8588 ULONG ref;
8589 D3DCOLOR color;
8591 window = create_window();
8592 ddraw = create_ddraw();
8593 ok(!!ddraw, "Failed to create a ddraw object.\n");
8594 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
8596 skip("Failed to create a 3D device, skipping test.\n");
8597 DestroyWindow(window);
8598 IDirectDraw2_Release(ddraw);
8599 return;
8602 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
8603 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8605 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
8606 viewport = create_viewport(device, 0, 0, 640, 480);
8607 viewport_set_background(device, viewport, red);
8608 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8609 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8611 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
8612 viewport2 = create_viewport(device, 100, 100, 20, 20);
8613 viewport_set_background(device, viewport2, green);
8614 hr = IDirect3DViewport2_Clear(viewport2, 1, &clear_rect2, D3DCLEAR_TARGET);
8615 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8617 color = get_surface_color(rt, 85, 85); /* Outside both. */
8618 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
8619 color = get_surface_color(rt, 95, 95); /* Outside vp, inside rect. */
8620 /* AMD GPUs ignore the viewport dimensions and only care about the rectangle. */
8621 ok(compare_color(color, 0x00ff0000, 1) || broken(compare_color(color, 0x0000ff00, 1)),
8622 "Got unexpected color 0x%08x.\n", color);
8623 color = get_surface_color(rt, 105, 105); /* Inside both. */
8624 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
8625 color = get_surface_color(rt, 115, 115); /* Inside vp, outside rect. */
8626 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
8627 color = get_surface_color(rt, 125, 125); /* Outside both. */
8628 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
8630 destroy_viewport(device, viewport2);
8631 destroy_material(green);
8632 destroy_viewport(device, viewport);
8633 destroy_material(red);
8634 IDirectDrawSurface_Release(rt);
8635 IDirect3DDevice2_Release(device);
8636 ref = IDirectDraw2_Release(ddraw);
8637 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
8638 DestroyWindow(window);
8641 static void test_color_fill(void)
8643 HRESULT hr;
8644 IDirect3DDevice2 *device;
8645 IDirectDraw2 *ddraw;
8646 IDirectDrawSurface *surface, *surface2;
8647 DDSURFACEDESC surface_desc;
8648 ULONG refcount;
8649 BOOL is_warp;
8650 HWND window;
8651 unsigned int i;
8652 DDBLTFX fx;
8653 RECT rect = {5, 5, 7, 7};
8654 DWORD *color;
8655 DWORD num_fourcc_codes, *fourcc_codes;
8656 DDCAPS hal_caps;
8657 BOOL support_uyvy = FALSE, support_yuy2 = FALSE;
8658 static const struct
8660 DWORD caps;
8661 HRESULT colorfill_hr, depthfill_hr;
8662 BOOL rop_success;
8663 const char *name;
8664 DWORD result;
8665 BOOL check_result;
8666 DDPIXELFORMAT format;
8668 tests[] =
8671 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
8672 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
8674 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
8675 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
8679 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
8680 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
8682 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
8683 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
8687 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
8688 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
8690 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
8691 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
8695 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
8696 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
8698 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
8699 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
8703 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY,
8704 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0xdeadbeef, TRUE,
8705 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
8708 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
8709 * different afterwards. DX9+ GPUs set one of the two luminance values
8710 * in each block, but AMD and Nvidia GPUs disagree on which luminance
8711 * value they set. r200 (dx8) just sets the entire block to the clear
8712 * value. */
8713 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
8714 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
8716 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
8717 {0}, {0}, {0}, {0}, {0}
8721 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
8722 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
8724 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
8725 {0}, {0}, {0}, {0}, {0}
8729 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY,
8730 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
8732 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
8733 {0}, {0}, {0}, {0}, {0}
8737 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY,
8738 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
8740 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
8741 {0}, {0}, {0}, {0}, {0}
8745 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
8746 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
8748 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
8749 {0}, {0}, {0}, {0}, {0}
8753 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
8754 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
8756 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
8757 {0}, {0}, {0}, {0}, {0}
8761 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
8762 * surface works, presumably because it is handled by the runtime instead of
8763 * the driver. */
8764 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
8765 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
8767 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
8768 {8}, {0}, {0}, {0}, {0}
8772 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
8773 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
8775 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
8776 {8}, {0}, {0}, {0}, {0}
8780 static const struct
8782 DWORD rop;
8783 const char *name;
8784 HRESULT hr;
8786 rops[] =
8788 {SRCCOPY, "SRCCOPY", DD_OK},
8789 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
8790 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
8791 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
8792 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
8793 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
8794 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
8795 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
8796 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
8797 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
8798 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
8799 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
8800 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
8801 {BLACKNESS, "BLACKNESS", DD_OK},
8802 {WHITENESS, "WHITENESS", DD_OK},
8803 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
8806 window = create_window();
8807 ddraw = create_ddraw();
8808 ok(!!ddraw, "Failed to create a ddraw object.\n");
8809 is_warp = ddraw_is_warp(ddraw);
8810 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
8812 skip("Failed to create a 3D device, skipping test.\n");
8813 DestroyWindow(window);
8814 IDirectDraw2_Release(ddraw);
8815 return;
8818 hr = IDirectDraw2_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
8819 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
8820 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8821 num_fourcc_codes * sizeof(*fourcc_codes));
8822 if (!fourcc_codes)
8823 goto done;
8824 hr = IDirectDraw2_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
8825 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
8826 for (i = 0; i < num_fourcc_codes; i++)
8828 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
8829 support_yuy2 = TRUE;
8830 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
8831 support_uyvy = TRUE;
8833 HeapFree(GetProcessHeap(), 0, fourcc_codes);
8835 memset(&hal_caps, 0, sizeof(hal_caps));
8836 hal_caps.dwSize = sizeof(hal_caps);
8837 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
8838 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8840 if ((!support_yuy2 && !support_uyvy) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
8841 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
8843 for (i = 0; i < ARRAY_SIZE(tests); i++)
8845 DWORD expected_broken = tests[i].result;
8846 DWORD mask = 0xffffffffu;
8848 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
8849 memset(&fx, 0, sizeof(fx));
8850 fx.dwSize = sizeof(fx);
8851 U5(fx).dwFillColor = 0xdeadbeef;
8853 memset(&surface_desc, 0, sizeof(surface_desc));
8854 surface_desc.dwSize = sizeof(surface_desc);
8855 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8856 surface_desc.dwWidth = 64;
8857 surface_desc.dwHeight = 64;
8858 surface_desc.ddpfPixelFormat = tests[i].format;
8859 surface_desc.ddsCaps.dwCaps = tests[i].caps;
8861 if (tests[i].caps & DDSCAPS_TEXTURE)
8863 struct format_support_check check = {&tests[i].format, FALSE};
8864 hr = IDirect3DDevice2_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
8865 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
8866 if (!check.supported)
8867 continue;
8870 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !support_yuy2)
8871 continue;
8872 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !support_uyvy)
8873 continue;
8874 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
8875 continue;
8877 if (tests[i].caps & DDSCAPS_ZBUFFER)
8879 surface_desc.dwFlags &= ~DDSD_PIXELFORMAT;
8880 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
8881 U2(surface_desc).dwZBufferBitDepth = get_device_z_depth(device);
8882 mask >>= (32 - U2(surface_desc).dwZBufferBitDepth);
8883 /* Some drivers seem to convert depth values incorrectly or not at
8884 * all. Affects at least AMD PALM, 8.17.10.1247. */
8885 if (tests[i].caps & DDSCAPS_VIDEOMEMORY)
8887 DWORD expected;
8888 float f, g;
8890 expected = tests[i].result & mask;
8891 f = ceilf(log2f(expected + 1.0f));
8892 g = (f + 1.0f) / 2.0f;
8893 g -= (int)g;
8894 expected_broken = (expected / exp2f(f) - g) * 256;
8895 expected_broken *= 0x01010101;
8899 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8900 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, surface %s.\n", hr, tests[i].name);
8902 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8903 todo_wine_if (tests[i].format.dwFourCC)
8904 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
8905 hr, tests[i].colorfill_hr, tests[i].name);
8907 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8908 todo_wine_if (tests[i].format.dwFourCC)
8909 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
8910 hr, tests[i].colorfill_hr, tests[i].name);
8912 if (SUCCEEDED(hr) && tests[i].check_result)
8914 memset(&surface_desc, 0, sizeof(surface_desc));
8915 surface_desc.dwSize = sizeof(surface_desc);
8916 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
8917 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8918 color = surface_desc.lpSurface;
8919 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
8920 *color, tests[i].result, tests[i].name);
8921 hr = IDirectDrawSurface_Unlock(surface, NULL);
8922 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8925 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8926 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
8927 hr, tests[i].depthfill_hr, tests[i].name);
8928 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8929 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
8930 hr, tests[i].depthfill_hr, tests[i].name);
8932 if (SUCCEEDED(hr) && tests[i].check_result)
8934 memset(&surface_desc, 0, sizeof(surface_desc));
8935 surface_desc.dwSize = sizeof(surface_desc);
8936 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
8937 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8938 color = surface_desc.lpSurface;
8939 todo_wine_if(tests[i].caps & DDSCAPS_VIDEOMEMORY && U2(surface_desc).dwZBufferBitDepth != 16)
8940 ok((*color & mask) == (tests[i].result & mask) || broken((*color & mask) == (expected_broken & mask))
8941 || broken(is_warp && (*color & mask) == (~0u & mask)) /* Windows 8+ testbot. */,
8942 "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
8943 *color & mask, tests[i].result & mask, tests[i].name);
8944 hr = IDirectDrawSurface_Unlock(surface, NULL);
8945 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8948 U5(fx).dwFillColor = 0xdeadbeef;
8949 fx.dwROP = BLACKNESS;
8950 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
8951 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
8952 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
8953 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
8954 U5(fx).dwFillColor, tests[i].name);
8956 if (SUCCEEDED(hr) && tests[i].check_result)
8958 memset(&surface_desc, 0, sizeof(surface_desc));
8959 surface_desc.dwSize = sizeof(surface_desc);
8960 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
8961 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8962 color = surface_desc.lpSurface;
8963 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
8964 *color, tests[i].name);
8965 hr = IDirectDrawSurface_Unlock(surface, NULL);
8966 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8969 fx.dwROP = WHITENESS;
8970 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
8971 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
8972 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
8973 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
8974 U5(fx).dwFillColor, tests[i].name);
8976 if (SUCCEEDED(hr) && tests[i].check_result)
8978 memset(&surface_desc, 0, sizeof(surface_desc));
8979 surface_desc.dwSize = sizeof(surface_desc);
8980 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
8981 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8982 color = surface_desc.lpSurface;
8983 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
8984 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
8985 *color, tests[i].name);
8986 hr = IDirectDrawSurface_Unlock(surface, NULL);
8987 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8990 IDirectDrawSurface_Release(surface);
8993 memset(&fx, 0, sizeof(fx));
8994 fx.dwSize = sizeof(fx);
8995 U5(fx).dwFillColor = 0xdeadbeef;
8996 fx.dwROP = WHITENESS;
8998 memset(&surface_desc, 0, sizeof(surface_desc));
8999 surface_desc.dwSize = sizeof(surface_desc);
9000 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9001 surface_desc.dwWidth = 64;
9002 surface_desc.dwHeight = 64;
9003 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
9004 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
9005 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
9006 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9007 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9008 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
9009 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
9010 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9011 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9012 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
9013 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9015 /* No DDBLTFX. */
9016 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
9017 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9018 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
9019 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9021 /* Unused source rectangle. */
9022 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9023 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9024 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9025 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9027 /* Unused source surface. */
9028 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9029 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9030 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9031 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9032 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9033 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9034 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9035 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9037 /* Inverted destination or source rectangle. */
9038 SetRect(&rect, 5, 7, 7, 5);
9039 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9040 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9041 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9042 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9043 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9044 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9045 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9046 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9047 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9048 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9050 /* Negative rectangle. */
9051 SetRect(&rect, -1, -1, 5, 5);
9052 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9053 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9054 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9055 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9056 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9057 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9058 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9059 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9060 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9061 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9063 /* Out of bounds rectangle. */
9064 SetRect(&rect, 0, 0, 65, 65);
9065 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9066 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9067 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9068 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9070 /* Combine multiple flags. */
9071 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9072 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9073 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
9074 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9075 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
9076 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9078 for (i = 0; i < ARRAY_SIZE(rops); i++)
9080 fx.dwROP = rops[i].rop;
9081 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9082 ok(hr == rops[i].hr, "Got unexpected hr %#x for rop %s.\n", hr, rops[i].name);
9085 IDirectDrawSurface_Release(surface2);
9086 IDirectDrawSurface_Release(surface);
9088 memset(&surface_desc, 0, sizeof(surface_desc));
9089 surface_desc.dwSize = sizeof(surface_desc);
9090 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_ZBUFFERBITDEPTH;
9091 surface_desc.dwWidth = 64;
9092 surface_desc.dwHeight = 64;
9093 U2(surface_desc).dwZBufferBitDepth = get_device_z_depth(device);
9094 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
9095 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9096 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9097 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
9098 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9100 /* No DDBLTFX. */
9101 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
9102 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9104 /* Unused source rectangle. */
9105 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9106 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9108 /* Unused source surface. */
9109 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9110 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9111 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9112 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9114 /* Inverted destination or source rectangle. */
9115 SetRect(&rect, 5, 7, 7, 5);
9116 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9117 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9118 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9119 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9120 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9121 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9122 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9123 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9125 /* Negative rectangle. */
9126 SetRect(&rect, -1, -1, 5, 5);
9127 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9128 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9129 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9130 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9131 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9132 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9133 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9134 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9136 /* Out of bounds rectangle. */
9137 SetRect(&rect, 0, 0, 65, 65);
9138 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9139 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9141 /* Combine multiple flags. */
9142 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9143 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9145 IDirectDrawSurface_Release(surface2);
9146 IDirectDrawSurface_Release(surface);
9148 done:
9149 IDirect3DDevice2_Release(device);
9150 refcount = IDirectDraw2_Release(ddraw);
9151 ok(refcount == 0, "Ddraw object not properly released, refcount %u.\n", refcount);
9152 DestroyWindow(window);
9155 static void test_colorkey_precision(void)
9157 static D3DLVERTEX quad[] =
9159 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xff000000}, {0}, {0.0f}, {0.0f}},
9160 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff000000}, {0}, {0.0f}, {1.0f}},
9161 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff000000}, {0}, {1.0f}, {0.0f}},
9162 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xff000000}, {0}, {1.0f}, {1.0f}},
9164 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
9165 IDirect3DDevice2 *device;
9166 IDirectDraw2 *ddraw;
9167 IDirectDrawSurface *rt;
9168 IDirect3DViewport2 *viewport;
9169 HWND window;
9170 HRESULT hr;
9171 IDirectDrawSurface *src, *dst, *texture;
9172 D3DTEXTUREHANDLE handle;
9173 IDirect3DTexture2 *d3d_texture;
9174 IDirect3DMaterial2 *green;
9175 DDSURFACEDESC surface_desc, lock_desc;
9176 ULONG refcount;
9177 D3DCOLOR color;
9178 unsigned int t, c;
9179 DDCOLORKEY ckey;
9180 DDBLTFX fx;
9181 DWORD data[4] = {0}, color_mask;
9182 BOOL is_nvidia, is_warp;
9183 static const struct
9185 unsigned int max, shift, bpp, clear;
9186 const char *name;
9187 BOOL skip_nv;
9188 DDPIXELFORMAT fmt;
9190 tests[] =
9193 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8", FALSE,
9195 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
9196 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
9201 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel", FALSE,
9203 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
9204 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
9209 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel", FALSE,
9211 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
9212 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
9217 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4", TRUE,
9219 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9220 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
9225 window = create_window();
9226 ddraw = create_ddraw();
9227 ok(!!ddraw, "Failed to create a ddraw object.\n");
9228 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
9230 skip("Failed to create a 3D device, skipping test.\n");
9231 DestroyWindow(window);
9232 IDirectDraw2_Release(ddraw);
9233 return;
9235 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
9236 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9238 is_nvidia = ddraw_is_nvidia(ddraw);
9239 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
9240 * (color key doesn't match although the values are equal), and a false
9241 * positive when the color key is 0 and the texture contains the value 1.
9242 * I don't want to mark this broken unconditionally since this would
9243 * essentially disable the test on Windows. Also on random occasions
9244 * 254 == 255 and 255 != 255.*/
9245 is_warp = ddraw_is_warp(ddraw);
9247 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
9248 viewport = create_viewport(device, 0, 0, 640, 480);
9249 viewport_set_background(device, viewport, green);
9250 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
9251 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
9253 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
9254 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
9255 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
9256 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
9257 /* There's no way to ignore the texture color in d3d2, so multiply the texture color
9258 * with a black vertex color. */
9259 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATEALPHA);
9260 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9262 memset(&fx, 0, sizeof(fx));
9263 fx.dwSize = sizeof(fx);
9264 memset(&lock_desc, 0, sizeof(lock_desc));
9265 lock_desc.dwSize = sizeof(lock_desc);
9267 for (t = 0; t < ARRAY_SIZE(tests); ++t)
9269 if (is_nvidia && tests[t].skip_nv)
9271 win_skip("Skipping test %s on Nvidia Windows drivers.\n", tests[t].name);
9272 continue;
9275 memset(&surface_desc, 0, sizeof(surface_desc));
9276 surface_desc.dwSize = sizeof(surface_desc);
9277 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9278 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9279 surface_desc.dwWidth = 4;
9280 surface_desc.dwHeight = 1;
9281 surface_desc.ddpfPixelFormat = tests[t].fmt;
9282 /* Windows XP (at least with the r200 driver, other drivers untested) produces
9283 * garbage when doing color keyed texture->texture blits. */
9284 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src, NULL);
9285 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9286 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst, NULL);
9287 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9289 U5(fx).dwFillColor = tests[t].clear;
9290 /* On the w8 testbot (WARP driver) the blit result has different values in the
9291 * X channel. */
9292 color_mask = U2(tests[t].fmt).dwRBitMask
9293 | U3(tests[t].fmt).dwGBitMask
9294 | U4(tests[t].fmt).dwBBitMask;
9296 for (c = 0; c <= tests[t].max; ++c)
9298 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
9299 * texture after it has been set once... */
9300 surface_desc.dwFlags |= DDSD_CKSRCBLT;
9301 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9302 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
9303 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
9304 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &texture, NULL);
9305 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9307 hr = IDirectDrawSurface4_QueryInterface(texture, &IID_IDirect3DTexture2, (void **)&d3d_texture);
9308 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
9309 hr = IDirect3DTexture2_GetHandle(d3d_texture, device, &handle);
9310 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
9311 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, handle);
9312 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
9313 IDirect3DTexture2_Release(d3d_texture);
9315 hr = IDirectDrawSurface_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9316 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
9318 hr = IDirectDrawSurface_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
9319 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9320 switch (tests[t].bpp)
9322 case 4:
9323 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
9324 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
9325 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
9326 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
9327 break;
9329 case 2:
9330 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
9331 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
9332 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
9333 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
9334 break;
9336 hr = IDirectDrawSurface_Unlock(src, 0);
9337 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9338 hr = IDirectDrawSurface_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
9339 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
9341 ckey.dwColorSpaceLowValue = c << tests[t].shift;
9342 ckey.dwColorSpaceHighValue = c << tests[t].shift;
9343 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
9344 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
9346 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
9347 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
9349 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
9350 hr = IDirectDrawSurface_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
9351 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9352 switch (tests[t].bpp)
9354 case 4:
9355 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
9356 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
9357 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
9358 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
9359 break;
9361 case 2:
9362 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
9363 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
9364 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
9365 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
9366 break;
9368 hr = IDirectDrawSurface_Unlock(dst, 0);
9369 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9371 if (!c)
9373 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
9374 tests[t].clear, data[0], tests[t].name, c);
9376 if (data[3] == tests[t].clear)
9378 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
9379 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
9380 * even when a different surface is used. The blit itself doesn't draw anything,
9381 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
9382 * never be masked out by the key.
9384 * On Windows 10 the problem is worse, Blt just hangs. For this reason the ARGB4444
9385 * test is disabled entirely.
9387 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
9388 * terrible on WARP. */
9389 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
9390 IDirectDrawSurface_Release(texture);
9391 IDirectDrawSurface_Release(src);
9392 IDirectDrawSurface_Release(dst);
9393 goto done;
9396 else
9397 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
9398 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
9400 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
9401 tests[t].clear, data[1], tests[t].name, c);
9403 if (c == tests[t].max)
9404 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
9405 tests[t].clear, data[2], tests[t].name, c);
9406 else
9407 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
9408 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
9410 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9411 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9413 hr = IDirect3DDevice2_BeginScene(device);
9414 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9415 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, 4, 0);
9416 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9417 hr = IDirect3DDevice2_EndScene(device);
9418 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9420 color = get_surface_color(rt, 80, 240);
9421 if (!c)
9422 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
9423 "Got unexpected color 0x%08x, format %s, c=%u.\n",
9424 color, tests[t].name, c);
9425 else
9426 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
9427 "Got unexpected color 0x%08x, format %s, c=%u.\n",
9428 color, tests[t].name, c);
9430 color = get_surface_color(rt, 240, 240);
9431 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
9432 "Got unexpected color 0x%08x, format %s, c=%u.\n",
9433 color, tests[t].name, c);
9435 color = get_surface_color(rt, 400, 240);
9436 if (c == tests[t].max)
9437 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
9438 "Got unexpected color 0x%08x, format %s, c=%u.\n",
9439 color, tests[t].name, c);
9440 else
9441 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
9442 "Got unexpected color 0x%08x, format %s, c=%u.\n",
9443 color, tests[t].name, c);
9445 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
9446 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
9447 IDirectDrawSurface_Release(texture);
9449 IDirectDrawSurface_Release(src);
9450 IDirectDrawSurface_Release(dst);
9452 done:
9454 destroy_viewport(device, viewport);
9455 destroy_material(green);
9456 IDirectDrawSurface_Release(rt);
9457 IDirect3DDevice2_Release(device);
9458 refcount = IDirectDraw2_Release(ddraw);
9459 ok(refcount == 0, "Ddraw object not properly released, refcount %u.\n", refcount);
9460 DestroyWindow(window);
9463 static void test_range_colorkey(void)
9465 IDirectDraw2 *ddraw;
9466 HWND window;
9467 HRESULT hr;
9468 IDirectDrawSurface *surface;
9469 DDSURFACEDESC surface_desc;
9470 ULONG refcount;
9471 DDCOLORKEY ckey;
9473 window = create_window();
9474 ddraw = create_ddraw();
9475 ok(!!ddraw, "Failed to create a ddraw object.\n");
9476 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9477 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9479 memset(&surface_desc, 0, sizeof(surface_desc));
9480 surface_desc.dwSize = sizeof(surface_desc);
9481 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
9482 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9483 surface_desc.dwWidth = 1;
9484 surface_desc.dwHeight = 1;
9485 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
9486 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
9487 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9488 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9489 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
9490 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
9492 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
9493 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
9494 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
9495 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9496 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
9498 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
9499 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
9500 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9501 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
9503 /* Same for DDSCAPS_OFFSCREENPLAIN. */
9504 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9505 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
9506 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
9507 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9508 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
9510 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
9511 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
9512 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9513 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
9515 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
9516 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
9517 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9518 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9520 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
9521 ckey.dwColorSpaceLowValue = 0x00000000;
9522 ckey.dwColorSpaceHighValue = 0x00000001;
9523 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9524 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
9526 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9527 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
9528 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
9529 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
9531 ckey.dwColorSpaceLowValue = 0x00000001;
9532 ckey.dwColorSpaceHighValue = 0x00000000;
9533 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9534 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
9536 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9537 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
9538 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
9539 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
9541 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
9542 ckey.dwColorSpaceLowValue = 0x00000000;
9543 ckey.dwColorSpaceHighValue = 0x00000000;
9544 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
9545 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
9547 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
9548 ckey.dwColorSpaceLowValue = 0x00000001;
9549 ckey.dwColorSpaceHighValue = 0x00000000;
9550 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
9551 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
9552 ckey.dwColorSpaceLowValue = 0x00000000;
9553 ckey.dwColorSpaceHighValue = 0x00000001;
9554 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
9555 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
9556 /* Range destination keys don't work either. */
9557 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
9558 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
9560 /* Just to show it's not because of A, R, and G having equal values. */
9561 ckey.dwColorSpaceLowValue = 0x00000000;
9562 ckey.dwColorSpaceHighValue = 0x01010101;
9563 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
9564 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
9566 /* None of these operations modified the key. */
9567 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9568 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
9569 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
9570 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
9572 IDirectDrawSurface_Release(surface);
9573 refcount = IDirectDraw2_Release(ddraw);
9574 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9575 DestroyWindow(window);
9578 static void test_shademode(void)
9580 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
9581 IDirect3DMaterial2 *background;
9582 IDirect3DViewport2 *viewport;
9583 IDirect3DDevice2 *device;
9584 IDirectDrawSurface *rt;
9585 DWORD color0, color1;
9586 IDirectDraw2 *ddraw;
9587 D3DLVERTEX *quad;
9588 ULONG refcount;
9589 UINT i, count;
9590 HWND window;
9591 HRESULT hr;
9592 static D3DLVERTEX quad_strip[] =
9594 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}},
9595 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
9596 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
9597 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffffffff}},
9599 quad_list[] =
9601 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}},
9602 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
9603 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
9605 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
9606 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
9607 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffffffff}},
9609 static const struct
9611 DWORD primtype;
9612 DWORD shademode;
9613 DWORD color0, color1;
9615 tests[] =
9617 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x0000ff00},
9618 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
9619 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
9620 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
9621 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
9622 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
9625 window = create_window();
9626 ddraw = create_ddraw();
9627 ok(!!ddraw, "Failed to create a ddraw object.\n");
9628 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
9630 skip("Failed to create a 3D device, skipping test.\n");
9631 IDirectDraw2_Release(ddraw);
9632 DestroyWindow(window);
9633 return;
9636 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
9637 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9639 background = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
9640 viewport = create_viewport(device, 0, 0, 640, 480);
9641 viewport_set_background(device, viewport, background);
9642 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
9643 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
9645 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
9646 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
9648 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
9649 * the color fixups we have to do for FLAT shading will be dependent on that. */
9651 for (i = 0; i < ARRAY_SIZE(tests); ++i)
9653 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9654 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
9656 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
9657 ok(hr == D3D_OK, "Failed to set shade mode, hr %#x.\n", hr);
9659 hr = IDirect3DDevice2_BeginScene(device);
9660 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9661 quad = tests[i].primtype == D3DPT_TRIANGLESTRIP ? quad_strip : quad_list;
9662 count = tests[i].primtype == D3DPT_TRIANGLESTRIP ? 4 : 6;
9663 hr = IDirect3DDevice2_DrawPrimitive(device, tests[i].primtype, D3DVT_LVERTEX, quad, count, 0);
9664 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9665 hr = IDirect3DDevice2_EndScene(device);
9666 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9668 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
9669 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
9671 /* For D3DSHADE_FLAT it should take the color of the first vertex of
9672 * each triangle. This requires EXT_provoking_vertex or similar
9673 * functionality being available. */
9674 /* PHONG should be the same as GOURAUD, since no hardware implements
9675 * this. */
9676 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
9677 i, color0, tests[i].color0);
9678 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
9679 i, color1, tests[i].color1);
9682 destroy_viewport(device, viewport);
9683 destroy_material(background);
9684 IDirectDrawSurface_Release(rt);
9685 refcount = IDirect3DDevice2_Release(device);
9686 ok(!refcount, "Device has %u references left.\n", refcount);
9687 IDirectDraw_Release(ddraw);
9688 DestroyWindow(window);
9691 static void test_lockrect_invalid(void)
9693 unsigned int i, r;
9694 IDirectDraw2 *ddraw;
9695 IDirectDrawSurface *surface1;
9696 IDirectDrawSurface2 *surface;
9697 HWND window;
9698 HRESULT hr;
9699 DDSURFACEDESC surface_desc;
9700 DDCAPS hal_caps;
9701 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
9702 static RECT valid[] =
9704 {60, 60, 68, 68},
9705 {60, 60, 60, 68},
9706 {60, 60, 68, 60},
9707 {120, 60, 128, 68},
9708 {60, 120, 68, 128},
9710 static RECT invalid[] =
9712 {68, 60, 60, 68}, /* left > right */
9713 {60, 68, 68, 60}, /* top > bottom */
9714 {-8, 60, 0, 68}, /* left < surface */
9715 {60, -8, 68, 0}, /* top < surface */
9716 {-16, 60, -8, 68}, /* right < surface */
9717 {60, -16, 68, -8}, /* bottom < surface */
9718 {60, 60, 136, 68}, /* right > surface */
9719 {60, 60, 68, 136}, /* bottom > surface */
9720 {136, 60, 144, 68}, /* left > surface */
9721 {60, 136, 68, 144}, /* top > surface */
9723 static const struct
9725 DWORD caps;
9726 const char *name;
9727 HRESULT hr;
9729 resources[] =
9731 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, "sysmem offscreenplain", DDERR_INVALIDPARAMS},
9732 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, "vidmem offscreenplain", DDERR_INVALIDPARAMS},
9733 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "sysmem texture", DDERR_INVALIDPARAMS},
9734 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "vidmem texture", DDERR_INVALIDPARAMS},
9737 window = create_window();
9738 ddraw = create_ddraw();
9739 ok(!!ddraw, "Failed to create a ddraw object.\n");
9740 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9741 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9743 memset(&hal_caps, 0, sizeof(hal_caps));
9744 hal_caps.dwSize = sizeof(hal_caps);
9745 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
9746 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9747 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
9749 skip("Required surface types not supported, skipping test.\n");
9750 goto done;
9753 for (r = 0; r < ARRAY_SIZE(resources); ++r)
9755 memset(&surface_desc, 0, sizeof(surface_desc));
9756 surface_desc.dwSize = sizeof(surface_desc);
9757 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9758 surface_desc.ddsCaps.dwCaps = resources[r].caps;
9759 surface_desc.dwWidth = 128;
9760 surface_desc.dwHeight = 128;
9761 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
9762 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
9763 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
9764 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xff0000;
9765 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x00ff00;
9766 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x0000ff;
9768 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
9769 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, resources[r].name);
9770 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
9771 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface2 interface, hr %#x.\n", hr);
9772 IDirectDrawSurface_Release(surface1);
9774 hr = IDirectDrawSurface2_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
9775 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
9777 for (i = 0; i < ARRAY_SIZE(valid); ++i)
9779 RECT *rect = &valid[i];
9781 memset(&surface_desc, 0, sizeof(surface_desc));
9782 surface_desc.dwSize = sizeof(surface_desc);
9784 hr = IDirectDrawSurface2_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
9785 ok(SUCCEEDED(hr), "Lock failed (%#x) for rect %s, type %s.\n",
9786 hr, wine_dbgstr_rect(rect), resources[r].name);
9788 hr = IDirectDrawSurface2_Unlock(surface, NULL);
9789 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
9792 for (i = 0; i < ARRAY_SIZE(invalid); ++i)
9794 RECT *rect = &invalid[i];
9796 memset(&surface_desc, 1, sizeof(surface_desc));
9797 surface_desc.dwSize = sizeof(surface_desc);
9799 hr = IDirectDrawSurface2_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
9800 ok(hr == resources[r].hr, "Lock returned %#x for rect %s, type %s.\n",
9801 hr, wine_dbgstr_rect(rect), resources[r].name);
9802 if (SUCCEEDED(hr))
9804 hr = IDirectDrawSurface2_Unlock(surface, NULL);
9805 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
9807 else
9808 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9811 hr = IDirectDrawSurface2_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
9812 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#x, type %s.\n",
9813 hr, resources[r].name);
9814 hr = IDirectDrawSurface2_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
9815 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#x, type %s.\n",
9816 hr, resources[r].name);
9817 hr = IDirectDrawSurface2_Unlock(surface, NULL);
9818 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
9820 hr = IDirectDrawSurface2_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
9821 ok(SUCCEEDED(hr), "Lock(rect = %s) failed (%#x).\n", wine_dbgstr_rect(&valid[0]), hr);
9822 hr = IDirectDrawSurface2_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
9823 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = %s) failed (%#x).\n",
9824 wine_dbgstr_rect(&valid[0]), hr);
9826 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
9827 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
9829 hr = IDirectDrawSurface2_Unlock(surface, NULL);
9830 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
9832 IDirectDrawSurface2_Release(surface);
9835 done:
9836 IDirectDraw2_Release(ddraw);
9837 DestroyWindow(window);
9840 static void test_yv12_overlay(void)
9842 IDirectDrawSurface *src_surface, *dst_surface;
9843 RECT rect = {13, 17, 14, 18};
9844 unsigned int offset, y;
9845 unsigned char *base;
9846 IDirectDraw2 *ddraw;
9847 DDSURFACEDESC desc;
9848 HWND window;
9849 HRESULT hr;
9851 window = create_window();
9852 ddraw = create_ddraw();
9853 ok(!!ddraw, "Failed to create a ddraw object.\n");
9854 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9855 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9857 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
9859 skip("Failed to create a YV12 overlay, skipping test.\n");
9860 goto done;
9863 memset(&desc, 0, sizeof(desc));
9864 desc.dwSize = sizeof(desc);
9865 hr = IDirectDrawSurface_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
9866 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9868 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
9869 "Got unexpected flags %#x.\n", desc.dwFlags);
9870 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
9871 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
9872 "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps);
9873 ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth);
9874 ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight);
9875 /* The overlay pitch seems to have 256 byte alignment. */
9876 ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch);
9878 /* Fill the surface with some data for the blit test. */
9879 base = desc.lpSurface;
9880 /* Luminance */
9881 for (y = 0; y < desc.dwHeight; ++y)
9883 memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth);
9885 /* V */
9886 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
9888 memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth);
9890 /* U */
9891 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
9893 memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth);
9896 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
9897 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9899 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
9900 * other block-based formats like DXT the entire Y channel is stored in
9901 * one big chunk of memory, followed by the chroma channels. So partial
9902 * locks do not really make sense. Show that they are allowed nevertheless
9903 * and the offset points into the luminance data. */
9904 hr = IDirectDrawSurface_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
9905 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9906 offset = ((const unsigned char *)desc.lpSurface - base);
9907 ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n",
9908 offset, rect.top * U1(desc).lPitch + rect.left);
9909 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
9910 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9912 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
9914 /* Windows XP with a Radeon X1600 GPU refuses to create a second
9915 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
9916 skip("Failed to create a second YV12 surface, skipping blit test.\n");
9917 IDirectDrawSurface_Release(src_surface);
9918 goto done;
9921 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
9922 /* VMware rejects YV12 blits. This behavior has not been seen on real
9923 * hardware yet, so mark it broken. */
9924 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr);
9926 if (SUCCEEDED(hr))
9928 memset(&desc, 0, sizeof(desc));
9929 desc.dwSize = sizeof(desc);
9930 hr = IDirectDrawSurface_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
9931 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9933 base = desc.lpSurface;
9934 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
9935 base += desc.dwHeight * U1(desc).lPitch;
9936 todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
9937 base += desc.dwHeight / 4 * U1(desc).lPitch;
9938 todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
9940 hr = IDirectDrawSurface_Unlock(dst_surface, NULL);
9941 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9944 IDirectDrawSurface_Release(dst_surface);
9945 IDirectDrawSurface_Release(src_surface);
9946 done:
9947 IDirectDraw2_Release(ddraw);
9948 DestroyWindow(window);
9951 static BOOL dwm_enabled(void)
9953 BOOL ret = FALSE;
9955 if (!strcmp(winetest_platform, "wine"))
9956 return FALSE;
9957 if (!pDwmIsCompositionEnabled)
9958 return FALSE;
9959 if (FAILED(pDwmIsCompositionEnabled(&ret)))
9960 return FALSE;
9961 return ret;
9964 static void test_offscreen_overlay(void)
9966 IDirectDrawSurface *overlay, *offscreen, *primary;
9967 DDSURFACEDESC surface_desc;
9968 IDirectDraw2 *ddraw;
9969 HWND window;
9970 HRESULT hr;
9971 HDC dc;
9973 window = create_window();
9974 ddraw = create_ddraw();
9975 ok(!!ddraw, "Failed to create a ddraw object.\n");
9976 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9977 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9979 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
9981 skip("Failed to create a UYVY overlay, skipping test.\n");
9982 goto done;
9985 memset(&surface_desc, 0, sizeof(surface_desc));
9986 surface_desc.dwSize = sizeof(surface_desc);
9987 surface_desc.dwFlags = DDSD_CAPS;
9988 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
9989 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
9990 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
9992 /* On Windows 7, and probably Vista, UpdateOverlay() will return
9993 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
9994 * surface prevents this by disabling the dwm. */
9995 hr = IDirectDrawSurface_GetDC(primary, &dc);
9996 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
9997 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
9998 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
10000 /* Try to overlay a NULL surface. */
10001 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
10002 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10003 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
10004 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10006 /* Try to overlay an offscreen surface. */
10007 memset(&surface_desc, 0, sizeof(surface_desc));
10008 surface_desc.dwSize = sizeof(surface_desc);
10009 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
10010 surface_desc.dwWidth = 64;
10011 surface_desc.dwHeight = 64;
10012 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10013 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
10014 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
10015 surface_desc.ddpfPixelFormat.dwFourCC = 0;
10016 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
10017 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xf800;
10018 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x07e0;
10019 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x001f;
10020 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
10021 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
10023 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
10024 ok(SUCCEEDED(hr) || broken(hr == DDERR_OUTOFCAPS && dwm_enabled())
10025 || broken(hr == E_NOTIMPL && ddraw_is_vmware(ddraw)),
10026 "Failed to update overlay, hr %#x.\n", hr);
10028 /* Try to overlay the primary with a non-overlay surface. */
10029 hr = IDirectDrawSurface_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
10030 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
10031 hr = IDirectDrawSurface_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_HIDE, NULL);
10032 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
10034 IDirectDrawSurface_Release(offscreen);
10035 IDirectDrawSurface_Release(primary);
10036 IDirectDrawSurface_Release(overlay);
10037 done:
10038 IDirectDraw2_Release(ddraw);
10039 DestroyWindow(window);
10042 static void test_overlay_rect(void)
10044 IDirectDrawSurface *overlay, *primary = NULL;
10045 DDSURFACEDESC surface_desc;
10046 RECT rect = {0, 0, 64, 64};
10047 IDirectDraw2 *ddraw;
10048 LONG pos_x, pos_y;
10049 HRESULT hr, hr2;
10050 HWND window;
10051 HDC dc;
10053 window = create_window();
10054 ddraw = create_ddraw();
10055 ok(!!ddraw, "Failed to create a ddraw object.\n");
10056 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10057 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10059 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
10061 skip("Failed to create a UYVY overlay, skipping test.\n");
10062 goto done;
10065 memset(&surface_desc, 0, sizeof(surface_desc));
10066 surface_desc.dwSize = sizeof(surface_desc);
10067 surface_desc.dwFlags = DDSD_CAPS;
10068 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
10069 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
10070 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
10072 /* On Windows 7, and probably Vista, UpdateOverlay() will return
10073 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
10074 * surface prevents this by disabling the dwm. */
10075 hr = IDirectDrawSurface_GetDC(primary, &dc);
10076 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
10077 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
10078 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
10080 /* On Windows 8 and newer DWM can't be turned off, making overlays unusable. */
10081 if (dwm_enabled())
10083 win_skip("Cannot disable DWM, skipping overlay test.\n");
10084 goto done;
10087 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is
10088 * used. This is not true in Windows Vista and earlier, but changed in
10089 * Windows 7. */
10090 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
10091 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
10092 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
10093 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
10094 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
10095 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10097 /* Show that the overlay position is the (top, left) coordinate of the
10098 * destination rectangle. */
10099 OffsetRect(&rect, 32, 16);
10100 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
10101 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
10102 pos_x = -1; pos_y = -1;
10103 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
10104 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
10105 ok(pos_x == rect.left, "Got unexpected pos_x %d, expected %d.\n", pos_x, rect.left);
10106 ok(pos_y == rect.top, "Got unexpected pos_y %d, expected %d.\n", pos_y, rect.top);
10108 /* Passing a NULL dest rect sets the position to 0/0. Visually it can be
10109 * seen that the overlay overlays the whole primary(==screen). */
10110 hr2 = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
10111 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS || hr2 == DDERR_OUTOFCAPS, "Got unexpected hr %#x.\n", hr2);
10112 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
10113 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
10114 if (SUCCEEDED(hr2))
10116 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
10117 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
10119 else
10121 ok(pos_x == 32, "Got unexpected pos_x %d.\n", pos_x);
10122 ok(pos_y == 16, "Got unexpected pos_y %d.\n", pos_y);
10125 /* The position cannot be retrieved when the overlay is not shown. */
10126 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
10127 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
10128 pos_x = -1; pos_y = -1;
10129 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
10130 ok(hr == DDERR_OVERLAYNOTVISIBLE, "Got unexpected hr %#x.\n", hr);
10131 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
10132 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
10134 IDirectDrawSurface_Release(overlay);
10135 done:
10136 if (primary)
10137 IDirectDrawSurface_Release(primary);
10138 IDirectDraw2_Release(ddraw);
10139 DestroyWindow(window);
10142 static void test_blt(void)
10144 IDirectDrawSurface *surface, *rt;
10145 DDSURFACEDESC surface_desc;
10146 IDirect3DDevice2 *device;
10147 IDirectDraw2 *ddraw;
10148 unsigned int i;
10149 ULONG refcount;
10150 HWND window;
10151 HRESULT hr;
10153 static struct
10155 RECT src_rect;
10156 RECT dst_rect;
10157 HRESULT hr;
10159 test_data[] =
10161 {{160, 0, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit. */
10162 {{160, 480, 640, 0}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, flipped source. */
10163 {{640, 0, 160, 480}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, mirrored source. */
10164 {{160, 0, 480, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched x. */
10165 {{160, 160, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched y. */
10166 {{ 0, 0, 640, 480}, { 0, 0, 640, 480}, DD_OK}, /* Full surface blit. */
10167 {{ 0, 0, 640, 480}, { 0, 480, 640, 0}, DDERR_INVALIDRECT}, /* Full surface, flipped destination. */
10168 {{ 0, 0, 640, 480}, {640, 0, 0, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored destination. */
10169 {{ 0, 480, 640, 0}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, flipped source. */
10170 {{640, 0, 0, 480}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored source. */
10173 window = create_window();
10174 ddraw = create_ddraw();
10175 ok(!!ddraw, "Failed to create a ddraw object.\n");
10176 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
10178 skip("Failed to create a 3D device, skipping test.\n");
10179 IDirectDraw2_Release(ddraw);
10180 DestroyWindow(window);
10181 return;
10184 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
10185 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10187 memset(&surface_desc, 0, sizeof(surface_desc));
10188 surface_desc.dwSize = sizeof(surface_desc);
10189 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
10190 surface_desc.dwWidth = 640;
10191 surface_desc.dwHeight = 480;
10192 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10193 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10194 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10196 hr = IDirectDrawSurface_Blt(surface, NULL, surface, NULL, 0, NULL);
10197 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
10199 hr = IDirectDrawSurface_Blt(surface, NULL, rt, NULL, 0, NULL);
10200 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
10202 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
10204 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
10205 surface, &test_data[i].src_rect, DDBLT_WAIT, NULL);
10206 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
10208 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
10209 rt, &test_data[i].src_rect, DDBLT_WAIT, NULL);
10210 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
10212 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
10213 NULL, &test_data[i].src_rect, DDBLT_WAIT, NULL);
10214 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
10216 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect, NULL, NULL, DDBLT_WAIT, NULL);
10217 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
10220 IDirectDrawSurface_Release(surface);
10221 IDirectDrawSurface_Release(rt);
10222 refcount = IDirect3DDevice2_Release(device);
10223 ok(!refcount, "Device has %u references left.\n", refcount);
10224 IDirectDraw2_Release(ddraw);
10225 DestroyWindow(window);
10228 static void test_blt_z_alpha(void)
10230 DWORD blt_flags[] =
10232 /* 0 */
10233 DDBLT_ALPHADEST,
10234 DDBLT_ALPHADESTCONSTOVERRIDE,
10235 DDBLT_ALPHADESTNEG,
10236 DDBLT_ALPHADESTSURFACEOVERRIDE,
10237 DDBLT_ALPHAEDGEBLEND,
10238 /* 5 */
10239 DDBLT_ALPHASRC,
10240 DDBLT_ALPHASRCCONSTOVERRIDE,
10241 DDBLT_ALPHASRCNEG,
10242 DDBLT_ALPHASRCSURFACEOVERRIDE,
10243 DDBLT_ZBUFFER,
10244 /* 10 */
10245 DDBLT_ZBUFFERDESTCONSTOVERRIDE,
10246 DDBLT_ZBUFFERDESTOVERRIDE,
10247 DDBLT_ZBUFFERSRCCONSTOVERRIDE,
10248 DDBLT_ZBUFFERSRCOVERRIDE,
10250 IDirectDrawSurface *src_surface, *dst_surface;
10251 DDSURFACEDESC surface_desc;
10252 IDirectDraw2 *ddraw;
10253 DDPIXELFORMAT pf;
10254 ULONG refcount;
10255 unsigned int i;
10256 D3DCOLOR color;
10257 HWND window;
10258 HRESULT hr;
10259 DDBLTFX fx;
10261 window = create_window();
10262 ddraw = create_ddraw();
10263 ok(!!ddraw, "Failed to create a ddraw object.\n");
10264 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10265 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10267 memset(&pf, 0, sizeof(pf));
10268 pf.dwSize = sizeof(pf);
10269 pf.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
10270 U1(pf).dwRGBBitCount = 32;
10271 U2(pf).dwRBitMask = 0x00ff0000;
10272 U3(pf).dwGBitMask = 0x0000ff00;
10273 U4(pf).dwBBitMask = 0x000000ff;
10274 U5(pf).dwRGBAlphaBitMask = 0xff000000;
10276 memset(&surface_desc, 0, sizeof(surface_desc));
10277 surface_desc.dwSize = sizeof(surface_desc);
10278 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
10279 surface_desc.dwWidth = 64;
10280 surface_desc.dwHeight = 64;
10281 surface_desc.ddpfPixelFormat = pf;
10282 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10284 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
10285 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
10286 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
10287 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
10289 memset(&fx, 0, sizeof(fx));
10290 fx.dwSize = sizeof(fx);
10291 fx.dwZBufferOpCode = D3DCMP_NEVER;
10292 fx.dwZDestConstBitDepth = 32;
10293 U1(fx).dwZDestConst = 0x11111111;
10294 fx.dwZSrcConstBitDepth = 32;
10295 U2(fx).dwZSrcConst = 0xeeeeeeee;
10296 fx.dwAlphaEdgeBlendBitDepth = 8;
10297 fx.dwAlphaEdgeBlend = 0x7f;
10298 fx.dwAlphaDestConstBitDepth = 8;
10299 U3(fx).dwAlphaDestConst = 0xdd;
10300 fx.dwAlphaSrcConstBitDepth = 8;
10301 U4(fx).dwAlphaSrcConst = 0x22;
10303 for (i = 0; i < ARRAY_SIZE(blt_flags); ++i)
10305 U5(fx).dwFillColor = 0x3300ff00;
10306 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10307 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
10309 U5(fx).dwFillColor = 0xccff0000;
10310 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10311 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
10313 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, NULL, blt_flags[i] | DDBLT_WAIT, &fx);
10314 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
10316 color = get_surface_color(dst_surface, 32, 32);
10317 ok(compare_color(color, 0x0000ff00, 0), "Test %u: Got unexpected color 0x%08x.\n", i, color);
10320 IDirectDrawSurface_Release(dst_surface);
10321 IDirectDrawSurface_Release(src_surface);
10322 refcount = IDirectDraw2_Release(ddraw);
10323 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
10324 DestroyWindow(window);
10327 static void test_cross_device_blt(void)
10329 IDirectDrawSurface *surface, *surface2, *sysmem_surface;
10330 IDirect3DDevice2 *device, *device2;
10331 IDirectDraw2 *ddraw, *ddraw2;
10332 DDSURFACEDESC surface_desc;
10333 HWND window, window2;
10334 ULONG refcount;
10335 D3DCOLOR color;
10336 DDBLTFX fx;
10337 HRESULT hr;
10339 window = create_window();
10340 ddraw = create_ddraw();
10341 if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
10343 skip("Failed to create a 3D device.\n");
10344 IDirectDraw2_Release(ddraw);
10345 DestroyWindow(window);
10346 return;
10349 window2 = create_window();
10350 ddraw2 = create_ddraw();
10351 if (!(device2 = create_device(ddraw2, window2, DDSCL_NORMAL)))
10353 skip("Failed to create a 3D device.\n");
10354 IDirectDraw2_Release(ddraw2);
10355 IDirect3DDevice2_Release(device);
10356 IDirectDraw2_Release(ddraw);
10357 DestroyWindow(window);
10358 DestroyWindow(window2);
10359 return;
10362 memset(&surface_desc, 0, sizeof(surface_desc));
10363 surface_desc.dwSize = sizeof(surface_desc);
10364 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
10365 surface_desc.dwWidth = 640;
10366 surface_desc.dwHeight = 480;
10367 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
10368 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
10369 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10371 memset(&surface_desc, 0, sizeof(surface_desc));
10372 surface_desc.dwSize = sizeof(surface_desc);
10373 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
10374 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_VIDEOMEMORY;
10375 surface_desc.dwBackBufferCount = 2;
10376 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10377 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10379 memset(&surface_desc, 0, sizeof(surface_desc));
10380 surface_desc.dwSize = sizeof(surface_desc);
10381 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
10382 surface_desc.dwWidth = 640;
10383 surface_desc.dwHeight = 480;
10384 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
10385 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
10386 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
10387 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
10388 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00007c00;
10389 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x000003e0;
10390 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x0000001f;
10391 hr = IDirectDraw2_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
10392 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10394 memset(&fx, 0, sizeof(fx));
10395 fx.dwSize = sizeof(fx);
10396 U5(fx).dwFillColor = 0xff0000ff;
10397 hr = IDirectDrawSurface_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10398 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
10400 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
10401 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
10402 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
10403 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10404 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
10405 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
10406 color = get_surface_color(surface, 320, 240);
10407 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
10409 hr = IDirectDrawSurface_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
10410 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
10411 color = get_surface_color(sysmem_surface, 320, 240);
10412 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
10414 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10415 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10416 hr = IDirectDrawSurface_IsLost(sysmem_surface);
10417 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10419 hr = IDirectDrawSurface_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
10420 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
10421 color = get_surface_color(sysmem_surface, 320, 240);
10422 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
10424 IDirectDrawSurface_Release(surface2);
10425 memset(&surface_desc, 0, sizeof(surface_desc));
10426 surface_desc.dwSize = sizeof(surface_desc);
10427 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
10428 surface_desc.dwWidth = 640;
10429 surface_desc.dwHeight = 480;
10430 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
10431 hr = IDirectDraw2_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
10432 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10433 hr = IDirectDrawSurface_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10434 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
10436 hr = IDirectDrawSurface_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
10437 todo_wine ok(hr == D3D_OK, "Failed to blit, hr %#x.\n", hr);
10438 color = get_surface_color(sysmem_surface, 320, 240);
10439 todo_wine ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
10441 IDirectDrawSurface_Release(surface);
10442 IDirectDrawSurface_Release(surface2);
10443 IDirectDrawSurface_Release(sysmem_surface);
10444 refcount = IDirect3DDevice2_Release(device);
10445 ok(!refcount, "Device has %u references left.\n", refcount);
10446 refcount = IDirect3DDevice2_Release(device2);
10447 ok(!refcount, "Device has %u references left.\n", refcount);
10448 IDirectDraw2_Release(ddraw);
10449 IDirectDraw2_Release(ddraw2);
10450 DestroyWindow(window);
10451 DestroyWindow(window2);
10454 static void test_getdc(void)
10456 IDirectDrawSurface *surface, *surface2, *tmp;
10457 DDSURFACEDESC surface_desc, map_desc;
10458 DDSCAPS caps = {DDSCAPS_COMPLEX};
10459 IDirectDraw2 *ddraw;
10460 unsigned int i;
10461 HWND window;
10462 HDC dc, dc2;
10463 HRESULT hr;
10465 static const struct
10467 const char *name;
10468 DDPIXELFORMAT format;
10469 BOOL getdc_supported;
10470 HRESULT alt_result;
10472 test_data[] =
10474 {"D3DFMT_A8R8G8B8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
10475 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}}, TRUE},
10476 {"D3DFMT_X8R8G8B8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
10477 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}}, TRUE},
10478 {"D3DFMT_R5G6B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
10479 {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}}, TRUE},
10480 {"D3DFMT_X1R5G5B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
10481 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}}, TRUE},
10482 {"D3DFMT_A1R5G5B5", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
10483 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}}, TRUE},
10484 {"D3DFMT_A4R4G4B4", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
10485 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
10486 {"D3DFMT_X4R4G4B4", {sizeof(test_data->format), DDPF_RGB, 0, {16},
10487 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
10488 {"D3DFMT_A2R10G10B10", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
10489 {0xc0000000}, {0x3ff00000}, {0x000ffc00}, {0x000003ff}}, TRUE},
10490 {"D3DFMT_A8B8G8R8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
10491 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
10492 {"D3DFMT_X8B8G8R8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
10493 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
10494 {"D3DFMT_R3G3B2", {sizeof(test_data->format), DDPF_RGB, 0, {8},
10495 {0x000000e0}, {0x0000001c}, {0x00000003}, {0x00000000}}, FALSE},
10496 /* GetDC() on a P8 surface fails unless the display mode is 8 bpp.
10497 * This is not implemented in wine yet, so disable the test for now.
10498 * Succeeding P8 GetDC() calls are tested in the ddraw:visual test.
10499 {"D3DFMT_P8", {sizeof(test_data->format), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0, {8 },
10500 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
10502 {"D3DFMT_L8", {sizeof(test_data->format), DDPF_LUMINANCE, 0, {8},
10503 {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
10504 {"D3DFMT_A8L8", {sizeof(test_data->format), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0, {16},
10505 {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}}, FALSE},
10506 {"D3DFMT_DXT1", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'), {0},
10507 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
10508 {"D3DFMT_DXT2", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'), {0},
10509 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
10510 {"D3DFMT_DXT3", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'), {0},
10511 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
10512 {"D3DFMT_DXT4", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'), {0},
10513 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
10514 {"D3DFMT_DXT5", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'), {0},
10515 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
10518 window = create_window();
10519 ddraw = create_ddraw();
10520 ok(!!ddraw, "Failed to create a ddraw object.\n");
10521 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10522 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10524 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
10526 memset(&surface_desc, 0, sizeof(surface_desc));
10527 surface_desc.dwSize = sizeof(surface_desc);
10528 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10529 surface_desc.dwWidth = 64;
10530 surface_desc.dwHeight = 64;
10531 surface_desc.ddpfPixelFormat = test_data[i].format;
10532 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10534 if (FAILED(IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
10536 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10537 if (FAILED(hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
10539 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
10540 continue;
10544 dc = (void *)0x1234;
10545 hr = IDirectDrawSurface_GetDC(surface, &dc);
10546 if (test_data[i].getdc_supported)
10547 ok(SUCCEEDED(hr) || broken(hr == test_data[i].alt_result || ddraw_is_vmware(ddraw)),
10548 "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
10549 else
10550 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
10552 if (SUCCEEDED(hr))
10554 unsigned int width_bytes;
10555 DIBSECTION dib;
10556 HBITMAP bitmap;
10557 DWORD type;
10558 int size;
10560 type = GetObjectType(dc);
10561 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
10562 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
10563 type = GetObjectType(bitmap);
10564 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
10566 size = GetObjectA(bitmap, sizeof(dib), &dib);
10567 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, test_data[i].name);
10568 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
10569 dib.dsBm.bmType, test_data[i].name);
10570 ok(dib.dsBm.bmWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
10571 dib.dsBm.bmWidth, test_data[i].name);
10572 ok(dib.dsBm.bmHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
10573 dib.dsBm.bmHeight, test_data[i].name);
10574 width_bytes = ((dib.dsBm.bmWidth * U1(test_data[i].format).dwRGBBitCount + 31) >> 3) & ~3;
10575 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
10576 dib.dsBm.bmWidthBytes, test_data[i].name);
10577 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
10578 dib.dsBm.bmPlanes, test_data[i].name);
10579 ok(dib.dsBm.bmBitsPixel == U1(test_data[i].format).dwRGBBitCount,
10580 "Got unexpected bit count %d for format %s.\n",
10581 dib.dsBm.bmBitsPixel, test_data[i].name);
10582 ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n",
10583 dib.dsBm.bmBits, test_data[i].name);
10585 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
10586 dib.dsBmih.biSize, test_data[i].name);
10587 ok(dib.dsBmih.biWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
10588 dib.dsBmih.biHeight, test_data[i].name);
10589 ok(dib.dsBmih.biHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
10590 dib.dsBmih.biHeight, test_data[i].name);
10591 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
10592 dib.dsBmih.biPlanes, test_data[i].name);
10593 ok(dib.dsBmih.biBitCount == U1(test_data[i].format).dwRGBBitCount,
10594 "Got unexpected bit count %u for format %s.\n",
10595 dib.dsBmih.biBitCount, test_data[i].name);
10596 ok(dib.dsBmih.biCompression == (U1(test_data[i].format).dwRGBBitCount == 16 ? BI_BITFIELDS : BI_RGB)
10597 || broken(U1(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
10598 "Got unexpected compression %#x for format %s.\n",
10599 dib.dsBmih.biCompression, test_data[i].name);
10600 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
10601 dib.dsBmih.biSizeImage, test_data[i].name);
10602 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
10603 dib.dsBmih.biXPelsPerMeter, test_data[i].name);
10604 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
10605 dib.dsBmih.biYPelsPerMeter, test_data[i].name);
10606 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
10607 dib.dsBmih.biClrUsed, test_data[i].name);
10608 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
10609 dib.dsBmih.biClrImportant, test_data[i].name);
10611 if (dib.dsBmih.biCompression == BI_BITFIELDS)
10613 ok((dib.dsBitfields[0] == U2(test_data[i].format).dwRBitMask
10614 && dib.dsBitfields[1] == U3(test_data[i].format).dwGBitMask
10615 && dib.dsBitfields[2] == U4(test_data[i].format).dwBBitMask)
10616 || broken(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2]),
10617 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
10618 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
10620 else
10622 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
10623 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
10624 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
10626 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, test_data[i].name);
10627 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, test_data[i].name);
10629 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
10630 ok(hr == DD_OK, "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10632 else
10634 ok(!dc, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
10637 IDirectDrawSurface_Release(surface);
10639 if (FAILED(hr))
10640 continue;
10642 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
10643 if (FAILED(hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
10645 skip("Failed to create mip-mapped texture for format %s (hr %#x), skipping tests.\n",
10646 test_data[i].name, hr);
10647 continue;
10650 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &tmp);
10651 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
10652 hr = IDirectDrawSurface_GetAttachedSurface(tmp, &caps, &surface2);
10653 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
10654 IDirectDrawSurface_Release(tmp);
10656 hr = IDirectDrawSurface_GetDC(surface, &dc);
10657 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10658 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
10659 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10660 hr = IDirectDrawSurface_GetDC(surface2, &dc);
10661 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10662 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
10663 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10665 hr = IDirectDrawSurface_GetDC(surface, &dc);
10666 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10667 dc2 = (void *)0x1234;
10668 hr = IDirectDrawSurface_GetDC(surface, &dc2);
10669 ok(hr == DDERR_DCALREADYCREATED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
10670 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
10671 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
10672 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10673 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
10674 ok(hr == DDERR_NODC, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
10676 map_desc.dwSize = sizeof(map_desc);
10677 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
10678 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
10679 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
10680 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
10681 hr = IDirectDrawSurface_Unlock(surface, NULL);
10682 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
10683 hr = IDirectDrawSurface_Unlock(surface, NULL);
10684 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
10686 hr = IDirectDrawSurface_GetDC(surface, &dc);
10687 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10688 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
10689 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
10690 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
10691 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10693 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
10694 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
10695 hr = IDirectDrawSurface_GetDC(surface, &dc);
10696 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10697 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
10698 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10699 hr = IDirectDrawSurface_Unlock(surface, NULL);
10700 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
10702 hr = IDirectDrawSurface_GetDC(surface, &dc);
10703 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10704 hr = IDirectDrawSurface_GetDC(surface2, &dc2);
10705 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10706 hr = IDirectDrawSurface_ReleaseDC(surface2, dc2);
10707 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10708 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
10709 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10711 hr = IDirectDrawSurface_GetDC(surface2, &dc);
10712 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10713 hr = IDirectDrawSurface_GetDC(surface, &dc2);
10714 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10715 hr = IDirectDrawSurface_ReleaseDC(surface, dc2);
10716 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10717 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
10718 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10720 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
10721 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
10722 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
10723 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
10724 hr = IDirectDrawSurface_Unlock(surface2, NULL);
10725 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
10726 hr = IDirectDrawSurface_Unlock(surface, NULL);
10727 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
10729 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
10730 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
10731 hr = IDirectDrawSurface_GetDC(surface, &dc);
10732 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10733 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
10734 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10735 hr = IDirectDrawSurface_Unlock(surface, NULL);
10736 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
10738 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
10739 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
10740 hr = IDirectDrawSurface_GetDC(surface, &dc);
10741 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10742 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
10743 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10744 hr = IDirectDrawSurface_Unlock(surface2, NULL);
10745 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
10747 hr = IDirectDrawSurface_GetDC(surface, &dc);
10748 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10749 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
10750 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
10751 hr = IDirectDrawSurface_Unlock(surface2, NULL);
10752 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
10753 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
10754 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10756 hr = IDirectDrawSurface_GetDC(surface2, &dc);
10757 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10758 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
10759 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
10760 hr = IDirectDrawSurface_Unlock(surface, NULL);
10761 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
10762 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
10763 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10765 hr = IDirectDrawSurface_Unlock(surface, NULL);
10766 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
10767 hr = IDirectDrawSurface_GetDC(surface2, &dc);
10768 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10769 hr = IDirectDrawSurface_Unlock(surface, NULL);
10770 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
10771 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
10772 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10773 hr = IDirectDrawSurface_Unlock(surface, NULL);
10774 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
10776 hr = IDirectDrawSurface_Unlock(surface2, NULL);
10777 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
10778 hr = IDirectDrawSurface_GetDC(surface, &dc);
10779 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10780 hr = IDirectDrawSurface_Unlock(surface2, NULL);
10781 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
10782 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
10783 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10784 hr = IDirectDrawSurface_Unlock(surface2, NULL);
10785 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
10787 IDirectDrawSurface_Release(surface2);
10788 IDirectDrawSurface_Release(surface);
10791 IDirectDraw2_Release(ddraw);
10792 DestroyWindow(window);
10795 static void test_draw_primitive(void)
10797 static WORD indices[] = {0, 1, 2, 3};
10798 static D3DVERTEX quad[] =
10800 {{-1.0f}, {-1.0f}, {0.0f}},
10801 {{-1.0f}, { 1.0f}, {0.0f}},
10802 {{ 1.0f}, {-1.0f}, {0.0f}},
10803 {{ 1.0f}, { 1.0f}, {0.0f}},
10805 IDirect3DViewport2 *viewport;
10806 IDirect3DDevice2 *device;
10807 IDirectDraw2 *ddraw;
10808 IDirect3D2 *d3d;
10809 ULONG refcount;
10810 HWND window;
10811 HRESULT hr;
10813 window = create_window();
10814 ddraw = create_ddraw();
10815 ok(!!ddraw, "Failed to create a ddraw object.\n");
10816 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
10818 skip("Failed to create a 3D device, skipping test.\n");
10819 IDirectDraw2_Release(ddraw);
10820 DestroyWindow(window);
10821 return;
10824 viewport = create_viewport(device, 0, 0, 640, 480);
10825 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
10826 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
10828 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
10829 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
10831 IDirect3D2_Release(d3d);
10833 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, NULL, 0, 0);
10834 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10835 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, 0);
10836 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10838 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, indices, 4, 0);
10839 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10841 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, NULL, 0, 0);
10842 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10843 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
10844 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10845 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, indices, 4, 0);
10846 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10848 destroy_viewport(device, viewport);
10849 refcount = IDirect3DDevice2_Release(device);
10850 ok(!refcount, "Device has %u references left.\n", refcount);
10851 IDirectDraw2_Release(ddraw);
10852 DestroyWindow(window);
10855 static void test_edge_antialiasing_blending(void)
10857 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
10858 IDirect3DMaterial2 *green_background;
10859 IDirect3DMaterial2 *red_background;
10860 IDirectDrawSurface *offscreen, *ds;
10861 D3DDEVICEDESC hal_desc, hel_desc;
10862 IDirect3DViewport2 *viewport;
10863 DDSURFACEDESC surface_desc;
10864 IDirect3DDevice2 *device;
10865 IDirectDraw2 *ddraw;
10866 ULONG refcount;
10867 D3DCOLOR color;
10868 HWND window;
10869 HRESULT hr;
10871 static D3DMATRIX mat =
10873 1.0f, 0.0f, 0.0f, 0.0f,
10874 0.0f, 1.0f, 0.0f, 0.0f,
10875 0.0f, 0.0f, 1.0f, 0.0f,
10876 0.0f, 0.0f, 0.0f, 1.0f,
10878 static D3DLVERTEX green_quad[] =
10880 {{-1.0f}, {-1.0f}, {0.1f}, 0, {0x7f00ff00}},
10881 {{-1.0f}, { 1.0f}, {0.1f}, 0, {0x7f00ff00}},
10882 {{ 1.0f}, {-1.0f}, {0.1f}, 0, {0x7f00ff00}},
10883 {{ 1.0f}, { 1.0f}, {0.1f}, 0, {0x7f00ff00}},
10885 static D3DLVERTEX red_quad[] =
10887 {{-1.0f}, {-1.0f}, {0.1f}, 0, {0xccff0000}},
10888 {{-1.0f}, { 1.0f}, {0.1f}, 0, {0xccff0000}},
10889 {{ 1.0f}, {-1.0f}, {0.1f}, 0, {0xccff0000}},
10890 {{ 1.0f}, { 1.0f}, {0.1f}, 0, {0xccff0000}},
10893 window = create_window();
10894 ddraw = create_ddraw();
10895 ok(!!ddraw, "Failed to create a ddraw object.\n");
10896 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
10898 skip("Failed to create a 3D device.\n");
10899 DestroyWindow(window);
10900 return;
10903 memset(&hal_desc, 0, sizeof(hal_desc));
10904 hal_desc.dwSize = sizeof(hal_desc);
10905 memset(&hel_desc, 0, sizeof(hel_desc));
10906 hel_desc.dwSize = sizeof(hel_desc);
10907 hr = IDirect3DDevice2_GetCaps(device, &hal_desc, &hel_desc);
10908 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10909 trace("HAL line edge antialiasing support: %#x.\n",
10910 hal_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
10911 trace("HAL triangle edge antialiasing support: %#x.\n",
10912 hal_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
10913 trace("HEL line edge antialiasing support: %#x.\n",
10914 hel_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
10915 trace("HEL triangle edge antialiasing support: %#x.\n",
10916 hel_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
10918 memset(&surface_desc, 0, sizeof(surface_desc));
10919 surface_desc.dwSize = sizeof(surface_desc);
10920 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
10921 surface_desc.dwWidth = 640;
10922 surface_desc.dwHeight = 480;
10923 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
10924 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
10925 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
10926 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
10927 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10928 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10929 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
10930 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
10931 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
10932 ok(hr == D3D_OK, "Creating the offscreen render target failed, hr %#x.\n", hr);
10934 ds = get_depth_stencil(device);
10935 hr = IDirectDrawSurface_AddAttachedSurface(offscreen, ds);
10936 todo_wine ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
10937 IDirectDrawSurface_Release(ds);
10939 hr = IDirect3DDevice2_SetRenderTarget(device, offscreen, 0);
10940 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
10942 red_background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 0.8f);
10943 green_background = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 0.5f);
10945 viewport = create_viewport(device, 0, 0, 640, 480);
10946 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
10947 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
10949 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
10950 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
10951 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
10952 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
10953 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
10954 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
10955 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
10956 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
10957 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
10958 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
10959 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
10960 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
10962 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
10963 ok(SUCCEEDED(hr), "Failed to enable blending, hr %#x.\n", hr);
10964 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
10965 ok(SUCCEEDED(hr), "Failed to set src blend, hr %#x.\n", hr);
10966 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
10967 ok(SUCCEEDED(hr), "Failed to set dest blend, hr %#x.\n", hr);
10969 viewport_set_background(device, viewport, red_background);
10970 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
10971 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
10972 hr = IDirect3DDevice2_BeginScene(device);
10973 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10974 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, green_quad, 4, 0);
10975 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10976 hr = IDirect3DDevice2_EndScene(device);
10977 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10978 color = get_surface_color(offscreen, 320, 240);
10979 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
10981 viewport_set_background(device, viewport, green_background);
10982 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
10983 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
10984 hr = IDirect3DDevice2_BeginScene(device);
10985 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10986 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, red_quad, 4, 0);
10987 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10988 hr = IDirect3DDevice2_EndScene(device);
10989 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10990 color = get_surface_color(offscreen, 320, 240);
10991 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
10993 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
10994 ok(SUCCEEDED(hr), "Failed to disable blending, hr %#x.\n", hr);
10996 viewport_set_background(device, viewport, red_background);
10997 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
10998 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
10999 hr = IDirect3DDevice2_BeginScene(device);
11000 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11001 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, green_quad, 4, 0);
11002 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11003 hr = IDirect3DDevice2_EndScene(device);
11004 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11005 color = get_surface_color(offscreen, 320, 240);
11006 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
11008 viewport_set_background(device, viewport, green_background);
11009 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
11010 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
11011 hr = IDirect3DDevice2_BeginScene(device);
11012 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11013 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, red_quad, 4, 0);
11014 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11015 hr = IDirect3DDevice2_EndScene(device);
11016 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11017 color = get_surface_color(offscreen, 320, 240);
11018 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
11020 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_EDGEANTIALIAS, TRUE);
11021 ok(SUCCEEDED(hr), "Failed to enable edge antialiasing, hr %#x.\n", hr);
11023 viewport_set_background(device, viewport, red_background);
11024 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
11025 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
11026 hr = IDirect3DDevice2_BeginScene(device);
11027 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11028 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, green_quad, 4, 0);
11029 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11030 hr = IDirect3DDevice2_EndScene(device);
11031 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11032 color = get_surface_color(offscreen, 320, 240);
11033 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
11035 viewport_set_background(device, viewport, green_background);
11036 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
11037 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
11038 hr = IDirect3DDevice2_BeginScene(device);
11039 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11040 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, red_quad, 4, 0);
11041 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11042 hr = IDirect3DDevice2_EndScene(device);
11043 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11044 color = get_surface_color(offscreen, 320, 240);
11045 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
11047 IDirectDrawSurface_Release(offscreen);
11048 destroy_viewport(device, viewport);
11049 destroy_material(red_background);
11050 destroy_material(green_background);
11051 refcount = IDirect3DDevice2_Release(device);
11052 ok(!refcount, "Device has %u references left.\n", refcount);
11053 IDirectDraw2_Release(ddraw);
11054 DestroyWindow(window);
11057 /* TransformVertices always writes 32 bytes regardless of the input / output stride.
11058 * The stride is honored for navigating to the next vertex. 3 floats input position
11059 * are read, and 16 bytes extra vertex data are copied around. */
11060 struct transform_input
11062 float x, y, z, unused1; /* Position data, transformed. */
11063 DWORD v1, v2, v3, v4; /* Extra data, e.g. color and texture coords, copied. */
11064 DWORD unused2;
11067 struct transform_output
11069 float x, y, z, w;
11070 DWORD v1, v2, v3, v4;
11071 DWORD unused3, unused4;
11074 static void test_transform_vertices(void)
11076 IDirect3DDevice2 *device;
11077 IDirectDrawSurface *rt;
11078 IDirectDraw2 *ddraw;
11079 ULONG refcount;
11080 HWND window;
11081 HRESULT hr;
11082 D3DCOLOR color;
11083 IDirect3DViewport2 *viewport;
11084 IDirect3DMaterial2 *background;
11085 D3DMATERIAL mat;
11086 static struct transform_input position_tests[] =
11088 { 0.0f, 0.0f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
11089 { 1.0f, 1.0f, 1.0f, 8.0f, 6, 7, 8, 9, 10},
11090 {-1.0f, -1.0f, -1.0f, 4.0f, 11, 12, 13, 14, 15},
11091 { 0.5f, 0.5f, 0.5f, 2.0f, 16, 17, 18, 19, 20},
11092 {-0.5f, -0.5f, -0.5f, 1.0f, ~1U, ~2U, ~3U, ~4U, ~5U},
11093 {-0.5f, -0.5f, 0.0f, 0.0f, ~6U, ~7U, ~8U, ~9U, ~0U},
11095 static struct transform_input cliptest[] =
11097 { 25.59f, 25.59f, 1.0f, 0.0f, 1, 2, 3, 4, 5},
11098 { 25.61f, 25.61f, 1.01f, 0.0f, 1, 2, 3, 4, 5},
11099 {-25.59f, -25.59f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
11100 {-25.61f, -25.61f, -0.01f, 0.0f, 1, 2, 3, 4, 5},
11102 static struct transform_input offscreentest[] =
11104 {128.1f, 0.0f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
11106 struct transform_output out[ARRAY_SIZE(position_tests)];
11107 D3DHVERTEX out_h[ARRAY_SIZE(position_tests)];
11108 D3DTRANSFORMDATA transformdata;
11109 static const D3DVIEWPORT vp_template =
11111 sizeof(vp_template), 0, 0, 256, 256, 5.0f, 5.0f, 256.0f, 256.0f, -25.0f, 60.0f
11113 D3DVIEWPORT vp_data =
11115 sizeof(vp_data), 0, 0, 256, 256, 1.0f, 1.0f, 256.0f, 256.0f, 0.0f, 1.0f
11117 D3DVIEWPORT2 vp2_data;
11118 unsigned int i;
11119 DWORD offscreen;
11120 static D3DMATRIX mat_scale =
11122 2.0f, 0.0f, 0.0f, 0.0f,
11123 0.0f, 2.0f, 0.0f, 0.0f,
11124 0.0f, 0.0f, 2.0f, 0.0f,
11125 0.0f, 0.0f, 0.0f, 1.0f,
11127 mat_translate1 =
11129 1.0f, 0.0f, 0.0f, 0.0f,
11130 0.0f, 1.0f, 0.0f, 0.0f,
11131 0.0f, 0.0f, 1.0f, 0.0f,
11132 1.0f, 0.0f, 0.0f, 1.0f,
11134 mat_translate2 =
11136 1.0f, 0.0f, 0.0f, 0.0f,
11137 0.0f, 1.0f, 0.0f, 0.0f,
11138 0.0f, 0.0f, 1.0f, 0.0f,
11139 0.0f, 1.0f, 0.0f, 1.0f,
11141 mat_transform3 =
11143 1.0f, 0.0f, 0.0f, 0.0f,
11144 0.0f, 1.0f, 0.0f, 0.0f,
11145 0.0f, 0.0f, 1.0f, 0.0f,
11146 0.0f, 19.2f, 0.0f, 2.0f,
11148 mat_identity =
11150 1.0f, 0.0f, 0.0f, 0.0f,
11151 0.0f, 1.0f, 0.0f, 0.0f,
11152 0.0f, 0.0f, 1.0f, 0.0f,
11153 0.0f, 0.0f, 0.0f, 1.0f,
11155 static D3DLVERTEX quad[] =
11157 {{-0.75f},{-0.5f }, {0.0f}, 0, {0xffff0000}},
11158 {{-0.75f},{ 0.25f}, {0.0f}, 0, {0xffff0000}},
11159 {{ 0.5f}, {-0.5f }, {0.0f}, 0, {0xffff0000}},
11160 {{ 0.5f}, { 0.25f}, {0.0f}, 0, {0xffff0000}},
11162 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
11165 for (i = 0; i < ARRAY_SIZE(out); ++i)
11167 out[i].unused3 = 0xdeadbeef;
11168 out[i].unused4 = 0xcafecafe;
11171 window = create_window();
11172 ddraw = create_ddraw();
11173 ok(!!ddraw, "Failed to create a ddraw object.\n");
11174 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
11176 skip("Failed to create a 3D device, skipping test.\n");
11177 IDirectDraw2_Release(ddraw);
11178 DestroyWindow(window);
11179 return;
11181 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
11182 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11184 viewport = create_viewport(device, 0, 0, 256, 256);
11185 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
11186 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
11188 memset(&transformdata, 0, sizeof(transformdata));
11189 transformdata.dwSize = sizeof(transformdata);
11190 transformdata.lpIn = position_tests;
11191 transformdata.dwInSize = sizeof(position_tests[0]);
11192 transformdata.lpOut = out;
11193 transformdata.dwOutSize = sizeof(out[0]);
11194 transformdata.lpHOut = NULL;
11196 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
11197 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
11198 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11199 ok(!offscreen, "Offscreen is %x.\n", offscreen);
11201 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
11203 static const struct vec4 cmp[] =
11205 {128.0f, 128.0f, 0.0f, 1.0f}, {129.0f, 127.0f, 1.0f, 1.0f}, {127.0f, 129.0f, -1.0f, 1.0f},
11206 {128.5f, 127.5f, 0.5f, 1.0f}, {127.5f, 128.5f, -0.5f, 1.0f}, {127.5f, 128.5f, 0.0f, 1.0f}
11209 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
11210 "Vertex %u differs. Got %f %f %f %f.\n", i,
11211 out[i].x, out[i].y, out[i].z, out[i].w);
11212 ok(out[i].v1 == position_tests[i].v1 && out[i].v2 == position_tests[i].v2
11213 && out[i].v3 == position_tests[i].v3 && out[i].v4 == position_tests[i].v4,
11214 "Vertex %u payload is %u %u %u %u.\n", i, out[i].v1, out[i].v2, out[i].v3, out[i].v4);
11215 ok(out[i].unused3 == 0xdeadbeef && out[i].unused4 == 0xcafecafe,
11216 "Vertex %u unused data is %#x, %#x.\n", i, out[i].unused3, out[i].unused4);
11219 vp_data = vp_template;
11220 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
11221 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
11222 offscreen = 0xdeadbeef;
11223 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
11224 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
11225 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11226 ok(!offscreen, "Offscreen is %x.\n", offscreen);
11228 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
11230 static const struct vec4 cmp[] =
11232 {128.0f, 128.0f, 0.0f, 1.0f}, {133.0f, 123.0f, 1.0f, 1.0f}, {123.0f, 133.0f, -1.0f, 1.0f},
11233 {130.5f, 125.5f, 0.5f, 1.0f}, {125.5f, 130.5f, -0.5f, 1.0f}, {125.5f, 130.5f, 0.0f, 1.0f}
11235 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
11236 "Vertex %u differs. Got %f %f %f %f.\n", i,
11237 out[i].x, out[i].y, out[i].z, out[i].w);
11240 vp_data.dwX = 10;
11241 vp_data.dwY = 20;
11242 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
11243 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
11244 offscreen = 0xdeadbeef;
11245 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
11246 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
11247 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11248 ok(!offscreen, "Offscreen is %x.\n", offscreen);
11249 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
11251 static const struct vec4 cmp[] =
11253 {138.0f, 148.0f, 0.0f, 1.0f}, {143.0f, 143.0f, 1.0f, 1.0f}, {133.0f, 153.0f, -1.0f, 1.0f},
11254 {140.5f, 145.5f, 0.5f, 1.0f}, {135.5f, 150.5f, -0.5f, 1.0f}, {135.5f, 150.5f, 0.0f, 1.0f}
11256 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
11257 "Vertex %u differs. Got %f %f %f %f.\n", i,
11258 out[i].x, out[i].y, out[i].z, out[i].w);
11261 transformdata.lpHOut = out_h;
11262 offscreen = 0xdeadbeef;
11263 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
11264 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11265 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11266 ok(!offscreen, "Offscreen is %x.\n", offscreen);
11267 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
11269 static const D3DHVERTEX cmp_h[] =
11271 {0, { 0.0f}, { 0.0f}, { 0.0f}}, {0, { 1.0f}, { 1.0f}, {1.0f}},
11272 {D3DCLIP_FRONT, {-1.0f}, {-1.0f}, {-1.0f}}, {0, { 0.5f}, { 0.5f}, {0.5f}},
11273 {D3DCLIP_FRONT, {-0.5f}, {-0.5f}, {-0.5f}}, {0, {-0.5f}, {-0.5f}, {0.0f}}
11275 ok(compare_float(U1(cmp_h[i]).hx, U1(out_h[i]).hx, 4096)
11276 && compare_float(U2(cmp_h[i]).hy, U2(out_h[i]).hy, 4096)
11277 && compare_float(U3(cmp_h[i]).hz, U3(out_h[i]).hz, 4096)
11278 && cmp_h[i].dwFlags == out_h[i].dwFlags,
11279 "HVertex %u differs. Got %#x %f %f %f.\n", i,
11280 out_h[i].dwFlags, U1(out_h[i]).hx, U2(out_h[i]).hy, U3(out_h[i]).hz);
11282 /* No scheme has been found behind those return values. It seems to be
11283 * whatever data windows has when throwing the vertex away. Modify the
11284 * input test vertices to test this more. Depending on the input data
11285 * it can happen that the z coord gets written into y, or similar things. */
11286 if (0)
11288 static const struct vec4 cmp[] =
11290 {138.0f, 148.0f, 0.0f, 1.0f}, {143.0f, 143.0f, 1.0f, 1.0f}, { -1.0f, -1.0f, 0.5f, 1.0f},
11291 {140.5f, 145.5f, 0.5f, 1.0f}, { -0.5f, -0.5f, -0.5f, 1.0f}, {135.5f, 150.5f, 0.0f, 1.0f}
11293 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
11294 "Vertex %u differs. Got %f %f %f %f.\n", i,
11295 out[i].x, out[i].y, out[i].z, out[i].w);
11299 transformdata.lpIn = cliptest;
11300 transformdata.dwInSize = sizeof(cliptest[0]);
11301 offscreen = 0xdeadbeef;
11302 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
11303 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11304 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11305 ok(!offscreen, "Offscreen is %x.\n", offscreen);
11306 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
11308 static const DWORD flags[] =
11311 D3DCLIP_RIGHT | D3DCLIP_BACK | D3DCLIP_TOP,
11313 D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
11315 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
11318 vp_data = vp_template;
11319 vp_data.dwWidth = 10;
11320 vp_data.dwHeight = 480;
11321 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
11322 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
11323 offscreen = 0xdeadbeef;
11324 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
11325 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11326 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11327 ok(!offscreen, "Offscreen is %x.\n", offscreen);
11328 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
11330 static const DWORD flags[] =
11332 D3DCLIP_RIGHT,
11333 D3DCLIP_RIGHT | D3DCLIP_BACK,
11334 D3DCLIP_LEFT,
11335 D3DCLIP_LEFT | D3DCLIP_FRONT,
11337 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
11340 vp_data = vp_template;
11341 vp_data.dwWidth = 256;
11342 vp_data.dwHeight = 256;
11343 vp_data.dvScaleX = 1;
11344 vp_data.dvScaleY = 1;
11345 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
11346 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
11347 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
11348 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11349 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11350 ok(!offscreen, "Offscreen is %x.\n", offscreen);
11351 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
11353 static const DWORD flags[] =
11356 D3DCLIP_BACK,
11358 D3DCLIP_FRONT,
11360 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
11363 /* Finally try to figure out how the DWORD dwOffscreen works.
11364 * It is a logical AND of the vertices' dwFlags members. */
11365 vp_data = vp_template;
11366 vp_data.dwWidth = 5;
11367 vp_data.dwHeight = 5;
11368 vp_data.dvScaleX = 10000.0f;
11369 vp_data.dvScaleY = 10000.0f;
11370 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
11371 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
11372 transformdata.lpIn = cliptest;
11373 offscreen = 0xdeadbeef;
11374 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
11375 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
11376 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11377 ok(!offscreen, "Offscreen is %x.\n", offscreen);
11379 offscreen = 0xdeadbeef;
11380 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
11381 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11382 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11383 ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
11384 offscreen = 0xdeadbeef;
11385 hr = IDirect3DViewport2_TransformVertices(viewport, 2,
11386 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11387 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11388 ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
11389 hr = IDirect3DViewport2_TransformVertices(viewport, 3,
11390 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11391 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11392 ok(!offscreen, "Offscreen is %x.\n", offscreen);
11394 transformdata.lpIn = cliptest + 1;
11395 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
11396 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11397 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11398 ok(offscreen == (D3DCLIP_BACK | D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
11400 transformdata.lpIn = cliptest + 2;
11401 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
11402 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11403 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11404 ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
11405 offscreen = 0xdeadbeef;
11406 hr = IDirect3DViewport2_TransformVertices(viewport, 2,
11407 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11408 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11409 ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
11411 transformdata.lpIn = cliptest + 3;
11412 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
11413 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11414 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11415 ok(offscreen == (D3DCLIP_FRONT | D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
11417 transformdata.lpIn = offscreentest;
11418 transformdata.dwInSize = sizeof(offscreentest[0]);
11419 vp_data = vp_template;
11420 vp_data.dwWidth = 257;
11421 vp_data.dwHeight = 257;
11422 vp_data.dvScaleX = 1.0f;
11423 vp_data.dvScaleY = 1.0f;
11424 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
11425 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
11426 offscreen = 0xdeadbeef;
11427 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
11428 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11429 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11430 ok(!offscreen, "Offscreen is %x.\n", offscreen);
11432 vp_data.dwWidth = 256;
11433 vp_data.dwHeight = 256;
11434 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
11435 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
11436 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
11437 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11438 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11439 ok(offscreen == D3DCLIP_RIGHT, "Offscreen is %x.\n", offscreen);
11441 /* Test the effect of Matrices.
11443 * Basically the x coordinate ends up as ((x + 1) * 2 + 0) * 5 and
11444 * y as ((y + 0) * 2 + 1) * 5. The 5 comes from dvScaleX/Y, 2 from
11445 * the view matrix and the +1's from the world and projection matrix. */
11446 vp_data.dwX = 0;
11447 vp_data.dwY = 0;
11448 vp_data.dwWidth = 256;
11449 vp_data.dwHeight = 256;
11450 vp_data.dvScaleX = 5.0f;
11451 vp_data.dvScaleY = 5.0f;
11452 vp_data.dvMinZ = 0.0f;
11453 vp_data.dvMaxZ = 1.0f;
11454 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
11455 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
11457 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat_translate1);
11458 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
11459 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat_scale);
11460 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
11461 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat_translate2);
11462 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
11464 transformdata.lpIn = position_tests;
11465 transformdata.dwInSize = sizeof(position_tests[0]);
11466 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
11467 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
11468 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11470 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
11472 static const struct vec4 cmp[] =
11474 {138.0f, 123.0f, 0.0f, 1.0f}, {148.0f, 113.0f, 2.0f, 1.0f}, {128.0f, 133.0f, -2.0f, 1.0f},
11475 {143.0f, 118.0f, 1.0f, 1.0f}, {133.0f, 128.0f, -1.0f, 1.0f}, {133.0f, 128.0f, 0.0f, 1.0f}
11478 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
11479 "Vertex %u differs. Got %f %f %f %f.\n", i,
11480 out[i].x, out[i].y, out[i].z, out[i].w);
11483 /* Invalid flags. */
11484 offscreen = 0xdeadbeef;
11485 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
11486 &transformdata, 0, &offscreen);
11487 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
11488 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
11490 /* NULL transform data. */
11491 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
11492 NULL, D3DTRANSFORM_UNCLIPPED, &offscreen);
11493 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
11494 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
11495 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
11496 NULL, D3DTRANSFORM_UNCLIPPED, &offscreen);
11497 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
11498 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
11500 /* NULL transform data and NULL dwOffscreen.
11502 * Valid transform data + NULL dwOffscreen -> crash. */
11503 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
11504 NULL, D3DTRANSFORM_UNCLIPPED, NULL);
11505 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
11507 /* No vertices. */
11508 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
11509 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
11510 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11511 ok(!offscreen, "Offscreen is %x.\n", offscreen);
11512 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
11513 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11514 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11515 ok(offscreen == ~0U, "Offscreen is %x.\n", offscreen);
11517 /* Invalid sizes. */
11518 offscreen = 0xdeadbeef;
11519 transformdata.dwSize = sizeof(transformdata) - 1;
11520 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
11521 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
11522 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
11523 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
11524 transformdata.dwSize = sizeof(transformdata) + 1;
11525 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
11526 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
11527 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
11528 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
11530 /* NULL lpIn or lpOut -> crash, except when transforming 0 vertices. */
11531 transformdata.dwSize = sizeof(transformdata);
11532 transformdata.lpIn = NULL;
11533 transformdata.lpOut = NULL;
11534 offscreen = 0xdeadbeef;
11535 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
11536 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11537 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11538 ok(offscreen == ~0U, "Offscreen is %x.\n", offscreen);
11540 /* Test how vertices are transformed during draws. */
11541 vp_data.dwX = 20;
11542 vp_data.dwY = 20;
11543 vp_data.dwWidth = 200;
11544 vp_data.dwHeight = 400;
11545 vp_data.dvScaleX = 20.0f;
11546 vp_data.dvScaleY = 50.0f;
11547 vp_data.dvMinZ = 0.0f;
11548 vp_data.dvMaxZ = 1.0f;
11549 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
11550 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
11551 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
11552 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
11554 ok(SUCCEEDED(hr), "Failed to clear the render target, hr %#x.\n", hr);
11555 background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 0.0f);
11556 viewport_set_background(device, viewport, background);
11557 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
11558 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
11560 hr = IDirect3DDevice2_BeginScene(device);
11561 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11562 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, 4, 0);
11563 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11564 hr = IDirect3DDevice2_EndScene(device);
11565 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11567 color = get_surface_color(rt, 128, 143);
11568 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
11569 color = get_surface_color(rt, 132, 143);
11570 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
11571 color = get_surface_color(rt, 128, 147);
11572 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
11573 color = get_surface_color(rt, 132, 147);
11574 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
11576 color = get_surface_color(rt, 177, 217);
11577 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
11578 color = get_surface_color(rt, 181, 217);
11579 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
11580 color = get_surface_color(rt, 177, 221);
11581 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
11582 color = get_surface_color(rt, 181, 221);
11583 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
11585 /* Test D3DVIEWPORT2 behavior. */
11586 vp2_data.dwSize = sizeof(vp2_data);
11587 vp2_data.dwX = 20;
11588 vp2_data.dwY = 20;
11589 vp2_data.dwWidth = 200;
11590 vp2_data.dwHeight = 400;
11591 vp2_data.dvClipX = -0.5f;
11592 vp2_data.dvClipY = 4.0f;
11593 vp2_data.dvClipWidth = 5.0f;
11594 vp2_data.dvClipHeight = 10.0f;
11595 vp2_data.dvMinZ = 0.0f;
11596 vp2_data.dvMaxZ = 2.0f;
11597 hr = IDirect3DViewport2_SetViewport2(viewport, &vp2_data);
11598 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
11599 transformdata.lpIn = position_tests;
11600 transformdata.lpOut = out;
11601 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
11602 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
11603 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11604 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
11606 static const struct vec4 cmp[] =
11608 {120.0f, 140.0f, 0.0f, 1.0f}, {200.0f, 60.0f, 1.0f, 1.0f}, {40.0f, 220.0f, -1.0f, 1.0f},
11609 {160.0f, 100.0f, 0.5f, 1.0f}, { 80.0f, 180.0f, -0.5f, 1.0f}, {80.0f, 180.0f, 0.0f, 1.0f}
11612 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
11613 "Vertex %u differs. Got %f %f %f %f.\n", i,
11614 out[i].x, out[i].y, out[i].z, out[i].w);
11617 memset(&mat, 0, sizeof(mat));
11618 mat.dwSize = sizeof(mat);
11619 U1(U(mat).diffuse).r = 0.0f;
11620 U2(U(mat).diffuse).g = 1.0f;
11621 U3(U(mat).diffuse).b = 0.0f;
11622 U4(U(mat).diffuse).a = 0.0f;
11623 hr = IDirect3DMaterial2_SetMaterial(background, &mat);
11624 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
11625 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
11626 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
11628 hr = IDirect3DDevice2_BeginScene(device);
11629 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11630 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, 4, 0);
11631 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11632 hr = IDirect3DDevice2_EndScene(device);
11633 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11635 color = get_surface_color(rt, 58, 118);
11636 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
11637 color = get_surface_color(rt, 62, 118);
11638 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
11639 color = get_surface_color(rt, 58, 122);
11640 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
11641 color = get_surface_color(rt, 62, 122);
11642 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
11644 color = get_surface_color(rt, 157, 177);
11645 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
11646 color = get_surface_color(rt, 161, 177);
11647 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
11648 color = get_surface_color(rt, 157, 181);
11649 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
11650 color = get_surface_color(rt, 161, 181);
11651 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
11653 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat_identity);
11654 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
11655 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat_identity);
11656 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
11657 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat_transform3);
11658 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
11660 vp2_data.dwX = 0.0;
11661 vp2_data.dwY = 0.0;
11662 vp2_data.dwWidth = 1;
11663 vp2_data.dwHeight = 1;
11664 vp2_data.dvClipX = -12.8f;
11665 vp2_data.dvClipY = 12.8f + mat_transform3._42 / mat_transform3._44;
11666 vp2_data.dvClipWidth = 25.6f;
11667 vp2_data.dvClipHeight = 25.6f;
11668 vp2_data.dvMinZ = 0.0f;
11669 vp2_data.dvMaxZ = 0.5f;
11670 hr = IDirect3DViewport2_SetViewport2(viewport, &vp2_data);
11671 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
11672 transformdata.lpIn = cliptest;
11673 transformdata.dwInSize = sizeof(cliptest[0]);
11674 offscreen = 0xdeadbeef;
11675 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
11676 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11677 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
11678 ok(!offscreen, "Offscreen is %x.\n", offscreen);
11679 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
11681 static const D3DHVERTEX cmp_h[] =
11683 {0, { 25.59f}, { 44.79f}, { 1.0f }},
11684 {D3DCLIP_RIGHT | D3DCLIP_TOP | D3DCLIP_BACK, { 25.61f}, { 44.81f}, { 1.01f}},
11685 {0, {-25.59f}, {-6.39f }, { 0.0f }},
11686 {D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,{-25.61f}, {-6.41f }, {-0.01f}},
11688 ok(compare_float(U1(cmp_h[i]).hx, U1(out_h[i]).hx, 4096)
11689 && compare_float(U2(cmp_h[i]).hy, U2(out_h[i]).hy, 4096)
11690 && compare_float(U3(cmp_h[i]).hz, U3(out_h[i]).hz, 4096)
11691 && cmp_h[i].dwFlags == out_h[i].dwFlags,
11692 "HVertex %u differs. Got %#x %f %f %f.\n", i,
11693 out_h[i].dwFlags, U1(out_h[i]).hx, U2(out_h[i]).hy, U3(out_h[i]).hz);
11696 IDirectDrawSurface_Release(rt);
11697 destroy_viewport(device, viewport);
11698 IDirect3DMaterial2_Release(background);
11699 refcount = IDirect3DDevice_Release(device);
11700 ok(!refcount, "Device has %u references left.\n", refcount);
11701 IDirectDraw2_Release(ddraw);
11702 DestroyWindow(window);
11705 static void test_display_mode_surface_pixel_format(void)
11707 unsigned int width, height, bpp;
11708 IDirectDrawSurface *surface;
11709 DDSURFACEDESC surface_desc;
11710 IDirectDraw2 *ddraw;
11711 ULONG refcount;
11712 HWND window;
11713 HRESULT hr;
11715 if (!(ddraw = create_ddraw()))
11717 skip("Failed to create ddraw.\n");
11718 return;
11721 surface_desc.dwSize = sizeof(surface_desc);
11722 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
11723 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
11724 width = surface_desc.dwWidth;
11725 height = surface_desc.dwHeight;
11727 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
11728 0, 0, width, height, NULL, NULL, NULL, NULL);
11729 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
11730 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11732 bpp = 0;
11733 if (SUCCEEDED(IDirectDraw2_SetDisplayMode(ddraw, width, height, 16, 0, 0)))
11734 bpp = 16;
11735 if (SUCCEEDED(IDirectDraw2_SetDisplayMode(ddraw, width, height, 24, 0, 0)))
11736 bpp = 24;
11737 if (SUCCEEDED(IDirectDraw2_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
11738 bpp = 32;
11739 ok(bpp, "Set display mode failed.\n");
11741 surface_desc.dwSize = sizeof(surface_desc);
11742 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
11743 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
11744 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
11745 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
11746 ok(U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
11747 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, bpp);
11749 memset(&surface_desc, 0, sizeof(surface_desc));
11750 surface_desc.dwSize = sizeof(surface_desc);
11751 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
11752 surface_desc.dwBackBufferCount = 1;
11753 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE;
11754 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11755 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
11756 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
11757 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
11758 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
11759 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
11760 ok(surface_desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
11761 surface_desc.ddpfPixelFormat.dwFlags);
11762 ok(U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
11763 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, bpp);
11764 IDirectDrawSurface_Release(surface);
11766 memset(&surface_desc, 0, sizeof(surface_desc));
11767 surface_desc.dwSize = sizeof(surface_desc);
11768 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
11769 surface_desc.dwWidth = width;
11770 surface_desc.dwHeight = height;
11771 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11772 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11773 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
11774 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
11775 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
11776 ok(surface_desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
11777 surface_desc.ddpfPixelFormat.dwFlags);
11778 ok(U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
11779 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, bpp);
11780 IDirectDrawSurface_Release(surface);
11782 refcount = IDirectDraw2_Release(ddraw);
11783 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
11784 DestroyWindow(window);
11787 static void test_surface_desc_size(void)
11789 union
11791 DWORD dwSize;
11792 DDSURFACEDESC desc1;
11793 DDSURFACEDESC2 desc2;
11794 BYTE blob[1024];
11795 } desc;
11796 IDirectDrawSurface7 *surface7;
11797 IDirectDrawSurface2 *surface2;
11798 IDirectDrawSurface *surface;
11799 DDSURFACEDESC surface_desc;
11800 HRESULT expected_hr, hr;
11801 IDirectDraw2 *ddraw;
11802 unsigned int i, j;
11803 ULONG refcount;
11805 static const struct
11807 unsigned int caps;
11808 const char *name;
11810 surface_caps[] =
11812 {DDSCAPS_OFFSCREENPLAIN, "offscreenplain"},
11813 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "systemmemory texture"},
11814 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "videomemory texture"},
11816 static const unsigned int desc_sizes[] =
11818 sizeof(DDSURFACEDESC),
11819 sizeof(DDSURFACEDESC2),
11820 sizeof(DDSURFACEDESC) + 1,
11821 sizeof(DDSURFACEDESC2) + 1,
11822 2 * sizeof(DDSURFACEDESC),
11823 2 * sizeof(DDSURFACEDESC2),
11824 sizeof(DDSURFACEDESC) - 1,
11825 sizeof(DDSURFACEDESC2) - 1,
11826 sizeof(DDSURFACEDESC) / 2,
11827 sizeof(DDSURFACEDESC2) / 2,
11831 sizeof(desc) / 2,
11832 sizeof(desc) - 100,
11835 if (!(ddraw = create_ddraw()))
11837 skip("Failed to create ddraw.\n");
11838 return;
11840 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
11841 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11843 for (i = 0; i < ARRAY_SIZE(surface_caps); ++i)
11845 memset(&surface_desc, 0, sizeof(surface_desc));
11846 surface_desc.dwSize = sizeof(surface_desc);
11847 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
11848 surface_desc.ddsCaps.dwCaps = surface_caps[i].caps;
11849 surface_desc.dwHeight = 128;
11850 surface_desc.dwWidth = 128;
11851 if (FAILED(IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11853 skip("Failed to create surface, type %s.\n", surface_caps[i].name);
11854 continue;
11856 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface2, (void **)&surface2);
11857 ok(hr == DD_OK, "Failed to query IDirectDrawSurface2, hr %#x, type %s.\n", hr, surface_caps[i].name);
11858 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface7, (void **)&surface7);
11859 ok(hr == DD_OK, "Failed to query IDirectDrawSurface7, hr %#x, type %s.\n", hr, surface_caps[i].name);
11861 /* GetSurfaceDesc() */
11862 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
11864 memset(&desc, 0, sizeof(desc));
11865 desc.dwSize = desc_sizes[j];
11866 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
11867 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc.desc1);
11868 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
11869 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
11871 memset(&desc, 0, sizeof(desc));
11872 desc.dwSize = desc_sizes[j];
11873 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
11874 hr = IDirectDrawSurface2_GetSurfaceDesc(surface2, &desc.desc1);
11875 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
11876 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
11878 memset(&desc, 0, sizeof(desc));
11879 desc.dwSize = desc_sizes[j];
11880 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC2) ? DD_OK : DDERR_INVALIDPARAMS;
11881 hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
11882 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
11883 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
11886 /* Lock() */
11887 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
11889 const BOOL valid_size = desc_sizes[j] == sizeof(DDSURFACEDESC)
11890 || desc_sizes[j] == sizeof(DDSURFACEDESC2);
11891 DWORD expected_texture_stage;
11893 memset(&desc, 0, sizeof(desc));
11894 desc.dwSize = desc_sizes[j];
11895 desc.desc2.dwTextureStage = 0xdeadbeef;
11896 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
11897 hr = IDirectDrawSurface_Lock(surface, NULL, &desc.desc1, 0, 0);
11898 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
11899 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
11900 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
11901 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
11902 desc_sizes[j], desc.dwSize, surface_caps[i].name);
11903 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
11904 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
11905 if (SUCCEEDED(hr))
11907 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
11908 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
11909 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
11910 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
11911 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
11912 todo_wine_if(!expected_texture_stage)
11913 ok(desc.desc2.dwTextureStage == expected_texture_stage,
11914 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
11915 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
11916 IDirectDrawSurface_Unlock(surface, NULL);
11919 memset(&desc, 0, sizeof(desc));
11920 desc.dwSize = desc_sizes[j];
11921 desc.desc2.dwTextureStage = 0xdeadbeef;
11922 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
11923 hr = IDirectDrawSurface2_Lock(surface2, NULL, &desc.desc1, 0, 0);
11924 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
11925 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
11926 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
11927 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
11928 desc_sizes[j], desc.dwSize, surface_caps[i].name);
11929 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
11930 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
11931 if (SUCCEEDED(hr))
11933 ok(desc.desc2.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
11934 desc.desc2.dwWidth, desc_sizes[j], surface_caps[i].name);
11935 ok(desc.desc2.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
11936 desc.desc2.dwHeight, desc_sizes[j], surface_caps[i].name);
11937 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
11938 todo_wine_if(!expected_texture_stage)
11939 ok(desc.desc2.dwTextureStage == expected_texture_stage,
11940 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
11941 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
11942 IDirectDrawSurface2_Unlock(surface2, NULL);
11945 memset(&desc, 0, sizeof(desc));
11946 desc.dwSize = desc_sizes[j];
11947 desc.desc2.dwTextureStage = 0xdeadbeef;
11948 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
11949 hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
11950 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
11951 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
11952 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
11953 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
11954 desc_sizes[j], desc.dwSize, surface_caps[i].name);
11955 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
11956 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
11957 if (SUCCEEDED(hr))
11959 ok(desc.desc2.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
11960 desc.desc2.dwWidth, desc_sizes[j], surface_caps[i].name);
11961 ok(desc.desc2.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
11962 desc.desc2.dwHeight, desc_sizes[j], surface_caps[i].name);
11963 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
11964 ok(desc.desc2.dwTextureStage == expected_texture_stage,
11965 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
11966 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
11967 IDirectDrawSurface7_Unlock(surface7, NULL);
11971 IDirectDrawSurface7_Release(surface7);
11972 IDirectDrawSurface2_Release(surface2);
11973 IDirectDrawSurface_Release(surface);
11976 /* GetDisplayMode() */
11977 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
11979 memset(&desc, 0xcc, sizeof(desc));
11980 desc.dwSize = desc_sizes[j];
11981 expected_hr = (desc.dwSize == sizeof(DDSURFACEDESC) || desc.dwSize == sizeof(DDSURFACEDESC2))
11982 ? DD_OK : DDERR_INVALIDPARAMS;
11983 hr = IDirectDraw2_GetDisplayMode(ddraw, &desc.desc1);
11984 ok(hr == expected_hr, "Got hr %#x, expected %#x, size %u.\n", hr, expected_hr, desc_sizes[j]);
11985 if (SUCCEEDED(hr))
11987 ok(desc.dwSize == sizeof(DDSURFACEDESC), "Wrong size %u for %u.\n", desc.dwSize, desc_sizes[j]);
11988 ok(desc.blob[desc_sizes[j]] == 0xcc, "Overflow for size %u.\n", desc_sizes[j]);
11989 ok(desc.blob[desc_sizes[j] - 1] != 0xcc, "Struct not cleared for size %u.\n", desc_sizes[j]);
11993 refcount = IDirectDraw2_Release(ddraw);
11994 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
11997 static void test_ck_operation(void)
11999 IDirectDrawSurface2 *src, *dst;
12000 IDirectDrawSurface7 *src7, *dst7;
12001 IDirectDrawSurface *surface1;
12002 DDSURFACEDESC surface_desc;
12003 IDirectDraw2 *ddraw;
12004 ULONG refcount;
12005 HWND window;
12006 HRESULT hr;
12007 D3DCOLOR *color;
12008 unsigned int i;
12009 DDCOLORKEY ckey;
12010 DDBLTFX fx;
12012 window = create_window();
12013 ddraw = create_ddraw();
12014 ok(!!ddraw, "Failed to create a ddraw object.\n");
12015 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12016 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12018 memset(&surface_desc, 0, sizeof(surface_desc));
12019 surface_desc.dwSize = sizeof(surface_desc);
12020 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12021 surface_desc.dwWidth = 4;
12022 surface_desc.dwHeight = 1;
12023 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12024 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
12025 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
12026 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
12027 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
12028 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
12029 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
12030 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12031 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&dst);
12032 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface2, hr %#x.\n", hr);
12033 IDirectDrawSurface_Release(surface1);
12035 surface_desc.dwFlags |= DDSD_CKSRCBLT;
12036 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff00ff;
12037 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff00ff;
12038 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
12039 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12040 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&src);
12041 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface2, hr %#x.\n", hr);
12042 IDirectDrawSurface_Release(surface1);
12044 hr = IDirectDrawSurface2_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12045 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12046 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
12047 color = surface_desc.lpSurface;
12048 color[0] = 0x77010203;
12049 color[1] = 0x00010203;
12050 color[2] = 0x77ff00ff;
12051 color[3] = 0x00ff00ff;
12052 hr = IDirectDrawSurface2_Unlock(src, NULL);
12053 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12055 for (i = 0; i < 2; ++i)
12057 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12058 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12059 color = surface_desc.lpSurface;
12060 color[0] = 0xcccccccc;
12061 color[1] = 0xcccccccc;
12062 color[2] = 0xcccccccc;
12063 color[3] = 0xcccccccc;
12064 hr = IDirectDrawSurface2_Unlock(dst, NULL);
12065 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12067 if (i)
12069 hr = IDirectDrawSurface2_BltFast(dst, 0, 0, src, NULL, DDBLTFAST_SRCCOLORKEY);
12070 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12072 else
12074 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, NULL);
12075 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12078 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT | DDLOCK_READONLY, NULL);
12079 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12080 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
12081 color = surface_desc.lpSurface;
12082 /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
12083 * color keying, but copy it to the destination surface. Others (sysmem surfaces) apply it for
12084 * color keying, but do not copy it into the destination surface. Nvidia neither uses it for
12085 * color keying nor copies it. */
12086 ok((color[0] == 0x77010203 && color[1] == 0x00010203
12087 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* AMD, Wine */
12088 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
12089 && color[2] == 0x00ff00ff && color[3] == 0xcccccccc) /* Sysmem surfaces? */
12090 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
12091 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Nvidia */
12092 || broken(color[0] == 0xff010203 && color[1] == 0xff010203
12093 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Testbot */,
12094 "Destination data after blitting is %08x %08x %08x %08x, i=%u.\n",
12095 color[0], color[1], color[2], color[3], i);
12096 hr = IDirectDrawSurface2_Unlock(dst, NULL);
12097 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12100 hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12101 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12102 ok(ckey.dwColorSpaceLowValue == 0x00ff00ff && ckey.dwColorSpaceHighValue == 0x00ff00ff,
12103 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12105 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
12106 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12107 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12109 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
12110 hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12111 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12112 ok(ckey.dwColorSpaceLowValue == 0x0000ff00 && ckey.dwColorSpaceHighValue == 0x0000ff00,
12113 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12115 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0;
12116 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0;
12117 hr = IDirectDrawSurface2_GetSurfaceDesc(src, &surface_desc);
12118 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
12119 ok(surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0x0000ff00
12120 && surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0x0000ff00,
12121 "Got unexpected color key low=%08x high=%08x.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue,
12122 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue);
12124 /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */
12125 ckey.dwColorSpaceLowValue = 0x000000ff;
12126 ckey.dwColorSpaceHighValue = 0x00000000;
12127 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12128 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12130 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
12131 hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12132 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12133 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
12134 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12136 ckey.dwColorSpaceLowValue = 0x000000ff;
12137 ckey.dwColorSpaceHighValue = 0x00000001;
12138 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12139 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12141 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
12142 hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12143 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12144 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
12145 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12147 ckey.dwColorSpaceLowValue = 0x000000fe;
12148 ckey.dwColorSpaceHighValue = 0x000000fd;
12149 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12150 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12152 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
12153 hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12154 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12155 ok(ckey.dwColorSpaceLowValue == 0x000000fe && ckey.dwColorSpaceHighValue == 0x000000fe,
12156 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12158 IDirectDrawSurface2_Release(src);
12159 IDirectDrawSurface2_Release(dst);
12161 /* Test source and destination keys and where they are read from. Use a surface with alpha
12162 * to avoid driver-dependent content in the X channel. */
12163 memset(&surface_desc, 0, sizeof(surface_desc));
12164 surface_desc.dwSize = sizeof(surface_desc);
12165 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12166 surface_desc.dwWidth = 6;
12167 surface_desc.dwHeight = 1;
12168 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12169 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
12170 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
12171 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
12172 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
12173 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
12174 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
12175 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
12176 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12177 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&dst);
12178 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface2, hr %#x.\n", hr);
12179 IDirectDrawSurface_Release(surface1);
12181 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
12182 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12183 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&src);
12184 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface2, hr %#x.\n", hr);
12185 IDirectDrawSurface_Release(surface1);
12187 ckey.dwColorSpaceLowValue = 0x0000ff00;
12188 ckey.dwColorSpaceHighValue = 0x0000ff00;
12189 hr = IDirectDrawSurface2_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
12190 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12191 ckey.dwColorSpaceLowValue = 0x00ff0000;
12192 ckey.dwColorSpaceHighValue = 0x00ff0000;
12193 hr = IDirectDrawSurface2_SetColorKey(dst, DDCKEY_DESTBLT, &ckey);
12194 ok(SUCCEEDED(hr) || hr == DDERR_NOCOLORKEYHW, "Failed to set color key, hr %#x.\n", hr);
12195 if (FAILED(hr))
12197 /* Nvidia reject dest keys, AMD allows them. This applies to vidmem and sysmem surfaces. */
12198 skip("Failed to set destination color key, skipping related tests.\n");
12199 goto done;
12202 ckey.dwColorSpaceLowValue = 0x000000ff;
12203 ckey.dwColorSpaceHighValue = 0x000000ff;
12204 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12205 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12206 ckey.dwColorSpaceLowValue = 0x000000aa;
12207 ckey.dwColorSpaceHighValue = 0x000000aa;
12208 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_DESTBLT, &ckey);
12209 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12211 memset(&fx, 0, sizeof(fx));
12212 fx.dwSize = sizeof(fx);
12213 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x00110000;
12214 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x00110000;
12215 fx.ddckDestColorkey.dwColorSpaceHighValue = 0x00001100;
12216 fx.ddckDestColorkey.dwColorSpaceLowValue = 0x00001100;
12218 hr = IDirectDrawSurface2_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12219 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12220 color = surface_desc.lpSurface;
12221 color[0] = 0x000000ff; /* Applies to src blt key in src surface. */
12222 color[1] = 0x000000aa; /* Applies to dst blt key in src surface. */
12223 color[2] = 0x00ff0000; /* Dst color key in dst surface. */
12224 color[3] = 0x0000ff00; /* Src color key in dst surface. */
12225 color[4] = 0x00001100; /* Src color key in ddbltfx. */
12226 color[5] = 0x00110000; /* Dst color key in ddbltfx. */
12227 hr = IDirectDrawSurface2_Unlock(src, NULL);
12228 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12230 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12231 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12232 color = surface_desc.lpSurface;
12233 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
12234 hr = IDirectDrawSurface2_Unlock(dst, NULL);
12235 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12237 /* Test a blit without keying. */
12238 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, 0, &fx);
12239 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12241 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12242 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12243 color = surface_desc.lpSurface;
12244 /* Should have copied src data unmodified to dst. */
12245 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
12246 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
12247 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12248 color[0], color[1], color[2], color[3], color[4], color[5]);
12250 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
12251 hr = IDirectDrawSurface2_Unlock(dst, NULL);
12252 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12254 /* Src key. */
12255 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
12256 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12258 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12259 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12260 color = surface_desc.lpSurface;
12261 /* Src key applied to color[0]. It is unmodified, the others are copied. */
12262 ok(color[0] == 0x55555555 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
12263 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
12264 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12265 color[0], color[1], color[2], color[3], color[4], color[5]);
12267 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
12268 hr = IDirectDrawSurface2_Unlock(dst, NULL);
12269 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12271 /* Src override. */
12272 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
12273 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12275 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12276 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12277 color = surface_desc.lpSurface;
12278 /* Override key applied to color[5]. It is unmodified, the others are copied. */
12279 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
12280 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x55555555,
12281 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12282 color[0], color[1], color[2], color[3], color[4], color[5]);
12284 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
12285 hr = IDirectDrawSurface2_Unlock(dst, NULL);
12286 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12288 /* Src override AND src key. That is not supposed to work. */
12289 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx);
12290 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
12292 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12293 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12294 color = surface_desc.lpSurface;
12295 /* Ensure the destination was not changed. */
12296 ok(color[0] == 0x55555555 && color[1] == 0x55555555 && color[2] == 0x55555555 &&
12297 color[3] == 0x55555555 && color[4] == 0x55555555 && color[5] == 0x55555555,
12298 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12299 color[0], color[1], color[2], color[3], color[4], color[5]);
12301 /* Use different dst colors for the dst key test. */
12302 color[0] = 0x00ff0000; /* Dest key in dst surface. */
12303 color[1] = 0x00ff0000; /* Dest key in dst surface. */
12304 color[2] = 0x00001100; /* Dest key in override. */
12305 color[3] = 0x00001100; /* Dest key in override. */
12306 color[4] = 0x000000aa; /* Dest key in src surface. */
12307 color[5] = 0x000000aa; /* Dest key in src surface. */
12308 hr = IDirectDrawSurface2_Unlock(dst, NULL);
12309 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12311 /* Dest key blit. The key is taken from the SOURCE surface in v2! */
12312 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
12313 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12315 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12316 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12317 color = surface_desc.lpSurface;
12318 /* Dst key applied to color[4,5], they are the only changed pixels. */
12319 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
12320 color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000,
12321 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12322 color[0], color[1], color[2], color[3], color[4], color[5]);
12324 color[0] = 0x00ff0000; /* Dest key in dst surface. */
12325 color[1] = 0x00ff0000; /* Dest key in dst surface. */
12326 color[2] = 0x00001100; /* Dest key in override. */
12327 color[3] = 0x00001100; /* Dest key in override. */
12328 color[4] = 0x000000aa; /* Dest key in src surface. */
12329 color[5] = 0x000000aa; /* Dest key in src surface. */
12330 hr = IDirectDrawSurface2_Unlock(dst, NULL);
12331 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12333 /* What happens with a QI'd newer version of the interface? It takes the key
12334 * from the destination surface. */
12335 hr = IDirectDrawSurface2_QueryInterface(src, &IID_IDirectDrawSurface7, (void **)&src7);
12336 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
12337 hr = IDirectDrawSurface2_QueryInterface(dst, &IID_IDirectDrawSurface7, (void **)&dst7);
12338 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
12340 hr = IDirectDrawSurface7_Blt(dst7, NULL, src7, NULL, DDBLT_KEYDEST, &fx);
12341 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12343 IDirectDrawSurface7_Release(dst7);
12344 IDirectDrawSurface7_Release(src7);
12346 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12347 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12348 color = surface_desc.lpSurface;
12349 /* Dst key applied to color[0,1], they are the only changed pixels. */
12350 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
12351 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
12352 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12353 color[0], color[1], color[2], color[3], color[4], color[5]);
12355 color[0] = 0x00ff0000; /* Dest key in dst surface. */
12356 color[1] = 0x00ff0000; /* Dest key in dst surface. */
12357 color[2] = 0x00001100; /* Dest key in override. */
12358 color[3] = 0x00001100; /* Dest key in override. */
12359 color[4] = 0x000000aa; /* Dest key in src surface. */
12360 color[5] = 0x000000aa; /* Dest key in src surface. */
12361 hr = IDirectDrawSurface2_Unlock(dst, NULL);
12362 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12364 /* Dest override key blit. */
12365 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
12366 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12368 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12369 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12370 color = surface_desc.lpSurface;
12371 /* Dst key applied to color[2,3], they are the only changed pixels. */
12372 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00ff0000 &&
12373 color[3] == 0x0000ff00 && color[4] == 0x000000aa && color[5] == 0x000000aa,
12374 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12375 color[0], color[1], color[2], color[3], color[4], color[5]);
12377 color[0] = 0x00ff0000; /* Dest key in dst surface. */
12378 color[1] = 0x00ff0000; /* Dest key in dst surface. */
12379 color[2] = 0x00001100; /* Dest key in override. */
12380 color[3] = 0x00001100; /* Dest key in override. */
12381 color[4] = 0x000000aa; /* Dest key in src surface. */
12382 color[5] = 0x000000aa; /* Dest key in src surface. */
12383 hr = IDirectDrawSurface2_Unlock(dst, NULL);
12384 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12386 /* Dest override together with surface key. Supposed to fail. */
12387 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx);
12388 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
12390 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12391 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12392 color = surface_desc.lpSurface;
12393 /* Destination is unchanged. */
12394 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
12395 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
12396 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12397 color[0], color[1], color[2], color[3], color[4], color[5]);
12398 hr = IDirectDrawSurface2_Unlock(dst, NULL);
12399 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12401 /* Source and destination key. This is driver dependent. New HW treats it like
12402 * DDBLT_KEYSRC. Older HW and some software renderers apply both keys. */
12403 if (0)
12405 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx);
12406 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12408 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12409 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12410 color = surface_desc.lpSurface;
12411 /* Color[0] is filtered by the src key, 2-5 are filtered by the dst key, if
12412 * the driver applies it. */
12413 ok(color[0] == 0x00ff0000 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
12414 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
12415 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12416 color[0], color[1], color[2], color[3], color[4], color[5]);
12418 color[0] = 0x00ff0000; /* Dest key in dst surface. */
12419 color[1] = 0x00ff0000; /* Dest key in dst surface. */
12420 color[2] = 0x00001100; /* Dest key in override. */
12421 color[3] = 0x00001100; /* Dest key in override. */
12422 color[4] = 0x000000aa; /* Dest key in src surface. */
12423 color[5] = 0x000000aa; /* Dest key in src surface. */
12424 hr = IDirectDrawSurface2_Unlock(dst, NULL);
12425 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12428 /* Override keys without ddbltfx parameter fail */
12429 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, NULL);
12430 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
12431 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, NULL);
12432 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
12434 /* Try blitting without keys in the source surface. */
12435 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, NULL);
12436 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12437 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_DESTBLT, NULL);
12438 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12440 /* That fails now. Do not bother to check that the data is unmodified. */
12441 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
12442 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
12444 /* Surprisingly this still works. It uses the old key from the src surface. */
12445 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
12446 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12448 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12449 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12450 color = surface_desc.lpSurface;
12451 /* Dst key applied to color[4,5], they are the only changed pixels. */
12452 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
12453 color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000,
12454 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12455 color[0], color[1], color[2], color[3], color[4], color[5]);
12456 hr = IDirectDrawSurface2_Unlock(dst, NULL);
12457 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12459 /* This returns DDERR_NOCOLORKEY as expected. */
12460 hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_DESTBLT, &ckey);
12461 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
12463 /* GetSurfaceDesc returns a zeroed key as expected. */
12464 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x12345678;
12465 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x12345678;
12466 hr = IDirectDrawSurface2_GetSurfaceDesc(src, &surface_desc);
12467 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
12468 ok(!surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue
12469 && !surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue,
12470 "Got unexpected color key low=%08x high=%08x.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue,
12471 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue);
12473 /* Try blitting without keys in the destination surface. */
12474 hr = IDirectDrawSurface2_SetColorKey(dst, DDCKEY_SRCBLT, NULL);
12475 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12476 hr = IDirectDrawSurface2_SetColorKey(dst, DDCKEY_DESTBLT, NULL);
12477 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12479 /* This fails, as sanity would dictate. */
12480 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
12481 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
12483 done:
12484 IDirectDrawSurface2_Release(src);
12485 IDirectDrawSurface2_Release(dst);
12486 refcount = IDirectDraw2_Release(ddraw);
12487 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
12488 DestroyWindow(window);
12491 static void test_set_render_state(void)
12493 IDirect3DDevice2 *device;
12494 IDirectDraw2 *ddraw;
12495 ULONG refcount;
12496 HWND window;
12497 DWORD state;
12498 HRESULT hr;
12500 window = create_window();
12501 ddraw = create_ddraw();
12502 ok(!!ddraw, "Failed to create a ddraw object.\n");
12503 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
12505 skip("Failed to create 3D device.\n");
12506 DestroyWindow(window);
12507 return;
12510 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, TRUE);
12511 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
12512 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, FALSE);
12513 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
12515 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
12516 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
12517 state = 0xdeadbeef;
12518 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, &state);
12519 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
12520 ok(!state, "Got unexpected render state %#x.\n", state);
12521 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
12522 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
12523 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, &state);
12524 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
12525 ok(state == D3DTBLEND_MODULATE, "Got unexpected render state %#x.\n", state);
12527 refcount = IDirect3DDevice2_Release(device);
12528 ok(!refcount, "Device has %u references left.\n", refcount);
12529 refcount = IDirectDraw2_Release(ddraw);
12530 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
12531 DestroyWindow(window);
12534 static void test_depth_readback(void)
12536 DWORD depth, expected_depth, max_diff, passed_fmts = 0;
12537 IDirect3DMaterial2 *blue_background;
12538 IDirectDrawSurface *rt, *ds;
12539 IDirect3DViewport2 *viewport;
12540 DDSURFACEDESC surface_desc;
12541 IDirect3DDevice2 *device;
12542 unsigned int i, x, y;
12543 IDirectDraw2 *ddraw;
12544 ULONG refcount;
12545 HWND window;
12546 HRESULT hr;
12547 void *ptr;
12548 BOOL all_pass;
12550 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
12551 static D3DLVERTEX quad[] =
12553 {{-1.0f}, {-1.0f}, {0.1f}, 0, {0xff00ff00}},
12554 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
12555 {{ 1.0f}, {-1.0f}, {1.0f}, 0, {0xff00ff00}},
12556 {{ 1.0f}, { 1.0f}, {0.9f}, 0, {0xff00ff00}},
12559 static const struct
12561 unsigned int z_depth, z_mask;
12563 tests[] =
12565 {16, 0x0000ffff},
12566 {24, 0x00ffffff},
12567 {32, 0xffffffff},
12570 window = create_window();
12571 ok(!!window, "Failed to create a window.\n");
12572 ddraw = create_ddraw();
12573 ok(!!ddraw, "Failed to create a ddraw object.\n");
12574 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
12576 skip("Failed to create a D3D device, skipping tests.\n");
12577 IDirectDraw2_Release(ddraw);
12578 DestroyWindow(window);
12579 return;
12582 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
12583 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
12584 blue_background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
12585 viewport = create_viewport(device, 0, 0, 640, 480);
12586 viewport_set_background(device, viewport, blue_background);
12587 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
12588 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
12590 ds = get_depth_stencil(device);
12591 hr = IDirectDrawSurface_DeleteAttachedSurface(rt, 0, ds);
12592 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
12593 IDirectDrawSurface_Release(ds);
12595 for (i = 0; i < ARRAY_SIZE(tests); ++i)
12597 memset(&surface_desc, 0, sizeof(surface_desc));
12598 surface_desc.dwSize = sizeof(surface_desc);
12599 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
12600 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
12601 U2(surface_desc).dwZBufferBitDepth = tests[i].z_depth;
12602 surface_desc.dwWidth = 640;
12603 surface_desc.dwHeight = 480;
12604 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
12605 if (FAILED(hr))
12607 skip("Format %u not supported, skipping test.\n", i);
12608 continue;
12611 hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
12612 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
12613 hr = IDirect3DDevice2_SetRenderTarget(device, rt, 0);
12614 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
12616 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
12617 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12618 hr = IDirect3DDevice2_BeginScene(device);
12619 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12620 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, 4, 0);
12621 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12622 hr = IDirect3DDevice2_EndScene(device);
12623 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12625 memset(&surface_desc, 0, sizeof(surface_desc));
12626 surface_desc.dwSize = sizeof(surface_desc);
12627 hr = IDirectDrawSurface_Lock(ds, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12628 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12630 all_pass = TRUE;
12631 for (y = 60; y < 480; y += 120)
12633 for (x = 80; x < 640; x += 160)
12635 ptr = (BYTE *)surface_desc.lpSurface
12636 + y * U1(surface_desc).lPitch
12637 + x * (tests[i].z_depth == 16 ? 2 : 4);
12638 depth = *((DWORD *)ptr) & tests[i].z_mask;
12639 expected_depth = (x * (0.9 / 640.0) + y * (0.1 / 480.0)) * tests[i].z_mask;
12640 max_diff = ((0.5f * 0.9f) / 640.0f) * tests[i].z_mask;
12641 /* The ddraw2 version of this test behaves similarly to the ddraw7 version on Nvidia GPUs,
12642 * except that we only have D16 (broken on geforce 9) and D24X8 (broken on geforce 7) available.
12643 * Accept all nvidia GPUs as broken here, but still expect one of the formats to pass. */
12644 ok(abs(expected_depth - depth) <= max_diff || ddraw_is_nvidia(ddraw),
12645 "Test %u: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n",
12646 i, depth, expected_depth - depth, expected_depth, max_diff, x, y);
12647 if (abs(expected_depth - depth) > max_diff)
12648 all_pass = FALSE;
12652 hr = IDirectDrawSurface_Unlock(ds, NULL);
12653 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12655 if (all_pass)
12656 passed_fmts++;
12658 hr = IDirectDrawSurface_DeleteAttachedSurface(rt, 0, ds);
12659 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
12660 IDirectDrawSurface_Release(ds);
12663 ok(passed_fmts, "Not a single format passed the tests, this is bad even by Nvidia's standards.\n");
12665 destroy_viewport(device, viewport);
12666 destroy_material(blue_background);
12667 IDirectDrawSurface_Release(rt);
12668 refcount = IDirect3DDevice2_Release(device);
12669 ok(!refcount, "Device has %u references left.\n", refcount);
12670 IDirectDraw2_Release(ddraw);
12671 DestroyWindow(window);
12674 static void test_clear(void)
12676 D3DRECT rect_negneg, rect_full = {{0}, {0}, {640}, {480}};
12677 IDirect3DViewport2 *viewport, *viewport2, *viewport3;
12678 IDirect3DMaterial2 *white, *red, *green, *blue;
12679 IDirect3DDevice2 *device;
12680 IDirectDrawSurface *rt;
12681 IDirectDraw2 *ddraw;
12682 D3DRECT rect[2];
12683 D3DCOLOR color;
12684 ULONG refcount;
12685 HWND window;
12686 HRESULT hr;
12688 window = create_window();
12689 ddraw = create_ddraw();
12690 ok(!!ddraw, "Failed to create a ddraw object.\n");
12691 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
12693 skip("Failed to create a 3D device, skipping test.\n");
12694 IDirectDraw2_Release(ddraw);
12695 DestroyWindow(window);
12696 return;
12698 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
12699 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
12701 viewport = create_viewport(device, 0, 0, 640, 480);
12702 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
12703 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
12705 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
12706 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
12707 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
12708 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
12710 viewport_set_background(device, viewport, white);
12711 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
12712 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12714 /* Positive x, negative y. */
12715 U1(rect[0]).x1 = 0;
12716 U2(rect[0]).y1 = 480;
12717 U3(rect[0]).x2 = 320;
12718 U4(rect[0]).y2 = 240;
12720 /* Positive x, positive y. */
12721 U1(rect[1]).x1 = 0;
12722 U2(rect[1]).y1 = 0;
12723 U3(rect[1]).x2 = 320;
12724 U4(rect[1]).y2 = 240;
12726 /* Clear 2 rectangles with one call. Unlike d3d8/9, the refrast does not
12727 * refuse negative rectangles, but it will not clear them either. */
12728 viewport_set_background(device, viewport, red);
12729 hr = IDirect3DViewport2_Clear(viewport, 2, rect, D3DCLEAR_TARGET);
12730 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12732 color = get_surface_color(rt, 160, 360);
12733 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 3 (pos, neg) has color 0x%08x.\n", color);
12734 color = get_surface_color(rt, 160, 120);
12735 ok(compare_color(color, 0x00ff0000, 0), "Clear rectangle 1 (pos, pos) has color 0x%08x.\n", color);
12736 color = get_surface_color(rt, 480, 360);
12737 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (NULL) has color 0x%08x.\n", color);
12738 color = get_surface_color(rt, 480, 120);
12739 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (neg, neg) has color 0x%08x.\n", color);
12741 viewport_set_background(device, viewport, white);
12742 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
12743 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12745 /* negative x, negative y.
12746 * Also ignored, except on WARP, which clears the entire screen. */
12747 U1(rect_negneg).x1 = 640;
12748 U2(rect_negneg).y1 = 240;
12749 U3(rect_negneg).x2 = 320;
12750 U4(rect_negneg).y2 = 0;
12751 viewport_set_background(device, viewport, green);
12752 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_negneg, D3DCLEAR_TARGET);
12753 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12755 color = get_surface_color(rt, 160, 360);
12756 ok(compare_color(color, 0x00ffffff, 0)
12757 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
12758 "Got unexpected color 0x%08x.\n", color);
12759 color = get_surface_color(rt, 160, 120);
12760 ok(compare_color(color, 0x00ffffff, 0)
12761 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
12762 "Got unexpected color 0x%08x.\n", color);
12763 color = get_surface_color(rt, 480, 360);
12764 ok(compare_color(color, 0x00ffffff, 0)
12765 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
12766 "Got unexpected color 0x%08x.\n", color);
12767 color = get_surface_color(rt, 480, 120);
12768 ok(compare_color(color, 0x00ffffff, 0)
12769 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
12770 "Got unexpected color 0x%08x.\n", color);
12772 /* Test how the viewport affects clears. */
12773 viewport_set_background(device, viewport, white);
12774 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
12775 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12777 viewport2 = create_viewport(device, 160, 120, 160, 120);
12778 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport2);
12779 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
12781 viewport_set_background(device, viewport2, blue);
12782 hr = IDirect3DViewport2_Clear(viewport2, 1, &rect_full, D3DCLEAR_TARGET);
12783 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12785 viewport3 = create_viewport(device, 320, 240, 320, 240);
12786 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport3);
12787 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
12789 U1(rect[0]).x1 = 160;
12790 U2(rect[0]).y1 = 120;
12791 U3(rect[0]).x2 = 480;
12792 U4(rect[0]).y2 = 360;
12793 viewport_set_background(device, viewport3, green);
12794 hr = IDirect3DViewport2_Clear(viewport3, 1, &rect[0], D3DCLEAR_TARGET);
12795 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12797 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
12798 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
12800 color = get_surface_color(rt, 158, 118);
12801 ok(compare_color(color, 0x00ffffff, 0), "(158, 118) has color 0x%08x.\n", color);
12802 color = get_surface_color(rt, 162, 118);
12803 ok(compare_color(color, 0x00ffffff, 0), "(162, 118) has color 0x%08x.\n", color);
12804 color = get_surface_color(rt, 158, 122);
12805 ok(compare_color(color, 0x00ffffff, 0), "(158, 122) has color 0x%08x.\n", color);
12806 color = get_surface_color(rt, 162, 122);
12807 ok(compare_color(color, 0x000000ff, 0), "(162, 122) has color 0x%08x.\n", color);
12809 color = get_surface_color(rt, 318, 238);
12810 ok(compare_color(color, 0x000000ff, 0), "(318, 238) has color 0x%08x.\n", color);
12811 color = get_surface_color(rt, 322, 238);
12812 ok(compare_color(color, 0x00ffffff, 0), "(322, 238) has color 0x%08x.\n", color);
12813 color = get_surface_color(rt, 318, 242);
12814 ok(compare_color(color, 0x00ffffff, 0), "(318, 242) has color 0x%08x.\n", color);
12815 color = get_surface_color(rt, 322, 242);
12816 ok(compare_color(color, 0x0000ff00, 0), "(322, 242) has color 0x%08x.\n", color);
12818 color = get_surface_color(rt, 478, 358);
12819 ok(compare_color(color, 0x0000ff00, 0), "(478, 358) has color 0x%08x.\n", color);
12820 color = get_surface_color(rt, 482, 358);
12821 ok(compare_color(color, 0x00ffffff, 0), "(482, 358) has color 0x%08x.\n", color);
12822 color = get_surface_color(rt, 478, 362);
12823 ok(compare_color(color, 0x00ffffff, 0), "(478, 362) has color 0x%08x.\n", color);
12824 color = get_surface_color(rt, 482, 362);
12825 ok(compare_color(color, 0x00ffffff, 0), "(482, 362) has color 0x%08x.\n", color);
12827 /* The clear rectangle is rendertarget absolute, not relative to the
12828 * viewport. */
12829 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
12830 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12831 U1(rect[0]).x1 = 330;
12832 U2(rect[0]).y1 = 250;
12833 U3(rect[0]).x2 = 340;
12834 U4(rect[0]).y2 = 260;
12835 hr = IDirect3DViewport2_Clear(viewport3, 1, &rect[0], D3DCLEAR_TARGET);
12836 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12838 color = get_surface_color(rt, 328, 248);
12839 ok(compare_color(color, 0x00ffffff, 0), "(328, 248) has color 0x%08x.\n", color);
12840 color = get_surface_color(rt, 332, 248);
12841 ok(compare_color(color, 0x00ffffff, 0), "(332, 248) has color 0x%08x.\n", color);
12842 color = get_surface_color(rt, 328, 252);
12843 ok(compare_color(color, 0x00ffffff, 0), "(328, 252) has color 0x%08x.\n", color);
12844 color = get_surface_color(rt, 332, 252);
12845 ok(compare_color(color, 0x0000ff00, 0), "(332, 252) has color 0x%08x.\n", color);
12847 color = get_surface_color(rt, 338, 248);
12848 ok(compare_color(color, 0x00ffffff, 0), "(338, 248) has color 0x%08x.\n", color);
12849 color = get_surface_color(rt, 342, 248);
12850 ok(compare_color(color, 0x00ffffff, 0), "(342, 248) has color 0x%08x.\n", color);
12851 color = get_surface_color(rt, 338, 252);
12852 ok(compare_color(color, 0x0000ff00, 0), "(338, 252) has color 0x%08x.\n", color);
12853 color = get_surface_color(rt, 342, 252);
12854 ok(compare_color(color, 0x00ffffff, 0), "(342, 252) has color 0x%08x.\n", color);
12856 color = get_surface_color(rt, 328, 258);
12857 ok(compare_color(color, 0x00ffffff, 0), "(328, 258) has color 0x%08x.\n", color);
12858 color = get_surface_color(rt, 332, 258);
12859 ok(compare_color(color, 0x0000ff00, 0), "(332, 258) has color 0x%08x.\n", color);
12860 color = get_surface_color(rt, 328, 262);
12861 ok(compare_color(color, 0x00ffffff, 0), "(328, 262) has color 0x%08x.\n", color);
12862 color = get_surface_color(rt, 332, 262);
12863 ok(compare_color(color, 0x00ffffff, 0), "(332, 262) has color 0x%08x.\n", color);
12865 color = get_surface_color(rt, 338, 258);
12866 ok(compare_color(color, 0x0000ff00, 0), "(338, 258) has color 0x%08x.\n", color);
12867 color = get_surface_color(rt, 342, 258);
12868 ok(compare_color(color, 0x00ffffff, 0), "(342, 258) has color 0x%08x.\n", color);
12869 color = get_surface_color(rt, 338, 262);
12870 ok(compare_color(color, 0x00ffffff, 0), "(338, 262) has color 0x%08x.\n", color);
12871 color = get_surface_color(rt, 342, 262);
12872 ok(compare_color(color, 0x00ffffff, 0), "(342, 262) has color 0x%08x.\n", color);
12874 /* COLORWRITEENABLE, SRGBWRITEENABLE and scissor rectangles do not exist
12875 * in d3d2. */
12877 IDirect3DViewport2_Release(viewport3);
12878 IDirect3DViewport2_Release(viewport2);
12879 IDirect3DViewport2_Release(viewport);
12880 IDirect3DMaterial2_Release(white);
12881 IDirect3DMaterial2_Release(red);
12882 IDirect3DMaterial2_Release(green);
12883 IDirect3DMaterial2_Release(blue);
12884 IDirectDrawSurface_Release(rt);
12885 refcount = IDirect3DDevice2_Release(device);
12886 ok(!refcount, "Device has %u references left.\n", refcount);
12887 refcount = IDirectDraw2_Release(ddraw);
12888 ok(!refcount, "Ddraw object has %u references left.\n", refcount);
12889 DestroyWindow(window);
12892 struct enum_surfaces_param
12894 IDirectDrawSurface *surfaces[8];
12895 unsigned int count;
12898 static HRESULT WINAPI enum_surfaces_cb(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
12900 struct enum_surfaces_param *param = context;
12901 BOOL found = FALSE;
12902 unsigned int i;
12904 for (i = 0; i < ARRAY_SIZE(param->surfaces); ++i)
12906 if (param->surfaces[i] == surface)
12908 found = TRUE;
12909 break;
12913 ok(found, "Unexpected surface %p enumerated.\n", surface);
12914 IDirectDrawSurface_Release(surface);
12915 ++param->count;
12917 return DDENUMRET_OK;
12920 static void test_enum_surfaces(void)
12922 struct enum_surfaces_param param = {{0}};
12923 IDirectDraw2 *ddraw;
12924 DDSURFACEDESC desc;
12925 HRESULT hr;
12927 ddraw = create_ddraw();
12928 ok(!!ddraw, "Failed to create a ddraw object.\n");
12930 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
12931 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12933 memset(&desc, 0, sizeof(desc));
12934 desc.dwSize = sizeof(desc);
12935 desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
12936 desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
12937 U2(desc).dwMipMapCount = 3;
12938 desc.dwWidth = 32;
12939 desc.dwHeight = 32;
12940 hr = IDirectDraw2_CreateSurface(ddraw, &desc, &param.surfaces[0], NULL);
12941 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
12943 hr = IDirectDrawSurface_GetAttachedSurface(param.surfaces[0], &desc.ddsCaps, &param.surfaces[1]);
12944 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
12945 hr = IDirectDrawSurface_GetAttachedSurface(param.surfaces[1], &desc.ddsCaps, &param.surfaces[2]);
12946 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
12947 hr = IDirectDrawSurface_GetAttachedSurface(param.surfaces[2], &desc.ddsCaps, &param.surfaces[3]);
12948 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
12949 ok(!param.surfaces[3], "Got unexpected pointer %p.\n", param.surfaces[3]);
12951 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
12952 &desc, &param, enum_surfaces_cb);
12953 ok(SUCCEEDED(hr), "Failed to enumerate surfaces, hr %#x.\n", hr);
12954 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
12956 param.count = 0;
12957 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
12958 NULL, &param, enum_surfaces_cb);
12959 ok(SUCCEEDED(hr), "Failed to enumerate surfaces, hr %#x.\n", hr);
12960 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
12962 IDirectDrawSurface_Release(param.surfaces[2]);
12963 IDirectDrawSurface_Release(param.surfaces[1]);
12964 IDirectDrawSurface_Release(param.surfaces[0]);
12965 IDirectDraw2_Release(ddraw);
12968 static void test_viewport(void)
12970 static struct
12972 D3DVIEWPORT7 vp;
12973 RECT expected_rect;
12974 const char *message;
12976 tests[] =
12978 {{ 0, 0, 640, 480}, { 0, 120, 479, 359}, "Viewport (0, 0) - (640, 480)"},
12979 {{ 0, 0, 320, 240}, { 0, 60, 239, 179}, "Viewport (0, 0) - (320, 240)"},
12980 {{ 0, 0, 1280, 960}, { 0, 240, 639, 479}, "Viewport (0, 0) - (1280, 960)"},
12981 {{ 0, 0, 2000, 1600}, { 0, 400, 639, 479}, "Viewport (0, 0) - (2000, 1600)"},
12982 {{100, 100, 640, 480}, {100, 220, 579, 459}, "Viewport (100, 100) - (640, 480)"},
12983 {{ 0, 0, 8192, 8192}, {-10, -10, -10, -10}, "Viewport (0, 0) - (8192, 8192)"},
12985 static const struct vec2 rt_sizes[] =
12987 {640, 480}, {1280, 960}, {320, 240}, {800, 600},
12989 static D3DMATRIX mat =
12991 1.0f, 0.0f, 0.0f, 0.0f,
12992 0.0f, 1.0f, 0.0f, 0.0f,
12993 0.0f, 0.0f, 1.0f, 0.0f,
12994 0.0f, 0.0f, 0.0f, 1.0f,
12996 static D3DLVERTEX quad[] =
12998 {{-1.5f}, {-0.5f}, {0.1f}, 0, {0xffffffff}},
12999 {{-1.5f}, { 0.5f}, {0.1f}, 0, {0xffffffff}},
13000 {{ 0.5f}, {-0.5f}, {0.1f}, 0, {0xffffffff}},
13001 {{ 0.5f}, { 0.5f}, {0.1f}, 0, {0xffffffff}},
13003 IDirect3DViewport2 *viewport, *full_viewport;
13004 IDirect3DMaterial2 *black_background;
13005 IDirectDrawSurface *rt, *ds;
13006 DDSURFACEDESC surface_desc;
13007 IDirect3DDevice2 *device;
13008 BOOL expected_failure;
13009 IDirectDraw2 *ddraw;
13010 DDPIXELFORMAT z_fmt;
13011 D3DRECT clear_rect;
13012 unsigned int i, j;
13013 IDirect3D2 *d3d;
13014 D3DVIEWPORT vp;
13015 ULONG refcount;
13016 HWND window;
13017 HRESULT hr;
13019 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
13020 0, 0, 640, 480, NULL, NULL, NULL, NULL);
13021 ddraw = create_ddraw();
13022 ok(!!ddraw, "Failed to create a ddraw object.\n");
13023 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
13025 skip("Failed to create a 3D device, skipping test.\n");
13026 IDirectDraw2_Release(ddraw);
13027 DestroyWindow(window);
13028 return;
13031 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
13032 ok(SUCCEEDED(hr), "Failed to get Direct3D2 interface, hr %#x.\n", hr);
13034 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
13035 ok(SUCCEEDED(hr), "Failed to disable depth test, hr %#x.\n", hr);
13036 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
13037 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
13039 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
13040 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
13041 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
13042 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
13043 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
13044 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
13046 black_background = create_diffuse_material(device, 0.0f, 0.0f, 0.0f, 0.0f);
13048 ds = get_depth_stencil(device);
13049 memset(&surface_desc, 0, sizeof(surface_desc));
13050 surface_desc.dwSize = sizeof(surface_desc);
13051 hr = IDirectDrawSurface_GetSurfaceDesc(ds, &surface_desc);
13052 z_fmt = surface_desc.ddpfPixelFormat;
13054 for (i = 0; i < ARRAY_SIZE(rt_sizes); ++i)
13056 if (i)
13058 memset(&surface_desc, 0, sizeof(surface_desc));
13059 surface_desc.dwSize = sizeof(surface_desc);
13060 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
13061 surface_desc.dwWidth = rt_sizes[i].x;
13062 surface_desc.dwHeight = rt_sizes[i].y;
13063 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
13064 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &rt, NULL);
13065 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x (i %u).\n", hr, i);
13067 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
13068 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
13069 surface_desc.ddpfPixelFormat = z_fmt;
13070 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
13071 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x (i %u).\n", hr, i);
13072 hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
13073 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x (i %u).\n", hr, i);
13075 hr = IDirect3DDevice2_SetRenderTarget(device, rt, 0);
13076 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x (i %u).\n", hr, i);
13078 else
13080 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
13081 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
13084 full_viewport = create_viewport(device, 0, 0, rt_sizes[i].x, rt_sizes[i].y);
13085 viewport_set_background(device, full_viewport, black_background);
13087 U1(clear_rect).x1 = U2(clear_rect).y1 = 0;
13088 U3(clear_rect).x2 = rt_sizes[i].x;
13089 U4(clear_rect).y2 = rt_sizes[i].y;
13091 for (j = 0; j < ARRAY_SIZE(tests); ++j)
13093 expected_failure = tests[j].vp.dwX + tests[j].vp.dwWidth > rt_sizes[i].x
13094 || tests[j].vp.dwY + tests[j].vp.dwHeight > rt_sizes[i].y;
13096 hr = IDirect3DViewport2_Clear(full_viewport, 1, &clear_rect, D3DCLEAR_TARGET);
13097 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x (i %u, j %u).\n", hr, i, j);
13099 hr = IDirect3D2_CreateViewport(d3d, &viewport, NULL);
13100 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x (i %u, j %u).\n", hr, i, j);
13101 hr = IDirect3DViewport2_SetViewport2(viewport, NULL);
13102 ok(hr == E_INVALIDARG, "Setting NULL viewport data returned unexpected hr %#x (i %u, j %u).\n",
13103 hr, i, j);
13104 memset(&vp, 0, sizeof(vp));
13105 vp.dwSize = sizeof(vp);
13106 vp.dwX = tests[j].vp.dwX;
13107 vp.dwY = tests[j].vp.dwY;
13108 vp.dwWidth = tests[j].vp.dwWidth;
13109 vp.dwHeight = tests[j].vp.dwHeight;
13110 vp.dvScaleX = tests[j].vp.dwWidth / 2.0f;
13111 vp.dvScaleY = tests[j].vp.dwHeight / 2.0f;
13112 vp.dvMinZ = 0.0f;
13113 vp.dvMaxZ = 1.0f;
13114 hr = IDirect3DViewport2_SetViewport(viewport, &vp);
13115 ok(hr == D3DERR_VIEWPORTHASNODEVICE,
13116 "Setting viewport data returned unexpected hr %#x (i %u, j %u).\n", hr, i, j);
13117 hr = IDirect3DDevice2_AddViewport(device, viewport);
13118 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x (i %u, j %u).\n", hr, i, j);
13119 hr = IDirect3DViewport2_SetViewport(viewport, &vp);
13120 if (expected_failure)
13121 ok(hr == E_INVALIDARG, "Setting viewport data returned unexpected hr %#x (i %u, j %u).\n",
13122 hr, i, j);
13123 else
13124 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x (i %u, j %u).\n", hr, i, j);
13126 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
13127 ok(SUCCEEDED(hr), "Failed to set the viewport, hr %#x (i %u, j %u).\n", hr, i, j);
13128 if (expected_failure)
13130 destroy_viewport(device, viewport);
13131 continue;
13134 hr = IDirect3DDevice2_BeginScene(device);
13135 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x (i %u, j %u).\n", hr, i, j);
13136 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, 4, 0);
13137 ok(SUCCEEDED(hr), "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
13138 hr = IDirect3DDevice2_EndScene(device);
13139 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x (i %u, j %u).\n", hr, i, j);
13141 check_rect(rt, tests[j].expected_rect, tests[j].message);
13143 destroy_viewport(device, viewport);
13146 destroy_viewport(device, full_viewport);
13148 hr = IDirectDrawSurface_DeleteAttachedSurface(rt, 0, ds);
13149 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x (i %u).\n", hr, i);
13150 IDirectDrawSurface_Release(ds);
13152 IDirectDrawSurface_Release(rt);
13155 destroy_material(black_background);
13156 refcount = IDirect3DDevice2_Release(device);
13157 ok(!refcount, "Device has %u references left.\n", refcount);
13158 IDirect3D2_Release(d3d);
13159 IDirectDraw2_Release(ddraw);
13160 DestroyWindow(window);
13163 static void test_find_device(void)
13165 D3DFINDDEVICESEARCH search = {0};
13166 D3DFINDDEVICERESULT result = {0};
13167 IDirect3DDevice2 *device;
13168 IDirectDraw2 *ddraw;
13169 IDirect3D2 *d3d;
13170 unsigned int i;
13171 HWND window;
13172 HRESULT hr;
13174 struct
13176 DWORD size;
13177 GUID guid;
13178 D3DDEVICEDESC_V1 hw_desc;
13179 D3DDEVICEDESC_V1 sw_desc;
13180 } result_v1;
13182 struct
13184 DWORD size;
13185 GUID guid;
13186 D3DDEVICEDESC_V2 hw_desc;
13187 D3DDEVICEDESC_V2 sw_desc;
13188 } result_v2;
13190 static const struct
13192 const GUID *guid;
13193 HRESULT hr;
13195 tests[] =
13197 {&IID_IDirect3D, DDERR_NOTFOUND},
13198 {&IID_IDirect3DRampDevice, D3D_OK},
13199 {&IID_IDirect3DRGBDevice, D3D_OK},
13200 {&IID_IDirect3DMMXDevice, D3D_OK},
13201 {&IID_IDirect3DRefDevice, DDERR_NOTFOUND},
13202 {&IID_IDirect3DTnLHalDevice, DDERR_NOTFOUND},
13203 {&IID_IDirect3DNullDevice, DDERR_NOTFOUND},
13206 ddraw = create_ddraw();
13207 ok(!!ddraw, "Failed to create a ddraw object.\n");
13209 if (FAILED(IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d)))
13211 skip("D3D interface is not available, skipping test.\n");
13212 IDirectDraw2_Release(ddraw);
13213 return;
13216 result.dwSize = sizeof(result);
13217 search.dwSize = sizeof(search);
13218 hr = IDirect3D2_FindDevice(d3d, NULL, NULL);
13219 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13220 hr = IDirect3D2_FindDevice(d3d, NULL, &result);
13221 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13222 hr = IDirect3D2_FindDevice(d3d, &search, NULL);
13223 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13224 hr = IDirect3D2_FindDevice(d3d, &search, &result);
13225 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13226 ok(result.dwSize == sizeof(result), "Got unexpected result size %u.\n", result.dwSize);
13227 ok(result.ddHwDesc.dwSize == sizeof(result_v2.hw_desc),
13228 "Got unexpected HW desc size %u.\n", result.ddHwDesc.dwSize);
13229 ok(result.ddSwDesc.dwSize == sizeof(result_v2.sw_desc),
13230 "Got unexpected SW desc size %u.\n", result.ddSwDesc.dwSize);
13232 memset(&search, 0, sizeof(search));
13233 memset(&result, 0, sizeof(result));
13234 hr = IDirect3D2_FindDevice(d3d, &search, &result);
13235 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13237 search.dwSize = sizeof(search) + 1;
13238 result.dwSize = sizeof(result) + 1;
13239 hr = IDirect3D2_FindDevice(d3d, &search, &result);
13240 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13242 search.dwSize = sizeof(search);
13244 memset(&result_v1, 0, sizeof(result_v1));
13245 result_v1.size = sizeof(result_v1);
13246 hr = IDirect3D2_FindDevice(d3d, &search, (D3DFINDDEVICERESULT *)&result_v1);
13247 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13248 ok(result_v1.hw_desc.dwSize == sizeof(result_v2.hw_desc),
13249 "Got unexpected HW desc size %u.\n", result_v1.hw_desc.dwSize);
13250 ok(result_v1.sw_desc.dwSize == sizeof(result_v2.sw_desc),
13251 "Got unexpected SW desc size %u.\n", result_v1.sw_desc.dwSize);
13253 memset(&result_v2, 0, sizeof(result_v2));
13254 result_v2.size = sizeof(result_v2);
13255 hr = IDirect3D2_FindDevice(d3d, &search, (D3DFINDDEVICERESULT *)&result_v2);
13256 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13257 ok(result_v2.hw_desc.dwSize == sizeof(result_v2.hw_desc),
13258 "Got unexpected HW desc size %u.\n", result_v2.hw_desc.dwSize);
13259 ok(result_v2.sw_desc.dwSize == sizeof(result_v2.sw_desc),
13260 "Got unexpected SW desc size %u.\n", result_v2.sw_desc.dwSize);
13262 for (i = 0; i < ARRAY_SIZE(tests); ++i)
13264 memset(&search, 0, sizeof(search));
13265 search.dwSize = sizeof(search);
13266 search.dwFlags = D3DFDS_GUID;
13267 search.guid = *tests[i].guid;
13269 memset(&result, 0, sizeof(result));
13270 result.dwSize = sizeof(result);
13272 hr = IDirect3D2_FindDevice(d3d, &search, &result);
13273 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
13274 ok(result.dwSize == sizeof(result), "Test %u: Got unexpected result size %u.\n", i, result.dwSize);
13275 if (SUCCEEDED(hr))
13277 ok(result.ddHwDesc.dwSize == sizeof(result_v2.hw_desc),
13278 "Test %u: Got unexpected HW desc size %u.\n", i, result.ddHwDesc.dwSize);
13279 ok(result.ddSwDesc.dwSize == sizeof(result_v2.sw_desc),
13280 "Test %u: Got unexpected SW desc size %u.\n", i, result.ddSwDesc.dwSize);
13282 else
13284 ok(!result.ddHwDesc.dwSize,
13285 "Test %u: Got unexpected HW desc size %u.\n", i, result.ddHwDesc.dwSize);
13286 ok(!result.ddSwDesc.dwSize,
13287 "Test %u: Got unexpected SW desc size %u.\n", i, result.ddSwDesc.dwSize);
13291 /* The HAL device can only be enumerated if hardware acceleration is present. */
13292 search.dwSize = sizeof(search);
13293 search.dwFlags = D3DFDS_GUID;
13294 search.guid = IID_IDirect3DHALDevice;
13295 result.dwSize = sizeof(result);
13296 hr = IDirect3D2_FindDevice(d3d, &search, &result);
13298 window = create_window();
13299 device = create_device(ddraw, window, DDSCL_NORMAL);
13300 if (hr == D3D_OK)
13301 ok(!!device, "Failed to create a 3D device.\n");
13302 else
13303 ok(!device, "Succeeded to create a 3D device.\n");
13304 if (device)
13305 IDirect3DDevice2_Release(device);
13306 DestroyWindow(window);
13308 /* Curiously the colour model criteria seem to be ignored. */
13309 search.dwSize = sizeof(search);
13310 search.dwFlags = D3DFDS_COLORMODEL;
13311 search.dcmColorModel = 0xdeadbeef;
13312 result.dwSize = sizeof(result);
13313 hr = IDirect3D2_FindDevice(d3d, &search, &result);
13314 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13316 IDirect3D2_Release(d3d);
13317 IDirectDraw2_Release(ddraw);
13320 static IDirectDraw2 *killfocus_ddraw;
13321 static IDirectDrawSurface *killfocus_surface;
13323 static LRESULT CALLBACK killfocus_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
13325 ULONG ref;
13327 if (message == WM_KILLFOCUS)
13329 ref = IDirectDrawSurface_Release(killfocus_surface);
13330 ok(!ref, "Unexpected surface refcount %u.\n", ref);
13331 ref = IDirectDraw2_Release(killfocus_ddraw);
13332 ok(!ref, "Unexpected ddraw refcount %u.\n", ref);
13333 killfocus_ddraw = NULL;
13336 return DefWindowProcA(window, message, wparam, lparam);
13339 static void test_killfocus(void)
13341 DDSURFACEDESC surface_desc;
13342 HRESULT hr;
13343 HWND window;
13344 WNDCLASSA wc = {0};
13346 wc.lpfnWndProc = killfocus_proc;
13347 wc.lpszClassName = "ddraw_killfocus_wndproc_wc";
13348 ok(RegisterClassA(&wc), "Failed to register window class.\n");
13350 window = CreateWindowA("ddraw_killfocus_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW,
13351 0, 0, 640, 480, 0, 0, 0, 0);
13353 killfocus_ddraw = create_ddraw();
13354 ok(!!killfocus_ddraw, "Failed to create a ddraw object.\n");
13356 hr = IDirectDraw2_SetCooperativeLevel(killfocus_ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
13357 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13359 memset(&surface_desc, 0, sizeof(surface_desc));
13360 surface_desc.dwSize = sizeof(surface_desc);
13361 surface_desc.dwFlags = DDSD_CAPS;
13362 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
13363 hr = IDirectDraw_CreateSurface(killfocus_ddraw, &surface_desc, &killfocus_surface, NULL);
13364 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13366 SetForegroundWindow(GetDesktopWindow());
13367 ok(!killfocus_ddraw, "WM_KILLFOCUS was not received.\n");
13369 DestroyWindow(window);
13370 UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL));
13373 static void test_gdi_surface(void)
13375 IDirectDrawSurface *primary, *backbuffer, *gdi_surface;
13376 DDSCAPS caps = {DDSCAPS_BACKBUFFER};
13377 DDSURFACEDESC surface_desc;
13378 IDirectDraw2 *ddraw;
13379 ULONG refcount;
13380 HWND window;
13381 HRESULT hr;
13383 window = create_window();
13384 ddraw = create_ddraw();
13385 ok(!!ddraw, "Failed to create a ddraw object.\n");
13386 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13387 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
13389 /* Retrieving the GDI surface requires a primary surface to exist. */
13390 gdi_surface = (void *)0xc0dec0de;
13391 hr = IDirectDraw2_GetGDISurface(ddraw, &gdi_surface);
13392 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13393 ok(!gdi_surface, "Got unexpected surface %p.\n", gdi_surface);
13395 hr = IDirectDraw2_FlipToGDISurface(ddraw);
13396 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13398 memset(&surface_desc, 0, sizeof(surface_desc));
13399 surface_desc.dwSize = sizeof(surface_desc);
13400 surface_desc.dwFlags = DDSD_CAPS;
13401 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
13402 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
13403 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
13405 hr = IDirectDraw2_GetGDISurface(ddraw, &gdi_surface);
13406 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
13407 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
13408 IDirectDrawSurface_Release(gdi_surface);
13410 /* Flipping to the GDI surface requires the primary surface to be
13411 * flippable. */
13412 hr = IDirectDraw2_FlipToGDISurface(ddraw);
13413 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
13415 IDirectDrawSurface_Release(primary);
13417 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
13418 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
13420 memset(&surface_desc, 0, sizeof(surface_desc));
13421 surface_desc.dwSize = sizeof(surface_desc);
13422 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
13423 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
13424 U5(surface_desc).dwBackBufferCount = 1;
13425 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
13426 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
13427 hr = IDirectDrawSurface_GetAttachedSurface(primary, &caps, &backbuffer);
13428 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
13429 ok(backbuffer != primary, "Got unexpected backbuffer %p.\n", backbuffer);
13431 hr = IDirectDraw2_GetGDISurface(ddraw, &gdi_surface);
13432 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
13433 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
13434 IDirectDrawSurface_Release(gdi_surface);
13436 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
13437 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
13438 hr = IDirectDraw2_GetGDISurface(ddraw, &gdi_surface);
13439 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
13440 ok(gdi_surface == backbuffer || broken(gdi_surface == primary),
13441 "Got unexpected surface %p, expected %p.\n", gdi_surface, backbuffer);
13442 IDirectDrawSurface_Release(gdi_surface);
13444 hr = IDirectDraw2_FlipToGDISurface(ddraw);
13445 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
13447 hr = IDirectDraw2_GetGDISurface(ddraw, &gdi_surface);
13448 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
13449 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
13450 IDirectDrawSurface_Release(gdi_surface);
13452 hr = IDirectDraw2_FlipToGDISurface(ddraw);
13453 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
13455 IDirectDrawSurface_Release(backbuffer);
13456 IDirectDrawSurface_Release(primary);
13458 refcount = IDirectDraw2_Release(ddraw);
13459 ok(!refcount, "%u references left.\n", refcount);
13460 DestroyWindow(window);
13463 static void test_alphatest(void)
13465 #define ALPHATEST_PASSED 0x0000ff00
13466 #define ALPHATEST_FAILED 0x00ff0000
13467 D3DRECT rect_full = {{0}, {0}, {640}, {480}};
13468 IDirect3DMaterial2 *blue, *failed;
13469 IDirect3DViewport2 *viewport;
13470 IDirect3DDevice2 *device;
13471 IDirectDrawSurface *rt;
13472 IDirectDraw2 *ddraw;
13473 unsigned int i;
13474 D3DCOLOR color;
13475 ULONG refcount;
13476 HWND window;
13477 DWORD value;
13478 HRESULT hr;
13480 static const struct
13482 D3DCMPFUNC func;
13483 D3DCOLOR color_less;
13484 D3DCOLOR color_equal;
13485 D3DCOLOR color_greater;
13487 test_data[] =
13489 {D3DCMP_NEVER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_FAILED},
13490 {D3DCMP_LESS, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_FAILED},
13491 {D3DCMP_EQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_FAILED},
13492 {D3DCMP_LESSEQUAL, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_FAILED},
13493 {D3DCMP_GREATER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_PASSED},
13494 {D3DCMP_NOTEQUAL, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_PASSED},
13495 {D3DCMP_GREATEREQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_PASSED},
13496 {D3DCMP_ALWAYS, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED},
13498 static D3DLVERTEX quad[] =
13500 {{-1.0f}, {-1.0f}, {0.1f}, 0, {ALPHATEST_PASSED | 0x80000000}},
13501 {{-1.0f}, { 1.0f}, {0.1f}, 0, {ALPHATEST_PASSED | 0x80000000}},
13502 {{ 1.0f}, {-1.0f}, {0.1f}, 0, {ALPHATEST_PASSED | 0x80000000}},
13503 {{ 1.0f}, { 1.0f}, {0.1f}, 0, {ALPHATEST_PASSED | 0x80000000}},
13506 window = create_window();
13507 ddraw = create_ddraw();
13508 ok(!!ddraw, "Failed to create a ddraw object.\n");
13509 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
13511 skip("Failed to create a 3D device.\n");
13512 IDirectDraw2_Release(ddraw);
13513 DestroyWindow(window);
13514 return;
13516 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
13517 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13519 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
13520 failed = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
13522 viewport = create_viewport(device, 0, 0, 640, 480);
13523 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
13524 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13526 viewport_set_background(device, viewport, blue);
13527 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
13528 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13529 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
13530 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13531 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
13532 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13533 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
13534 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13536 viewport_set_background(device, viewport, failed);
13537 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
13539 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHAFUNC, test_data[i].func);
13540 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13542 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
13543 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13544 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHAREF, 0x70);
13545 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13546 hr = IDirect3DDevice2_BeginScene(device);
13547 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13548 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
13549 D3DVT_LVERTEX, quad, ARRAY_SIZE(quad), 0);
13550 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13551 hr = IDirect3DDevice2_EndScene(device);
13552 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13553 color = get_surface_color(rt, 320, 240);
13554 ok(compare_color(color, test_data[i].color_greater, 0),
13555 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
13556 color, test_data[i].color_greater, test_data[i].func);
13558 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
13559 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13560 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHAREF, 0xff70);
13561 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13562 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHAREF, &value);
13563 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13564 ok(value == 0xff70, "Got unexpected value %#x.\n", value);
13565 hr = IDirect3DDevice2_BeginScene(device);
13566 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13567 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
13568 D3DVT_LVERTEX, quad, ARRAY_SIZE(quad), 0);
13569 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13570 hr = IDirect3DDevice2_EndScene(device);
13571 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13572 color = get_surface_color(rt, 320, 240);
13573 ok(compare_color(color, test_data[i].color_greater, 0),
13574 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
13575 color, test_data[i].color_greater, test_data[i].func);
13578 destroy_viewport(device, viewport);
13579 destroy_material(failed);
13580 destroy_material(blue);
13581 IDirectDrawSurface_Release(rt);
13582 refcount = IDirect3DDevice2_Release(device);
13583 ok(!refcount, "Device has %u references left.\n", refcount);
13584 refcount = IDirectDraw2_Release(ddraw);
13585 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13586 DestroyWindow(window);
13589 static void test_clipper_refcount(void)
13591 IDirectDrawSurface *surface;
13592 IDirectDrawClipper *clipper, *clipper2;
13593 DDSURFACEDESC surface_desc;
13594 IDirectDraw2 *ddraw;
13595 IDirectDraw *ddraw1;
13596 ULONG refcount;
13597 HWND window;
13598 HRESULT hr;
13599 BOOL changed;
13600 const IDirectDrawClipperVtbl *orig_vtbl;
13602 window = create_window();
13603 ddraw = create_ddraw();
13604 ok(!!ddraw, "Failed to create a ddraw object.\n");
13605 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13606 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
13608 memset(&surface_desc, 0, sizeof(surface_desc));
13609 surface_desc.dwSize = sizeof(surface_desc);
13610 surface_desc.dwFlags = DDSD_CAPS;
13611 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
13612 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13613 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
13615 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
13616 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
13617 refcount = get_refcount((IUnknown *)clipper);
13618 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13620 /* Show that clipper validation doesn't somehow happen through per-clipper vtable
13621 * pointers. */
13622 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper2, NULL);
13623 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
13624 ok(clipper->lpVtbl == clipper2->lpVtbl, "Got different clipper vtables %p and %p.\n",
13625 clipper->lpVtbl, clipper2->lpVtbl);
13626 orig_vtbl = clipper->lpVtbl;
13627 IDirectDrawClipper_Release(clipper2);
13629 /* Surfaces hold a reference to clippers. No surprises there. */
13630 hr = IDirectDrawSurface_SetClipper(surface, clipper);
13631 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
13632 refcount = get_refcount((IUnknown *)clipper);
13633 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
13635 hr = IDirectDrawSurface_GetClipper(surface, &clipper2);
13636 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#x.\n", hr);
13637 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
13638 refcount = IDirectDrawClipper_Release(clipper2);
13639 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
13641 hr = IDirectDrawSurface_SetClipper(surface, NULL);
13642 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
13643 refcount = get_refcount((IUnknown *)clipper);
13644 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13646 hr = IDirectDrawSurface_SetClipper(surface, clipper);
13647 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
13648 refcount = get_refcount((IUnknown *)clipper);
13649 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
13651 refcount = IDirectDrawSurface_Release(surface);
13652 ok(!refcount, "%u references left.\n", refcount);
13653 refcount = get_refcount((IUnknown *)clipper);
13654 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13656 /* SetClipper with an invalid pointer crashes. */
13658 /* Clipper methods work with a broken vtable, with the exception of Release. */
13659 clipper->lpVtbl = (void *)0xdeadbeef;
13660 refcount = orig_vtbl->AddRef(clipper);
13661 todo_wine ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
13662 refcount = orig_vtbl->Release(clipper);
13663 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
13665 clipper->lpVtbl = orig_vtbl;
13666 refcount = orig_vtbl->Release(clipper);
13667 todo_wine ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13669 /* Fix the refcount difference because Wine did not increase the ref in the
13670 * AddRef call above. */
13671 if (refcount)
13673 refcount = IDirectDrawClipper_Release(clipper);
13674 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
13677 /* Steal the reference and see what happens - releasing the surface works fine.
13678 * The clipper is destroyed and not kept alive by a hidden refcount - trying to
13679 * release it after the GetClipper call is likely to crash, and certain to crash
13680 * if we allocate and zero as much heap memory as we can get. */
13681 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13682 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
13683 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
13684 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
13685 hr = IDirectDrawSurface_SetClipper(surface, clipper);
13686 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
13688 IDirectDrawClipper_Release(clipper);
13689 IDirectDrawClipper_Release(clipper);
13691 hr = IDirectDrawSurface_GetClipper(surface, &clipper2);
13692 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#x.\n", hr);
13693 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
13695 /* Show that invoking the Release method does not crash, but don't get the
13696 * vtable through the clipper pointer because it is no longer pointing to
13697 * valid memory. */
13698 refcount = orig_vtbl->Release(clipper);
13699 ok(!refcount, "%u references left.\n", refcount);
13701 refcount = IDirectDrawSurface_Release(surface);
13702 ok(!refcount, "%u references left.\n", refcount);
13704 /* It looks like the protection against invalid thispointers is part of
13705 * the IDirectDrawClipper method implementation, not IDirectDrawSurface. */
13706 clipper = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 0x1000);
13707 ok(!!clipper, "failed to allocate memory\n");
13709 /* Assigning the vtable to our fake clipper does NOT make a difference on
13710 * native - there is a different member of the clipper implementation struct
13711 * that is used to determine if a clipper is valid. */
13712 clipper->lpVtbl = orig_vtbl;
13714 refcount = orig_vtbl->AddRef(clipper);
13715 todo_wine ok(!refcount, "Got refcount %u.\n", refcount);
13716 refcount = orig_vtbl->AddRef((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef);
13717 ok(!refcount, "Got refcount %u.\n", refcount);
13719 changed = 0x1234;
13720 hr = orig_vtbl->IsClipListChanged(clipper, &changed);
13721 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13722 todo_wine ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
13724 changed = 0x1234;
13725 hr = orig_vtbl->IsClipListChanged((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef, &changed);
13726 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13727 ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
13729 /* Nope, we can't initialize our fake clipper. */
13730 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirectDraw, (void **)&ddraw1);
13731 ok(SUCCEEDED(hr), "Failed to get ddraw1 interface, hr %#x.\n", hr);
13733 hr = orig_vtbl->Initialize(clipper, ddraw1, 0);
13734 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13736 IDirectDraw_Release(ddraw1);
13738 HeapFree(GetProcessHeap(), 0, clipper);
13740 refcount = IDirectDraw2_Release(ddraw);
13741 ok(!refcount, "%u references left.\n", refcount);
13742 DestroyWindow(window);
13746 START_TEST(ddraw2)
13748 DDDEVICEIDENTIFIER identifier;
13749 DEVMODEW current_mode;
13750 IDirectDraw2 *ddraw;
13751 HMODULE dwmapi;
13753 if (!(ddraw = create_ddraw()))
13755 skip("Failed to create a ddraw object, skipping tests.\n");
13756 return;
13759 if (ddraw_get_identifier(ddraw, &identifier))
13761 trace("Driver string: \"%s\"\n", identifier.szDriver);
13762 trace("Description string: \"%s\"\n", identifier.szDescription);
13763 trace("Driver version %d.%d.%d.%d\n",
13764 HIWORD(U(identifier.liDriverVersion).HighPart), LOWORD(U(identifier.liDriverVersion).HighPart),
13765 HIWORD(U(identifier.liDriverVersion).LowPart), LOWORD(U(identifier.liDriverVersion).LowPart));
13767 IDirectDraw2_Release(ddraw);
13769 memset(&current_mode, 0, sizeof(current_mode));
13770 current_mode.dmSize = sizeof(current_mode);
13771 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
13772 registry_mode.dmSize = sizeof(registry_mode);
13773 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
13774 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
13775 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
13777 skip("Current mode does not match registry mode, skipping test.\n");
13778 return;
13781 if ((dwmapi = LoadLibraryA("dwmapi.dll")))
13782 pDwmIsCompositionEnabled = (void *)GetProcAddress(dwmapi, "DwmIsCompositionEnabled");
13784 test_coop_level_create_device_window();
13785 test_clipper_blt();
13786 test_coop_level_d3d_state();
13787 test_surface_interface_mismatch();
13788 test_coop_level_threaded();
13789 test_depth_blit();
13790 test_texture_load_ckey();
13791 test_viewport_object();
13792 test_zenable();
13793 test_ck_rgba();
13794 test_ck_default();
13795 test_ck_complex();
13796 test_surface_qi();
13797 test_device_qi();
13798 test_wndproc();
13799 test_window_style();
13800 test_redundant_mode_set();
13801 test_coop_level_mode_set();
13802 test_coop_level_mode_set_multi();
13803 test_initialize();
13804 test_coop_level_surf_create();
13805 test_coop_level_multi_window();
13806 test_clear_rect_count();
13807 test_coop_level_versions();
13808 test_lighting_interface_versions();
13809 test_coop_level_activateapp();
13810 test_unsupported_formats();
13811 test_rt_caps();
13812 test_primary_caps();
13813 test_surface_lock();
13814 test_surface_discard();
13815 test_flip();
13816 test_set_surface_desc();
13817 test_user_memory_getdc();
13818 test_sysmem_overlay();
13819 test_primary_palette();
13820 test_surface_attachment();
13821 test_pixel_format();
13822 test_create_surface_pitch();
13823 test_mipmap();
13824 test_palette_complex();
13825 test_p8_blit();
13826 test_material();
13827 test_lighting();
13828 test_specular_lighting();
13829 test_palette_gdi();
13830 test_palette_alpha();
13831 test_lost_device();
13832 test_surface_desc_lock();
13833 test_texturemapblend();
13834 test_viewport_clear_rect();
13835 test_color_fill();
13836 test_colorkey_precision();
13837 test_range_colorkey();
13838 test_shademode();
13839 test_lockrect_invalid();
13840 test_yv12_overlay();
13841 test_offscreen_overlay();
13842 test_overlay_rect();
13843 test_blt();
13844 test_blt_z_alpha();
13845 test_cross_device_blt();
13846 test_getdc();
13847 test_draw_primitive();
13848 test_edge_antialiasing_blending();
13849 test_transform_vertices();
13850 test_display_mode_surface_pixel_format();
13851 test_surface_desc_size();
13852 test_ck_operation();
13853 test_set_render_state();
13854 test_depth_readback();
13855 test_clear();
13856 test_enum_surfaces();
13857 test_viewport();
13858 test_find_device();
13859 test_killfocus();
13860 test_gdi_surface();
13861 test_alphatest();
13862 test_clipper_refcount();