ddraw: Return early in d3d_device7_DrawIndexedPrimitive() with a 0 vertex or index...
[wine.git] / dlls / ddraw / tests / ddraw2.c
blobd11cb2a4577f5de1edc83e61c9d3db2895f9e057
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 *frontbuffer, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
4804 DDSCAPS caps = {DDSCAPS_FLIP};
4805 DDSURFACEDESC surface_desc;
4806 BOOL sysmem_primary;
4807 IDirectDraw2 *ddraw;
4808 DWORD expected_caps;
4809 unsigned int i;
4810 D3DCOLOR color;
4811 ULONG refcount;
4812 HWND window;
4813 DDBLTFX fx;
4814 HRESULT hr;
4816 static const struct
4818 const char *name;
4819 DWORD caps;
4821 test_data[] =
4823 {"PRIMARYSURFACE", DDSCAPS_PRIMARYSURFACE},
4824 {"OFFSCREENPLAIN", DDSCAPS_OFFSCREENPLAIN},
4825 {"TEXTURE", DDSCAPS_TEXTURE},
4828 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4829 0, 0, 640, 480, 0, 0, 0, 0);
4830 ddraw = create_ddraw();
4831 ok(!!ddraw, "Failed to create a ddraw object.\n");
4833 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4834 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4836 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
4838 memset(&surface_desc, 0, sizeof(surface_desc));
4839 surface_desc.dwSize = sizeof(surface_desc);
4840 surface_desc.dwFlags = DDSD_CAPS;
4841 if (!(test_data[i].caps & DDSCAPS_PRIMARYSURFACE))
4842 surface_desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
4843 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
4844 surface_desc.dwWidth = 512;
4845 surface_desc.dwHeight = 512;
4846 surface_desc.dwBackBufferCount = 3;
4847 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
4848 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4850 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
4851 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
4852 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
4853 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4855 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
4856 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
4857 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
4858 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4860 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
4861 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
4862 todo_wine_if(test_data[i].caps & DDSCAPS_TEXTURE)
4863 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
4864 if (FAILED(hr))
4865 continue;
4867 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
4868 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
4869 hr = IDirectDrawSurface_IsLost(frontbuffer);
4870 ok(hr == DD_OK, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4871 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
4872 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
4873 ok(hr == DDERR_NOEXCLUSIVEMODE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4874 else
4875 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
4876 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4877 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
4878 hr = IDirectDrawSurface_IsLost(frontbuffer);
4879 todo_wine ok(hr == DDERR_SURFACELOST, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4880 hr = restore_surfaces(ddraw);
4881 ok(SUCCEEDED(hr), "%s: Failed to restore surfaces, hr %#x.\n", test_data[i].name, hr);
4883 memset(&surface_desc, 0, sizeof(surface_desc));
4884 surface_desc.dwSize = sizeof(surface_desc);
4885 hr = IDirectDrawSurface_GetSurfaceDesc(frontbuffer, &surface_desc);
4886 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
4887 expected_caps = DDSCAPS_FRONTBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
4888 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
4889 expected_caps |= DDSCAPS_VISIBLE;
4890 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
4891 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
4892 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
4894 hr = IDirectDrawSurface_GetAttachedSurface(frontbuffer, &caps, &backbuffer1);
4895 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
4896 memset(&surface_desc, 0, sizeof(surface_desc));
4897 surface_desc.dwSize = sizeof(surface_desc);
4898 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer1, &surface_desc);
4899 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
4900 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
4901 test_data[i].name, surface_desc.dwBackBufferCount);
4902 expected_caps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER);
4903 expected_caps |= DDSCAPS_BACKBUFFER;
4904 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
4905 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
4907 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
4908 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
4909 memset(&surface_desc, 0, sizeof(surface_desc));
4910 surface_desc.dwSize = sizeof(surface_desc);
4911 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer2, &surface_desc);
4912 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
4913 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
4914 test_data[i].name, surface_desc.dwBackBufferCount);
4915 expected_caps &= ~DDSCAPS_BACKBUFFER;
4916 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
4917 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
4919 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
4920 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
4921 memset(&surface_desc, 0, sizeof(surface_desc));
4922 surface_desc.dwSize = sizeof(surface_desc);
4923 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer3, &surface_desc);
4924 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
4925 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
4926 test_data[i].name, surface_desc.dwBackBufferCount);
4927 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
4928 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
4930 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer3, &caps, &surface);
4931 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
4932 ok(surface == frontbuffer, "%s: Got unexpected surface %p, expected %p.\n",
4933 test_data[i].name, surface, frontbuffer);
4934 IDirectDrawSurface_Release(surface);
4936 memset(&surface_desc, 0, sizeof(surface_desc));
4937 surface_desc.dwSize = sizeof(surface_desc);
4938 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4939 surface_desc.ddsCaps.dwCaps = 0;
4940 surface_desc.dwWidth = 640;
4941 surface_desc.dwHeight = 480;
4942 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4943 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
4944 hr = IDirectDrawSurface_Flip(frontbuffer, surface, DDFLIP_WAIT);
4945 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4946 IDirectDrawSurface_Release(surface);
4948 hr = IDirectDrawSurface_Flip(frontbuffer, frontbuffer, DDFLIP_WAIT);
4949 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4950 hr = IDirectDrawSurface_Flip(backbuffer1, NULL, DDFLIP_WAIT);
4951 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4952 hr = IDirectDrawSurface_Flip(backbuffer2, NULL, DDFLIP_WAIT);
4953 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4954 hr = IDirectDrawSurface_Flip(backbuffer3, NULL, DDFLIP_WAIT);
4955 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4957 memset(&fx, 0, sizeof(fx));
4958 fx.dwSize = sizeof(fx);
4959 U5(fx).dwFillColor = 0xffff0000;
4960 hr = IDirectDrawSurface_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4961 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4962 U5(fx).dwFillColor = 0xff00ff00;
4963 hr = IDirectDrawSurface_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4964 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4965 U5(fx).dwFillColor = 0xff0000ff;
4966 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4967 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4969 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
4970 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
4971 color = get_surface_color(backbuffer1, 320, 240);
4972 /* The testbot seems to just copy the contents of one surface to all the
4973 * others, instead of properly flipping. */
4974 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
4975 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4976 color = get_surface_color(backbuffer2, 320, 240);
4977 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4978 U5(fx).dwFillColor = 0xffff0000;
4979 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4980 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4982 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
4983 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
4984 color = get_surface_color(backbuffer1, 320, 240);
4985 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
4986 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4987 color = get_surface_color(backbuffer2, 320, 240);
4988 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4989 U5(fx).dwFillColor = 0xff00ff00;
4990 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4991 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4993 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
4994 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
4995 color = get_surface_color(backbuffer1, 320, 240);
4996 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
4997 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4998 color = get_surface_color(backbuffer2, 320, 240);
4999 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5000 U5(fx).dwFillColor = 0xff0000ff;
5001 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5002 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
5004 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer1, DDFLIP_WAIT);
5005 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
5006 color = get_surface_color(backbuffer2, 320, 240);
5007 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
5008 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5009 color = get_surface_color(backbuffer3, 320, 240);
5010 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5011 U5(fx).dwFillColor = 0xffff0000;
5012 hr = IDirectDrawSurface_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5013 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
5015 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer2, DDFLIP_WAIT);
5016 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
5017 color = get_surface_color(backbuffer1, 320, 240);
5018 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5019 color = get_surface_color(backbuffer3, 320, 240);
5020 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
5021 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5022 U5(fx).dwFillColor = 0xff00ff00;
5023 hr = IDirectDrawSurface_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5024 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
5026 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer3, DDFLIP_WAIT);
5027 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
5028 color = get_surface_color(backbuffer1, 320, 240);
5029 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
5030 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5031 color = get_surface_color(backbuffer2, 320, 240);
5032 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5034 IDirectDrawSurface_Release(backbuffer3);
5035 IDirectDrawSurface_Release(backbuffer2);
5036 IDirectDrawSurface_Release(backbuffer1);
5037 IDirectDrawSurface_Release(frontbuffer);
5040 refcount = IDirectDraw2_Release(ddraw);
5041 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5042 DestroyWindow(window);
5045 static void reset_ddsd(DDSURFACEDESC *ddsd)
5047 memset(ddsd, 0, sizeof(*ddsd));
5048 ddsd->dwSize = sizeof(*ddsd);
5051 static void test_set_surface_desc(void)
5053 IDirectDraw2 *ddraw;
5054 HWND window;
5055 HRESULT hr;
5056 DDSURFACEDESC ddsd;
5057 IDirectDrawSurface *surface;
5058 IDirectDrawSurface3 *surface3;
5059 BYTE data[16*16*4];
5060 ULONG ref;
5061 unsigned int i;
5062 static const struct
5064 DWORD caps;
5065 BOOL supported;
5066 const char *name;
5068 invalid_caps_tests[] =
5070 {DDSCAPS_VIDEOMEMORY, FALSE, "videomemory plain"},
5071 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, TRUE, "systemmemory texture"},
5072 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, FALSE, "systemmemory primary"},
5075 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5076 0, 0, 640, 480, 0, 0, 0, 0);
5077 ddraw = create_ddraw();
5078 ok(!!ddraw, "Failed to create a ddraw object.\n");
5079 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5080 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5082 reset_ddsd(&ddsd);
5083 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
5084 ddsd.dwWidth = 8;
5085 ddsd.dwHeight = 8;
5086 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5087 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5088 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
5089 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5090 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5091 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5092 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
5094 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
5095 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5097 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
5098 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface3 interface, hr %#x.\n", hr);
5099 IDirectDrawSurface_Release(surface);
5101 reset_ddsd(&ddsd);
5102 ddsd.dwFlags = DDSD_LPSURFACE;
5103 ddsd.lpSurface = data;
5104 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5105 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5107 /* Redundantly setting the same lpSurface is not an error. */
5108 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5109 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5110 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
5111 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5112 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
5113 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
5115 hr = IDirectDrawSurface3_Lock(surface3, NULL, &ddsd, 0, NULL);
5116 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5117 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
5118 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
5119 hr = IDirectDrawSurface3_Unlock(surface3, NULL);
5120 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5122 reset_ddsd(&ddsd);
5123 ddsd.dwFlags = DDSD_LPSURFACE;
5124 ddsd.lpSurface = data;
5125 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 1);
5126 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
5128 ddsd.lpSurface = NULL;
5129 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5130 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
5132 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, NULL, 0);
5133 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
5135 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
5136 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5137 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
5138 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
5140 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
5141 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5142 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
5144 ddsd.dwFlags = DDSD_CAPS;
5145 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5146 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
5148 /* dwCaps = 0 is allowed, but ignored. */
5149 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
5150 ddsd.lpSurface = data;
5151 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5152 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
5153 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
5154 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5155 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
5156 ddsd.ddsCaps.dwCaps = 0;
5157 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5158 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5160 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
5161 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5162 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
5163 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
5165 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
5166 reset_ddsd(&ddsd);
5167 ddsd.dwFlags = DDSD_HEIGHT;
5168 ddsd.dwHeight = 16;
5169 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5170 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
5172 ddsd.lpSurface = data;
5173 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
5174 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5175 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5177 ddsd.dwHeight = 0;
5178 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5179 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
5181 reset_ddsd(&ddsd);
5182 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
5183 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
5184 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
5185 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
5187 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0. */
5188 reset_ddsd(&ddsd);
5189 ddsd.dwFlags = DDSD_PITCH;
5190 U1(ddsd).lPitch = 8 * 4;
5191 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5192 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
5194 ddsd.dwFlags = DDSD_WIDTH;
5195 ddsd.dwWidth = 16;
5196 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5197 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
5199 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
5200 ddsd.lpSurface = data;
5201 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5202 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
5204 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
5205 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5206 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
5208 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5209 U1(ddsd).lPitch = 16 * 4;
5210 ddsd.dwWidth = 16;
5211 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5212 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5214 reset_ddsd(&ddsd);
5215 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
5216 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5217 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
5218 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
5219 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
5221 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
5223 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
5224 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5225 U1(ddsd).lPitch = 4 * 4;
5226 ddsd.lpSurface = data;
5227 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5228 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
5230 U1(ddsd).lPitch = 4;
5231 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5232 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
5234 U1(ddsd).lPitch = 16 * 4 + 1;
5235 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5236 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
5238 U1(ddsd).lPitch = 16 * 4 + 3;
5239 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5240 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
5242 U1(ddsd).lPitch = -4;
5243 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5244 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
5246 U1(ddsd).lPitch = 16 * 4;
5247 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5248 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5250 reset_ddsd(&ddsd);
5251 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5252 U1(ddsd).lPitch = 0;
5253 ddsd.dwWidth = 16;
5254 ddsd.lpSurface = data;
5255 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5256 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
5258 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5259 U1(ddsd).lPitch = 16 * 4;
5260 ddsd.dwWidth = 0;
5261 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5262 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
5264 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
5265 ddsd.dwFlags = DDSD_PIXELFORMAT;
5266 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5267 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5268 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
5269 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5270 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5271 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5272 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5273 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
5275 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
5276 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5277 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5279 /* Can't set color keys. */
5280 reset_ddsd(&ddsd);
5281 ddsd.dwFlags = DDSD_CKSRCBLT;
5282 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
5283 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
5284 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5285 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
5287 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
5288 ddsd.lpSurface = data;
5289 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5290 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
5292 IDirectDrawSurface3_Release(surface3);
5294 /* SetSurfaceDesc needs systemmemory surfaces.
5296 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing DDSD_LINEARSIZE is moot. */
5297 for (i = 0; i < sizeof(invalid_caps_tests) / sizeof(*invalid_caps_tests); i++)
5299 reset_ddsd(&ddsd);
5300 ddsd.dwFlags = DDSD_CAPS;
5301 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
5302 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
5304 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5305 ddsd.dwWidth = 8;
5306 ddsd.dwHeight = 8;
5307 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5308 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5309 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
5310 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5311 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5312 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5315 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
5316 ok(SUCCEEDED(hr) || hr == DDERR_NODIRECTDRAWHW, "Failed to create surface, hr %#x.\n", hr);
5317 if (FAILED(hr))
5319 skip("Cannot create a %s surface, skipping vidmem SetSurfaceDesc test.\n",
5320 invalid_caps_tests[i].name);
5321 goto done;
5323 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
5324 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface3 interface, hr %#x.\n", hr);
5325 IDirectDrawSurface_Release(surface);
5327 reset_ddsd(&ddsd);
5328 ddsd.dwFlags = DDSD_LPSURFACE;
5329 ddsd.lpSurface = data;
5330 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5331 if (invalid_caps_tests[i].supported)
5333 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5335 else
5337 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
5338 invalid_caps_tests[i].name, hr);
5340 /* Check priority of error conditions. */
5341 ddsd.dwFlags = DDSD_WIDTH;
5342 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5343 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
5344 invalid_caps_tests[i].name, hr);
5347 IDirectDrawSurface3_Release(surface3);
5350 done:
5351 ref = IDirectDraw2_Release(ddraw);
5352 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
5353 DestroyWindow(window);
5356 static void test_user_memory_getdc(void)
5358 IDirectDraw2 *ddraw;
5359 HWND window;
5360 HRESULT hr;
5361 DDSURFACEDESC ddsd;
5362 IDirectDrawSurface *surface;
5363 IDirectDrawSurface3 *surface3;
5364 DWORD data[16][16];
5365 HBITMAP bitmap;
5366 DIBSECTION dib;
5367 ULONG ref;
5368 int size;
5369 HDC dc;
5370 unsigned int x, y;
5372 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5373 0, 0, 640, 480, 0, 0, 0, 0);
5374 ddraw = create_ddraw();
5375 ok(!!ddraw, "Failed to create a ddraw object.\n");
5377 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5378 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5380 reset_ddsd(&ddsd);
5381 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
5382 ddsd.dwWidth = 16;
5383 ddsd.dwHeight = 16;
5384 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5385 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5386 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
5387 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5388 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5389 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5390 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
5391 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
5392 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5394 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
5395 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface3 interface, hr %#x.\n", hr);
5396 IDirectDrawSurface_Release(surface);
5398 memset(data, 0xaa, sizeof(data));
5399 reset_ddsd(&ddsd);
5400 ddsd.dwFlags = DDSD_LPSURFACE;
5401 ddsd.lpSurface = data;
5402 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5403 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5405 hr = IDirectDrawSurface3_GetDC(surface3, &dc);
5406 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
5407 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
5408 ok(!!bitmap, "Failed to get bitmap.\n");
5409 size = GetObjectA(bitmap, sizeof(dib), &dib);
5410 ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
5411 ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
5412 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
5413 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
5414 hr = IDirectDrawSurface3_ReleaseDC(surface3, dc);
5415 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
5417 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
5418 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
5420 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
5421 ddsd.lpSurface = data;
5422 ddsd.dwWidth = 4;
5423 ddsd.dwHeight = 8;
5424 U1(ddsd).lPitch = sizeof(*data);
5425 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5426 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5428 memset(data, 0xaa, sizeof(data));
5429 hr = IDirectDrawSurface3_GetDC(surface3, &dc);
5430 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
5431 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
5432 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
5433 hr = IDirectDrawSurface3_ReleaseDC(surface3, dc);
5434 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
5436 for (y = 0; y < 4; y++)
5438 for (x = 0; x < 4; x++)
5440 if ((x == 1 || x == 2) && (y == 1 || y == 2))
5441 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
5442 x, y, data[y][x]);
5443 else
5444 ok(data[y][x] == 0x00000000, "Expected color 0xaaaaaaaa on position %ux%u, got %#x.\n",
5445 x, y, data[y][x]);
5448 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
5449 data[0][5]);
5450 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
5451 data[7][3]);
5452 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
5453 data[7][4]);
5454 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
5455 data[8][0]);
5457 IDirectDrawSurface3_Release(surface3);
5458 ref = IDirectDraw2_Release(ddraw);
5459 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
5460 DestroyWindow(window);
5463 static void test_sysmem_overlay(void)
5465 IDirectDraw2 *ddraw;
5466 HWND window;
5467 HRESULT hr;
5468 DDSURFACEDESC ddsd;
5469 IDirectDrawSurface *surface;
5470 ULONG ref;
5472 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5473 0, 0, 640, 480, 0, 0, 0, 0);
5474 ddraw = create_ddraw();
5475 ok(!!ddraw, "Failed to create a ddraw object.\n");
5477 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5478 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5480 reset_ddsd(&ddsd);
5481 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
5482 ddsd.dwWidth = 16;
5483 ddsd.dwHeight = 16;
5484 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
5485 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5486 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5487 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
5488 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5489 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5490 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5491 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
5492 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
5494 ref = IDirectDraw2_Release(ddraw);
5495 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
5496 DestroyWindow(window);
5499 static void test_primary_palette(void)
5501 DDSCAPS surface_caps = {DDSCAPS_FLIP};
5502 IDirectDrawSurface *primary, *backbuffer;
5503 PALETTEENTRY palette_entries[256];
5504 IDirectDrawPalette *palette, *tmp;
5505 DDSURFACEDESC surface_desc;
5506 IDirectDraw2 *ddraw;
5507 DWORD palette_caps;
5508 ULONG refcount;
5509 HWND window;
5510 HRESULT hr;
5512 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5513 0, 0, 640, 480, 0, 0, 0, 0);
5514 ddraw = create_ddraw();
5515 ok(!!ddraw, "Failed to create a ddraw object.\n");
5516 if (FAILED(IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
5518 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
5519 IDirectDraw2_Release(ddraw);
5520 DestroyWindow(window);
5521 return;
5523 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5524 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5526 memset(&surface_desc, 0, sizeof(surface_desc));
5527 surface_desc.dwSize = sizeof(surface_desc);
5528 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
5529 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
5530 surface_desc.dwBackBufferCount = 1;
5531 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
5532 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5533 hr = IDirectDrawSurface_GetAttachedSurface(primary, &surface_caps, &backbuffer);
5534 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
5536 memset(palette_entries, 0, sizeof(palette_entries));
5537 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
5538 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5539 refcount = get_refcount((IUnknown *)palette);
5540 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5542 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
5543 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
5544 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
5546 hr = IDirectDrawSurface_SetPalette(primary, palette);
5547 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5549 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
5550 * and is generally somewhat broken with respect to 8 bpp / palette
5551 * handling. */
5552 if (SUCCEEDED(IDirectDrawSurface_GetPalette(backbuffer, &tmp)))
5554 win_skip("Broken palette handling detected, skipping tests.\n");
5555 IDirectDrawPalette_Release(tmp);
5556 IDirectDrawPalette_Release(palette);
5557 /* The Windows 8 testbot keeps extra references to the primary and
5558 * backbuffer while in 8 bpp mode. */
5559 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
5560 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
5561 goto done;
5564 refcount = get_refcount((IUnknown *)palette);
5565 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
5567 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
5568 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
5569 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
5570 "Got unexpected palette caps %#x.\n", palette_caps);
5572 hr = IDirectDrawSurface_SetPalette(primary, NULL);
5573 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5574 refcount = get_refcount((IUnknown *)palette);
5575 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5577 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
5578 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
5579 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
5581 hr = IDirectDrawSurface_SetPalette(primary, palette);
5582 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5583 refcount = get_refcount((IUnknown *)palette);
5584 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
5586 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
5587 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
5588 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
5589 IDirectDrawPalette_Release(tmp);
5590 hr = IDirectDrawSurface_GetPalette(backbuffer, &tmp);
5591 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
5593 refcount = IDirectDrawPalette_Release(palette);
5594 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5595 refcount = IDirectDrawPalette_Release(palette);
5596 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5598 /* Note that this only seems to work when the palette is attached to the
5599 * primary surface. When attached to a regular surface, attempting to get
5600 * the palette here will cause an access violation. */
5601 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
5602 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
5604 done:
5605 refcount = IDirectDrawSurface_Release(backbuffer);
5606 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5607 refcount = IDirectDrawSurface_Release(primary);
5608 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5609 refcount = IDirectDraw2_Release(ddraw);
5610 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5611 DestroyWindow(window);
5614 static HRESULT WINAPI surface_counter(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
5616 UINT *surface_count = context;
5618 ++(*surface_count);
5619 IDirectDrawSurface_Release(surface);
5621 return DDENUMRET_OK;
5624 static void test_surface_attachment(void)
5626 IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
5627 DDSCAPS caps = {DDSCAPS_TEXTURE};
5628 DDSURFACEDESC surface_desc;
5629 IDirectDraw2 *ddraw;
5630 UINT surface_count;
5631 ULONG refcount;
5632 HWND window;
5633 HRESULT hr;
5635 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5636 0, 0, 640, 480, 0, 0, 0, 0);
5637 ddraw = create_ddraw();
5638 ok(!!ddraw, "Failed to create a ddraw object.\n");
5639 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5640 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5642 memset(&surface_desc, 0, sizeof(surface_desc));
5643 surface_desc.dwSize = sizeof(surface_desc);
5644 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
5645 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
5646 U2(surface_desc).dwMipMapCount = 3;
5647 surface_desc.dwWidth = 128;
5648 surface_desc.dwHeight = 128;
5649 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
5650 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5652 hr = IDirectDrawSurface_GetAttachedSurface(surface1, &caps, &surface2);
5653 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
5654 hr = IDirectDrawSurface_GetAttachedSurface(surface2, &caps, &surface3);
5655 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
5656 hr = IDirectDrawSurface_GetAttachedSurface(surface3, &caps, &surface4);
5657 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5659 surface_count = 0;
5660 IDirectDrawSurface_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
5661 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
5662 surface_count = 0;
5663 IDirectDrawSurface_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
5664 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
5665 surface_count = 0;
5666 IDirectDrawSurface_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
5667 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
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_TEXTURE;
5673 surface_desc.dwWidth = 16;
5674 surface_desc.dwHeight = 16;
5675 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
5676 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5678 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
5679 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5680 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
5681 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5682 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
5683 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5684 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
5685 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5686 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
5687 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5688 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
5689 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5691 IDirectDrawSurface_Release(surface4);
5693 memset(&surface_desc, 0, sizeof(surface_desc));
5694 surface_desc.dwSize = sizeof(surface_desc);
5695 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5696 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
5697 surface_desc.dwWidth = 16;
5698 surface_desc.dwHeight = 16;
5699 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
5700 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5702 if (SUCCEEDED(hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4)))
5704 skip("Running on refrast, skipping some tests.\n");
5705 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface4);
5706 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5708 else
5710 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5711 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
5712 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5713 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
5714 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5715 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
5716 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5717 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
5718 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5719 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
5720 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 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5729 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5731 /* Try a single primary and two offscreen plain surfaces. */
5732 memset(&surface_desc, 0, sizeof(surface_desc));
5733 surface_desc.dwSize = sizeof(surface_desc);
5734 surface_desc.dwFlags = DDSD_CAPS;
5735 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
5736 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
5737 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5739 memset(&surface_desc, 0, sizeof(surface_desc));
5740 surface_desc.dwSize = sizeof(surface_desc);
5741 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5742 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5743 surface_desc.dwWidth = registry_mode.dmPelsWidth;
5744 surface_desc.dwHeight = registry_mode.dmPelsHeight;
5745 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
5746 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5748 memset(&surface_desc, 0, sizeof(surface_desc));
5749 surface_desc.dwSize = sizeof(surface_desc);
5750 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5751 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5752 surface_desc.dwWidth = registry_mode.dmPelsWidth;
5753 surface_desc.dwHeight = registry_mode.dmPelsHeight;
5754 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
5755 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5757 /* This one has a different size. */
5758 memset(&surface_desc, 0, sizeof(surface_desc));
5759 surface_desc.dwSize = sizeof(surface_desc);
5760 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5761 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5762 surface_desc.dwWidth = 128;
5763 surface_desc.dwHeight = 128;
5764 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
5765 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5767 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5768 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5769 /* Try the reverse without detaching first. */
5770 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
5771 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
5772 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
5773 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5775 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
5776 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5777 /* Try to detach reversed. */
5778 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
5779 ok(hr == DDERR_CANNOTDETACHSURFACE, "Got unexpected hr %#x.\n", hr);
5780 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
5781 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5783 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
5784 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5785 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
5786 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5788 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
5789 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5790 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
5791 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5793 IDirectDrawSurface_Release(surface4);
5794 IDirectDrawSurface_Release(surface3);
5795 IDirectDrawSurface_Release(surface2);
5796 IDirectDrawSurface_Release(surface1);
5798 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
5799 memset(&surface_desc, 0, sizeof(surface_desc));
5800 surface_desc.dwSize = sizeof(surface_desc);
5801 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5802 surface_desc.dwWidth = 64;
5803 surface_desc.dwHeight = 64;
5804 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5805 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
5806 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
5807 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
5808 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xf800;
5809 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x07e0;
5810 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x001f;
5811 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
5812 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5813 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
5814 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5816 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
5817 surface_desc.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
5818 U1(surface_desc.ddpfPixelFormat).dwZBufferBitDepth = 16;
5819 U3(surface_desc.ddpfPixelFormat).dwZBitMask = 0x0000ffff;
5820 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
5821 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5823 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5824 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5825 refcount = get_refcount((IUnknown *)surface2);
5826 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
5827 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5828 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
5830 /* Attaching while already attached to other surface. */
5831 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface2);
5832 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5833 hr = IDirectDrawSurface_DeleteAttachedSurface(surface3, 0, surface2);
5834 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5835 IDirectDrawSurface_Release(surface3);
5837 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
5838 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5839 refcount = get_refcount((IUnknown *)surface2);
5840 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5842 /* Automatic detachment on release. */
5843 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5844 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5845 refcount = get_refcount((IUnknown *)surface2);
5846 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
5847 refcount = IDirectDrawSurface_Release(surface1);
5848 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5849 refcount = IDirectDrawSurface_Release(surface2);
5850 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5851 refcount = IDirectDraw2_Release(ddraw);
5852 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5853 DestroyWindow(window);
5856 static void test_pixel_format(void)
5858 HWND window, window2 = NULL;
5859 HDC hdc, hdc2 = NULL;
5860 HMODULE gl = NULL;
5861 int format, test_format;
5862 PIXELFORMATDESCRIPTOR pfd;
5863 IDirectDraw2 *ddraw = NULL;
5864 IDirectDrawClipper *clipper = NULL;
5865 DDSURFACEDESC ddsd;
5866 IDirectDrawSurface *primary = NULL;
5867 DDBLTFX fx;
5868 HRESULT hr;
5870 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5871 100, 100, 160, 160, NULL, NULL, NULL, NULL);
5872 if (!window)
5874 skip("Failed to create window\n");
5875 return;
5878 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5879 100, 100, 160, 160, NULL, NULL, NULL, NULL);
5881 hdc = GetDC(window);
5882 if (!hdc)
5884 skip("Failed to get DC\n");
5885 goto cleanup;
5888 if (window2)
5889 hdc2 = GetDC(window2);
5891 gl = LoadLibraryA("opengl32.dll");
5892 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
5894 format = GetPixelFormat(hdc);
5895 ok(format == 0, "new window has pixel format %d\n", format);
5897 ZeroMemory(&pfd, sizeof(pfd));
5898 pfd.nSize = sizeof(pfd);
5899 pfd.nVersion = 1;
5900 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
5901 pfd.iPixelType = PFD_TYPE_RGBA;
5902 pfd.iLayerType = PFD_MAIN_PLANE;
5903 format = ChoosePixelFormat(hdc, &pfd);
5904 if (format <= 0)
5906 skip("no pixel format available\n");
5907 goto cleanup;
5910 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
5912 skip("failed to set pixel format\n");
5913 goto cleanup;
5916 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
5918 skip("failed to set pixel format on second window\n");
5919 if (hdc2)
5921 ReleaseDC(window2, hdc2);
5922 hdc2 = NULL;
5926 ddraw = create_ddraw();
5927 ok(!!ddraw, "Failed to create a ddraw object.\n");
5929 test_format = GetPixelFormat(hdc);
5930 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5932 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5933 if (FAILED(hr))
5935 skip("Failed to set cooperative level, hr %#x.\n", hr);
5936 goto cleanup;
5939 test_format = GetPixelFormat(hdc);
5940 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5942 if (hdc2)
5944 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
5945 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
5946 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
5947 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
5949 test_format = GetPixelFormat(hdc);
5950 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5952 test_format = GetPixelFormat(hdc2);
5953 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
5956 memset(&ddsd, 0, sizeof(ddsd));
5957 ddsd.dwSize = sizeof(ddsd);
5958 ddsd.dwFlags = DDSD_CAPS;
5959 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
5961 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
5962 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
5964 test_format = GetPixelFormat(hdc);
5965 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5967 if (hdc2)
5969 test_format = GetPixelFormat(hdc2);
5970 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
5973 if (clipper)
5975 hr = IDirectDrawSurface2_SetClipper(primary, clipper);
5976 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
5978 test_format = GetPixelFormat(hdc);
5979 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5981 test_format = GetPixelFormat(hdc2);
5982 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
5985 memset(&fx, 0, sizeof(fx));
5986 fx.dwSize = sizeof(fx);
5987 hr = IDirectDrawSurface2_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5988 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
5990 test_format = GetPixelFormat(hdc);
5991 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5993 if (hdc2)
5995 test_format = GetPixelFormat(hdc2);
5996 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
5999 cleanup:
6000 if (primary) IDirectDrawSurface2_Release(primary);
6001 if (clipper) IDirectDrawClipper_Release(clipper);
6002 if (ddraw) IDirectDraw2_Release(ddraw);
6003 if (gl) FreeLibrary(gl);
6004 if (hdc) ReleaseDC(window, hdc);
6005 if (hdc2) ReleaseDC(window2, hdc2);
6006 if (window) DestroyWindow(window);
6007 if (window2) DestroyWindow(window2);
6010 static void test_create_surface_pitch(void)
6012 IDirectDrawSurface *surface;
6013 DDSURFACEDESC surface_desc;
6014 IDirectDraw2 *ddraw;
6015 unsigned int i;
6016 ULONG refcount;
6017 HWND window;
6018 HRESULT hr;
6019 void *mem;
6021 static const struct
6023 DWORD caps;
6024 DWORD flags_in;
6025 DWORD pitch_in;
6026 HRESULT hr;
6027 DWORD flags_out;
6028 DWORD pitch_out32;
6029 DWORD pitch_out64;
6031 test_data[] =
6033 /* 0 */
6034 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
6035 0, 0, DD_OK,
6036 DDSD_PITCH, 0x100, 0x100},
6037 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
6038 DDSD_PITCH, 0x104, DD_OK,
6039 DDSD_PITCH, 0x100, 0x100},
6040 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
6041 DDSD_PITCH, 0x0f8, DD_OK,
6042 DDSD_PITCH, 0x100, 0x100},
6043 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
6044 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
6045 0, 0, 0 },
6046 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6047 0, 0, DD_OK,
6048 DDSD_PITCH, 0x100, 0x0fc},
6049 /* 5 */
6050 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6051 DDSD_PITCH, 0x104, DD_OK,
6052 DDSD_PITCH, 0x100, 0x0fc},
6053 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6054 DDSD_PITCH, 0x0f8, DD_OK,
6055 DDSD_PITCH, 0x100, 0x0fc},
6056 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6057 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
6058 DDSD_PITCH, 0x100, 0x0fc},
6059 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6060 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
6061 0, 0, 0 },
6062 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6063 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDPARAMS,
6064 0, 0, 0 },
6065 /* 10 */
6066 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
6067 0, 0, DDERR_INVALIDCAPS,
6068 0, 0, 0 },
6069 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
6070 0, 0, DD_OK,
6071 DDSD_PITCH, 0x100, 0 },
6072 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
6073 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
6074 0, 0, 0 },
6075 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
6076 0, 0, DDERR_INVALIDCAPS,
6077 0, 0, 0 },
6078 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
6079 0, 0, DD_OK,
6080 DDSD_PITCH, 0x100, 0 },
6081 /* 15 */
6082 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
6083 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDPARAMS,
6084 0, 0, 0 },
6086 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
6088 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6089 0, 0, 640, 480, 0, 0, 0, 0);
6090 ddraw = create_ddraw();
6091 ok(!!ddraw, "Failed to create a ddraw object.\n");
6092 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6093 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6095 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
6097 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
6099 memset(&surface_desc, 0, sizeof(surface_desc));
6100 surface_desc.dwSize = sizeof(surface_desc);
6101 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
6102 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
6103 surface_desc.dwWidth = 63;
6104 surface_desc.dwHeight = 63;
6105 U1(surface_desc).lPitch = test_data[i].pitch_in;
6106 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6107 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
6108 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
6109 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6110 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6111 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
6112 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6113 if (test_data[i].flags_in & DDSD_LPSURFACE)
6115 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
6116 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, expected_hr);
6117 surface_desc.lpSurface = mem;
6118 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6120 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
6121 continue;
6122 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
6123 if (FAILED(hr))
6124 continue;
6126 memset(&surface_desc, 0, sizeof(surface_desc));
6127 surface_desc.dwSize = sizeof(surface_desc);
6128 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
6129 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
6130 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
6131 "Test %u: Got unexpected flags %#x, expected %#x.\n",
6132 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
6133 /* The pitch for textures seems to be implementation specific. */
6134 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
6136 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
6137 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
6138 "Test %u: Got unexpected pitch %u, expected %u.\n",
6139 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
6140 else
6141 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
6142 "Test %u: Got unexpected pitch %u, expected %u.\n",
6143 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
6145 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
6147 IDirectDrawSurface_Release(surface);
6150 HeapFree(GetProcessHeap(), 0, mem);
6151 refcount = IDirectDraw2_Release(ddraw);
6152 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6153 DestroyWindow(window);
6156 static void test_mipmap(void)
6158 IDirectDrawSurface *surface1;
6159 IDirectDrawSurface2 *surface, *surface2;
6160 DDSURFACEDESC surface_desc;
6161 IDirectDraw2 *ddraw;
6162 unsigned int i;
6163 ULONG refcount;
6164 HWND window;
6165 HRESULT hr;
6166 DDSCAPS caps = {DDSCAPS_COMPLEX};
6167 DDCAPS hal_caps;
6169 static const struct
6171 DWORD flags;
6172 DWORD caps;
6173 DWORD width;
6174 DWORD height;
6175 DWORD mipmap_count_in;
6176 HRESULT hr;
6177 DWORD mipmap_count_out;
6179 tests[] =
6181 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
6182 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS, 0},
6183 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
6184 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS, 0},
6185 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 6},
6186 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 6},
6189 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6190 0, 0, 640, 480, 0, 0, 0, 0);
6191 ddraw = create_ddraw();
6192 ok(!!ddraw, "Failed to create a ddraw object.\n");
6193 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6194 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6196 memset(&hal_caps, 0, sizeof(hal_caps));
6197 hal_caps.dwSize = sizeof(hal_caps);
6198 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
6199 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6200 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
6202 skip("Mipmapped textures not supported, skipping tests.\n");
6203 IDirectDraw2_Release(ddraw);
6204 DestroyWindow(window);
6205 return;
6208 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
6210 memset(&surface_desc, 0, sizeof(surface_desc));
6211 surface_desc.dwSize = sizeof(surface_desc);
6212 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
6213 surface_desc.ddsCaps.dwCaps = tests[i].caps;
6214 surface_desc.dwWidth = tests[i].width;
6215 surface_desc.dwHeight = tests[i].height;
6216 if (tests[i].flags & DDSD_MIPMAPCOUNT)
6217 U2(surface_desc).dwMipMapCount = tests[i].mipmap_count_in;
6218 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6219 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
6220 if (FAILED(hr))
6221 continue;
6223 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
6224 ok(SUCCEEDED(hr), "Test %u: Failed to get IDirectDrawSurface2 interface, hr %#x.\n", i, hr);
6225 IDirectDrawSurface_Release(surface1);
6227 memset(&surface_desc, 0, sizeof(surface_desc));
6228 surface_desc.dwSize = sizeof(surface_desc);
6229 hr = IDirectDrawSurface2_GetSurfaceDesc(surface, &surface_desc);
6230 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
6231 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
6232 "Test %u: Got unexpected flags %#x.\n", i, surface_desc.dwFlags);
6233 ok(U2(surface_desc).dwMipMapCount == tests[i].mipmap_count_out,
6234 "Test %u: Got unexpected mipmap count %u.\n", i, U2(surface_desc).dwMipMapCount);
6236 if (U2(surface_desc).dwMipMapCount > 1)
6238 hr = IDirectDrawSurface2_GetAttachedSurface(surface, &caps, &surface2);
6239 ok(SUCCEEDED(hr), "Test %u: Failed to get attached surface, hr %#x.\n", i, hr);
6241 memset(&surface_desc, 0, sizeof(surface_desc));
6242 surface_desc.dwSize = sizeof(surface_desc);
6243 hr = IDirectDrawSurface2_Lock(surface, NULL, &surface_desc, 0, NULL);
6244 ok(SUCCEEDED(hr), "Test %u: Failed to lock surface, hr %#x.\n", i, hr);
6245 memset(&surface_desc, 0, sizeof(surface_desc));
6246 surface_desc.dwSize = sizeof(surface_desc);
6247 hr = IDirectDrawSurface2_Lock(surface2, NULL, &surface_desc, 0, NULL);
6248 ok(SUCCEEDED(hr), "Test %u: Failed to lock surface, hr %#x.\n", i, hr);
6249 IDirectDrawSurface2_Unlock(surface2, NULL);
6250 IDirectDrawSurface2_Unlock(surface, NULL);
6252 IDirectDrawSurface2_Release(surface2);
6255 IDirectDrawSurface2_Release(surface);
6258 refcount = IDirectDraw2_Release(ddraw);
6259 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6260 DestroyWindow(window);
6263 static void test_palette_complex(void)
6265 IDirectDrawSurface *surface1;
6266 IDirectDrawSurface2 *surface, *mipmap, *tmp;
6267 DDSURFACEDESC surface_desc;
6268 IDirectDraw2 *ddraw;
6269 IDirectDrawPalette *palette, *palette2, *palette_mipmap;
6270 ULONG refcount;
6271 HWND window;
6272 HRESULT hr;
6273 DDSCAPS caps = {DDSCAPS_COMPLEX};
6274 DDCAPS hal_caps;
6275 PALETTEENTRY palette_entries[256];
6276 unsigned int i;
6277 HDC dc;
6278 RGBQUAD rgbquad;
6279 UINT count;
6281 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6282 0, 0, 640, 480, 0, 0, 0, 0);
6283 ddraw = create_ddraw();
6284 ok(!!ddraw, "Failed to create a ddraw object.\n");
6285 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6286 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6288 memset(&hal_caps, 0, sizeof(hal_caps));
6289 hal_caps.dwSize = sizeof(hal_caps);
6290 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
6291 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6292 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
6294 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
6295 IDirectDraw2_Release(ddraw);
6296 DestroyWindow(window);
6297 return;
6300 memset(&surface_desc, 0, sizeof(surface_desc));
6301 surface_desc.dwSize = sizeof(surface_desc);
6302 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6303 surface_desc.dwWidth = 128;
6304 surface_desc.dwHeight = 128;
6305 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
6306 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6307 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
6308 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
6309 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6310 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6311 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
6312 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface2 interface, hr %#x.\n", hr);
6313 IDirectDrawSurface_Release(surface1);
6315 memset(palette_entries, 0, sizeof(palette_entries));
6316 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
6317 palette_entries, &palette, NULL);
6318 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6320 memset(palette_entries, 0, sizeof(palette_entries));
6321 palette_entries[1].peRed = 0xff;
6322 palette_entries[1].peGreen = 0x80;
6323 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
6324 palette_entries, &palette_mipmap, NULL);
6325 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6327 palette2 = (void *)0xdeadbeef;
6328 hr = IDirectDrawSurface2_GetPalette(surface, &palette2);
6329 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6330 ok(!palette2, "Got unexpected palette %p.\n", palette2);
6331 hr = IDirectDrawSurface2_SetPalette(surface, palette);
6332 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6333 hr = IDirectDrawSurface2_GetPalette(surface, &palette2);
6334 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
6335 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
6336 IDirectDrawPalette_Release(palette2);
6338 mipmap = surface;
6339 IDirectDrawSurface2_AddRef(mipmap);
6340 for (i = 0; i < 7; ++i)
6342 hr = IDirectDrawSurface2_GetAttachedSurface(mipmap, &caps, &tmp);
6343 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
6344 palette2 = (void *)0xdeadbeef;
6345 hr = IDirectDrawSurface2_GetPalette(tmp, &palette2);
6346 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
6347 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
6349 hr = IDirectDrawSurface2_SetPalette(tmp, palette_mipmap);
6350 ok(SUCCEEDED(hr), "Failed to set palette, i %u, hr %#x.\n", i, hr);
6352 hr = IDirectDrawSurface2_GetPalette(tmp, &palette2);
6353 ok(SUCCEEDED(hr), "Failed to get palette, i %u, hr %#x.\n", i, hr);
6354 ok(palette_mipmap == palette2, "Got unexpected palette %p.\n", palette2);
6355 IDirectDrawPalette_Release(palette2);
6357 hr = IDirectDrawSurface2_GetDC(tmp, &dc);
6358 ok(SUCCEEDED(hr), "Failed to get DC, i %u, hr %#x.\n", i, hr);
6359 count = GetDIBColorTable(dc, 1, 1, &rgbquad);
6360 ok(count == 1, "Expected count 1, got %u.\n", count);
6361 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x.\n", rgbquad.rgbRed);
6362 ok(rgbquad.rgbGreen == 0x80, "Expected rgbGreen = 0x80, got %#x.\n", rgbquad.rgbGreen);
6363 ok(rgbquad.rgbBlue == 0x0, "Expected rgbBlue = 0x0, got %#x.\n", rgbquad.rgbBlue);
6364 hr = IDirectDrawSurface2_ReleaseDC(tmp, dc);
6365 ok(SUCCEEDED(hr), "Failed to release DC, i %u, hr %#x.\n", i, hr);
6367 IDirectDrawSurface2_Release(mipmap);
6368 mipmap = tmp;
6371 hr = IDirectDrawSurface2_GetAttachedSurface(mipmap, &caps, &tmp);
6372 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
6373 IDirectDrawSurface2_Release(mipmap);
6374 refcount = IDirectDrawSurface2_Release(surface);
6375 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6376 refcount = IDirectDrawPalette_Release(palette_mipmap);
6377 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6378 refcount = IDirectDrawPalette_Release(palette);
6379 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6381 refcount = IDirectDraw2_Release(ddraw);
6382 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6383 DestroyWindow(window);
6386 static void test_p8_rgb_blit(void)
6388 IDirectDrawSurface *src, *dst;
6389 DDSURFACEDESC surface_desc;
6390 IDirectDraw2 *ddraw;
6391 IDirectDrawPalette *palette;
6392 ULONG refcount;
6393 HWND window;
6394 HRESULT hr;
6395 PALETTEENTRY palette_entries[256];
6396 unsigned int x;
6397 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
6398 static const D3DCOLOR expected[] =
6400 0x00101010, 0x00010101, 0x00020202, 0x00030303,
6401 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
6403 D3DCOLOR color;
6405 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6406 0, 0, 640, 480, 0, 0, 0, 0);
6407 ddraw = create_ddraw();
6408 ok(!!ddraw, "Failed to create a ddraw object.\n");
6409 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6410 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6412 memset(palette_entries, 0, sizeof(palette_entries));
6413 palette_entries[1].peGreen = 0xff;
6414 palette_entries[2].peBlue = 0xff;
6415 palette_entries[3].peFlags = 0xff;
6416 palette_entries[4].peRed = 0xff;
6417 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
6418 palette_entries, &palette, NULL);
6419 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6421 memset(&surface_desc, 0, sizeof(surface_desc));
6422 surface_desc.dwSize = sizeof(surface_desc);
6423 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6424 surface_desc.dwWidth = 8;
6425 surface_desc.dwHeight = 1;
6426 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6427 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6428 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
6429 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
6430 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src, NULL);
6431 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6433 memset(&surface_desc, 0, sizeof(surface_desc));
6434 surface_desc.dwSize = sizeof(surface_desc);
6435 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6436 surface_desc.dwWidth = 8;
6437 surface_desc.dwHeight = 1;
6438 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6439 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6440 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
6441 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
6442 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6443 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6444 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
6445 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
6446 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst, NULL);
6447 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6449 memset(&surface_desc, 0, sizeof(surface_desc));
6450 surface_desc.dwSize = sizeof(surface_desc);
6451 hr = IDirectDrawSurface_Lock(src, NULL, &surface_desc, 0, NULL);
6452 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
6453 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
6454 hr = IDirectDrawSurface_Unlock(src, NULL);
6455 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
6457 hr = IDirectDrawSurface_SetPalette(src, palette);
6458 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6459 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
6460 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
6461 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
6462 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
6463 "Failed to blit, hr %#x.\n", hr);
6465 if (SUCCEEDED(hr))
6467 for (x = 0; x < sizeof(expected) / sizeof(*expected); x++)
6469 color = get_surface_color(dst, x, 0);
6470 todo_wine ok(compare_color(color, expected[x], 0),
6471 "Pixel %u: Got color %#x, expected %#x.\n",
6472 x, color, expected[x]);
6476 IDirectDrawSurface_Release(src);
6477 IDirectDrawSurface_Release(dst);
6478 IDirectDrawPalette_Release(palette);
6480 refcount = IDirectDraw2_Release(ddraw);
6481 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6482 DestroyWindow(window);
6485 static void test_material(void)
6487 IDirect3DMaterial2 *background, *material;
6488 D3DMATERIALHANDLE mat_handle, tmp;
6489 IDirect3DViewport2 *viewport;
6490 IDirect3DDevice2 *device;
6491 IDirectDrawSurface *rt;
6492 IDirectDraw2 *ddraw;
6493 D3DCOLOR color;
6494 ULONG refcount;
6495 unsigned int i;
6496 HWND window;
6497 HRESULT hr;
6498 BOOL valid;
6500 static D3DVERTEX quad[] =
6502 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
6503 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
6504 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
6505 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
6507 static const struct
6509 BOOL material;
6510 D3DCOLOR expected_color;
6512 test_data[] =
6514 {TRUE, 0x0000ff00},
6515 {FALSE, 0x00ffffff},
6517 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
6519 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6520 0, 0, 640, 480, 0, 0, 0, 0);
6521 ddraw = create_ddraw();
6522 ok(!!ddraw, "Failed to create a ddraw object.\n");
6523 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
6525 skip("Failed to create a 3D device, skipping test.\n");
6526 DestroyWindow(window);
6527 return;
6530 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
6531 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
6533 background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
6534 viewport = create_viewport(device, 0, 0, 640, 480);
6535 viewport_set_background(device, viewport, background);
6536 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
6537 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
6539 material = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
6540 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
6541 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
6543 hr = IDirect3DDevice2_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
6544 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
6545 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
6546 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
6547 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
6548 hr = IDirect3DDevice2_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
6549 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
6550 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
6551 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, 0);
6552 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
6553 hr = IDirect3DDevice2_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
6554 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
6555 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
6557 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
6559 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
6560 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
6562 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, test_data[i].material ? mat_handle : 0);
6563 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
6565 hr = IDirect3DDevice2_BeginScene(device);
6566 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6567 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_VERTEX, quad, 4, 0);
6568 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6569 hr = IDirect3DDevice2_EndScene(device);
6570 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6571 color = get_surface_color(rt, 320, 240);
6572 ok(compare_color(color, test_data[i].expected_color, 1),
6573 "Got unexpected color 0x%08x, test %u.\n", color, i);
6576 destroy_material(material);
6577 material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
6578 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
6579 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
6581 hr = IDirect3DViewport2_SetBackground(viewport, mat_handle);
6582 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
6583 hr = IDirect3DViewport2_GetBackground(viewport, &tmp, &valid);
6584 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
6585 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
6586 ok(valid, "Got unexpected valid %#x.\n", valid);
6587 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6588 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
6589 color = get_surface_color(rt, 320, 240);
6590 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
6592 hr = IDirect3DViewport2_SetBackground(viewport, 0);
6593 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6594 hr = IDirect3DViewport2_GetBackground(viewport, &tmp, &valid);
6595 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
6596 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
6597 ok(valid, "Got unexpected valid %#x.\n", valid);
6598 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6599 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
6600 color = get_surface_color(rt, 320, 240);
6601 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
6603 destroy_viewport(device, viewport);
6604 viewport = create_viewport(device, 0, 0, 640, 480);
6606 hr = IDirect3DViewport2_GetBackground(viewport, &tmp, &valid);
6607 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
6608 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
6609 ok(!valid, "Got unexpected valid %#x.\n", valid);
6610 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6611 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
6612 color = get_surface_color(rt, 320, 240);
6613 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x.\n", color);
6615 destroy_viewport(device, viewport);
6616 destroy_material(background);
6617 destroy_material(material);
6618 IDirectDrawSurface_Release(rt);
6619 refcount = IDirect3DDevice2_Release(device);
6620 ok(!refcount, "Device has %u references left.\n", refcount);
6621 refcount = IDirectDraw2_Release(ddraw);
6622 ok(!refcount, "Ddraw object has %u references left.\n", refcount);
6623 DestroyWindow(window);
6626 static void test_lighting(void)
6628 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
6629 static D3DMATRIX mat =
6631 1.0f, 0.0f, 0.0f, 0.0f,
6632 0.0f, 1.0f, 0.0f, 0.0f,
6633 0.0f, 0.0f, 1.0f, 0.0f,
6634 0.0f, 0.0f, 0.0f, 1.0f,
6636 mat_singular =
6638 1.0f, 0.0f, 1.0f, 0.0f,
6639 0.0f, 1.0f, 0.0f, 0.0f,
6640 1.0f, 0.0f, 1.0f, 0.0f,
6641 0.0f, 0.0f, 0.5f, 1.0f,
6643 mat_transf =
6645 0.0f, 0.0f, 1.0f, 0.0f,
6646 0.0f, 1.0f, 0.0f, 0.0f,
6647 -1.0f, 0.0f, 0.0f, 0.0f,
6648 10.f, 10.0f, 10.0f, 1.0f,
6650 mat_nonaffine =
6652 1.0f, 0.0f, 0.0f, 0.0f,
6653 0.0f, 1.0f, 0.0f, 0.0f,
6654 0.0f, 0.0f, 1.0f, -1.0f,
6655 10.f, 10.0f, 10.0f, 0.0f,
6657 static D3DLVERTEX unlitquad[] =
6659 {{-1.0f}, {-1.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
6660 {{-1.0f}, { 0.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
6661 {{ 0.0f}, { 0.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
6662 {{ 0.0f}, {-1.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
6664 litquad[] =
6666 {{-1.0f}, { 0.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
6667 {{-1.0f}, { 1.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
6668 {{ 0.0f}, { 1.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
6669 {{ 0.0f}, { 0.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
6671 static D3DVERTEX unlitnquad[] =
6673 {{0.0f}, {-1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6674 {{0.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6675 {{1.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6676 {{1.0f}, {-1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6678 litnquad[] =
6680 {{0.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6681 {{0.0f}, { 1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6682 {{1.0f}, { 1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6683 {{1.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6685 nquad[] =
6687 {{-1.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6688 {{-1.0f}, { 1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6689 {{ 1.0f}, { 1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6690 {{ 1.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6692 rotatedquad[] =
6694 {{-10.0f}, {-11.0f}, {11.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
6695 {{-10.0f}, { -9.0f}, {11.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
6696 {{-10.0f}, { -9.0f}, { 9.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
6697 {{-10.0f}, {-11.0f}, { 9.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
6699 translatedquad[] =
6701 {{-11.0f}, {-11.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6702 {{-11.0f}, { -9.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6703 {{ -9.0f}, { -9.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6704 {{ -9.0f}, {-11.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6706 static WORD indices[] = {0, 1, 2, 2, 3, 0};
6707 static const struct
6709 D3DMATRIX *world_matrix;
6710 void *quad;
6711 DWORD expected;
6712 const char *message;
6714 tests[] =
6716 {&mat, nquad, 0x000000ff, "Lit quad with light"},
6717 {&mat_singular, nquad, 0x000000b4, "Lit quad with singular world matrix"},
6718 {&mat_transf, rotatedquad, 0x000000ff, "Lit quad with transformation matrix"},
6719 {&mat_nonaffine, translatedquad, 0x000000ff, "Lit quad with non-affine matrix"},
6722 HWND window;
6723 IDirect3D2 *d3d;
6724 IDirect3DDevice2 *device;
6725 IDirectDraw2 *ddraw;
6726 IDirectDrawSurface *rt;
6727 IDirect3DViewport2 *viewport;
6728 IDirect3DMaterial2 *material;
6729 IDirect3DLight *light;
6730 D3DMATERIALHANDLE mat_handle;
6731 D3DLIGHT2 light_desc;
6732 HRESULT hr;
6733 D3DCOLOR color;
6734 ULONG refcount;
6735 unsigned int i;
6737 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6738 0, 0, 640, 480, 0, 0, 0, 0);
6739 ddraw = create_ddraw();
6740 ok(!!ddraw, "Failed to create a ddraw object.\n");
6741 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
6743 skip("Failed to create a 3D device, skipping test.\n");
6744 DestroyWindow(window);
6745 return;
6748 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
6749 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
6751 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
6752 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
6754 viewport = create_viewport(device, 0, 0, 640, 480);
6755 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
6756 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
6758 material = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
6759 viewport_set_background(device, viewport, material);
6761 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6762 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
6764 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
6765 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
6766 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
6767 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
6768 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
6769 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
6770 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
6771 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
6772 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
6773 ok(SUCCEEDED(hr), "Failed to disable zbuffer, hr %#x.\n", hr);
6774 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
6775 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
6776 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
6777 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
6779 hr = IDirect3DDevice2_BeginScene(device);
6780 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6782 /* There is no D3DRENDERSTATE_LIGHTING on ddraw < 7. */
6783 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
6784 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
6785 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_LVERTEX, unlitquad,
6786 4, indices, 6, 0);
6787 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6789 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
6790 ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
6791 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_LVERTEX, litquad,
6792 4, indices, 6, 0);
6793 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6795 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
6796 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
6797 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX, unlitnquad,
6798 4, indices, 6, 0);
6799 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6801 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
6802 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
6803 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX, litnquad,
6804 4, indices, 6, 0);
6805 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6807 hr = IDirect3DDevice2_EndScene(device);
6808 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6810 color = get_surface_color(rt, 160, 360);
6811 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x.\n", color);
6812 color = get_surface_color(rt, 160, 120);
6813 ok(color == 0x0000ff00, "Lit quad without normals has color 0x%08x.\n", color);
6814 color = get_surface_color(rt, 480, 360);
6815 ok(color == 0x00ffffff, "Unlit quad with normals has color 0x%08x.\n", color);
6816 color = get_surface_color(rt, 480, 120);
6817 ok(color == 0x00ffffff, "Lit quad with normals has color 0x%08x.\n", color);
6819 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
6820 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
6821 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
6822 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
6824 hr = IDirect3D2_CreateLight(d3d, &light, NULL);
6825 ok(SUCCEEDED(hr), "Failed to create a light object, hr %#x.\n", hr);
6826 memset(&light_desc, 0, sizeof(light_desc));
6827 light_desc.dwSize = sizeof(light_desc);
6828 light_desc.dltType = D3DLIGHT_DIRECTIONAL;
6829 U1(light_desc.dcvColor).r = 0.0f;
6830 U2(light_desc.dcvColor).g = 0.0f;
6831 U3(light_desc.dcvColor).b = 1.0f;
6832 U4(light_desc.dcvColor).a = 1.0f;
6833 U3(light_desc.dvDirection).z = 1.0f;
6834 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
6835 ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
6836 hr = IDirect3DViewport2_AddLight(viewport, light);
6837 ok(SUCCEEDED(hr), "Failed to add a light to the viewport, hr %#x.\n", hr);
6839 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6840 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
6842 hr = IDirect3DDevice2_BeginScene(device);
6843 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6845 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX, nquad,
6846 4, indices, 6, 0);
6847 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6849 hr = IDirect3DDevice2_EndScene(device);
6850 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6852 color = get_surface_color(rt, 320, 240);
6853 ok(color == 0x00000000, "Lit quad with no light has color 0x%08x.\n", color);
6855 light_desc.dwFlags = D3DLIGHT_ACTIVE;
6856 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
6857 ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
6859 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
6861 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
6862 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
6864 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6865 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
6867 hr = IDirect3DDevice2_BeginScene(device);
6868 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6870 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX,
6871 tests[i].quad, 4, indices, 6, 0);
6872 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6874 hr = IDirect3DDevice2_EndScene(device);
6875 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6877 color = get_surface_color(rt, 320, 240);
6878 ok(color == tests[i].expected, "%s has color 0x%08x.\n", tests[i].message, color);
6881 hr = IDirect3DViewport2_DeleteLight(viewport, light);
6882 ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#x.\n", hr);
6883 IDirect3DLight_Release(light);
6884 destroy_material(material);
6885 destroy_viewport(device, viewport);
6886 IDirectDrawSurface2_Release(rt);
6887 refcount = IDirect3DDevice2_Release(device);
6888 ok(!refcount, "Device has %u references left.\n", refcount);
6889 IDirect3D2_Release(d3d);
6890 refcount = IDirectDraw2_Release(ddraw);
6891 ok(!refcount, "Ddraw object has %u references left.\n", refcount);
6892 DestroyWindow(window);
6895 static void test_specular_lighting(void)
6897 static const unsigned int vertices_side = 5;
6898 const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
6899 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
6900 static D3DMATRIX mat =
6902 1.0f, 0.0f, 0.0f, 0.0f,
6903 0.0f, 1.0f, 0.0f, 0.0f,
6904 0.0f, 0.0f, 1.0f, 0.0f,
6905 0.0f, 0.0f, 0.0f, 1.0f,
6907 static D3DLIGHT2 directional =
6909 sizeof(D3DLIGHT2),
6910 D3DLIGHT_DIRECTIONAL,
6911 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
6912 {{0.0f}, {0.0f}, {0.0f}},
6913 {{0.0f}, {0.0f}, {1.0f}},
6915 point =
6917 sizeof(D3DLIGHT2),
6918 D3DLIGHT_POINT,
6919 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
6920 {{0.0f}, {0.0f}, {0.0f}},
6921 {{0.0f}, {0.0f}, {0.0f}},
6922 100.0f,
6923 0.0f,
6924 0.0f, 0.0f, 1.0f,
6926 spot =
6928 sizeof(D3DLIGHT2),
6929 D3DLIGHT_SPOT,
6930 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
6931 {{0.0f}, {0.0f}, {0.0f}},
6932 {{0.0f}, {0.0f}, {1.0f}},
6933 100.0f,
6934 1.0f,
6935 0.0f, 0.0f, 1.0f,
6936 M_PI / 12.0f, M_PI / 3.0f
6938 parallelpoint =
6940 sizeof(D3DLIGHT2),
6941 D3DLIGHT_PARALLELPOINT,
6942 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
6943 {{0.5f}, {0.0f}, {-1.0f}},
6944 {{0.0f}, {0.0f}, {0.0f}},
6946 static const struct expected_color
6948 unsigned int x, y;
6949 D3DCOLOR color;
6951 expected_directional_local[] =
6953 {160, 120, 0x003c3c3c},
6954 {320, 120, 0x00717171},
6955 {480, 120, 0x003c3c3c},
6956 {160, 240, 0x00717171},
6957 {320, 240, 0x00ffffff},
6958 {480, 240, 0x00717171},
6959 {160, 360, 0x003c3c3c},
6960 {320, 360, 0x00717171},
6961 {480, 360, 0x003c3c3c},
6963 expected_point_local[] =
6965 {160, 120, 0x00000000},
6966 {320, 120, 0x00090909},
6967 {480, 120, 0x00000000},
6968 {160, 240, 0x00090909},
6969 {320, 240, 0x00fafafa},
6970 {480, 240, 0x00090909},
6971 {160, 360, 0x00000000},
6972 {320, 360, 0x00090909},
6973 {480, 360, 0x00000000},
6975 expected_spot_local[] =
6977 {160, 120, 0x00000000},
6978 {320, 120, 0x00020202},
6979 {480, 120, 0x00000000},
6980 {160, 240, 0x00020202},
6981 {320, 240, 0x00fafafa},
6982 {480, 240, 0x00020202},
6983 {160, 360, 0x00000000},
6984 {320, 360, 0x00020202},
6985 {480, 360, 0x00000000},
6987 expected_parallelpoint[] =
6989 {160, 120, 0x00050505},
6990 {320, 120, 0x002c2c2c},
6991 {480, 120, 0x006e6e6e},
6992 {160, 240, 0x00090909},
6993 {320, 240, 0x00717171},
6994 {480, 240, 0x00ffffff},
6995 {160, 360, 0x00050505},
6996 {320, 360, 0x002c2c2c},
6997 {480, 360, 0x006e6e6e},
6999 static const struct
7001 D3DLIGHT2 *light;
7002 const struct expected_color *expected;
7003 unsigned int expected_count;
7005 tests[] =
7007 {&directional, expected_directional_local,
7008 sizeof(expected_directional_local) / sizeof(expected_directional_local[0])},
7009 {&point, expected_point_local,
7010 sizeof(expected_point_local) / sizeof(expected_point_local[0])},
7011 {&spot, expected_spot_local,
7012 sizeof(expected_spot_local) / sizeof(expected_spot_local[0])},
7013 {&parallelpoint, expected_parallelpoint,
7014 sizeof(expected_parallelpoint) / sizeof(expected_parallelpoint[0])},
7016 IDirect3D2 *d3d;
7017 IDirect3DDevice2 *device;
7018 IDirectDraw2 *ddraw;
7019 IDirectDrawSurface *rt;
7020 IDirect3DViewport2 *viewport;
7021 IDirect3DMaterial2 *material, *background_material;
7022 IDirect3DLight *light;
7023 D3DMATERIALHANDLE mat_handle;
7024 D3DCOLOR color;
7025 ULONG refcount;
7026 HWND window;
7027 HRESULT hr;
7028 unsigned int i, j, x, y;
7029 D3DVERTEX *quad;
7030 WORD *indices;
7032 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7033 0, 0, 640, 480, 0, 0, 0, 0);
7034 ddraw = create_ddraw();
7035 ok(!!ddraw, "Failed to create a ddraw object.\n");
7036 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
7038 skip("Failed to create a 3D device, skipping test.\n");
7039 DestroyWindow(window);
7040 return;
7043 quad = HeapAlloc(GetProcessHeap(), 0, vertices_side * vertices_side * sizeof(*quad));
7044 indices = HeapAlloc(GetProcessHeap(), 0, indices_count * sizeof(*indices));
7045 for (i = 0, y = 0; y < vertices_side; ++y)
7047 for (x = 0; x < vertices_side; ++x)
7049 U1(quad[i]).x = x * 2.0f / (vertices_side - 1) - 1.0f;
7050 U2(quad[i]).y = y * 2.0f / (vertices_side - 1) - 1.0f;
7051 U3(quad[i]).z = 1.0f;
7052 U4(quad[i]).nx = 0.0f;
7053 U5(quad[i]).ny = 0.0f;
7054 U6(quad[i]).nz = -1.0f;
7055 U7(quad[i]).tu = 0.0f;
7056 U8(quad[i++]).tv = 0.0f;
7059 for (i = 0, y = 0; y < (vertices_side - 1); ++y)
7061 for (x = 0; x < (vertices_side - 1); ++x)
7063 indices[i++] = y * vertices_side + x + 1;
7064 indices[i++] = y * vertices_side + x;
7065 indices[i++] = (y + 1) * vertices_side + x;
7066 indices[i++] = y * vertices_side + x + 1;
7067 indices[i++] = (y + 1) * vertices_side + x;
7068 indices[i++] = (y + 1) * vertices_side + x + 1;
7072 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
7073 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
7075 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
7076 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
7078 viewport = create_viewport(device, 0, 0, 640, 480);
7079 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
7080 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
7082 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
7083 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
7084 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
7085 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
7086 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
7087 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
7088 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
7089 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
7090 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
7091 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
7092 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
7093 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
7095 background_material = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
7096 viewport_set_background(device, viewport, background_material);
7098 material = create_specular_material(device, 1.0f, 1.0f, 1.0f, 1.0f, 30.0f);
7099 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
7100 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
7101 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
7102 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
7104 hr = IDirect3D2_CreateLight(d3d, &light, NULL);
7105 ok(SUCCEEDED(hr), "Failed to create a light object, hr %#x.\n", hr);
7106 hr = IDirect3DViewport2_AddLight(viewport, light);
7107 ok(SUCCEEDED(hr), "Failed to add a light to the viewport, hr %#x.\n", hr);
7109 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
7110 ok(SUCCEEDED(hr), "Failed to enable specular lighting, hr %#x.\n", hr);
7112 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
7114 tests[i].light->dwFlags = D3DLIGHT_ACTIVE;
7115 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)tests[i].light);
7116 ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
7118 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7119 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
7121 hr = IDirect3DDevice2_BeginScene(device);
7122 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
7124 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX,
7125 quad, vertices_side * vertices_side, indices, indices_count, 0);
7126 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7128 hr = IDirect3DDevice2_EndScene(device);
7129 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7131 for (j = 0; j < tests[i].expected_count; ++j)
7133 color = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
7134 ok(compare_color(color, tests[i].expected[j].color, 1),
7135 "Expected color 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
7136 tests[i].expected[j].color, tests[i].expected[j].x,
7137 tests[i].expected[j].y, color, i);
7141 hr = IDirect3DViewport2_DeleteLight(viewport, light);
7142 ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#x.\n", hr);
7143 IDirect3DLight_Release(light);
7144 destroy_material(material);
7145 destroy_material(background_material);
7146 destroy_viewport(device, viewport);
7147 IDirectDrawSurface2_Release(rt);
7148 refcount = IDirect3DDevice2_Release(device);
7149 ok(!refcount, "Device has %u references left.\n", refcount);
7150 IDirect3D2_Release(d3d);
7151 refcount = IDirectDraw2_Release(ddraw);
7152 ok(!refcount, "Ddraw object has %u references left.\n", refcount);
7153 DestroyWindow(window);
7154 HeapFree(GetProcessHeap(), 0, indices);
7155 HeapFree(GetProcessHeap(), 0, quad);
7158 static void test_palette_gdi(void)
7160 IDirectDrawSurface *surface, *primary;
7161 DDSURFACEDESC surface_desc;
7162 IDirectDraw2 *ddraw;
7163 IDirectDrawPalette *palette, *palette2;
7164 ULONG refcount;
7165 HWND window;
7166 HRESULT hr;
7167 PALETTEENTRY palette_entries[256];
7168 UINT i;
7169 HDC dc;
7170 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
7171 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
7172 * not the point of this test. */
7173 static const RGBQUAD expected1[] =
7175 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
7176 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
7178 static const RGBQUAD expected2[] =
7180 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
7181 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
7183 static const RGBQUAD expected3[] =
7185 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
7186 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
7188 HPALETTE ddraw_palette_handle;
7189 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
7190 RGBQUAD rgbquad[255];
7191 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
7193 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7194 0, 0, 640, 480, 0, 0, 0, 0);
7195 ddraw = create_ddraw();
7196 ok(!!ddraw, "Failed to create a ddraw object.\n");
7197 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7198 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7200 memset(&surface_desc, 0, sizeof(surface_desc));
7201 surface_desc.dwSize = sizeof(surface_desc);
7202 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7203 surface_desc.dwWidth = 16;
7204 surface_desc.dwHeight = 16;
7205 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7206 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
7207 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7208 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
7209 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7210 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7212 /* Avoid colors from the Windows default palette. */
7213 memset(palette_entries, 0, sizeof(palette_entries));
7214 palette_entries[1].peRed = 0x01;
7215 palette_entries[2].peGreen = 0x02;
7216 palette_entries[3].peBlue = 0x03;
7217 palette_entries[4].peRed = 0x13;
7218 palette_entries[4].peGreen = 0x14;
7219 palette_entries[4].peBlue = 0x15;
7220 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7221 palette_entries, &palette, NULL);
7222 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7224 /* If there is no palette assigned and the display mode is not 8 bpp, some
7225 * drivers refuse to create a DC while others allow it. If a DC is created,
7226 * the DIB color table is uninitialized and contains random colors. No error
7227 * is generated when trying to read pixels and random garbage is returned.
7229 * The most likely explanation is that if the driver creates a DC, it (or
7230 * the higher-level runtime) uses GetSystemPaletteEntries to find the
7231 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
7232 * contains uninitialized garbage. See comments below for the P8 case. */
7234 hr = IDirectDrawSurface_SetPalette(surface, palette);
7235 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7236 hr = IDirectDrawSurface_GetDC(surface, &dc);
7237 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7238 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
7239 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
7240 "Got unexpected palette %p, expected %p.\n",
7241 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
7243 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7244 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7245 for (i = 0; i < sizeof(expected1) / sizeof(*expected1); i++)
7247 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
7248 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7249 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7250 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
7252 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7254 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7255 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7256 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7259 /* Update the palette while the DC is in use. This does not modify the DC. */
7260 palette_entries[4].peRed = 0x23;
7261 palette_entries[4].peGreen = 0x24;
7262 palette_entries[4].peBlue = 0x25;
7263 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
7264 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
7266 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
7267 ok(i == 1, "Expected count 1, got %u.\n", i);
7268 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
7269 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7270 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
7271 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
7273 /* Neither does re-setting the palette. */
7274 hr = IDirectDrawSurface_SetPalette(surface, NULL);
7275 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7276 hr = IDirectDrawSurface_SetPalette(surface, palette);
7277 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7279 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
7280 ok(i == 1, "Expected count 1, got %u.\n", i);
7281 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
7282 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7283 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
7284 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
7286 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
7287 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7289 /* Refresh the DC. This updates the palette. */
7290 hr = IDirectDrawSurface_GetDC(surface, &dc);
7291 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7292 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7293 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7294 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
7296 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
7297 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7298 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7299 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
7301 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7303 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7304 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7305 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7307 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
7308 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7310 refcount = IDirectDrawSurface_Release(surface);
7311 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7313 if (FAILED(IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
7315 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
7316 IDirectDrawPalette_Release(palette);
7317 IDirectDraw2_Release(ddraw);
7318 DestroyWindow(window);
7319 return;
7321 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
7322 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
7323 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7325 memset(&surface_desc, 0, sizeof(surface_desc));
7326 surface_desc.dwSize = sizeof(surface_desc);
7327 surface_desc.dwFlags = DDSD_CAPS;
7328 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7329 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
7330 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7332 hr = IDirectDrawSurface_SetPalette(primary, palette);
7333 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7334 hr = IDirectDrawSurface_GetDC(primary, &dc);
7335 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7336 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
7337 /* Windows 2000 on the testbot assigns a different palette to the primary. Refrast? */
7338 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE) || broken(TRUE),
7339 "Got unexpected palette %p, expected %p.\n",
7340 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
7341 SelectPalette(dc, ddraw_palette_handle, FALSE);
7343 /* The primary uses the system palette. In exclusive mode, the system palette matches
7344 * the ddraw palette attached to the primary, so the result is what you would expect
7345 * from a regular surface. Tests for the interaction between the ddraw palette and
7346 * the system palette are not included pending an application that depends on this.
7347 * The relation between those causes problems on Windows Vista and newer for games
7348 * like Age of Empires or StarCraft. Don't emulate it without a real need. */
7349 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7350 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7351 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
7353 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
7354 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7355 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7356 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
7358 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7360 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7361 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7362 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7364 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
7365 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7367 memset(&surface_desc, 0, sizeof(surface_desc));
7368 surface_desc.dwSize = sizeof(surface_desc);
7369 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7370 surface_desc.dwWidth = 16;
7371 surface_desc.dwHeight = 16;
7372 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7373 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7374 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7376 /* Here the offscreen surface appears to use the primary's palette,
7377 * but in all likelihood it is actually the system palette. */
7378 hr = IDirectDrawSurface_GetDC(surface, &dc);
7379 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7380 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7381 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7382 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
7384 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
7385 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7386 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7387 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
7389 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7391 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7392 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7393 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7395 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
7396 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7398 /* On real hardware a change to the primary surface's palette applies immediately,
7399 * even on device contexts from offscreen surfaces that do not have their own
7400 * palette. On the testbot VMs this is not the case. Don't test this until we
7401 * know of an application that depends on this. */
7403 memset(palette_entries, 0, sizeof(palette_entries));
7404 palette_entries[1].peBlue = 0x40;
7405 palette_entries[2].peRed = 0x40;
7406 palette_entries[3].peGreen = 0x40;
7407 palette_entries[4].peRed = 0x12;
7408 palette_entries[4].peGreen = 0x34;
7409 palette_entries[4].peBlue = 0x56;
7410 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7411 palette_entries, &palette2, NULL);
7412 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7413 hr = IDirectDrawSurface_SetPalette(surface, palette2);
7414 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7416 /* A palette assigned to the offscreen surface overrides the primary / system
7417 * palette. */
7418 hr = IDirectDrawSurface_GetDC(surface, &dc);
7419 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7420 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7421 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7422 for (i = 0; i < sizeof(expected3) / sizeof(*expected3); i++)
7424 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
7425 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7426 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7427 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
7429 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7431 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7432 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7433 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7435 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
7436 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7438 refcount = IDirectDrawSurface_Release(surface);
7439 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7441 /* The Windows 8 testbot keeps extra references to the primary and
7442 * backbuffer while in 8 bpp mode. */
7443 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
7444 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
7446 refcount = IDirectDrawSurface_Release(primary);
7447 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7448 refcount = IDirectDrawPalette_Release(palette2);
7449 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7450 refcount = IDirectDrawPalette_Release(palette);
7451 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7452 refcount = IDirectDraw2_Release(ddraw);
7453 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7454 DestroyWindow(window);
7457 static void test_palette_alpha(void)
7459 IDirectDrawSurface *surface1;
7460 IDirectDrawSurface2 *surface;
7461 DDSURFACEDESC surface_desc;
7462 IDirectDraw2 *ddraw;
7463 IDirectDrawPalette *palette;
7464 ULONG refcount;
7465 HWND window;
7466 HRESULT hr;
7467 PALETTEENTRY palette_entries[256];
7468 unsigned int i;
7469 static const struct
7471 DWORD caps, flags;
7472 BOOL attach_allowed;
7473 const char *name;
7475 test_data[] =
7477 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
7478 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
7479 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
7482 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7483 0, 0, 640, 480, 0, 0, 0, 0);
7484 ddraw = create_ddraw();
7485 ok(!!ddraw, "Failed to create a ddraw object.\n");
7486 if (FAILED(IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
7488 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
7489 IDirectDraw2_Release(ddraw);
7490 DestroyWindow(window);
7491 return;
7493 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7494 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7496 memset(palette_entries, 0, sizeof(palette_entries));
7497 palette_entries[1].peFlags = 0x42;
7498 palette_entries[2].peFlags = 0xff;
7499 palette_entries[3].peFlags = 0x80;
7500 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
7501 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7503 memset(palette_entries, 0x66, sizeof(palette_entries));
7504 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
7505 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
7506 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7507 palette_entries[0].peFlags);
7508 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7509 palette_entries[1].peFlags);
7510 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
7511 palette_entries[2].peFlags);
7512 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
7513 palette_entries[3].peFlags);
7515 IDirectDrawPalette_Release(palette);
7517 memset(palette_entries, 0, sizeof(palette_entries));
7518 palette_entries[1].peFlags = 0x42;
7519 palette_entries[1].peRed = 0xff;
7520 palette_entries[2].peFlags = 0xff;
7521 palette_entries[3].peFlags = 0x80;
7522 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
7523 palette_entries, &palette, NULL);
7524 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7526 memset(palette_entries, 0x66, sizeof(palette_entries));
7527 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
7528 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
7529 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7530 palette_entries[0].peFlags);
7531 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7532 palette_entries[1].peFlags);
7533 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
7534 palette_entries[2].peFlags);
7535 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
7536 palette_entries[3].peFlags);
7538 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); i++)
7540 memset(&surface_desc, 0, sizeof(surface_desc));
7541 surface_desc.dwSize = sizeof(surface_desc);
7542 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
7543 surface_desc.dwWidth = 128;
7544 surface_desc.dwHeight = 128;
7545 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
7546 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7547 ok(SUCCEEDED(hr), "Failed to create %s surface, hr %#x.\n", test_data[i].name, hr);
7548 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
7549 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface2 interface, hr %#x.\n", hr);
7550 IDirectDrawSurface_Release(surface1);
7552 hr = IDirectDrawSurface2_SetPalette(surface, palette);
7553 if (test_data[i].attach_allowed)
7554 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#x.\n", test_data[i].name, hr);
7555 else
7556 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x, %s surface.\n", hr, test_data[i].name);
7558 if (SUCCEEDED(hr))
7560 HDC dc;
7561 RGBQUAD rgbquad;
7562 UINT retval;
7564 hr = IDirectDrawSurface2_GetDC(surface, &dc);
7565 ok(SUCCEEDED(hr) || broken(hr == DDERR_CANTCREATEDC) /* Win2k testbot */,
7566 "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
7567 if (SUCCEEDED(hr))
7569 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
7570 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
7571 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
7572 rgbquad.rgbRed, test_data[i].name);
7573 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
7574 rgbquad.rgbGreen, test_data[i].name);
7575 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
7576 rgbquad.rgbBlue, test_data[i].name);
7577 todo_wine ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
7578 rgbquad.rgbReserved, test_data[i].name);
7579 hr = IDirectDrawSurface2_ReleaseDC(surface, dc);
7580 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7583 IDirectDrawSurface2_Release(surface);
7586 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
7587 memset(&surface_desc, 0, sizeof(surface_desc));
7588 surface_desc.dwSize = sizeof(surface_desc);
7589 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7590 surface_desc.dwWidth = 128;
7591 surface_desc.dwHeight = 128;
7592 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7593 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
7594 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
7595 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
7596 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7597 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7598 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
7599 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7600 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7601 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
7602 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface2 interface, hr %#x.\n", hr);
7603 IDirectDrawSurface_Release(surface1);
7605 hr = IDirectDrawSurface2_SetPalette(surface, palette);
7606 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
7607 IDirectDrawSurface2_Release(surface);
7609 /* The Windows 8 testbot keeps extra references to the primary
7610 * while in 8 bpp mode. */
7611 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
7612 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
7614 refcount = IDirectDrawPalette_Release(palette);
7615 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7616 refcount = IDirectDraw2_Release(ddraw);
7617 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7618 DestroyWindow(window);
7621 static void test_lost_device(void)
7623 IDirectDrawSurface *surface;
7624 DDSURFACEDESC surface_desc;
7625 HWND window1, window2;
7626 IDirectDraw2 *ddraw;
7627 ULONG refcount;
7628 HRESULT hr;
7629 BOOL ret;
7631 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7632 0, 0, 640, 480, 0, 0, 0, 0);
7633 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7634 0, 0, 640, 480, 0, 0, 0, 0);
7635 ddraw = create_ddraw();
7636 ok(!!ddraw, "Failed to create a ddraw object.\n");
7637 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7638 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7640 memset(&surface_desc, 0, sizeof(surface_desc));
7641 surface_desc.dwSize = sizeof(surface_desc);
7642 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
7643 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
7644 surface_desc.dwBackBufferCount = 1;
7645 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7646 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7648 hr = IDirectDrawSurface_IsLost(surface);
7649 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7650 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7651 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7653 ret = SetForegroundWindow(GetDesktopWindow());
7654 ok(ret, "Failed to set foreground window.\n");
7655 hr = IDirectDrawSurface_IsLost(surface);
7656 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7657 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7658 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7660 ret = SetForegroundWindow(window1);
7661 ok(ret, "Failed to set foreground window.\n");
7662 hr = IDirectDrawSurface_IsLost(surface);
7663 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7664 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7665 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7667 hr = restore_surfaces(ddraw);
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 == DD_OK, "Got unexpected hr %#x.\n", hr);
7674 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
7675 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7676 hr = IDirectDrawSurface_IsLost(surface);
7677 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7678 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7679 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7681 /* Trying to restore the primary will crash, probably because flippable
7682 * surfaces can't exist in DDSCL_NORMAL. */
7683 IDirectDrawSurface_Release(surface);
7684 memset(&surface_desc, 0, sizeof(surface_desc));
7685 surface_desc.dwSize = sizeof(surface_desc);
7686 surface_desc.dwFlags = DDSD_CAPS;
7687 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7688 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7689 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7691 hr = IDirectDrawSurface_IsLost(surface);
7692 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7694 ret = SetForegroundWindow(GetDesktopWindow());
7695 ok(ret, "Failed to set foreground window.\n");
7696 hr = IDirectDrawSurface_IsLost(surface);
7697 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7699 ret = SetForegroundWindow(window1);
7700 ok(ret, "Failed to set foreground window.\n");
7701 hr = IDirectDrawSurface_IsLost(surface);
7702 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7704 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7705 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7706 hr = IDirectDrawSurface_IsLost(surface);
7707 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7709 hr = restore_surfaces(ddraw);
7710 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7711 hr = IDirectDrawSurface_IsLost(surface);
7712 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7714 IDirectDrawSurface_Release(surface);
7715 memset(&surface_desc, 0, sizeof(surface_desc));
7716 surface_desc.dwSize = sizeof(surface_desc);
7717 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
7718 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
7719 U5(surface_desc).dwBackBufferCount = 1;
7720 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7721 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7723 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7724 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7725 hr = IDirectDrawSurface_IsLost(surface);
7726 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7727 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7728 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7730 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
7731 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7732 hr = IDirectDrawSurface_IsLost(surface);
7733 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7734 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7735 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
7737 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
7738 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7739 hr = IDirectDrawSurface_IsLost(surface);
7740 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7741 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7742 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
7744 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
7745 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7746 hr = IDirectDrawSurface_IsLost(surface);
7747 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7748 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7749 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
7751 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
7752 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7753 hr = IDirectDrawSurface_IsLost(surface);
7754 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7755 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7756 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
7758 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7759 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7760 hr = IDirectDrawSurface_IsLost(surface);
7761 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7762 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
7763 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7765 IDirectDrawSurface_Release(surface);
7766 refcount = IDirectDraw2_Release(ddraw);
7767 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7768 DestroyWindow(window2);
7769 DestroyWindow(window1);
7772 static void test_surface_desc_lock(void)
7774 IDirectDrawSurface *surface;
7775 DDSURFACEDESC surface_desc;
7776 IDirectDraw2 *ddraw;
7777 ULONG refcount;
7778 HWND window;
7779 HRESULT hr;
7781 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7782 0, 0, 640, 480, 0, 0, 0, 0);
7783 ddraw = create_ddraw();
7784 ok(!!ddraw, "Failed to create a ddraw object.\n");
7785 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7786 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7788 memset(&surface_desc, 0, sizeof(surface_desc));
7789 surface_desc.dwSize = sizeof(surface_desc);
7790 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7791 surface_desc.dwWidth = 16;
7792 surface_desc.dwHeight = 16;
7793 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7794 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7795 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7797 memset(&surface_desc, 0xaa, sizeof(surface_desc));
7798 surface_desc.dwSize = sizeof(surface_desc);
7799 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
7800 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7801 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
7803 memset(&surface_desc, 0xaa, sizeof(surface_desc));
7804 surface_desc.dwSize = sizeof(surface_desc);
7805 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, 0, NULL);
7806 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7807 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
7808 memset(&surface_desc, 0xaa, sizeof(surface_desc));
7809 surface_desc.dwSize = sizeof(surface_desc);
7810 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
7811 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7812 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
7813 hr = IDirectDrawSurface_Unlock(surface, NULL);
7814 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7816 memset(&surface_desc, 0xaa, sizeof(surface_desc));
7817 surface_desc.dwSize = sizeof(surface_desc);
7818 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
7819 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7820 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
7822 IDirectDrawSurface_Release(surface);
7823 refcount = IDirectDraw2_Release(ddraw);
7824 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7825 DestroyWindow(window);
7828 static void test_texturemapblend(void)
7830 HRESULT hr;
7831 DDSURFACEDESC ddsd;
7832 DDBLTFX fx;
7833 static RECT rect = {0, 0, 64, 128};
7834 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
7835 DDCOLORKEY ckey;
7836 IDirectDrawSurface *surface, *rt;
7837 IDirect3DTexture2 *texture;
7838 D3DTEXTUREHANDLE texture_handle;
7839 HWND window;
7840 IDirectDraw2 *ddraw;
7841 IDirect3DDevice2 *device;
7842 IDirect3DMaterial2 *material;
7843 IDirect3DViewport2 *viewport;
7844 ULONG ref;
7845 D3DCOLOR color;
7847 static D3DTLVERTEX test1_quads[] =
7849 {{0.0f}, {0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {0.0f}, {0.0f}},
7850 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {0.0f}, {1.0f}},
7851 {{640.0f}, {0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {1.0f}, {0.0f}},
7852 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {1.0f}, {1.0f}},
7853 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {0.0f}, {0.0f}},
7854 {{0.0f}, {480.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {0.0f}, {1.0f}},
7855 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {1.0f}, {0.0f}},
7856 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {1.0f}, {1.0f}},
7858 test2_quads[] =
7860 {{0.0f}, {0.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {0.0f}, {0.0f}},
7861 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {0.0f}, {1.0f}},
7862 {{640.0f}, {0.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {1.0f}, {0.0f}},
7863 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {1.0f}, {1.0f}},
7864 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {0.0f}, {0.0f}},
7865 {{0.0f}, {480.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {0.0f}, {1.0f}},
7866 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {1.0f}, {0.0f}},
7867 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {1.0f}, {1.0f}},
7870 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7871 0, 0, 640, 480, 0, 0, 0, 0);
7872 ddraw = create_ddraw();
7873 ok(!!ddraw, "Failed to create a ddraw object.\n");
7874 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
7876 skip("Failed to create a 3D device, skipping test.\n");
7877 DestroyWindow(window);
7878 IDirectDraw2_Release(ddraw);
7879 return;
7882 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
7883 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
7885 material = create_diffuse_material(device, 0.0f, 0.0f, 0.0f, 1.0f);
7886 viewport = create_viewport(device, 0, 0, 640, 480);
7887 viewport_set_background(device, viewport, material);
7888 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
7889 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
7891 /* Test alpha with DDPF_ALPHAPIXELS texture - should be taken from texture alpha channel.
7893 * The vertex alpha is completely ignored in this case, so case 1 and 2 combined are not
7894 * a D3DTOP_MODULATE with texture alpha = 0xff in case 2 (no alpha in texture). */
7895 memset(&ddsd, 0, sizeof(ddsd));
7896 ddsd.dwSize = sizeof(ddsd);
7897 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
7898 ddsd.dwHeight = 128;
7899 ddsd.dwWidth = 128;
7900 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
7901 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
7902 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
7903 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
7904 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7905 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7906 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
7907 U5(ddsd.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
7908 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
7909 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7911 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
7912 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
7913 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
7914 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
7915 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
7916 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
7918 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7919 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
7921 memset(&fx, 0, sizeof(fx));
7922 fx.dwSize = sizeof(fx);
7923 U5(fx).dwFillColor = 0xff0000ff;
7924 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7925 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
7926 U5(fx).dwFillColor = 0x800000ff;
7927 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7928 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
7930 /* Note that the ddraw1 version of this test runs tests 1-3 with D3DRENDERSTATE_COLORKEYENABLE
7931 * enabled, whereas this version only runs test 4 with color keying on. Because no color key
7932 * is set on the texture this should not result in different behavior. */
7933 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
7934 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
7935 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
7936 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
7937 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
7938 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
7939 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
7940 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
7941 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
7942 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
7943 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
7944 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
7946 hr = IDirect3DDevice2_BeginScene(device);
7947 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
7948 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[0], 4, 0);
7949 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7950 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[4], 4, 0);
7951 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7952 hr = IDirect3DDevice2_EndScene(device);
7953 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7955 color = get_surface_color(rt, 5, 5);
7956 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
7957 color = get_surface_color(rt, 400, 5);
7958 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
7959 color = get_surface_color(rt, 5, 245);
7960 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
7961 color = get_surface_color(rt, 400, 245);
7962 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
7964 IDirect3DTexture2_Release(texture);
7965 ref = IDirectDrawSurface_Release(surface);
7966 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
7968 /* Test alpha with texture that has no alpha channel - alpha should be taken from diffuse vertex color. */
7969 memset(&ddsd, 0, sizeof(ddsd));
7970 ddsd.dwSize = sizeof(ddsd);
7971 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
7972 ddsd.dwHeight = 128;
7973 ddsd.dwWidth = 128;
7974 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
7975 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
7976 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
7977 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
7978 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7979 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7980 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
7982 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
7983 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7985 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
7986 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
7987 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
7988 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
7989 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
7990 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
7992 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7993 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
7995 U5(fx).dwFillColor = 0xff0000ff;
7996 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7997 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
7998 U5(fx).dwFillColor = 0x800000ff;
7999 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8000 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
8002 hr = IDirect3DDevice2_BeginScene(device);
8003 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8004 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[0], 4, 0);
8005 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8006 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[4], 4, 0);
8007 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8008 hr = IDirect3DDevice2_EndScene(device);
8009 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8011 color = get_surface_color(rt, 5, 5);
8012 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
8013 color = get_surface_color(rt, 400, 5);
8014 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
8015 color = get_surface_color(rt, 5, 245);
8016 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
8017 color = get_surface_color(rt, 400, 245);
8018 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
8020 IDirect3DTexture2_Release(texture);
8021 ref = IDirectDrawSurface_Release(surface);
8022 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
8024 /* Test RGB - should multiply color components from diffuse vertex color and texture. */
8025 memset(&ddsd, 0, sizeof(ddsd));
8026 ddsd.dwSize = sizeof(ddsd);
8027 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
8028 ddsd.dwHeight = 128;
8029 ddsd.dwWidth = 128;
8030 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
8031 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
8032 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
8033 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
8034 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8035 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8036 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
8037 U5(ddsd.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
8038 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
8039 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8041 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
8042 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
8043 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
8044 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
8045 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
8046 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8048 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8049 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
8051 U5(fx).dwFillColor = 0x00ffffff;
8052 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8053 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
8054 U5(fx).dwFillColor = 0x00ffff80;
8055 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8056 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
8058 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
8059 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8061 hr = IDirect3DDevice2_BeginScene(device);
8062 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8063 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test2_quads[0], 4, 0);
8064 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8065 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test2_quads[4], 4, 0);
8066 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8067 hr = IDirect3DDevice2_EndScene(device);
8068 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8070 color = get_surface_color(rt, 5, 5);
8071 ok(compare_color(color, 0x00ff0040, 2), "Got unexpected color 0x%08x.\n", color);
8072 color = get_surface_color(rt, 400, 5);
8073 ok(compare_color(color, 0x00ff0080, 2), "Got unexpected color 0x%08x.\n", color);
8074 color = get_surface_color(rt, 5, 245);
8075 ok(compare_color(color, 0x00800080, 2), "Got unexpected color 0x%08x.\n", color);
8076 color = get_surface_color(rt, 400, 245);
8077 ok(compare_color(color, 0x008000ff, 2), "Got unexpected color 0x%08x.\n", color);
8079 IDirect3DTexture2_Release(texture);
8080 ref = IDirectDrawSurface_Release(surface);
8081 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
8083 /* Test alpha again, now with color keyed texture (colorkey emulation in wine can interfere). */
8084 memset(&ddsd, 0, sizeof(ddsd));
8085 ddsd.dwSize = sizeof(ddsd);
8086 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
8087 ddsd.dwHeight = 128;
8088 ddsd.dwWidth = 128;
8089 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
8090 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
8091 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
8092 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 16;
8093 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xf800;
8094 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x07e0;
8095 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x001f;
8097 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
8098 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8100 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
8101 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
8102 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
8103 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
8104 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
8105 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8107 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8108 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
8110 U5(fx).dwFillColor = 0xf800;
8111 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8112 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
8113 U5(fx).dwFillColor = 0x001f;
8114 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8115 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
8117 ckey.dwColorSpaceLowValue = 0x001f;
8118 ckey.dwColorSpaceHighValue = 0x001f;
8119 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
8120 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
8122 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
8123 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8124 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
8125 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8127 hr = IDirect3DDevice2_BeginScene(device);
8128 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8129 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[0], 4, 0);
8130 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8131 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[4], 4, 0);
8132 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8133 hr = IDirect3DDevice2_EndScene(device);
8134 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8136 color = get_surface_color(rt, 5, 5);
8137 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
8138 color = get_surface_color(rt, 400, 5);
8139 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
8140 color = get_surface_color(rt, 5, 245);
8141 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
8142 color = get_surface_color(rt, 400, 245);
8143 ok(compare_color(color, 0x00800000, 2), "Got unexpected color 0x%08x.\n", color);
8145 IDirect3DTexture2_Release(texture);
8146 ref = IDirectDrawSurface_Release(surface);
8147 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
8149 destroy_viewport(device, viewport);
8150 ref = IDirect3DMaterial2_Release(material);
8151 ok(ref == 0, "Material not properly released, refcount %u.\n", ref);
8152 IDirectDrawSurface_Release(rt);
8153 IDirect3DDevice2_Release(device);
8154 ref = IDirectDraw2_Release(ddraw);
8155 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
8156 DestroyWindow(window);
8159 static void test_viewport_clear_rect(void)
8161 HRESULT hr;
8162 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
8163 static D3DRECT clear_rect2 = {{90}, {90}, {110}, {110}};
8164 IDirectDrawSurface *rt;
8165 HWND window;
8166 IDirectDraw2 *ddraw;
8167 IDirect3DDevice2 *device;
8168 IDirect3DMaterial2 *red, *green;
8169 IDirect3DViewport2 *viewport, *viewport2;
8170 ULONG ref;
8171 D3DCOLOR color;
8173 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8174 0, 0, 640, 480, 0, 0, 0, 0);
8175 ddraw = create_ddraw();
8176 ok(!!ddraw, "Failed to create a ddraw object.\n");
8177 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
8179 skip("Failed to create a 3D device, skipping test.\n");
8180 DestroyWindow(window);
8181 IDirectDraw2_Release(ddraw);
8182 return;
8185 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
8186 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8188 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
8189 viewport = create_viewport(device, 0, 0, 640, 480);
8190 viewport_set_background(device, viewport, red);
8191 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8192 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8194 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
8195 viewport2 = create_viewport(device, 100, 100, 20, 20);
8196 viewport_set_background(device, viewport2, green);
8197 hr = IDirect3DViewport2_Clear(viewport2, 1, &clear_rect2, D3DCLEAR_TARGET);
8198 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8200 color = get_surface_color(rt, 85, 85); /* Outside both. */
8201 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
8202 color = get_surface_color(rt, 95, 95); /* Outside vp, inside rect. */
8203 /* AMD GPUs ignore the viewport dimensions and only care about the rectangle. */
8204 ok(compare_color(color, 0x00ff0000, 1) || broken(compare_color(color, 0x0000ff00, 1)),
8205 "Got unexpected color 0x%08x.\n", color);
8206 color = get_surface_color(rt, 105, 105); /* Inside both. */
8207 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
8208 color = get_surface_color(rt, 115, 115); /* Inside vp, outside rect. */
8209 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
8210 color = get_surface_color(rt, 125, 125); /* Outside both. */
8211 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
8213 destroy_viewport(device, viewport2);
8214 destroy_material(green);
8215 destroy_viewport(device, viewport);
8216 destroy_material(red);
8217 IDirectDrawSurface_Release(rt);
8218 IDirect3DDevice2_Release(device);
8219 ref = IDirectDraw2_Release(ddraw);
8220 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
8221 DestroyWindow(window);
8224 static void test_color_fill(void)
8226 HRESULT hr;
8227 IDirect3DDevice2 *device;
8228 IDirectDraw2 *ddraw;
8229 IDirectDrawSurface *surface, *surface2;
8230 DDSURFACEDESC surface_desc;
8231 ULONG refcount;
8232 HWND window;
8233 unsigned int i;
8234 DDBLTFX fx;
8235 RECT rect = {5, 5, 7, 7};
8236 DWORD *color;
8237 DWORD num_fourcc_codes, *fourcc_codes;
8238 DDCAPS hal_caps;
8239 BOOL support_uyvy = FALSE, support_yuy2 = FALSE;
8240 static const struct
8242 DWORD caps;
8243 HRESULT colorfill_hr, depthfill_hr;
8244 BOOL rop_success;
8245 const char *name;
8246 DWORD result;
8247 BOOL check_result;
8248 DDPIXELFORMAT format;
8250 tests[] =
8253 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
8254 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
8256 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
8257 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
8261 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
8262 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
8264 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
8265 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
8269 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
8270 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
8272 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
8273 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
8277 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
8278 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
8280 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
8281 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
8285 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY,
8286 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0, FALSE,
8287 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
8290 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
8291 * different afterwards. DX9+ GPUs set one of the two luminance values
8292 * in each block, but AMD and Nvidia GPUs disagree on which luminance
8293 * value they set. r200 (dx8) just sets the entire block to the clear
8294 * value. */
8295 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
8296 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
8298 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
8299 {0}, {0}, {0}, {0}, {0}
8303 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
8304 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
8306 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
8307 {0}, {0}, {0}, {0}, {0}
8311 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY,
8312 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
8314 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
8315 {0}, {0}, {0}, {0}, {0}
8319 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY,
8320 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
8322 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
8323 {0}, {0}, {0}, {0}, {0}
8327 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
8328 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
8330 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
8331 {0}, {0}, {0}, {0}, {0}
8335 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
8336 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
8338 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
8339 {0}, {0}, {0}, {0}, {0}
8343 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
8344 * surface works, presumably because it is handled by the runtime instead of
8345 * the driver. */
8346 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
8347 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
8349 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
8350 {8}, {0}, {0}, {0}, {0}
8354 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
8355 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
8357 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
8358 {8}, {0}, {0}, {0}, {0}
8362 static const struct
8364 DWORD rop;
8365 const char *name;
8366 HRESULT hr;
8368 rops[] =
8370 {SRCCOPY, "SRCCOPY", DD_OK},
8371 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
8372 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
8373 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
8374 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
8375 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
8376 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
8377 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
8378 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
8379 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
8380 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
8381 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
8382 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
8383 {BLACKNESS, "BLACKNESS", DD_OK},
8384 {WHITENESS, "WHITENESS", DD_OK},
8385 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
8388 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8389 0, 0, 640, 480, 0, 0, 0, 0);
8390 ddraw = create_ddraw();
8391 ok(!!ddraw, "Failed to create a ddraw object.\n");
8392 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
8394 skip("Failed to create a 3D device, skipping test.\n");
8395 DestroyWindow(window);
8396 IDirectDraw2_Release(ddraw);
8397 return;
8400 hr = IDirectDraw2_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
8401 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
8402 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8403 num_fourcc_codes * sizeof(*fourcc_codes));
8404 if (!fourcc_codes)
8405 goto done;
8406 hr = IDirectDraw2_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
8407 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
8408 for (i = 0; i < num_fourcc_codes; i++)
8410 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
8411 support_yuy2 = TRUE;
8412 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
8413 support_uyvy = TRUE;
8415 HeapFree(GetProcessHeap(), 0, fourcc_codes);
8417 memset(&hal_caps, 0, sizeof(hal_caps));
8418 hal_caps.dwSize = sizeof(hal_caps);
8419 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
8420 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8422 if ((!support_yuy2 && !support_uyvy) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
8423 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
8425 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
8427 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
8428 memset(&fx, 0, sizeof(fx));
8429 fx.dwSize = sizeof(fx);
8430 U5(fx).dwFillColor = 0xdeadbeef;
8432 memset(&surface_desc, 0, sizeof(surface_desc));
8433 surface_desc.dwSize = sizeof(surface_desc);
8434 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8435 surface_desc.dwWidth = 64;
8436 surface_desc.dwHeight = 64;
8437 surface_desc.ddpfPixelFormat = tests[i].format;
8438 surface_desc.ddsCaps.dwCaps = tests[i].caps;
8440 if (tests[i].caps & DDSCAPS_TEXTURE)
8442 struct format_support_check check = {&tests[i].format, FALSE};
8443 hr = IDirect3DDevice2_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
8444 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
8445 if (!check.supported)
8446 continue;
8449 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !support_yuy2)
8450 continue;
8451 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !support_uyvy)
8452 continue;
8453 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
8454 continue;
8456 if (tests[i].caps & DDSCAPS_ZBUFFER)
8458 surface_desc.dwFlags &= ~DDSD_PIXELFORMAT;
8459 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
8460 U2(surface_desc).dwZBufferBitDepth = get_device_z_depth(device);
8463 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8464 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, surface %s.\n", hr, tests[i].name);
8466 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8467 todo_wine_if (tests[i].format.dwFourCC)
8468 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
8469 hr, tests[i].colorfill_hr, tests[i].name);
8471 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8472 todo_wine_if (tests[i].format.dwFourCC)
8473 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
8474 hr, tests[i].colorfill_hr, tests[i].name);
8476 if (SUCCEEDED(hr) && tests[i].check_result)
8478 memset(&surface_desc, 0, sizeof(surface_desc));
8479 surface_desc.dwSize = sizeof(surface_desc);
8480 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
8481 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8482 color = surface_desc.lpSurface;
8483 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
8484 *color, tests[i].result, tests[i].name);
8485 hr = IDirectDrawSurface_Unlock(surface, NULL);
8486 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8489 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8490 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
8491 hr, tests[i].depthfill_hr, tests[i].name);
8492 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8493 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
8494 hr, tests[i].depthfill_hr, tests[i].name);
8496 U5(fx).dwFillColor = 0xdeadbeef;
8497 fx.dwROP = BLACKNESS;
8498 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
8499 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
8500 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
8501 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
8502 U5(fx).dwFillColor, tests[i].name);
8504 if (SUCCEEDED(hr) && tests[i].check_result)
8506 memset(&surface_desc, 0, sizeof(surface_desc));
8507 surface_desc.dwSize = sizeof(surface_desc);
8508 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
8509 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8510 color = surface_desc.lpSurface;
8511 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
8512 *color, tests[i].name);
8513 hr = IDirectDrawSurface_Unlock(surface, NULL);
8514 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8517 fx.dwROP = WHITENESS;
8518 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
8519 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
8520 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
8521 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
8522 U5(fx).dwFillColor, tests[i].name);
8524 if (SUCCEEDED(hr) && tests[i].check_result)
8526 memset(&surface_desc, 0, sizeof(surface_desc));
8527 surface_desc.dwSize = sizeof(surface_desc);
8528 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
8529 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8530 color = surface_desc.lpSurface;
8531 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
8532 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
8533 *color, tests[i].name);
8534 hr = IDirectDrawSurface_Unlock(surface, NULL);
8535 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8538 IDirectDrawSurface_Release(surface);
8541 memset(&fx, 0, sizeof(fx));
8542 fx.dwSize = sizeof(fx);
8543 U5(fx).dwFillColor = 0xdeadbeef;
8544 fx.dwROP = WHITENESS;
8546 memset(&surface_desc, 0, sizeof(surface_desc));
8547 surface_desc.dwSize = sizeof(surface_desc);
8548 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8549 surface_desc.dwWidth = 64;
8550 surface_desc.dwHeight = 64;
8551 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
8552 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
8553 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
8554 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8555 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8556 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
8557 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
8558 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8559 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8560 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
8561 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8563 /* No DDBLTFX. */
8564 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
8565 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8566 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
8567 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8569 /* Unused source rectangle. */
8570 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8571 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8572 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
8573 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8575 /* Unused source surface. */
8576 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8577 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8578 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
8579 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8580 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8581 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8582 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
8583 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8585 /* Inverted destination or source rectangle. */
8586 SetRect(&rect, 5, 7, 7, 5);
8587 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8588 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8589 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8590 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8591 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8592 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8593 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8594 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8595 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
8596 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8598 /* Negative rectangle. */
8599 SetRect(&rect, -1, -1, 5, 5);
8600 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8601 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8602 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8603 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8604 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8605 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8606 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8607 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8608 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
8609 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8611 /* Out of bounds rectangle. */
8612 SetRect(&rect, 0, 0, 65, 65);
8613 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8614 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8615 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
8616 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8618 /* Combine multiple flags. */
8619 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8620 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8621 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
8622 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8623 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
8624 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8626 for (i = 0; i < sizeof(rops) / sizeof(*rops); i++)
8628 fx.dwROP = rops[i].rop;
8629 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
8630 ok(hr == rops[i].hr, "Got unexpected hr %#x for rop %s.\n", hr, rops[i].name);
8633 IDirectDrawSurface_Release(surface2);
8634 IDirectDrawSurface_Release(surface);
8636 memset(&surface_desc, 0, sizeof(surface_desc));
8637 surface_desc.dwSize = sizeof(surface_desc);
8638 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_ZBUFFERBITDEPTH;
8639 surface_desc.dwWidth = 64;
8640 surface_desc.dwHeight = 64;
8641 U2(surface_desc).dwZBufferBitDepth = get_device_z_depth(device);
8642 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
8643 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8644 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8645 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
8646 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8648 /* No DDBLTFX. */
8649 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
8650 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8652 /* Unused source rectangle. */
8653 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8654 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8656 /* Unused source surface. */
8657 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8658 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8659 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8660 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8662 /* Inverted destination or source rectangle. */
8663 SetRect(&rect, 5, 7, 7, 5);
8664 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8665 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8666 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8667 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8668 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8669 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8670 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8671 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8673 /* Negative rectangle. */
8674 SetRect(&rect, -1, -1, 5, 5);
8675 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8676 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8677 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8678 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8679 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8680 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8681 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8682 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8684 /* Out of bounds rectangle. */
8685 SetRect(&rect, 0, 0, 65, 65);
8686 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8687 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8689 /* Combine multiple flags. */
8690 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8691 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8693 IDirectDrawSurface_Release(surface2);
8694 IDirectDrawSurface_Release(surface);
8696 done:
8697 IDirect3DDevice2_Release(device);
8698 refcount = IDirectDraw2_Release(ddraw);
8699 ok(refcount == 0, "Ddraw object not properly released, refcount %u.\n", refcount);
8700 DestroyWindow(window);
8703 static void test_colorkey_precision(void)
8705 static D3DLVERTEX quad[] =
8707 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xff000000}, {0}, {0.0f}, {0.0f}},
8708 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff000000}, {0}, {0.0f}, {1.0f}},
8709 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff000000}, {0}, {1.0f}, {0.0f}},
8710 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xff000000}, {0}, {1.0f}, {1.0f}},
8712 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
8713 IDirect3DDevice2 *device;
8714 IDirectDraw2 *ddraw;
8715 IDirectDrawSurface *rt;
8716 IDirect3DViewport2 *viewport;
8717 HWND window;
8718 HRESULT hr;
8719 IDirectDrawSurface *src, *dst, *texture;
8720 D3DTEXTUREHANDLE handle;
8721 IDirect3DTexture2 *d3d_texture;
8722 IDirect3DMaterial2 *green;
8723 DDSURFACEDESC surface_desc, lock_desc;
8724 ULONG refcount;
8725 D3DCOLOR color;
8726 unsigned int t, c;
8727 DDCOLORKEY ckey;
8728 DDBLTFX fx;
8729 DWORD data[4] = {0}, color_mask;
8730 D3DDEVICEDESC device_desc, hel_desc;
8731 BOOL warp;
8732 static const struct
8734 unsigned int max, shift, bpp, clear;
8735 const char *name;
8736 DDPIXELFORMAT fmt;
8738 tests[] =
8741 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8",
8743 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
8744 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
8749 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel",
8751 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
8752 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
8757 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel",
8759 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
8760 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
8765 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4",
8767 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
8768 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
8774 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8775 0, 0, 640, 480, 0, 0, 0, 0);
8776 ddraw = create_ddraw();
8777 ok(!!ddraw, "Failed to create a ddraw object.\n");
8778 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
8780 skip("Failed to create a 3D device, skipping test.\n");
8781 DestroyWindow(window);
8782 IDirectDraw2_Release(ddraw);
8783 return;
8785 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
8786 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8788 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
8789 * (color key doesn't match although the values are equal), and a false
8790 * positive when the color key is 0 and the texture contains the value 1.
8791 * I don't want to mark this broken unconditionally since this would
8792 * essentially disable the test on Windows. Try to detect WARP (and I
8793 * guess mismatch other SW renderers) by its ability to texture from
8794 * system memory. Also on random occasions 254 == 255 and 255 != 255.*/
8795 memset(&device_desc, 0, sizeof(device_desc));
8796 device_desc.dwSize = sizeof(device_desc);
8797 memset(&hel_desc, 0, sizeof(hel_desc));
8798 hel_desc.dwSize = sizeof(hel_desc);
8799 hr = IDirect3DDevice2_GetCaps(device, &device_desc, &hel_desc);
8800 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
8801 warp = !!(device_desc.dwDevCaps & D3DDEVCAPS_TEXTURESYSTEMMEMORY);
8803 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
8804 viewport = create_viewport(device, 0, 0, 640, 480);
8805 viewport_set_background(device, viewport, green);
8806 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
8807 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
8809 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
8810 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
8811 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
8812 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
8813 /* There's no way to ignore the texture color in d3d2, so multiply the texture color
8814 * with a black vertex color. */
8815 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATEALPHA);
8816 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8818 memset(&fx, 0, sizeof(fx));
8819 fx.dwSize = sizeof(fx);
8820 memset(&lock_desc, 0, sizeof(lock_desc));
8821 lock_desc.dwSize = sizeof(lock_desc);
8823 for (t = 0; t < sizeof(tests) / sizeof(*tests); ++t)
8825 memset(&surface_desc, 0, sizeof(surface_desc));
8826 surface_desc.dwSize = sizeof(surface_desc);
8827 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8828 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8829 surface_desc.dwWidth = 4;
8830 surface_desc.dwHeight = 1;
8831 surface_desc.ddpfPixelFormat = tests[t].fmt;
8832 /* Windows XP (at least with the r200 driver, other drivers untested) produces
8833 * garbage when doing color keyed texture->texture blits. */
8834 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src, NULL);
8835 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8836 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst, NULL);
8837 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8839 fx.dwFillColor = tests[t].clear;
8840 /* On the w8 testbot (WARP driver) the blit result has different values in the
8841 * X channel. */
8842 color_mask = U2(tests[t].fmt).dwRBitMask
8843 | U3(tests[t].fmt).dwGBitMask
8844 | U4(tests[t].fmt).dwBBitMask;
8846 for (c = 0; c <= tests[t].max; ++c)
8848 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
8849 * texture after it has been set once... */
8850 surface_desc.dwFlags |= DDSD_CKSRCBLT;
8851 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
8852 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
8853 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
8854 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &texture, NULL);
8855 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8857 hr = IDirectDrawSurface4_QueryInterface(texture, &IID_IDirect3DTexture2, (void **)&d3d_texture);
8858 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
8859 hr = IDirect3DTexture2_GetHandle(d3d_texture, device, &handle);
8860 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
8861 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, handle);
8862 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
8863 IDirect3DTexture2_Release(d3d_texture);
8865 hr = IDirectDrawSurface_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8866 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
8868 hr = IDirectDrawSurface_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
8869 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8870 switch (tests[t].bpp)
8872 case 4:
8873 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
8874 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
8875 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
8876 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
8877 break;
8879 case 2:
8880 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
8881 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
8882 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
8883 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
8884 break;
8886 hr = IDirectDrawSurface_Unlock(src, 0);
8887 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8888 hr = IDirectDrawSurface_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
8889 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
8891 ckey.dwColorSpaceLowValue = c << tests[t].shift;
8892 ckey.dwColorSpaceHighValue = c << tests[t].shift;
8893 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
8894 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
8896 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
8897 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
8899 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
8900 hr = IDirectDrawSurface_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
8901 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8902 switch (tests[t].bpp)
8904 case 4:
8905 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
8906 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
8907 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
8908 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
8909 break;
8911 case 2:
8912 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
8913 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
8914 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
8915 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
8916 break;
8918 hr = IDirectDrawSurface_Unlock(dst, 0);
8919 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8921 if (!c)
8923 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
8924 tests[t].clear, data[0], tests[t].name, c);
8926 if (data[3] == tests[t].clear)
8928 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
8929 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
8930 * even when a different surface is used. The blit itself doesn't draw anything,
8931 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
8932 * never be masked out by the key.
8934 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
8935 * terrible on WARP. */
8936 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
8937 IDirectDrawSurface_Release(texture);
8938 IDirectDrawSurface_Release(src);
8939 IDirectDrawSurface_Release(dst);
8940 goto done;
8943 else
8944 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
8945 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
8947 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
8948 tests[t].clear, data[1], tests[t].name, c);
8950 if (c == tests[t].max)
8951 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
8952 tests[t].clear, data[2], tests[t].name, c);
8953 else
8954 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
8955 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
8957 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8958 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
8960 hr = IDirect3DDevice2_BeginScene(device);
8961 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8962 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, 4, 0);
8963 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8964 hr = IDirect3DDevice2_EndScene(device);
8965 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8967 color = get_surface_color(rt, 80, 240);
8968 if (!c)
8969 ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
8970 "Got unexpected color 0x%08x, format %s, c=%u.\n",
8971 color, tests[t].name, c);
8972 else
8973 ok(compare_color(color, 0x00000000, 1) || broken(warp && compare_color(color, 0x0000ff00, 1)),
8974 "Got unexpected color 0x%08x, format %s, c=%u.\n",
8975 color, tests[t].name, c);
8977 color = get_surface_color(rt, 240, 240);
8978 ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
8979 "Got unexpected color 0x%08x, format %s, c=%u.\n",
8980 color, tests[t].name, c);
8982 color = get_surface_color(rt, 400, 240);
8983 if (c == tests[t].max)
8984 ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
8985 "Got unexpected color 0x%08x, format %s, c=%u.\n",
8986 color, tests[t].name, c);
8987 else
8988 ok(compare_color(color, 0x00000000, 1) || broken(warp && compare_color(color, 0x0000ff00, 1)),
8989 "Got unexpected color 0x%08x, format %s, c=%u.\n",
8990 color, tests[t].name, c);
8992 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
8993 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
8994 IDirectDrawSurface_Release(texture);
8996 IDirectDrawSurface_Release(src);
8997 IDirectDrawSurface_Release(dst);
8999 done:
9001 destroy_viewport(device, viewport);
9002 destroy_material(green);
9003 IDirectDrawSurface_Release(rt);
9004 IDirect3DDevice2_Release(device);
9005 refcount = IDirectDraw2_Release(ddraw);
9006 ok(refcount == 0, "Ddraw object not properly released, refcount %u.\n", refcount);
9007 DestroyWindow(window);
9010 static void test_range_colorkey(void)
9012 IDirectDraw2 *ddraw;
9013 HWND window;
9014 HRESULT hr;
9015 IDirectDrawSurface *surface;
9016 DDSURFACEDESC surface_desc;
9017 ULONG refcount;
9018 DDCOLORKEY ckey;
9020 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9021 0, 0, 640, 480, 0, 0, 0, 0);
9022 ddraw = create_ddraw();
9023 ok(!!ddraw, "Failed to create a ddraw object.\n");
9024 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9025 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9027 memset(&surface_desc, 0, sizeof(surface_desc));
9028 surface_desc.dwSize = sizeof(surface_desc);
9029 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
9030 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9031 surface_desc.dwWidth = 1;
9032 surface_desc.dwHeight = 1;
9033 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
9034 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
9035 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9036 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9037 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
9038 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
9040 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
9041 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
9042 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
9043 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9044 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
9046 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
9047 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
9048 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9049 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
9051 /* Same for DDSCAPS_OFFSCREENPLAIN. */
9052 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9053 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
9054 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
9055 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9056 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
9058 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
9059 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
9060 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9061 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
9063 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
9064 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
9065 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9066 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9068 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
9069 ckey.dwColorSpaceLowValue = 0x00000000;
9070 ckey.dwColorSpaceHighValue = 0x00000001;
9071 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9072 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
9074 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9075 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
9076 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
9077 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
9079 ckey.dwColorSpaceLowValue = 0x00000001;
9080 ckey.dwColorSpaceHighValue = 0x00000000;
9081 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9082 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
9084 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9085 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
9086 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
9087 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
9089 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
9090 ckey.dwColorSpaceLowValue = 0x00000000;
9091 ckey.dwColorSpaceHighValue = 0x00000000;
9092 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
9093 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
9095 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
9096 ckey.dwColorSpaceLowValue = 0x00000001;
9097 ckey.dwColorSpaceHighValue = 0x00000000;
9098 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
9099 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
9100 ckey.dwColorSpaceLowValue = 0x00000000;
9101 ckey.dwColorSpaceHighValue = 0x00000001;
9102 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
9103 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
9104 /* Range destination keys don't work either. */
9105 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
9106 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
9108 /* Just to show it's not because of A, R, and G having equal values. */
9109 ckey.dwColorSpaceLowValue = 0x00000000;
9110 ckey.dwColorSpaceHighValue = 0x01010101;
9111 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
9112 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
9114 /* None of these operations modified the key. */
9115 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9116 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
9117 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
9118 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
9120 IDirectDrawSurface_Release(surface),
9121 refcount = IDirectDraw2_Release(ddraw);
9122 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9123 DestroyWindow(window);
9126 static void test_shademode(void)
9128 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
9129 IDirect3DMaterial2 *background;
9130 IDirect3DViewport2 *viewport;
9131 IDirect3DDevice2 *device;
9132 IDirectDrawSurface *rt;
9133 DWORD color0, color1;
9134 IDirectDraw2 *ddraw;
9135 D3DLVERTEX *quad;
9136 ULONG refcount;
9137 UINT i, count;
9138 HWND window;
9139 HRESULT hr;
9140 static D3DLVERTEX quad_strip[] =
9142 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}},
9143 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
9144 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
9145 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffffffff}},
9147 quad_list[] =
9149 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}},
9150 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
9151 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
9153 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
9154 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
9155 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffffffff}},
9157 static const struct
9159 DWORD primtype;
9160 DWORD shademode;
9161 DWORD color0, color1;
9163 tests[] =
9165 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x0000ff00},
9166 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
9167 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
9168 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
9169 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
9170 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
9173 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9174 0, 0, 640, 480, 0, 0, 0, 0);
9175 ddraw = create_ddraw();
9176 ok(!!ddraw, "Failed to create a ddraw object.\n");
9177 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
9179 skip("Failed to create a 3D device, skipping test.\n");
9180 IDirectDraw2_Release(ddraw);
9181 DestroyWindow(window);
9182 return;
9185 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
9186 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9188 background = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
9189 viewport = create_viewport(device, 0, 0, 640, 480);
9190 viewport_set_background(device, viewport, background);
9191 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
9192 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
9194 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
9195 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
9197 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
9198 * the color fixups we have to do for FLAT shading will be dependent on that. */
9200 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
9202 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9203 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
9205 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
9206 ok(hr == D3D_OK, "Failed to set shade mode, hr %#x.\n", hr);
9208 hr = IDirect3DDevice2_BeginScene(device);
9209 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9210 quad = tests[i].primtype == D3DPT_TRIANGLESTRIP ? quad_strip : quad_list;
9211 count = tests[i].primtype == D3DPT_TRIANGLESTRIP ? 4 : 6;
9212 hr = IDirect3DDevice2_DrawPrimitive(device, tests[i].primtype, D3DVT_LVERTEX, quad, count, 0);
9213 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9214 hr = IDirect3DDevice2_EndScene(device);
9215 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9217 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
9218 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
9220 /* For D3DSHADE_FLAT it should take the color of the first vertex of
9221 * each triangle. This requires EXT_provoking_vertex or similar
9222 * functionality being available. */
9223 /* PHONG should be the same as GOURAUD, since no hardware implements
9224 * this. */
9225 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
9226 i, color0, tests[i].color0);
9227 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
9228 i, color1, tests[i].color1);
9231 destroy_viewport(device, viewport);
9232 destroy_material(background);
9233 IDirectDrawSurface_Release(rt);
9234 refcount = IDirect3DDevice2_Release(device);
9235 ok(!refcount, "Device has %u references left.\n", refcount);
9236 IDirectDraw_Release(ddraw);
9237 DestroyWindow(window);
9240 static void test_lockrect_invalid(void)
9242 unsigned int i, r;
9243 IDirectDraw2 *ddraw;
9244 IDirectDrawSurface *surface1;
9245 IDirectDrawSurface2 *surface;
9246 HWND window;
9247 HRESULT hr;
9248 DDSURFACEDESC surface_desc;
9249 DDCAPS hal_caps;
9250 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
9251 static RECT valid[] =
9253 {60, 60, 68, 68},
9254 {60, 60, 60, 68},
9255 {60, 60, 68, 60},
9256 {120, 60, 128, 68},
9257 {60, 120, 68, 128},
9259 static RECT invalid[] =
9261 {68, 60, 60, 68}, /* left > right */
9262 {60, 68, 68, 60}, /* top > bottom */
9263 {-8, 60, 0, 68}, /* left < surface */
9264 {60, -8, 68, 0}, /* top < surface */
9265 {-16, 60, -8, 68}, /* right < surface */
9266 {60, -16, 68, -8}, /* bottom < surface */
9267 {60, 60, 136, 68}, /* right > surface */
9268 {60, 60, 68, 136}, /* bottom > surface */
9269 {136, 60, 144, 68}, /* left > surface */
9270 {60, 136, 68, 144}, /* top > surface */
9272 static const struct
9274 DWORD caps;
9275 const char *name;
9276 HRESULT hr;
9278 resources[] =
9280 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, "sysmem offscreenplain", DDERR_INVALIDPARAMS},
9281 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, "vidmem offscreenplain", DDERR_INVALIDPARAMS},
9282 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "sysmem texture", DDERR_INVALIDPARAMS},
9283 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "vidmem texture", DDERR_INVALIDPARAMS},
9286 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9287 0, 0, 640, 480, 0, 0, 0, 0);
9288 ddraw = create_ddraw();
9289 ok(!!ddraw, "Failed to create a ddraw object.\n");
9290 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9291 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9293 memset(&hal_caps, 0, sizeof(hal_caps));
9294 hal_caps.dwSize = sizeof(hal_caps);
9295 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
9296 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9297 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
9299 skip("Required surface types not supported, skipping test.\n");
9300 goto done;
9303 for (r = 0; r < sizeof(resources) / sizeof(*resources); ++r)
9305 memset(&surface_desc, 0, sizeof(surface_desc));
9306 surface_desc.dwSize = sizeof(surface_desc);
9307 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9308 surface_desc.ddsCaps.dwCaps = resources[r].caps;
9309 surface_desc.dwWidth = 128;
9310 surface_desc.dwHeight = 128;
9311 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
9312 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
9313 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
9314 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xff0000;
9315 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x00ff00;
9316 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x0000ff;
9318 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
9319 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, resources[r].name);
9320 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
9321 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface2 interface, hr %#x.\n", hr);
9322 IDirectDrawSurface_Release(surface1);
9324 hr = IDirectDrawSurface2_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
9325 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
9327 for (i = 0; i < sizeof(valid) / sizeof(*valid); ++i)
9329 RECT *rect = &valid[i];
9331 memset(&surface_desc, 0, sizeof(surface_desc));
9332 surface_desc.dwSize = sizeof(surface_desc);
9334 hr = IDirectDrawSurface2_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
9335 ok(SUCCEEDED(hr), "Lock failed (%#x) for rect [%d, %d]->[%d, %d], type %s.\n",
9336 hr, rect->left, rect->top, rect->right, rect->bottom, resources[r].name);
9338 hr = IDirectDrawSurface2_Unlock(surface, NULL);
9339 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
9342 for (i = 0; i < sizeof(invalid) / sizeof(*invalid); ++i)
9344 RECT *rect = &invalid[i];
9346 memset(&surface_desc, 1, sizeof(surface_desc));
9347 surface_desc.dwSize = sizeof(surface_desc);
9349 hr = IDirectDrawSurface2_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
9350 ok(hr == resources[r].hr, "Lock returned %#x for rect [%d, %d]->[%d, %d], type %s.\n",
9351 hr, rect->left, rect->top, rect->right, rect->bottom, resources[r].name);
9352 if (SUCCEEDED(hr))
9354 hr = IDirectDrawSurface2_Unlock(surface, NULL);
9355 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
9357 else
9358 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9361 hr = IDirectDrawSurface2_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
9362 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#x, type %s.\n",
9363 hr, resources[r].name);
9364 hr = IDirectDrawSurface2_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
9365 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#x, type %s.\n",
9366 hr, resources[r].name);
9367 hr = IDirectDrawSurface2_Unlock(surface, NULL);
9368 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
9370 hr = IDirectDrawSurface2_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
9371 ok(SUCCEEDED(hr), "Lock(rect = [%d, %d]->[%d, %d]) failed (%#x).\n",
9372 valid[0].left, valid[0].top, valid[0].right, valid[0].bottom, hr);
9373 hr = IDirectDrawSurface2_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
9374 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = [%d, %d]->[%d, %d]) failed (%#x).\n",
9375 valid[0].left, valid[0].top, valid[0].right, valid[0].bottom, hr);
9377 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
9378 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
9380 hr = IDirectDrawSurface2_Unlock(surface, NULL);
9381 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
9383 IDirectDrawSurface2_Release(surface);
9386 done:
9387 IDirectDraw2_Release(ddraw);
9388 DestroyWindow(window);
9391 static void test_yv12_overlay(void)
9393 IDirectDrawSurface *src_surface, *dst_surface;
9394 RECT rect = {13, 17, 14, 18};
9395 unsigned int offset, y;
9396 unsigned char *base;
9397 IDirectDraw2 *ddraw;
9398 DDSURFACEDESC desc;
9399 HWND window;
9400 HRESULT hr;
9402 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9403 0, 0, 640, 480, 0, 0, 0, 0);
9404 ddraw = create_ddraw();
9405 ok(!!ddraw, "Failed to create a ddraw object.\n");
9406 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9407 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9409 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
9411 skip("Failed to create a YV12 overlay, skipping test.\n");
9412 goto done;
9415 memset(&desc, 0, sizeof(desc));
9416 desc.dwSize = sizeof(desc);
9417 hr = IDirectDrawSurface_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
9418 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9420 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
9421 "Got unexpected flags %#x.\n", desc.dwFlags);
9422 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
9423 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
9424 "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps);
9425 ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth);
9426 ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight);
9427 /* The overlay pitch seems to have 256 byte alignment. */
9428 ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch);
9430 /* Fill the surface with some data for the blit test. */
9431 base = desc.lpSurface;
9432 /* Luminance */
9433 for (y = 0; y < desc.dwHeight; ++y)
9435 memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth);
9437 /* V */
9438 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
9440 memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth);
9442 /* U */
9443 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
9445 memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth);
9448 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
9449 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9451 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
9452 * other block-based formats like DXT the entire Y channel is stored in
9453 * one big chunk of memory, followed by the chroma channels. So partial
9454 * locks do not really make sense. Show that they are allowed nevertheless
9455 * and the offset points into the luminance data. */
9456 hr = IDirectDrawSurface_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
9457 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9458 offset = ((const unsigned char *)desc.lpSurface - base);
9459 ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n",
9460 offset, rect.top * U1(desc).lPitch + rect.left);
9461 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
9462 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9464 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
9466 /* Windows XP with a Radeon X1600 GPU refuses to create a second
9467 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
9468 skip("Failed to create a second YV12 surface, skipping blit test.\n");
9469 IDirectDrawSurface_Release(src_surface);
9470 goto done;
9473 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
9474 /* VMware rejects YV12 blits. This behavior has not been seen on real
9475 * hardware yet, so mark it broken. */
9476 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr);
9478 if (SUCCEEDED(hr))
9480 memset(&desc, 0, sizeof(desc));
9481 desc.dwSize = sizeof(desc);
9482 hr = IDirectDrawSurface_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
9483 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9485 base = desc.lpSurface;
9486 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
9487 base += desc.dwHeight * U1(desc).lPitch;
9488 todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
9489 base += desc.dwHeight / 4 * U1(desc).lPitch;
9490 todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
9492 hr = IDirectDrawSurface_Unlock(dst_surface, NULL);
9493 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9496 IDirectDrawSurface_Release(dst_surface);
9497 IDirectDrawSurface_Release(src_surface);
9498 done:
9499 IDirectDraw2_Release(ddraw);
9500 DestroyWindow(window);
9503 static void test_offscreen_overlay(void)
9505 IDirectDrawSurface *overlay, *offscreen, *primary;
9506 DDSURFACEDESC surface_desc;
9507 IDirectDraw2 *ddraw;
9508 HWND window;
9509 HRESULT hr;
9510 HDC dc;
9512 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9513 0, 0, 640, 480, 0, 0, 0, 0);
9514 ddraw = create_ddraw();
9515 ok(!!ddraw, "Failed to create a ddraw object.\n");
9516 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9517 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9519 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
9521 skip("Failed to create a UYVY overlay, skipping test.\n");
9522 goto done;
9525 memset(&surface_desc, 0, sizeof(surface_desc));
9526 surface_desc.dwSize = sizeof(surface_desc);
9527 surface_desc.dwFlags = DDSD_CAPS;
9528 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
9529 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
9530 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
9532 /* On Windows 7, and probably Vista, UpdateOverlay() will return
9533 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
9534 * surface prevents this by disabling the dwm. */
9535 hr = IDirectDrawSurface_GetDC(primary, &dc);
9536 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
9537 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
9538 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9540 /* Try to overlay a NULL surface. */
9541 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
9542 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9543 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
9544 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9546 /* Try to overlay an offscreen surface. */
9547 memset(&surface_desc, 0, sizeof(surface_desc));
9548 surface_desc.dwSize = sizeof(surface_desc);
9549 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9550 surface_desc.dwWidth = 64;
9551 surface_desc.dwHeight = 64;
9552 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9553 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
9554 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
9555 surface_desc.ddpfPixelFormat.dwFourCC = 0;
9556 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
9557 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xf800;
9558 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x07e0;
9559 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x001f;
9560 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
9561 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
9563 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
9564 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
9566 /* Try to overlay the primary with a non-overlay surface. */
9567 hr = IDirectDrawSurface_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
9568 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
9569 hr = IDirectDrawSurface_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_HIDE, NULL);
9570 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
9572 IDirectDrawSurface_Release(offscreen);
9573 IDirectDrawSurface_Release(primary);
9574 IDirectDrawSurface_Release(overlay);
9575 done:
9576 IDirectDraw2_Release(ddraw);
9577 DestroyWindow(window);
9580 static void test_overlay_rect(void)
9582 IDirectDrawSurface *overlay, *primary;
9583 DDSURFACEDESC surface_desc;
9584 RECT rect = {0, 0, 64, 64};
9585 IDirectDraw2 *ddraw;
9586 LONG pos_x, pos_y;
9587 HRESULT hr, hr2;
9588 HWND window;
9589 HDC dc;
9591 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9592 0, 0, 640, 480, 0, 0, 0, 0);
9593 ddraw = create_ddraw();
9594 ok(!!ddraw, "Failed to create a ddraw object.\n");
9595 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9596 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9598 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
9600 skip("Failed to create a UYVY overlay, skipping test.\n");
9601 goto done;
9604 memset(&surface_desc, 0, sizeof(surface_desc));
9605 surface_desc.dwSize = sizeof(surface_desc);
9606 surface_desc.dwFlags = DDSD_CAPS;
9607 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
9608 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
9609 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
9611 /* On Windows 7, and probably Vista, UpdateOverlay() will return
9612 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
9613 * surface prevents this by disabling the dwm. */
9614 hr = IDirectDrawSurface_GetDC(primary, &dc);
9615 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
9616 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
9617 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9619 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is
9620 * used. This is not true in Windows Vista and earlier, but changed in
9621 * Windows 7. */
9622 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
9623 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
9624 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
9625 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
9626 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
9627 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9629 /* Show that the overlay position is the (top, left) coordinate of the
9630 * destination rectangle. */
9631 OffsetRect(&rect, 32, 16);
9632 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
9633 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
9634 pos_x = -1; pos_y = -1;
9635 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
9636 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
9637 ok(pos_x == rect.left, "Got unexpected pos_x %d, expected %d.\n", pos_x, rect.left);
9638 ok(pos_y == rect.top, "Got unexpected pos_y %d, expected %d.\n", pos_y, rect.top);
9640 /* Passing a NULL dest rect sets the position to 0/0. Visually it can be
9641 * seen that the overlay overlays the whole primary(==screen). */
9642 hr2 = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
9643 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS || hr2 == DDERR_OUTOFCAPS, "Got unexpected hr %#x.\n", hr2);
9644 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
9645 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
9646 if (SUCCEEDED(hr2))
9648 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
9649 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
9651 else
9653 ok(pos_x == 32, "Got unexpected pos_x %d.\n", pos_x);
9654 ok(pos_y == 16, "Got unexpected pos_y %d.\n", pos_y);
9657 /* The position cannot be retrieved when the overlay is not shown. */
9658 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
9659 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
9660 pos_x = -1; pos_y = -1;
9661 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
9662 ok(hr == DDERR_OVERLAYNOTVISIBLE, "Got unexpected hr %#x.\n", hr);
9663 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
9664 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
9666 IDirectDrawSurface_Release(primary);
9667 IDirectDrawSurface_Release(overlay);
9668 done:
9669 IDirectDraw2_Release(ddraw);
9670 DestroyWindow(window);
9673 static void test_blt(void)
9675 IDirectDrawSurface *surface, *rt;
9676 DDSURFACEDESC surface_desc;
9677 IDirect3DDevice2 *device;
9678 IDirectDraw2 *ddraw;
9679 unsigned int i;
9680 ULONG refcount;
9681 HWND window;
9682 HRESULT hr;
9684 static struct
9686 RECT src_rect;
9687 RECT dst_rect;
9688 HRESULT hr;
9690 test_data[] =
9692 {{160, 0, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit. */
9693 {{160, 480, 640, 0}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, flipped source. */
9694 {{640, 0, 160, 480}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, mirrored source. */
9695 {{160, 0, 480, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched x. */
9696 {{160, 160, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched y. */
9697 {{ 0, 0, 640, 480}, { 0, 0, 640, 480}, DD_OK}, /* Full surface blit. */
9698 {{ 0, 0, 640, 480}, { 0, 480, 640, 0}, DDERR_INVALIDRECT}, /* Full surface, flipped destination. */
9699 {{ 0, 0, 640, 480}, {640, 0, 0, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored destination. */
9700 {{ 0, 480, 640, 0}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, flipped source. */
9701 {{640, 0, 0, 480}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored source. */
9704 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9705 0, 0, 640, 480, 0, 0, 0, 0);
9706 ddraw = create_ddraw();
9707 ok(!!ddraw, "Failed to create a ddraw object.\n");
9708 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
9710 skip("Failed to create a 3D device, skipping test.\n");
9711 IDirectDraw2_Release(ddraw);
9712 DestroyWindow(window);
9713 return;
9716 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
9717 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9719 memset(&surface_desc, 0, sizeof(surface_desc));
9720 surface_desc.dwSize = sizeof(surface_desc);
9721 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
9722 surface_desc.dwWidth = 640;
9723 surface_desc.dwHeight = 480;
9724 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9725 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9726 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9728 hr = IDirectDrawSurface_Blt(surface, NULL, surface, NULL, 0, NULL);
9729 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
9731 hr = IDirectDrawSurface_Blt(surface, NULL, rt, NULL, 0, NULL);
9732 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
9734 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
9736 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
9737 surface, &test_data[i].src_rect, DDBLT_WAIT, NULL);
9738 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
9740 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
9741 rt, &test_data[i].src_rect, DDBLT_WAIT, NULL);
9742 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
9745 IDirectDrawSurface_Release(surface);
9746 IDirectDrawSurface_Release(rt);
9747 refcount = IDirect3DDevice2_Release(device);
9748 ok(!refcount, "Device has %u references left.\n", refcount);
9749 IDirectDraw2_Release(ddraw);
9750 DestroyWindow(window);
9753 static void test_getdc(void)
9755 IDirectDrawSurface *surface, *surface2, *tmp;
9756 DDSURFACEDESC surface_desc, map_desc;
9757 DDSCAPS caps = {DDSCAPS_COMPLEX};
9758 IDirectDraw2 *ddraw;
9759 unsigned int i;
9760 HWND window;
9761 HDC dc, dc2;
9762 HRESULT hr;
9764 static const struct
9766 const char *name;
9767 DDPIXELFORMAT format;
9768 BOOL getdc_supported;
9769 HRESULT alt_result;
9771 test_data[] =
9773 {"D3DFMT_A8R8G8B8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
9774 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}}, TRUE},
9775 {"D3DFMT_X8R8G8B8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
9776 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}}, TRUE},
9777 {"D3DFMT_R5G6B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
9778 {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}}, TRUE},
9779 {"D3DFMT_X1R5G5B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
9780 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}}, TRUE},
9781 {"D3DFMT_A1R5G5B5", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
9782 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}}, TRUE},
9783 {"D3DFMT_A4R4G4B4", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
9784 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
9785 {"D3DFMT_X4R4G4B4", {sizeof(test_data->format), DDPF_RGB, 0, {16},
9786 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
9787 {"D3DFMT_A2R10G10B10", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
9788 {0xc0000000}, {0x3ff00000}, {0x000ffc00}, {0x000003ff}}, TRUE},
9789 {"D3DFMT_A8B8G8R8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
9790 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
9791 {"D3DFMT_X8B8G8R8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
9792 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
9793 {"D3DFMT_R3G3B2", {sizeof(test_data->format), DDPF_RGB, 0, {8},
9794 {0x000000e0}, {0x0000001c}, {0x00000003}, {0x00000000}}, FALSE},
9795 /* GetDC() on a P8 surface fails unless the display mode is 8 bpp.
9796 * This is not implemented in wine yet, so disable the test for now.
9797 * Succeeding P8 GetDC() calls are tested in the ddraw:visual test.
9798 {"D3DFMT_P8", {sizeof(test_data->format), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0, {8 },
9799 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
9801 {"D3DFMT_L8", {sizeof(test_data->format), DDPF_LUMINANCE, 0, {8},
9802 {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
9803 {"D3DFMT_A8L8", {sizeof(test_data->format), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0, {16},
9804 {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}}, FALSE},
9805 {"D3DFMT_DXT1", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'), {0},
9806 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
9807 {"D3DFMT_DXT2", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'), {0},
9808 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
9809 {"D3DFMT_DXT3", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'), {0},
9810 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
9811 {"D3DFMT_DXT4", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'), {0},
9812 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
9813 {"D3DFMT_DXT5", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'), {0},
9814 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
9817 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9818 0, 0, 640, 480, 0, 0, 0, 0);
9819 ddraw = create_ddraw();
9820 ok(!!ddraw, "Failed to create a ddraw object.\n");
9821 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9822 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9824 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
9826 memset(&surface_desc, 0, sizeof(surface_desc));
9827 surface_desc.dwSize = sizeof(surface_desc);
9828 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9829 surface_desc.dwWidth = 64;
9830 surface_desc.dwHeight = 64;
9831 U4(surface_desc).ddpfPixelFormat = test_data[i].format;
9832 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9834 if (FAILED(IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
9836 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9837 if (FAILED(hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
9839 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
9840 continue;
9844 dc = (void *)0x1234;
9845 hr = IDirectDrawSurface_GetDC(surface, &dc);
9846 if (test_data[i].getdc_supported)
9847 ok(SUCCEEDED(hr) || (test_data[i].alt_result && hr == test_data[i].alt_result),
9848 "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9849 else
9850 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9852 if (SUCCEEDED(hr))
9854 unsigned int width_bytes;
9855 DIBSECTION dib;
9856 HBITMAP bitmap;
9857 DWORD type;
9858 int size;
9860 type = GetObjectType(dc);
9861 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
9862 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
9863 type = GetObjectType(bitmap);
9864 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
9866 size = GetObjectA(bitmap, sizeof(dib), &dib);
9867 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, test_data[i].name);
9868 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
9869 dib.dsBm.bmType, test_data[i].name);
9870 ok(dib.dsBm.bmWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
9871 dib.dsBm.bmWidth, test_data[i].name);
9872 ok(dib.dsBm.bmHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
9873 dib.dsBm.bmHeight, test_data[i].name);
9874 width_bytes = ((dib.dsBm.bmWidth * U1(test_data[i].format).dwRGBBitCount + 31) >> 3) & ~3;
9875 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
9876 dib.dsBm.bmWidthBytes, test_data[i].name);
9877 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
9878 dib.dsBm.bmPlanes, test_data[i].name);
9879 ok(dib.dsBm.bmBitsPixel == U1(test_data[i].format).dwRGBBitCount,
9880 "Got unexpected bit count %d for format %s.\n",
9881 dib.dsBm.bmBitsPixel, test_data[i].name);
9882 ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n",
9883 dib.dsBm.bmBits, test_data[i].name);
9885 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
9886 dib.dsBmih.biSize, test_data[i].name);
9887 ok(dib.dsBmih.biWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
9888 dib.dsBmih.biHeight, test_data[i].name);
9889 ok(dib.dsBmih.biHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
9890 dib.dsBmih.biHeight, test_data[i].name);
9891 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
9892 dib.dsBmih.biPlanes, test_data[i].name);
9893 ok(dib.dsBmih.biBitCount == U1(test_data[i].format).dwRGBBitCount,
9894 "Got unexpected bit count %u for format %s.\n",
9895 dib.dsBmih.biBitCount, test_data[i].name);
9896 ok(dib.dsBmih.biCompression == (U1(test_data[i].format).dwRGBBitCount == 16 ? BI_BITFIELDS : BI_RGB)
9897 || broken(U2(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
9898 "Got unexpected compression %#x for format %s.\n",
9899 dib.dsBmih.biCompression, test_data[i].name);
9900 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
9901 dib.dsBmih.biSizeImage, test_data[i].name);
9902 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
9903 dib.dsBmih.biXPelsPerMeter, test_data[i].name);
9904 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
9905 dib.dsBmih.biYPelsPerMeter, test_data[i].name);
9906 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
9907 dib.dsBmih.biClrUsed, test_data[i].name);
9908 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
9909 dib.dsBmih.biClrImportant, test_data[i].name);
9911 if (dib.dsBmih.biCompression == BI_BITFIELDS)
9913 ok((dib.dsBitfields[0] == U2(test_data[i].format).dwRBitMask
9914 && dib.dsBitfields[1] == U3(test_data[i].format).dwGBitMask
9915 && dib.dsBitfields[2] == U4(test_data[i].format).dwBBitMask)
9916 || broken(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2]),
9917 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
9918 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
9920 else
9922 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
9923 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
9924 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
9926 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, test_data[i].name);
9927 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, test_data[i].name);
9929 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
9930 ok(hr == DD_OK, "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9932 else
9934 ok(!dc, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
9937 IDirectDrawSurface_Release(surface);
9939 if (FAILED(hr))
9940 continue;
9942 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
9943 if (FAILED(hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
9945 skip("Failed to create mip-mapped texture for format %s (hr %#x), skipping tests.\n",
9946 test_data[i].name, hr);
9947 continue;
9950 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &tmp);
9951 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
9952 hr = IDirectDrawSurface_GetAttachedSurface(tmp, &caps, &surface2);
9953 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
9954 IDirectDrawSurface_Release(tmp);
9956 hr = IDirectDrawSurface_GetDC(surface, &dc);
9957 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9958 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
9959 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9960 hr = IDirectDrawSurface_GetDC(surface2, &dc);
9961 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9962 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
9963 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9965 hr = IDirectDrawSurface_GetDC(surface, &dc);
9966 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9967 dc2 = (void *)0x1234;
9968 hr = IDirectDrawSurface_GetDC(surface, &dc2);
9969 ok(hr == DDERR_DCALREADYCREATED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9970 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
9971 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
9972 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9973 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
9974 ok(hr == DDERR_NODC, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9976 map_desc.dwSize = sizeof(map_desc);
9977 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
9978 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
9979 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
9980 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9981 hr = IDirectDrawSurface_Unlock(surface, NULL);
9982 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
9983 hr = IDirectDrawSurface_Unlock(surface, NULL);
9984 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9986 hr = IDirectDrawSurface_GetDC(surface, &dc);
9987 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9988 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
9989 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9990 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
9991 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9993 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
9994 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
9995 hr = IDirectDrawSurface_GetDC(surface, &dc);
9996 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9997 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
9998 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9999 hr = IDirectDrawSurface_Unlock(surface, NULL);
10000 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
10002 hr = IDirectDrawSurface_GetDC(surface, &dc);
10003 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10004 hr = IDirectDrawSurface_GetDC(surface2, &dc2);
10005 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10006 hr = IDirectDrawSurface_ReleaseDC(surface2, dc2);
10007 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10008 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
10009 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10011 hr = IDirectDrawSurface_GetDC(surface2, &dc);
10012 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10013 hr = IDirectDrawSurface_GetDC(surface, &dc2);
10014 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10015 hr = IDirectDrawSurface_ReleaseDC(surface, dc2);
10016 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10017 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
10018 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10020 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
10021 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
10022 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
10023 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
10024 hr = IDirectDrawSurface_Unlock(surface2, NULL);
10025 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
10026 hr = IDirectDrawSurface_Unlock(surface, NULL);
10027 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
10029 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
10030 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
10031 hr = IDirectDrawSurface_GetDC(surface, &dc);
10032 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10033 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
10034 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10035 hr = IDirectDrawSurface_Unlock(surface, NULL);
10036 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
10038 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
10039 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
10040 hr = IDirectDrawSurface_GetDC(surface, &dc);
10041 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10042 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
10043 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10044 hr = IDirectDrawSurface_Unlock(surface2, NULL);
10045 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
10047 hr = IDirectDrawSurface_GetDC(surface, &dc);
10048 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10049 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
10050 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
10051 hr = IDirectDrawSurface_Unlock(surface2, NULL);
10052 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
10053 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
10054 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10056 hr = IDirectDrawSurface_GetDC(surface2, &dc);
10057 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10058 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
10059 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
10060 hr = IDirectDrawSurface_Unlock(surface, NULL);
10061 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
10062 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
10063 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10065 hr = IDirectDrawSurface_Unlock(surface, NULL);
10066 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
10067 hr = IDirectDrawSurface_GetDC(surface2, &dc);
10068 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10069 hr = IDirectDrawSurface_Unlock(surface, NULL);
10070 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
10071 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
10072 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10073 hr = IDirectDrawSurface_Unlock(surface, NULL);
10074 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
10076 hr = IDirectDrawSurface_Unlock(surface2, NULL);
10077 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
10078 hr = IDirectDrawSurface_GetDC(surface, &dc);
10079 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
10080 hr = IDirectDrawSurface_Unlock(surface2, NULL);
10081 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
10082 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
10083 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
10084 hr = IDirectDrawSurface_Unlock(surface2, NULL);
10085 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
10087 IDirectDrawSurface_Release(surface2);
10088 IDirectDrawSurface_Release(surface);
10091 IDirectDraw2_Release(ddraw);
10092 DestroyWindow(window);
10095 static void test_draw_primitive(void)
10097 static WORD indices[] = {0, 1, 2, 3};
10098 static D3DVERTEX quad[] =
10100 {{-1.0f}, {-1.0f}, {0.0f}},
10101 {{-1.0f}, { 1.0f}, {0.0f}},
10102 {{ 1.0f}, {-1.0f}, {0.0f}},
10103 {{ 1.0f}, { 1.0f}, {0.0f}},
10105 IDirect3DViewport2 *viewport;
10106 IDirect3DDevice2 *device;
10107 IDirectDraw2 *ddraw;
10108 IDirect3D2 *d3d;
10109 ULONG refcount;
10110 HWND window;
10111 HRESULT hr;
10113 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10114 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10115 ddraw = create_ddraw();
10116 ok(!!ddraw, "Failed to create a ddraw object.\n");
10117 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
10119 skip("Failed to create a 3D device, skipping test.\n");
10120 IDirectDraw2_Release(ddraw);
10121 DestroyWindow(window);
10122 return;
10125 viewport = create_viewport(device, 0, 0, 640, 480);
10126 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
10127 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
10129 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
10130 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
10132 IDirect3D2_Release(d3d);
10134 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, NULL, 0, 0);
10135 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10136 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, 0);
10137 todo_wine ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10139 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, indices, 4, 0);
10140 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10142 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, NULL, 0, 0);
10143 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10144 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
10145 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10146 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, indices, 4, 0);
10147 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10149 destroy_viewport(device, viewport);
10150 refcount = IDirect3DDevice2_Release(device);
10151 ok(!refcount, "Device has %u references left.\n", refcount);
10152 IDirectDraw2_Release(ddraw);
10153 DestroyWindow(window);
10156 START_TEST(ddraw2)
10158 IDirectDraw2 *ddraw;
10159 DEVMODEW current_mode;
10161 if (!(ddraw = create_ddraw()))
10163 skip("Failed to create a ddraw object, skipping tests.\n");
10164 return;
10166 IDirectDraw2_Release(ddraw);
10168 memset(&current_mode, 0, sizeof(current_mode));
10169 current_mode.dmSize = sizeof(current_mode);
10170 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
10171 registry_mode.dmSize = sizeof(registry_mode);
10172 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
10173 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
10174 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
10176 skip("Current mode does not match registry mode, skipping test.\n");
10177 return;
10180 test_coop_level_create_device_window();
10181 test_clipper_blt();
10182 test_coop_level_d3d_state();
10183 test_surface_interface_mismatch();
10184 test_coop_level_threaded();
10185 test_depth_blit();
10186 test_texture_load_ckey();
10187 test_viewport();
10188 test_zenable();
10189 test_ck_rgba();
10190 test_ck_default();
10191 test_ck_complex();
10192 test_surface_qi();
10193 test_device_qi();
10194 test_wndproc();
10195 test_window_style();
10196 test_redundant_mode_set();
10197 test_coop_level_mode_set();
10198 test_coop_level_mode_set_multi();
10199 test_initialize();
10200 test_coop_level_surf_create();
10201 test_coop_level_multi_window();
10202 test_clear_rect_count();
10203 test_coop_level_versions();
10204 test_lighting_interface_versions();
10205 test_coop_level_activateapp();
10206 test_unsupported_formats();
10207 test_rt_caps();
10208 test_primary_caps();
10209 test_surface_lock();
10210 test_surface_discard();
10211 test_flip();
10212 test_set_surface_desc();
10213 test_user_memory_getdc();
10214 test_sysmem_overlay();
10215 test_primary_palette();
10216 test_surface_attachment();
10217 test_pixel_format();
10218 test_create_surface_pitch();
10219 test_mipmap();
10220 test_palette_complex();
10221 test_p8_rgb_blit();
10222 test_material();
10223 test_lighting();
10224 test_specular_lighting();
10225 test_palette_gdi();
10226 test_palette_alpha();
10227 test_lost_device();
10228 test_surface_desc_lock();
10229 test_texturemapblend();
10230 test_viewport_clear_rect();
10231 test_color_fill();
10232 test_colorkey_precision();
10233 test_range_colorkey();
10234 test_shademode();
10235 test_lockrect_invalid();
10236 test_yv12_overlay();
10237 test_offscreen_overlay();
10238 test_overlay_rect();
10239 test_blt();
10240 test_getdc();
10241 test_draw_primitive();