ddraw/tests: Rewrite rectangle_settings().
[wine.git] / dlls / ddraw / tests / ddraw2.c
blob5c0bb5208f515b1c58cf3c03658ca21cbdb84456
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 "d3d.h"
27 static BOOL is_ddraw64 = sizeof(DWORD) != sizeof(DWORD *);
28 static DEVMODEW registry_mode;
30 struct create_window_thread_param
32 HWND window;
33 HANDLE window_created;
34 HANDLE destroy_window;
35 HANDLE thread;
38 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
40 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
41 c1 >>= 8; c2 >>= 8;
42 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
43 c1 >>= 8; c2 >>= 8;
44 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
45 c1 >>= 8; c2 >>= 8;
46 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
47 return TRUE;
50 static IDirectDrawSurface *create_overlay(IDirectDraw2 *ddraw,
51 unsigned int width, unsigned int height, DWORD format)
53 IDirectDrawSurface *surface;
54 DDSURFACEDESC desc;
56 memset(&desc, 0, sizeof(desc));
57 desc.dwSize = sizeof(desc);
58 desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
59 desc.dwWidth = width;
60 desc.dwHeight = height;
61 desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
62 desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
63 desc.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
64 desc.ddpfPixelFormat.dwFourCC = format;
66 if (FAILED(IDirectDraw2_CreateSurface(ddraw, &desc, &surface, NULL)))
67 return NULL;
68 return surface;
71 static DWORD WINAPI create_window_thread_proc(void *param)
73 struct create_window_thread_param *p = param;
74 DWORD res;
75 BOOL ret;
77 p->window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
78 0, 0, 640, 480, 0, 0, 0, 0);
79 ret = SetEvent(p->window_created);
80 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
82 for (;;)
84 MSG msg;
86 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
87 DispatchMessageA(&msg);
88 res = WaitForSingleObject(p->destroy_window, 100);
89 if (res == WAIT_OBJECT_0)
90 break;
91 if (res != WAIT_TIMEOUT)
93 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
94 break;
98 DestroyWindow(p->window);
100 return 0;
103 static void create_window_thread(struct create_window_thread_param *p)
105 DWORD res, tid;
107 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
108 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
109 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
110 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
111 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
112 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
113 res = WaitForSingleObject(p->window_created, INFINITE);
114 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
117 static void destroy_window_thread(struct create_window_thread_param *p)
119 SetEvent(p->destroy_window);
120 WaitForSingleObject(p->thread, INFINITE);
121 CloseHandle(p->destroy_window);
122 CloseHandle(p->window_created);
123 CloseHandle(p->thread);
126 static IDirectDrawSurface *get_depth_stencil(IDirect3DDevice2 *device)
128 IDirectDrawSurface *rt, *ret;
129 DDSCAPS caps = {DDSCAPS_ZBUFFER};
130 HRESULT hr;
132 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
133 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
134 hr = IDirectDrawSurface_GetAttachedSurface(rt, &caps, &ret);
135 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
136 IDirectDrawSurface_Release(rt);
137 return ret;
140 static HRESULT set_display_mode(IDirectDraw2 *ddraw, DWORD width, DWORD height)
142 if (SUCCEEDED(IDirectDraw2_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
143 return DD_OK;
144 return IDirectDraw2_SetDisplayMode(ddraw, width, height, 24, 0, 0);
147 static D3DCOLOR get_surface_color(IDirectDrawSurface *surface, UINT x, UINT y)
149 RECT rect = {x, y, x + 1, y + 1};
150 DDSURFACEDESC surface_desc;
151 D3DCOLOR color;
152 HRESULT hr;
154 memset(&surface_desc, 0, sizeof(surface_desc));
155 surface_desc.dwSize = sizeof(surface_desc);
157 hr = IDirectDrawSurface_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
158 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
159 if (FAILED(hr))
160 return 0xdeadbeef;
162 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
164 hr = IDirectDrawSurface_Unlock(surface, NULL);
165 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
167 return color;
170 static DWORD get_device_z_depth(IDirect3DDevice2 *device)
172 DDSCAPS caps = {DDSCAPS_ZBUFFER};
173 IDirectDrawSurface *ds, *rt;
174 DDSURFACEDESC desc;
175 HRESULT hr;
177 if (FAILED(IDirect3DDevice2_GetRenderTarget(device, &rt)))
178 return 0;
180 hr = IDirectDrawSurface_GetAttachedSurface(rt, &caps, &ds);
181 IDirectDrawSurface_Release(rt);
182 if (FAILED(hr))
183 return 0;
185 desc.dwSize = sizeof(desc);
186 hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
187 IDirectDrawSurface_Release(ds);
188 if (FAILED(hr))
189 return 0;
191 return U2(desc).dwZBufferBitDepth;
194 static IDirectDraw2 *create_ddraw(void)
196 IDirectDraw2 *ddraw2;
197 IDirectDraw *ddraw1;
198 HRESULT hr;
200 if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
201 return NULL;
203 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2);
204 IDirectDraw_Release(ddraw1);
205 if (FAILED(hr))
206 return NULL;
208 return ddraw2;
211 static IDirect3DDevice2 *create_device(IDirectDraw2 *ddraw, HWND window, DWORD coop_level)
213 static const DWORD z_depths[] = {32, 24, 16};
214 IDirectDrawSurface *surface, *ds;
215 IDirect3DDevice2 *device = NULL;
216 DDSURFACEDESC surface_desc;
217 IDirect3D2 *d3d;
218 unsigned int i;
219 HRESULT hr;
221 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, coop_level);
222 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
224 memset(&surface_desc, 0, sizeof(surface_desc));
225 surface_desc.dwSize = sizeof(surface_desc);
226 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
227 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
228 surface_desc.dwWidth = 640;
229 surface_desc.dwHeight = 480;
231 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
232 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
234 if (coop_level & DDSCL_NORMAL)
236 IDirectDrawClipper *clipper;
238 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
239 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
240 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
241 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
242 hr = IDirectDrawSurface_SetClipper(surface, clipper);
243 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
244 IDirectDrawClipper_Release(clipper);
247 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
248 if (FAILED(hr))
250 IDirectDrawSurface_Release(surface);
251 return NULL;
254 /* We used to use EnumDevices() for this, but it seems
255 * D3DDEVICEDESC.dwDeviceZBufferBitDepth only has a very casual
256 * relationship with reality. */
257 for (i = 0; i < sizeof(z_depths) / sizeof(*z_depths); ++i)
259 memset(&surface_desc, 0, sizeof(surface_desc));
260 surface_desc.dwSize = sizeof(surface_desc);
261 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
262 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
263 U2(surface_desc).dwZBufferBitDepth = z_depths[i];
264 surface_desc.dwWidth = 640;
265 surface_desc.dwHeight = 480;
266 if (FAILED(IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL)))
267 continue;
269 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
270 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
271 IDirectDrawSurface_Release(ds);
272 if (FAILED(hr))
273 continue;
275 if (SUCCEEDED(IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device)))
276 break;
278 IDirectDrawSurface_DeleteAttachedSurface(surface, 0, ds);
281 IDirect3D2_Release(d3d);
282 IDirectDrawSurface_Release(surface);
283 return device;
286 static IDirect3DViewport2 *create_viewport(IDirect3DDevice2 *device, UINT x, UINT y, UINT w, UINT h)
288 IDirect3DViewport2 *viewport;
289 D3DVIEWPORT2 vp;
290 IDirect3D2 *d3d;
291 HRESULT hr;
293 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
294 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
295 hr = IDirect3D2_CreateViewport(d3d, &viewport, NULL);
296 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
297 hr = IDirect3DDevice2_AddViewport(device, viewport);
298 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
299 memset(&vp, 0, sizeof(vp));
300 vp.dwSize = sizeof(vp);
301 vp.dwX = x;
302 vp.dwY = y;
303 vp.dwWidth = w;
304 vp.dwHeight = h;
305 vp.dvClipX = -1.0f;
306 vp.dvClipY = 1.0f;
307 vp.dvClipWidth = 2.0f;
308 vp.dvClipHeight = 2.0f;
309 vp.dvMinZ = 0.0f;
310 vp.dvMaxZ = 1.0f;
311 hr = IDirect3DViewport2_SetViewport2(viewport, &vp);
312 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
313 IDirect3D2_Release(d3d);
315 return viewport;
318 static void viewport_set_background(IDirect3DDevice2 *device, IDirect3DViewport2 *viewport,
319 IDirect3DMaterial2 *material)
321 D3DMATERIALHANDLE material_handle;
322 HRESULT hr;
324 hr = IDirect3DMaterial2_GetHandle(material, device, &material_handle);
325 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
326 hr = IDirect3DViewport2_SetBackground(viewport, material_handle);
327 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
330 static void destroy_viewport(IDirect3DDevice2 *device, IDirect3DViewport2 *viewport)
332 HRESULT hr;
334 hr = IDirect3DDevice2_DeleteViewport(device, viewport);
335 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
336 IDirect3DViewport2_Release(viewport);
339 static IDirect3DMaterial2 *create_material(IDirect3DDevice2 *device, D3DMATERIAL *mat)
341 IDirect3DMaterial2 *material;
342 IDirect3D2 *d3d;
343 HRESULT hr;
345 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
346 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
347 hr = IDirect3D2_CreateMaterial(d3d, &material, NULL);
348 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
349 hr = IDirect3DMaterial2_SetMaterial(material, mat);
350 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
351 IDirect3D2_Release(d3d);
353 return material;
356 static IDirect3DMaterial2 *create_diffuse_material(IDirect3DDevice2 *device, float r, float g, float b, float a)
358 D3DMATERIAL mat;
360 memset(&mat, 0, sizeof(mat));
361 mat.dwSize = sizeof(mat);
362 U1(U(mat).diffuse).r = r;
363 U2(U(mat).diffuse).g = g;
364 U3(U(mat).diffuse).b = b;
365 U4(U(mat).diffuse).a = a;
367 return create_material(device, &mat);
370 static IDirect3DMaterial2 *create_specular_material(IDirect3DDevice2 *device,
371 float r, float g, float b, float a, float power)
373 D3DMATERIAL mat;
375 memset(&mat, 0, sizeof(mat));
376 mat.dwSize = sizeof(mat);
377 U1(U2(mat).specular).r = r;
378 U2(U2(mat).specular).g = g;
379 U3(U2(mat).specular).b = b;
380 U4(U2(mat).specular).a = a;
381 U4(mat).power = power;
383 return create_material(device, &mat);
386 static IDirect3DMaterial2 *create_emissive_material(IDirect3DDevice2 *device, float r, float g, float b, float a)
388 D3DMATERIAL mat;
390 memset(&mat, 0, sizeof(mat));
391 mat.dwSize = sizeof(mat);
392 U1(U3(mat).emissive).r = r;
393 U2(U3(mat).emissive).g = g;
394 U3(U3(mat).emissive).b = b;
395 U4(U3(mat).emissive).a = a;
397 return create_material(device, &mat);
400 static void destroy_material(IDirect3DMaterial2 *material)
402 IDirect3DMaterial2_Release(material);
405 struct message
407 UINT message;
408 BOOL check_wparam;
409 WPARAM expect_wparam;
412 static const struct message *expect_messages;
414 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
416 if (expect_messages && message == expect_messages->message)
418 if (expect_messages->check_wparam)
419 ok (wparam == expect_messages->expect_wparam,
420 "Got unexpected wparam %lx for message %x, expected %lx.\n",
421 wparam, message, expect_messages->expect_wparam);
423 ++expect_messages;
426 return DefWindowProcA(hwnd, message, wparam, lparam);
429 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
430 * interface. This prevents subsequent SetCooperativeLevel() calls on a
431 * different window from failing with DDERR_HWNDALREADYSET. */
432 static void fix_wndproc(HWND window, LONG_PTR proc)
434 IDirectDraw2 *ddraw;
435 HRESULT hr;
437 if (!(ddraw = create_ddraw()))
438 return;
440 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
441 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
442 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
443 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
444 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
446 IDirectDraw2_Release(ddraw);
449 static HRESULT CALLBACK restore_callback(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
451 HRESULT hr = IDirectDrawSurface_Restore(surface);
452 ok(SUCCEEDED(hr) || hr == DDERR_IMPLICITLYCREATED, "Failed to restore surface, hr %#x.\n", hr);
453 IDirectDrawSurface_Release(surface);
455 return DDENUMRET_OK;
458 static HRESULT restore_surfaces(IDirectDraw2 *ddraw)
460 return IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
461 NULL, NULL, restore_callback);
464 static void test_coop_level_create_device_window(void)
466 HWND focus_window, device_window;
467 IDirectDraw2 *ddraw;
468 HRESULT hr;
470 focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
471 0, 0, 640, 480, 0, 0, 0, 0);
472 ddraw = create_ddraw();
473 ok(!!ddraw, "Failed to create a ddraw object.\n");
475 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
476 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
477 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
478 ok(!device_window, "Unexpected device window found.\n");
479 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
480 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
481 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
482 ok(!device_window, "Unexpected device window found.\n");
483 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
484 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
485 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
486 ok(!device_window, "Unexpected device window found.\n");
487 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
488 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
489 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
490 ok(!device_window, "Unexpected device window found.\n");
491 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
492 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
493 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
494 ok(!device_window, "Unexpected device window found.\n");
496 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
497 if (broken(hr == DDERR_INVALIDPARAMS))
499 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
500 IDirectDraw2_Release(ddraw);
501 DestroyWindow(focus_window);
502 return;
505 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
506 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
507 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
508 ok(!device_window, "Unexpected device window found.\n");
509 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
510 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
511 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
512 ok(!device_window, "Unexpected device window found.\n");
514 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
515 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
516 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
517 ok(!device_window, "Unexpected device window found.\n");
518 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
519 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
520 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
521 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
522 ok(!!device_window, "Device window not found.\n");
524 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
525 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
526 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
527 ok(!device_window, "Unexpected device window found.\n");
528 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
529 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
530 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
531 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
532 ok(!!device_window, "Device window not found.\n");
534 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
535 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
536 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
537 ok(!device_window, "Unexpected device window found.\n");
538 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
539 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
540 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
541 ok(!device_window, "Unexpected device window found.\n");
542 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
543 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
544 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
545 ok(!device_window, "Unexpected device window found.\n");
546 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
547 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
548 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
549 ok(!!device_window, "Device window not found.\n");
551 IDirectDraw2_Release(ddraw);
552 DestroyWindow(focus_window);
555 static void test_clipper_blt(void)
557 IDirectDrawSurface *src_surface, *dst_surface;
558 RECT client_rect, src_rect;
559 IDirectDrawClipper *clipper;
560 DDSURFACEDESC surface_desc;
561 unsigned int i, j, x, y;
562 IDirectDraw2 *ddraw;
563 RGNDATA *rgn_data;
564 D3DCOLOR color;
565 ULONG refcount;
566 HRGN r1, r2;
567 HWND window;
568 DDBLTFX fx;
569 HRESULT hr;
570 DWORD *ptr;
571 DWORD ret;
573 static const DWORD src_data[] =
575 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
576 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
577 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
579 static const D3DCOLOR expected1[] =
581 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
582 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
583 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
584 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
586 /* Nvidia on Windows seems to have an off-by-one error
587 * when processing source rectangles. Our left = 1 and
588 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
589 * read as well, but only for the edge pixels on the
590 * output image. The bug happens on the y axis as well,
591 * but we only read one row there, and all source rows
592 * contain the same data. This bug is not dependent on
593 * the presence of a clipper. */
594 static const D3DCOLOR expected1_broken[] =
596 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
597 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
598 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
599 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
601 static const D3DCOLOR expected2[] =
603 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
604 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
605 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
606 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
609 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
610 10, 10, 640, 480, 0, 0, 0, 0);
611 ShowWindow(window, SW_SHOW);
612 ddraw = create_ddraw();
613 ok(!!ddraw, "Failed to create a ddraw object.\n");
615 ret = GetClientRect(window, &client_rect);
616 ok(ret, "Failed to get client rect.\n");
617 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
618 ok(ret, "Failed to map client rect.\n");
620 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
621 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
623 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
624 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
625 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
626 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
627 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
628 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
629 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
630 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
631 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
632 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
633 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
634 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
635 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
636 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
637 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
638 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
639 rgn_data->rdh.rcBound.left, rgn_data->rdh.rcBound.top,
640 rgn_data->rdh.rcBound.right, rgn_data->rdh.rcBound.bottom,
641 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
642 HeapFree(GetProcessHeap(), 0, rgn_data);
644 r1 = CreateRectRgn(0, 0, 320, 240);
645 ok(!!r1, "Failed to create region.\n");
646 r2 = CreateRectRgn(320, 240, 640, 480);
647 ok(!!r2, "Failed to create region.\n");
648 CombineRgn(r1, r1, r2, RGN_OR);
649 ret = GetRegionData(r1, 0, NULL);
650 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
651 ret = GetRegionData(r1, ret, rgn_data);
652 ok(!!ret, "Failed to get region data.\n");
654 DeleteObject(r2);
655 DeleteObject(r1);
657 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
658 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
659 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
660 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
661 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
662 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
664 HeapFree(GetProcessHeap(), 0, rgn_data);
666 memset(&surface_desc, 0, sizeof(surface_desc));
667 surface_desc.dwSize = sizeof(surface_desc);
668 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
669 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
670 surface_desc.dwWidth = 640;
671 surface_desc.dwHeight = 480;
672 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
673 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
674 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
675 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
676 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
677 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
679 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
680 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
681 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
682 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
684 memset(&fx, 0, sizeof(fx));
685 fx.dwSize = sizeof(fx);
686 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
687 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
688 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
689 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
691 hr = IDirectDrawSurface_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
692 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
693 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
694 ptr = surface_desc.lpSurface;
695 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
696 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
697 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
698 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
699 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
701 hr = IDirectDrawSurface_SetClipper(dst_surface, clipper);
702 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
704 SetRect(&src_rect, 1, 1, 5, 2);
705 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
706 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
707 for (i = 0; i < 4; ++i)
709 for (j = 0; j < 4; ++j)
711 x = 80 * ((2 * j) + 1);
712 y = 60 * ((2 * i) + 1);
713 color = get_surface_color(dst_surface, x, y);
714 ok(compare_color(color, expected1[i * 4 + j], 1)
715 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
716 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
720 U5(fx).dwFillColor = 0xff0000ff;
721 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
722 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
723 for (i = 0; i < 4; ++i)
725 for (j = 0; j < 4; ++j)
727 x = 80 * ((2 * j) + 1);
728 y = 60 * ((2 * i) + 1);
729 color = get_surface_color(dst_surface, x, y);
730 ok(compare_color(color, expected2[i * 4 + j], 1),
731 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
735 hr = IDirectDrawSurface_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
736 ok(hr == DDERR_BLTFASTCANTCLIP || broken(hr == E_NOTIMPL /* NT4 */), "Got unexpected hr %#x.\n", hr);
738 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
739 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
740 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
741 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
742 DestroyWindow(window);
743 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
744 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
745 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
746 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
747 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
748 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
749 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
750 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
751 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
752 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
753 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
754 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
756 IDirectDrawSurface_Release(dst_surface);
757 IDirectDrawSurface_Release(src_surface);
758 refcount = IDirectDrawClipper_Release(clipper);
759 ok(!refcount, "Clipper has %u references left.\n", refcount);
760 IDirectDraw2_Release(ddraw);
763 static void test_coop_level_d3d_state(void)
765 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
766 IDirectDrawSurface *rt, *surface;
767 IDirect3DMaterial2 *background;
768 IDirect3DViewport2 *viewport;
769 IDirect3DDevice2 *device;
770 D3DMATERIAL material;
771 IDirectDraw2 *ddraw;
772 D3DCOLOR color;
773 DWORD value;
774 HWND window;
775 HRESULT hr;
777 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
778 0, 0, 640, 480, 0, 0, 0, 0);
779 ddraw = create_ddraw();
780 ok(!!ddraw, "Failed to create a ddraw object.\n");
781 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
783 skip("Failed to create a 3D device, skipping test.\n");
784 IDirectDraw2_Release(ddraw);
785 DestroyWindow(window);
786 return;
789 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
790 viewport = create_viewport(device, 0, 0, 640, 480);
791 viewport_set_background(device, viewport, background);
793 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
794 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
795 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
796 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
797 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
798 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
799 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
800 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
801 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
802 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
803 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
804 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
805 color = get_surface_color(rt, 320, 240);
806 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
808 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
809 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
810 hr = IDirectDrawSurface_IsLost(rt);
811 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
812 hr = restore_surfaces(ddraw);
813 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
815 memset(&material, 0, sizeof(material));
816 material.dwSize = sizeof(material);
817 U1(U(material).diffuse).r = 0.0f;
818 U2(U(material).diffuse).g = 1.0f;
819 U3(U(material).diffuse).b = 0.0f;
820 U4(U(material).diffuse).a = 1.0f;
821 hr = IDirect3DMaterial2_SetMaterial(background, &material);
822 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
824 hr = IDirect3DDevice2_GetRenderTarget(device, &surface);
825 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
826 ok(surface == rt, "Got unexpected surface %p.\n", surface);
827 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
828 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
829 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
830 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
831 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
832 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
833 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
834 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
835 color = get_surface_color(rt, 320, 240);
836 ok(compare_color(color, 0x0000ff00, 1) || broken(compare_color(color, 0x00000000, 1)),
837 "Got unexpected color 0x%08x.\n", color);
839 destroy_viewport(device, viewport);
840 destroy_material(background);
841 IDirectDrawSurface_Release(surface);
842 IDirectDrawSurface_Release(rt);
843 IDirect3DDevice2_Release(device);
844 IDirectDraw2_Release(ddraw);
845 DestroyWindow(window);
848 static void test_surface_interface_mismatch(void)
850 IDirectDraw2 *ddraw = NULL;
851 IDirect3D2 *d3d = NULL;
852 IDirectDrawSurface *surface = NULL, *ds;
853 IDirectDrawSurface3 *surface3 = NULL;
854 IDirect3DDevice2 *device = NULL;
855 IDirect3DViewport2 *viewport = NULL;
856 IDirect3DMaterial2 *background = NULL;
857 DDSURFACEDESC surface_desc;
858 DWORD z_depth = 0;
859 ULONG refcount;
860 HRESULT hr;
861 D3DCOLOR color;
862 HWND window;
863 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
865 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
866 0, 0, 640, 480, 0, 0, 0, 0);
867 ddraw = create_ddraw();
868 ok(!!ddraw, "Failed to create a ddraw object.\n");
869 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
871 skip("Failed to create a 3D device, skipping test.\n");
872 IDirectDraw2_Release(ddraw);
873 DestroyWindow(window);
874 return;
876 z_depth = get_device_z_depth(device);
877 ok(!!z_depth, "Failed to get device z depth.\n");
878 IDirect3DDevice2_Release(device);
879 device = NULL;
881 memset(&surface_desc, 0, sizeof(surface_desc));
882 surface_desc.dwSize = sizeof(surface_desc);
883 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
884 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
885 surface_desc.dwWidth = 640;
886 surface_desc.dwHeight = 480;
888 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
889 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
891 hr = IDirectDrawSurface2_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
892 if (FAILED(hr))
894 skip("Failed to get the IDirectDrawSurface3 interface, skipping test.\n");
895 goto cleanup;
898 if (FAILED(IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d)))
900 skip("D3D interface is not available, skipping test.\n");
901 goto cleanup;
904 memset(&surface_desc, 0, sizeof(surface_desc));
905 surface_desc.dwSize = sizeof(surface_desc);
906 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
907 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
908 U2(surface_desc).dwZBufferBitDepth = z_depth;
909 surface_desc.dwWidth = 640;
910 surface_desc.dwHeight = 480;
911 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
912 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
913 if (FAILED(hr))
914 goto cleanup;
916 /* Using a different surface interface version still works */
917 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
918 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
919 refcount = IDirectDrawSurface_Release(ds);
920 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
921 if (FAILED(hr))
922 goto cleanup;
924 /* Here too */
925 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface *)surface3, &device);
926 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
927 if (FAILED(hr))
928 goto cleanup;
930 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
931 viewport = create_viewport(device, 0, 0, 640, 480);
932 viewport_set_background(device, viewport, background);
934 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
935 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
936 color = get_surface_color(surface, 320, 240);
937 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
939 cleanup:
940 if (viewport)
941 destroy_viewport(device, viewport);
942 if (background)
943 destroy_material(background);
944 if (surface3) IDirectDrawSurface3_Release(surface3);
945 if (surface) IDirectDrawSurface_Release(surface);
946 if (device) IDirect3DDevice2_Release(device);
947 if (d3d) IDirect3D2_Release(d3d);
948 if (ddraw) IDirectDraw2_Release(ddraw);
949 DestroyWindow(window);
952 static void test_coop_level_threaded(void)
954 struct create_window_thread_param p;
955 IDirectDraw2 *ddraw;
956 HRESULT hr;
958 ddraw = create_ddraw();
959 ok(!!ddraw, "Failed to create a ddraw object.\n");
960 create_window_thread(&p);
962 hr = IDirectDraw2_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
963 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
965 IDirectDraw2_Release(ddraw);
966 destroy_window_thread(&p);
969 static void test_depth_blit(void)
971 static D3DLVERTEX quad1[] =
973 {{-1.0}, { 1.0}, {0.50f}, 0, {0xff00ff00}},
974 {{ 1.0}, { 1.0}, {0.50f}, 0, {0xff00ff00}},
975 {{-1.0}, {-1.0}, {0.50f}, 0, {0xff00ff00}},
976 {{ 1.0}, {-1.0}, {0.50f}, 0, {0xff00ff00}},
978 static const D3DCOLOR expected_colors[4][4] =
980 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
981 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
982 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
983 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
985 DDSURFACEDESC ddsd_new, ddsd_existing;
987 IDirect3DDevice2 *device;
988 IDirectDrawSurface *ds1, *ds2, *ds3, *rt;
989 IDirect3DViewport2 *viewport;
990 RECT src_rect, dst_rect;
991 unsigned int i, j;
992 D3DCOLOR color;
993 HRESULT hr;
994 IDirectDraw2 *ddraw;
995 DDBLTFX fx;
996 HWND window;
997 D3DRECT d3drect;
998 IDirect3DMaterial2 *background;
1000 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1001 0, 0, 640, 480, 0, 0, 0, 0);
1002 ddraw = create_ddraw();
1003 ok(!!ddraw, "Failed to create a ddraw object.\n");
1004 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1006 skip("Failed to create a 3D device, skipping test.\n");
1007 IDirectDraw2_Release(ddraw);
1008 DestroyWindow(window);
1009 return;
1012 ds1 = get_depth_stencil(device);
1014 memset(&ddsd_new, 0, sizeof(ddsd_new));
1015 ddsd_new.dwSize = sizeof(ddsd_new);
1016 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1017 ddsd_existing.dwSize = sizeof(ddsd_existing);
1018 hr = IDirectDrawSurface_GetSurfaceDesc(ds1, &ddsd_existing);
1019 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
1020 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1021 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1022 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1023 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1024 ddsd_new.ddpfPixelFormat = ddsd_existing.ddpfPixelFormat;
1025 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1026 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1027 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1028 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1030 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1031 viewport = create_viewport(device, 0, 0, ddsd_existing.dwWidth, ddsd_existing.dwHeight);
1032 viewport_set_background(device, viewport, background);
1033 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1034 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
1036 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1037 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
1038 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1039 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
1041 U1(d3drect).x1 = U2(d3drect).y1 = 0;
1042 U3(d3drect).x2 = ddsd_existing.dwWidth; U4(d3drect).y2 = ddsd_existing.dwHeight;
1043 hr = IDirect3DViewport2_Clear(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER);
1044 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
1046 /* Partial blit. */
1047 SetRect(&src_rect, 0, 0, 320, 240);
1048 SetRect(&dst_rect, 0, 0, 320, 240);
1049 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1050 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1051 /* Different locations. */
1052 SetRect(&src_rect, 0, 0, 320, 240);
1053 SetRect(&dst_rect, 320, 240, 640, 480);
1054 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1055 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1056 /* Streched. */
1057 SetRect(&src_rect, 0, 0, 320, 240);
1058 SetRect(&dst_rect, 0, 0, 640, 480);
1059 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1060 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1061 /* Flipped. */
1062 SetRect(&src_rect, 0, 480, 640, 0);
1063 SetRect(&dst_rect, 0, 0, 640, 480);
1064 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1065 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1066 SetRect(&src_rect, 0, 0, 640, 480);
1067 SetRect(&dst_rect, 0, 480, 640, 0);
1068 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1069 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1070 /* Full, explicit. */
1071 SetRect(&src_rect, 0, 0, 640, 480);
1072 SetRect(&dst_rect, 0, 0, 640, 480);
1073 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1074 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1075 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1077 /* Depth blit inside a BeginScene / EndScene pair */
1078 hr = IDirect3DDevice2_BeginScene(device);
1079 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1080 /* From the current depth stencil */
1081 hr = IDirectDrawSurface_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1082 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1083 /* To the current depth stencil */
1084 hr = IDirectDrawSurface_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1085 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1086 /* Between unbound surfaces */
1087 hr = IDirectDrawSurface_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1088 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1089 hr = IDirect3DDevice2_EndScene(device);
1090 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1092 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1093 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1094 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1095 * a reliable result(z = 0.0) */
1096 memset(&fx, 0, sizeof(fx));
1097 fx.dwSize = sizeof(fx);
1098 U5(fx).dwFillDepth = 0;
1099 hr = IDirectDrawSurface_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1100 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1102 /* This clears the Z buffer with 1.0 */
1103 hr = IDirect3DViewport2_Clear(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET);
1104 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1106 SetRect(&dst_rect, 0, 0, 320, 240);
1107 hr = IDirectDrawSurface_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1108 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1109 IDirectDrawSurface_Release(ds3);
1110 IDirectDrawSurface_Release(ds2);
1111 IDirectDrawSurface_Release(ds1);
1113 hr = IDirect3DDevice2_BeginScene(device);
1114 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1115 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad1, 4, 0);
1116 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1117 hr = IDirect3DDevice2_EndScene(device);
1118 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1120 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1121 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1122 for (i = 0; i < 4; ++i)
1124 for (j = 0; j < 4; ++j)
1126 unsigned int x = 80 * ((2 * j) + 1);
1127 unsigned int y = 60 * ((2 * i) + 1);
1128 color = get_surface_color(rt, x, y);
1129 ok(compare_color(color, expected_colors[i][j], 1),
1130 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1133 IDirectDrawSurface_Release(rt);
1135 destroy_viewport(device, viewport);
1136 destroy_material(background);
1137 IDirect3DDevice2_Release(device);
1138 IDirectDraw2_Release(ddraw);
1139 DestroyWindow(window);
1142 static void test_texture_load_ckey(void)
1144 IDirectDraw2 *ddraw = NULL;
1145 IDirectDrawSurface *src = NULL;
1146 IDirectDrawSurface *dst = NULL;
1147 IDirect3DTexture *src_tex = NULL;
1148 IDirect3DTexture *dst_tex = NULL;
1149 DDSURFACEDESC ddsd;
1150 HRESULT hr;
1151 DDCOLORKEY ckey;
1153 ddraw = create_ddraw();
1154 ok(!!ddraw, "Failed to create a ddraw object.\n");
1155 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
1156 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1158 memset(&ddsd, 0, sizeof(ddsd));
1159 ddsd.dwSize = sizeof(ddsd);
1160 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1161 ddsd.dwHeight = 128;
1162 ddsd.dwWidth = 128;
1163 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1164 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &src, NULL);
1165 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1166 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1167 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &dst, NULL);
1168 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1170 hr = IDirectDrawSurface_QueryInterface(src, &IID_IDirect3DTexture, (void **)&src_tex);
1171 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get Direct3DTexture interface, hr %#x.\n", hr);
1172 if (FAILED(hr))
1174 /* 64 bit ddraw does not support d3d */
1175 skip("Could not get Direct3DTexture interface, skipping texture::Load color keying tests.\n");
1176 goto done;
1178 hr = IDirectDrawSurface_QueryInterface(dst, &IID_IDirect3DTexture, (void **)&dst_tex);
1179 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture interface, hr %#x.\n", hr);
1181 /* No surface has a color key */
1182 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1183 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDCAPS), "Got unexpected hr %#x.\n", hr);
1184 if (FAILED(hr))
1186 /* Testbot Windows NT VMs */
1187 skip("IDirect3DTexture::Load does not work, skipping color keying tests.\n");
1188 goto done;
1191 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1192 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1193 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1194 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1195 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1197 /* Source surface has a color key */
1198 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1199 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1200 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1201 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1202 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1203 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1204 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1205 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1206 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1208 /* Both surfaces have a color key: Dest ckey is overwritten */
1209 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1210 hr = IDirectDrawSurface_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1211 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1212 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1213 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1214 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1215 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1216 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1217 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1219 /* Only the destination has a color key: It is not deleted */
1220 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1221 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1222 hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1223 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1224 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1225 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1226 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1227 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1228 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1229 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1231 done:
1232 if (dst_tex) IDirect3DTexture_Release(dst_tex);
1233 if (src_tex) IDirect3DTexture_Release(src_tex);
1234 if (dst) IDirectDrawSurface_Release(dst);
1235 if (src) IDirectDrawSurface_Release(src);
1236 if (ddraw) IDirectDraw2_Release(ddraw);
1239 static ULONG get_refcount(IUnknown *test_iface)
1241 IUnknown_AddRef(test_iface);
1242 return IUnknown_Release(test_iface);
1245 static void test_viewport(void)
1247 IDirectDraw2 *ddraw;
1248 IDirect3D2 *d3d;
1249 HRESULT hr;
1250 ULONG ref, old_d3d_ref;
1251 IDirect3DViewport *viewport;
1252 IDirect3DViewport2 *viewport2, *another_vp, *test_vp;
1253 IDirect3DViewport3 *viewport3;
1254 IDirectDrawGammaControl *gamma;
1255 IUnknown *unknown;
1256 IDirect3DDevice2 *device;
1257 HWND window;
1259 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1260 0, 0, 640, 480, 0, 0, 0, 0);
1261 ddraw = create_ddraw();
1262 ok(!!ddraw, "Failed to create a ddraw object.\n");
1263 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1265 skip("Failed to create a 3D device, skipping test.\n");
1266 IDirectDraw_Release(ddraw);
1267 DestroyWindow(window);
1268 return;
1271 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
1272 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get d3d interface, hr %#x.\n", hr);
1273 if (FAILED(hr))
1275 skip("D3D interface is not available, skipping test.\n");
1276 IDirectDraw2_Release(ddraw);
1277 return;
1279 old_d3d_ref = get_refcount((IUnknown *)d3d);
1281 hr = IDirect3D2_CreateViewport(d3d, &viewport2, NULL);
1282 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1283 ref = get_refcount((IUnknown *)viewport2);
1284 ok(ref == 1, "Initial IDirect3DViewport2 refcount is %u\n", ref);
1285 ref = get_refcount((IUnknown *)d3d);
1286 ok(ref == old_d3d_ref, "IDirect3D2 refcount is %u\n", ref);
1288 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1289 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirectDrawGammaControl, (void **)&gamma);
1290 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
1291 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
1292 if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
1293 /* NULL iid: Segfaults */
1295 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirect3DViewport, (void **)&viewport);
1296 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport, hr %#x.\n", hr);
1297 if (viewport)
1299 ref = get_refcount((IUnknown *)viewport);
1300 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1301 ref = get_refcount((IUnknown *)viewport2);
1302 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1303 IDirect3DViewport_Release(viewport);
1304 viewport = NULL;
1307 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirect3DViewport3, (void **)&viewport3);
1308 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1309 if (viewport3)
1311 ref = get_refcount((IUnknown *)viewport2);
1312 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1313 ref = get_refcount((IUnknown *)viewport3);
1314 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1315 IDirect3DViewport3_Release(viewport3);
1318 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IUnknown, (void **)&unknown);
1319 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1320 if (unknown)
1322 ref = get_refcount((IUnknown *)viewport2);
1323 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1324 ref = get_refcount(unknown);
1325 ok(ref == 2, "IUnknown refcount is %u\n", ref);
1326 IUnknown_Release(unknown);
1329 /* AddViewport(NULL): Segfault */
1330 hr = IDirect3DDevice2_DeleteViewport(device, NULL);
1331 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1332 hr = IDirect3DDevice2_GetCurrentViewport(device, NULL);
1333 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1335 hr = IDirect3D2_CreateViewport(d3d, &another_vp, NULL);
1336 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1338 /* Setting a viewport not in the viewport list fails */
1339 hr = IDirect3DDevice2_SetCurrentViewport(device, another_vp);
1340 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1342 hr = IDirect3DDevice2_AddViewport(device, viewport2);
1343 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1344 ref = get_refcount((IUnknown *) viewport2);
1345 ok(ref == 2, "viewport2 refcount is %d\n", ref);
1346 hr = IDirect3DDevice2_AddViewport(device, another_vp);
1347 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1348 ref = get_refcount((IUnknown *) another_vp);
1349 ok(ref == 2, "another_vp refcount is %d\n", ref);
1351 test_vp = (IDirect3DViewport2 *) 0xbaadc0de;
1352 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1353 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1354 ok(test_vp == (IDirect3DViewport2 *) 0xbaadc0de, "Got unexpected pointer %p\n", test_vp);
1356 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport2);
1357 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1358 ref = get_refcount((IUnknown *) viewport2);
1359 ok(ref == 3, "viewport2 refcount is %d\n", ref);
1360 ref = get_refcount((IUnknown *) device);
1361 ok(ref == 1, "device refcount is %d\n", ref);
1363 test_vp = NULL;
1364 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1365 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1366 ok(test_vp == viewport2, "Got unexpected viewport %p\n", test_vp);
1367 ref = get_refcount((IUnknown *) viewport2);
1368 ok(ref == 4, "viewport2 refcount is %d\n", ref);
1369 if(test_vp) IDirect3DViewport2_Release(test_vp);
1371 /* GetCurrentViewport with a viewport set and NULL input param: Segfault */
1373 /* Cannot set the viewport to NULL */
1374 hr = IDirect3DDevice2_SetCurrentViewport(device, NULL);
1375 ok(hr == DDERR_INVALIDPARAMS, "Failed to set viewport to NULL, hr %#x.\n", hr);
1376 test_vp = NULL;
1377 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1378 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1379 ok(test_vp == viewport2, "Got unexpected viewport %p\n", test_vp);
1380 if(test_vp) IDirect3DViewport2_Release(test_vp);
1382 /* SetCurrentViewport properly releases the old viewport's reference */
1383 hr = IDirect3DDevice2_SetCurrentViewport(device, another_vp);
1384 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1385 ref = get_refcount((IUnknown *) viewport2);
1386 ok(ref == 2, "viewport2 refcount is %d\n", ref);
1387 ref = get_refcount((IUnknown *) another_vp);
1388 ok(ref == 3, "another_vp refcount is %d\n", ref);
1390 /* Deleting the viewport removes the reference added by AddViewport, but not
1391 * the one added by SetCurrentViewport. */
1392 hr = IDirect3DDevice2_DeleteViewport(device, another_vp);
1393 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1394 ref = get_refcount((IUnknown *) another_vp);
1395 todo_wine ok(ref == 2, "IDirect3DViewport2 refcount is %d\n", ref);
1397 /* GetCurrentViewport fails though */
1398 test_vp = NULL;
1399 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1400 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1401 ok(test_vp == NULL, "Got unexpected viewport %p\n", test_vp);
1402 if(test_vp) IDirect3DViewport2_Release(test_vp);
1404 /* Setting a different viewport does not free the leaked reference. How
1405 * do I get rid of it? Leak the viewport for now. */
1406 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport2);
1407 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1408 ref = get_refcount((IUnknown *) viewport2);
1409 ok(ref == 3, "viewport2 refcount is %d\n", ref);
1410 ref = get_refcount((IUnknown *) another_vp);
1411 todo_wine ok(ref == 2, "another_vp refcount is %d\n", ref);
1413 /* Destroying the device removes the viewport, but does not free the reference
1414 * added by SetCurrentViewport. */
1415 IDirect3DDevice2_Release(device);
1416 ref = get_refcount((IUnknown *) viewport2);
1417 todo_wine ok(ref == 2, "viewport2 refcount is %d\n", ref);
1419 IDirect3DViewport2_Release(another_vp);
1420 IDirect3DViewport2_Release(viewport2);
1421 IDirect3D2_Release(d3d);
1422 DestroyWindow(window);
1423 IDirectDraw2_Release(ddraw);
1426 static void test_zenable(void)
1428 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1429 static D3DTLVERTEX tquad[] =
1431 {{ 0.0f}, {480.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1432 {{ 0.0f}, { 0.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1433 {{640.0f}, {480.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1434 {{640.0f}, { 0.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1436 IDirect3DMaterial2 *background;
1437 IDirect3DViewport2 *viewport;
1438 IDirect3DDevice2 *device;
1439 IDirectDrawSurface *rt;
1440 IDirectDraw2 *ddraw;
1441 D3DCOLOR color;
1442 HWND window;
1443 HRESULT hr;
1444 UINT x, y;
1445 UINT i, j;
1447 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1448 0, 0, 640, 480, 0, 0, 0, 0);
1449 ddraw = create_ddraw();
1450 ok(!!ddraw, "Failed to create a ddraw object.\n");
1451 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1453 skip("Failed to create a 3D device, skipping test.\n");
1454 IDirectDraw2_Release(ddraw);
1455 DestroyWindow(window);
1456 return;
1459 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1460 viewport = create_viewport(device, 0, 0, 640, 480);
1461 viewport_set_background(device, viewport, background);
1462 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1463 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1465 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1466 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1468 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1469 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1470 hr = IDirect3DDevice2_BeginScene(device);
1471 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1472 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, tquad, 4, 0);
1473 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1474 hr = IDirect3DDevice2_EndScene(device);
1475 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1477 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1478 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1479 for (i = 0; i < 4; ++i)
1481 for (j = 0; j < 4; ++j)
1483 x = 80 * ((2 * j) + 1);
1484 y = 60 * ((2 * i) + 1);
1485 color = get_surface_color(rt, x, y);
1486 ok(compare_color(color, 0x0000ff00, 1),
1487 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1490 IDirectDrawSurface_Release(rt);
1492 destroy_viewport(device, viewport);
1493 destroy_material(background);
1494 IDirect3DDevice2_Release(device);
1495 IDirectDraw2_Release(ddraw);
1496 DestroyWindow(window);
1499 static void test_ck_rgba(void)
1501 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1502 static D3DTLVERTEX tquad[] =
1504 {{ 0.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1505 {{ 0.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1506 {{640.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1507 {{640.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1508 {{ 0.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1509 {{ 0.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1510 {{640.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1511 {{640.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1513 static const struct
1515 D3DCOLOR fill_color;
1516 BOOL color_key;
1517 BOOL blend;
1518 D3DCOLOR result1, result1_broken;
1519 D3DCOLOR result2, result2_broken;
1521 tests[] =
1523 /* r200 on Windows doesn't check the alpha component when applying the color
1524 * key, so the key matches on every texel. */
1525 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1526 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1527 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1528 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1529 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00ff0000, 0x00807f00, 0x000000ff},
1530 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x00ff0000, 0x0000ff00, 0x000000ff},
1531 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00, 0x00807f00, 0x00807f00},
1532 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1535 D3DTEXTUREHANDLE texture_handle;
1536 IDirect3DMaterial2 *background;
1537 IDirectDrawSurface *surface;
1538 IDirect3DViewport2 *viewport;
1539 IDirect3DTexture2 *texture;
1540 DDSURFACEDESC surface_desc;
1541 IDirect3DDevice2 *device;
1542 IDirectDrawSurface *rt;
1543 IDirectDraw2 *ddraw;
1544 D3DCOLOR color;
1545 HWND window;
1546 DDBLTFX fx;
1547 HRESULT hr;
1548 UINT i;
1550 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1551 0, 0, 640, 480, 0, 0, 0, 0);
1552 ddraw = create_ddraw();
1553 ok(!!ddraw, "Failed to create a ddraw object.\n");
1554 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1556 skip("Failed to create a 3D device, skipping test.\n");
1557 IDirectDraw2_Release(ddraw);
1558 DestroyWindow(window);
1559 return;
1562 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1563 viewport = create_viewport(device, 0, 0, 640, 480);
1564 viewport_set_background(device, viewport, background);
1565 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1566 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1568 memset(&surface_desc, 0, sizeof(surface_desc));
1569 surface_desc.dwSize = sizeof(surface_desc);
1570 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1571 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1572 surface_desc.dwWidth = 256;
1573 surface_desc.dwHeight = 256;
1574 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1575 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1576 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1577 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1578 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1579 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1580 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1581 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1582 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1583 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1584 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1585 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1586 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1587 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
1588 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1589 IDirect3DTexture2_Release(texture);
1591 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1592 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1593 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1594 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1595 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1596 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1598 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1599 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1601 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1603 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1604 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1605 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1606 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1608 memset(&fx, 0, sizeof(fx));
1609 fx.dwSize = sizeof(fx);
1610 U5(fx).dwFillColor = tests[i].fill_color;
1611 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1612 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1614 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
1615 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1616 hr = IDirect3DDevice2_BeginScene(device);
1617 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1618 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
1619 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1620 hr = IDirect3DDevice2_EndScene(device);
1621 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1623 color = get_surface_color(rt, 320, 240);
1624 ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
1625 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1626 tests[i].result1, i, color);
1628 U5(fx).dwFillColor = 0xff0000ff;
1629 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1630 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1632 hr = IDirect3DDevice2_BeginScene(device);
1633 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1634 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[4], 4, 0);
1635 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1636 hr = IDirect3DDevice2_EndScene(device);
1637 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1639 /* This tests that fragments that are masked out by the color key are
1640 * discarded, instead of just fully transparent. */
1641 color = get_surface_color(rt, 320, 240);
1642 ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
1643 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1644 tests[i].result2, i, color);
1647 IDirectDrawSurface_Release(rt);
1648 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1649 ok(SUCCEEDED(hr), "Failed to unset texture, hr %#x.\n", hr);
1650 IDirectDrawSurface_Release(surface);
1651 destroy_viewport(device, viewport);
1652 destroy_material(background);
1653 IDirect3DDevice2_Release(device);
1654 IDirectDraw2_Release(ddraw);
1655 DestroyWindow(window);
1658 static void test_ck_default(void)
1660 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1661 static D3DTLVERTEX tquad[] =
1663 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1664 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1665 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1666 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1668 IDirectDrawSurface *surface, *rt;
1669 D3DTEXTUREHANDLE texture_handle;
1670 IDirect3DMaterial2 *background;
1671 IDirect3DViewport2 *viewport;
1672 DDSURFACEDESC surface_desc;
1673 IDirect3DTexture2 *texture;
1674 IDirect3DDevice2 *device;
1675 IDirectDraw2 *ddraw;
1676 D3DCOLOR color;
1677 DWORD value;
1678 HWND window;
1679 DDBLTFX fx;
1680 HRESULT hr;
1682 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1683 0, 0, 640, 480, 0, 0, 0, 0);
1684 ddraw = create_ddraw();
1685 ok(!!ddraw, "Failed to create a ddraw object.\n");
1686 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1688 skip("Failed to create a 3D device, skipping test.\n");
1689 IDirectDraw2_Release(ddraw);
1690 DestroyWindow(window);
1691 return;
1694 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1695 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1697 background = create_diffuse_material(device, 0.0, 1.0f, 0.0f, 1.0f);
1698 viewport = create_viewport(device, 0, 0, 640, 480);
1699 viewport_set_background(device, viewport, background);
1700 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1701 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1703 memset(&surface_desc, 0, sizeof(surface_desc));
1704 surface_desc.dwSize = sizeof(surface_desc);
1705 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1706 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1707 surface_desc.dwWidth = 256;
1708 surface_desc.dwHeight = 256;
1709 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1710 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
1711 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1712 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1713 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1714 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1715 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1716 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1717 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1718 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1719 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1720 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1721 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
1722 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1723 IDirect3DTexture_Release(texture);
1725 memset(&fx, 0, sizeof(fx));
1726 fx.dwSize = sizeof(fx);
1727 U5(fx).dwFillColor = 0x000000ff;
1728 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1729 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1731 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1732 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1733 hr = IDirect3DDevice2_BeginScene(device);
1734 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1735 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1736 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
1737 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1738 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1739 ok(!value, "Got unexpected color keying state %#x.\n", value);
1740 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
1741 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1742 hr = IDirect3DDevice2_EndScene(device);
1743 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1744 color = get_surface_color(rt, 320, 240);
1745 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1747 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1748 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1749 hr = IDirect3DDevice2_BeginScene(device);
1750 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1751 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1752 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1753 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
1754 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1755 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1756 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1757 ok(!!value, "Got unexpected color keying state %#x.\n", value);
1758 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1759 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
1760 hr = IDirect3DDevice2_EndScene(device);
1761 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1762 color = get_surface_color(rt, 320, 240);
1763 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1765 IDirectDrawSurface_Release(surface);
1766 destroy_viewport(device, viewport);
1767 destroy_material(background);
1768 IDirectDrawSurface_Release(rt);
1769 IDirect3DDevice2_Release(device);
1770 IDirectDraw2_Release(ddraw);
1771 DestroyWindow(window);
1774 static void test_ck_complex(void)
1776 IDirectDrawSurface *surface, *mipmap, *tmp;
1777 DDSCAPS caps = {DDSCAPS_COMPLEX};
1778 DDSURFACEDESC surface_desc;
1779 IDirect3DDevice2 *device;
1780 DDCOLORKEY color_key;
1781 IDirectDraw2 *ddraw;
1782 unsigned int i;
1783 ULONG refcount;
1784 HWND window;
1785 HRESULT hr;
1787 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1788 0, 0, 640, 480, 0, 0, 0, 0);
1789 ddraw = create_ddraw();
1790 ok(!!ddraw, "Failed to create a ddraw object.\n");
1791 if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
1793 skip("Failed to create a 3D device, skipping test.\n");
1794 DestroyWindow(window);
1795 IDirectDraw2_Release(ddraw);
1796 return;
1798 IDirect3DDevice2_Release(device);
1800 memset(&surface_desc, 0, sizeof(surface_desc));
1801 surface_desc.dwSize = sizeof(surface_desc);
1802 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1803 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1804 surface_desc.dwWidth = 128;
1805 surface_desc.dwHeight = 128;
1806 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1807 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1809 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1810 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1811 color_key.dwColorSpaceLowValue = 0x0000ff00;
1812 color_key.dwColorSpaceHighValue = 0x0000ff00;
1813 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1814 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1815 memset(&color_key, 0, sizeof(color_key));
1816 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1817 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1818 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1819 color_key.dwColorSpaceLowValue);
1820 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1821 color_key.dwColorSpaceHighValue);
1823 mipmap = surface;
1824 IDirectDrawSurface_AddRef(mipmap);
1825 for (i = 0; i < 7; ++i)
1827 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
1828 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1830 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1831 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1832 color_key.dwColorSpaceLowValue = 0x000000ff;
1833 color_key.dwColorSpaceHighValue = 0x000000ff;
1834 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1835 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x, i %u.\n", hr, i);
1836 memset(&color_key, 0, sizeof(color_key));
1837 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1838 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x, i %u.\n", hr, i);
1839 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
1840 color_key.dwColorSpaceLowValue, i);
1841 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
1842 color_key.dwColorSpaceHighValue, i);
1844 IDirectDrawSurface_Release(mipmap);
1845 mipmap = tmp;
1848 memset(&color_key, 0, sizeof(color_key));
1849 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1850 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1851 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1852 color_key.dwColorSpaceLowValue);
1853 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1854 color_key.dwColorSpaceHighValue);
1856 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
1857 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1858 IDirectDrawSurface_Release(mipmap);
1859 refcount = IDirectDrawSurface_Release(surface);
1860 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1862 memset(&surface_desc, 0, sizeof(surface_desc));
1863 surface_desc.dwSize = sizeof(surface_desc);
1864 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1865 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
1866 surface_desc.dwBackBufferCount = 1;
1867 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1868 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1870 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1871 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1872 color_key.dwColorSpaceLowValue = 0x0000ff00;
1873 color_key.dwColorSpaceHighValue = 0x0000ff00;
1874 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1875 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1876 memset(&color_key, 0, sizeof(color_key));
1877 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1878 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1879 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1880 color_key.dwColorSpaceLowValue);
1881 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1882 color_key.dwColorSpaceHighValue);
1884 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &tmp);
1885 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
1887 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1888 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1889 color_key.dwColorSpaceLowValue = 0x0000ff00;
1890 color_key.dwColorSpaceHighValue = 0x0000ff00;
1891 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1892 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1893 memset(&color_key, 0, sizeof(color_key));
1894 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1895 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1896 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1897 color_key.dwColorSpaceLowValue);
1898 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1899 color_key.dwColorSpaceHighValue);
1901 IDirectDrawSurface_Release(tmp);
1903 refcount = IDirectDrawSurface_Release(surface);
1904 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1905 refcount = IDirectDraw2_Release(ddraw);
1906 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1907 DestroyWindow(window);
1910 struct qi_test
1912 REFIID iid;
1913 REFIID refcount_iid;
1914 HRESULT hr;
1917 static void test_qi(const char *test_name, IUnknown *base_iface,
1918 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1920 ULONG refcount, expected_refcount;
1921 IUnknown *iface1, *iface2;
1922 HRESULT hr;
1923 UINT i, j;
1925 for (i = 0; i < entry_count; ++i)
1927 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1928 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1929 if (SUCCEEDED(hr))
1931 for (j = 0; j < entry_count; ++j)
1933 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1934 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1935 if (SUCCEEDED(hr))
1937 expected_refcount = 0;
1938 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1939 ++expected_refcount;
1940 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1941 ++expected_refcount;
1942 refcount = IUnknown_Release(iface2);
1943 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1944 refcount, test_name, i, j, expected_refcount);
1948 expected_refcount = 0;
1949 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1950 ++expected_refcount;
1951 refcount = IUnknown_Release(iface1);
1952 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1953 refcount, test_name, i, expected_refcount);
1958 static void test_surface_qi(void)
1960 static const struct qi_test tests[] =
1962 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
1963 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
1964 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1965 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1966 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1967 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1968 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1969 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1970 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1971 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1972 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1973 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1974 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1975 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1976 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1977 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1978 {&IID_IDirect3D, NULL, E_INVALIDARG },
1979 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1980 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1981 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1982 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1983 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1984 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1985 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1986 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1987 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1988 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1989 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1990 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1991 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1992 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1993 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1994 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1995 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1996 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1999 IDirectDrawSurface *surface;
2000 DDSURFACEDESC surface_desc;
2001 IDirect3DDevice2 *device;
2002 IDirectDraw2 *ddraw;
2003 HWND window;
2004 HRESULT hr;
2006 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
2008 win_skip("DirectDrawCreateEx not available, skipping test.\n");
2009 return;
2012 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2013 0, 0, 640, 480, 0, 0, 0, 0);
2014 ddraw = create_ddraw();
2015 ok(!!ddraw, "Failed to create a ddraw object.\n");
2016 /* Try to create a D3D device to see if the ddraw implementation supports
2017 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
2018 * doesn't support e.g. the IDirect3DTexture interfaces. */
2019 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2021 skip("Failed to create a 3D device, skipping test.\n");
2022 IDirectDraw2_Release(ddraw);
2023 DestroyWindow(window);
2024 return;
2026 IDirect3DDevice_Release(device);
2028 memset(&surface_desc, 0, sizeof(surface_desc));
2029 surface_desc.dwSize = sizeof(surface_desc);
2030 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2031 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2032 surface_desc.dwWidth = 512;
2033 surface_desc.dwHeight = 512;
2034 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2035 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2037 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
2039 IDirectDrawSurface_Release(surface);
2040 IDirectDraw2_Release(ddraw);
2041 DestroyWindow(window);
2044 static void test_device_qi(void)
2046 static const struct qi_test tests[] =
2048 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
2049 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
2050 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
2051 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2052 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
2053 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
2054 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
2055 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
2056 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
2057 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
2058 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
2059 {&IID_IDirect3DDevice2, &IID_IDirect3DDevice2, S_OK },
2060 {&IID_IDirect3DDevice, &IID_IDirect3DDevice2, S_OK },
2061 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2062 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2063 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2064 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2065 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2066 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2067 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2068 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2069 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2070 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2071 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2072 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2073 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2074 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2075 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2076 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2077 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2078 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2079 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2080 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2081 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2082 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2083 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2084 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2085 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2086 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2087 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2088 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2089 {&IID_IUnknown, &IID_IDirect3DDevice2, S_OK },
2092 IDirect3DDevice2 *device;
2093 IDirectDraw2 *ddraw;
2094 HWND window;
2096 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2097 0, 0, 640, 480, 0, 0, 0, 0);
2098 ddraw = create_ddraw();
2099 ok(!!ddraw, "Failed to create a ddraw object.\n");
2100 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2102 skip("Failed to create a 3D device, skipping test.\n");
2103 IDirectDraw2_Release(ddraw);
2104 DestroyWindow(window);
2105 return;
2108 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice2, tests, sizeof(tests) / sizeof(*tests));
2110 IDirect3DDevice2_Release(device);
2111 IDirectDraw2_Release(ddraw);
2112 DestroyWindow(window);
2115 static void test_wndproc(void)
2117 LONG_PTR proc, ddraw_proc;
2118 IDirectDraw2 *ddraw;
2119 WNDCLASSA wc = {0};
2120 HWND window;
2121 HRESULT hr;
2122 ULONG ref;
2124 static struct message messages[] =
2126 {WM_WINDOWPOSCHANGING, FALSE, 0},
2127 {WM_MOVE, FALSE, 0},
2128 {WM_SIZE, FALSE, 0},
2129 {WM_WINDOWPOSCHANGING, FALSE, 0},
2130 {WM_ACTIVATE, FALSE, 0},
2131 {WM_SETFOCUS, FALSE, 0},
2132 {0, FALSE, 0},
2135 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2136 ddraw = create_ddraw();
2137 ok(!!ddraw, "Failed to create a ddraw object.\n");
2139 wc.lpfnWndProc = test_proc;
2140 wc.lpszClassName = "ddraw_test_wndproc_wc";
2141 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2143 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2144 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2146 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2147 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2148 (LONG_PTR)test_proc, proc);
2149 expect_messages = messages;
2150 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2151 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2152 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2153 expect_messages = NULL;
2154 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2155 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2156 (LONG_PTR)test_proc, proc);
2157 ref = IDirectDraw2_Release(ddraw);
2158 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2159 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2160 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2161 (LONG_PTR)test_proc, proc);
2163 /* DDSCL_NORMAL doesn't. */
2164 ddraw = create_ddraw();
2165 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2166 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2167 (LONG_PTR)test_proc, proc);
2168 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2169 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2170 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2171 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2172 (LONG_PTR)test_proc, proc);
2173 ref = IDirectDraw2_Release(ddraw);
2174 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2175 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2176 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2177 (LONG_PTR)test_proc, proc);
2179 /* The original window proc is only restored by ddraw if the current
2180 * window proc matches the one ddraw set. This also affects switching
2181 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2182 ddraw = create_ddraw();
2183 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2184 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2185 (LONG_PTR)test_proc, proc);
2186 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2187 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2188 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2189 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2190 (LONG_PTR)test_proc, proc);
2191 ddraw_proc = proc;
2192 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2193 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2194 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2195 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2196 (LONG_PTR)test_proc, proc);
2197 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2198 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2199 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2200 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2201 (LONG_PTR)test_proc, proc);
2202 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2203 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2204 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2205 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2206 (LONG_PTR)DefWindowProcA, proc);
2207 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2208 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2209 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
2210 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2211 (LONG_PTR)DefWindowProcA, proc);
2212 ref = IDirectDraw2_Release(ddraw);
2213 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2214 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2215 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2216 (LONG_PTR)test_proc, proc);
2218 ddraw = create_ddraw();
2219 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2220 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2221 (LONG_PTR)test_proc, proc);
2222 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2223 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2224 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2225 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2226 (LONG_PTR)test_proc, proc);
2227 ref = IDirectDraw2_Release(ddraw);
2228 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2229 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2230 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2231 (LONG_PTR)DefWindowProcA, proc);
2233 fix_wndproc(window, (LONG_PTR)test_proc);
2234 expect_messages = NULL;
2235 DestroyWindow(window);
2236 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2239 static void test_window_style(void)
2241 LONG style, exstyle, tmp, expected_style;
2242 RECT fullscreen_rect, r;
2243 IDirectDraw2 *ddraw;
2244 HWND window;
2245 HRESULT hr;
2246 ULONG ref;
2247 BOOL ret;
2249 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2250 0, 0, 100, 100, 0, 0, 0, 0);
2251 ddraw = create_ddraw();
2252 ok(!!ddraw, "Failed to create a ddraw object.\n");
2254 style = GetWindowLongA(window, GWL_STYLE);
2255 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2256 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2258 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2259 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2261 tmp = GetWindowLongA(window, GWL_STYLE);
2262 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2263 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2264 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2266 GetWindowRect(window, &r);
2267 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2268 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2269 r.left, r.top, r.right, r.bottom);
2270 GetClientRect(window, &r);
2271 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2273 ret = SetForegroundWindow(GetDesktopWindow());
2274 ok(ret, "Failed to set foreground window.\n");
2276 tmp = GetWindowLongA(window, GWL_STYLE);
2277 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2278 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2279 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2281 ret = SetForegroundWindow(window);
2282 ok(ret, "Failed to set foreground window.\n");
2283 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2284 * the next tests expect this. */
2285 ShowWindow(window, SW_HIDE);
2287 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2288 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2290 tmp = GetWindowLongA(window, GWL_STYLE);
2291 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2292 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2293 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2295 ShowWindow(window, SW_SHOW);
2296 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2297 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2299 tmp = GetWindowLongA(window, GWL_STYLE);
2300 expected_style = style | WS_VISIBLE;
2301 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2302 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2303 expected_style = exstyle | WS_EX_TOPMOST;
2304 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2306 ret = SetForegroundWindow(GetDesktopWindow());
2307 ok(ret, "Failed to set foreground window.\n");
2308 tmp = GetWindowLongA(window, GWL_STYLE);
2309 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
2310 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2311 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2312 expected_style = exstyle | WS_EX_TOPMOST;
2313 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2315 ref = IDirectDraw2_Release(ddraw);
2316 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2318 DestroyWindow(window);
2321 static void test_redundant_mode_set(void)
2323 DDSURFACEDESC surface_desc = {0};
2324 IDirectDraw2 *ddraw;
2325 HWND window;
2326 HRESULT hr;
2327 RECT r, s;
2328 ULONG ref;
2330 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2331 0, 0, 100, 100, 0, 0, 0, 0);
2332 ddraw = create_ddraw();
2333 ok(!!ddraw, "Failed to create a ddraw object.\n");
2335 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2336 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2338 surface_desc.dwSize = sizeof(surface_desc);
2339 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
2340 ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
2342 hr = IDirectDraw2_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2343 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, 0, 0);
2344 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2346 GetWindowRect(window, &r);
2347 r.right /= 2;
2348 r.bottom /= 2;
2349 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2350 GetWindowRect(window, &s);
2351 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2352 r.left, r.top, r.right, r.bottom,
2353 s.left, s.top, s.right, s.bottom);
2355 hr = IDirectDraw2_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2356 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, 0, 0);
2357 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2359 GetWindowRect(window, &s);
2360 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2361 r.left, r.top, r.right, r.bottom,
2362 s.left, s.top, s.right, s.bottom);
2364 ref = IDirectDraw2_Release(ddraw);
2365 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2367 DestroyWindow(window);
2370 static SIZE screen_size, screen_size2;
2372 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2374 if (message == WM_SIZE)
2376 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2377 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2380 return test_proc(hwnd, message, wparam, lparam);
2383 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2385 if (message == WM_SIZE)
2387 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
2388 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
2391 return test_proc(hwnd, message, wparam, lparam);
2394 struct test_coop_level_mode_set_enum_param
2396 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
2399 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC *surface_desc, void *context)
2401 struct test_coop_level_mode_set_enum_param *param = context;
2403 if (U1(surface_desc->ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
2404 return DDENUMRET_OK;
2405 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
2406 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
2407 return DDENUMRET_OK;
2409 if (!param->ddraw_width)
2411 param->ddraw_width = surface_desc->dwWidth;
2412 param->ddraw_height = surface_desc->dwHeight;
2413 return DDENUMRET_OK;
2415 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
2416 return DDENUMRET_OK;
2418 param->user32_width = surface_desc->dwWidth;
2419 param->user32_height = surface_desc->dwHeight;
2420 return DDENUMRET_CANCEL;
2423 static void test_coop_level_mode_set(void)
2425 IDirectDrawSurface *primary;
2426 RECT registry_rect, ddraw_rect, user32_rect, r;
2427 IDirectDraw2 *ddraw;
2428 DDSURFACEDESC ddsd;
2429 WNDCLASSA wc = {0};
2430 HWND window, window2;
2431 HRESULT hr;
2432 ULONG ref;
2433 MSG msg;
2434 struct test_coop_level_mode_set_enum_param param;
2435 DEVMODEW devmode;
2436 BOOL ret;
2437 LONG change_ret;
2439 static const struct message exclusive_messages[] =
2441 {WM_WINDOWPOSCHANGING, FALSE, 0},
2442 {WM_WINDOWPOSCHANGED, FALSE, 0},
2443 {WM_SIZE, FALSE, 0},
2444 {WM_DISPLAYCHANGE, FALSE, 0},
2445 {0, FALSE, 0},
2447 static const struct message exclusive_focus_loss_messages[] =
2449 {WM_ACTIVATE, TRUE, WA_INACTIVE},
2450 {WM_DISPLAYCHANGE, FALSE, 0},
2451 {WM_WINDOWPOSCHANGING, FALSE, 0},
2452 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
2453 * SW_MINIMIZED, causing a recursive window activation that does not
2454 * produce the same result in Wine yet. Ignore the difference for now.
2455 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
2456 {WM_WINDOWPOSCHANGED, FALSE, 0},
2457 {WM_MOVE, FALSE, 0},
2458 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2459 {WM_ACTIVATEAPP, TRUE, FALSE},
2460 {0, FALSE, 0},
2462 static const struct message exclusive_focus_restore_messages[] =
2464 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
2465 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
2466 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
2467 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
2468 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
2469 /* Native redundantly sets the window size here. */
2470 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
2471 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
2472 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
2473 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
2474 {0, FALSE, 0},
2476 static const struct message sc_restore_messages[] =
2478 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
2479 {WM_WINDOWPOSCHANGING, FALSE, 0},
2480 {WM_WINDOWPOSCHANGED, FALSE, 0},
2481 {WM_SIZE, TRUE, SIZE_RESTORED},
2482 {0, FALSE, 0},
2484 static const struct message sc_minimize_messages[] =
2486 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
2487 {WM_WINDOWPOSCHANGING, FALSE, 0},
2488 {WM_WINDOWPOSCHANGED, FALSE, 0},
2489 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2490 {0, FALSE, 0},
2492 static const struct message sc_maximize_messages[] =
2494 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
2495 {WM_WINDOWPOSCHANGING, FALSE, 0},
2496 {WM_WINDOWPOSCHANGED, FALSE, 0},
2497 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
2498 {0, FALSE, 0},
2501 static const struct message normal_messages[] =
2503 {WM_DISPLAYCHANGE, FALSE, 0},
2504 {0, FALSE, 0},
2507 ddraw = create_ddraw();
2508 ok(!!ddraw, "Failed to create a ddraw object.\n");
2510 memset(&param, 0, sizeof(param));
2511 hr = IDirectDraw2_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
2512 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2513 ref = IDirectDraw2_Release(ddraw);
2514 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2516 if (!param.user32_height)
2518 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
2519 return;
2522 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2523 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
2524 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
2526 memset(&devmode, 0, sizeof(devmode));
2527 devmode.dmSize = sizeof(devmode);
2528 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2529 devmode.dmPelsWidth = param.user32_width;
2530 devmode.dmPelsHeight = param.user32_height;
2531 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2532 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2534 ddraw = create_ddraw();
2535 ok(!!ddraw, "Failed to create a ddraw object.\n");
2537 wc.lpfnWndProc = mode_set_proc;
2538 wc.lpszClassName = "ddraw_test_wndproc_wc";
2539 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2540 wc.lpfnWndProc = mode_set_proc2;
2541 wc.lpszClassName = "ddraw_test_wndproc_wc2";
2542 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2544 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2545 0, 0, 100, 100, 0, 0, 0, 0);
2546 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
2547 0, 0, 100, 100, 0, 0, 0, 0);
2549 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2550 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2552 GetWindowRect(window, &r);
2553 ok(EqualRect(&r, &user32_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2554 user32_rect.left, user32_rect.top, user32_rect.right, user32_rect.bottom,
2555 r.left, r.top, r.right, r.bottom);
2557 memset(&ddsd, 0, sizeof(ddsd));
2558 ddsd.dwSize = sizeof(ddsd);
2559 ddsd.dwFlags = DDSD_CAPS;
2560 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2562 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2563 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2564 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2565 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2566 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2567 param.user32_width, ddsd.dwWidth);
2568 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2569 param.user32_height, ddsd.dwHeight);
2571 GetWindowRect(window, &r);
2572 ok(EqualRect(&r, &user32_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2573 user32_rect.left, user32_rect.top, user32_rect.right, user32_rect.bottom,
2574 r.left, r.top, r.right, r.bottom);
2576 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2577 expect_messages = exclusive_messages;
2578 screen_size.cx = 0;
2579 screen_size.cy = 0;
2581 hr = IDirectDrawSurface_IsLost(primary);
2582 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2583 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2584 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2585 hr = IDirectDrawSurface_IsLost(primary);
2586 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2588 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2589 expect_messages = NULL;
2590 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
2591 "Expected screen size %ux%u, got %ux%u.\n",
2592 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
2594 GetWindowRect(window, &r);
2595 ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2596 ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
2597 r.left, r.top, r.right, r.bottom);
2599 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2600 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2601 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2602 param.user32_width, ddsd.dwWidth);
2603 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2604 param.user32_height, ddsd.dwHeight);
2605 IDirectDrawSurface_Release(primary);
2607 memset(&ddsd, 0, sizeof(ddsd));
2608 ddsd.dwSize = sizeof(ddsd);
2609 ddsd.dwFlags = DDSD_CAPS;
2610 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2612 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2613 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2614 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2615 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2616 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2617 param.ddraw_width, ddsd.dwWidth);
2618 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2619 param.ddraw_height, ddsd.dwHeight);
2621 GetWindowRect(window, &r);
2622 ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2623 ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
2624 r.left, r.top, r.right, r.bottom);
2626 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2627 expect_messages = exclusive_messages;
2628 screen_size.cx = 0;
2629 screen_size.cy = 0;
2631 hr = IDirectDrawSurface_IsLost(primary);
2632 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2633 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2634 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2635 hr = IDirectDrawSurface_IsLost(primary);
2636 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2638 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2639 expect_messages = NULL;
2640 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
2641 "Expected screen size %ux%u, got %ux%u.\n",
2642 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
2644 GetWindowRect(window, &r);
2645 ok(EqualRect(&r, &user32_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2646 user32_rect.left, user32_rect.top, user32_rect.right, user32_rect.bottom,
2647 r.left, r.top, r.right, r.bottom);
2649 expect_messages = exclusive_focus_loss_messages;
2650 ret = SetForegroundWindow(GetDesktopWindow());
2651 ok(ret, "Failed to set foreground window.\n");
2652 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2653 memset(&devmode, 0, sizeof(devmode));
2654 devmode.dmSize = sizeof(devmode);
2655 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2656 ok(ret, "Failed to get display mode.\n");
2657 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2658 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
2659 devmode.dmPelsWidth, devmode.dmPelsHeight);
2661 expect_messages = exclusive_focus_restore_messages;
2662 ShowWindow(window, SW_RESTORE);
2663 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2665 GetWindowRect(window, &r);
2666 ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2667 ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
2668 r.left, r.top, r.right, r.bottom);
2669 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2670 ok(ret, "Failed to get display mode.\n");
2671 ok(devmode.dmPelsWidth == param.ddraw_width
2672 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpect screen size %ux%u.\n",
2673 devmode.dmPelsWidth, devmode.dmPelsHeight);
2675 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2676 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2677 /* Normally the primary should be restored here. Unfortunately this causes the
2678 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
2679 * testbot. Another Restore call would presumably avoid the crash, but it also moots
2680 * the point of the GetSurfaceDesc call. */
2682 expect_messages = sc_minimize_messages;
2683 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
2684 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2685 expect_messages = NULL;
2687 expect_messages = sc_restore_messages;
2688 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
2689 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2690 expect_messages = NULL;
2692 expect_messages = sc_maximize_messages;
2693 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
2694 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2695 expect_messages = NULL;
2697 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2698 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2700 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2701 expect_messages = exclusive_messages;
2702 screen_size.cx = 0;
2703 screen_size.cy = 0;
2705 hr = IDirectDrawSurface_IsLost(primary);
2706 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2707 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
2708 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2709 hr = IDirectDrawSurface_IsLost(primary);
2710 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2712 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2713 expect_messages = NULL;
2714 ok(screen_size.cx == registry_mode.dmPelsWidth
2715 && screen_size.cy == registry_mode.dmPelsHeight,
2716 "Expected screen size %ux%u, got %ux%u.\n",
2717 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
2719 GetWindowRect(window, &r);
2720 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2721 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2722 r.left, r.top, r.right, r.bottom);
2724 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2725 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2726 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2727 param.ddraw_width, ddsd.dwWidth);
2728 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2729 param.ddraw_height, ddsd.dwHeight);
2730 IDirectDrawSurface_Release(primary);
2732 /* For Wine. */
2733 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2734 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2736 memset(&ddsd, 0, sizeof(ddsd));
2737 ddsd.dwSize = sizeof(ddsd);
2738 ddsd.dwFlags = DDSD_CAPS;
2739 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2741 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2742 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2743 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2744 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2745 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2746 registry_mode.dmPelsWidth, ddsd.dwWidth);
2747 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2748 registry_mode.dmPelsHeight, ddsd.dwHeight);
2750 GetWindowRect(window, &r);
2751 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2752 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2753 r.left, r.top, r.right, r.bottom);
2755 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2756 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2758 GetWindowRect(window, &r);
2759 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2760 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2761 r.left, r.top, r.right, r.bottom);
2763 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2764 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2765 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2766 registry_mode.dmPelsWidth, ddsd.dwWidth);
2767 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2768 registry_mode.dmPelsHeight, ddsd.dwHeight);
2769 IDirectDrawSurface_Release(primary);
2771 memset(&ddsd, 0, sizeof(ddsd));
2772 ddsd.dwSize = sizeof(ddsd);
2773 ddsd.dwFlags = DDSD_CAPS;
2774 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2776 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2777 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2778 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2779 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2780 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2781 registry_mode.dmPelsWidth, ddsd.dwWidth);
2782 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2783 registry_mode.dmPelsHeight, ddsd.dwHeight);
2785 GetWindowRect(window, &r);
2786 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2787 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2788 r.left, r.top, r.right, r.bottom);
2790 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2791 expect_messages = normal_messages;
2792 screen_size.cx = 0;
2793 screen_size.cy = 0;
2795 hr = IDirectDrawSurface_IsLost(primary);
2796 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2797 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2798 devmode.dmPelsWidth = param.user32_width;
2799 devmode.dmPelsHeight = param.user32_height;
2800 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2801 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2802 hr = IDirectDrawSurface_IsLost(primary);
2803 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2805 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2806 expect_messages = NULL;
2807 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2809 GetWindowRect(window, &r);
2810 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2811 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2812 r.left, r.top, r.right, r.bottom);
2814 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2815 expect_messages = normal_messages;
2816 screen_size.cx = 0;
2817 screen_size.cy = 0;
2819 hr = IDirectDrawSurface_Restore(primary);
2820 todo_wine ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2821 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2822 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
2824 win_skip("Broken SetDisplayMode(), skipping remaining tests.\n");
2825 IDirectDrawSurface_Release(primary);
2826 IDirectDraw2_Release(ddraw);
2827 goto done;
2829 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2830 hr = IDirectDrawSurface_Restore(primary);
2831 todo_wine ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2832 hr = IDirectDrawSurface_IsLost(primary);
2833 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2835 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2836 expect_messages = NULL;
2837 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2839 GetWindowRect(window, &r);
2840 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2841 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2842 r.left, r.top, r.right, r.bottom);
2844 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2845 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2846 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2847 registry_mode.dmPelsWidth, ddsd.dwWidth);
2848 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2849 registry_mode.dmPelsHeight, ddsd.dwHeight);
2850 IDirectDrawSurface_Release(primary);
2852 memset(&ddsd, 0, sizeof(ddsd));
2853 ddsd.dwSize = sizeof(ddsd);
2854 ddsd.dwFlags = DDSD_CAPS;
2855 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2857 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2858 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2859 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2860 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2861 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2862 param.ddraw_width, ddsd.dwWidth);
2863 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2864 param.ddraw_height, ddsd.dwHeight);
2866 GetWindowRect(window, &r);
2867 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2868 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2869 r.left, r.top, r.right, r.bottom);
2871 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2872 expect_messages = normal_messages;
2873 screen_size.cx = 0;
2874 screen_size.cy = 0;
2876 hr = IDirectDrawSurface_IsLost(primary);
2877 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2878 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2879 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2880 hr = IDirectDrawSurface_IsLost(primary);
2881 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2883 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2884 expect_messages = NULL;
2885 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2887 GetWindowRect(window, &r);
2888 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2889 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2890 r.left, r.top, r.right, r.bottom);
2892 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2893 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2894 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2895 param.ddraw_width, ddsd.dwWidth);
2896 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2897 param.ddraw_height, ddsd.dwHeight);
2898 IDirectDrawSurface_Release(primary);
2900 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2901 ok(ret, "Failed to get display mode.\n");
2902 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2903 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
2904 "Expected resolution %ux%u, got %ux%u.\n",
2905 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
2906 devmode.dmPelsWidth, devmode.dmPelsHeight);
2907 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2908 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2910 memset(&ddsd, 0, sizeof(ddsd));
2911 ddsd.dwSize = sizeof(ddsd);
2912 ddsd.dwFlags = DDSD_CAPS;
2913 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2915 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2916 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2917 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2918 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2919 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2920 registry_mode.dmPelsWidth, ddsd.dwWidth);
2921 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2922 registry_mode.dmPelsHeight, ddsd.dwHeight);
2924 GetWindowRect(window, &r);
2925 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2926 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2927 r.left, r.top, r.right, r.bottom);
2929 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2930 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2931 * not DDSCL_FULLSCREEN. */
2932 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2933 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2935 GetWindowRect(window, &r);
2936 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2937 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2938 r.left, r.top, r.right, r.bottom);
2940 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2941 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2942 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2943 registry_mode.dmPelsWidth, ddsd.dwWidth);
2944 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2945 registry_mode.dmPelsHeight, ddsd.dwHeight);
2946 IDirectDrawSurface_Release(primary);
2948 memset(&ddsd, 0, sizeof(ddsd));
2949 ddsd.dwSize = sizeof(ddsd);
2950 ddsd.dwFlags = DDSD_CAPS;
2951 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2953 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2954 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2955 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2956 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2957 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2958 registry_mode.dmPelsWidth, ddsd.dwWidth);
2959 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2960 registry_mode.dmPelsHeight, ddsd.dwHeight);
2962 GetWindowRect(window, &r);
2963 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2964 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2965 r.left, r.top, r.right, r.bottom);
2967 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2968 expect_messages = normal_messages;
2969 screen_size.cx = 0;
2970 screen_size.cy = 0;
2972 hr = IDirectDrawSurface_IsLost(primary);
2973 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2974 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2975 devmode.dmPelsWidth = param.user32_width;
2976 devmode.dmPelsHeight = param.user32_height;
2977 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2978 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2979 hr = IDirectDrawSurface_IsLost(primary);
2980 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2982 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2983 expect_messages = NULL;
2984 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2986 GetWindowRect(window, &r);
2987 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2988 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2989 r.left, r.top, r.right, r.bottom);
2991 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2992 expect_messages = normal_messages;
2993 screen_size.cx = 0;
2994 screen_size.cy = 0;
2996 hr = IDirectDrawSurface_Restore(primary);
2997 todo_wine ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2998 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2999 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3000 hr = IDirectDrawSurface_Restore(primary);
3001 todo_wine ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3002 hr = IDirectDrawSurface_IsLost(primary);
3003 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3005 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3006 expect_messages = NULL;
3007 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3009 GetWindowRect(window, &r);
3010 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3011 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
3012 r.left, r.top, r.right, r.bottom);
3014 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3015 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3016 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3017 registry_mode.dmPelsWidth, ddsd.dwWidth);
3018 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3019 registry_mode.dmPelsHeight, ddsd.dwHeight);
3020 IDirectDrawSurface_Release(primary);
3022 memset(&ddsd, 0, sizeof(ddsd));
3023 ddsd.dwSize = sizeof(ddsd);
3024 ddsd.dwFlags = DDSD_CAPS;
3025 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3027 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3028 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3029 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3030 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3031 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3032 param.ddraw_width, ddsd.dwWidth);
3033 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3034 param.ddraw_height, ddsd.dwHeight);
3036 GetWindowRect(window, &r);
3037 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3038 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
3039 r.left, r.top, r.right, r.bottom);
3041 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3042 expect_messages = normal_messages;
3043 screen_size.cx = 0;
3044 screen_size.cy = 0;
3046 hr = IDirectDrawSurface_IsLost(primary);
3047 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3048 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
3049 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3050 hr = IDirectDrawSurface_IsLost(primary);
3051 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3053 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3054 expect_messages = NULL;
3055 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3057 GetWindowRect(window, &r);
3058 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3059 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
3060 r.left, r.top, r.right, r.bottom);
3062 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3063 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3064 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3065 param.ddraw_width, ddsd.dwWidth);
3066 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3067 param.ddraw_height, ddsd.dwHeight);
3068 IDirectDrawSurface_Release(primary);
3070 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3071 ok(ret, "Failed to get display mode.\n");
3072 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3073 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3074 "Expected resolution %ux%u, got %ux%u.\n",
3075 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3076 devmode.dmPelsWidth, devmode.dmPelsHeight);
3077 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3078 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3080 memset(&ddsd, 0, sizeof(ddsd));
3081 ddsd.dwSize = sizeof(ddsd);
3082 ddsd.dwFlags = DDSD_CAPS;
3083 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3085 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3086 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3087 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3088 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3089 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3090 registry_mode.dmPelsWidth, ddsd.dwWidth);
3091 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3092 registry_mode.dmPelsHeight, ddsd.dwHeight);
3093 IDirectDrawSurface_Release(primary);
3095 GetWindowRect(window, &r);
3096 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3097 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
3098 r.left, r.top, r.right, r.bottom);
3100 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
3101 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3102 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3103 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3104 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3106 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3107 expect_messages = exclusive_messages;
3108 screen_size.cx = 0;
3109 screen_size.cy = 0;
3111 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3112 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3114 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3115 expect_messages = NULL;
3116 ok(screen_size.cx == registry_mode.dmPelsWidth
3117 && screen_size.cy == registry_mode.dmPelsHeight,
3118 "Expected screen size %ux%u, got %ux%u.\n",
3119 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3120 screen_size.cx, screen_size.cy);
3122 GetWindowRect(window, &r);
3123 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3124 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
3125 r.left, r.top, r.right, r.bottom);
3127 memset(&ddsd, 0, sizeof(ddsd));
3128 ddsd.dwSize = sizeof(ddsd);
3129 ddsd.dwFlags = DDSD_CAPS;
3130 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3132 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3133 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3134 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3135 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3136 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3137 registry_mode.dmPelsWidth, ddsd.dwWidth);
3138 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3139 registry_mode.dmPelsHeight, ddsd.dwHeight);
3140 IDirectDrawSurface_Release(primary);
3142 /* The screen restore is a property of DDSCL_EXCLUSIVE */
3143 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3144 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3145 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3146 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3148 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3149 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3151 memset(&ddsd, 0, sizeof(ddsd));
3152 ddsd.dwSize = sizeof(ddsd);
3153 ddsd.dwFlags = DDSD_CAPS;
3154 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3156 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3157 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3158 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3159 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3160 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3161 param.ddraw_width, ddsd.dwWidth);
3162 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3163 param.ddraw_height, ddsd.dwHeight);
3164 IDirectDrawSurface_Release(primary);
3166 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
3167 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3169 /* If the window is changed at the same time, messages are sent to the new window. */
3170 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3171 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3172 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3173 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3175 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3176 expect_messages = exclusive_messages;
3177 screen_size.cx = 0;
3178 screen_size.cy = 0;
3179 screen_size2.cx = 0;
3180 screen_size2.cy = 0;
3182 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3183 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3185 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3186 expect_messages = NULL;
3187 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n",
3188 screen_size.cx, screen_size.cy);
3189 ok(screen_size2.cx == registry_mode.dmPelsWidth && screen_size2.cy == registry_mode.dmPelsHeight,
3190 "Expected screen size 2 %ux%u, got %ux%u.\n",
3191 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size2.cx, screen_size2.cy);
3193 GetWindowRect(window, &r);
3194 ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3195 ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
3196 r.left, r.top, r.right, r.bottom);
3197 GetWindowRect(window2, &r);
3198 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3199 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
3200 r.left, r.top, r.right, r.bottom);
3202 memset(&ddsd, 0, sizeof(ddsd));
3203 ddsd.dwSize = sizeof(ddsd);
3204 ddsd.dwFlags = DDSD_CAPS;
3205 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3207 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3208 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3209 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3210 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3211 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3212 registry_mode.dmPelsWidth, ddsd.dwWidth);
3213 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3214 registry_mode.dmPelsHeight, ddsd.dwHeight);
3215 IDirectDrawSurface_Release(primary);
3217 ref = IDirectDraw2_Release(ddraw);
3218 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3220 GetWindowRect(window, &r);
3221 ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3222 ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
3223 r.left, r.top, r.right, r.bottom);
3225 done:
3226 expect_messages = NULL;
3227 DestroyWindow(window);
3228 DestroyWindow(window2);
3229 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3230 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
3233 static void test_coop_level_mode_set_multi(void)
3235 IDirectDraw2 *ddraw1, *ddraw2;
3236 UINT w, h;
3237 HWND window;
3238 HRESULT hr;
3239 ULONG ref;
3241 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3242 0, 0, 100, 100, 0, 0, 0, 0);
3243 ddraw1 = create_ddraw();
3244 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3246 /* With just a single ddraw object, the display mode is restored on
3247 * release. */
3248 hr = set_display_mode(ddraw1, 800, 600);
3249 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
3251 win_skip("Broken SetDisplayMode(), skipping test.\n");
3252 IDirectDraw2_Release(ddraw1);
3253 DestroyWindow(window);
3254 return;
3256 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3257 w = GetSystemMetrics(SM_CXSCREEN);
3258 ok(w == 800, "Got unexpected screen width %u.\n", w);
3259 h = GetSystemMetrics(SM_CYSCREEN);
3260 ok(h == 600, "Got unexpected screen height %u.\n", h);
3262 ref = IDirectDraw2_Release(ddraw1);
3263 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3264 w = GetSystemMetrics(SM_CXSCREEN);
3265 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3266 h = GetSystemMetrics(SM_CYSCREEN);
3267 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3269 /* When there are multiple ddraw objects, the display mode is restored to
3270 * the initial mode, before the first SetDisplayMode() call. */
3271 ddraw1 = create_ddraw();
3272 hr = set_display_mode(ddraw1, 800, 600);
3273 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3274 w = GetSystemMetrics(SM_CXSCREEN);
3275 ok(w == 800, "Got unexpected screen width %u.\n", w);
3276 h = GetSystemMetrics(SM_CYSCREEN);
3277 ok(h == 600, "Got unexpected screen height %u.\n", h);
3279 ddraw2 = create_ddraw();
3280 hr = set_display_mode(ddraw2, 640, 480);
3281 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3282 w = GetSystemMetrics(SM_CXSCREEN);
3283 ok(w == 640, "Got unexpected screen width %u.\n", w);
3284 h = GetSystemMetrics(SM_CYSCREEN);
3285 ok(h == 480, "Got unexpected screen height %u.\n", h);
3287 ref = IDirectDraw2_Release(ddraw2);
3288 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3289 w = GetSystemMetrics(SM_CXSCREEN);
3290 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3291 h = GetSystemMetrics(SM_CYSCREEN);
3292 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3294 ref = IDirectDraw2_Release(ddraw1);
3295 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3296 w = GetSystemMetrics(SM_CXSCREEN);
3297 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3298 h = GetSystemMetrics(SM_CYSCREEN);
3299 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3301 /* Regardless of release ordering. */
3302 ddraw1 = create_ddraw();
3303 hr = set_display_mode(ddraw1, 800, 600);
3304 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3305 w = GetSystemMetrics(SM_CXSCREEN);
3306 ok(w == 800, "Got unexpected screen width %u.\n", w);
3307 h = GetSystemMetrics(SM_CYSCREEN);
3308 ok(h == 600, "Got unexpected screen height %u.\n", h);
3310 ddraw2 = create_ddraw();
3311 hr = set_display_mode(ddraw2, 640, 480);
3312 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3313 w = GetSystemMetrics(SM_CXSCREEN);
3314 ok(w == 640, "Got unexpected screen width %u.\n", w);
3315 h = GetSystemMetrics(SM_CYSCREEN);
3316 ok(h == 480, "Got unexpected screen height %u.\n", h);
3318 ref = IDirectDraw2_Release(ddraw1);
3319 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3320 w = GetSystemMetrics(SM_CXSCREEN);
3321 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3322 h = GetSystemMetrics(SM_CYSCREEN);
3323 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3325 ref = IDirectDraw2_Release(ddraw2);
3326 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3327 w = GetSystemMetrics(SM_CXSCREEN);
3328 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3329 h = GetSystemMetrics(SM_CYSCREEN);
3330 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3332 /* But only for ddraw objects that called SetDisplayMode(). */
3333 ddraw1 = create_ddraw();
3334 ddraw2 = create_ddraw();
3335 hr = set_display_mode(ddraw2, 640, 480);
3336 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3337 w = GetSystemMetrics(SM_CXSCREEN);
3338 ok(w == 640, "Got unexpected screen width %u.\n", w);
3339 h = GetSystemMetrics(SM_CYSCREEN);
3340 ok(h == 480, "Got unexpected screen height %u.\n", h);
3342 ref = IDirectDraw2_Release(ddraw1);
3343 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3344 w = GetSystemMetrics(SM_CXSCREEN);
3345 ok(w == 640, "Got unexpected screen width %u.\n", w);
3346 h = GetSystemMetrics(SM_CYSCREEN);
3347 ok(h == 480, "Got unexpected screen height %u.\n", h);
3349 ref = IDirectDraw2_Release(ddraw2);
3350 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3351 w = GetSystemMetrics(SM_CXSCREEN);
3352 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3353 h = GetSystemMetrics(SM_CYSCREEN);
3354 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3356 /* If there's a ddraw object that's currently in exclusive mode, it blocks
3357 * restoring the display mode. */
3358 ddraw1 = create_ddraw();
3359 hr = set_display_mode(ddraw1, 800, 600);
3360 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3361 w = GetSystemMetrics(SM_CXSCREEN);
3362 ok(w == 800, "Got unexpected screen width %u.\n", w);
3363 h = GetSystemMetrics(SM_CYSCREEN);
3364 ok(h == 600, "Got unexpected screen height %u.\n", h);
3366 ddraw2 = create_ddraw();
3367 hr = set_display_mode(ddraw2, 640, 480);
3368 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3369 w = GetSystemMetrics(SM_CXSCREEN);
3370 ok(w == 640, "Got unexpected screen width %u.\n", w);
3371 h = GetSystemMetrics(SM_CYSCREEN);
3372 ok(h == 480, "Got unexpected screen height %u.\n", h);
3374 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3375 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3377 ref = IDirectDraw2_Release(ddraw1);
3378 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3379 w = GetSystemMetrics(SM_CXSCREEN);
3380 ok(w == 640, "Got unexpected screen width %u.\n", w);
3381 h = GetSystemMetrics(SM_CYSCREEN);
3382 ok(h == 480, "Got unexpected screen height %u.\n", h);
3384 ref = IDirectDraw2_Release(ddraw2);
3385 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3386 w = GetSystemMetrics(SM_CXSCREEN);
3387 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3388 h = GetSystemMetrics(SM_CYSCREEN);
3389 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3391 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3392 ddraw1 = create_ddraw();
3393 hr = set_display_mode(ddraw1, 800, 600);
3394 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3395 w = GetSystemMetrics(SM_CXSCREEN);
3396 ok(w == 800, "Got unexpected screen width %u.\n", w);
3397 h = GetSystemMetrics(SM_CYSCREEN);
3398 ok(h == 600, "Got unexpected screen height %u.\n", h);
3400 hr = IDirectDraw2_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3401 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3403 ddraw2 = create_ddraw();
3404 hr = set_display_mode(ddraw2, 640, 480);
3405 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3407 ref = IDirectDraw2_Release(ddraw1);
3408 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3409 w = GetSystemMetrics(SM_CXSCREEN);
3410 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3411 h = GetSystemMetrics(SM_CYSCREEN);
3412 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3414 ref = IDirectDraw2_Release(ddraw2);
3415 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3416 w = GetSystemMetrics(SM_CXSCREEN);
3417 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3418 h = GetSystemMetrics(SM_CYSCREEN);
3419 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3421 DestroyWindow(window);
3424 static void test_initialize(void)
3426 IDirectDraw2 *ddraw;
3427 HRESULT hr;
3429 ddraw = create_ddraw();
3430 ok(!!ddraw, "Failed to create a ddraw object.\n");
3432 hr = IDirectDraw2_Initialize(ddraw, NULL);
3433 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
3434 IDirectDraw2_Release(ddraw);
3436 CoInitialize(NULL);
3437 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw2, (void **)&ddraw);
3438 ok(SUCCEEDED(hr), "Failed to create IDirectDraw2 instance, hr %#x.\n", hr);
3439 hr = IDirectDraw2_Initialize(ddraw, NULL);
3440 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
3441 hr = IDirectDraw2_Initialize(ddraw, NULL);
3442 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
3443 IDirectDraw2_Release(ddraw);
3444 CoUninitialize();
3447 static void test_coop_level_surf_create(void)
3449 IDirectDrawSurface *surface;
3450 IDirectDraw2 *ddraw;
3451 DDSURFACEDESC ddsd;
3452 HRESULT hr;
3454 ddraw = create_ddraw();
3455 ok(!!ddraw, "Failed to create a ddraw object.\n");
3457 memset(&ddsd, 0, sizeof(ddsd));
3458 ddsd.dwSize = sizeof(ddsd);
3459 ddsd.dwFlags = DDSD_CAPS;
3460 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3461 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
3462 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3464 IDirectDraw2_Release(ddraw);
3467 static void test_coop_level_multi_window(void)
3469 HWND window1, window2;
3470 IDirectDraw2 *ddraw;
3471 HRESULT hr;
3473 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
3474 0, 0, 640, 480, 0, 0, 0, 0);
3475 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
3476 0, 0, 640, 480, 0, 0, 0, 0);
3477 ddraw = create_ddraw();
3478 ok(!!ddraw, "Failed to create a ddraw object.\n");
3480 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
3481 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3482 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3483 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3484 ok(IsWindow(window1), "Window 1 was destroyed.\n");
3485 ok(IsWindow(window2), "Window 2 was destroyed.\n");
3487 IDirectDraw2_Release(ddraw);
3488 DestroyWindow(window2);
3489 DestroyWindow(window1);
3492 static void test_clear_rect_count(void)
3494 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3495 IDirect3DMaterial2 *white, *red, *green, *blue;
3496 IDirect3DViewport2 *viewport;
3497 IDirect3DDevice2 *device;
3498 IDirectDrawSurface *rt;
3499 IDirectDraw2 *ddraw;
3500 D3DCOLOR color;
3501 HWND window;
3502 HRESULT hr;
3504 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3505 0, 0, 640, 480, 0, 0, 0, 0);
3506 ddraw = create_ddraw();
3507 ok(!!ddraw, "Failed to create a ddraw object.\n");
3508 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3510 skip("Failed to create a 3D device, skipping test.\n");
3511 IDirectDraw2_Release(ddraw);
3512 DestroyWindow(window);
3513 return;
3516 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
3517 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3519 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
3520 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
3521 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
3522 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
3524 viewport = create_viewport(device, 0, 0, 640, 480);
3525 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
3526 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
3528 viewport_set_background(device, viewport, white);
3529 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
3530 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3531 viewport_set_background(device, viewport, red);
3532 hr = IDirect3DViewport2_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
3533 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3534 viewport_set_background(device, viewport, green);
3535 hr = IDirect3DViewport2_Clear(viewport, 0, NULL, D3DCLEAR_TARGET);
3536 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3537 viewport_set_background(device, viewport, blue);
3538 hr = IDirect3DViewport2_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
3539 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3541 color = get_surface_color(rt, 320, 240);
3542 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x000000ff, 1)),
3543 "Got unexpected color 0x%08x.\n", color);
3545 IDirectDrawSurface_Release(rt);
3546 destroy_viewport(device, viewport);
3547 destroy_material(white);
3548 destroy_material(red);
3549 destroy_material(green);
3550 destroy_material(blue);
3551 IDirect3DDevice2_Release(device);
3552 IDirectDraw2_Release(ddraw);
3553 DestroyWindow(window);
3556 static BOOL test_mode_restored(IDirectDraw2 *ddraw, HWND window)
3558 DDSURFACEDESC ddsd1, ddsd2;
3559 HRESULT hr;
3561 memset(&ddsd1, 0, sizeof(ddsd1));
3562 ddsd1.dwSize = sizeof(ddsd1);
3563 hr = IDirectDraw2_GetDisplayMode(ddraw, &ddsd1);
3564 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
3566 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3567 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3568 hr = set_display_mode(ddraw, 640, 480);
3569 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3570 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3571 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3573 memset(&ddsd2, 0, sizeof(ddsd2));
3574 ddsd2.dwSize = sizeof(ddsd2);
3575 hr = IDirectDraw2_GetDisplayMode(ddraw, &ddsd2);
3576 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
3577 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
3578 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3580 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
3583 static void test_coop_level_versions(void)
3585 HWND window;
3586 IDirectDraw *ddraw;
3587 HRESULT hr;
3588 BOOL restored;
3589 IDirectDrawSurface *surface;
3590 IDirectDraw2 *ddraw2;
3591 DDSURFACEDESC ddsd;
3593 window = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
3594 0, 0, 640, 480, 0, 0, 0, 0);
3596 ddraw2 = create_ddraw();
3597 ok(!!ddraw2, "Failed to create a ddraw object.\n");
3598 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
3599 restored = test_mode_restored(ddraw2, window);
3600 ok(restored, "Display mode not restored in new ddraw object\n");
3602 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
3603 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
3604 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3606 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
3607 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
3608 restored = test_mode_restored(ddraw2, window);
3609 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
3611 /* A successful one does */
3612 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3613 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3614 restored = test_mode_restored(ddraw2, window);
3615 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
3617 IDirectDraw_Release(ddraw);
3618 IDirectDraw2_Release(ddraw2);
3620 ddraw2 = create_ddraw();
3621 ok(!!ddraw2, "Failed to create a ddraw object.\n");
3622 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
3623 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3625 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
3626 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3627 restored = test_mode_restored(ddraw2, window);
3628 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
3630 IDirectDraw_Release(ddraw);
3631 IDirectDraw2_Release(ddraw2);
3633 /* A failing call does not restore the ddraw2+ behavior */
3634 ddraw2 = create_ddraw();
3635 ok(!!ddraw2, "Failed to create a ddraw object.\n");
3636 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
3637 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3639 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3640 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3641 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
3642 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
3643 restored = test_mode_restored(ddraw2, window);
3644 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
3646 IDirectDraw_Release(ddraw);
3647 IDirectDraw2_Release(ddraw2);
3649 /* Neither does a sequence of successful calls with the new interface */
3650 ddraw2 = create_ddraw();
3651 ok(!!ddraw2, "Failed to create a ddraw object.\n");
3652 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
3653 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3655 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3656 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3657 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
3658 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3659 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_NORMAL);
3660 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3662 restored = test_mode_restored(ddraw2, window);
3663 ok(!restored, "Display mode restored after ddraw1-ddraw2 SetCooperativeLevel() call sequence\n");
3664 IDirectDraw_Release(ddraw);
3665 IDirectDraw2_Release(ddraw2);
3667 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
3668 ddraw2 = create_ddraw();
3669 ok(!!ddraw2, "Failed to create a ddraw object.\n");
3670 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
3671 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3673 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_NORMAL);
3674 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3676 memset(&ddsd, 0, sizeof(ddsd));
3677 ddsd.dwSize = sizeof(ddsd);
3678 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
3679 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
3680 ddsd.dwWidth = ddsd.dwHeight = 8;
3681 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3682 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
3683 IDirectDrawSurface_Release(surface);
3684 restored = test_mode_restored(ddraw2, window);
3685 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
3687 IDirectDraw_Release(ddraw);
3688 IDirectDraw2_Release(ddraw2);
3689 DestroyWindow(window);
3692 static void test_lighting_interface_versions(void)
3694 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3695 IDirect3DMaterial2 *emissive, *background;
3696 IDirect3DViewport2 *viewport;
3697 IDirect3DDevice2 *device;
3698 IDirectDrawSurface *rt;
3699 IDirectDraw2 *ddraw;
3700 D3DCOLOR color;
3701 HWND window;
3702 HRESULT hr;
3703 D3DMATERIALHANDLE mat_handle;
3704 DWORD rs;
3705 unsigned int i;
3706 ULONG ref;
3707 static D3DVERTEX quad[] =
3709 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3710 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3711 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3712 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3714 static D3DLVERTEX lquad[] =
3716 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3717 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3718 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3719 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3721 static D3DTLVERTEX tlquad[] =
3723 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3724 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3725 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3726 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3728 static const struct
3730 D3DVERTEXTYPE vertextype;
3731 void *data;
3732 DWORD d3drs_lighting, d3drs_specular;
3733 DWORD draw_flags;
3734 D3DCOLOR color;
3736 tests[] =
3738 /* Lighting is enabled when D3DVT_VERTEX is used and D3DDP_DONOTLIGHT is not
3739 * set. D3DVT_VERTEX has diffuse = 0xffffffff and specular = 0x00000000, as
3740 * in later d3d versions */
3741 { D3DVT_VERTEX, quad, FALSE, FALSE, 0, 0x0000ff00},
3742 { D3DVT_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
3743 { D3DVT_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
3744 { D3DVT_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
3745 { D3DVT_VERTEX, quad, FALSE, TRUE, 0, 0x0000ff00},
3746 { D3DVT_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
3747 { D3DVT_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
3748 { D3DVT_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
3750 { D3DVT_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
3751 { D3DVT_LVERTEX, lquad, TRUE, FALSE, 0, 0x00ff0000},
3752 { D3DVT_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
3753 { D3DVT_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
3754 { D3DVT_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
3755 { D3DVT_LVERTEX, lquad, TRUE, TRUE, 0, 0x00ff8080},
3756 { D3DVT_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
3757 { D3DVT_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
3759 { D3DVT_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
3760 { D3DVT_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
3761 { D3DVT_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
3762 { D3DVT_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
3763 { D3DVT_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
3764 { D3DVT_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
3765 { D3DVT_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
3766 { D3DVT_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
3769 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3770 0, 0, 640, 480, 0, 0, 0, 0);
3771 ddraw = create_ddraw();
3772 ok(!!ddraw, "Failed to create a ddraw object.\n");
3773 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3775 skip("Failed to create a 3D device, skipping test.\n");
3776 IDirectDraw2_Release(ddraw);
3777 DestroyWindow(window);
3778 return;
3781 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
3782 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3784 viewport = create_viewport(device, 0, 0, 640, 480);
3785 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
3786 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
3788 emissive = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
3789 hr = IDirect3DMaterial2_GetHandle(emissive, device, &mat_handle);
3790 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
3791 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
3792 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
3793 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
3794 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr);
3796 background = create_diffuse_material(device, 0.1f, 0.1f, 0.1f, 0.1f);
3797 viewport_set_background(device, viewport, background);
3799 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
3800 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#x.\n", hr);
3801 ok(rs == TRUE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#x, expected TRUE.\n", rs);
3803 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
3805 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
3806 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3808 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
3809 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#x.\n", hr);
3810 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
3811 tests[i].d3drs_specular);
3812 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#x.\n", hr);
3814 hr = IDirect3DDevice2_BeginScene(device);
3815 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3816 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
3817 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
3818 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3819 hr = IDirect3DDevice2_EndScene(device);
3820 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3822 color = get_surface_color(rt, 320, 240);
3823 ok(compare_color(color, tests[i].color, 1),
3824 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
3825 color, tests[i].color, i);
3828 destroy_material(background);
3829 destroy_material(emissive);
3830 IDirectDrawSurface_Release(rt);
3831 IDirect3DDevice2_Release(device);
3832 ref = IDirectDraw2_Release(ddraw);
3833 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
3834 DestroyWindow(window);
3837 static struct
3839 BOOL received;
3840 IDirectDraw2 *ddraw;
3841 HWND window;
3842 DWORD coop_level;
3843 } activateapp_testdata;
3845 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3847 if (message == WM_ACTIVATEAPP)
3849 if (activateapp_testdata.ddraw)
3851 HRESULT hr;
3852 activateapp_testdata.received = FALSE;
3853 hr = IDirectDraw2_SetCooperativeLevel(activateapp_testdata.ddraw,
3854 activateapp_testdata.window, activateapp_testdata.coop_level);
3855 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
3856 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
3858 activateapp_testdata.received = TRUE;
3861 return DefWindowProcA(hwnd, message, wparam, lparam);
3864 static void test_coop_level_activateapp(void)
3866 IDirectDraw2 *ddraw;
3867 HRESULT hr;
3868 HWND window;
3869 WNDCLASSA wc = {0};
3870 DDSURFACEDESC ddsd;
3871 IDirectDrawSurface *surface;
3873 ddraw = create_ddraw();
3874 ok(!!ddraw, "Failed to create a ddraw object.\n");
3876 wc.lpfnWndProc = activateapp_test_proc;
3877 wc.lpszClassName = "ddraw_test_wndproc_wc";
3878 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3880 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
3881 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
3883 /* Exclusive with window already active. */
3884 SetForegroundWindow(window);
3885 activateapp_testdata.received = FALSE;
3886 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3887 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3888 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
3889 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3890 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3892 /* Exclusive with window not active. */
3893 SetForegroundWindow(GetDesktopWindow());
3894 activateapp_testdata.received = FALSE;
3895 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3896 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3897 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3898 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3899 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3901 /* Normal with window not active, then exclusive with the same window. */
3902 SetForegroundWindow(GetDesktopWindow());
3903 activateapp_testdata.received = FALSE;
3904 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3905 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3906 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
3907 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3908 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3909 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3910 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3911 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3913 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
3914 SetForegroundWindow(GetDesktopWindow());
3915 activateapp_testdata.received = FALSE;
3916 activateapp_testdata.ddraw = ddraw;
3917 activateapp_testdata.window = window;
3918 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
3919 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3920 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3921 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3922 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3923 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3925 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
3926 * succeeding. Another switch to exclusive and back to normal is needed to release the
3927 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
3928 * WM_ACTIVATEAPP messages. */
3929 activateapp_testdata.ddraw = NULL;
3930 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3931 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3932 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3933 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3935 /* Setting DDSCL_NORMAL with recursive invocation. */
3936 SetForegroundWindow(GetDesktopWindow());
3937 activateapp_testdata.received = FALSE;
3938 activateapp_testdata.ddraw = ddraw;
3939 activateapp_testdata.window = window;
3940 activateapp_testdata.coop_level = DDSCL_NORMAL;
3941 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3942 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3943 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3945 /* DDraw is in exlusive mode now. */
3946 memset(&ddsd, 0, sizeof(ddsd));
3947 ddsd.dwSize = sizeof(ddsd);
3948 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
3949 ddsd.dwBackBufferCount = 1;
3950 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
3951 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
3952 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3953 IDirectDrawSurface_Release(surface);
3955 /* Recover again, just to be sure. */
3956 activateapp_testdata.ddraw = NULL;
3957 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3958 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3959 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3960 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3962 DestroyWindow(window);
3963 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3964 IDirectDraw2_Release(ddraw);
3967 struct format_support_check
3969 const DDPIXELFORMAT *format;
3970 BOOL supported;
3973 static HRESULT WINAPI test_unsupported_formats_cb(DDSURFACEDESC *desc, void *ctx)
3975 struct format_support_check *format = ctx;
3977 if (!memcmp(format->format, &desc->ddpfPixelFormat, sizeof(*format->format)))
3979 format->supported = TRUE;
3980 return DDENUMRET_CANCEL;
3983 return DDENUMRET_OK;
3986 static void test_unsupported_formats(void)
3988 HRESULT hr;
3989 BOOL expect_success;
3990 HWND window;
3991 IDirectDraw2 *ddraw;
3992 IDirect3DDevice2 *device;
3993 IDirectDrawSurface *surface;
3994 DDSURFACEDESC ddsd;
3995 unsigned int i, j;
3996 DWORD expected_caps;
3997 static const struct
3999 const char *name;
4000 DDPIXELFORMAT fmt;
4002 formats[] =
4005 "D3DFMT_A8R8G8B8",
4007 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
4008 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
4012 "D3DFMT_P8",
4014 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
4015 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
4019 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
4021 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4022 0, 0, 640, 480, 0, 0, 0, 0);
4023 ddraw = create_ddraw();
4024 ok(!!ddraw, "Failed to create a ddraw object.\n");
4025 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4027 skip("Failed to create a 3D device, skipping test.\n");
4028 IDirectDraw2_Release(ddraw);
4029 DestroyWindow(window);
4030 return;
4033 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
4035 struct format_support_check check = {&formats[i].fmt, FALSE};
4036 hr = IDirect3DDevice2_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
4037 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
4039 for (j = 0; j < sizeof(caps) / sizeof(*caps); j++)
4041 memset(&ddsd, 0, sizeof(ddsd));
4042 ddsd.dwSize = sizeof(ddsd);
4043 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4044 ddsd.ddpfPixelFormat = formats[i].fmt;
4045 ddsd.dwWidth = 4;
4046 ddsd.dwHeight = 4;
4047 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
4049 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
4050 expect_success = FALSE;
4051 else
4052 expect_success = TRUE;
4054 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4055 ok(SUCCEEDED(hr) == expect_success,
4056 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
4057 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
4058 if (FAILED(hr))
4059 continue;
4061 memset(&ddsd, 0, sizeof(ddsd));
4062 ddsd.dwSize = sizeof(ddsd);
4063 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
4064 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4066 if (caps[j] & DDSCAPS_VIDEOMEMORY)
4067 expected_caps = DDSCAPS_VIDEOMEMORY;
4068 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
4069 expected_caps = DDSCAPS_SYSTEMMEMORY;
4070 else if (check.supported)
4071 expected_caps = DDSCAPS_VIDEOMEMORY;
4072 else
4073 expected_caps = DDSCAPS_SYSTEMMEMORY;
4075 ok(ddsd.ddsCaps.dwCaps & expected_caps,
4076 "Expected capability %#x, format %s, input cap %#x.\n",
4077 expected_caps, formats[i].name, caps[j]);
4079 IDirectDrawSurface_Release(surface);
4083 IDirect3DDevice2_Release(device);
4084 IDirectDraw2_Release(ddraw);
4085 DestroyWindow(window);
4088 static void test_rt_caps(void)
4090 PALETTEENTRY palette_entries[256];
4091 IDirectDrawPalette *palette;
4092 IDirect3DDevice2 *device;
4093 IDirectDraw2 *ddraw;
4094 DWORD z_depth = 0;
4095 IDirect3D2 *d3d;
4096 unsigned int i;
4097 ULONG refcount;
4098 HWND window;
4099 HRESULT hr;
4101 static const DDPIXELFORMAT p8_fmt =
4103 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
4104 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
4107 static const struct
4109 const DDPIXELFORMAT *pf;
4110 DWORD caps_in;
4111 DWORD caps_out;
4112 HRESULT create_device_hr;
4113 HRESULT set_rt_hr;
4114 HRESULT alternative_set_rt_hr;
4115 BOOL create_may_fail;
4117 test_data[] =
4120 NULL,
4121 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
4122 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4123 D3D_OK,
4124 D3D_OK,
4125 D3D_OK,
4126 FALSE,
4129 NULL,
4130 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
4131 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4132 D3D_OK,
4133 D3D_OK,
4134 D3D_OK,
4135 FALSE,
4138 NULL,
4139 DDSCAPS_OFFSCREENPLAIN,
4140 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4141 DDERR_INVALIDCAPS,
4142 DDERR_INVALIDCAPS,
4143 DDERR_INVALIDCAPS,
4144 FALSE,
4147 NULL,
4148 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4149 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4150 D3DERR_SURFACENOTINVIDMEM,
4151 D3D_OK,
4152 D3D_OK,
4153 FALSE,
4156 NULL,
4157 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4158 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4159 DDERR_INVALIDCAPS,
4160 DDERR_INVALIDCAPS,
4161 DDERR_INVALIDCAPS,
4162 FALSE,
4165 NULL,
4166 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
4167 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4168 D3D_OK,
4169 D3D_OK,
4170 D3D_OK,
4171 FALSE,
4174 NULL,
4175 DDSCAPS_3DDEVICE,
4176 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4177 D3D_OK,
4178 D3D_OK,
4179 D3D_OK,
4180 FALSE,
4183 NULL,
4185 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4186 DDERR_INVALIDCAPS,
4187 DDERR_INVALIDCAPS,
4188 DDERR_INVALIDCAPS,
4189 FALSE,
4192 NULL,
4193 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4194 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4195 D3DERR_SURFACENOTINVIDMEM,
4196 D3D_OK,
4197 D3D_OK,
4198 FALSE,
4201 NULL,
4202 DDSCAPS_SYSTEMMEMORY,
4203 DDSCAPS_SYSTEMMEMORY,
4204 DDERR_INVALIDCAPS,
4205 DDERR_INVALIDCAPS,
4206 DDERR_INVALIDCAPS,
4207 FALSE,
4210 &p8_fmt,
4212 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4213 DDERR_INVALIDCAPS,
4214 DDERR_INVALIDCAPS,
4215 DDERR_INVALIDCAPS,
4216 FALSE,
4219 &p8_fmt,
4220 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
4221 ~0U /* AMD r200 */,
4222 DDERR_NOPALETTEATTACHED,
4223 DDERR_INVALIDCAPS,
4224 DDERR_INVALIDCAPS,
4225 FALSE,
4228 &p8_fmt,
4229 DDSCAPS_OFFSCREENPLAIN,
4230 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4231 DDERR_INVALIDCAPS,
4232 DDERR_INVALIDCAPS,
4233 DDERR_INVALIDCAPS,
4234 FALSE,
4237 &p8_fmt,
4238 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4239 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4240 DDERR_NOPALETTEATTACHED,
4241 DDERR_INVALIDCAPS,
4242 DDERR_INVALIDCAPS,
4243 FALSE,
4246 &p8_fmt,
4247 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4248 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4249 DDERR_INVALIDCAPS,
4250 DDERR_INVALIDCAPS,
4251 DDERR_INVALIDCAPS,
4252 FALSE,
4255 NULL,
4256 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
4257 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
4258 DDERR_INVALIDCAPS,
4259 DDERR_INVALIDPIXELFORMAT,
4260 DDERR_INVALIDCAPS,
4261 TRUE /* AMD Evergreen */,
4264 NULL,
4265 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
4266 ~0U /* AMD Evergreen */,
4267 DDERR_INVALIDCAPS,
4268 DDERR_INVALIDPIXELFORMAT,
4269 DDERR_INVALIDCAPS,
4270 FALSE,
4273 NULL,
4274 DDSCAPS_ZBUFFER,
4275 ~0U /* AMD Evergreen */,
4276 DDERR_INVALIDCAPS,
4277 DDERR_INVALIDCAPS,
4278 DDERR_INVALIDCAPS,
4279 FALSE,
4282 NULL,
4283 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
4284 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
4285 DDERR_INVALIDCAPS,
4286 DDERR_INVALIDPIXELFORMAT,
4287 DDERR_INVALIDPIXELFORMAT,
4288 TRUE /* Nvidia Kepler */,
4291 NULL,
4292 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
4293 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
4294 DDERR_INVALIDCAPS,
4295 DDERR_INVALIDCAPS,
4296 DDERR_INVALIDCAPS,
4297 TRUE /* Nvidia Kepler */,
4301 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4302 0, 0, 640, 480, 0, 0, 0, 0);
4303 ddraw = create_ddraw();
4304 ok(!!ddraw, "Failed to create a ddraw object.\n");
4305 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4307 skip("Failed to create a 3D device, skipping test.\n");
4308 IDirectDraw2_Release(ddraw);
4309 DestroyWindow(window);
4310 return;
4312 z_depth = get_device_z_depth(device);
4313 ok(!!z_depth, "Failed to get device z depth.\n");
4314 IDirect3DDevice2_Release(device);
4316 if (FAILED(IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d)))
4318 skip("D3D interface is not available, skipping test.\n");
4319 goto done;
4322 memset(palette_entries, 0, sizeof(palette_entries));
4323 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
4324 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
4326 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
4328 IDirectDrawSurface *surface, *rt, *expected_rt, *tmp;
4329 DDSURFACEDESC surface_desc;
4330 IDirect3DDevice2 *device;
4332 memset(&surface_desc, 0, sizeof(surface_desc));
4333 surface_desc.dwSize = sizeof(surface_desc);
4334 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4335 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
4336 if (test_data[i].pf)
4338 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
4339 surface_desc.ddpfPixelFormat = *test_data[i].pf;
4341 if (test_data[i].caps_in & DDSCAPS_ZBUFFER)
4343 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
4344 U2(surface_desc).dwZBufferBitDepth = z_depth;
4346 surface_desc.dwWidth = 640;
4347 surface_desc.dwHeight = 480;
4348 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4349 ok(SUCCEEDED(hr) || broken(test_data[i].create_may_fail),
4350 "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
4351 i, test_data[i].caps_in, hr);
4352 if (FAILED(hr))
4353 continue;
4355 memset(&surface_desc, 0, sizeof(surface_desc));
4356 surface_desc.dwSize = sizeof(surface_desc);
4357 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
4358 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
4359 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
4360 "Test %u: Got unexpected caps %#x, expected %#x.\n",
4361 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
4363 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
4364 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
4365 i, hr, test_data[i].create_device_hr);
4366 if (FAILED(hr))
4368 if (hr == DDERR_NOPALETTEATTACHED)
4370 hr = IDirectDrawSurface_SetPalette(surface, palette);
4371 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
4372 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
4373 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
4374 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
4375 else
4376 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
4378 IDirectDrawSurface_Release(surface);
4380 memset(&surface_desc, 0, sizeof(surface_desc));
4381 surface_desc.dwSize = sizeof(surface_desc);
4382 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4383 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
4384 surface_desc.dwWidth = 640;
4385 surface_desc.dwHeight = 480;
4386 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4387 ok(SUCCEEDED(hr), "Test %u: Failed to create surface, hr %#x.\n", i, hr);
4389 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
4390 ok(SUCCEEDED(hr), "Test %u: Failed to create device, hr %#x.\n", i, hr);
4393 memset(&surface_desc, 0, sizeof(surface_desc));
4394 surface_desc.dwSize = sizeof(surface_desc);
4395 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4396 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
4397 if (test_data[i].pf)
4399 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
4400 surface_desc.ddpfPixelFormat = *test_data[i].pf;
4402 if (test_data[i].caps_in & DDSCAPS_ZBUFFER)
4404 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
4405 U2(surface_desc).dwZBufferBitDepth = z_depth;
4407 surface_desc.dwWidth = 640;
4408 surface_desc.dwHeight = 480;
4409 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &rt, NULL);
4410 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
4411 i, test_data[i].caps_in, hr);
4413 hr = IDirect3DDevice2_SetRenderTarget(device, rt, 0);
4414 ok(hr == test_data[i].set_rt_hr || broken(hr == test_data[i].alternative_set_rt_hr),
4415 "Test %u: Got unexpected hr %#x, expected %#x.\n",
4416 i, hr, test_data[i].set_rt_hr);
4417 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
4418 expected_rt = rt;
4419 else
4420 expected_rt = surface;
4422 /* It appears the surface is set as render target in this case, but no
4423 * reference is taken. */
4424 if (hr == DDERR_INVALIDPIXELFORMAT)
4426 refcount = IDirectDrawSurface_AddRef(rt);
4427 ok(refcount == 2, "Test %u: Got unexpected refcount %u.\n", i, refcount);
4430 hr = IDirect3DDevice2_GetRenderTarget(device, &tmp);
4431 ok(SUCCEEDED(hr), "Test %u: Failed to get render target, hr %#x.\n", i, hr);
4432 ok(tmp == expected_rt, "Test %u: Got unexpected rt %p.\n", i, tmp);
4434 IDirectDrawSurface_Release(tmp);
4435 IDirectDrawSurface_Release(rt);
4436 refcount = IDirect3DDevice2_Release(device);
4437 ok(refcount == 0, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
4438 refcount = IDirectDrawSurface_Release(surface);
4439 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
4442 IDirectDrawPalette_Release(palette);
4443 IDirect3D2_Release(d3d);
4445 done:
4446 refcount = IDirectDraw2_Release(ddraw);
4447 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4448 DestroyWindow(window);
4451 static void test_primary_caps(void)
4453 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
4454 IDirectDrawSurface *surface;
4455 DDSURFACEDESC surface_desc;
4456 IDirectDraw2 *ddraw;
4457 unsigned int i;
4458 ULONG refcount;
4459 HWND window;
4460 HRESULT hr;
4462 static const struct
4464 DWORD coop_level;
4465 DWORD caps_in;
4466 DWORD back_buffer_count;
4467 HRESULT hr;
4468 DWORD caps_out;
4470 test_data[] =
4473 DDSCL_NORMAL,
4474 DDSCAPS_PRIMARYSURFACE,
4475 ~0u,
4476 DD_OK,
4477 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
4480 DDSCL_NORMAL,
4481 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
4482 ~0u,
4483 DDERR_INVALIDCAPS,
4484 ~0u,
4487 DDSCL_NORMAL,
4488 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
4489 ~0u,
4490 DDERR_INVALIDCAPS,
4491 ~0u,
4494 DDSCL_NORMAL,
4495 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
4496 ~0u,
4497 DDERR_INVALIDCAPS,
4498 ~0u,
4501 DDSCL_NORMAL,
4502 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
4503 ~0u,
4504 DDERR_INVALIDCAPS,
4505 ~0u,
4508 DDSCL_NORMAL,
4509 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
4510 ~0u,
4511 DDERR_INVALIDCAPS,
4512 ~0u,
4515 DDSCL_NORMAL,
4516 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4517 ~0u,
4518 DDERR_INVALIDCAPS,
4519 ~0u,
4522 DDSCL_NORMAL,
4523 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4525 DDERR_INVALIDCAPS,
4526 ~0u,
4529 DDSCL_NORMAL,
4530 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4532 DDERR_NOEXCLUSIVEMODE,
4533 ~0u,
4536 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4537 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4539 DDERR_INVALIDCAPS,
4540 ~0u,
4543 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4544 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4546 DD_OK,
4547 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
4550 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4551 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
4553 DDERR_INVALIDCAPS,
4554 ~0u,
4557 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4558 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
4560 DDERR_INVALIDCAPS,
4561 ~0u,
4565 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4566 0, 0, 640, 480, 0, 0, 0, 0);
4567 ddraw = create_ddraw();
4568 ok(!!ddraw, "Failed to create a ddraw object.\n");
4570 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
4572 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
4573 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4575 memset(&surface_desc, 0, sizeof(surface_desc));
4576 surface_desc.dwSize = sizeof(surface_desc);
4577 surface_desc.dwFlags = DDSD_CAPS;
4578 if (test_data[i].back_buffer_count != ~0u)
4579 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
4580 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
4581 surface_desc.dwBackBufferCount = test_data[i].back_buffer_count;
4582 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4583 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
4584 if (FAILED(hr))
4585 continue;
4587 memset(&surface_desc, 0, sizeof(surface_desc));
4588 surface_desc.dwSize = sizeof(surface_desc);
4589 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
4590 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
4591 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
4592 "Test %u: Got unexpected caps %#x, expected %#x.\n",
4593 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
4595 IDirectDrawSurface_Release(surface);
4598 refcount = IDirectDraw2_Release(ddraw);
4599 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4600 DestroyWindow(window);
4603 static void test_surface_lock(void)
4605 IDirectDraw2 *ddraw;
4606 IDirectDrawSurface *surface;
4607 IDirect3DDevice2 *device;
4608 HRESULT hr;
4609 HWND window;
4610 unsigned int i;
4611 DDSURFACEDESC ddsd;
4612 ULONG refcount;
4613 DWORD z_depth = 0;
4614 static const struct
4616 DWORD caps;
4617 const char *name;
4619 tests[] =
4622 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
4623 "videomemory offscreenplain"
4626 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4627 "systemmemory offscreenplain"
4630 DDSCAPS_PRIMARYSURFACE,
4631 "primary"
4634 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
4635 "videomemory texture"
4638 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
4639 "systemmemory texture"
4642 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
4643 "render target"
4646 DDSCAPS_ZBUFFER,
4647 "Z buffer"
4651 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4652 0, 0, 640, 480, 0, 0, 0, 0);
4653 ddraw = create_ddraw();
4654 ok(!!ddraw, "Failed to create a ddraw object.\n");
4655 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4657 skip("Failed to create a 3D device, skipping test.\n");
4658 IDirectDraw2_Release(ddraw);
4659 DestroyWindow(window);
4660 return;
4662 z_depth = get_device_z_depth(device);
4663 ok(!!z_depth, "Failed to get device z depth.\n");
4664 IDirect3DDevice2_Release(device);
4666 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4668 memset(&ddsd, 0, sizeof(ddsd));
4669 ddsd.dwSize = sizeof(ddsd);
4670 ddsd.dwFlags = DDSD_CAPS;
4671 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
4673 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
4674 ddsd.dwWidth = 64;
4675 ddsd.dwHeight = 64;
4677 if (tests[i].caps & DDSCAPS_ZBUFFER)
4679 ddsd.dwFlags |= DDSD_ZBUFFERBITDEPTH;
4680 U2(ddsd).dwZBufferBitDepth = z_depth;
4682 ddsd.ddsCaps.dwCaps = tests[i].caps;
4684 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4685 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
4687 memset(&ddsd, 0, sizeof(ddsd));
4688 ddsd.dwSize = sizeof(ddsd);
4689 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
4690 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
4691 if (SUCCEEDED(hr))
4693 hr = IDirectDrawSurface_Unlock(surface, NULL);
4694 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
4697 IDirectDrawSurface_Release(surface);
4700 refcount = IDirectDraw2_Release(ddraw);
4701 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4702 DestroyWindow(window);
4705 static void test_surface_discard(void)
4707 IDirectDraw2 *ddraw;
4708 IDirect3DDevice2 *device;
4709 HRESULT hr;
4710 HWND window;
4711 DDSURFACEDESC ddsd;
4712 IDirectDrawSurface *surface, *target;
4713 void *addr;
4714 static const struct
4716 DWORD caps;
4717 BOOL discard;
4719 tests[] =
4721 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, TRUE},
4722 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, FALSE},
4723 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, TRUE},
4724 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, FALSE},
4726 unsigned int i;
4728 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4729 0, 0, 640, 480, 0, 0, 0, 0);
4730 ddraw = create_ddraw();
4731 ok(!!ddraw, "Failed to create a ddraw object.\n");
4732 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4734 skip("Failed to create a 3D device, skipping test.\n");
4735 DestroyWindow(window);
4736 IDirectDraw2_Release(ddraw);
4737 return;
4740 hr = IDirect3DDevice2_GetRenderTarget(device, &target);
4741 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4743 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4745 BOOL discarded;
4747 memset(&ddsd, 0, sizeof(ddsd));
4748 ddsd.dwSize = sizeof(ddsd);
4749 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4750 ddsd.ddsCaps.dwCaps = tests[i].caps;
4751 ddsd.dwWidth = 64;
4752 ddsd.dwHeight = 64;
4753 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4754 if (FAILED(hr))
4756 skip("Failed to create surface, skipping.\n");
4757 continue;
4760 memset(&ddsd, 0, sizeof(ddsd));
4761 ddsd.dwSize = sizeof(ddsd);
4762 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
4763 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4764 addr = ddsd.lpSurface;
4765 hr = IDirectDrawSurface_Unlock(surface, NULL);
4766 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4768 memset(&ddsd, 0, sizeof(ddsd));
4769 ddsd.dwSize = sizeof(ddsd);
4770 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
4771 ok(SUCCEEDED(hr) , "Failed to lock surface, hr %#x.\n", hr);
4772 discarded = ddsd.lpSurface != addr;
4773 hr = IDirectDrawSurface_Unlock(surface, NULL);
4774 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4776 hr = IDirectDrawSurface_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
4777 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
4779 memset(&ddsd, 0, sizeof(ddsd));
4780 ddsd.dwSize = sizeof(ddsd);
4781 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
4782 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4783 discarded |= ddsd.lpSurface != addr;
4784 hr = IDirectDrawSurface_Unlock(surface, NULL);
4785 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4787 IDirectDrawSurface_Release(surface);
4789 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
4790 * AMD r500, evergreen). Windows XP, at least on AMD r200, never changes the pointer. */
4791 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
4794 IDirectDrawSurface_Release(target);
4795 IDirect3DDevice2_Release(device);
4796 IDirectDraw2_Release(ddraw);
4797 DestroyWindow(window);
4800 static void test_flip(void)
4802 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
4803 IDirectDrawSurface *primary, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
4804 DDSCAPS caps = {DDSCAPS_FLIP};
4805 DDSURFACEDESC surface_desc;
4806 BOOL sysmem_primary;
4807 IDirectDraw2 *ddraw;
4808 D3DCOLOR color;
4809 ULONG refcount;
4810 HWND window;
4811 DDBLTFX fx;
4812 HRESULT hr;
4814 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4815 0, 0, 640, 480, 0, 0, 0, 0);
4816 ddraw = create_ddraw();
4817 ok(!!ddraw, "Failed to create a ddraw object.\n");
4819 hr = set_display_mode(ddraw, 640, 480);
4820 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
4821 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4822 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4824 memset(&surface_desc, 0, sizeof(surface_desc));
4825 surface_desc.dwSize = sizeof(surface_desc);
4826 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
4827 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
4828 surface_desc.dwBackBufferCount = 3;
4829 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
4830 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4832 memset(&surface_desc, 0, sizeof(surface_desc));
4833 surface_desc.dwSize = sizeof(surface_desc);
4834 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
4835 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4836 ok((surface_desc.ddsCaps.dwCaps & ~placement)
4837 == (DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX),
4838 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
4839 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
4841 hr = IDirectDrawSurface_GetAttachedSurface(primary, &caps, &backbuffer1);
4842 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
4843 memset(&surface_desc, 0, sizeof(surface_desc));
4844 surface_desc.dwSize = sizeof(surface_desc);
4845 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer1, &surface_desc);
4846 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4847 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
4848 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_BACKBUFFER),
4849 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
4851 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
4852 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
4853 memset(&surface_desc, 0, sizeof(surface_desc));
4854 surface_desc.dwSize = sizeof(surface_desc);
4855 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer2, &surface_desc);
4856 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4857 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
4858 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
4859 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
4861 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
4862 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
4863 memset(&surface_desc, 0, sizeof(surface_desc));
4864 surface_desc.dwSize = sizeof(surface_desc);
4865 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer3, &surface_desc);
4866 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4867 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
4868 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
4869 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
4871 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer3, &caps, &surface);
4872 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
4873 ok(surface == primary, "Got unexpected surface %p, expected %p.\n", surface, primary);
4874 IDirectDrawSurface_Release(surface);
4876 memset(&surface_desc, 0, sizeof(surface_desc));
4877 surface_desc.dwSize = sizeof(surface_desc);
4878 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4879 surface_desc.ddsCaps.dwCaps = 0;
4880 surface_desc.dwWidth = 640;
4881 surface_desc.dwHeight = 480;
4882 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4883 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4884 hr = IDirectDrawSurface_Flip(primary, surface, DDFLIP_WAIT);
4885 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
4886 IDirectDrawSurface_Release(surface);
4888 hr = IDirectDrawSurface_Flip(primary, primary, DDFLIP_WAIT);
4889 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
4890 hr = IDirectDrawSurface_Flip(backbuffer1, NULL, DDFLIP_WAIT);
4891 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
4892 hr = IDirectDrawSurface_Flip(backbuffer2, NULL, DDFLIP_WAIT);
4893 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
4894 hr = IDirectDrawSurface_Flip(backbuffer3, NULL, DDFLIP_WAIT);
4895 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
4897 memset(&fx, 0, sizeof(fx));
4898 fx.dwSize = sizeof(fx);
4899 U5(fx).dwFillColor = 0xffff0000;
4900 hr = IDirectDrawSurface_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4901 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4902 U5(fx).dwFillColor = 0xff00ff00;
4903 hr = IDirectDrawSurface_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4904 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4905 U5(fx).dwFillColor = 0xff0000ff;
4906 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4907 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4909 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
4910 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
4911 color = get_surface_color(backbuffer1, 320, 240);
4912 /* The testbot seems to just copy the contents of one surface to all the
4913 * others, instead of properly flipping. */
4914 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
4915 "Got unexpected color 0x%08x.\n", color);
4916 color = get_surface_color(backbuffer2, 320, 240);
4917 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
4918 U5(fx).dwFillColor = 0xffff0000;
4919 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4920 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4922 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
4923 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
4924 color = get_surface_color(backbuffer1, 320, 240);
4925 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
4926 "Got unexpected color 0x%08x.\n", color);
4927 color = get_surface_color(backbuffer2, 320, 240);
4928 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
4929 U5(fx).dwFillColor = 0xff00ff00;
4930 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4931 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4933 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
4934 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
4935 color = get_surface_color(backbuffer1, 320, 240);
4936 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
4937 "Got unexpected color 0x%08x.\n", color);
4938 color = get_surface_color(backbuffer2, 320, 240);
4939 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
4940 U5(fx).dwFillColor = 0xff0000ff;
4941 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4942 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4944 hr = IDirectDrawSurface_Flip(primary, backbuffer1, DDFLIP_WAIT);
4945 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
4946 color = get_surface_color(backbuffer2, 320, 240);
4947 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
4948 "Got unexpected color 0x%08x.\n", color);
4949 color = get_surface_color(backbuffer3, 320, 240);
4950 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
4951 U5(fx).dwFillColor = 0xffff0000;
4952 hr = IDirectDrawSurface_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4953 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4955 hr = IDirectDrawSurface_Flip(primary, backbuffer2, DDFLIP_WAIT);
4956 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
4957 color = get_surface_color(backbuffer1, 320, 240);
4958 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
4959 color = get_surface_color(backbuffer3, 320, 240);
4960 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
4961 "Got unexpected color 0x%08x.\n", color);
4962 U5(fx).dwFillColor = 0xff00ff00;
4963 hr = IDirectDrawSurface_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4964 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4966 hr = IDirectDrawSurface_Flip(primary, backbuffer3, DDFLIP_WAIT);
4967 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
4968 color = get_surface_color(backbuffer1, 320, 240);
4969 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
4970 "Got unexpected color 0x%08x.\n", color);
4971 color = get_surface_color(backbuffer2, 320, 240);
4972 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
4974 IDirectDrawSurface_Release(backbuffer3);
4975 IDirectDrawSurface_Release(backbuffer2);
4976 IDirectDrawSurface_Release(backbuffer1);
4977 IDirectDrawSurface_Release(primary);
4978 refcount = IDirectDraw2_Release(ddraw);
4979 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4980 DestroyWindow(window);
4983 static void reset_ddsd(DDSURFACEDESC *ddsd)
4985 memset(ddsd, 0, sizeof(*ddsd));
4986 ddsd->dwSize = sizeof(*ddsd);
4989 static void test_set_surface_desc(void)
4991 IDirectDraw2 *ddraw;
4992 HWND window;
4993 HRESULT hr;
4994 DDSURFACEDESC ddsd;
4995 IDirectDrawSurface *surface;
4996 IDirectDrawSurface3 *surface3;
4997 BYTE data[16*16*4];
4998 ULONG ref;
4999 unsigned int i;
5000 static const struct
5002 DWORD caps;
5003 BOOL supported;
5004 const char *name;
5006 invalid_caps_tests[] =
5008 {DDSCAPS_VIDEOMEMORY, FALSE, "videomemory plain"},
5009 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, TRUE, "systemmemory texture"},
5010 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, FALSE, "systemmemory primary"},
5013 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5014 0, 0, 640, 480, 0, 0, 0, 0);
5015 ddraw = create_ddraw();
5016 ok(!!ddraw, "Failed to create a ddraw object.\n");
5017 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5018 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5020 reset_ddsd(&ddsd);
5021 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
5022 ddsd.dwWidth = 8;
5023 ddsd.dwHeight = 8;
5024 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5025 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5026 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
5027 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5028 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5029 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5030 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
5032 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
5033 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5035 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
5036 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface3 interface, hr %#x.\n", hr);
5037 IDirectDrawSurface_Release(surface);
5039 reset_ddsd(&ddsd);
5040 ddsd.dwFlags = DDSD_LPSURFACE;
5041 ddsd.lpSurface = data;
5042 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5043 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5045 /* Redundantly setting the same lpSurface is not an error. */
5046 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5047 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5048 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
5049 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5050 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
5051 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
5053 hr = IDirectDrawSurface3_Lock(surface3, NULL, &ddsd, 0, NULL);
5054 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5055 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
5056 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
5057 hr = IDirectDrawSurface3_Unlock(surface3, NULL);
5058 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5060 reset_ddsd(&ddsd);
5061 ddsd.dwFlags = DDSD_LPSURFACE;
5062 ddsd.lpSurface = data;
5063 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 1);
5064 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
5066 ddsd.lpSurface = NULL;
5067 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5068 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
5070 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, NULL, 0);
5071 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
5073 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
5074 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5075 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
5076 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
5078 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
5079 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5080 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
5082 ddsd.dwFlags = DDSD_CAPS;
5083 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5084 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
5086 /* dwCaps = 0 is allowed, but ignored. */
5087 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
5088 ddsd.lpSurface = data;
5089 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5090 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
5091 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
5092 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5093 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
5094 ddsd.ddsCaps.dwCaps = 0;
5095 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5096 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5098 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
5099 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5100 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
5101 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
5103 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
5104 reset_ddsd(&ddsd);
5105 ddsd.dwFlags = DDSD_HEIGHT;
5106 ddsd.dwHeight = 16;
5107 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5108 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
5110 ddsd.lpSurface = data;
5111 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
5112 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5113 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5115 ddsd.dwHeight = 0;
5116 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5117 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
5119 reset_ddsd(&ddsd);
5120 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
5121 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
5122 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
5123 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
5125 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0. */
5126 reset_ddsd(&ddsd);
5127 ddsd.dwFlags = DDSD_PITCH;
5128 U1(ddsd).lPitch = 8 * 4;
5129 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5130 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
5132 ddsd.dwFlags = DDSD_WIDTH;
5133 ddsd.dwWidth = 16;
5134 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5135 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
5137 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
5138 ddsd.lpSurface = data;
5139 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5140 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
5142 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
5143 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5144 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
5146 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5147 U1(ddsd).lPitch = 16 * 4;
5148 ddsd.dwWidth = 16;
5149 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5150 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5152 reset_ddsd(&ddsd);
5153 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
5154 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5155 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
5156 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
5157 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
5159 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
5161 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
5162 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5163 U1(ddsd).lPitch = 4 * 4;
5164 ddsd.lpSurface = data;
5165 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5166 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
5168 U1(ddsd).lPitch = 4;
5169 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5170 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
5172 U1(ddsd).lPitch = 16 * 4 + 1;
5173 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5174 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
5176 U1(ddsd).lPitch = 16 * 4 + 3;
5177 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5178 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
5180 U1(ddsd).lPitch = -4;
5181 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5182 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
5184 U1(ddsd).lPitch = 16 * 4;
5185 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5186 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5188 reset_ddsd(&ddsd);
5189 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5190 U1(ddsd).lPitch = 0;
5191 ddsd.dwWidth = 16;
5192 ddsd.lpSurface = data;
5193 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5194 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
5196 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5197 U1(ddsd).lPitch = 16 * 4;
5198 ddsd.dwWidth = 0;
5199 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5200 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
5202 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
5203 ddsd.dwFlags = DDSD_PIXELFORMAT;
5204 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5205 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5206 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
5207 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5208 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5209 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5210 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5211 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
5213 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
5214 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5215 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5217 /* Can't set color keys. */
5218 reset_ddsd(&ddsd);
5219 ddsd.dwFlags = DDSD_CKSRCBLT;
5220 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
5221 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
5222 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5223 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
5225 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
5226 ddsd.lpSurface = data;
5227 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5228 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
5230 IDirectDrawSurface3_Release(surface3);
5232 /* SetSurfaceDesc needs systemmemory surfaces.
5234 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing DDSD_LINEARSIZE is moot. */
5235 for (i = 0; i < sizeof(invalid_caps_tests) / sizeof(*invalid_caps_tests); i++)
5237 reset_ddsd(&ddsd);
5238 ddsd.dwFlags = DDSD_CAPS;
5239 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
5240 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
5242 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5243 ddsd.dwWidth = 8;
5244 ddsd.dwHeight = 8;
5245 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5246 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5247 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
5248 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5249 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5250 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5253 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
5254 ok(SUCCEEDED(hr) || hr == DDERR_NODIRECTDRAWHW, "Failed to create surface, hr %#x.\n", hr);
5255 if (FAILED(hr))
5257 skip("Cannot create a %s surface, skipping vidmem SetSurfaceDesc test.\n",
5258 invalid_caps_tests[i].name);
5259 goto done;
5261 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
5262 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface3 interface, hr %#x.\n", hr);
5263 IDirectDrawSurface_Release(surface);
5265 reset_ddsd(&ddsd);
5266 ddsd.dwFlags = DDSD_LPSURFACE;
5267 ddsd.lpSurface = data;
5268 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5269 if (invalid_caps_tests[i].supported)
5271 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5273 else
5275 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
5276 invalid_caps_tests[i].name, hr);
5278 /* Check priority of error conditions. */
5279 ddsd.dwFlags = DDSD_WIDTH;
5280 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5281 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
5282 invalid_caps_tests[i].name, hr);
5285 IDirectDrawSurface3_Release(surface3);
5288 done:
5289 ref = IDirectDraw2_Release(ddraw);
5290 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
5291 DestroyWindow(window);
5294 static void test_user_memory_getdc(void)
5296 IDirectDraw2 *ddraw;
5297 HWND window;
5298 HRESULT hr;
5299 DDSURFACEDESC ddsd;
5300 IDirectDrawSurface *surface;
5301 IDirectDrawSurface3 *surface3;
5302 DWORD data[16][16];
5303 ULONG ref;
5304 HDC dc;
5305 unsigned int x, y;
5307 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5308 0, 0, 640, 480, 0, 0, 0, 0);
5309 ddraw = create_ddraw();
5310 ok(!!ddraw, "Failed to create a ddraw object.\n");
5312 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5313 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5315 reset_ddsd(&ddsd);
5316 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
5317 ddsd.dwWidth = 16;
5318 ddsd.dwHeight = 16;
5319 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5320 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5321 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
5322 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5323 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5324 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5325 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
5326 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
5327 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5329 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
5330 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface3 interface, hr %#x.\n", hr);
5331 IDirectDrawSurface_Release(surface);
5333 memset(data, 0xaa, sizeof(data));
5334 reset_ddsd(&ddsd);
5335 ddsd.dwFlags = DDSD_LPSURFACE;
5336 ddsd.lpSurface = data;
5337 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5338 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5340 hr = IDirectDrawSurface3_GetDC(surface3, &dc);
5341 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
5342 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
5343 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
5344 hr = IDirectDrawSurface3_ReleaseDC(surface3, dc);
5345 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
5347 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
5348 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
5350 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
5351 ddsd.lpSurface = data;
5352 ddsd.dwWidth = 4;
5353 ddsd.dwHeight = 8;
5354 U1(ddsd).lPitch = sizeof(*data);
5355 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5356 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5358 memset(data, 0xaa, sizeof(data));
5359 hr = IDirectDrawSurface3_GetDC(surface3, &dc);
5360 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
5361 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
5362 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
5363 hr = IDirectDrawSurface3_ReleaseDC(surface3, dc);
5364 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
5366 for (y = 0; y < 4; y++)
5368 for (x = 0; x < 4; x++)
5370 if ((x == 1 || x == 2) && (y == 1 || y == 2))
5371 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
5372 x, y, data[y][x]);
5373 else
5374 ok(data[y][x] == 0x00000000, "Expected color 0xaaaaaaaa on position %ux%u, got %#x.\n",
5375 x, y, data[y][x]);
5378 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
5379 data[0][5]);
5380 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
5381 data[7][3]);
5382 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
5383 data[7][4]);
5384 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
5385 data[8][0]);
5387 IDirectDrawSurface3_Release(surface3);
5388 ref = IDirectDraw2_Release(ddraw);
5389 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
5390 DestroyWindow(window);
5393 static void test_sysmem_overlay(void)
5395 IDirectDraw2 *ddraw;
5396 HWND window;
5397 HRESULT hr;
5398 DDSURFACEDESC ddsd;
5399 IDirectDrawSurface *surface;
5400 ULONG ref;
5402 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5403 0, 0, 640, 480, 0, 0, 0, 0);
5404 ddraw = create_ddraw();
5405 ok(!!ddraw, "Failed to create a ddraw object.\n");
5407 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5408 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5410 reset_ddsd(&ddsd);
5411 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
5412 ddsd.dwWidth = 16;
5413 ddsd.dwHeight = 16;
5414 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
5415 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5416 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5417 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
5418 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5419 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5420 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5421 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
5422 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
5424 ref = IDirectDraw2_Release(ddraw);
5425 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
5426 DestroyWindow(window);
5429 static void test_primary_palette(void)
5431 DDSCAPS surface_caps = {DDSCAPS_FLIP};
5432 IDirectDrawSurface *primary, *backbuffer;
5433 PALETTEENTRY palette_entries[256];
5434 IDirectDrawPalette *palette, *tmp;
5435 DDSURFACEDESC surface_desc;
5436 IDirectDraw2 *ddraw;
5437 DWORD palette_caps;
5438 ULONG refcount;
5439 HWND window;
5440 HRESULT hr;
5442 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5443 0, 0, 640, 480, 0, 0, 0, 0);
5444 ddraw = create_ddraw();
5445 ok(!!ddraw, "Failed to create a ddraw object.\n");
5446 if (FAILED(IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
5448 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
5449 IDirectDraw2_Release(ddraw);
5450 DestroyWindow(window);
5451 return;
5453 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5454 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5456 memset(&surface_desc, 0, sizeof(surface_desc));
5457 surface_desc.dwSize = sizeof(surface_desc);
5458 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
5459 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
5460 surface_desc.dwBackBufferCount = 1;
5461 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
5462 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5463 hr = IDirectDrawSurface_GetAttachedSurface(primary, &surface_caps, &backbuffer);
5464 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
5466 memset(palette_entries, 0, sizeof(palette_entries));
5467 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
5468 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5469 refcount = get_refcount((IUnknown *)palette);
5470 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5472 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
5473 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
5474 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
5476 hr = IDirectDrawSurface_SetPalette(primary, palette);
5477 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5479 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
5480 * and is generally somewhat broken with respect to 8 bpp / palette
5481 * handling. */
5482 if (SUCCEEDED(IDirectDrawSurface_GetPalette(backbuffer, &tmp)))
5484 win_skip("Broken palette handling detected, skipping tests.\n");
5485 IDirectDrawPalette_Release(tmp);
5486 IDirectDrawPalette_Release(palette);
5487 /* The Windows 8 testbot keeps extra references to the primary and
5488 * backbuffer while in 8 bpp mode. */
5489 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
5490 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
5491 goto done;
5494 refcount = get_refcount((IUnknown *)palette);
5495 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
5497 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
5498 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
5499 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
5500 "Got unexpected palette caps %#x.\n", palette_caps);
5502 hr = IDirectDrawSurface_SetPalette(primary, NULL);
5503 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5504 refcount = get_refcount((IUnknown *)palette);
5505 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5507 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
5508 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
5509 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
5511 hr = IDirectDrawSurface_SetPalette(primary, palette);
5512 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5513 refcount = get_refcount((IUnknown *)palette);
5514 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
5516 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
5517 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
5518 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
5519 IDirectDrawPalette_Release(tmp);
5520 hr = IDirectDrawSurface_GetPalette(backbuffer, &tmp);
5521 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
5523 refcount = IDirectDrawPalette_Release(palette);
5524 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5525 refcount = IDirectDrawPalette_Release(palette);
5526 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5528 /* Note that this only seems to work when the palette is attached to the
5529 * primary surface. When attached to a regular surface, attempting to get
5530 * the palette here will cause an access violation. */
5531 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
5532 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
5534 done:
5535 refcount = IDirectDrawSurface_Release(backbuffer);
5536 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5537 refcount = IDirectDrawSurface_Release(primary);
5538 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5539 refcount = IDirectDraw2_Release(ddraw);
5540 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5541 DestroyWindow(window);
5544 static HRESULT WINAPI surface_counter(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
5546 UINT *surface_count = context;
5548 ++(*surface_count);
5549 IDirectDrawSurface_Release(surface);
5551 return DDENUMRET_OK;
5554 static void test_surface_attachment(void)
5556 IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
5557 DDSCAPS caps = {DDSCAPS_TEXTURE};
5558 DDSURFACEDESC surface_desc;
5559 IDirectDraw2 *ddraw;
5560 UINT surface_count;
5561 ULONG refcount;
5562 HWND window;
5563 HRESULT hr;
5565 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5566 0, 0, 640, 480, 0, 0, 0, 0);
5567 ddraw = create_ddraw();
5568 ok(!!ddraw, "Failed to create a ddraw object.\n");
5569 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5570 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5572 memset(&surface_desc, 0, sizeof(surface_desc));
5573 surface_desc.dwSize = sizeof(surface_desc);
5574 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
5575 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
5576 U2(surface_desc).dwMipMapCount = 3;
5577 surface_desc.dwWidth = 128;
5578 surface_desc.dwHeight = 128;
5579 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
5580 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5582 hr = IDirectDrawSurface_GetAttachedSurface(surface1, &caps, &surface2);
5583 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
5584 hr = IDirectDrawSurface_GetAttachedSurface(surface2, &caps, &surface3);
5585 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
5586 hr = IDirectDrawSurface_GetAttachedSurface(surface3, &caps, &surface4);
5587 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5589 surface_count = 0;
5590 IDirectDrawSurface_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
5591 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
5592 surface_count = 0;
5593 IDirectDrawSurface_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
5594 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
5595 surface_count = 0;
5596 IDirectDrawSurface_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
5597 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
5599 memset(&surface_desc, 0, sizeof(surface_desc));
5600 surface_desc.dwSize = sizeof(surface_desc);
5601 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5602 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5603 surface_desc.dwWidth = 16;
5604 surface_desc.dwHeight = 16;
5605 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
5606 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5608 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
5609 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5610 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
5611 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5612 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
5613 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5614 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
5615 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5616 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
5617 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5618 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
5619 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5621 IDirectDrawSurface_Release(surface4);
5623 memset(&surface_desc, 0, sizeof(surface_desc));
5624 surface_desc.dwSize = sizeof(surface_desc);
5625 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5626 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
5627 surface_desc.dwWidth = 16;
5628 surface_desc.dwHeight = 16;
5629 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
5630 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5632 if (SUCCEEDED(hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4)))
5634 skip("Running on refrast, skipping some tests.\n");
5635 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface4);
5636 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5638 else
5640 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5641 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
5642 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5643 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
5644 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5645 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
5646 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5647 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
5648 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5649 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
5650 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5653 IDirectDrawSurface_Release(surface4);
5654 IDirectDrawSurface_Release(surface3);
5655 IDirectDrawSurface_Release(surface2);
5656 IDirectDrawSurface_Release(surface1);
5658 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5659 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5661 /* Try a single primary and two offscreen plain surfaces. */
5662 memset(&surface_desc, 0, sizeof(surface_desc));
5663 surface_desc.dwSize = sizeof(surface_desc);
5664 surface_desc.dwFlags = DDSD_CAPS;
5665 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
5666 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
5667 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5669 memset(&surface_desc, 0, sizeof(surface_desc));
5670 surface_desc.dwSize = sizeof(surface_desc);
5671 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5672 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5673 surface_desc.dwWidth = registry_mode.dmPelsWidth;
5674 surface_desc.dwHeight = registry_mode.dmPelsHeight;
5675 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
5676 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5678 memset(&surface_desc, 0, sizeof(surface_desc));
5679 surface_desc.dwSize = sizeof(surface_desc);
5680 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5681 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5682 surface_desc.dwWidth = registry_mode.dmPelsWidth;
5683 surface_desc.dwHeight = registry_mode.dmPelsHeight;
5684 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
5685 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5687 /* This one has a different size. */
5688 memset(&surface_desc, 0, sizeof(surface_desc));
5689 surface_desc.dwSize = sizeof(surface_desc);
5690 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5691 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5692 surface_desc.dwWidth = 128;
5693 surface_desc.dwHeight = 128;
5694 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
5695 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5697 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5698 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5699 /* Try the reverse without detaching first. */
5700 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
5701 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
5702 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
5703 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5705 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
5706 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5707 /* Try to detach reversed. */
5708 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
5709 ok(hr == DDERR_CANNOTDETACHSURFACE, "Got unexpected hr %#x.\n", hr);
5710 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
5711 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5713 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
5714 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5715 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
5716 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5718 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
5719 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5720 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
5721 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5723 IDirectDrawSurface_Release(surface4);
5724 IDirectDrawSurface_Release(surface3);
5725 IDirectDrawSurface_Release(surface2);
5726 IDirectDrawSurface_Release(surface1);
5728 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
5729 memset(&surface_desc, 0, sizeof(surface_desc));
5730 surface_desc.dwSize = sizeof(surface_desc);
5731 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5732 surface_desc.dwWidth = 64;
5733 surface_desc.dwHeight = 64;
5734 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5735 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
5736 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
5737 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
5738 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xf800;
5739 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x07e0;
5740 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x001f;
5741 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
5742 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5743 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
5744 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5746 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
5747 surface_desc.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
5748 U1(surface_desc.ddpfPixelFormat).dwZBufferBitDepth = 16;
5749 U3(surface_desc.ddpfPixelFormat).dwZBitMask = 0x0000ffff;
5750 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
5751 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5753 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5754 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5755 refcount = get_refcount((IUnknown *)surface2);
5756 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
5757 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5758 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
5760 /* Attaching while already attached to other surface. */
5761 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface2);
5762 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5763 hr = IDirectDrawSurface_DeleteAttachedSurface(surface3, 0, surface2);
5764 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5765 IDirectDrawSurface_Release(surface3);
5767 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
5768 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5769 refcount = get_refcount((IUnknown *)surface2);
5770 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5772 /* Automatic detachment on release. */
5773 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5774 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5775 refcount = get_refcount((IUnknown *)surface2);
5776 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
5777 refcount = IDirectDrawSurface_Release(surface1);
5778 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5779 refcount = IDirectDrawSurface_Release(surface2);
5780 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5781 refcount = IDirectDraw2_Release(ddraw);
5782 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5783 DestroyWindow(window);
5786 static void test_pixel_format(void)
5788 HWND window, window2 = NULL;
5789 HDC hdc, hdc2 = NULL;
5790 HMODULE gl = NULL;
5791 int format, test_format;
5792 PIXELFORMATDESCRIPTOR pfd;
5793 IDirectDraw2 *ddraw = NULL;
5794 IDirectDrawClipper *clipper = NULL;
5795 DDSURFACEDESC ddsd;
5796 IDirectDrawSurface *primary = NULL;
5797 DDBLTFX fx;
5798 HRESULT hr;
5800 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5801 100, 100, 160, 160, NULL, NULL, NULL, NULL);
5802 if (!window)
5804 skip("Failed to create window\n");
5805 return;
5808 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5809 100, 100, 160, 160, NULL, NULL, NULL, NULL);
5811 hdc = GetDC(window);
5812 if (!hdc)
5814 skip("Failed to get DC\n");
5815 goto cleanup;
5818 if (window2)
5819 hdc2 = GetDC(window2);
5821 gl = LoadLibraryA("opengl32.dll");
5822 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
5824 format = GetPixelFormat(hdc);
5825 ok(format == 0, "new window has pixel format %d\n", format);
5827 ZeroMemory(&pfd, sizeof(pfd));
5828 pfd.nSize = sizeof(pfd);
5829 pfd.nVersion = 1;
5830 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
5831 pfd.iPixelType = PFD_TYPE_RGBA;
5832 pfd.iLayerType = PFD_MAIN_PLANE;
5833 format = ChoosePixelFormat(hdc, &pfd);
5834 if (format <= 0)
5836 skip("no pixel format available\n");
5837 goto cleanup;
5840 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
5842 skip("failed to set pixel format\n");
5843 goto cleanup;
5846 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
5848 skip("failed to set pixel format on second window\n");
5849 if (hdc2)
5851 ReleaseDC(window2, hdc2);
5852 hdc2 = NULL;
5856 ddraw = create_ddraw();
5857 ok(!!ddraw, "Failed to create a ddraw object.\n");
5859 test_format = GetPixelFormat(hdc);
5860 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5862 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5863 if (FAILED(hr))
5865 skip("Failed to set cooperative level, hr %#x.\n", hr);
5866 goto cleanup;
5869 test_format = GetPixelFormat(hdc);
5870 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5872 if (hdc2)
5874 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
5875 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
5876 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
5877 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
5879 test_format = GetPixelFormat(hdc);
5880 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5882 test_format = GetPixelFormat(hdc2);
5883 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
5886 memset(&ddsd, 0, sizeof(ddsd));
5887 ddsd.dwSize = sizeof(ddsd);
5888 ddsd.dwFlags = DDSD_CAPS;
5889 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
5891 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
5892 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
5894 test_format = GetPixelFormat(hdc);
5895 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5897 if (hdc2)
5899 test_format = GetPixelFormat(hdc2);
5900 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
5903 if (clipper)
5905 hr = IDirectDrawSurface2_SetClipper(primary, clipper);
5906 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
5908 test_format = GetPixelFormat(hdc);
5909 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5911 test_format = GetPixelFormat(hdc2);
5912 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
5915 memset(&fx, 0, sizeof(fx));
5916 fx.dwSize = sizeof(fx);
5917 hr = IDirectDrawSurface2_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5918 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
5920 test_format = GetPixelFormat(hdc);
5921 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5923 if (hdc2)
5925 test_format = GetPixelFormat(hdc2);
5926 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
5929 cleanup:
5930 if (primary) IDirectDrawSurface2_Release(primary);
5931 if (clipper) IDirectDrawClipper_Release(clipper);
5932 if (ddraw) IDirectDraw2_Release(ddraw);
5933 if (gl) FreeLibrary(gl);
5934 if (hdc) ReleaseDC(window, hdc);
5935 if (hdc2) ReleaseDC(window2, hdc2);
5936 if (window) DestroyWindow(window);
5937 if (window2) DestroyWindow(window2);
5940 static void test_create_surface_pitch(void)
5942 IDirectDrawSurface *surface;
5943 DDSURFACEDESC surface_desc;
5944 IDirectDraw2 *ddraw;
5945 unsigned int i;
5946 ULONG refcount;
5947 HWND window;
5948 HRESULT hr;
5949 void *mem;
5951 static const struct
5953 DWORD caps;
5954 DWORD flags_in;
5955 DWORD pitch_in;
5956 HRESULT hr;
5957 DWORD flags_out;
5958 DWORD pitch_out32;
5959 DWORD pitch_out64;
5961 test_data[] =
5963 /* 0 */
5964 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
5965 0, 0, DD_OK,
5966 DDSD_PITCH, 0x100, 0x100},
5967 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
5968 DDSD_PITCH, 0x104, DD_OK,
5969 DDSD_PITCH, 0x100, 0x100},
5970 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
5971 DDSD_PITCH, 0x0f8, DD_OK,
5972 DDSD_PITCH, 0x100, 0x100},
5973 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
5974 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
5975 0, 0, 0 },
5976 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
5977 0, 0, DD_OK,
5978 DDSD_PITCH, 0x100, 0x0fc},
5979 /* 5 */
5980 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
5981 DDSD_PITCH, 0x104, DD_OK,
5982 DDSD_PITCH, 0x100, 0x0fc},
5983 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
5984 DDSD_PITCH, 0x0f8, DD_OK,
5985 DDSD_PITCH, 0x100, 0x0fc},
5986 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
5987 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
5988 DDSD_PITCH, 0x100, 0x0fc},
5989 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
5990 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
5991 0, 0, 0 },
5992 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
5993 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDPARAMS,
5994 0, 0, 0 },
5995 /* 10 */
5996 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
5997 0, 0, DDERR_INVALIDCAPS,
5998 0, 0, 0 },
5999 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
6000 0, 0, DD_OK,
6001 DDSD_PITCH, 0x100, 0 },
6002 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
6003 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
6004 0, 0, 0 },
6005 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
6006 0, 0, DDERR_INVALIDCAPS,
6007 0, 0, 0 },
6008 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
6009 0, 0, DD_OK,
6010 DDSD_PITCH, 0x100, 0 },
6011 /* 15 */
6012 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
6013 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDPARAMS,
6014 0, 0, 0 },
6016 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
6018 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6019 0, 0, 640, 480, 0, 0, 0, 0);
6020 ddraw = create_ddraw();
6021 ok(!!ddraw, "Failed to create a ddraw object.\n");
6022 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6023 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6025 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
6027 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
6029 memset(&surface_desc, 0, sizeof(surface_desc));
6030 surface_desc.dwSize = sizeof(surface_desc);
6031 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
6032 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
6033 surface_desc.dwWidth = 63;
6034 surface_desc.dwHeight = 63;
6035 U1(surface_desc).lPitch = test_data[i].pitch_in;
6036 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6037 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
6038 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
6039 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6040 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6041 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
6042 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6043 if (test_data[i].flags_in & DDSD_LPSURFACE)
6045 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
6046 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, expected_hr);
6047 surface_desc.lpSurface = mem;
6048 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6050 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
6051 continue;
6052 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
6053 if (FAILED(hr))
6054 continue;
6056 memset(&surface_desc, 0, sizeof(surface_desc));
6057 surface_desc.dwSize = sizeof(surface_desc);
6058 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
6059 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
6060 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
6061 "Test %u: Got unexpected flags %#x, expected %#x.\n",
6062 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
6063 /* The pitch for textures seems to be implementation specific. */
6064 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
6066 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
6067 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
6068 "Test %u: Got unexpected pitch %u, expected %u.\n",
6069 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
6070 else
6071 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
6072 "Test %u: Got unexpected pitch %u, expected %u.\n",
6073 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
6075 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
6077 IDirectDrawSurface_Release(surface);
6080 HeapFree(GetProcessHeap(), 0, mem);
6081 refcount = IDirectDraw2_Release(ddraw);
6082 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6083 DestroyWindow(window);
6086 static void test_mipmap(void)
6088 IDirectDrawSurface *surface1;
6089 IDirectDrawSurface2 *surface, *surface2;
6090 DDSURFACEDESC surface_desc;
6091 IDirectDraw2 *ddraw;
6092 unsigned int i;
6093 ULONG refcount;
6094 HWND window;
6095 HRESULT hr;
6096 DDSCAPS caps = {DDSCAPS_COMPLEX};
6097 DDCAPS hal_caps;
6099 static const struct
6101 DWORD flags;
6102 DWORD caps;
6103 DWORD width;
6104 DWORD height;
6105 DWORD mipmap_count_in;
6106 HRESULT hr;
6107 DWORD mipmap_count_out;
6109 tests[] =
6111 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
6112 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS, 0},
6113 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
6114 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS, 0},
6115 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 6},
6116 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 6},
6119 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6120 0, 0, 640, 480, 0, 0, 0, 0);
6121 ddraw = create_ddraw();
6122 ok(!!ddraw, "Failed to create a ddraw object.\n");
6123 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6124 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6126 memset(&hal_caps, 0, sizeof(hal_caps));
6127 hal_caps.dwSize = sizeof(hal_caps);
6128 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
6129 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6130 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
6132 skip("Mipmapped textures not supported, skipping tests.\n");
6133 IDirectDraw2_Release(ddraw);
6134 DestroyWindow(window);
6135 return;
6138 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
6140 memset(&surface_desc, 0, sizeof(surface_desc));
6141 surface_desc.dwSize = sizeof(surface_desc);
6142 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
6143 surface_desc.ddsCaps.dwCaps = tests[i].caps;
6144 surface_desc.dwWidth = tests[i].width;
6145 surface_desc.dwHeight = tests[i].height;
6146 if (tests[i].flags & DDSD_MIPMAPCOUNT)
6147 U2(surface_desc).dwMipMapCount = tests[i].mipmap_count_in;
6148 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6149 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
6150 if (FAILED(hr))
6151 continue;
6153 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
6154 ok(SUCCEEDED(hr), "Test %u: Failed to get IDirectDrawSurface2 interface, hr %#x.\n", i, hr);
6155 IDirectDrawSurface_Release(surface1);
6157 memset(&surface_desc, 0, sizeof(surface_desc));
6158 surface_desc.dwSize = sizeof(surface_desc);
6159 hr = IDirectDrawSurface2_GetSurfaceDesc(surface, &surface_desc);
6160 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
6161 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
6162 "Test %u: Got unexpected flags %#x.\n", i, surface_desc.dwFlags);
6163 ok(U2(surface_desc).dwMipMapCount == tests[i].mipmap_count_out,
6164 "Test %u: Got unexpected mipmap count %u.\n", i, U2(surface_desc).dwMipMapCount);
6166 if (U2(surface_desc).dwMipMapCount > 1)
6168 hr = IDirectDrawSurface2_GetAttachedSurface(surface, &caps, &surface2);
6169 ok(SUCCEEDED(hr), "Test %u: Failed to get attached surface, hr %#x.\n", i, hr);
6171 memset(&surface_desc, 0, sizeof(surface_desc));
6172 surface_desc.dwSize = sizeof(surface_desc);
6173 hr = IDirectDrawSurface2_Lock(surface, NULL, &surface_desc, 0, NULL);
6174 ok(SUCCEEDED(hr), "Test %u: Failed to lock surface, hr %#x.\n", i, hr);
6175 memset(&surface_desc, 0, sizeof(surface_desc));
6176 surface_desc.dwSize = sizeof(surface_desc);
6177 hr = IDirectDrawSurface2_Lock(surface2, NULL, &surface_desc, 0, NULL);
6178 ok(SUCCEEDED(hr), "Test %u: Failed to lock surface, hr %#x.\n", i, hr);
6179 IDirectDrawSurface2_Unlock(surface2, NULL);
6180 IDirectDrawSurface2_Unlock(surface, NULL);
6182 IDirectDrawSurface2_Release(surface2);
6185 IDirectDrawSurface2_Release(surface);
6188 refcount = IDirectDraw2_Release(ddraw);
6189 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6190 DestroyWindow(window);
6193 static void test_palette_complex(void)
6195 IDirectDrawSurface *surface1;
6196 IDirectDrawSurface2 *surface, *mipmap, *tmp;
6197 DDSURFACEDESC surface_desc;
6198 IDirectDraw2 *ddraw;
6199 IDirectDrawPalette *palette, *palette2, *palette_mipmap;
6200 ULONG refcount;
6201 HWND window;
6202 HRESULT hr;
6203 DDSCAPS caps = {DDSCAPS_COMPLEX};
6204 DDCAPS hal_caps;
6205 PALETTEENTRY palette_entries[256];
6206 unsigned int i;
6207 HDC dc;
6208 RGBQUAD rgbquad;
6209 UINT count;
6211 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6212 0, 0, 640, 480, 0, 0, 0, 0);
6213 ddraw = create_ddraw();
6214 ok(!!ddraw, "Failed to create a ddraw object.\n");
6215 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6216 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6218 memset(&hal_caps, 0, sizeof(hal_caps));
6219 hal_caps.dwSize = sizeof(hal_caps);
6220 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
6221 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6222 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
6224 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
6225 IDirectDraw2_Release(ddraw);
6226 DestroyWindow(window);
6227 return;
6230 memset(&surface_desc, 0, sizeof(surface_desc));
6231 surface_desc.dwSize = sizeof(surface_desc);
6232 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6233 surface_desc.dwWidth = 128;
6234 surface_desc.dwHeight = 128;
6235 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
6236 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6237 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
6238 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
6239 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6240 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6241 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
6242 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface2 interface, hr %#x.\n", hr);
6243 IDirectDrawSurface_Release(surface1);
6245 memset(palette_entries, 0, sizeof(palette_entries));
6246 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
6247 palette_entries, &palette, NULL);
6248 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6250 memset(palette_entries, 0, sizeof(palette_entries));
6251 palette_entries[1].peRed = 0xff;
6252 palette_entries[1].peGreen = 0x80;
6253 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
6254 palette_entries, &palette_mipmap, NULL);
6255 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6257 palette2 = (void *)0xdeadbeef;
6258 hr = IDirectDrawSurface2_GetPalette(surface, &palette2);
6259 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6260 ok(!palette2, "Got unexpected palette %p.\n", palette2);
6261 hr = IDirectDrawSurface2_SetPalette(surface, palette);
6262 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6263 hr = IDirectDrawSurface2_GetPalette(surface, &palette2);
6264 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
6265 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
6266 IDirectDrawPalette_Release(palette2);
6268 mipmap = surface;
6269 IDirectDrawSurface2_AddRef(mipmap);
6270 for (i = 0; i < 7; ++i)
6272 hr = IDirectDrawSurface2_GetAttachedSurface(mipmap, &caps, &tmp);
6273 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
6274 palette2 = (void *)0xdeadbeef;
6275 hr = IDirectDrawSurface2_GetPalette(tmp, &palette2);
6276 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
6277 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
6279 hr = IDirectDrawSurface2_SetPalette(tmp, palette_mipmap);
6280 ok(SUCCEEDED(hr), "Failed to set palette, i %u, hr %#x.\n", i, hr);
6282 hr = IDirectDrawSurface2_GetPalette(tmp, &palette2);
6283 ok(SUCCEEDED(hr), "Failed to get palette, i %u, hr %#x.\n", i, hr);
6284 ok(palette_mipmap == palette2, "Got unexpected palette %p.\n", palette2);
6285 IDirectDrawPalette_Release(palette2);
6287 hr = IDirectDrawSurface2_GetDC(tmp, &dc);
6288 ok(SUCCEEDED(hr), "Failed to get DC, i %u, hr %#x.\n", i, hr);
6289 count = GetDIBColorTable(dc, 1, 1, &rgbquad);
6290 ok(count == 1, "Expected count 1, got %u.\n", count);
6291 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x.\n", rgbquad.rgbRed);
6292 ok(rgbquad.rgbGreen == 0x80, "Expected rgbGreen = 0x80, got %#x.\n", rgbquad.rgbGreen);
6293 ok(rgbquad.rgbBlue == 0x0, "Expected rgbBlue = 0x0, got %#x.\n", rgbquad.rgbBlue);
6294 hr = IDirectDrawSurface2_ReleaseDC(tmp, dc);
6295 ok(SUCCEEDED(hr), "Failed to release DC, i %u, hr %#x.\n", i, hr);
6297 IDirectDrawSurface2_Release(mipmap);
6298 mipmap = tmp;
6301 hr = IDirectDrawSurface2_GetAttachedSurface(mipmap, &caps, &tmp);
6302 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
6303 IDirectDrawSurface2_Release(mipmap);
6304 refcount = IDirectDrawSurface2_Release(surface);
6305 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6306 refcount = IDirectDrawPalette_Release(palette_mipmap);
6307 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6308 refcount = IDirectDrawPalette_Release(palette);
6309 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6311 refcount = IDirectDraw2_Release(ddraw);
6312 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6313 DestroyWindow(window);
6316 static void test_p8_rgb_blit(void)
6318 IDirectDrawSurface *src, *dst;
6319 DDSURFACEDESC surface_desc;
6320 IDirectDraw2 *ddraw;
6321 IDirectDrawPalette *palette;
6322 ULONG refcount;
6323 HWND window;
6324 HRESULT hr;
6325 PALETTEENTRY palette_entries[256];
6326 unsigned int x;
6327 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
6328 static const D3DCOLOR expected[] =
6330 0x00101010, 0x00010101, 0x00020202, 0x00030303,
6331 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
6333 D3DCOLOR color;
6335 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6336 0, 0, 640, 480, 0, 0, 0, 0);
6337 ddraw = create_ddraw();
6338 ok(!!ddraw, "Failed to create a ddraw object.\n");
6339 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6340 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6342 memset(palette_entries, 0, sizeof(palette_entries));
6343 palette_entries[1].peGreen = 0xff;
6344 palette_entries[2].peBlue = 0xff;
6345 palette_entries[3].peFlags = 0xff;
6346 palette_entries[4].peRed = 0xff;
6347 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
6348 palette_entries, &palette, NULL);
6349 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6351 memset(&surface_desc, 0, sizeof(surface_desc));
6352 surface_desc.dwSize = sizeof(surface_desc);
6353 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6354 surface_desc.dwWidth = 8;
6355 surface_desc.dwHeight = 1;
6356 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6357 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6358 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
6359 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
6360 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src, NULL);
6361 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6363 memset(&surface_desc, 0, sizeof(surface_desc));
6364 surface_desc.dwSize = sizeof(surface_desc);
6365 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6366 surface_desc.dwWidth = 8;
6367 surface_desc.dwHeight = 1;
6368 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6369 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6370 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
6371 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
6372 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6373 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6374 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
6375 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
6376 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst, NULL);
6377 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6379 memset(&surface_desc, 0, sizeof(surface_desc));
6380 surface_desc.dwSize = sizeof(surface_desc);
6381 hr = IDirectDrawSurface_Lock(src, NULL, &surface_desc, 0, NULL);
6382 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
6383 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
6384 hr = IDirectDrawSurface_Unlock(src, NULL);
6385 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
6387 hr = IDirectDrawSurface_SetPalette(src, palette);
6388 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6389 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
6390 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
6391 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
6392 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
6393 "Failed to blit, hr %#x.\n", hr);
6395 if (SUCCEEDED(hr))
6397 for (x = 0; x < sizeof(expected) / sizeof(*expected); x++)
6399 color = get_surface_color(dst, x, 0);
6400 todo_wine ok(compare_color(color, expected[x], 0),
6401 "Pixel %u: Got color %#x, expected %#x.\n",
6402 x, color, expected[x]);
6406 IDirectDrawSurface_Release(src);
6407 IDirectDrawSurface_Release(dst);
6408 IDirectDrawPalette_Release(palette);
6410 refcount = IDirectDraw2_Release(ddraw);
6411 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6412 DestroyWindow(window);
6415 static void test_material(void)
6417 IDirect3DMaterial2 *background, *material;
6418 D3DMATERIALHANDLE mat_handle, tmp;
6419 IDirect3DViewport2 *viewport;
6420 IDirect3DDevice2 *device;
6421 IDirectDrawSurface *rt;
6422 IDirectDraw2 *ddraw;
6423 D3DCOLOR color;
6424 ULONG refcount;
6425 unsigned int i;
6426 HWND window;
6427 HRESULT hr;
6428 BOOL valid;
6430 static D3DVERTEX quad[] =
6432 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
6433 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
6434 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
6435 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
6437 static const struct
6439 BOOL material;
6440 D3DCOLOR expected_color;
6442 test_data[] =
6444 {TRUE, 0x0000ff00},
6445 {FALSE, 0x00ffffff},
6447 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
6449 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6450 0, 0, 640, 480, 0, 0, 0, 0);
6451 ddraw = create_ddraw();
6452 ok(!!ddraw, "Failed to create a ddraw object.\n");
6453 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
6455 skip("Failed to create a 3D device, skipping test.\n");
6456 DestroyWindow(window);
6457 return;
6460 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
6461 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
6463 background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
6464 viewport = create_viewport(device, 0, 0, 640, 480);
6465 viewport_set_background(device, viewport, background);
6466 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
6467 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
6469 material = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
6470 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
6471 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
6473 hr = IDirect3DDevice2_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
6474 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
6475 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
6476 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
6477 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
6478 hr = IDirect3DDevice2_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
6479 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
6480 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
6481 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, 0);
6482 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
6483 hr = IDirect3DDevice2_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
6484 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
6485 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
6487 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
6489 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
6490 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
6492 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, test_data[i].material ? mat_handle : 0);
6493 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
6495 hr = IDirect3DDevice2_BeginScene(device);
6496 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6497 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_VERTEX, quad, 4, 0);
6498 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6499 hr = IDirect3DDevice2_EndScene(device);
6500 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6501 color = get_surface_color(rt, 320, 240);
6502 ok(compare_color(color, test_data[i].expected_color, 1),
6503 "Got unexpected color 0x%08x, test %u.\n", color, i);
6506 destroy_material(material);
6507 material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
6508 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
6509 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
6511 hr = IDirect3DViewport2_SetBackground(viewport, mat_handle);
6512 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
6513 hr = IDirect3DViewport2_GetBackground(viewport, &tmp, &valid);
6514 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
6515 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
6516 ok(valid, "Got unexpected valid %#x.\n", valid);
6517 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6518 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
6519 color = get_surface_color(rt, 320, 240);
6520 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
6522 hr = IDirect3DViewport2_SetBackground(viewport, 0);
6523 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6524 hr = IDirect3DViewport2_GetBackground(viewport, &tmp, &valid);
6525 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
6526 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
6527 ok(valid, "Got unexpected valid %#x.\n", valid);
6528 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6529 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
6530 color = get_surface_color(rt, 320, 240);
6531 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
6533 destroy_viewport(device, viewport);
6534 viewport = create_viewport(device, 0, 0, 640, 480);
6536 hr = IDirect3DViewport2_GetBackground(viewport, &tmp, &valid);
6537 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
6538 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
6539 ok(!valid, "Got unexpected valid %#x.\n", valid);
6540 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6541 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
6542 color = get_surface_color(rt, 320, 240);
6543 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x.\n", color);
6545 destroy_viewport(device, viewport);
6546 destroy_material(background);
6547 destroy_material(material);
6548 IDirectDrawSurface_Release(rt);
6549 refcount = IDirect3DDevice2_Release(device);
6550 ok(!refcount, "Device has %u references left.\n", refcount);
6551 refcount = IDirectDraw2_Release(ddraw);
6552 ok(!refcount, "Ddraw object has %u references left.\n", refcount);
6553 DestroyWindow(window);
6556 static void test_lighting(void)
6558 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
6559 static D3DMATRIX mat =
6561 1.0f, 0.0f, 0.0f, 0.0f,
6562 0.0f, 1.0f, 0.0f, 0.0f,
6563 0.0f, 0.0f, 1.0f, 0.0f,
6564 0.0f, 0.0f, 0.0f, 1.0f,
6566 mat_singular =
6568 1.0f, 0.0f, 1.0f, 0.0f,
6569 0.0f, 1.0f, 0.0f, 0.0f,
6570 1.0f, 0.0f, 1.0f, 0.0f,
6571 0.0f, 0.0f, 0.5f, 1.0f,
6573 mat_transf =
6575 0.0f, 0.0f, 1.0f, 0.0f,
6576 0.0f, 1.0f, 0.0f, 0.0f,
6577 -1.0f, 0.0f, 0.0f, 0.0f,
6578 10.f, 10.0f, 10.0f, 1.0f,
6580 mat_nonaffine =
6582 1.0f, 0.0f, 0.0f, 0.0f,
6583 0.0f, 1.0f, 0.0f, 0.0f,
6584 0.0f, 0.0f, 1.0f, -1.0f,
6585 10.f, 10.0f, 10.0f, 0.0f,
6587 static D3DLVERTEX unlitquad[] =
6589 {{-1.0f}, {-1.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
6590 {{-1.0f}, { 0.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
6591 {{ 0.0f}, { 0.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
6592 {{ 0.0f}, {-1.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
6594 litquad[] =
6596 {{-1.0f}, { 0.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
6597 {{-1.0f}, { 1.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
6598 {{ 0.0f}, { 1.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
6599 {{ 0.0f}, { 0.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
6601 static D3DVERTEX unlitnquad[] =
6603 {{0.0f}, {-1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6604 {{0.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6605 {{1.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6606 {{1.0f}, {-1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6608 litnquad[] =
6610 {{0.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6611 {{0.0f}, { 1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6612 {{1.0f}, { 1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6613 {{1.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6615 nquad[] =
6617 {{-1.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6618 {{-1.0f}, { 1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6619 {{ 1.0f}, { 1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6620 {{ 1.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6622 rotatedquad[] =
6624 {{-10.0f}, {-11.0f}, {11.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
6625 {{-10.0f}, { -9.0f}, {11.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
6626 {{-10.0f}, { -9.0f}, { 9.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
6627 {{-10.0f}, {-11.0f}, { 9.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
6629 translatedquad[] =
6631 {{-11.0f}, {-11.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6632 {{-11.0f}, { -9.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6633 {{ -9.0f}, { -9.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6634 {{ -9.0f}, {-11.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6636 static WORD indices[] = {0, 1, 2, 2, 3, 0};
6637 static const struct
6639 D3DMATRIX *world_matrix;
6640 void *quad;
6641 DWORD expected;
6642 const char *message;
6644 tests[] =
6646 {&mat, nquad, 0x000000ff, "Lit quad with light"},
6647 {&mat_singular, nquad, 0x000000b4, "Lit quad with singular world matrix"},
6648 {&mat_transf, rotatedquad, 0x000000ff, "Lit quad with transformation matrix"},
6649 {&mat_nonaffine, translatedquad, 0x000000ff, "Lit quad with non-affine matrix"},
6652 HWND window;
6653 IDirect3D2 *d3d;
6654 IDirect3DDevice2 *device;
6655 IDirectDraw2 *ddraw;
6656 IDirectDrawSurface *rt;
6657 IDirect3DViewport2 *viewport;
6658 IDirect3DMaterial2 *material;
6659 IDirect3DLight *light;
6660 D3DMATERIALHANDLE mat_handle;
6661 D3DLIGHT2 light_desc;
6662 HRESULT hr;
6663 D3DCOLOR color;
6664 ULONG refcount;
6665 unsigned int i;
6667 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6668 0, 0, 640, 480, 0, 0, 0, 0);
6669 ddraw = create_ddraw();
6670 ok(!!ddraw, "Failed to create a ddraw object.\n");
6671 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
6673 skip("Failed to create a 3D device, skipping test.\n");
6674 DestroyWindow(window);
6675 return;
6678 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
6679 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
6681 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
6682 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
6684 viewport = create_viewport(device, 0, 0, 640, 480);
6685 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
6686 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
6688 material = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
6689 viewport_set_background(device, viewport, material);
6691 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6692 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
6694 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
6695 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
6696 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
6697 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
6698 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
6699 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
6700 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
6701 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
6702 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
6703 ok(SUCCEEDED(hr), "Failed to disable zbuffer, hr %#x.\n", hr);
6704 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
6705 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
6706 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
6707 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
6709 hr = IDirect3DDevice2_BeginScene(device);
6710 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6712 /* There is no D3DRENDERSTATE_LIGHTING on ddraw < 7. */
6713 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
6714 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
6715 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_LVERTEX, unlitquad,
6716 4, indices, 6, 0);
6717 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6719 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
6720 ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
6721 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_LVERTEX, litquad,
6722 4, indices, 6, 0);
6723 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6725 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
6726 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
6727 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX, unlitnquad,
6728 4, indices, 6, 0);
6729 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6731 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
6732 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
6733 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX, litnquad,
6734 4, indices, 6, 0);
6735 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6737 hr = IDirect3DDevice2_EndScene(device);
6738 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6740 color = get_surface_color(rt, 160, 360);
6741 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x.\n", color);
6742 color = get_surface_color(rt, 160, 120);
6743 ok(color == 0x0000ff00, "Lit quad without normals has color 0x%08x.\n", color);
6744 color = get_surface_color(rt, 480, 360);
6745 ok(color == 0x00ffffff, "Unlit quad with normals has color 0x%08x.\n", color);
6746 color = get_surface_color(rt, 480, 120);
6747 ok(color == 0x00ffffff, "Lit quad with normals has color 0x%08x.\n", color);
6749 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
6750 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
6751 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
6752 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
6754 hr = IDirect3D2_CreateLight(d3d, &light, NULL);
6755 ok(SUCCEEDED(hr), "Failed to create a light object, hr %#x.\n", hr);
6756 memset(&light_desc, 0, sizeof(light_desc));
6757 light_desc.dwSize = sizeof(light_desc);
6758 light_desc.dltType = D3DLIGHT_DIRECTIONAL;
6759 U1(light_desc.dcvColor).r = 0.0f;
6760 U2(light_desc.dcvColor).g = 0.0f;
6761 U3(light_desc.dcvColor).b = 1.0f;
6762 U4(light_desc.dcvColor).a = 1.0f;
6763 U3(light_desc.dvDirection).z = 1.0f;
6764 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
6765 ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
6766 hr = IDirect3DViewport2_AddLight(viewport, light);
6767 ok(SUCCEEDED(hr), "Failed to add a light to the viewport, hr %#x.\n", hr);
6769 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6770 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
6772 hr = IDirect3DDevice2_BeginScene(device);
6773 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6775 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX, nquad,
6776 4, indices, 6, 0);
6777 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6779 hr = IDirect3DDevice2_EndScene(device);
6780 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6782 color = get_surface_color(rt, 320, 240);
6783 ok(color == 0x00000000, "Lit quad with no light has color 0x%08x.\n", color);
6785 light_desc.dwFlags = D3DLIGHT_ACTIVE;
6786 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
6787 ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
6789 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
6791 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
6792 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
6794 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6795 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
6797 hr = IDirect3DDevice2_BeginScene(device);
6798 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6800 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX,
6801 tests[i].quad, 4, indices, 6, 0);
6802 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6804 hr = IDirect3DDevice2_EndScene(device);
6805 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6807 color = get_surface_color(rt, 320, 240);
6808 ok(color == tests[i].expected, "%s has color 0x%08x.\n", tests[i].message, color);
6811 hr = IDirect3DViewport2_DeleteLight(viewport, light);
6812 ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#x.\n", hr);
6813 IDirect3DLight_Release(light);
6814 destroy_material(material);
6815 destroy_viewport(device, viewport);
6816 IDirectDrawSurface2_Release(rt);
6817 refcount = IDirect3DDevice2_Release(device);
6818 ok(!refcount, "Device has %u references left.\n", refcount);
6819 IDirect3D2_Release(d3d);
6820 refcount = IDirectDraw2_Release(ddraw);
6821 ok(!refcount, "Ddraw object has %u references left.\n", refcount);
6822 DestroyWindow(window);
6825 static void test_specular_lighting(void)
6827 static const unsigned int vertices_side = 5;
6828 const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
6829 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
6830 static D3DMATRIX mat =
6832 1.0f, 0.0f, 0.0f, 0.0f,
6833 0.0f, 1.0f, 0.0f, 0.0f,
6834 0.0f, 0.0f, 1.0f, 0.0f,
6835 0.0f, 0.0f, 0.0f, 1.0f,
6837 static D3DLIGHT2 directional =
6839 sizeof(D3DLIGHT2),
6840 D3DLIGHT_DIRECTIONAL,
6841 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
6842 {{0.0f}, {0.0f}, {0.0f}},
6843 {{0.0f}, {0.0f}, {1.0f}},
6845 point =
6847 sizeof(D3DLIGHT2),
6848 D3DLIGHT_POINT,
6849 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
6850 {{0.0f}, {0.0f}, {0.0f}},
6851 {{0.0f}, {0.0f}, {0.0f}},
6852 100.0f,
6853 0.0f,
6854 0.0f, 0.0f, 1.0f,
6856 spot =
6858 sizeof(D3DLIGHT2),
6859 D3DLIGHT_SPOT,
6860 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
6861 {{0.0f}, {0.0f}, {0.0f}},
6862 {{0.0f}, {0.0f}, {1.0f}},
6863 100.0f,
6864 1.0f,
6865 0.0f, 0.0f, 1.0f,
6866 M_PI / 12.0f, M_PI / 3.0f
6868 parallelpoint =
6870 sizeof(D3DLIGHT2),
6871 D3DLIGHT_PARALLELPOINT,
6872 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
6873 {{0.5f}, {0.0f}, {-1.0f}},
6874 {{0.0f}, {0.0f}, {0.0f}},
6876 static const struct expected_color
6878 unsigned int x, y;
6879 D3DCOLOR color;
6881 expected_directional_local[] =
6883 {160, 120, 0x003c3c3c},
6884 {320, 120, 0x00717171},
6885 {480, 120, 0x003c3c3c},
6886 {160, 240, 0x00717171},
6887 {320, 240, 0x00ffffff},
6888 {480, 240, 0x00717171},
6889 {160, 360, 0x003c3c3c},
6890 {320, 360, 0x00717171},
6891 {480, 360, 0x003c3c3c},
6893 expected_point_local[] =
6895 {160, 120, 0x00000000},
6896 {320, 120, 0x00090909},
6897 {480, 120, 0x00000000},
6898 {160, 240, 0x00090909},
6899 {320, 240, 0x00fafafa},
6900 {480, 240, 0x00090909},
6901 {160, 360, 0x00000000},
6902 {320, 360, 0x00090909},
6903 {480, 360, 0x00000000},
6905 expected_spot_local[] =
6907 {160, 120, 0x00000000},
6908 {320, 120, 0x00020202},
6909 {480, 120, 0x00000000},
6910 {160, 240, 0x00020202},
6911 {320, 240, 0x00fafafa},
6912 {480, 240, 0x00020202},
6913 {160, 360, 0x00000000},
6914 {320, 360, 0x00020202},
6915 {480, 360, 0x00000000},
6917 expected_parallelpoint[] =
6919 {160, 120, 0x00050505},
6920 {320, 120, 0x002c2c2c},
6921 {480, 120, 0x006e6e6e},
6922 {160, 240, 0x00090909},
6923 {320, 240, 0x00717171},
6924 {480, 240, 0x00ffffff},
6925 {160, 360, 0x00050505},
6926 {320, 360, 0x002c2c2c},
6927 {480, 360, 0x006e6e6e},
6929 static const struct
6931 D3DLIGHT2 *light;
6932 const struct expected_color *expected;
6933 unsigned int expected_count;
6935 tests[] =
6937 {&directional, expected_directional_local,
6938 sizeof(expected_directional_local) / sizeof(expected_directional_local[0])},
6939 {&point, expected_point_local,
6940 sizeof(expected_point_local) / sizeof(expected_point_local[0])},
6941 {&spot, expected_spot_local,
6942 sizeof(expected_spot_local) / sizeof(expected_spot_local[0])},
6943 {&parallelpoint, expected_parallelpoint,
6944 sizeof(expected_parallelpoint) / sizeof(expected_parallelpoint[0])},
6946 IDirect3D2 *d3d;
6947 IDirect3DDevice2 *device;
6948 IDirectDraw2 *ddraw;
6949 IDirectDrawSurface *rt;
6950 IDirect3DViewport2 *viewport;
6951 IDirect3DMaterial2 *material, *background_material;
6952 IDirect3DLight *light;
6953 D3DMATERIALHANDLE mat_handle;
6954 D3DCOLOR color;
6955 ULONG refcount;
6956 HWND window;
6957 HRESULT hr;
6958 unsigned int i, j, x, y;
6959 D3DVERTEX *quad;
6960 WORD *indices;
6962 quad = HeapAlloc(GetProcessHeap(), 0, vertices_side * vertices_side * sizeof(*quad));
6963 indices = HeapAlloc(GetProcessHeap(), 0, indices_count * sizeof(*indices));
6964 for (i = 0, y = 0; y < vertices_side; ++y)
6966 for (x = 0; x < vertices_side; ++x)
6968 U1(quad[i]).x = x * 2.0f / (vertices_side - 1) - 1.0f;
6969 U2(quad[i]).y = y * 2.0f / (vertices_side - 1) - 1.0f;
6970 U3(quad[i]).z = 1.0f;
6971 U4(quad[i]).nx = 0.0f;
6972 U5(quad[i]).ny = 0.0f;
6973 U6(quad[i]).nz = -1.0f;
6974 U7(quad[i]).tu = 0.0f;
6975 U8(quad[i++]).tv = 0.0f;
6978 for (i = 0, y = 0; y < (vertices_side - 1); ++y)
6980 for (x = 0; x < (vertices_side - 1); ++x)
6982 indices[i++] = y * vertices_side + x + 1;
6983 indices[i++] = y * vertices_side + x;
6984 indices[i++] = (y + 1) * vertices_side + x;
6985 indices[i++] = y * vertices_side + x + 1;
6986 indices[i++] = (y + 1) * vertices_side + x;
6987 indices[i++] = (y + 1) * vertices_side + x + 1;
6991 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6992 0, 0, 640, 480, 0, 0, 0, 0);
6993 ddraw = create_ddraw();
6994 ok(!!ddraw, "Failed to create a ddraw object.\n");
6995 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
6997 skip("Failed to create a 3D device, skipping test.\n");
6998 DestroyWindow(window);
6999 return;
7002 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
7003 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
7005 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
7006 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
7008 viewport = create_viewport(device, 0, 0, 640, 480);
7009 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
7010 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
7012 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
7013 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
7014 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
7015 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
7016 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
7017 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
7018 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
7019 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
7020 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
7021 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
7022 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
7023 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
7025 background_material = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
7026 viewport_set_background(device, viewport, background_material);
7028 material = create_specular_material(device, 1.0f, 1.0f, 1.0f, 1.0f, 30.0f);
7029 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
7030 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
7031 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
7032 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
7034 hr = IDirect3D2_CreateLight(d3d, &light, NULL);
7035 ok(SUCCEEDED(hr), "Failed to create a light object, hr %#x.\n", hr);
7036 hr = IDirect3DViewport2_AddLight(viewport, light);
7037 ok(SUCCEEDED(hr), "Failed to add a light to the viewport, hr %#x.\n", hr);
7039 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
7040 ok(SUCCEEDED(hr), "Failed to enable specular lighting, hr %#x.\n", hr);
7042 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
7044 tests[i].light->dwFlags = D3DLIGHT_ACTIVE;
7045 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)tests[i].light);
7046 ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
7048 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7049 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
7051 hr = IDirect3DDevice2_BeginScene(device);
7052 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
7054 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX,
7055 quad, vertices_side * vertices_side, indices, indices_count, 0);
7056 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7058 hr = IDirect3DDevice2_EndScene(device);
7059 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7061 for (j = 0; j < tests[i].expected_count; ++j)
7063 color = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
7064 ok(compare_color(color, tests[i].expected[j].color, 1),
7065 "Expected color 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
7066 tests[i].expected[j].color, tests[i].expected[j].x,
7067 tests[i].expected[j].y, color, i);
7071 hr = IDirect3DViewport2_DeleteLight(viewport, light);
7072 ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#x.\n", hr);
7073 IDirect3DLight_Release(light);
7074 destroy_material(material);
7075 destroy_material(background_material);
7076 destroy_viewport(device, viewport);
7077 IDirectDrawSurface2_Release(rt);
7078 refcount = IDirect3DDevice2_Release(device);
7079 ok(!refcount, "Device has %u references left.\n", refcount);
7080 IDirect3D2_Release(d3d);
7081 refcount = IDirectDraw2_Release(ddraw);
7082 ok(!refcount, "Ddraw object has %u references left.\n", refcount);
7083 DestroyWindow(window);
7084 HeapFree(GetProcessHeap(), 0, indices);
7085 HeapFree(GetProcessHeap(), 0, quad);
7088 static void test_palette_gdi(void)
7090 IDirectDrawSurface *surface, *primary;
7091 DDSURFACEDESC surface_desc;
7092 IDirectDraw2 *ddraw;
7093 IDirectDrawPalette *palette, *palette2;
7094 ULONG refcount;
7095 HWND window;
7096 HRESULT hr;
7097 PALETTEENTRY palette_entries[256];
7098 UINT i;
7099 HDC dc;
7100 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
7101 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
7102 * not the point of this test. */
7103 static const RGBQUAD expected1[] =
7105 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
7106 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
7108 static const RGBQUAD expected2[] =
7110 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
7111 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
7113 static const RGBQUAD expected3[] =
7115 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
7116 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
7118 HPALETTE ddraw_palette_handle;
7119 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
7120 RGBQUAD rgbquad[255];
7121 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
7123 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7124 0, 0, 640, 480, 0, 0, 0, 0);
7125 ddraw = create_ddraw();
7126 ok(!!ddraw, "Failed to create a ddraw object.\n");
7127 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7128 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7130 memset(&surface_desc, 0, sizeof(surface_desc));
7131 surface_desc.dwSize = sizeof(surface_desc);
7132 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7133 surface_desc.dwWidth = 16;
7134 surface_desc.dwHeight = 16;
7135 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7136 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
7137 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7138 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
7139 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7140 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7142 /* Avoid colors from the Windows default palette. */
7143 memset(palette_entries, 0, sizeof(palette_entries));
7144 palette_entries[1].peRed = 0x01;
7145 palette_entries[2].peGreen = 0x02;
7146 palette_entries[3].peBlue = 0x03;
7147 palette_entries[4].peRed = 0x13;
7148 palette_entries[4].peGreen = 0x14;
7149 palette_entries[4].peBlue = 0x15;
7150 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7151 palette_entries, &palette, NULL);
7152 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7154 /* If there is no palette assigned and the display mode is not 8 bpp, some
7155 * drivers refuse to create a DC while others allow it. If a DC is created,
7156 * the DIB color table is uninitialized and contains random colors. No error
7157 * is generated when trying to read pixels and random garbage is returned.
7159 * The most likely explanation is that if the driver creates a DC, it (or
7160 * the higher-level runtime) uses GetSystemPaletteEntries to find the
7161 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
7162 * contains uninitialized garbage. See comments below for the P8 case. */
7164 hr = IDirectDrawSurface_SetPalette(surface, palette);
7165 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7166 hr = IDirectDrawSurface_GetDC(surface, &dc);
7167 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7168 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
7169 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
7170 "Got unexpected palette %p, expected %p.\n",
7171 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
7173 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7174 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7175 for (i = 0; i < sizeof(expected1) / sizeof(*expected1); i++)
7177 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
7178 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7179 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7180 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
7182 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7184 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7185 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7186 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7189 /* Update the palette while the DC is in use. This does not modify the DC. */
7190 palette_entries[4].peRed = 0x23;
7191 palette_entries[4].peGreen = 0x24;
7192 palette_entries[4].peBlue = 0x25;
7193 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
7194 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
7196 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
7197 ok(i == 1, "Expected count 1, got %u.\n", i);
7198 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
7199 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7200 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
7201 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
7203 /* Neither does re-setting the palette. */
7204 hr = IDirectDrawSurface_SetPalette(surface, NULL);
7205 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7206 hr = IDirectDrawSurface_SetPalette(surface, palette);
7207 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7209 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
7210 ok(i == 1, "Expected count 1, got %u.\n", i);
7211 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
7212 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7213 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
7214 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
7216 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
7217 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7219 /* Refresh the DC. This updates the palette. */
7220 hr = IDirectDrawSurface_GetDC(surface, &dc);
7221 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7222 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7223 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7224 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
7226 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
7227 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7228 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7229 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
7231 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7233 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7234 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7235 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7237 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
7238 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7240 refcount = IDirectDrawSurface_Release(surface);
7241 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7243 if (FAILED(IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
7245 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
7246 IDirectDrawPalette_Release(palette);
7247 IDirectDraw2_Release(ddraw);
7248 DestroyWindow(window);
7249 return;
7251 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
7252 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
7253 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7255 memset(&surface_desc, 0, sizeof(surface_desc));
7256 surface_desc.dwSize = sizeof(surface_desc);
7257 surface_desc.dwFlags = DDSD_CAPS;
7258 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7259 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
7260 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7262 hr = IDirectDrawSurface_SetPalette(primary, palette);
7263 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7264 hr = IDirectDrawSurface_GetDC(primary, &dc);
7265 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7266 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
7267 /* Windows 2000 on the testbot assigns a different palette to the primary. Refrast? */
7268 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE) || broken(TRUE),
7269 "Got unexpected palette %p, expected %p.\n",
7270 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
7271 SelectPalette(dc, ddraw_palette_handle, FALSE);
7273 /* The primary uses the system palette. In exclusive mode, the system palette matches
7274 * the ddraw palette attached to the primary, so the result is what you would expect
7275 * from a regular surface. Tests for the interaction between the ddraw palette and
7276 * the system palette are not included pending an application that depends on this.
7277 * The relation between those causes problems on Windows Vista and newer for games
7278 * like Age of Empires or StarCraft. Don't emulate it without a real need. */
7279 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7280 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7281 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
7283 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
7284 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7285 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7286 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
7288 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7290 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7291 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7292 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7294 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
7295 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7297 memset(&surface_desc, 0, sizeof(surface_desc));
7298 surface_desc.dwSize = sizeof(surface_desc);
7299 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7300 surface_desc.dwWidth = 16;
7301 surface_desc.dwHeight = 16;
7302 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7303 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7304 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7306 /* Here the offscreen surface appears to use the primary's palette,
7307 * but in all likelihood it is actually the system palette. */
7308 hr = IDirectDrawSurface_GetDC(surface, &dc);
7309 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7310 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7311 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7312 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
7314 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
7315 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7316 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7317 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
7319 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7321 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7322 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7323 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7325 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
7326 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7328 /* On real hardware a change to the primary surface's palette applies immediately,
7329 * even on device contexts from offscreen surfaces that do not have their own
7330 * palette. On the testbot VMs this is not the case. Don't test this until we
7331 * know of an application that depends on this. */
7333 memset(palette_entries, 0, sizeof(palette_entries));
7334 palette_entries[1].peBlue = 0x40;
7335 palette_entries[2].peRed = 0x40;
7336 palette_entries[3].peGreen = 0x40;
7337 palette_entries[4].peRed = 0x12;
7338 palette_entries[4].peGreen = 0x34;
7339 palette_entries[4].peBlue = 0x56;
7340 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7341 palette_entries, &palette2, NULL);
7342 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7343 hr = IDirectDrawSurface_SetPalette(surface, palette2);
7344 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7346 /* A palette assigned to the offscreen surface overrides the primary / system
7347 * palette. */
7348 hr = IDirectDrawSurface_GetDC(surface, &dc);
7349 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7350 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7351 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7352 for (i = 0; i < sizeof(expected3) / sizeof(*expected3); i++)
7354 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
7355 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7356 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7357 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
7359 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7361 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7362 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7363 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7365 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
7366 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7368 refcount = IDirectDrawSurface_Release(surface);
7369 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7371 /* The Windows 8 testbot keeps extra references to the primary and
7372 * backbuffer while in 8 bpp mode. */
7373 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
7374 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
7376 refcount = IDirectDrawSurface_Release(primary);
7377 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7378 refcount = IDirectDrawPalette_Release(palette2);
7379 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7380 refcount = IDirectDrawPalette_Release(palette);
7381 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7382 refcount = IDirectDraw2_Release(ddraw);
7383 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7384 DestroyWindow(window);
7387 static void test_palette_alpha(void)
7389 IDirectDrawSurface *surface1;
7390 IDirectDrawSurface2 *surface;
7391 DDSURFACEDESC surface_desc;
7392 IDirectDraw2 *ddraw;
7393 IDirectDrawPalette *palette;
7394 ULONG refcount;
7395 HWND window;
7396 HRESULT hr;
7397 PALETTEENTRY palette_entries[256];
7398 unsigned int i;
7399 static const struct
7401 DWORD caps, flags;
7402 BOOL attach_allowed;
7403 const char *name;
7405 test_data[] =
7407 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
7408 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
7409 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
7412 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7413 0, 0, 640, 480, 0, 0, 0, 0);
7414 ddraw = create_ddraw();
7415 ok(!!ddraw, "Failed to create a ddraw object.\n");
7416 if (FAILED(IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
7418 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
7419 IDirectDraw2_Release(ddraw);
7420 DestroyWindow(window);
7421 return;
7423 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7424 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7426 memset(palette_entries, 0, sizeof(palette_entries));
7427 palette_entries[1].peFlags = 0x42;
7428 palette_entries[2].peFlags = 0xff;
7429 palette_entries[3].peFlags = 0x80;
7430 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
7431 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7433 memset(palette_entries, 0x66, sizeof(palette_entries));
7434 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
7435 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
7436 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7437 palette_entries[0].peFlags);
7438 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7439 palette_entries[1].peFlags);
7440 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
7441 palette_entries[2].peFlags);
7442 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
7443 palette_entries[3].peFlags);
7445 IDirectDrawPalette_Release(palette);
7447 memset(palette_entries, 0, sizeof(palette_entries));
7448 palette_entries[1].peFlags = 0x42;
7449 palette_entries[1].peRed = 0xff;
7450 palette_entries[2].peFlags = 0xff;
7451 palette_entries[3].peFlags = 0x80;
7452 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
7453 palette_entries, &palette, NULL);
7454 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7456 memset(palette_entries, 0x66, sizeof(palette_entries));
7457 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
7458 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
7459 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7460 palette_entries[0].peFlags);
7461 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7462 palette_entries[1].peFlags);
7463 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
7464 palette_entries[2].peFlags);
7465 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
7466 palette_entries[3].peFlags);
7468 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); i++)
7470 memset(&surface_desc, 0, sizeof(surface_desc));
7471 surface_desc.dwSize = sizeof(surface_desc);
7472 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
7473 surface_desc.dwWidth = 128;
7474 surface_desc.dwHeight = 128;
7475 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
7476 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7477 ok(SUCCEEDED(hr), "Failed to create %s surface, hr %#x.\n", test_data[i].name, hr);
7478 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
7479 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface2 interface, hr %#x.\n", hr);
7480 IDirectDrawSurface_Release(surface1);
7482 hr = IDirectDrawSurface2_SetPalette(surface, palette);
7483 if (test_data[i].attach_allowed)
7484 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#x.\n", test_data[i].name, hr);
7485 else
7486 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x, %s surface.\n", hr, test_data[i].name);
7488 if (SUCCEEDED(hr))
7490 HDC dc;
7491 RGBQUAD rgbquad;
7492 UINT retval;
7494 hr = IDirectDrawSurface2_GetDC(surface, &dc);
7495 ok(SUCCEEDED(hr) || broken(hr == DDERR_CANTCREATEDC) /* Win2k testbot */,
7496 "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
7497 if (SUCCEEDED(hr))
7499 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
7500 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
7501 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
7502 rgbquad.rgbRed, test_data[i].name);
7503 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
7504 rgbquad.rgbGreen, test_data[i].name);
7505 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
7506 rgbquad.rgbBlue, test_data[i].name);
7507 todo_wine ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
7508 rgbquad.rgbReserved, test_data[i].name);
7509 hr = IDirectDrawSurface2_ReleaseDC(surface, dc);
7510 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7513 IDirectDrawSurface2_Release(surface);
7516 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
7517 memset(&surface_desc, 0, sizeof(surface_desc));
7518 surface_desc.dwSize = sizeof(surface_desc);
7519 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7520 surface_desc.dwWidth = 128;
7521 surface_desc.dwHeight = 128;
7522 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7523 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
7524 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
7525 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
7526 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7527 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7528 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
7529 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7530 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7531 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
7532 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface2 interface, hr %#x.\n", hr);
7533 IDirectDrawSurface_Release(surface1);
7535 hr = IDirectDrawSurface2_SetPalette(surface, palette);
7536 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
7537 IDirectDrawSurface2_Release(surface);
7539 /* The Windows 8 testbot keeps extra references to the primary
7540 * while in 8 bpp mode. */
7541 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
7542 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
7544 refcount = IDirectDrawPalette_Release(palette);
7545 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7546 refcount = IDirectDraw2_Release(ddraw);
7547 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7548 DestroyWindow(window);
7551 static void test_lost_device(void)
7553 IDirectDrawSurface *surface;
7554 DDSURFACEDESC surface_desc;
7555 HWND window1, window2;
7556 IDirectDraw2 *ddraw;
7557 ULONG refcount;
7558 HRESULT hr;
7559 BOOL ret;
7561 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7562 0, 0, 640, 480, 0, 0, 0, 0);
7563 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7564 0, 0, 640, 480, 0, 0, 0, 0);
7565 ddraw = create_ddraw();
7566 ok(!!ddraw, "Failed to create a ddraw object.\n");
7567 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7568 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7570 memset(&surface_desc, 0, sizeof(surface_desc));
7571 surface_desc.dwSize = sizeof(surface_desc);
7572 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
7573 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
7574 surface_desc.dwBackBufferCount = 1;
7575 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7576 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7578 hr = IDirectDrawSurface_IsLost(surface);
7579 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7580 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7581 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7583 ret = SetForegroundWindow(GetDesktopWindow());
7584 ok(ret, "Failed to set foreground window.\n");
7585 hr = IDirectDrawSurface_IsLost(surface);
7586 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7587 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7588 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7590 ret = SetForegroundWindow(window1);
7591 ok(ret, "Failed to set foreground window.\n");
7592 hr = IDirectDrawSurface_IsLost(surface);
7593 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7594 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7595 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7597 hr = restore_surfaces(ddraw);
7598 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7599 hr = IDirectDrawSurface_IsLost(surface);
7600 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7601 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7602 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7604 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
7605 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7606 hr = IDirectDrawSurface_IsLost(surface);
7607 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7608 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7609 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7611 /* Trying to restore the primary will crash, probably because flippable
7612 * surfaces can't exist in DDSCL_NORMAL. */
7613 IDirectDrawSurface_Release(surface);
7614 memset(&surface_desc, 0, sizeof(surface_desc));
7615 surface_desc.dwSize = sizeof(surface_desc);
7616 surface_desc.dwFlags = DDSD_CAPS;
7617 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7618 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7619 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7621 hr = IDirectDrawSurface_IsLost(surface);
7622 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7624 ret = SetForegroundWindow(GetDesktopWindow());
7625 ok(ret, "Failed to set foreground window.\n");
7626 hr = IDirectDrawSurface_IsLost(surface);
7627 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7629 ret = SetForegroundWindow(window1);
7630 ok(ret, "Failed to set foreground window.\n");
7631 hr = IDirectDrawSurface_IsLost(surface);
7632 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7634 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7635 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7636 hr = IDirectDrawSurface_IsLost(surface);
7637 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7639 hr = restore_surfaces(ddraw);
7640 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7641 hr = IDirectDrawSurface_IsLost(surface);
7642 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7644 IDirectDrawSurface_Release(surface);
7645 memset(&surface_desc, 0, sizeof(surface_desc));
7646 surface_desc.dwSize = sizeof(surface_desc);
7647 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
7648 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
7649 U5(surface_desc).dwBackBufferCount = 1;
7650 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7651 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7653 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7654 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7655 hr = IDirectDrawSurface_IsLost(surface);
7656 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7657 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7658 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7660 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
7661 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7662 hr = IDirectDrawSurface_IsLost(surface);
7663 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7664 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7665 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
7667 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
7668 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7669 hr = IDirectDrawSurface_IsLost(surface);
7670 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7671 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7672 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
7674 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
7675 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7676 hr = IDirectDrawSurface_IsLost(surface);
7677 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7678 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7679 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
7681 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
7682 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7683 hr = IDirectDrawSurface_IsLost(surface);
7684 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7685 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7686 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
7688 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7689 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7690 hr = IDirectDrawSurface_IsLost(surface);
7691 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7692 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7693 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7695 IDirectDrawSurface_Release(surface);
7696 refcount = IDirectDraw2_Release(ddraw);
7697 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7698 DestroyWindow(window2);
7699 DestroyWindow(window1);
7702 static void test_surface_desc_lock(void)
7704 IDirectDrawSurface *surface;
7705 DDSURFACEDESC surface_desc;
7706 IDirectDraw2 *ddraw;
7707 ULONG refcount;
7708 HWND window;
7709 HRESULT hr;
7711 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7712 0, 0, 640, 480, 0, 0, 0, 0);
7713 ddraw = create_ddraw();
7714 ok(!!ddraw, "Failed to create a ddraw object.\n");
7715 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7716 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7718 memset(&surface_desc, 0, sizeof(surface_desc));
7719 surface_desc.dwSize = sizeof(surface_desc);
7720 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7721 surface_desc.dwWidth = 16;
7722 surface_desc.dwHeight = 16;
7723 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7724 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7725 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7727 memset(&surface_desc, 0xaa, sizeof(surface_desc));
7728 surface_desc.dwSize = sizeof(surface_desc);
7729 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
7730 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7731 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
7733 memset(&surface_desc, 0xaa, sizeof(surface_desc));
7734 surface_desc.dwSize = sizeof(surface_desc);
7735 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, 0, NULL);
7736 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7737 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
7738 memset(&surface_desc, 0xaa, sizeof(surface_desc));
7739 surface_desc.dwSize = sizeof(surface_desc);
7740 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
7741 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7742 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
7743 hr = IDirectDrawSurface_Unlock(surface, NULL);
7744 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7746 memset(&surface_desc, 0xaa, sizeof(surface_desc));
7747 surface_desc.dwSize = sizeof(surface_desc);
7748 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
7749 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7750 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
7752 IDirectDrawSurface_Release(surface);
7753 refcount = IDirectDraw2_Release(ddraw);
7754 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7755 DestroyWindow(window);
7758 static void test_texturemapblend(void)
7760 HRESULT hr;
7761 DDSURFACEDESC ddsd;
7762 DDBLTFX fx;
7763 static RECT rect = {0, 0, 64, 128};
7764 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
7765 DDCOLORKEY ckey;
7766 IDirectDrawSurface *surface, *rt;
7767 IDirect3DTexture2 *texture;
7768 D3DTEXTUREHANDLE texture_handle;
7769 HWND window;
7770 IDirectDraw2 *ddraw;
7771 IDirect3DDevice2 *device;
7772 IDirect3DMaterial2 *material;
7773 IDirect3DViewport2 *viewport;
7774 ULONG ref;
7775 D3DCOLOR color;
7777 static D3DTLVERTEX test1_quads[] =
7779 {{0.0f}, {0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {0.0f}, {0.0f}},
7780 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {0.0f}, {1.0f}},
7781 {{640.0f}, {0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {1.0f}, {0.0f}},
7782 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {1.0f}, {1.0f}},
7783 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {0.0f}, {0.0f}},
7784 {{0.0f}, {480.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {0.0f}, {1.0f}},
7785 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {1.0f}, {0.0f}},
7786 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {1.0f}, {1.0f}},
7788 test2_quads[] =
7790 {{0.0f}, {0.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {0.0f}, {0.0f}},
7791 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {0.0f}, {1.0f}},
7792 {{640.0f}, {0.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {1.0f}, {0.0f}},
7793 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {1.0f}, {1.0f}},
7794 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {0.0f}, {0.0f}},
7795 {{0.0f}, {480.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {0.0f}, {1.0f}},
7796 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {1.0f}, {0.0f}},
7797 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {1.0f}, {1.0f}},
7800 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7801 0, 0, 640, 480, 0, 0, 0, 0);
7802 ddraw = create_ddraw();
7803 ok(!!ddraw, "Failed to create a ddraw object.\n");
7804 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
7806 skip("Failed to create a 3D device, skipping test.\n");
7807 DestroyWindow(window);
7808 IDirectDraw2_Release(ddraw);
7809 return;
7812 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
7813 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
7815 material = create_diffuse_material(device, 0.0f, 0.0f, 0.0f, 1.0f);
7816 viewport = create_viewport(device, 0, 0, 640, 480);
7817 viewport_set_background(device, viewport, material);
7818 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
7819 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
7821 /* Test alpha with DDPF_ALPHAPIXELS texture - should be taken from texture alpha channel.
7823 * The vertex alpha is completely ignored in this case, so case 1 and 2 combined are not
7824 * a D3DTOP_MODULATE with texture alpha = 0xff in case 2 (no alpha in texture). */
7825 memset(&ddsd, 0, sizeof(ddsd));
7826 ddsd.dwSize = sizeof(ddsd);
7827 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
7828 ddsd.dwHeight = 128;
7829 ddsd.dwWidth = 128;
7830 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
7831 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
7832 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
7833 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
7834 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7835 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7836 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
7837 U5(ddsd.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
7838 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
7839 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7841 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
7842 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
7843 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
7844 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
7845 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
7846 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
7848 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7849 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
7851 memset(&fx, 0, sizeof(fx));
7852 fx.dwSize = sizeof(fx);
7853 U5(fx).dwFillColor = 0xff0000ff;
7854 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7855 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
7856 U5(fx).dwFillColor = 0x800000ff;
7857 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7858 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
7860 /* Note that the ddraw1 version of this test runs tests 1-3 with D3DRENDERSTATE_COLORKEYENABLE
7861 * enabled, whereas this version only runs test 4 with color keying on. Because no color key
7862 * is set on the texture this should not result in different behavior. */
7863 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
7864 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
7865 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
7866 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
7867 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
7868 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
7869 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
7870 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
7871 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
7872 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
7873 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
7874 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
7876 hr = IDirect3DDevice2_BeginScene(device);
7877 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
7878 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[0], 4, 0);
7879 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7880 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[4], 4, 0);
7881 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7882 hr = IDirect3DDevice2_EndScene(device);
7883 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7885 color = get_surface_color(rt, 5, 5);
7886 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
7887 color = get_surface_color(rt, 400, 5);
7888 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
7889 color = get_surface_color(rt, 5, 245);
7890 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
7891 color = get_surface_color(rt, 400, 245);
7892 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
7894 IDirect3DTexture2_Release(texture);
7895 ref = IDirectDrawSurface_Release(surface);
7896 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
7898 /* Test alpha with texture that has no alpha channel - alpha should be taken from diffuse vertex color. */
7899 memset(&ddsd, 0, sizeof(ddsd));
7900 ddsd.dwSize = sizeof(ddsd);
7901 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
7902 ddsd.dwHeight = 128;
7903 ddsd.dwWidth = 128;
7904 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
7905 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
7906 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
7907 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
7908 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7909 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7910 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
7912 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
7913 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7915 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
7916 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
7917 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
7918 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
7919 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
7920 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
7922 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7923 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
7925 U5(fx).dwFillColor = 0xff0000ff;
7926 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7927 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
7928 U5(fx).dwFillColor = 0x800000ff;
7929 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7930 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
7932 hr = IDirect3DDevice2_BeginScene(device);
7933 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
7934 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[0], 4, 0);
7935 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7936 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[4], 4, 0);
7937 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7938 hr = IDirect3DDevice2_EndScene(device);
7939 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7941 color = get_surface_color(rt, 5, 5);
7942 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
7943 color = get_surface_color(rt, 400, 5);
7944 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
7945 color = get_surface_color(rt, 5, 245);
7946 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
7947 color = get_surface_color(rt, 400, 245);
7948 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
7950 IDirect3DTexture2_Release(texture);
7951 ref = IDirectDrawSurface_Release(surface);
7952 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
7954 /* Test RGB - should multiply color components from diffuse vertex color and texture. */
7955 memset(&ddsd, 0, sizeof(ddsd));
7956 ddsd.dwSize = sizeof(ddsd);
7957 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
7958 ddsd.dwHeight = 128;
7959 ddsd.dwWidth = 128;
7960 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
7961 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
7962 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
7963 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
7964 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7965 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7966 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
7967 U5(ddsd.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
7968 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
7969 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7971 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
7972 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
7973 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
7974 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
7975 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
7976 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
7978 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7979 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
7981 U5(fx).dwFillColor = 0x00ffffff;
7982 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7983 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
7984 U5(fx).dwFillColor = 0x00ffff80;
7985 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7986 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
7988 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
7989 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
7991 hr = IDirect3DDevice2_BeginScene(device);
7992 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
7993 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test2_quads[0], 4, 0);
7994 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7995 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test2_quads[4], 4, 0);
7996 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7997 hr = IDirect3DDevice2_EndScene(device);
7998 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8000 color = get_surface_color(rt, 5, 5);
8001 ok(compare_color(color, 0x00ff0040, 2), "Got unexpected color 0x%08x.\n", color);
8002 color = get_surface_color(rt, 400, 5);
8003 ok(compare_color(color, 0x00ff0080, 2), "Got unexpected color 0x%08x.\n", color);
8004 color = get_surface_color(rt, 5, 245);
8005 ok(compare_color(color, 0x00800080, 2), "Got unexpected color 0x%08x.\n", color);
8006 color = get_surface_color(rt, 400, 245);
8007 ok(compare_color(color, 0x008000ff, 2), "Got unexpected color 0x%08x.\n", color);
8009 IDirect3DTexture2_Release(texture);
8010 ref = IDirectDrawSurface_Release(surface);
8011 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
8013 /* Test alpha again, now with color keyed texture (colorkey emulation in wine can interfere). */
8014 memset(&ddsd, 0, sizeof(ddsd));
8015 ddsd.dwSize = sizeof(ddsd);
8016 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
8017 ddsd.dwHeight = 128;
8018 ddsd.dwWidth = 128;
8019 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
8020 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
8021 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
8022 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 16;
8023 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xf800;
8024 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x07e0;
8025 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x001f;
8027 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
8028 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8030 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
8031 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
8032 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
8033 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
8034 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
8035 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8037 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8038 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
8040 U5(fx).dwFillColor = 0xf800;
8041 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8042 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
8043 U5(fx).dwFillColor = 0x001f;
8044 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8045 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
8047 ckey.dwColorSpaceLowValue = 0x001f;
8048 ckey.dwColorSpaceHighValue = 0x001f;
8049 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
8050 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
8052 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
8053 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8054 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
8055 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8057 hr = IDirect3DDevice2_BeginScene(device);
8058 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8059 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[0], 4, 0);
8060 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8061 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[4], 4, 0);
8062 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8063 hr = IDirect3DDevice2_EndScene(device);
8064 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8066 color = get_surface_color(rt, 5, 5);
8067 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
8068 color = get_surface_color(rt, 400, 5);
8069 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
8070 color = get_surface_color(rt, 5, 245);
8071 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
8072 color = get_surface_color(rt, 400, 245);
8073 ok(compare_color(color, 0x00800000, 2), "Got unexpected color 0x%08x.\n", color);
8075 IDirect3DTexture2_Release(texture);
8076 ref = IDirectDrawSurface_Release(surface);
8077 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
8079 destroy_viewport(device, viewport);
8080 ref = IDirect3DMaterial2_Release(material);
8081 ok(ref == 0, "Material not properly released, refcount %u.\n", ref);
8082 IDirectDrawSurface_Release(rt);
8083 IDirect3DDevice2_Release(device);
8084 ref = IDirectDraw2_Release(ddraw);
8085 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
8086 DestroyWindow(window);
8089 static void test_viewport_clear_rect(void)
8091 HRESULT hr;
8092 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
8093 static D3DRECT clear_rect2 = {{90}, {90}, {110}, {110}};
8094 IDirectDrawSurface *rt;
8095 HWND window;
8096 IDirectDraw2 *ddraw;
8097 IDirect3DDevice2 *device;
8098 IDirect3DMaterial2 *red, *green;
8099 IDirect3DViewport2 *viewport, *viewport2;
8100 ULONG ref;
8101 D3DCOLOR color;
8103 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8104 0, 0, 640, 480, 0, 0, 0, 0);
8105 ddraw = create_ddraw();
8106 ok(!!ddraw, "Failed to create a ddraw object.\n");
8107 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
8109 skip("Failed to create a 3D device, skipping test.\n");
8110 DestroyWindow(window);
8111 IDirectDraw2_Release(ddraw);
8112 return;
8115 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
8116 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8118 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
8119 viewport = create_viewport(device, 0, 0, 640, 480);
8120 viewport_set_background(device, viewport, red);
8121 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8122 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8124 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
8125 viewport2 = create_viewport(device, 100, 100, 20, 20);
8126 viewport_set_background(device, viewport2, green);
8127 hr = IDirect3DViewport2_Clear(viewport2, 1, &clear_rect2, D3DCLEAR_TARGET);
8128 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8130 color = get_surface_color(rt, 85, 85); /* Outside both. */
8131 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
8132 color = get_surface_color(rt, 95, 95); /* Outside vp, inside rect. */
8133 /* AMD GPUs ignore the viewport dimensions and only care about the rectangle. */
8134 ok(compare_color(color, 0x00ff0000, 1) || broken(compare_color(color, 0x0000ff00, 1)),
8135 "Got unexpected color 0x%08x.\n", color);
8136 color = get_surface_color(rt, 105, 105); /* Inside both. */
8137 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
8138 color = get_surface_color(rt, 115, 115); /* Inside vp, outside rect. */
8139 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
8140 color = get_surface_color(rt, 125, 125); /* Outside both. */
8141 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
8143 destroy_viewport(device, viewport2);
8144 destroy_material(green);
8145 destroy_viewport(device, viewport);
8146 destroy_material(red);
8147 IDirectDrawSurface_Release(rt);
8148 IDirect3DDevice2_Release(device);
8149 ref = IDirectDraw2_Release(ddraw);
8150 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
8151 DestroyWindow(window);
8154 static void test_color_fill(void)
8156 HRESULT hr;
8157 IDirect3DDevice2 *device;
8158 IDirectDraw2 *ddraw;
8159 IDirectDrawSurface *surface, *surface2;
8160 DDSURFACEDESC surface_desc;
8161 ULONG refcount;
8162 HWND window;
8163 unsigned int i;
8164 DDBLTFX fx;
8165 RECT rect = {5, 5, 7, 7};
8166 DWORD *color;
8167 DWORD num_fourcc_codes, *fourcc_codes;
8168 DDCAPS hal_caps;
8169 BOOL support_uyvy = FALSE, support_yuy2 = FALSE;
8170 static const struct
8172 DWORD caps;
8173 HRESULT colorfill_hr, depthfill_hr;
8174 BOOL rop_success;
8175 const char *name;
8176 DWORD result;
8177 BOOL check_result;
8178 DDPIXELFORMAT format;
8180 tests[] =
8183 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
8184 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
8186 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
8187 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
8191 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
8192 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
8194 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
8195 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
8199 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
8200 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
8202 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
8203 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
8207 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
8208 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
8210 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
8211 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
8215 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY,
8216 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0, FALSE,
8217 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
8220 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
8221 * different afterwards. DX9+ GPUs set one of the two luminance values
8222 * in each block, but AMD and Nvidia GPUs disagree on which luminance
8223 * value they set. r200 (dx8) just sets the entire block to the clear
8224 * value. */
8225 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
8226 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
8228 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
8229 {0}, {0}, {0}, {0}, {0}
8233 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
8234 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
8236 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
8237 {0}, {0}, {0}, {0}, {0}
8241 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY,
8242 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
8244 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
8245 {0}, {0}, {0}, {0}, {0}
8249 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY,
8250 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
8252 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
8253 {0}, {0}, {0}, {0}, {0}
8257 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
8258 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
8260 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
8261 {0}, {0}, {0}, {0}, {0}
8265 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
8266 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
8268 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
8269 {0}, {0}, {0}, {0}, {0}
8273 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
8274 * surface works, presumably because it is handled by the runtime instead of
8275 * the driver. */
8276 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
8277 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
8279 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
8280 {8}, {0}, {0}, {0}, {0}
8284 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
8285 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
8287 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
8288 {8}, {0}, {0}, {0}, {0}
8292 static const struct
8294 DWORD rop;
8295 const char *name;
8296 HRESULT hr;
8298 rops[] =
8300 {SRCCOPY, "SRCCOPY", DD_OK},
8301 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
8302 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
8303 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
8304 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
8305 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
8306 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
8307 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
8308 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
8309 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
8310 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
8311 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
8312 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
8313 {BLACKNESS, "BLACKNESS", DD_OK},
8314 {WHITENESS, "WHITENESS", DD_OK},
8315 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
8318 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8319 0, 0, 640, 480, 0, 0, 0, 0);
8320 ddraw = create_ddraw();
8321 ok(!!ddraw, "Failed to create a ddraw object.\n");
8322 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
8324 skip("Failed to create a 3D device, skipping test.\n");
8325 DestroyWindow(window);
8326 IDirectDraw2_Release(ddraw);
8327 return;
8330 hr = IDirectDraw2_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
8331 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
8332 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8333 num_fourcc_codes * sizeof(*fourcc_codes));
8334 if (!fourcc_codes)
8335 goto done;
8336 hr = IDirectDraw2_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
8337 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
8338 for (i = 0; i < num_fourcc_codes; i++)
8340 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
8341 support_yuy2 = TRUE;
8342 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
8343 support_uyvy = TRUE;
8345 HeapFree(GetProcessHeap(), 0, fourcc_codes);
8347 memset(&hal_caps, 0, sizeof(hal_caps));
8348 hal_caps.dwSize = sizeof(hal_caps);
8349 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
8350 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8352 if ((!support_yuy2 && !support_uyvy) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
8353 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
8355 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
8357 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
8358 memset(&fx, 0, sizeof(fx));
8359 fx.dwSize = sizeof(fx);
8360 U5(fx).dwFillColor = 0xdeadbeef;
8362 memset(&surface_desc, 0, sizeof(surface_desc));
8363 surface_desc.dwSize = sizeof(surface_desc);
8364 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8365 surface_desc.dwWidth = 64;
8366 surface_desc.dwHeight = 64;
8367 surface_desc.ddpfPixelFormat = tests[i].format;
8368 surface_desc.ddsCaps.dwCaps = tests[i].caps;
8370 if (tests[i].caps & DDSCAPS_TEXTURE)
8372 struct format_support_check check = {&tests[i].format, FALSE};
8373 hr = IDirect3DDevice2_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
8374 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
8375 if (!check.supported)
8376 continue;
8379 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !support_yuy2)
8380 continue;
8381 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !support_uyvy)
8382 continue;
8383 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
8384 continue;
8386 if (tests[i].caps & DDSCAPS_ZBUFFER)
8388 surface_desc.dwFlags &= ~DDSD_PIXELFORMAT;
8389 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
8390 U2(surface_desc).dwZBufferBitDepth = get_device_z_depth(device);
8393 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8394 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, surface %s.\n", hr, tests[i].name);
8396 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8397 if (tests[i].format.dwFourCC)
8398 todo_wine ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
8399 hr, tests[i].colorfill_hr, tests[i].name);
8400 else
8401 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
8402 hr, tests[i].colorfill_hr, tests[i].name);
8404 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8405 if (tests[i].format.dwFourCC)
8406 todo_wine ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
8407 hr, tests[i].colorfill_hr, tests[i].name);
8408 else
8409 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
8410 hr, tests[i].colorfill_hr, tests[i].name);
8412 if (SUCCEEDED(hr) && tests[i].check_result)
8414 memset(&surface_desc, 0, sizeof(surface_desc));
8415 surface_desc.dwSize = sizeof(surface_desc);
8416 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
8417 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8418 color = surface_desc.lpSurface;
8419 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
8420 *color, tests[i].result, tests[i].name);
8421 hr = IDirectDrawSurface_Unlock(surface, NULL);
8422 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8425 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8426 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
8427 hr, tests[i].depthfill_hr, tests[i].name);
8428 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8429 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
8430 hr, tests[i].depthfill_hr, tests[i].name);
8432 U5(fx).dwFillColor = 0xdeadbeef;
8433 fx.dwROP = BLACKNESS;
8434 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
8435 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
8436 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
8437 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
8438 U5(fx).dwFillColor, tests[i].name);
8440 if (SUCCEEDED(hr) && tests[i].check_result)
8442 memset(&surface_desc, 0, sizeof(surface_desc));
8443 surface_desc.dwSize = sizeof(surface_desc);
8444 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
8445 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8446 color = surface_desc.lpSurface;
8447 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
8448 *color, tests[i].name);
8449 hr = IDirectDrawSurface_Unlock(surface, NULL);
8450 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8453 fx.dwROP = WHITENESS;
8454 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
8455 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
8456 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
8457 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
8458 U5(fx).dwFillColor, tests[i].name);
8460 if (SUCCEEDED(hr) && tests[i].check_result)
8462 memset(&surface_desc, 0, sizeof(surface_desc));
8463 surface_desc.dwSize = sizeof(surface_desc);
8464 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
8465 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8466 color = surface_desc.lpSurface;
8467 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
8468 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
8469 *color, tests[i].name);
8470 hr = IDirectDrawSurface_Unlock(surface, NULL);
8471 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8474 IDirectDrawSurface_Release(surface);
8477 memset(&fx, 0, sizeof(fx));
8478 fx.dwSize = sizeof(fx);
8479 U5(fx).dwFillColor = 0xdeadbeef;
8480 fx.dwROP = WHITENESS;
8482 memset(&surface_desc, 0, sizeof(surface_desc));
8483 surface_desc.dwSize = sizeof(surface_desc);
8484 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8485 surface_desc.dwWidth = 64;
8486 surface_desc.dwHeight = 64;
8487 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
8488 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
8489 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
8490 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8491 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8492 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
8493 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
8494 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8495 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8496 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
8497 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8499 /* No DDBLTFX. */
8500 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
8501 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8502 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
8503 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8505 /* Unused source rectangle. */
8506 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8507 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8508 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
8509 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8511 /* Unused source surface. */
8512 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8513 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8514 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
8515 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8516 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8517 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8518 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
8519 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8521 /* Inverted destination or source rectangle. */
8522 SetRect(&rect, 5, 7, 7, 5);
8523 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8524 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8525 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8526 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8527 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8528 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8529 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8530 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8531 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
8532 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8534 /* Negative rectangle. */
8535 SetRect(&rect, -1, -1, 5, 5);
8536 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8537 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8538 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8539 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8540 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8541 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8542 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8543 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8544 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
8545 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8547 /* Out of bounds rectangle. */
8548 SetRect(&rect, 0, 0, 65, 65);
8549 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8550 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8551 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
8552 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8554 /* Combine multiple flags. */
8555 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8556 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8557 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
8558 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8559 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
8560 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8562 for (i = 0; i < sizeof(rops) / sizeof(*rops); i++)
8564 fx.dwROP = rops[i].rop;
8565 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
8566 ok(hr == rops[i].hr, "Got unexpected hr %#x for rop %s.\n", hr, rops[i].name);
8569 IDirectDrawSurface_Release(surface2);
8570 IDirectDrawSurface_Release(surface);
8572 memset(&surface_desc, 0, sizeof(surface_desc));
8573 surface_desc.dwSize = sizeof(surface_desc);
8574 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_ZBUFFERBITDEPTH;
8575 surface_desc.dwWidth = 64;
8576 surface_desc.dwHeight = 64;
8577 U2(surface_desc).dwZBufferBitDepth = get_device_z_depth(device);
8578 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
8579 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8580 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8581 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
8582 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8584 /* No DDBLTFX. */
8585 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
8586 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8588 /* Unused source rectangle. */
8589 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8590 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8592 /* Unused source surface. */
8593 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8594 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8595 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8596 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8598 /* Inverted destination or source rectangle. */
8599 SetRect(&rect, 5, 7, 7, 5);
8600 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8601 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8602 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8603 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8604 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8605 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8606 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8607 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8609 /* Negative rectangle. */
8610 SetRect(&rect, -1, -1, 5, 5);
8611 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8612 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8613 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8614 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8615 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8616 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8617 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8618 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8620 /* Out of bounds rectangle. */
8621 SetRect(&rect, 0, 0, 65, 65);
8622 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8623 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8625 /* Combine multiple flags. */
8626 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8627 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8629 IDirectDrawSurface_Release(surface2);
8630 IDirectDrawSurface_Release(surface);
8632 done:
8633 IDirect3DDevice2_Release(device);
8634 refcount = IDirectDraw2_Release(ddraw);
8635 ok(refcount == 0, "Ddraw object not properly released, refcount %u.\n", refcount);
8636 DestroyWindow(window);
8639 static void test_colorkey_precision(void)
8641 static D3DLVERTEX quad[] =
8643 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xff000000}, {0}, {0.0f}, {0.0f}},
8644 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff000000}, {0}, {0.0f}, {1.0f}},
8645 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff000000}, {0}, {1.0f}, {0.0f}},
8646 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xff000000}, {0}, {1.0f}, {1.0f}},
8648 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
8649 IDirect3DDevice2 *device;
8650 IDirectDraw2 *ddraw;
8651 IDirectDrawSurface *rt;
8652 IDirect3DViewport2 *viewport;
8653 HWND window;
8654 HRESULT hr;
8655 IDirectDrawSurface *src, *dst, *texture;
8656 D3DTEXTUREHANDLE handle;
8657 IDirect3DTexture2 *d3d_texture;
8658 IDirect3DMaterial2 *green;
8659 DDSURFACEDESC surface_desc, lock_desc;
8660 ULONG refcount;
8661 D3DCOLOR color;
8662 unsigned int t, c;
8663 DDCOLORKEY ckey;
8664 DDBLTFX fx;
8665 DWORD data[4] = {0}, color_mask;
8666 D3DDEVICEDESC device_desc, hel_desc;
8667 BOOL warp;
8668 static const struct
8670 unsigned int max, shift, bpp, clear;
8671 const char *name;
8672 DDPIXELFORMAT fmt;
8674 tests[] =
8677 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8",
8679 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
8680 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
8685 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel",
8687 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
8688 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
8693 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel",
8695 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
8696 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
8701 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4",
8703 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
8704 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
8710 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8711 0, 0, 640, 480, 0, 0, 0, 0);
8712 ddraw = create_ddraw();
8713 ok(!!ddraw, "Failed to create a ddraw object.\n");
8714 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
8716 skip("Failed to create a 3D device, skipping test.\n");
8717 DestroyWindow(window);
8718 IDirectDraw2_Release(ddraw);
8719 return;
8721 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
8722 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8724 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
8725 * (color key doesn't match although the values are equal), and a false
8726 * positive when the color key is 0 and the texture contains the value 1.
8727 * I don't want to mark this broken unconditionally since this would
8728 * essentially disable the test on Windows. Try to detect WARP (and I
8729 * guess mismatch other SW renderers) by its ability to texture from
8730 * system memory. Also on random occasions 254 == 255 and 255 != 255.*/
8731 memset(&device_desc, 0, sizeof(device_desc));
8732 device_desc.dwSize = sizeof(device_desc);
8733 memset(&hel_desc, 0, sizeof(hel_desc));
8734 hel_desc.dwSize = sizeof(hel_desc);
8735 hr = IDirect3DDevice2_GetCaps(device, &device_desc, &hel_desc);
8736 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
8737 warp = !!(device_desc.dwDevCaps & D3DDEVCAPS_TEXTURESYSTEMMEMORY);
8739 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
8740 viewport = create_viewport(device, 0, 0, 640, 480);
8741 viewport_set_background(device, viewport, green);
8742 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
8743 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
8745 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
8746 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
8747 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
8748 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
8749 /* There's no way to ignore the texture color in d3d2, so multiply the texture color
8750 * with a black vertex color. */
8751 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATEALPHA);
8752 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8754 memset(&fx, 0, sizeof(fx));
8755 fx.dwSize = sizeof(fx);
8756 memset(&lock_desc, 0, sizeof(lock_desc));
8757 lock_desc.dwSize = sizeof(lock_desc);
8759 for (t = 0; t < sizeof(tests) / sizeof(*tests); ++t)
8761 memset(&surface_desc, 0, sizeof(surface_desc));
8762 surface_desc.dwSize = sizeof(surface_desc);
8763 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8764 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8765 surface_desc.dwWidth = 4;
8766 surface_desc.dwHeight = 1;
8767 surface_desc.ddpfPixelFormat = tests[t].fmt;
8768 /* Windows XP (at least with the r200 driver, other drivers untested) produces
8769 * garbage when doing color keyed texture->texture blits. */
8770 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src, NULL);
8771 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8772 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst, NULL);
8773 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8775 fx.dwFillColor = tests[t].clear;
8776 /* On the w8 testbot (WARP driver) the blit result has different values in the
8777 * X channel. */
8778 color_mask = U2(tests[t].fmt).dwRBitMask
8779 | U3(tests[t].fmt).dwGBitMask
8780 | U4(tests[t].fmt).dwBBitMask;
8782 for (c = 0; c <= tests[t].max; ++c)
8784 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
8785 * texture after it has been set once... */
8786 surface_desc.dwFlags |= DDSD_CKSRCBLT;
8787 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
8788 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
8789 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
8790 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &texture, NULL);
8791 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8793 hr = IDirectDrawSurface4_QueryInterface(texture, &IID_IDirect3DTexture2, (void **)&d3d_texture);
8794 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
8795 hr = IDirect3DTexture2_GetHandle(d3d_texture, device, &handle);
8796 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
8797 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, handle);
8798 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
8799 IDirect3DTexture2_Release(d3d_texture);
8801 hr = IDirectDrawSurface_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8802 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
8804 hr = IDirectDrawSurface_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
8805 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8806 switch (tests[t].bpp)
8808 case 4:
8809 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
8810 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
8811 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
8812 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
8813 break;
8815 case 2:
8816 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
8817 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
8818 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
8819 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
8820 break;
8822 hr = IDirectDrawSurface_Unlock(src, 0);
8823 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8824 hr = IDirectDrawSurface_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
8825 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
8827 ckey.dwColorSpaceLowValue = c << tests[t].shift;
8828 ckey.dwColorSpaceHighValue = c << tests[t].shift;
8829 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
8830 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
8832 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
8833 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
8835 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
8836 hr = IDirectDrawSurface_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
8837 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8838 switch (tests[t].bpp)
8840 case 4:
8841 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
8842 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
8843 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
8844 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
8845 break;
8847 case 2:
8848 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
8849 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
8850 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
8851 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
8852 break;
8854 hr = IDirectDrawSurface_Unlock(dst, 0);
8855 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8857 if (!c)
8859 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
8860 tests[t].clear, data[0], tests[t].name, c);
8862 if (data[3] == tests[t].clear)
8864 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
8865 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
8866 * even when a different surface is used. The blit itself doesn't draw anything,
8867 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
8868 * never be masked out by the key.
8870 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
8871 * terrible on WARP. */
8872 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
8873 IDirectDrawSurface_Release(texture);
8874 IDirectDrawSurface_Release(src);
8875 IDirectDrawSurface_Release(dst);
8876 goto done;
8879 else
8880 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
8881 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
8883 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
8884 tests[t].clear, data[1], tests[t].name, c);
8886 if (c == tests[t].max)
8887 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
8888 tests[t].clear, data[2], tests[t].name, c);
8889 else
8890 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
8891 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
8893 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8894 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
8896 hr = IDirect3DDevice2_BeginScene(device);
8897 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8898 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, 4, 0);
8899 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8900 hr = IDirect3DDevice2_EndScene(device);
8901 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8903 color = get_surface_color(rt, 80, 240);
8904 if (!c)
8905 ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
8906 "Got unexpected color 0x%08x, format %s, c=%u.\n",
8907 color, tests[t].name, c);
8908 else
8909 ok(compare_color(color, 0x00000000, 1) || broken(warp && compare_color(color, 0x0000ff00, 1)),
8910 "Got unexpected color 0x%08x, format %s, c=%u.\n",
8911 color, tests[t].name, c);
8913 color = get_surface_color(rt, 240, 240);
8914 ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
8915 "Got unexpected color 0x%08x, format %s, c=%u.\n",
8916 color, tests[t].name, c);
8918 color = get_surface_color(rt, 400, 240);
8919 if (c == tests[t].max)
8920 ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
8921 "Got unexpected color 0x%08x, format %s, c=%u.\n",
8922 color, tests[t].name, c);
8923 else
8924 ok(compare_color(color, 0x00000000, 1) || broken(warp && compare_color(color, 0x0000ff00, 1)),
8925 "Got unexpected color 0x%08x, format %s, c=%u.\n",
8926 color, tests[t].name, c);
8928 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
8929 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
8930 IDirectDrawSurface_Release(texture);
8932 IDirectDrawSurface_Release(src);
8933 IDirectDrawSurface_Release(dst);
8935 done:
8937 destroy_viewport(device, viewport);
8938 destroy_material(green);
8939 IDirectDrawSurface_Release(rt);
8940 IDirect3DDevice2_Release(device);
8941 refcount = IDirectDraw2_Release(ddraw);
8942 ok(refcount == 0, "Ddraw object not properly released, refcount %u.\n", refcount);
8943 DestroyWindow(window);
8946 static void test_range_colorkey(void)
8948 IDirectDraw2 *ddraw;
8949 HWND window;
8950 HRESULT hr;
8951 IDirectDrawSurface *surface;
8952 DDSURFACEDESC surface_desc;
8953 ULONG refcount;
8954 DDCOLORKEY ckey;
8956 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8957 0, 0, 640, 480, 0, 0, 0, 0);
8958 ddraw = create_ddraw();
8959 ok(!!ddraw, "Failed to create a ddraw object.\n");
8960 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8961 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8963 memset(&surface_desc, 0, sizeof(surface_desc));
8964 surface_desc.dwSize = sizeof(surface_desc);
8965 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
8966 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
8967 surface_desc.dwWidth = 1;
8968 surface_desc.dwHeight = 1;
8969 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
8970 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
8971 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8972 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8973 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
8974 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
8976 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
8977 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
8978 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
8979 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8980 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
8982 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
8983 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
8984 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8985 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
8987 /* Same for DDSCAPS_OFFSCREENPLAIN. */
8988 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8989 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
8990 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
8991 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8992 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
8994 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
8995 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
8996 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8997 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
8999 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
9000 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
9001 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9002 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9004 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
9005 ckey.dwColorSpaceLowValue = 0x00000000;
9006 ckey.dwColorSpaceHighValue = 0x00000001;
9007 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9008 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
9010 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9011 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
9012 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
9013 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
9015 ckey.dwColorSpaceLowValue = 0x00000001;
9016 ckey.dwColorSpaceHighValue = 0x00000000;
9017 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9018 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
9020 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9021 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
9022 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
9023 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
9025 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
9026 ckey.dwColorSpaceLowValue = 0x00000000;
9027 ckey.dwColorSpaceHighValue = 0x00000000;
9028 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
9029 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
9031 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
9032 ckey.dwColorSpaceLowValue = 0x00000001;
9033 ckey.dwColorSpaceHighValue = 0x00000000;
9034 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
9035 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
9036 ckey.dwColorSpaceLowValue = 0x00000000;
9037 ckey.dwColorSpaceHighValue = 0x00000001;
9038 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
9039 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
9040 /* Range destination keys don't work either. */
9041 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
9042 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
9044 /* Just to show it's not because of A, R, and G having equal values. */
9045 ckey.dwColorSpaceLowValue = 0x00000000;
9046 ckey.dwColorSpaceHighValue = 0x01010101;
9047 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
9048 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
9050 /* None of these operations modified the key. */
9051 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9052 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
9053 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
9054 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
9056 IDirectDrawSurface_Release(surface),
9057 refcount = IDirectDraw2_Release(ddraw);
9058 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9059 DestroyWindow(window);
9062 static void test_shademode(void)
9064 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
9065 IDirect3DMaterial2 *background;
9066 IDirect3DViewport2 *viewport;
9067 IDirect3DDevice2 *device;
9068 IDirectDrawSurface *rt;
9069 DWORD color0, color1;
9070 IDirectDraw2 *ddraw;
9071 D3DLVERTEX *quad;
9072 IDirect3D2 *d3d;
9073 ULONG refcount;
9074 UINT i, count;
9075 HWND window;
9076 HRESULT hr;
9077 static D3DLVERTEX quad_strip[] =
9079 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}},
9080 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
9081 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
9082 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffffffff}},
9084 quad_list[] =
9086 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}},
9087 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
9088 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
9090 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
9091 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
9092 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffffffff}},
9094 static const struct
9096 DWORD primtype;
9097 DWORD shademode;
9098 DWORD color0, color1;
9100 tests[] =
9102 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x0000ff00},
9103 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
9104 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
9105 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
9106 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
9107 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
9110 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9111 0, 0, 640, 480, 0, 0, 0, 0);
9112 ddraw = create_ddraw();
9113 ok(!!ddraw, "Failed to create a ddraw object.\n");
9114 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
9116 skip("Failed to create a 3D device, skipping test.\n");
9117 IDirectDraw2_Release(ddraw);
9118 DestroyWindow(window);
9119 return;
9122 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
9123 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9124 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
9125 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9127 background = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
9128 viewport = create_viewport(device, 0, 0, 640, 480);
9129 viewport_set_background(device, viewport, background);
9130 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
9131 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
9133 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
9134 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
9136 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
9137 * the color fixups we have to do for FLAT shading will be dependent on that. */
9139 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
9141 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9142 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
9144 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
9145 ok(hr == D3D_OK, "Failed to set shade mode, hr %#x.\n", hr);
9147 hr = IDirect3DDevice2_BeginScene(device);
9148 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9149 quad = tests[i].primtype == D3DPT_TRIANGLESTRIP ? quad_strip : quad_list;
9150 count = tests[i].primtype == D3DPT_TRIANGLESTRIP ? 4 : 6;
9151 hr = IDirect3DDevice2_DrawPrimitive(device, tests[i].primtype, D3DVT_LVERTEX, quad, count, 0);
9152 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9153 hr = IDirect3DDevice2_EndScene(device);
9154 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9156 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
9157 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
9159 /* For D3DSHADE_FLAT it should take the color of the first vertex of
9160 * each triangle. This requires EXT_provoking_vertex or similar
9161 * functionality being available. */
9162 /* PHONG should be the same as GOURAUD, since no hardware implements
9163 * this. */
9164 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
9165 i, color0, tests[i].color0);
9166 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
9167 i, color1, tests[i].color1);
9170 destroy_viewport(device, viewport);
9171 destroy_material(background);
9172 IDirectDrawSurface_Release(rt);
9173 IDirect3D2_Release(d3d);
9174 refcount = IDirect3DDevice2_Release(device);
9175 ok(!refcount, "Device has %u references left.\n", refcount);
9176 IDirectDraw_Release(ddraw);
9177 DestroyWindow(window);
9180 static void test_lockrect_invalid(void)
9182 unsigned int i, r;
9183 IDirectDraw2 *ddraw;
9184 IDirectDrawSurface *surface1;
9185 IDirectDrawSurface2 *surface;
9186 HWND window;
9187 HRESULT hr;
9188 DDSURFACEDESC surface_desc;
9189 DDCAPS hal_caps;
9190 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
9191 static RECT valid[] =
9193 {60, 60, 68, 68},
9194 {60, 60, 60, 68},
9195 {60, 60, 68, 60},
9196 {120, 60, 128, 68},
9197 {60, 120, 68, 128},
9199 static RECT invalid[] =
9201 {68, 60, 60, 68}, /* left > right */
9202 {60, 68, 68, 60}, /* top > bottom */
9203 {-8, 60, 0, 68}, /* left < surface */
9204 {60, -8, 68, 0}, /* top < surface */
9205 {-16, 60, -8, 68}, /* right < surface */
9206 {60, -16, 68, -8}, /* bottom < surface */
9207 {60, 60, 136, 68}, /* right > surface */
9208 {60, 60, 68, 136}, /* bottom > surface */
9209 {136, 60, 144, 68}, /* left > surface */
9210 {60, 136, 68, 144}, /* top > surface */
9212 static const struct
9214 DWORD caps;
9215 const char *name;
9216 HRESULT hr;
9218 resources[] =
9220 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, "sysmem offscreenplain", DDERR_INVALIDPARAMS},
9221 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, "vidmem offscreenplain", DDERR_INVALIDPARAMS},
9222 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "sysmem texture", DDERR_INVALIDPARAMS},
9223 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "vidmem texture", DDERR_INVALIDPARAMS},
9226 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9227 0, 0, 640, 480, 0, 0, 0, 0);
9228 ddraw = create_ddraw();
9229 ok(!!ddraw, "Failed to create a ddraw object.\n");
9230 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9231 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9233 memset(&hal_caps, 0, sizeof(hal_caps));
9234 hal_caps.dwSize = sizeof(hal_caps);
9235 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
9236 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9237 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
9239 skip("Required surface types not supported, skipping test.\n");
9240 goto done;
9243 for (r = 0; r < sizeof(resources) / sizeof(*resources); ++r)
9245 memset(&surface_desc, 0, sizeof(surface_desc));
9246 surface_desc.dwSize = sizeof(surface_desc);
9247 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9248 surface_desc.ddsCaps.dwCaps = resources[r].caps;
9249 surface_desc.dwWidth = 128;
9250 surface_desc.dwHeight = 128;
9251 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
9252 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
9253 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
9254 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xff0000;
9255 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x00ff00;
9256 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x0000ff;
9258 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
9259 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, resources[r].name);
9260 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
9261 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface2 interface, hr %#x.\n", hr);
9262 IDirectDrawSurface_Release(surface1);
9264 hr = IDirectDrawSurface2_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
9265 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
9267 for (i = 0; i < sizeof(valid) / sizeof(*valid); ++i)
9269 RECT *rect = &valid[i];
9271 memset(&surface_desc, 0, sizeof(surface_desc));
9272 surface_desc.dwSize = sizeof(surface_desc);
9274 hr = IDirectDrawSurface2_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
9275 ok(SUCCEEDED(hr), "Lock failed (%#x) for rect [%d, %d]->[%d, %d], type %s.\n",
9276 hr, rect->left, rect->top, rect->right, rect->bottom, resources[r].name);
9278 hr = IDirectDrawSurface2_Unlock(surface, NULL);
9279 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
9282 for (i = 0; i < sizeof(invalid) / sizeof(*invalid); ++i)
9284 RECT *rect = &invalid[i];
9286 memset(&surface_desc, 1, sizeof(surface_desc));
9287 surface_desc.dwSize = sizeof(surface_desc);
9289 hr = IDirectDrawSurface2_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
9290 ok(hr == resources[r].hr, "Lock returned %#x for rect [%d, %d]->[%d, %d], type %s.\n",
9291 hr, rect->left, rect->top, rect->right, rect->bottom, resources[r].name);
9292 if (SUCCEEDED(hr))
9294 hr = IDirectDrawSurface2_Unlock(surface, NULL);
9295 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
9297 else
9298 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9301 hr = IDirectDrawSurface2_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
9302 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#x, type %s.\n",
9303 hr, resources[r].name);
9304 hr = IDirectDrawSurface2_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
9305 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#x, type %s.\n",
9306 hr, resources[r].name);
9307 hr = IDirectDrawSurface2_Unlock(surface, NULL);
9308 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
9310 hr = IDirectDrawSurface2_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
9311 ok(SUCCEEDED(hr), "Lock(rect = [%d, %d]->[%d, %d]) failed (%#x).\n",
9312 valid[0].left, valid[0].top, valid[0].right, valid[0].bottom, hr);
9313 hr = IDirectDrawSurface2_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
9314 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = [%d, %d]->[%d, %d]) failed (%#x).\n",
9315 valid[0].left, valid[0].top, valid[0].right, valid[0].bottom, hr);
9317 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
9318 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
9320 hr = IDirectDrawSurface2_Unlock(surface, NULL);
9321 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
9323 IDirectDrawSurface2_Release(surface);
9326 done:
9327 IDirectDraw2_Release(ddraw);
9328 DestroyWindow(window);
9331 static void test_yv12_overlay(void)
9333 IDirectDrawSurface *src_surface, *dst_surface;
9334 RECT rect = {13, 17, 14, 18};
9335 unsigned int offset, y;
9336 unsigned char *base;
9337 IDirectDraw2 *ddraw;
9338 DDSURFACEDESC desc;
9339 HWND window;
9340 HRESULT hr;
9342 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9343 0, 0, 640, 480, 0, 0, 0, 0);
9344 ddraw = create_ddraw();
9345 ok(!!ddraw, "Failed to create a ddraw object.\n");
9346 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9347 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9349 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
9351 skip("Failed to create a YV12 overlay, skipping test.\n");
9352 goto done;
9355 memset(&desc, 0, sizeof(desc));
9356 desc.dwSize = sizeof(desc);
9357 hr = IDirectDrawSurface_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
9358 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9360 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
9361 "Got unexpected flags %#x.\n", desc.dwFlags);
9362 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
9363 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
9364 "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps);
9365 ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth);
9366 ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight);
9367 /* The overlay pitch seems to have 256 byte alignment. */
9368 ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch);
9370 /* Fill the surface with some data for the blit test. */
9371 base = desc.lpSurface;
9372 /* Luminance */
9373 for (y = 0; y < desc.dwHeight; ++y)
9375 memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth);
9377 /* V */
9378 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
9380 memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth);
9382 /* U */
9383 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
9385 memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth);
9388 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
9389 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9391 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
9392 * other block-based formats like DXT the entire Y channel is stored in
9393 * one big chunk of memory, followed by the chroma channels. So partial
9394 * locks do not really make sense. Show that they are allowed nevertheless
9395 * and the offset points into the luminance data. */
9396 hr = IDirectDrawSurface_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
9397 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9398 offset = ((const unsigned char *)desc.lpSurface - base);
9399 ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n",
9400 offset, rect.top * U1(desc).lPitch + rect.left);
9401 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
9402 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9404 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
9406 /* Windows XP with a Radeon X1600 GPU refuses to create a second
9407 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
9408 skip("Failed to create a second YV12 surface, skipping blit test.\n");
9409 IDirectDrawSurface_Release(src_surface);
9410 goto done;
9413 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
9414 /* VMware rejects YV12 blits. This behavior has not been seen on real
9415 * hardware yet, so mark it broken. */
9416 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr);
9418 if (SUCCEEDED(hr))
9420 memset(&desc, 0, sizeof(desc));
9421 desc.dwSize = sizeof(desc);
9422 hr = IDirectDrawSurface_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
9423 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9425 base = desc.lpSurface;
9426 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
9427 base += desc.dwHeight * U1(desc).lPitch;
9428 todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
9429 base += desc.dwHeight / 4 * U1(desc).lPitch;
9430 todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
9432 hr = IDirectDrawSurface_Unlock(dst_surface, NULL);
9433 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9436 IDirectDrawSurface_Release(dst_surface);
9437 IDirectDrawSurface_Release(src_surface);
9438 done:
9439 IDirectDraw2_Release(ddraw);
9440 DestroyWindow(window);
9443 static void test_offscreen_overlay(void)
9445 IDirectDrawSurface *overlay, *offscreen, *primary;
9446 DDSURFACEDESC surface_desc;
9447 IDirectDraw2 *ddraw;
9448 HWND window;
9449 HRESULT hr;
9450 HDC dc;
9452 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9453 0, 0, 640, 480, 0, 0, 0, 0);
9454 ddraw = create_ddraw();
9455 ok(!!ddraw, "Failed to create a ddraw object.\n");
9456 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9457 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9459 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
9461 skip("Failed to create a UYVY overlay, skipping test.\n");
9462 goto done;
9465 memset(&surface_desc, 0, sizeof(surface_desc));
9466 surface_desc.dwSize = sizeof(surface_desc);
9467 surface_desc.dwFlags = DDSD_CAPS;
9468 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
9469 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
9470 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
9472 /* On Windows 7, and probably Vista, UpdateOverlay() will return
9473 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
9474 * surface prevents this by disabling the dwm. */
9475 hr = IDirectDrawSurface_GetDC(primary, &dc);
9476 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
9477 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
9478 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9480 /* Try to overlay a NULL surface. */
9481 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
9482 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9483 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
9484 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9486 /* Try to overlay an offscreen surface. */
9487 memset(&surface_desc, 0, sizeof(surface_desc));
9488 surface_desc.dwSize = sizeof(surface_desc);
9489 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9490 surface_desc.dwWidth = 64;
9491 surface_desc.dwHeight = 64;
9492 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9493 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
9494 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
9495 surface_desc.ddpfPixelFormat.dwFourCC = 0;
9496 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
9497 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xf800;
9498 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x07e0;
9499 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x001f;
9500 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
9501 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
9503 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
9504 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
9506 /* Try to overlay the primary with a non-overlay surface. */
9507 hr = IDirectDrawSurface_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
9508 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
9509 hr = IDirectDrawSurface_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_HIDE, NULL);
9510 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
9512 IDirectDrawSurface_Release(offscreen);
9513 IDirectDrawSurface_Release(primary);
9514 IDirectDrawSurface_Release(overlay);
9515 done:
9516 IDirectDraw2_Release(ddraw);
9517 DestroyWindow(window);
9520 static void test_overlay_rect(void)
9522 IDirectDrawSurface *overlay, *primary;
9523 DDSURFACEDESC surface_desc;
9524 RECT rect = {0, 0, 64, 64};
9525 IDirectDraw2 *ddraw;
9526 LONG pos_x, pos_y;
9527 HRESULT hr, hr2;
9528 HWND window;
9529 HDC dc;
9531 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9532 0, 0, 640, 480, 0, 0, 0, 0);
9533 ddraw = create_ddraw();
9534 ok(!!ddraw, "Failed to create a ddraw object.\n");
9535 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9536 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9538 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
9540 skip("Failed to create a UYVY overlay, skipping test.\n");
9541 goto done;
9544 memset(&surface_desc, 0, sizeof(surface_desc));
9545 surface_desc.dwSize = sizeof(surface_desc);
9546 surface_desc.dwFlags = DDSD_CAPS;
9547 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
9548 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
9549 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
9551 /* On Windows 7, and probably Vista, UpdateOverlay() will return
9552 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
9553 * surface prevents this by disabling the dwm. */
9554 hr = IDirectDrawSurface_GetDC(primary, &dc);
9555 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
9556 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
9557 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9559 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is
9560 * used. This is not true in Windows Vista and earlier, but changed in
9561 * Windows 7. */
9562 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
9563 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
9564 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
9565 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
9566 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
9567 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9569 /* Show that the overlay position is the (top, left) coordinate of the
9570 * destination rectangle. */
9571 OffsetRect(&rect, 32, 16);
9572 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
9573 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
9574 pos_x = -1; pos_y = -1;
9575 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
9576 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
9577 ok(pos_x == rect.left, "Got unexpected pos_x %d, expected %d.\n", pos_x, rect.left);
9578 ok(pos_y == rect.top, "Got unexpected pos_y %d, expected %d.\n", pos_y, rect.top);
9580 /* Passing a NULL dest rect sets the position to 0/0. Visually it can be
9581 * seen that the overlay overlays the whole primary(==screen). */
9582 hr2 = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
9583 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS || hr2 == DDERR_OUTOFCAPS, "Got unexpected hr %#x.\n", hr2);
9584 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
9585 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
9586 if (SUCCEEDED(hr2))
9588 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
9589 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
9591 else
9593 ok(pos_x == 32, "Got unexpected pos_x %d.\n", pos_x);
9594 ok(pos_y == 16, "Got unexpected pos_y %d.\n", pos_y);
9597 /* The position cannot be retrieved when the overlay is not shown. */
9598 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
9599 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
9600 pos_x = -1; pos_y = -1;
9601 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
9602 ok(hr == DDERR_OVERLAYNOTVISIBLE, "Got unexpected hr %#x.\n", hr);
9603 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
9604 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
9606 IDirectDrawSurface_Release(primary);
9607 IDirectDrawSurface_Release(overlay);
9608 done:
9609 IDirectDraw2_Release(ddraw);
9610 DestroyWindow(window);
9613 START_TEST(ddraw2)
9615 IDirectDraw2 *ddraw;
9616 DEVMODEW current_mode;
9618 if (!(ddraw = create_ddraw()))
9620 skip("Failed to create a ddraw object, skipping tests.\n");
9621 return;
9623 IDirectDraw2_Release(ddraw);
9625 memset(&current_mode, 0, sizeof(current_mode));
9626 current_mode.dmSize = sizeof(current_mode);
9627 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
9628 registry_mode.dmSize = sizeof(registry_mode);
9629 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
9630 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
9631 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
9633 skip("Current mode does not match registry mode, skipping test.\n");
9634 return;
9637 test_coop_level_create_device_window();
9638 test_clipper_blt();
9639 test_coop_level_d3d_state();
9640 test_surface_interface_mismatch();
9641 test_coop_level_threaded();
9642 test_depth_blit();
9643 test_texture_load_ckey();
9644 test_viewport();
9645 test_zenable();
9646 test_ck_rgba();
9647 test_ck_default();
9648 test_ck_complex();
9649 test_surface_qi();
9650 test_device_qi();
9651 test_wndproc();
9652 test_window_style();
9653 test_redundant_mode_set();
9654 test_coop_level_mode_set();
9655 test_coop_level_mode_set_multi();
9656 test_initialize();
9657 test_coop_level_surf_create();
9658 test_coop_level_multi_window();
9659 test_clear_rect_count();
9660 test_coop_level_versions();
9661 test_lighting_interface_versions();
9662 test_coop_level_activateapp();
9663 test_unsupported_formats();
9664 test_rt_caps();
9665 test_primary_caps();
9666 test_surface_lock();
9667 test_surface_discard();
9668 test_flip();
9669 test_set_surface_desc();
9670 test_user_memory_getdc();
9671 test_sysmem_overlay();
9672 test_primary_palette();
9673 test_surface_attachment();
9674 test_pixel_format();
9675 test_create_surface_pitch();
9676 test_mipmap();
9677 test_palette_complex();
9678 test_p8_rgb_blit();
9679 test_material();
9680 test_lighting();
9681 test_specular_lighting();
9682 test_palette_gdi();
9683 test_palette_alpha();
9684 test_lost_device();
9685 test_surface_desc_lock();
9686 test_texturemapblend();
9687 test_viewport_clear_rect();
9688 test_color_fill();
9689 test_colorkey_precision();
9690 test_range_colorkey();
9691 test_shademode();
9692 test_lockrect_invalid();
9693 test_yv12_overlay();
9694 test_offscreen_overlay();
9695 test_overlay_rect();