wined3d: Implement color keying in the glsl fragment pipeline.
[wine.git] / dlls / ddraw / tests / ddraw4.c
blobac31e24d844fd38726b1871ec468991f6e92832f
1 /*
2 * Copyright 2011-2014 Henri Verbeet for CodeWeavers
3 * Copyright 2012-2014 Stefan Dösinger for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
21 #include "wine/test.h"
22 #include <limits.h>
23 #include "d3d.h"
25 static DEVMODEW registry_mode;
27 struct vec2
29 float x, y;
32 struct vec3
34 float x, y, z;
37 struct vec4
39 float x, y, z, w;
42 struct create_window_thread_param
44 HWND window;
45 HANDLE window_created;
46 HANDLE destroy_window;
47 HANDLE thread;
50 static BOOL compare_float(float f, float g, unsigned int ulps)
52 int x = *(int *)&f;
53 int y = *(int *)&g;
55 if (x < 0)
56 x = INT_MIN - x;
57 if (y < 0)
58 y = INT_MIN - y;
60 if (abs(x - y) > ulps)
61 return FALSE;
63 return TRUE;
66 static BOOL compare_vec4(struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
68 return compare_float(vec->x, x, ulps)
69 && compare_float(vec->y, y, ulps)
70 && compare_float(vec->z, z, ulps)
71 && compare_float(vec->w, w, ulps);
74 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
76 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
77 c1 >>= 8; c2 >>= 8;
78 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
79 c1 >>= 8; c2 >>= 8;
80 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
81 c1 >>= 8; c2 >>= 8;
82 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
83 return TRUE;
86 static DWORD WINAPI create_window_thread_proc(void *param)
88 struct create_window_thread_param *p = param;
89 DWORD res;
90 BOOL ret;
92 p->window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
93 0, 0, 640, 480, 0, 0, 0, 0);
94 ret = SetEvent(p->window_created);
95 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
97 for (;;)
99 MSG msg;
101 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
102 DispatchMessageA(&msg);
103 res = WaitForSingleObject(p->destroy_window, 100);
104 if (res == WAIT_OBJECT_0)
105 break;
106 if (res != WAIT_TIMEOUT)
108 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
109 break;
113 DestroyWindow(p->window);
115 return 0;
118 static void create_window_thread(struct create_window_thread_param *p)
120 DWORD res, tid;
122 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
123 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
124 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
125 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
126 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
127 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
128 res = WaitForSingleObject(p->window_created, INFINITE);
129 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
132 static void destroy_window_thread(struct create_window_thread_param *p)
134 SetEvent(p->destroy_window);
135 WaitForSingleObject(p->thread, INFINITE);
136 CloseHandle(p->destroy_window);
137 CloseHandle(p->window_created);
138 CloseHandle(p->thread);
141 static IDirectDrawSurface4 *get_depth_stencil(IDirect3DDevice3 *device)
143 IDirectDrawSurface4 *rt, *ret;
144 DDSCAPS2 caps = {DDSCAPS_ZBUFFER, 0, 0, {0}};
145 HRESULT hr;
147 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
148 ok(SUCCEEDED(hr), "Failed to get the render target, hr %#x.\n", hr);
149 hr = IDirectDrawSurface4_GetAttachedSurface(rt, &caps, &ret);
150 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
151 IDirectDrawSurface4_Release(rt);
152 return ret;
155 static HRESULT set_display_mode(IDirectDraw4 *ddraw, DWORD width, DWORD height)
157 if (SUCCEEDED(IDirectDraw4_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
158 return DD_OK;
159 return IDirectDraw4_SetDisplayMode(ddraw, width, height, 24, 0, 0);
162 static D3DCOLOR get_surface_color(IDirectDrawSurface4 *surface, UINT x, UINT y)
164 RECT rect = {x, y, x + 1, y + 1};
165 DDSURFACEDESC2 surface_desc;
166 D3DCOLOR color;
167 HRESULT hr;
169 memset(&surface_desc, 0, sizeof(surface_desc));
170 surface_desc.dwSize = sizeof(surface_desc);
172 hr = IDirectDrawSurface4_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
173 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
174 if (FAILED(hr))
175 return 0xdeadbeef;
177 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
179 hr = IDirectDrawSurface4_Unlock(surface, &rect);
180 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
182 return color;
185 static HRESULT CALLBACK enum_z_fmt(DDPIXELFORMAT *format, void *ctx)
187 DDPIXELFORMAT *z_fmt = ctx;
189 if (U1(*format).dwZBufferBitDepth > U1(*z_fmt).dwZBufferBitDepth)
190 *z_fmt = *format;
192 return DDENUMRET_OK;
195 static IDirectDraw4 *create_ddraw(void)
197 IDirectDraw4 *ddraw4;
198 IDirectDraw *ddraw1;
199 HRESULT hr;
201 if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
202 return NULL;
204 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw4, (void **)&ddraw4);
205 IDirectDraw_Release(ddraw1);
206 if (FAILED(hr))
207 return NULL;
209 return ddraw4;
212 static IDirect3DDevice3 *create_device(HWND window, DWORD coop_level)
214 IDirectDrawSurface4 *surface, *ds;
215 IDirect3DDevice3 *device = NULL;
216 DDSURFACEDESC2 surface_desc;
217 IDirectDraw4 *ddraw4;
218 DDPIXELFORMAT z_fmt;
219 IDirect3D3 *d3d3;
220 HRESULT hr;
222 if (!(ddraw4 = create_ddraw()))
223 return NULL;
225 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, coop_level);
226 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
228 memset(&surface_desc, 0, sizeof(surface_desc));
229 surface_desc.dwSize = sizeof(surface_desc);
230 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
231 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
232 surface_desc.dwWidth = 640;
233 surface_desc.dwHeight = 480;
235 hr = IDirectDraw4_CreateSurface(ddraw4, &surface_desc, &surface, NULL);
236 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
238 if (coop_level & DDSCL_NORMAL)
240 IDirectDrawClipper *clipper;
242 hr = IDirectDraw4_CreateClipper(ddraw4, 0, &clipper, NULL);
243 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
244 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
245 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
246 hr = IDirectDrawSurface4_SetClipper(surface, clipper);
247 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
248 IDirectDrawClipper_Release(clipper);
251 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirect3D3, (void **)&d3d3);
252 IDirectDraw4_Release(ddraw4);
253 if (FAILED(hr))
255 IDirectDrawSurface4_Release(surface);
256 return NULL;
259 memset(&z_fmt, 0, sizeof(z_fmt));
260 hr = IDirect3D3_EnumZBufferFormats(d3d3, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
261 if (FAILED(hr) || !z_fmt.dwSize)
263 IDirect3D3_Release(d3d3);
264 IDirectDrawSurface4_Release(surface);
265 return NULL;
268 memset(&surface_desc, 0, sizeof(surface_desc));
269 surface_desc.dwSize = sizeof(surface_desc);
270 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
271 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
272 U4(surface_desc).ddpfPixelFormat = z_fmt;
273 surface_desc.dwWidth = 640;
274 surface_desc.dwHeight = 480;
275 hr = IDirectDraw4_CreateSurface(ddraw4, &surface_desc, &ds, NULL);
276 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
277 if (FAILED(hr))
279 IDirect3D3_Release(d3d3);
280 IDirectDrawSurface4_Release(surface);
281 return NULL;
284 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
285 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
286 IDirectDrawSurface4_Release(ds);
287 if (FAILED(hr))
289 IDirect3D3_Release(d3d3);
290 IDirectDrawSurface4_Release(surface);
291 return NULL;
294 hr = IDirect3D3_CreateDevice(d3d3, &IID_IDirect3DHALDevice, surface, &device, NULL);
295 IDirect3D3_Release(d3d3);
296 IDirectDrawSurface4_Release(surface);
297 if (FAILED(hr))
298 return NULL;
300 return device;
303 static IDirect3DViewport3 *create_viewport(IDirect3DDevice3 *device, UINT x, UINT y, UINT w, UINT h)
305 IDirect3DViewport3 *viewport;
306 D3DVIEWPORT2 vp;
307 IDirect3D3 *d3d;
308 HRESULT hr;
310 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
311 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
312 hr = IDirect3D3_CreateViewport(d3d, &viewport, NULL);
313 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
314 hr = IDirect3DDevice3_AddViewport(device, viewport);
315 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
316 memset(&vp, 0, sizeof(vp));
317 vp.dwSize = sizeof(vp);
318 vp.dwX = x;
319 vp.dwY = y;
320 vp.dwWidth = w;
321 vp.dwHeight = h;
322 vp.dvClipX = -1.0f;
323 vp.dvClipY = 1.0f;
324 vp.dvClipWidth = 2.0f;
325 vp.dvClipHeight = 2.0f;
326 vp.dvMinZ = 0.0f;
327 vp.dvMaxZ = 1.0f;
328 hr = IDirect3DViewport3_SetViewport2(viewport, &vp);
329 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
330 IDirect3D3_Release(d3d);
332 return viewport;
335 static void destroy_viewport(IDirect3DDevice3 *device, IDirect3DViewport3 *viewport)
337 HRESULT hr;
339 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
340 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
341 IDirect3DViewport3_Release(viewport);
344 static IDirect3DMaterial3 *create_material(IDirect3DDevice3 *device, D3DMATERIAL *mat)
346 IDirect3DMaterial3 *material;
347 IDirect3D3 *d3d;
348 HRESULT hr;
350 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
351 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
352 hr = IDirect3D3_CreateMaterial(d3d, &material, NULL);
353 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
354 hr = IDirect3DMaterial3_SetMaterial(material, mat);
355 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
356 IDirect3D3_Release(d3d);
358 return material;
361 static IDirect3DMaterial3 *create_diffuse_material(IDirect3DDevice3 *device, float r, float g, float b, float a)
363 D3DMATERIAL mat;
365 memset(&mat, 0, sizeof(mat));
366 mat.dwSize = sizeof(mat);
367 U1(U(mat).diffuse).r = r;
368 U2(U(mat).diffuse).g = g;
369 U3(U(mat).diffuse).b = b;
370 U4(U(mat).diffuse).a = a;
372 return create_material(device, &mat);
375 static IDirect3DMaterial3 *create_emissive_material(IDirect3DDevice3 *device, float r, float g, float b, float a)
377 D3DMATERIAL mat;
379 memset(&mat, 0, sizeof(mat));
380 mat.dwSize = sizeof(mat);
381 U1(U3(mat).emissive).r = r;
382 U2(U3(mat).emissive).g = g;
383 U3(U3(mat).emissive).b = b;
384 U4(U3(mat).emissive).a = a;
386 return create_material(device, &mat);
389 static void destroy_material(IDirect3DMaterial3 *material)
391 IDirect3DMaterial3_Release(material);
394 struct message
396 UINT message;
397 BOOL check_wparam;
398 WPARAM expect_wparam;
401 static const struct message *expect_messages;
403 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
405 if (expect_messages && message == expect_messages->message)
407 if (expect_messages->check_wparam)
408 ok (wparam == expect_messages->expect_wparam,
409 "Got unexpected wparam %lx for message %x, expected %lx.\n",
410 wparam, message, expect_messages->expect_wparam);
412 ++expect_messages;
415 return DefWindowProcA(hwnd, message, wparam, lparam);
418 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
419 * interface. This prevents subsequent SetCooperativeLevel() calls on a
420 * different window from failing with DDERR_HWNDALREADYSET. */
421 static void fix_wndproc(HWND window, LONG_PTR proc)
423 IDirectDraw4 *ddraw;
424 HRESULT hr;
426 if (!(ddraw = create_ddraw()))
427 return;
429 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
430 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
431 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
432 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
433 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
435 IDirectDraw4_Release(ddraw);
438 static void test_process_vertices(void)
440 IDirect3DVertexBuffer *src_vb, *dst_vb;
441 IDirect3DViewport3 *viewport;
442 D3DVERTEXBUFFERDESC vb_desc;
443 IDirect3DDevice3 *device;
444 struct vec3 *src_data;
445 struct vec4 *dst_data;
446 IDirect3D3 *d3d3;
447 D3DVIEWPORT2 vp2;
448 D3DVIEWPORT vp1;
449 HWND window;
450 HRESULT hr;
452 static D3DMATRIX identity =
454 1.0f, 0.0f, 0.0f, 0.0f,
455 0.0f, 1.0f, 0.0f, 0.0f,
456 0.0f, 0.0f, 1.0f, 0.0f,
457 0.0f, 0.0f, 0.0f, 1.0f,
459 static D3DMATRIX projection =
461 1.0f, 0.0f, 0.0f, 0.0f,
462 0.0f, 1.0f, 0.0f, 0.0f,
463 0.0f, 0.0f, 1.0f, 0.0f,
464 6.0f, 7.0f, 8.0f, 1.0f,
467 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
468 0, 0, 640, 480, 0, 0, 0, 0);
469 if (!(device = create_device(window, DDSCL_NORMAL)))
471 skip("Failed to create a 3D device, skipping test.\n");
472 DestroyWindow(window);
473 return;
476 hr = IDirect3DDevice3_GetDirect3D(device, &d3d3);
477 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
479 memset(&vb_desc, 0, sizeof(vb_desc));
480 vb_desc.dwSize = sizeof(vb_desc);
481 vb_desc.dwFVF = D3DFVF_XYZ;
482 vb_desc.dwNumVertices = 3;
483 hr = IDirect3D3_CreateVertexBuffer(d3d3, &vb_desc, &src_vb, 0, NULL);
484 ok(SUCCEEDED(hr), "Failed to create source vertex buffer, hr %#x.\n", hr);
486 hr = IDirect3DVertexBuffer_Lock(src_vb, DDLOCK_WRITEONLY, (void **)&src_data, NULL);
487 ok(SUCCEEDED(hr), "Failed to lock source vertex buffer, hr %#x.\n", hr);
488 src_data[0].x = -1.0f;
489 src_data[0].y = -1.0f;
490 src_data[0].z = -1.0f;
491 src_data[1].x = 0.0f;
492 src_data[1].y = 0.0f;
493 src_data[1].z = 0.0f;
494 src_data[2].x = 1.0f;
495 src_data[2].y = 1.0f;
496 src_data[2].z = 1.0f;
497 hr = IDirect3DVertexBuffer_Unlock(src_vb);
498 ok(SUCCEEDED(hr), "Failed to unlock source vertex buffer, hr %#x.\n", hr);
500 memset(&vb_desc, 0, sizeof(vb_desc));
501 vb_desc.dwSize = sizeof(vb_desc);
502 vb_desc.dwFVF = D3DFVF_XYZRHW;
503 vb_desc.dwNumVertices = 3;
504 hr = IDirect3D3_CreateVertexBuffer(d3d3, &vb_desc, &dst_vb, 0, NULL);
505 ok(SUCCEEDED(hr), "Failed to create destination vertex buffer, hr %#x.\n", hr);
507 hr = IDirect3D3_CreateViewport(d3d3, &viewport, NULL);
508 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
509 hr = IDirect3DDevice3_AddViewport(device, viewport);
510 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
511 vp2.dwSize = sizeof(vp2);
512 vp2.dwX = 10;
513 vp2.dwY = 20;
514 vp2.dwWidth = 100;
515 vp2.dwHeight = 200;
516 vp2.dvClipX = 2.0f;
517 vp2.dvClipY = 3.0f;
518 vp2.dvClipWidth = 4.0f;
519 vp2.dvClipHeight = 5.0f;
520 vp2.dvMinZ = -2.0f;
521 vp2.dvMaxZ = 3.0f;
522 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2);
523 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
524 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
525 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
527 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
528 ok(SUCCEEDED(hr), "Failed to set world transformation, hr %#x.\n", hr);
529 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &identity);
530 ok(SUCCEEDED(hr), "Failed to set view transformation, hr %#x.\n", hr);
531 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity);
532 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
534 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
535 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
537 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
538 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
539 ok(compare_vec4(&dst_data[0], -6.500e+1f, +1.800e+2f, +2.000e-1f, +1.000e+0f, 4096),
540 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
541 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
542 ok(compare_vec4(&dst_data[1], -4.000e+1f, +1.400e+2f, +4.000e-1f, +1.000e+0f, 4096),
543 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
544 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
545 ok(compare_vec4(&dst_data[2], -1.500e+1f, +1.000e+2f, +6.000e-1f, +1.000e+0f, 4096),
546 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
547 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
548 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
549 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
551 hr = IDirect3DDevice3_MultiplyTransform(device, D3DTRANSFORMSTATE_PROJECTION, &projection);
552 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
554 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
555 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
557 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
558 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
559 ok(compare_vec4(&dst_data[0], +8.500e+1f, -1.000e+2f, +1.800e+0f, +1.000e+0f, 4096),
560 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
561 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
562 ok(compare_vec4(&dst_data[1], +1.100e+2f, -1.400e+2f, +2.000e+0f, +1.000e+0f, 4096),
563 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
564 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
565 ok(compare_vec4(&dst_data[2], +1.350e+2f, -1.800e+2f, +2.200e+0f, +1.000e+0f, 4096),
566 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
567 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
568 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
569 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
571 vp2.dwSize = sizeof(vp2);
572 vp2.dwX = 30;
573 vp2.dwY = 40;
574 vp2.dwWidth = 90;
575 vp2.dwHeight = 80;
576 vp2.dvClipX = 4.0f;
577 vp2.dvClipY = 6.0f;
578 vp2.dvClipWidth = 2.0f;
579 vp2.dvClipHeight = 4.0f;
580 vp2.dvMinZ = 3.0f;
581 vp2.dvMaxZ = -2.0f;
582 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2);
583 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
585 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
586 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
588 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
589 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
590 ok(compare_vec4(&dst_data[0], +7.500e+1f, +4.000e+1f, -8.000e-1f, +1.000e+0f, 4096),
591 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
592 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
593 ok(compare_vec4(&dst_data[1], +1.200e+2f, +2.000e+1f, -1.000e+0f, +1.000e+0f, 4096),
594 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
595 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
596 ok(compare_vec4(&dst_data[2], +1.650e+2f, +0.000e+0f, -1.200e+0f, +1.000e+0f, 4096),
597 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
598 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
599 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
600 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
602 vp1.dwSize = sizeof(vp1);
603 vp1.dwX = 30;
604 vp1.dwY = 40;
605 vp1.dwWidth = 90;
606 vp1.dwHeight = 80;
607 vp1.dvScaleX = 7.0f;
608 vp1.dvScaleY = 2.0f;
609 vp1.dvMaxX = 6.0f;
610 vp1.dvMaxY = 10.0f;
611 vp1.dvMinZ = -2.0f;
612 vp1.dvMaxZ = 3.0f;
613 hr = IDirect3DViewport3_SetViewport(viewport, &vp1);
614 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
616 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
617 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
619 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
620 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
621 ok(compare_vec4(&dst_data[0], +1.100e+2f, +6.800e+1f, +7.000e+0f, +1.000e+0f, 4096),
622 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
623 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
624 ok(compare_vec4(&dst_data[1], +1.170e+2f, +6.600e+1f, +8.000e+0f, +1.000e+0f, 4096),
625 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
626 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
627 ok(compare_vec4(&dst_data[2], +1.240e+2f, +6.400e+1f, +9.000e+0f, +1.000e+0f, 4096),
628 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
629 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
630 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
631 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
633 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
634 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
636 IDirect3DVertexBuffer_Release(dst_vb);
637 IDirect3DVertexBuffer_Release(src_vb);
638 IDirect3DViewport3_Release(viewport);
639 IDirect3D3_Release(d3d3);
640 IDirect3DDevice3_Release(device);
641 DestroyWindow(window);
644 static void test_coop_level_create_device_window(void)
646 HWND focus_window, device_window;
647 IDirectDraw4 *ddraw;
648 HRESULT hr;
650 focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
651 0, 0, 640, 480, 0, 0, 0, 0);
652 ddraw = create_ddraw();
653 ok(!!ddraw, "Failed to create a ddraw object.\n");
655 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
656 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
657 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
658 ok(!device_window, "Unexpected device window found.\n");
659 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
660 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
661 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
662 ok(!device_window, "Unexpected device window found.\n");
663 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
664 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
665 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
666 ok(!device_window, "Unexpected device window found.\n");
667 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
668 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
669 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
670 ok(!device_window, "Unexpected device window found.\n");
671 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
672 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
673 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
674 ok(!device_window, "Unexpected device window found.\n");
676 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
677 if (broken(hr == DDERR_INVALIDPARAMS))
679 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
680 IDirectDraw4_Release(ddraw);
681 DestroyWindow(focus_window);
682 return;
685 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
686 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
687 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
688 ok(!device_window, "Unexpected device window found.\n");
689 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
690 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
691 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
692 ok(!device_window, "Unexpected device window found.\n");
694 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
695 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
696 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
697 ok(!device_window, "Unexpected device window found.\n");
698 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
699 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
700 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
701 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
702 ok(!!device_window, "Device window not found.\n");
704 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
705 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
706 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
707 ok(!device_window, "Unexpected device window found.\n");
708 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
709 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
710 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
711 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
712 ok(!!device_window, "Device window not found.\n");
714 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
715 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
716 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
717 ok(!device_window, "Unexpected device window found.\n");
718 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
719 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
720 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
721 ok(!device_window, "Unexpected device window found.\n");
722 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
723 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
724 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
725 ok(!device_window, "Unexpected device window found.\n");
726 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
727 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
728 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
729 ok(!!device_window, "Device window not found.\n");
731 IDirectDraw4_Release(ddraw);
732 DestroyWindow(focus_window);
735 static void test_clipper_blt(void)
737 IDirectDrawSurface4 *src_surface, *dst_surface;
738 RECT client_rect, src_rect;
739 IDirectDrawClipper *clipper;
740 DDSURFACEDESC2 surface_desc;
741 unsigned int i, j, x, y;
742 IDirectDraw4 *ddraw;
743 RGNDATA *rgn_data;
744 D3DCOLOR color;
745 HRGN r1, r2;
746 HWND window;
747 DDBLTFX fx;
748 HRESULT hr;
749 DWORD *ptr;
750 DWORD ret;
752 static const DWORD src_data[] =
754 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
755 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
756 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
758 static const D3DCOLOR expected1[] =
760 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
761 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
762 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
763 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
765 /* Nvidia on Windows seems to have an off-by-one error
766 * when processing source rectangles. Our left = 1 and
767 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
768 * read as well, but only for the edge pixels on the
769 * output image. The bug happens on the y axis as well,
770 * but we only read one row there, and all source rows
771 * contain the same data. This bug is not dependent on
772 * the presence of a clipper. */
773 static const D3DCOLOR expected1_broken[] =
775 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
776 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
777 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
778 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
780 static const D3DCOLOR expected2[] =
782 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
783 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
784 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
785 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
788 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
789 10, 10, 640, 480, 0, 0, 0, 0);
790 ShowWindow(window, SW_SHOW);
791 ddraw = create_ddraw();
792 ok(!!ddraw, "Failed to create a ddraw object.\n");
794 ret = GetClientRect(window, &client_rect);
795 ok(ret, "Failed to get client rect.\n");
796 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
797 ok(ret, "Failed to map client rect.\n");
799 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
800 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
802 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL);
803 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
804 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
805 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
806 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
807 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
808 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
809 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
810 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
811 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
812 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
813 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
814 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
815 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
816 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
817 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
818 rgn_data->rdh.rcBound.left, rgn_data->rdh.rcBound.top,
819 rgn_data->rdh.rcBound.right, rgn_data->rdh.rcBound.bottom,
820 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
821 HeapFree(GetProcessHeap(), 0, rgn_data);
823 r1 = CreateRectRgn(0, 0, 320, 240);
824 ok(!!r1, "Failed to create region.\n");
825 r2 = CreateRectRgn(320, 240, 640, 480);
826 ok(!!r2, "Failed to create region.\n");
827 CombineRgn(r1, r1, r2, RGN_OR);
828 ret = GetRegionData(r1, 0, NULL);
829 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
830 ret = GetRegionData(r1, ret, rgn_data);
831 ok(!!ret, "Failed to get region data.\n");
833 DeleteObject(r2);
834 DeleteObject(r1);
836 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
837 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
838 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
839 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
840 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
841 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
843 HeapFree(GetProcessHeap(), 0, rgn_data);
845 memset(&surface_desc, 0, sizeof(surface_desc));
846 surface_desc.dwSize = sizeof(surface_desc);
847 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
848 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
849 surface_desc.dwWidth = 640;
850 surface_desc.dwHeight = 480;
851 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
852 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
853 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
854 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
855 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
856 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
858 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
859 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
860 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
861 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
863 memset(&fx, 0, sizeof(fx));
864 fx.dwSize = sizeof(fx);
865 hr = IDirectDrawSurface4_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
866 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
867 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
868 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
870 hr = IDirectDrawSurface4_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
871 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
872 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
873 ptr = surface_desc.lpSurface;
874 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
875 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
876 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
877 hr = IDirectDrawSurface4_Unlock(src_surface, NULL);
878 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
880 hr = IDirectDrawSurface4_SetClipper(dst_surface, clipper);
881 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
883 SetRect(&src_rect, 1, 1, 5, 2);
884 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
885 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
886 for (i = 0; i < 4; ++i)
888 for (j = 0; j < 4; ++j)
890 x = 80 * ((2 * j) + 1);
891 y = 60 * ((2 * i) + 1);
892 color = get_surface_color(dst_surface, x, y);
893 ok(compare_color(color, expected1[i * 4 + j], 1)
894 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
895 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
899 U5(fx).dwFillColor = 0xff0000ff;
900 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
901 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
902 for (i = 0; i < 4; ++i)
904 for (j = 0; j < 4; ++j)
906 x = 80 * ((2 * j) + 1);
907 y = 60 * ((2 * i) + 1);
908 color = get_surface_color(dst_surface, x, y);
909 ok(compare_color(color, expected2[i * 4 + j], 1),
910 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
914 hr = IDirectDrawSurface4_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
915 ok(hr == DDERR_BLTFASTCANTCLIP, "Got unexpected hr %#x.\n", hr);
917 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
918 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
919 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
920 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
921 DestroyWindow(window);
922 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
923 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
924 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
925 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
926 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
927 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
928 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
929 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
930 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
931 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
932 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
933 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
935 IDirectDrawSurface4_Release(dst_surface);
936 IDirectDrawSurface4_Release(src_surface);
937 IDirectDrawClipper_Release(clipper);
938 IDirectDraw4_Release(ddraw);
941 static void test_coop_level_d3d_state(void)
943 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
944 IDirectDrawSurface4 *rt, *surface;
945 IDirect3DViewport3 *viewport;
946 IDirect3DDevice3 *device;
947 IDirectDraw4 *ddraw;
948 IDirect3D3 *d3d;
949 D3DCOLOR color;
950 DWORD value;
951 HWND window;
952 HRESULT hr;
954 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
955 0, 0, 640, 480, 0, 0, 0, 0);
956 if (!(device = create_device(window, DDSCL_NORMAL)))
958 skip("Failed to create a 3D device, skipping test.\n");
959 DestroyWindow(window);
960 return;
963 viewport = create_viewport(device, 0, 0, 640, 480);
965 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
966 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
967 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
968 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
969 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
970 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
971 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
972 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
973 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
974 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
975 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
976 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
977 color = get_surface_color(rt, 320, 240);
978 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
980 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
981 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
982 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
983 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
984 IDirect3D3_Release(d3d);
985 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
986 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
987 hr = IDirectDrawSurface4_IsLost(rt);
988 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
989 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
990 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
991 IDirectDraw4_Release(ddraw);
993 hr = IDirect3DDevice3_GetRenderTarget(device, &surface);
994 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
995 ok(surface == rt, "Got unexpected surface %p.\n", surface);
996 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
997 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
998 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
999 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1000 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1001 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
1002 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
1003 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1004 color = get_surface_color(rt, 320, 240);
1005 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1007 destroy_viewport(device, viewport);
1008 IDirectDrawSurface4_Release(surface);
1009 IDirectDrawSurface4_Release(rt);
1010 IDirect3DDevice3_Release(device);
1011 DestroyWindow(window);
1014 static void test_surface_interface_mismatch(void)
1016 IDirectDraw4 *ddraw = NULL;
1017 IDirect3D3 *d3d = NULL;
1018 IDirectDrawSurface4 *surface = NULL, *ds;
1019 IDirectDrawSurface3 *surface3 = NULL;
1020 IDirect3DDevice3 *device = NULL;
1021 IDirect3DViewport3 *viewport = NULL;
1022 DDSURFACEDESC2 surface_desc;
1023 DDPIXELFORMAT z_fmt;
1024 ULONG refcount;
1025 HRESULT hr;
1026 D3DCOLOR color;
1027 HWND window;
1028 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1030 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1031 0, 0, 640, 480, 0, 0, 0, 0);
1032 ddraw = create_ddraw();
1033 ok(!!ddraw, "Failed to create a ddraw object.\n");
1034 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1035 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1037 memset(&surface_desc, 0, sizeof(surface_desc));
1038 surface_desc.dwSize = sizeof(surface_desc);
1039 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1040 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1041 surface_desc.dwWidth = 640;
1042 surface_desc.dwHeight = 480;
1044 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1045 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1047 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
1048 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface3, hr %#x.\n", hr);
1050 if (FAILED(IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
1052 skip("D3D interface is not available, skipping test.\n");
1053 goto cleanup;
1056 memset(&z_fmt, 0, sizeof(z_fmt));
1057 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
1058 if (FAILED(hr) || !z_fmt.dwSize)
1060 skip("No depth buffer formats available, skipping test.\n");
1061 goto cleanup;
1064 memset(&surface_desc, 0, sizeof(surface_desc));
1065 surface_desc.dwSize = sizeof(surface_desc);
1066 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
1067 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1068 U4(surface_desc).ddpfPixelFormat = z_fmt;
1069 surface_desc.dwWidth = 640;
1070 surface_desc.dwHeight = 480;
1071 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &ds, NULL);
1072 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
1073 if (FAILED(hr))
1074 goto cleanup;
1076 /* Using a different surface interface version still works */
1077 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
1078 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
1079 refcount = IDirectDrawSurface4_Release(ds);
1080 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
1081 if (FAILED(hr))
1082 goto cleanup;
1084 /* Here too */
1085 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface4 *)surface3, &device, NULL);
1086 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
1087 if (FAILED(hr))
1088 goto cleanup;
1090 viewport = create_viewport(device, 0, 0, 640, 480);
1092 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1093 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1094 color = get_surface_color(surface, 320, 240);
1095 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1097 cleanup:
1098 if (viewport)
1099 destroy_viewport(device, viewport);
1100 if (surface3) IDirectDrawSurface3_Release(surface3);
1101 if (surface) IDirectDrawSurface4_Release(surface);
1102 if (device) IDirect3DDevice3_Release(device);
1103 if (d3d) IDirect3D3_Release(d3d);
1104 if (ddraw) IDirectDraw4_Release(ddraw);
1105 DestroyWindow(window);
1108 static void test_coop_level_threaded(void)
1110 struct create_window_thread_param p;
1111 IDirectDraw4 *ddraw;
1112 HRESULT hr;
1114 ddraw = create_ddraw();
1115 ok(!!ddraw, "Failed to create a ddraw object.\n");
1116 create_window_thread(&p);
1118 hr = IDirectDraw4_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1119 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1121 IDirectDraw4_Release(ddraw);
1122 destroy_window_thread(&p);
1125 static void test_depth_blit(void)
1127 static struct
1129 float x, y, z;
1130 DWORD color;
1132 quad1[] =
1134 { -1.0, 1.0, 0.50f, 0xff00ff00},
1135 { 1.0, 1.0, 0.50f, 0xff00ff00},
1136 { -1.0, -1.0, 0.50f, 0xff00ff00},
1137 { 1.0, -1.0, 0.50f, 0xff00ff00},
1139 static const D3DCOLOR expected_colors[4][4] =
1141 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1142 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1143 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1144 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1146 DDSURFACEDESC2 ddsd_new, ddsd_existing;
1148 IDirect3DDevice3 *device;
1149 IDirectDrawSurface4 *ds1, *ds2, *ds3, *rt;
1150 IDirect3DViewport3 *viewport;
1151 RECT src_rect, dst_rect;
1152 unsigned int i, j;
1153 D3DCOLOR color;
1154 HRESULT hr;
1155 IDirect3D3 *d3d;
1156 IDirectDraw4 *ddraw;
1157 DDBLTFX fx;
1158 HWND window;
1159 D3DRECT d3drect;
1161 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1162 0, 0, 640, 480, 0, 0, 0, 0);
1163 if (!(device = create_device(window, DDSCL_NORMAL)))
1165 skip("Failed to create a 3D device, skipping test.\n");
1166 DestroyWindow(window);
1167 return;
1170 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1171 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
1172 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1173 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
1174 IDirect3D3_Release(d3d);
1176 ds1 = get_depth_stencil(device);
1178 memset(&ddsd_new, 0, sizeof(ddsd_new));
1179 ddsd_new.dwSize = sizeof(ddsd_new);
1180 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1181 ddsd_existing.dwSize = sizeof(ddsd_existing);
1182 hr = IDirectDrawSurface4_GetSurfaceDesc(ds1, &ddsd_existing);
1183 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
1184 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1185 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1186 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1187 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1188 U4(ddsd_new).ddpfPixelFormat = U4(ddsd_existing).ddpfPixelFormat;
1189 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1190 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1191 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1192 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1193 IDirectDraw4_Release(ddraw);
1195 viewport = create_viewport(device, 0, 0, ddsd_existing.dwWidth, ddsd_existing.dwHeight);
1196 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1197 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
1199 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1200 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
1201 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1202 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
1204 U1(d3drect).x1 = U2(d3drect).y1 = 0;
1205 U3(d3drect).x2 = ddsd_existing.dwWidth; U4(d3drect).y2 = ddsd_existing.dwHeight;
1206 hr = IDirect3DViewport3_Clear2(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
1207 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
1209 /* Partial blit. */
1210 SetRect(&src_rect, 0, 0, 320, 240);
1211 SetRect(&dst_rect, 0, 0, 320, 240);
1212 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1213 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1214 /* Different locations. */
1215 SetRect(&src_rect, 0, 0, 320, 240);
1216 SetRect(&dst_rect, 320, 240, 640, 480);
1217 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1218 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1219 /* Streched. */
1220 SetRect(&src_rect, 0, 0, 320, 240);
1221 SetRect(&dst_rect, 0, 0, 640, 480);
1222 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1223 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1224 /* Flipped. */
1225 SetRect(&src_rect, 0, 480, 640, 0);
1226 SetRect(&dst_rect, 0, 0, 640, 480);
1227 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1228 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1229 SetRect(&src_rect, 0, 0, 640, 480);
1230 SetRect(&dst_rect, 0, 480, 640, 0);
1231 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1232 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1233 /* Full, explicit. */
1234 SetRect(&src_rect, 0, 0, 640, 480);
1235 SetRect(&dst_rect, 0, 0, 640, 480);
1236 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1237 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1238 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1240 /* Depth blit inside a BeginScene / EndScene pair */
1241 hr = IDirect3DDevice3_BeginScene(device);
1242 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1243 /* From the current depth stencil */
1244 hr = IDirectDrawSurface4_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1245 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1246 /* To the current depth stencil */
1247 hr = IDirectDrawSurface4_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1248 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1249 /* Between unbound surfaces */
1250 hr = IDirectDrawSurface4_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1251 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1252 hr = IDirect3DDevice3_EndScene(device);
1253 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1255 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1256 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1257 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1258 * a reliable result(z = 0.0) */
1259 memset(&fx, 0, sizeof(fx));
1260 fx.dwSize = sizeof(fx);
1261 hr = IDirectDrawSurface4_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1262 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1264 hr = IDirect3DViewport3_Clear2(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
1265 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1266 SetRect(&dst_rect, 0, 0, 320, 240);
1267 hr = IDirectDrawSurface4_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1268 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1269 IDirectDrawSurface4_Release(ds3);
1270 IDirectDrawSurface4_Release(ds2);
1271 IDirectDrawSurface4_Release(ds1);
1273 hr = IDirect3DDevice3_BeginScene(device);
1274 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1275 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1276 quad1, 4, 0);
1277 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1278 hr = IDirect3DDevice3_EndScene(device);
1279 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1281 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1282 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1283 for (i = 0; i < 4; ++i)
1285 for (j = 0; j < 4; ++j)
1287 unsigned int x = 80 * ((2 * j) + 1);
1288 unsigned int y = 60 * ((2 * i) + 1);
1289 color = get_surface_color(rt, x, y);
1290 ok(compare_color(color, expected_colors[i][j], 1),
1291 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1294 IDirectDrawSurface4_Release(rt);
1296 destroy_viewport(device, viewport);
1297 IDirect3DDevice3_Release(device);
1298 DestroyWindow(window);
1301 static void test_texture_load_ckey(void)
1303 IDirectDraw4 *ddraw;
1304 IDirectDrawSurface4 *src;
1305 IDirectDrawSurface4 *dst;
1306 IDirect3DTexture2 *src_tex;
1307 IDirect3DTexture2 *dst_tex;
1308 DDSURFACEDESC2 ddsd;
1309 HRESULT hr;
1310 DDCOLORKEY ckey;
1312 ddraw = create_ddraw();
1313 ok(!!ddraw, "Failed to create a ddraw object.\n");
1314 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
1315 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1317 memset(&ddsd, 0, sizeof(ddsd));
1318 ddsd.dwSize = sizeof(ddsd);
1319 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1320 ddsd.dwHeight = 128;
1321 ddsd.dwWidth = 128;
1322 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1323 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &src, NULL);
1324 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1325 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1326 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &dst, NULL);
1327 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1329 hr = IDirectDrawSurface4_QueryInterface(src, &IID_IDirect3DTexture2, (void **)&src_tex);
1330 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get Direct3DTexture2 interface, hr %#x.\n", hr);
1331 if (FAILED(hr))
1333 /* 64 bit ddraw does not support d3d */
1334 skip("Could not get Direct3DTexture2 interface, skipping texture::Load color keying tests.\n");
1335 IDirectDrawSurface4_Release(dst);
1336 IDirectDrawSurface4_Release(src);
1337 IDirectDraw4_Release(ddraw);
1338 return;
1340 hr = IDirectDrawSurface4_QueryInterface(dst, &IID_IDirect3DTexture2, (void **)&dst_tex);
1341 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture2 interface, hr %#x.\n", hr);
1343 /* No surface has a color key */
1344 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1345 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1346 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1347 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1348 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1349 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1350 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1352 /* Source surface has a color key */
1353 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1354 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1355 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1356 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1357 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1358 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1359 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1360 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1361 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1363 /* Both surfaces have a color key: Dest ckey is overwritten */
1364 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1365 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1366 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1367 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1368 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1369 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1370 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1371 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1372 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1374 /* Only the destination has a color key: It is not deleted */
1375 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1376 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1377 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1378 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1379 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1380 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1381 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1382 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1383 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1384 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1386 IDirect3DTexture2_Release(dst_tex);
1387 IDirect3DTexture2_Release(src_tex);
1388 IDirectDrawSurface4_Release(dst);
1389 IDirectDrawSurface4_Release(src);
1390 IDirectDraw4_Release(ddraw);
1393 static ULONG get_refcount(IUnknown *test_iface)
1395 IUnknown_AddRef(test_iface);
1396 return IUnknown_Release(test_iface);
1399 static void test_viewport(void)
1401 IDirectDraw4 *ddraw;
1402 IDirect3D3 *d3d;
1403 HRESULT hr, old_d3d_ref;
1404 ULONG ref;
1405 IDirect3DViewport *viewport;
1406 IDirect3DViewport2 *viewport2;
1407 IDirect3DViewport3 *viewport3, *another_vp, *test_vp;
1408 IDirectDrawGammaControl *gamma;
1409 IUnknown *unknown;
1410 HWND window;
1411 IDirect3DDevice3 *device;
1413 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1414 0, 0, 640, 480, 0, 0, 0, 0);
1415 if (!(device = create_device(window, DDSCL_NORMAL)))
1417 skip("Failed to create a 3D device, skipping test.\n");
1418 DestroyWindow(window);
1419 return;
1421 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1422 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
1423 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1424 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
1425 old_d3d_ref = get_refcount((IUnknown *) d3d);
1427 hr = IDirect3D3_CreateViewport(d3d, &viewport3, NULL);
1428 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1429 ref = get_refcount((IUnknown *)viewport3);
1430 ok(ref == 1, "Initial IDirect3DViewport3 refcount is %u\n", ref);
1431 ref = get_refcount((IUnknown *)d3d);
1432 ok(ref == old_d3d_ref, "IDirect3D3 refcount is %u\n", ref);
1434 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1435 hr = IDirect3DViewport2_QueryInterface(viewport3, &IID_IDirectDrawGammaControl, (void **)&gamma);
1436 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
1437 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
1438 if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
1439 /* NULL iid: Segfaults */
1441 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IDirect3DViewport, (void **)&viewport);
1442 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport, hr %#x.\n", hr);
1443 if (viewport)
1445 ref = get_refcount((IUnknown *)viewport);
1446 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1447 ref = get_refcount((IUnknown *)viewport3);
1448 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1449 IDirect3DViewport_Release(viewport);
1450 viewport = NULL;
1453 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IDirect3DViewport3, (void **)&viewport2);
1454 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1455 if (viewport2)
1457 ref = get_refcount((IUnknown *)viewport2);
1458 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1459 ref = get_refcount((IUnknown *)viewport3);
1460 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1461 IDirect3DViewport3_Release(viewport2);
1464 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IUnknown, (void **)&unknown);
1465 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1466 if (unknown)
1468 ref = get_refcount((IUnknown *)viewport3);
1469 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1470 ref = get_refcount(unknown);
1471 ok(ref == 2, "IUnknown refcount is %u\n", ref);
1472 IUnknown_Release(unknown);
1475 /* AddViewport(NULL): Segfault */
1476 hr = IDirect3DDevice3_DeleteViewport(device, NULL);
1477 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1478 hr = IDirect3DDevice3_GetCurrentViewport(device, NULL);
1479 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1481 hr = IDirect3D3_CreateViewport(d3d, &another_vp, NULL);
1482 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1484 /* Setting a viewport not in the viewport list fails */
1485 hr = IDirect3DDevice3_SetCurrentViewport(device, another_vp);
1486 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1488 hr = IDirect3DDevice3_AddViewport(device, viewport3);
1489 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1490 ref = get_refcount((IUnknown *) viewport3);
1491 ok(ref == 2, "viewport3 refcount is %d\n", ref);
1492 hr = IDirect3DDevice3_AddViewport(device, another_vp);
1493 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1494 ref = get_refcount((IUnknown *) another_vp);
1495 ok(ref == 2, "another_vp refcount is %d\n", ref);
1497 test_vp = (IDirect3DViewport3 *) 0xbaadc0de;
1498 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1499 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1500 ok(test_vp == (IDirect3DViewport3 *) 0xbaadc0de, "Got unexpected pointer %p\n", test_vp);
1502 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport3);
1503 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1504 ref = get_refcount((IUnknown *) viewport3);
1505 ok(ref == 3, "viewport3 refcount is %d\n", ref);
1506 ref = get_refcount((IUnknown *) device);
1507 ok(ref == 1, "device refcount is %d\n", ref);
1509 test_vp = NULL;
1510 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1511 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1512 ok(test_vp == viewport3, "Got unexpected viewport %p\n", test_vp);
1513 ref = get_refcount((IUnknown *) viewport3);
1514 ok(ref == 4, "viewport3 refcount is %d\n", ref);
1515 if(test_vp) IDirect3DViewport3_Release(test_vp);
1517 /* GetCurrentViewport with a viewport set and NULL input param: Segfault */
1519 /* Cannot set the viewport to NULL */
1520 hr = IDirect3DDevice3_SetCurrentViewport(device, NULL);
1521 ok(hr == DDERR_INVALIDPARAMS, "Failed to set viewport to NULL, hr %#x.\n", hr);
1522 test_vp = NULL;
1523 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1524 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1525 ok(test_vp == viewport3, "Got unexpected viewport %p\n", test_vp);
1526 if(test_vp) IDirect3DViewport3_Release(test_vp);
1528 /* SetCurrentViewport properly releases the old viewport's reference */
1529 hr = IDirect3DDevice3_SetCurrentViewport(device, another_vp);
1530 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1531 ref = get_refcount((IUnknown *) viewport3);
1532 ok(ref == 2, "viewport3 refcount is %d\n", ref);
1533 ref = get_refcount((IUnknown *) another_vp);
1534 ok(ref == 3, "another_vp refcount is %d\n", ref);
1536 /* Unlike device2::DeleteViewport, device3::DeleteViewport releases the
1537 * reference held by SetCurrentViewport */
1538 hr = IDirect3DDevice3_DeleteViewport(device, another_vp);
1539 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1540 ref = get_refcount((IUnknown *) another_vp);
1541 ok(ref == 1, "another_vp refcount is %d\n", ref);
1543 /* GetCurrentViewport still fails */
1544 test_vp = NULL;
1545 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1546 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1547 ok(test_vp == NULL, "Got unexpected viewport %p\n", test_vp);
1548 if(test_vp) IDirect3DViewport3_Release(test_vp);
1550 /* Setting a different viewport doesn't have any surprises now */
1551 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport3);
1552 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1553 ref = get_refcount((IUnknown *) viewport3);
1554 ok(ref == 3, "viewport3 refcount is %d\n", ref);
1555 ref = get_refcount((IUnknown *) another_vp);
1556 ok(ref == 1, "another_vp refcount is %d\n", ref);
1558 /* Destroying the device removes the viewport and releases the reference */
1559 IDirect3DDevice3_Release(device);
1560 ref = get_refcount((IUnknown *) viewport3);
1561 ok(ref == 1, "viewport3 refcount is %d\n", ref);
1563 ref = IDirect3DViewport3_Release(another_vp);
1564 ok(ref == 0, "Got unexpected ref %d\n", ref);
1565 ref = IDirect3DViewport3_Release(viewport3);
1566 ok(ref == 0, "Got unexpected ref %d\n", ref);
1567 IDirect3D3_Release(d3d);
1568 DestroyWindow(window);
1569 IDirectDraw4_Release(ddraw);
1572 static void test_zenable(void)
1574 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1575 static struct
1577 struct vec4 position;
1578 D3DCOLOR diffuse;
1580 tquad[] =
1582 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xff00ff00},
1583 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xff00ff00},
1584 {{640.0f, 480.0f, 1.5f, 1.0f}, 0xff00ff00},
1585 {{640.0f, 0.0f, 1.5f, 1.0f}, 0xff00ff00},
1587 IDirect3DViewport3 *viewport;
1588 IDirect3DDevice3 *device;
1589 IDirectDrawSurface4 *rt;
1590 D3DCOLOR color;
1591 HWND window;
1592 HRESULT hr;
1593 UINT x, y;
1594 UINT i, j;
1596 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1597 0, 0, 640, 480, 0, 0, 0, 0);
1598 if (!(device = create_device(window, DDSCL_NORMAL)))
1600 skip("Failed to create a 3D device, skipping test.\n");
1601 DestroyWindow(window);
1602 return;
1605 viewport = create_viewport(device, 0, 0, 640, 480);
1606 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1607 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1609 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1610 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1612 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0f, 0);
1613 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1614 hr = IDirect3DDevice3_BeginScene(device);
1615 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1616 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, tquad, 4, 0);
1617 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1618 hr = IDirect3DDevice3_EndScene(device);
1619 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1621 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1622 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1623 for (i = 0; i < 4; ++i)
1625 for (j = 0; j < 4; ++j)
1627 x = 80 * ((2 * j) + 1);
1628 y = 60 * ((2 * i) + 1);
1629 color = get_surface_color(rt, x, y);
1630 ok(compare_color(color, 0x0000ff00, 1),
1631 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1634 IDirectDrawSurface4_Release(rt);
1636 destroy_viewport(device, viewport);
1637 IDirect3DDevice3_Release(device);
1638 DestroyWindow(window);
1641 static void test_ck_rgba(void)
1643 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1644 static struct
1646 struct vec4 position;
1647 struct vec2 texcoord;
1649 tquad[] =
1651 {{ 0.0f, 480.0f, 0.25f, 1.0f}, {0.0f, 0.0f}},
1652 {{ 0.0f, 0.0f, 0.25f, 1.0f}, {0.0f, 1.0f}},
1653 {{640.0f, 480.0f, 0.25f, 1.0f}, {1.0f, 0.0f}},
1654 {{640.0f, 0.0f, 0.25f, 1.0f}, {1.0f, 1.0f}},
1655 {{ 0.0f, 480.0f, 0.75f, 1.0f}, {0.0f, 0.0f}},
1656 {{ 0.0f, 0.0f, 0.75f, 1.0f}, {0.0f, 1.0f}},
1657 {{640.0f, 480.0f, 0.75f, 1.0f}, {1.0f, 0.0f}},
1658 {{640.0f, 0.0f, 0.75f, 1.0f}, {1.0f, 1.0f}},
1660 static const struct
1662 D3DCOLOR fill_color;
1663 BOOL color_key;
1664 BOOL blend;
1665 D3DCOLOR result1, result1_broken;
1666 D3DCOLOR result2, result2_broken;
1668 tests[] =
1670 /* r200 on Windows doesn't check the alpha component when applying the color
1671 * key, so the key matches on every texel. */
1672 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1673 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1674 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1675 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1676 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00ff0000, 0x00807f00, 0x000000ff},
1677 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x00ff0000, 0x0000ff00, 0x000000ff},
1678 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00, 0x00807f00, 0x00807f00},
1679 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1682 IDirectDrawSurface4 *surface;
1683 IDirect3DViewport3 *viewport;
1684 DDSURFACEDESC2 surface_desc;
1685 IDirect3DTexture2 *texture;
1686 IDirect3DDevice3 *device;
1687 IDirectDrawSurface4 *rt;
1688 IDirectDraw4 *ddraw;
1689 IDirect3D3 *d3d;
1690 D3DCOLOR color;
1691 HWND window;
1692 DDBLTFX fx;
1693 HRESULT hr;
1694 UINT i;
1696 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1697 0, 0, 640, 480, 0, 0, 0, 0);
1698 if (!(device = create_device(window, DDSCL_NORMAL)))
1700 skip("Failed to create a 3D device, skipping test.\n");
1701 DestroyWindow(window);
1702 return;
1705 viewport = create_viewport(device, 0, 0, 640, 480);
1706 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1707 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1709 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1710 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1711 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1712 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1713 IDirect3D3_Release(d3d);
1715 memset(&surface_desc, 0, sizeof(surface_desc));
1716 surface_desc.dwSize = sizeof(surface_desc);
1717 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1718 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1719 surface_desc.dwWidth = 256;
1720 surface_desc.dwHeight = 256;
1721 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1722 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1723 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1724 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1725 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1726 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1727 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1728 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1729 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1730 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1731 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1732 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1733 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1735 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
1736 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1737 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1738 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1739 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1740 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1742 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1743 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1745 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1747 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1748 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1749 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1750 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1752 memset(&fx, 0, sizeof(fx));
1753 fx.dwSize = sizeof(fx);
1754 U5(fx).dwFillColor = tests[i].fill_color;
1755 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1756 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1758 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect,
1759 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
1760 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1761 hr = IDirect3DDevice3_BeginScene(device);
1762 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1763 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1764 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1765 hr = IDirect3DDevice3_EndScene(device);
1766 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1768 color = get_surface_color(rt, 320, 240);
1769 ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
1770 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1771 tests[i].result1, i, color);
1773 U5(fx).dwFillColor = 0xff0000ff;
1774 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1775 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1777 hr = IDirect3DDevice3_BeginScene(device);
1778 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1779 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[4], 4, 0);
1780 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1781 hr = IDirect3DDevice3_EndScene(device);
1782 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1784 /* This tests that fragments that are masked out by the color key are
1785 * discarded, instead of just fully transparent. */
1786 color = get_surface_color(rt, 320, 240);
1787 ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
1788 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1789 tests[i].result2, i, color);
1792 IDirectDrawSurface4_Release(rt);
1793 IDirect3DTexture2_Release(texture);
1794 IDirectDrawSurface4_Release(surface);
1795 destroy_viewport(device, viewport);
1796 IDirectDraw4_Release(ddraw);
1797 IDirect3DDevice3_Release(device);
1798 DestroyWindow(window);
1801 static void test_ck_default(void)
1803 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1804 static struct
1806 struct vec4 position;
1807 struct vec2 texcoord;
1809 tquad[] =
1811 {{ 0.0f, 480.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
1812 {{ 0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
1813 {{640.0f, 480.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
1814 {{640.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
1816 IDirectDrawSurface4 *surface, *rt;
1817 IDirect3DViewport3 *viewport;
1818 DDSURFACEDESC2 surface_desc;
1819 IDirect3DTexture2 *texture;
1820 IDirect3DDevice3 *device;
1821 IDirectDraw4 *ddraw;
1822 IDirect3D3 *d3d;
1823 D3DCOLOR color;
1824 DWORD value;
1825 HWND window;
1826 DDBLTFX fx;
1827 HRESULT hr;
1829 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1830 0, 0, 640, 480, 0, 0, 0, 0);
1832 if (!(device = create_device(window, DDSCL_NORMAL)))
1834 skip("Failed to create a 3D device, skipping test.\n");
1835 DestroyWindow(window);
1836 return;
1839 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1840 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1841 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1842 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1843 IDirect3D3_Release(d3d);
1845 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1846 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1848 viewport = create_viewport(device, 0, 0, 640, 480);
1849 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1850 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1852 memset(&surface_desc, 0, sizeof(surface_desc));
1853 surface_desc.dwSize = sizeof(surface_desc);
1854 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1855 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1856 surface_desc.dwWidth = 256;
1857 surface_desc.dwHeight = 256;
1858 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1859 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
1860 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1861 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1862 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1863 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1864 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1865 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1866 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1867 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1868 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1869 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1870 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
1871 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1873 memset(&fx, 0, sizeof(fx));
1874 fx.dwSize = sizeof(fx);
1875 U5(fx).dwFillColor = 0x000000ff;
1876 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1877 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1879 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1880 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1881 hr = IDirect3DDevice3_BeginScene(device);
1882 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1883 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1884 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1885 ok(!value, "Got unexpected color keying state %#x.\n", value);
1886 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1887 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1888 hr = IDirect3DDevice3_EndScene(device);
1889 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1890 color = get_surface_color(rt, 320, 240);
1891 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1893 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1894 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1895 hr = IDirect3DDevice3_BeginScene(device);
1896 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1897 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1898 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1899 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1900 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1901 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1902 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1903 ok(!!value, "Got unexpected color keying state %#x.\n", value);
1904 hr = IDirect3DDevice3_EndScene(device);
1905 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1906 color = get_surface_color(rt, 320, 240);
1907 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1909 IDirect3DTexture_Release(texture);
1910 IDirectDrawSurface4_Release(surface);
1911 destroy_viewport(device, viewport);
1912 IDirectDrawSurface4_Release(rt);
1913 IDirect3DDevice3_Release(device);
1914 IDirectDraw4_Release(ddraw);
1915 DestroyWindow(window);
1918 static void test_ck_complex(void)
1920 IDirectDrawSurface4 *surface, *mipmap, *tmp;
1921 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
1922 DDSURFACEDESC2 surface_desc;
1923 IDirect3DDevice3 *device;
1924 DDCOLORKEY color_key;
1925 IDirectDraw4 *ddraw;
1926 IDirect3D3 *d3d;
1927 unsigned int i;
1928 ULONG refcount;
1929 HWND window;
1930 HRESULT hr;
1932 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1933 0, 0, 640, 480, 0, 0, 0, 0);
1934 if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
1936 skip("Failed to create a 3D device, skipping test.\n");
1937 DestroyWindow(window);
1938 return;
1940 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1941 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1942 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1943 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1944 IDirect3D3_Release(d3d);
1946 memset(&surface_desc, 0, sizeof(surface_desc));
1947 surface_desc.dwSize = sizeof(surface_desc);
1948 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1949 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1950 surface_desc.dwWidth = 128;
1951 surface_desc.dwHeight = 128;
1952 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1953 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1955 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1956 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1957 color_key.dwColorSpaceLowValue = 0x0000ff00;
1958 color_key.dwColorSpaceHighValue = 0x0000ff00;
1959 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1960 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1961 memset(&color_key, 0, sizeof(color_key));
1962 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1963 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1964 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1965 color_key.dwColorSpaceLowValue);
1966 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1967 color_key.dwColorSpaceHighValue);
1969 mipmap = surface;
1970 IDirectDrawSurface_AddRef(mipmap);
1971 for (i = 0; i < 7; ++i)
1973 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
1974 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1976 hr = IDirectDrawSurface4_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1977 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1978 color_key.dwColorSpaceLowValue = 0x000000ff;
1979 color_key.dwColorSpaceHighValue = 0x000000ff;
1980 hr = IDirectDrawSurface4_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1981 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x, i %u.\n", hr, i);
1982 memset(&color_key, 0, sizeof(color_key));
1983 hr = IDirectDrawSurface4_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1984 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x, i %u.\n", hr, i);
1985 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
1986 color_key.dwColorSpaceLowValue, i);
1987 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
1988 color_key.dwColorSpaceHighValue, i);
1990 IDirectDrawSurface_Release(mipmap);
1991 mipmap = tmp;
1994 memset(&color_key, 0, sizeof(color_key));
1995 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1996 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1997 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1998 color_key.dwColorSpaceLowValue);
1999 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2000 color_key.dwColorSpaceHighValue);
2002 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
2003 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
2004 IDirectDrawSurface_Release(mipmap);
2005 refcount = IDirectDrawSurface4_Release(surface);
2006 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2008 memset(&surface_desc, 0, sizeof(surface_desc));
2009 surface_desc.dwSize = sizeof(surface_desc);
2010 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
2011 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
2012 U5(surface_desc).dwBackBufferCount = 1;
2013 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2014 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2016 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2017 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
2018 color_key.dwColorSpaceLowValue = 0x0000ff00;
2019 color_key.dwColorSpaceHighValue = 0x0000ff00;
2020 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2021 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2022 memset(&color_key, 0, sizeof(color_key));
2023 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2024 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2025 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2026 color_key.dwColorSpaceLowValue);
2027 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2028 color_key.dwColorSpaceHighValue);
2030 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &tmp);
2031 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
2033 hr = IDirectDrawSurface4_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2034 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
2035 color_key.dwColorSpaceLowValue = 0x0000ff00;
2036 color_key.dwColorSpaceHighValue = 0x0000ff00;
2037 hr = IDirectDrawSurface4_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2038 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2039 memset(&color_key, 0, sizeof(color_key));
2040 hr = IDirectDrawSurface4_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2041 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2042 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2043 color_key.dwColorSpaceLowValue);
2044 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2045 color_key.dwColorSpaceHighValue);
2047 IDirectDrawSurface_Release(tmp);
2049 refcount = IDirectDrawSurface4_Release(surface);
2050 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2051 IDirectDraw4_Release(ddraw);
2052 refcount = IDirect3DDevice3_Release(device);
2053 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2054 DestroyWindow(window);
2057 struct qi_test
2059 REFIID iid;
2060 REFIID refcount_iid;
2061 HRESULT hr;
2064 static void test_qi(const char *test_name, IUnknown *base_iface,
2065 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
2067 ULONG refcount, expected_refcount;
2068 IUnknown *iface1, *iface2;
2069 HRESULT hr;
2070 UINT i, j;
2072 for (i = 0; i < entry_count; ++i)
2074 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
2075 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
2076 if (SUCCEEDED(hr))
2078 for (j = 0; j < entry_count; ++j)
2080 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
2081 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
2082 if (SUCCEEDED(hr))
2084 expected_refcount = 0;
2085 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
2086 ++expected_refcount;
2087 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
2088 ++expected_refcount;
2089 refcount = IUnknown_Release(iface2);
2090 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
2091 refcount, test_name, i, j, expected_refcount);
2095 expected_refcount = 0;
2096 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
2097 ++expected_refcount;
2098 refcount = IUnknown_Release(iface1);
2099 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
2100 refcount, test_name, i, expected_refcount);
2105 static void test_surface_qi(void)
2107 static const struct qi_test tests[] =
2109 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface4, S_OK },
2110 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface4, S_OK },
2111 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
2112 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2113 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
2114 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
2115 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
2116 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
2117 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
2118 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
2119 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
2120 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
2121 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
2122 {&IID_IDirect3D7, NULL, E_INVALIDARG },
2123 {&IID_IDirect3D3, NULL, E_INVALIDARG },
2124 {&IID_IDirect3D2, NULL, E_INVALIDARG },
2125 {&IID_IDirect3D, NULL, E_INVALIDARG },
2126 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
2127 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
2128 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
2129 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
2130 {&IID_IDirectDraw, NULL, E_INVALIDARG },
2131 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
2132 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
2133 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
2134 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
2135 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
2136 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
2137 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
2138 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
2139 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
2140 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
2141 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
2142 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
2143 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
2146 IDirectDrawSurface4 *surface;
2147 DDSURFACEDESC2 surface_desc;
2148 IDirect3DDevice3 *device;
2149 IDirectDraw4 *ddraw;
2150 HWND window;
2151 HRESULT hr;
2153 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
2155 win_skip("DirectDrawCreateEx not available, skipping test.\n");
2156 return;
2159 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2160 0, 0, 640, 480, 0, 0, 0, 0);
2161 /* Try to create a D3D device to see if the ddraw implementation supports
2162 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
2163 * doesn't support e.g. the IDirect3DTexture interfaces. */
2164 if (!(device = create_device(window, DDSCL_NORMAL)))
2166 skip("Failed to create a 3D device, skipping test.\n");
2167 DestroyWindow(window);
2168 return;
2170 IDirect3DDevice_Release(device);
2171 ddraw = create_ddraw();
2172 ok(!!ddraw, "Failed to create a ddraw object.\n");
2173 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2174 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2176 memset(&surface_desc, 0, sizeof(surface_desc));
2177 surface_desc.dwSize = sizeof(surface_desc);
2178 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2179 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2180 surface_desc.dwWidth = 512;
2181 surface_desc.dwHeight = 512;
2182 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2183 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2185 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface4, tests, sizeof(tests) / sizeof(*tests));
2187 IDirectDrawSurface4_Release(surface);
2188 IDirectDraw4_Release(ddraw);
2189 DestroyWindow(window);
2192 static void test_device_qi(void)
2194 static const struct qi_test tests[] =
2196 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
2197 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
2198 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
2199 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2200 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
2201 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
2202 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
2203 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
2204 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
2205 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
2206 {&IID_IDirect3DDevice3, &IID_IDirect3DDevice3, S_OK },
2207 {&IID_IDirect3DDevice2, &IID_IDirect3DDevice3, S_OK },
2208 {&IID_IDirect3DDevice, &IID_IDirect3DDevice3, S_OK },
2209 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2210 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2211 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2212 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2213 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2214 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2215 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2216 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2217 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2218 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2219 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2220 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2221 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2222 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2223 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2224 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2225 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2226 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2227 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2228 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2229 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2230 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2231 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2232 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2233 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2234 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2235 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2236 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2237 {&IID_IUnknown, &IID_IDirect3DDevice3, S_OK },
2240 IDirect3DDevice3 *device;
2241 HWND window;
2243 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2244 0, 0, 640, 480, 0, 0, 0, 0);
2245 if (!(device = create_device(window, DDSCL_NORMAL)))
2247 skip("Failed to create a 3D device, skipping test.\n");
2248 DestroyWindow(window);
2249 return;
2252 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice3, tests, sizeof(tests) / sizeof(*tests));
2254 IDirect3DDevice3_Release(device);
2255 DestroyWindow(window);
2258 static void test_wndproc(void)
2260 LONG_PTR proc, ddraw_proc;
2261 IDirectDraw4 *ddraw;
2262 WNDCLASSA wc = {0};
2263 HWND window;
2264 HRESULT hr;
2265 ULONG ref;
2267 static struct message messages[] =
2269 {WM_WINDOWPOSCHANGING, FALSE, 0},
2270 {WM_MOVE, FALSE, 0},
2271 {WM_SIZE, FALSE, 0},
2272 {WM_WINDOWPOSCHANGING, FALSE, 0},
2273 {WM_ACTIVATE, FALSE, 0},
2274 {WM_SETFOCUS, FALSE, 0},
2275 {0, FALSE, 0},
2278 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2279 ddraw = create_ddraw();
2280 ok(!!ddraw, "Failed to create a ddraw object.\n");
2282 wc.lpfnWndProc = test_proc;
2283 wc.lpszClassName = "ddraw_test_wndproc_wc";
2284 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2286 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2287 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2289 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2290 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2291 (LONG_PTR)test_proc, proc);
2292 expect_messages = messages;
2293 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2294 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2295 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2296 expect_messages = NULL;
2297 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2298 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2299 (LONG_PTR)test_proc, proc);
2300 ref = IDirectDraw4_Release(ddraw);
2301 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2302 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2303 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2304 (LONG_PTR)test_proc, proc);
2306 /* DDSCL_NORMAL doesn't. */
2307 ddraw = create_ddraw();
2308 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2309 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2310 (LONG_PTR)test_proc, proc);
2311 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2312 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2313 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2314 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2315 (LONG_PTR)test_proc, proc);
2316 ref = IDirectDraw4_Release(ddraw);
2317 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2318 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2319 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2320 (LONG_PTR)test_proc, proc);
2322 /* The original window proc is only restored by ddraw if the current
2323 * window proc matches the one ddraw set. This also affects switching
2324 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2325 ddraw = create_ddraw();
2326 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2327 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2328 (LONG_PTR)test_proc, proc);
2329 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2330 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2331 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2332 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2333 (LONG_PTR)test_proc, proc);
2334 ddraw_proc = proc;
2335 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2336 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2337 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2338 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2339 (LONG_PTR)test_proc, proc);
2340 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2341 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2342 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2343 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2344 (LONG_PTR)test_proc, proc);
2345 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2346 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2347 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2348 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2349 (LONG_PTR)DefWindowProcA, proc);
2350 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2351 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2352 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
2353 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2354 (LONG_PTR)DefWindowProcA, proc);
2355 ref = IDirectDraw4_Release(ddraw);
2356 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2357 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2358 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2359 (LONG_PTR)test_proc, proc);
2361 ddraw = create_ddraw();
2362 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2363 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2364 (LONG_PTR)test_proc, proc);
2365 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2366 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2367 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2368 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2369 (LONG_PTR)test_proc, proc);
2370 ref = IDirectDraw4_Release(ddraw);
2371 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2372 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2373 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2374 (LONG_PTR)DefWindowProcA, proc);
2376 fix_wndproc(window, (LONG_PTR)test_proc);
2377 expect_messages = NULL;
2378 DestroyWindow(window);
2379 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2382 static void test_window_style(void)
2384 LONG style, exstyle, tmp, expected_style;
2385 RECT fullscreen_rect, r;
2386 IDirectDraw4 *ddraw;
2387 HWND window;
2388 HRESULT hr;
2389 ULONG ref;
2390 BOOL ret;
2392 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2393 0, 0, 100, 100, 0, 0, 0, 0);
2394 ddraw = create_ddraw();
2395 ok(!!ddraw, "Failed to create a ddraw object.\n");
2397 style = GetWindowLongA(window, GWL_STYLE);
2398 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2399 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2401 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2402 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2404 tmp = GetWindowLongA(window, GWL_STYLE);
2405 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2406 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2407 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2409 GetWindowRect(window, &r);
2410 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2411 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2412 r.left, r.top, r.right, r.bottom);
2413 GetClientRect(window, &r);
2414 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2416 ret = SetForegroundWindow(GetDesktopWindow());
2417 ok(ret, "Failed to set foreground window.\n");
2419 tmp = GetWindowLongA(window, GWL_STYLE);
2420 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2421 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2422 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2424 ret = SetForegroundWindow(window);
2425 ok(ret, "Failed to set foreground window.\n");
2426 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2427 * the next tests expect this. */
2428 ShowWindow(window, SW_HIDE);
2430 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2431 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2433 tmp = GetWindowLongA(window, GWL_STYLE);
2434 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2435 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2436 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2438 ShowWindow(window, SW_SHOW);
2439 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2440 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2442 tmp = GetWindowLongA(window, GWL_STYLE);
2443 expected_style = style | WS_VISIBLE;
2444 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2445 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2446 expected_style = exstyle | WS_EX_TOPMOST;
2447 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2449 ret = SetForegroundWindow(GetDesktopWindow());
2450 ok(ret, "Failed to set foreground window.\n");
2451 tmp = GetWindowLongA(window, GWL_STYLE);
2452 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
2453 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2454 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2455 expected_style = exstyle | WS_EX_TOPMOST;
2456 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2458 ref = IDirectDraw4_Release(ddraw);
2459 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2461 DestroyWindow(window);
2464 static void test_redundant_mode_set(void)
2466 DDSURFACEDESC2 surface_desc = {0};
2467 IDirectDraw4 *ddraw;
2468 HWND window;
2469 HRESULT hr;
2470 RECT r, s;
2471 ULONG ref;
2473 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2474 0, 0, 100, 100, 0, 0, 0, 0);
2475 ddraw = create_ddraw();
2476 ok(!!ddraw, "Failed to create a ddraw object.\n");
2478 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2479 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2481 surface_desc.dwSize = sizeof(surface_desc);
2482 hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc);
2483 ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
2485 hr = IDirectDraw4_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2486 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2487 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2489 GetWindowRect(window, &r);
2490 r.right /= 2;
2491 r.bottom /= 2;
2492 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2493 GetWindowRect(window, &s);
2494 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2495 r.left, r.top, r.right, r.bottom,
2496 s.left, s.top, s.right, s.bottom);
2498 hr = IDirectDraw4_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2499 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2500 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2502 GetWindowRect(window, &s);
2503 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2504 r.left, r.top, r.right, r.bottom,
2505 s.left, s.top, s.right, s.bottom);
2507 ref = IDirectDraw4_Release(ddraw);
2508 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2510 DestroyWindow(window);
2513 static SIZE screen_size, screen_size2;
2515 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2517 if (message == WM_SIZE)
2519 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2520 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2523 return test_proc(hwnd, message, wparam, lparam);
2526 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2528 if (message == WM_SIZE)
2530 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
2531 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
2534 return test_proc(hwnd, message, wparam, lparam);
2537 struct test_coop_level_mode_set_enum_param
2539 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
2542 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC2 *surface_desc, void *context)
2544 struct test_coop_level_mode_set_enum_param *param = context;
2546 if (U1(U4(*surface_desc).ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
2547 return DDENUMRET_OK;
2548 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
2549 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
2550 return DDENUMRET_OK;
2552 if (!param->ddraw_width)
2554 param->ddraw_width = surface_desc->dwWidth;
2555 param->ddraw_height = surface_desc->dwHeight;
2556 return DDENUMRET_OK;
2558 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
2559 return DDENUMRET_OK;
2561 param->user32_width = surface_desc->dwWidth;
2562 param->user32_height = surface_desc->dwHeight;
2563 return DDENUMRET_CANCEL;
2566 static void test_coop_level_mode_set(void)
2568 IDirectDrawSurface4 *primary;
2569 RECT registry_rect, ddraw_rect, user32_rect, r;
2570 IDirectDraw4 *ddraw;
2571 DDSURFACEDESC2 ddsd;
2572 WNDCLASSA wc = {0};
2573 HWND window, window2;
2574 HRESULT hr;
2575 ULONG ref;
2576 MSG msg;
2577 struct test_coop_level_mode_set_enum_param param;
2578 DEVMODEW devmode;
2579 BOOL ret;
2580 LONG change_ret;
2582 static const struct message exclusive_messages[] =
2584 {WM_WINDOWPOSCHANGING, FALSE, 0},
2585 {WM_WINDOWPOSCHANGED, FALSE, 0},
2586 {WM_SIZE, FALSE, 0},
2587 {WM_DISPLAYCHANGE, FALSE, 0},
2588 {0, FALSE, 0},
2590 static const struct message exclusive_focus_loss_messages[] =
2592 {WM_ACTIVATE, TRUE, WA_INACTIVE},
2593 {WM_DISPLAYCHANGE, FALSE, 0},
2594 {WM_WINDOWPOSCHANGING, FALSE, 0},
2595 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
2596 * SW_MINIMIZED, causing a recursive window activation that does not
2597 * produce the same result in Wine yet. Ignore the difference for now.
2598 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
2599 {WM_WINDOWPOSCHANGED, FALSE, 0},
2600 {WM_MOVE, FALSE, 0},
2601 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2602 {WM_ACTIVATEAPP, TRUE, FALSE},
2603 {0, FALSE, 0},
2605 static const struct message exclusive_focus_restore_messages[] =
2607 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
2608 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
2609 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
2610 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
2611 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
2612 /* Native redundantly sets the window size here. */
2613 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
2614 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
2615 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
2616 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
2617 {0, FALSE, 0},
2619 static const struct message sc_restore_messages[] =
2621 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
2622 {WM_WINDOWPOSCHANGING, FALSE, 0},
2623 {WM_WINDOWPOSCHANGED, FALSE, 0},
2624 {WM_SIZE, TRUE, SIZE_RESTORED},
2625 {0, FALSE, 0},
2627 static const struct message sc_minimize_messages[] =
2629 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
2630 {WM_WINDOWPOSCHANGING, FALSE, 0},
2631 {WM_WINDOWPOSCHANGED, FALSE, 0},
2632 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2633 {0, FALSE, 0},
2635 static const struct message sc_maximize_messages[] =
2637 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
2638 {WM_WINDOWPOSCHANGING, FALSE, 0},
2639 {WM_WINDOWPOSCHANGED, FALSE, 0},
2640 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
2641 {0, FALSE, 0},
2644 static const struct message normal_messages[] =
2646 {WM_DISPLAYCHANGE, FALSE, 0},
2647 {0, FALSE, 0},
2650 ddraw = create_ddraw();
2651 ok(!!ddraw, "Failed to create a ddraw object.\n");
2653 memset(&param, 0, sizeof(param));
2654 hr = IDirectDraw4_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
2655 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2656 ref = IDirectDraw4_Release(ddraw);
2657 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2659 if (!param.user32_height)
2661 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
2662 return;
2665 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2666 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
2667 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
2669 memset(&devmode, 0, sizeof(devmode));
2670 devmode.dmSize = sizeof(devmode);
2671 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2672 devmode.dmPelsWidth = param.user32_width;
2673 devmode.dmPelsHeight = param.user32_height;
2674 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2675 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2677 ddraw = create_ddraw();
2678 ok(!!ddraw, "Failed to create a ddraw object.\n");
2680 wc.lpfnWndProc = mode_set_proc;
2681 wc.lpszClassName = "ddraw_test_wndproc_wc";
2682 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2683 wc.lpfnWndProc = mode_set_proc2;
2684 wc.lpszClassName = "ddraw_test_wndproc_wc2";
2685 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2687 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2688 0, 0, 100, 100, 0, 0, 0, 0);
2689 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
2690 0, 0, 100, 100, 0, 0, 0, 0);
2692 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2693 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2695 GetWindowRect(window, &r);
2696 ok(EqualRect(&r, &user32_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2697 user32_rect.left, user32_rect.top, user32_rect.right, user32_rect.bottom,
2698 r.left, r.top, r.right, r.bottom);
2700 memset(&ddsd, 0, sizeof(ddsd));
2701 ddsd.dwSize = sizeof(ddsd);
2702 ddsd.dwFlags = DDSD_CAPS;
2703 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2705 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2706 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2707 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2708 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2709 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2710 param.user32_width, ddsd.dwWidth);
2711 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2712 param.user32_height, ddsd.dwHeight);
2714 GetWindowRect(window, &r);
2715 ok(EqualRect(&r, &user32_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2716 user32_rect.left, user32_rect.top, user32_rect.right, user32_rect.bottom,
2717 r.left, r.top, r.right, r.bottom);
2719 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2720 expect_messages = exclusive_messages;
2721 screen_size.cx = 0;
2722 screen_size.cy = 0;
2724 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2725 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2727 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2728 expect_messages = NULL;
2729 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
2730 "Expected screen size %ux%u, got %ux%u.\n",
2731 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
2733 GetWindowRect(window, &r);
2734 ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2735 ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
2736 r.left, r.top, r.right, r.bottom);
2738 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2739 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2740 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2741 param.user32_width, ddsd.dwWidth);
2742 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2743 param.user32_height, ddsd.dwHeight);
2744 IDirectDrawSurface4_Release(primary);
2746 memset(&ddsd, 0, sizeof(ddsd));
2747 ddsd.dwSize = sizeof(ddsd);
2748 ddsd.dwFlags = DDSD_CAPS;
2749 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2751 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2752 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2753 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2754 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2755 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2756 param.ddraw_width, ddsd.dwWidth);
2757 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2758 param.ddraw_height, ddsd.dwHeight);
2760 GetWindowRect(window, &r);
2761 ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2762 ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
2763 r.left, r.top, r.right, r.bottom);
2765 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2766 expect_messages = exclusive_messages;
2767 screen_size.cx = 0;
2768 screen_size.cy = 0;
2770 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2771 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2773 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2774 expect_messages = NULL;
2775 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
2776 "Expected screen size %ux%u, got %ux%u.\n",
2777 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
2779 GetWindowRect(window, &r);
2780 ok(EqualRect(&r, &user32_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2781 user32_rect.left, user32_rect.top, user32_rect.right, user32_rect.bottom,
2782 r.left, r.top, r.right, r.bottom);
2784 expect_messages = exclusive_focus_loss_messages;
2785 ret = SetForegroundWindow(GetDesktopWindow());
2786 ok(ret, "Failed to set foreground window.\n");
2787 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2788 memset(&devmode, 0, sizeof(devmode));
2789 devmode.dmSize = sizeof(devmode);
2790 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2791 ok(ret, "Failed to get display mode.\n");
2792 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2793 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
2794 devmode.dmPelsWidth, devmode.dmPelsHeight);
2796 expect_messages = exclusive_focus_restore_messages;
2797 ShowWindow(window, SW_RESTORE);
2798 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2800 GetWindowRect(window, &r);
2801 ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2802 ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
2803 r.left, r.top, r.right, r.bottom);
2804 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2805 ok(ret, "Failed to get display mode.\n");
2806 ok(devmode.dmPelsWidth == param.ddraw_width
2807 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpect screen size %ux%u.\n",
2808 devmode.dmPelsWidth, devmode.dmPelsHeight);
2810 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2811 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2812 /* Normally the primary should be restored here. Unfortunately this causes the
2813 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
2814 * testbot. Another Restore call would presumably avoid the crash, but it also moots
2815 * the point of the GetSurfaceDesc call. */
2817 expect_messages = sc_minimize_messages;
2818 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
2819 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2820 expect_messages = NULL;
2822 expect_messages = sc_restore_messages;
2823 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
2824 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2825 expect_messages = NULL;
2827 expect_messages = sc_maximize_messages;
2828 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
2829 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2830 expect_messages = NULL;
2832 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2833 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2835 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2836 expect_messages = exclusive_messages;
2837 screen_size.cx = 0;
2838 screen_size.cy = 0;
2840 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
2841 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2843 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2844 expect_messages = NULL;
2845 ok(screen_size.cx == registry_mode.dmPelsWidth
2846 && screen_size.cy == registry_mode.dmPelsHeight,
2847 "Expected screen size %ux%u, got %ux%u.\n",
2848 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
2850 GetWindowRect(window, &r);
2851 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2852 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2853 r.left, r.top, r.right, r.bottom);
2855 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2856 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2857 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2858 param.ddraw_width, ddsd.dwWidth);
2859 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2860 param.ddraw_height, ddsd.dwHeight);
2861 IDirectDrawSurface4_Release(primary);
2863 /* For Wine. */
2864 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2865 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2867 memset(&ddsd, 0, sizeof(ddsd));
2868 ddsd.dwSize = sizeof(ddsd);
2869 ddsd.dwFlags = DDSD_CAPS;
2870 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2872 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2873 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2874 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2875 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2876 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2877 registry_mode.dmPelsWidth, ddsd.dwWidth);
2878 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2879 registry_mode.dmPelsHeight, ddsd.dwHeight);
2881 GetWindowRect(window, &r);
2882 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2883 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2884 r.left, r.top, r.right, r.bottom);
2886 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2887 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2889 GetWindowRect(window, &r);
2890 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2891 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2892 r.left, r.top, r.right, r.bottom);
2894 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2895 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2896 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2897 registry_mode.dmPelsWidth, ddsd.dwWidth);
2898 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2899 registry_mode.dmPelsHeight, ddsd.dwHeight);
2900 IDirectDrawSurface4_Release(primary);
2902 memset(&ddsd, 0, sizeof(ddsd));
2903 ddsd.dwSize = sizeof(ddsd);
2904 ddsd.dwFlags = DDSD_CAPS;
2905 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2907 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2908 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2909 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2910 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2911 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2912 registry_mode.dmPelsWidth, ddsd.dwWidth);
2913 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2914 registry_mode.dmPelsHeight, ddsd.dwHeight);
2916 GetWindowRect(window, &r);
2917 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2918 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2919 r.left, r.top, r.right, r.bottom);
2921 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2922 expect_messages = normal_messages;
2923 screen_size.cx = 0;
2924 screen_size.cy = 0;
2926 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2927 devmode.dmPelsWidth = param.user32_width;
2928 devmode.dmPelsHeight = param.user32_height;
2929 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2930 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2932 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2933 expect_messages = NULL;
2934 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2936 GetWindowRect(window, &r);
2937 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2938 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2939 r.left, r.top, r.right, r.bottom);
2941 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2942 expect_messages = normal_messages;
2943 screen_size.cx = 0;
2944 screen_size.cy = 0;
2946 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2947 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2949 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2950 expect_messages = NULL;
2951 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2953 GetWindowRect(window, &r);
2954 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2955 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2956 r.left, r.top, r.right, r.bottom);
2958 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2959 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2960 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2961 registry_mode.dmPelsWidth, ddsd.dwWidth);
2962 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2963 registry_mode.dmPelsHeight, ddsd.dwHeight);
2964 IDirectDrawSurface4_Release(primary);
2966 memset(&ddsd, 0, sizeof(ddsd));
2967 ddsd.dwSize = sizeof(ddsd);
2968 ddsd.dwFlags = DDSD_CAPS;
2969 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2971 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2972 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2973 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2974 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2975 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2976 param.ddraw_width, ddsd.dwWidth);
2977 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2978 param.ddraw_height, ddsd.dwHeight);
2980 GetWindowRect(window, &r);
2981 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2982 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2983 r.left, r.top, r.right, r.bottom);
2985 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2986 expect_messages = normal_messages;
2987 screen_size.cx = 0;
2988 screen_size.cy = 0;
2990 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
2991 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2993 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2994 expect_messages = NULL;
2995 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2997 GetWindowRect(window, &r);
2998 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2999 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
3000 r.left, r.top, r.right, r.bottom);
3002 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3003 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3004 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3005 param.ddraw_width, ddsd.dwWidth);
3006 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3007 param.ddraw_height, ddsd.dwHeight);
3008 IDirectDrawSurface4_Release(primary);
3010 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3011 ok(ret, "Failed to get display mode.\n");
3012 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3013 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3014 "Expected resolution %ux%u, got %ux%u.\n",
3015 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3016 devmode.dmPelsWidth, devmode.dmPelsHeight);
3017 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3018 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3020 memset(&ddsd, 0, sizeof(ddsd));
3021 ddsd.dwSize = sizeof(ddsd);
3022 ddsd.dwFlags = DDSD_CAPS;
3023 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3025 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3026 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3027 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3028 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3029 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3030 registry_mode.dmPelsWidth, ddsd.dwWidth);
3031 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3032 registry_mode.dmPelsHeight, ddsd.dwHeight);
3034 GetWindowRect(window, &r);
3035 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3036 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
3037 r.left, r.top, r.right, r.bottom);
3039 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
3040 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
3041 * not DDSCL_FULLSCREEN. */
3042 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3043 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3045 GetWindowRect(window, &r);
3046 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3047 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
3048 r.left, r.top, r.right, r.bottom);
3050 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3051 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3052 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3053 registry_mode.dmPelsWidth, ddsd.dwWidth);
3054 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3055 registry_mode.dmPelsHeight, ddsd.dwHeight);
3056 IDirectDrawSurface4_Release(primary);
3058 memset(&ddsd, 0, sizeof(ddsd));
3059 ddsd.dwSize = sizeof(ddsd);
3060 ddsd.dwFlags = DDSD_CAPS;
3061 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3063 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3064 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3065 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3066 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3067 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3068 registry_mode.dmPelsWidth, ddsd.dwWidth);
3069 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3070 registry_mode.dmPelsHeight, ddsd.dwHeight);
3072 GetWindowRect(window, &r);
3073 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3074 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
3075 r.left, r.top, r.right, r.bottom);
3077 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3078 expect_messages = normal_messages;
3079 screen_size.cx = 0;
3080 screen_size.cy = 0;
3082 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3083 devmode.dmPelsWidth = param.user32_width;
3084 devmode.dmPelsHeight = param.user32_height;
3085 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3086 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3088 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3089 expect_messages = NULL;
3090 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3092 GetWindowRect(window, &r);
3093 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3094 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
3095 r.left, r.top, r.right, r.bottom);
3097 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3098 expect_messages = normal_messages;
3099 screen_size.cx = 0;
3100 screen_size.cy = 0;
3102 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3103 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3105 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3106 expect_messages = NULL;
3107 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3109 GetWindowRect(window, &r);
3110 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3111 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
3112 r.left, r.top, r.right, r.bottom);
3114 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3115 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3116 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3117 registry_mode.dmPelsWidth, ddsd.dwWidth);
3118 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3119 registry_mode.dmPelsHeight, ddsd.dwHeight);
3120 IDirectDrawSurface4_Release(primary);
3122 memset(&ddsd, 0, sizeof(ddsd));
3123 ddsd.dwSize = sizeof(ddsd);
3124 ddsd.dwFlags = DDSD_CAPS;
3125 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3127 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3128 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3129 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3130 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3131 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3132 param.ddraw_width, ddsd.dwWidth);
3133 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3134 param.ddraw_height, ddsd.dwHeight);
3136 GetWindowRect(window, &r);
3137 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3138 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
3139 r.left, r.top, r.right, r.bottom);
3141 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3142 expect_messages = normal_messages;
3143 screen_size.cx = 0;
3144 screen_size.cy = 0;
3146 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
3147 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3149 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3150 expect_messages = NULL;
3151 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3153 GetWindowRect(window, &r);
3154 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3155 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
3156 r.left, r.top, r.right, r.bottom);
3158 hr = IDirectDrawSurface4_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 IDirectDrawSurface4_Release(primary);
3166 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3167 ok(ret, "Failed to get display mode.\n");
3168 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3169 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3170 "Expected resolution %ux%u, got %ux%u.\n",
3171 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3172 devmode.dmPelsWidth, devmode.dmPelsHeight);
3173 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3174 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3176 memset(&ddsd, 0, sizeof(ddsd));
3177 ddsd.dwSize = sizeof(ddsd);
3178 ddsd.dwFlags = DDSD_CAPS;
3179 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3181 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3182 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3183 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3184 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3185 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3186 registry_mode.dmPelsWidth, ddsd.dwWidth);
3187 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3188 registry_mode.dmPelsHeight, ddsd.dwHeight);
3189 IDirectDrawSurface4_Release(primary);
3191 GetWindowRect(window, &r);
3192 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3193 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
3194 r.left, r.top, r.right, r.bottom);
3196 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
3197 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3198 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3199 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3200 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3202 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3203 expect_messages = exclusive_messages;
3204 screen_size.cx = 0;
3205 screen_size.cy = 0;
3207 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3208 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3210 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3211 expect_messages = NULL;
3212 ok(screen_size.cx == registry_mode.dmPelsWidth
3213 && screen_size.cy == registry_mode.dmPelsHeight,
3214 "Expected screen size %ux%u, got %ux%u.\n",
3215 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3216 screen_size.cx, screen_size.cy);
3218 GetWindowRect(window, &r);
3219 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3220 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
3221 r.left, r.top, r.right, r.bottom);
3223 memset(&ddsd, 0, sizeof(ddsd));
3224 ddsd.dwSize = sizeof(ddsd);
3225 ddsd.dwFlags = DDSD_CAPS;
3226 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3228 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3229 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3230 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3231 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3232 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3233 registry_mode.dmPelsWidth, ddsd.dwWidth);
3234 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3235 registry_mode.dmPelsHeight, ddsd.dwHeight);
3236 IDirectDrawSurface4_Release(primary);
3238 /* The screen restore is a property of DDSCL_EXCLUSIVE */
3239 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3240 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3241 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3242 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3244 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3245 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3247 memset(&ddsd, 0, sizeof(ddsd));
3248 ddsd.dwSize = sizeof(ddsd);
3249 ddsd.dwFlags = DDSD_CAPS;
3250 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3252 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3253 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3254 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3255 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3256 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3257 param.ddraw_width, ddsd.dwWidth);
3258 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3259 param.ddraw_height, ddsd.dwHeight);
3260 IDirectDrawSurface4_Release(primary);
3262 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
3263 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3265 /* If the window is changed at the same time, messages are sent to the new window. */
3266 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3267 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3268 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3269 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3271 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3272 expect_messages = exclusive_messages;
3273 screen_size.cx = 0;
3274 screen_size.cy = 0;
3275 screen_size2.cx = 0;
3276 screen_size2.cy = 0;
3278 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3279 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3281 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3282 expect_messages = NULL;
3283 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n",
3284 screen_size.cx, screen_size.cy);
3285 ok(screen_size2.cx == registry_mode.dmPelsWidth && screen_size2.cy == registry_mode.dmPelsHeight,
3286 "Expected screen size 2 %ux%u, got %ux%u.\n",
3287 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size2.cx, screen_size2.cy);
3289 GetWindowRect(window, &r);
3290 ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3291 ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
3292 r.left, r.top, r.right, r.bottom);
3293 GetWindowRect(window2, &r);
3294 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3295 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
3296 r.left, r.top, r.right, r.bottom);
3298 memset(&ddsd, 0, sizeof(ddsd));
3299 ddsd.dwSize = sizeof(ddsd);
3300 ddsd.dwFlags = DDSD_CAPS;
3301 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3303 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3304 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3305 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3306 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3307 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3308 registry_mode.dmPelsWidth, ddsd.dwWidth);
3309 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3310 registry_mode.dmPelsHeight, ddsd.dwHeight);
3311 IDirectDrawSurface4_Release(primary);
3313 ref = IDirectDraw4_Release(ddraw);
3314 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3316 GetWindowRect(window, &r);
3317 ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3318 ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
3319 r.left, r.top, r.right, r.bottom);
3321 expect_messages = NULL;
3322 DestroyWindow(window);
3323 DestroyWindow(window2);
3324 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3325 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
3328 static void test_coop_level_mode_set_multi(void)
3330 IDirectDraw4 *ddraw1, *ddraw2;
3331 UINT w, h;
3332 HWND window;
3333 HRESULT hr;
3334 ULONG ref;
3336 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3337 0, 0, 100, 100, 0, 0, 0, 0);
3338 ddraw1 = create_ddraw();
3339 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3341 /* With just a single ddraw object, the display mode is restored on
3342 * release. */
3343 hr = set_display_mode(ddraw1, 800, 600);
3344 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3345 w = GetSystemMetrics(SM_CXSCREEN);
3346 ok(w == 800, "Got unexpected screen width %u.\n", w);
3347 h = GetSystemMetrics(SM_CYSCREEN);
3348 ok(h == 600, "Got unexpected screen height %u.\n", h);
3350 ref = IDirectDraw4_Release(ddraw1);
3351 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3352 w = GetSystemMetrics(SM_CXSCREEN);
3353 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3354 h = GetSystemMetrics(SM_CYSCREEN);
3355 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3357 /* When there are multiple ddraw objects, the display mode is restored to
3358 * the initial mode, before the first SetDisplayMode() call. */
3359 ddraw1 = create_ddraw();
3360 hr = set_display_mode(ddraw1, 800, 600);
3361 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3362 w = GetSystemMetrics(SM_CXSCREEN);
3363 ok(w == 800, "Got unexpected screen width %u.\n", w);
3364 h = GetSystemMetrics(SM_CYSCREEN);
3365 ok(h == 600, "Got unexpected screen height %u.\n", h);
3367 ddraw2 = create_ddraw();
3368 hr = set_display_mode(ddraw2, 640, 480);
3369 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3370 w = GetSystemMetrics(SM_CXSCREEN);
3371 ok(w == 640, "Got unexpected screen width %u.\n", w);
3372 h = GetSystemMetrics(SM_CYSCREEN);
3373 ok(h == 480, "Got unexpected screen height %u.\n", h);
3375 ref = IDirectDraw4_Release(ddraw2);
3376 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3377 w = GetSystemMetrics(SM_CXSCREEN);
3378 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3379 h = GetSystemMetrics(SM_CYSCREEN);
3380 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3382 ref = IDirectDraw4_Release(ddraw1);
3383 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3384 w = GetSystemMetrics(SM_CXSCREEN);
3385 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3386 h = GetSystemMetrics(SM_CYSCREEN);
3387 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3389 /* Regardless of release ordering. */
3390 ddraw1 = create_ddraw();
3391 hr = set_display_mode(ddraw1, 800, 600);
3392 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3393 w = GetSystemMetrics(SM_CXSCREEN);
3394 ok(w == 800, "Got unexpected screen width %u.\n", w);
3395 h = GetSystemMetrics(SM_CYSCREEN);
3396 ok(h == 600, "Got unexpected screen height %u.\n", h);
3398 ddraw2 = create_ddraw();
3399 hr = set_display_mode(ddraw2, 640, 480);
3400 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3401 w = GetSystemMetrics(SM_CXSCREEN);
3402 ok(w == 640, "Got unexpected screen width %u.\n", w);
3403 h = GetSystemMetrics(SM_CYSCREEN);
3404 ok(h == 480, "Got unexpected screen height %u.\n", h);
3406 ref = IDirectDraw4_Release(ddraw1);
3407 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3408 w = GetSystemMetrics(SM_CXSCREEN);
3409 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3410 h = GetSystemMetrics(SM_CYSCREEN);
3411 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3413 ref = IDirectDraw4_Release(ddraw2);
3414 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3415 w = GetSystemMetrics(SM_CXSCREEN);
3416 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3417 h = GetSystemMetrics(SM_CYSCREEN);
3418 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3420 /* But only for ddraw objects that called SetDisplayMode(). */
3421 ddraw1 = create_ddraw();
3422 ddraw2 = create_ddraw();
3423 hr = set_display_mode(ddraw2, 640, 480);
3424 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3425 w = GetSystemMetrics(SM_CXSCREEN);
3426 ok(w == 640, "Got unexpected screen width %u.\n", w);
3427 h = GetSystemMetrics(SM_CYSCREEN);
3428 ok(h == 480, "Got unexpected screen height %u.\n", h);
3430 ref = IDirectDraw4_Release(ddraw1);
3431 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3432 w = GetSystemMetrics(SM_CXSCREEN);
3433 ok(w == 640, "Got unexpected screen width %u.\n", w);
3434 h = GetSystemMetrics(SM_CYSCREEN);
3435 ok(h == 480, "Got unexpected screen height %u.\n", h);
3437 ref = IDirectDraw4_Release(ddraw2);
3438 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3439 w = GetSystemMetrics(SM_CXSCREEN);
3440 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3441 h = GetSystemMetrics(SM_CYSCREEN);
3442 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3444 /* If there's a ddraw object that's currently in exclusive mode, it blocks
3445 * restoring the display mode. */
3446 ddraw1 = create_ddraw();
3447 hr = set_display_mode(ddraw1, 800, 600);
3448 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3449 w = GetSystemMetrics(SM_CXSCREEN);
3450 ok(w == 800, "Got unexpected screen width %u.\n", w);
3451 h = GetSystemMetrics(SM_CYSCREEN);
3452 ok(h == 600, "Got unexpected screen height %u.\n", h);
3454 ddraw2 = create_ddraw();
3455 hr = set_display_mode(ddraw2, 640, 480);
3456 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3457 w = GetSystemMetrics(SM_CXSCREEN);
3458 ok(w == 640, "Got unexpected screen width %u.\n", w);
3459 h = GetSystemMetrics(SM_CYSCREEN);
3460 ok(h == 480, "Got unexpected screen height %u.\n", h);
3462 hr = IDirectDraw4_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3463 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3465 ref = IDirectDraw4_Release(ddraw1);
3466 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3467 w = GetSystemMetrics(SM_CXSCREEN);
3468 ok(w == 640, "Got unexpected screen width %u.\n", w);
3469 h = GetSystemMetrics(SM_CYSCREEN);
3470 ok(h == 480, "Got unexpected screen height %u.\n", h);
3472 ref = IDirectDraw4_Release(ddraw2);
3473 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3474 w = GetSystemMetrics(SM_CXSCREEN);
3475 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3476 h = GetSystemMetrics(SM_CYSCREEN);
3477 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3479 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3480 ddraw1 = create_ddraw();
3481 hr = set_display_mode(ddraw1, 800, 600);
3482 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3483 w = GetSystemMetrics(SM_CXSCREEN);
3484 ok(w == 800, "Got unexpected screen width %u.\n", w);
3485 h = GetSystemMetrics(SM_CYSCREEN);
3486 ok(h == 600, "Got unexpected screen height %u.\n", h);
3488 hr = IDirectDraw4_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3489 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3491 ddraw2 = create_ddraw();
3492 hr = set_display_mode(ddraw2, 640, 480);
3493 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3495 ref = IDirectDraw4_Release(ddraw1);
3496 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3497 w = GetSystemMetrics(SM_CXSCREEN);
3498 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3499 h = GetSystemMetrics(SM_CYSCREEN);
3500 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3502 ref = IDirectDraw4_Release(ddraw2);
3503 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3504 w = GetSystemMetrics(SM_CXSCREEN);
3505 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3506 h = GetSystemMetrics(SM_CYSCREEN);
3507 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3509 DestroyWindow(window);
3512 static void test_initialize(void)
3514 IDirectDraw4 *ddraw;
3515 HRESULT hr;
3517 ddraw = create_ddraw();
3518 ok(!!ddraw, "Failed to create a ddraw object.\n");
3520 hr = IDirectDraw4_Initialize(ddraw, NULL);
3521 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
3522 IDirectDraw4_Release(ddraw);
3524 CoInitialize(NULL);
3525 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw4, (void **)&ddraw);
3526 ok(SUCCEEDED(hr), "Failed to create IDirectDraw4 instance, hr %#x.\n", hr);
3527 hr = IDirectDraw4_Initialize(ddraw, NULL);
3528 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
3529 hr = IDirectDraw4_Initialize(ddraw, NULL);
3530 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
3531 IDirectDraw4_Release(ddraw);
3532 CoUninitialize();
3535 static void test_coop_level_surf_create(void)
3537 IDirectDrawSurface4 *surface;
3538 IDirectDraw4 *ddraw;
3539 DDSURFACEDESC2 ddsd;
3540 HRESULT hr;
3542 ddraw = create_ddraw();
3543 ok(!!ddraw, "Failed to create a ddraw object.\n");
3545 memset(&ddsd, 0, sizeof(ddsd));
3546 ddsd.dwSize = sizeof(ddsd);
3547 ddsd.dwFlags = DDSD_CAPS;
3548 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3549 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
3550 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3552 IDirectDraw4_Release(ddraw);
3555 static void test_vb_discard(void)
3557 static const struct vec4 quad[] =
3559 { 0.0f, 480.0f, 0.0f, 1.0f},
3560 { 0.0f, 0.0f, 0.0f, 1.0f},
3561 {640.0f, 480.0f, 0.0f, 1.0f},
3562 {640.0f, 0.0f, 0.0f, 1.0f},
3565 IDirect3DDevice3 *device;
3566 IDirect3D3 *d3d;
3567 IDirect3DVertexBuffer *buffer;
3568 HWND window;
3569 HRESULT hr;
3570 D3DVERTEXBUFFERDESC desc;
3571 BYTE *data;
3572 static const unsigned int vbsize = 16;
3573 unsigned int i;
3575 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3576 0, 0, 640, 480, 0, 0, 0, 0);
3578 if (!(device = create_device(window, DDSCL_NORMAL)))
3580 skip("Failed to create a 3D device, skipping test.\n");
3581 DestroyWindow(window);
3582 return;
3585 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
3586 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
3588 memset(&desc, 0, sizeof(desc));
3589 desc.dwSize = sizeof(desc);
3590 desc.dwCaps = D3DVBCAPS_WRITEONLY;
3591 desc.dwFVF = D3DFVF_XYZRHW;
3592 desc.dwNumVertices = vbsize;
3593 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &buffer, 0, NULL);
3594 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3596 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3597 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3598 memcpy(data, quad, sizeof(quad));
3599 hr = IDirect3DVertexBuffer_Unlock(buffer);
3600 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3602 hr = IDirect3DDevice3_BeginScene(device);
3603 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3604 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
3605 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3606 hr = IDirect3DDevice3_EndScene(device);
3607 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3609 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3610 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3611 memset(data, 0xaa, sizeof(struct vec4) * vbsize);
3612 hr = IDirect3DVertexBuffer_Unlock(buffer);
3613 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3615 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3616 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3617 for (i = 0; i < sizeof(struct vec4) * vbsize; i++)
3619 if (data[i] != 0xaa)
3621 ok(FALSE, "Vertex buffer data byte %u is 0x%02x, expected 0xaa\n", i, data[i]);
3622 break;
3625 hr = IDirect3DVertexBuffer_Unlock(buffer);
3626 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3628 IDirect3DVertexBuffer_Release(buffer);
3629 IDirect3D3_Release(d3d);
3630 IDirect3DDevice3_Release(device);
3631 DestroyWindow(window);
3634 static void test_coop_level_multi_window(void)
3636 HWND window1, window2;
3637 IDirectDraw4 *ddraw;
3638 HRESULT hr;
3640 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
3641 0, 0, 640, 480, 0, 0, 0, 0);
3642 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
3643 0, 0, 640, 480, 0, 0, 0, 0);
3644 ddraw = create_ddraw();
3645 ok(!!ddraw, "Failed to create a ddraw object.\n");
3647 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
3648 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3649 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3650 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3651 ok(IsWindow(window1), "Window 1 was destroyed.\n");
3652 ok(IsWindow(window2), "Window 2 was destroyed.\n");
3654 IDirectDraw4_Release(ddraw);
3655 DestroyWindow(window2);
3656 DestroyWindow(window1);
3659 static void test_draw_strided(void)
3661 static struct vec3 position[] =
3663 {-1.0, -1.0, 0.0},
3664 {-1.0, 1.0, 0.0},
3665 { 1.0, 1.0, 0.0},
3666 { 1.0, -1.0, 0.0},
3668 static DWORD diffuse[] =
3670 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
3672 static WORD indices[] =
3674 0, 1, 2, 2, 3, 0
3677 IDirectDrawSurface4 *rt;
3678 IDirect3DDevice3 *device;
3679 D3DCOLOR color;
3680 HWND window;
3681 HRESULT hr;
3682 D3DDRAWPRIMITIVESTRIDEDDATA strided;
3683 IDirect3DViewport3 *viewport;
3684 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3686 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3687 0, 0, 640, 480, 0, 0, 0, 0);
3689 if (!(device = create_device(window, DDSCL_NORMAL)))
3691 skip("Failed to create a 3D device, skipping test.\n");
3692 DestroyWindow(window);
3693 return;
3696 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
3697 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3698 viewport = create_viewport(device, 0, 0, 640, 480);
3699 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
3700 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
3701 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
3702 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
3704 hr = IDirect3DDevice3_BeginScene(device);
3705 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3707 memset(&strided, 0x55, sizeof(strided));
3708 strided.position.lpvData = position;
3709 strided.position.dwStride = sizeof(*position);
3710 strided.diffuse.lpvData = diffuse;
3711 strided.diffuse.dwStride = sizeof(*diffuse);
3712 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE,
3713 &strided, 4, indices, 6, 0);
3714 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3716 hr = IDirect3DDevice3_EndScene(device);
3717 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3719 color = get_surface_color(rt, 320, 240);
3720 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3722 IDirect3DViewport3_Release(viewport);
3723 IDirectDrawSurface4_Release(rt);
3724 IDirect3DDevice3_Release(device);
3725 DestroyWindow(window);
3728 static void test_clear_rect_count(void)
3730 IDirectDrawSurface4 *rt;
3731 IDirect3DDevice3 *device;
3732 D3DCOLOR color;
3733 HWND window;
3734 HRESULT hr;
3735 IDirect3DViewport3 *viewport;
3736 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3738 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3739 0, 0, 640, 480, 0, 0, 0, 0);
3740 if (!(device = create_device(window, DDSCL_NORMAL)))
3742 skip("Failed to create a 3D device, skipping test.\n");
3743 DestroyWindow(window);
3744 return;
3747 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
3748 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3750 viewport = create_viewport(device, 0, 0, 640, 480);
3751 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
3752 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
3753 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00ffffff, 0.0f, 0);
3754 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
3755 hr = IDirect3DViewport3_Clear2(viewport, 0, &clear_rect, D3DCLEAR_TARGET, 0x00ff0000, 0.0f, 0);
3756 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
3757 hr = IDirect3DViewport3_Clear2(viewport, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 0.0f, 0);
3758 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
3759 hr = IDirect3DViewport3_Clear2(viewport, 1, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
3760 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
3762 color = get_surface_color(rt, 320, 240);
3763 ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
3765 IDirect3DViewport3_Release(viewport);
3766 IDirectDrawSurface4_Release(rt);
3767 IDirect3DDevice3_Release(device);
3768 DestroyWindow(window);
3771 static BOOL test_mode_restored(IDirectDraw4 *ddraw, HWND window)
3773 DDSURFACEDESC2 ddsd1, ddsd2;
3774 HRESULT hr;
3776 memset(&ddsd1, 0, sizeof(ddsd1));
3777 ddsd1.dwSize = sizeof(ddsd1);
3778 hr = IDirectDraw4_GetDisplayMode(ddraw, &ddsd1);
3779 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
3781 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3782 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3783 hr = set_display_mode(ddraw, 640, 480);
3784 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3785 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3786 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3788 memset(&ddsd2, 0, sizeof(ddsd2));
3789 ddsd2.dwSize = sizeof(ddsd2);
3790 hr = IDirectDraw4_GetDisplayMode(ddraw, &ddsd2);
3791 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
3792 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
3793 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3795 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
3798 static void test_coop_level_versions(void)
3800 HWND window;
3801 IDirectDraw *ddraw;
3802 HRESULT hr;
3803 BOOL restored;
3804 IDirectDrawSurface *surface;
3805 IDirectDraw4 *ddraw4;
3806 DDSURFACEDESC ddsd;
3808 window = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
3809 0, 0, 640, 480, 0, 0, 0, 0);
3811 ddraw4 = create_ddraw();
3812 ok(!!ddraw4, "Failed to create a ddraw object.\n");
3813 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
3814 restored = test_mode_restored(ddraw4, window);
3815 ok(restored, "Display mode not restored in new ddraw object\n");
3817 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
3818 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
3819 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3821 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
3822 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
3823 restored = test_mode_restored(ddraw4, window);
3824 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
3826 /* A successful one does */
3827 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3828 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3829 restored = test_mode_restored(ddraw4, window);
3830 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
3832 IDirectDraw_Release(ddraw);
3833 IDirectDraw4_Release(ddraw4);
3835 ddraw4 = create_ddraw();
3836 ok(!!ddraw4, "Failed to create a ddraw object.\n");
3837 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
3838 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3840 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
3841 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3842 restored = test_mode_restored(ddraw4, window);
3843 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
3845 IDirectDraw_Release(ddraw);
3846 IDirectDraw4_Release(ddraw4);
3848 /* A failing call does not restore the ddraw2+ behavior */
3849 ddraw4 = create_ddraw();
3850 ok(!!ddraw4, "Failed to create a ddraw object.\n");
3851 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
3852 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3854 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3855 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3856 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
3857 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
3858 restored = test_mode_restored(ddraw4, window);
3859 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
3861 IDirectDraw_Release(ddraw);
3862 IDirectDraw4_Release(ddraw4);
3864 /* Neither does a sequence of successful calls with the new interface */
3865 ddraw4 = create_ddraw();
3866 ok(!!ddraw4, "Failed to create a ddraw object.\n");
3867 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
3868 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3870 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3871 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3872 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
3873 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3874 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_NORMAL);
3875 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3877 restored = test_mode_restored(ddraw4, window);
3878 ok(!restored, "Display mode restored after ddraw1-ddraw4 SetCooperativeLevel() call sequence\n");
3879 IDirectDraw_Release(ddraw);
3880 IDirectDraw4_Release(ddraw4);
3882 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
3883 ddraw4 = create_ddraw();
3884 ok(!!ddraw4, "Failed to create a ddraw object.\n");
3885 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
3886 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3888 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_NORMAL);
3889 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3891 memset(&ddsd, 0, sizeof(ddsd));
3892 ddsd.dwSize = sizeof(ddsd);
3893 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
3894 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
3895 ddsd.dwWidth = ddsd.dwHeight = 8;
3896 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3897 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
3898 IDirectDrawSurface_Release(surface);
3899 restored = test_mode_restored(ddraw4, window);
3900 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
3902 IDirectDraw_Release(ddraw);
3903 IDirectDraw4_Release(ddraw4);
3904 DestroyWindow(window);
3907 static void test_lighting_interface_versions(void)
3909 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3910 IDirect3DMaterial3 *emissive;
3911 IDirect3DViewport3 *viewport;
3912 IDirect3DDevice3 *device;
3913 IDirectDrawSurface4 *rt;
3914 D3DCOLOR color;
3915 HWND window;
3916 HRESULT hr;
3917 D3DMATERIALHANDLE mat_handle;
3918 DWORD rs;
3919 unsigned int i;
3920 ULONG ref;
3921 static D3DVERTEX quad[] =
3923 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3924 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3925 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3926 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3929 #define FVF_COLORVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_SPECULAR)
3930 static struct
3932 struct vec3 position;
3933 struct vec3 normal;
3934 DWORD diffuse, specular;
3936 quad2[] =
3938 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
3939 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
3940 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
3941 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
3944 static D3DLVERTEX lquad[] =
3946 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3947 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3948 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3949 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3952 #define FVF_LVERTEX2 (D3DFVF_LVERTEX & ~D3DFVF_RESERVED1)
3953 static struct
3955 struct vec3 position;
3956 DWORD diffuse, specular;
3957 struct vec2 texcoord;
3959 lquad2[] =
3961 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
3962 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
3963 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
3964 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
3967 static D3DTLVERTEX tlquad[] =
3969 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3970 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3971 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3972 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3975 static const struct
3977 DWORD vertextype;
3978 void *data;
3979 DWORD d3drs_lighting, d3drs_specular;
3980 DWORD draw_flags;
3981 D3DCOLOR color;
3983 tests[] =
3985 /* Lighting is enabled when all of these conditions are met:
3986 * 1) No pretransformed position(D3DFVF_XYZRHW)
3987 * 2) Normals are available (D3DFVF_NORMAL)
3988 * 3) D3DDP_DONOTLIGHT is not set.
3990 * D3DRENDERSTATE_LIGHTING is ignored, it is not defined
3991 * in this d3d version */
3993 /* 0 */
3994 { D3DFVF_VERTEX, quad, FALSE, FALSE, 0, 0x0000ff00},
3995 { D3DFVF_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
3996 { D3DFVF_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
3997 { D3DFVF_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
3998 { D3DFVF_VERTEX, quad, FALSE, TRUE, 0, 0x0000ff00},
3999 { D3DFVF_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
4000 { D3DFVF_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
4001 { D3DFVF_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
4003 /* 8 */
4004 { FVF_COLORVERTEX, quad2, FALSE, FALSE, 0, 0x0000ff00},
4005 { FVF_COLORVERTEX, quad2, TRUE, FALSE, 0, 0x0000ff00},
4006 { FVF_COLORVERTEX, quad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4007 { FVF_COLORVERTEX, quad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4008 /* The specular color in the vertex is ignored because
4009 * D3DRENDERSTATE_COLORVERTEX is not enabled */
4010 { FVF_COLORVERTEX, quad2, FALSE, TRUE, 0, 0x0000ff00},
4011 { FVF_COLORVERTEX, quad2, TRUE, TRUE, 0, 0x0000ff00},
4012 { FVF_COLORVERTEX, quad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4013 { FVF_COLORVERTEX, quad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4015 /* 16 */
4016 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
4017 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, 0, 0x00ff0000},
4018 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4019 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4020 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
4021 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, 0, 0x00ff8080},
4022 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4023 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4025 /* 24 */
4026 { FVF_LVERTEX2, lquad2, FALSE, FALSE, 0, 0x00ff0000},
4027 { FVF_LVERTEX2, lquad2, TRUE, FALSE, 0, 0x00ff0000},
4028 { FVF_LVERTEX2, lquad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4029 { FVF_LVERTEX2, lquad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4030 { FVF_LVERTEX2, lquad2, FALSE, TRUE, 0, 0x00ff8080},
4031 { FVF_LVERTEX2, lquad2, TRUE, TRUE, 0, 0x00ff8080},
4032 { FVF_LVERTEX2, lquad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4033 { FVF_LVERTEX2, lquad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4035 /* 32 */
4036 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
4037 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
4038 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4039 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4040 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
4041 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
4042 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4043 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4046 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4047 0, 0, 640, 480, 0, 0, 0, 0);
4049 if (!(device = create_device(window, DDSCL_NORMAL)))
4051 skip("Failed to create a 3D device, skipping test.\n");
4052 DestroyWindow(window);
4053 return;
4056 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
4057 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4059 viewport = create_viewport(device, 0, 0, 640, 480);
4060 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
4061 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
4063 emissive = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
4064 hr = IDirect3DMaterial3_GetHandle(emissive, device, &mat_handle);
4065 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
4066 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
4067 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
4068 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
4069 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr);
4071 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
4072 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#x.\n", hr);
4073 ok(rs == FALSE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#x, expected FALSE.\n", rs);
4075 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4077 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff202020, 0.0f, 0);
4078 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4080 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
4081 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#x.\n", hr);
4082 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
4083 tests[i].d3drs_specular);
4084 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#x.\n", hr);
4086 hr = IDirect3DDevice3_BeginScene(device);
4087 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4088 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
4089 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
4090 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4091 hr = IDirect3DDevice3_EndScene(device);
4092 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4094 color = get_surface_color(rt, 320, 240);
4095 ok(compare_color(color, tests[i].color, 1),
4096 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
4097 color, tests[i].color, i);
4100 destroy_material(emissive);
4101 IDirectDrawSurface4_Release(rt);
4102 ref = IDirect3DDevice3_Release(device);
4103 ok(ref == 0, "Device not properly released, refcount %u.\n", ref);
4104 DestroyWindow(window);
4107 static struct
4109 BOOL received;
4110 IDirectDraw4 *ddraw;
4111 HWND window;
4112 DWORD coop_level;
4113 } activateapp_testdata;
4115 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
4117 if (message == WM_ACTIVATEAPP)
4119 if (activateapp_testdata.ddraw)
4121 HRESULT hr;
4122 activateapp_testdata.received = FALSE;
4123 hr = IDirectDraw4_SetCooperativeLevel(activateapp_testdata.ddraw,
4124 activateapp_testdata.window, activateapp_testdata.coop_level);
4125 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
4126 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
4128 activateapp_testdata.received = TRUE;
4131 return DefWindowProcA(hwnd, message, wparam, lparam);
4134 static void test_coop_level_activateapp(void)
4136 IDirectDraw4 *ddraw;
4137 HRESULT hr;
4138 HWND window;
4139 WNDCLASSA wc = {0};
4140 DDSURFACEDESC2 ddsd;
4141 IDirectDrawSurface4 *surface;
4143 ddraw = create_ddraw();
4144 ok(!!ddraw, "Failed to create a ddraw object.\n");
4146 wc.lpfnWndProc = activateapp_test_proc;
4147 wc.lpszClassName = "ddraw_test_wndproc_wc";
4148 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4150 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
4151 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
4153 /* Exclusive with window already active. */
4154 SetForegroundWindow(window);
4155 activateapp_testdata.received = FALSE;
4156 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4157 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4158 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
4159 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4160 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4162 /* Exclusive with window not active. */
4163 SetForegroundWindow(GetDesktopWindow());
4164 activateapp_testdata.received = FALSE;
4165 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4166 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4167 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4168 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4169 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4171 /* Normal with window not active, then exclusive with the same window. */
4172 SetForegroundWindow(GetDesktopWindow());
4173 activateapp_testdata.received = FALSE;
4174 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4175 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4176 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
4177 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4178 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4179 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4180 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4181 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4183 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
4184 SetForegroundWindow(GetDesktopWindow());
4185 activateapp_testdata.received = FALSE;
4186 activateapp_testdata.ddraw = ddraw;
4187 activateapp_testdata.window = window;
4188 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
4189 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4190 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4191 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4192 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4193 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4195 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
4196 * succeeding. Another switch to exclusive and back to normal is needed to release the
4197 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
4198 * WM_ACTIVATEAPP messages. */
4199 activateapp_testdata.ddraw = NULL;
4200 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4201 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4202 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4203 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4205 /* Setting DDSCL_NORMAL with recursive invocation. */
4206 SetForegroundWindow(GetDesktopWindow());
4207 activateapp_testdata.received = FALSE;
4208 activateapp_testdata.ddraw = ddraw;
4209 activateapp_testdata.window = window;
4210 activateapp_testdata.coop_level = DDSCL_NORMAL;
4211 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4212 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4213 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4215 /* DDraw is in exlusive mode now. */
4216 memset(&ddsd, 0, sizeof(ddsd));
4217 ddsd.dwSize = sizeof(ddsd);
4218 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
4219 U5(ddsd).dwBackBufferCount = 1;
4220 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
4221 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
4222 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4223 IDirectDrawSurface4_Release(surface);
4225 /* Recover again, just to be sure. */
4226 activateapp_testdata.ddraw = NULL;
4227 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4228 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4229 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4230 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4232 DestroyWindow(window);
4233 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
4234 IDirectDraw4_Release(ddraw);
4237 static void test_texturemanage(void)
4239 IDirectDraw4 *ddraw;
4240 HRESULT hr;
4241 DDSURFACEDESC2 ddsd;
4242 IDirectDrawSurface4 *surface;
4243 unsigned int i;
4244 DDCAPS hal_caps, hel_caps;
4245 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
4246 static const struct
4248 DWORD caps_in, caps2_in;
4249 HRESULT hr;
4250 DWORD caps_out, caps2_out;
4252 tests[] =
4254 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4255 ~0U, ~0U},
4256 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4257 ~0U, ~0U},
4258 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4259 ~0U, ~0U},
4260 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4261 ~0U, ~0U},
4262 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DD_OK,
4263 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE},
4264 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DD_OK,
4265 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE},
4266 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
4267 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_LOCALVIDMEM, 0},
4268 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
4269 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0},
4271 {0, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4272 ~0U, ~0U},
4273 {0, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4274 ~0U, ~0U},
4275 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4276 ~0U, ~0U},
4277 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4278 ~0U, ~0U},
4279 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4280 ~0U, ~0U},
4281 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4282 ~0U, ~0U},
4283 {DDSCAPS_VIDEOMEMORY, 0, DD_OK,
4284 DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY, 0},
4285 {DDSCAPS_SYSTEMMEMORY, 0, DD_OK,
4286 DDSCAPS_SYSTEMMEMORY, 0},
4289 ddraw = create_ddraw();
4290 ok(!!ddraw, "Failed to create a ddraw object.\n");
4291 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4292 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4294 memset(&hal_caps, 0, sizeof(hal_caps));
4295 hal_caps.dwSize = sizeof(hal_caps);
4296 memset(&hel_caps, 0, sizeof(hel_caps));
4297 hel_caps.dwSize = sizeof(hel_caps);
4298 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, &hel_caps);
4299 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
4300 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
4302 skip("Managed textures not supported, skipping managed texture test.\n");
4303 IDirectDraw4_Release(ddraw);
4304 return;
4307 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4309 memset(&ddsd, 0, sizeof(ddsd));
4310 ddsd.dwSize = sizeof(ddsd);
4311 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4312 ddsd.ddsCaps.dwCaps = tests[i].caps_in;
4313 ddsd.ddsCaps.dwCaps2 = tests[i].caps2_in;
4314 ddsd.dwWidth = 4;
4315 ddsd.dwHeight = 4;
4317 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
4318 ok(hr == tests[i].hr, "Got unexpected, hr %#x, case %u.\n", hr, i);
4319 if (FAILED(hr))
4320 continue;
4322 memset(&ddsd, 0, sizeof(ddsd));
4323 ddsd.dwSize = sizeof(ddsd);
4324 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
4325 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4327 ok(ddsd.ddsCaps.dwCaps == tests[i].caps_out,
4328 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
4329 tests[i].caps_in, tests[i].caps2_in, tests[i].caps_out, ddsd.ddsCaps.dwCaps, i);
4330 ok(ddsd.ddsCaps.dwCaps2 == tests[i].caps2_out,
4331 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
4332 tests[i].caps_in, tests[i].caps2_in, tests[i].caps2_out, ddsd.ddsCaps.dwCaps2, i);
4334 IDirectDrawSurface4_Release(surface);
4337 IDirectDraw4_Release(ddraw);
4340 #define SUPPORT_DXT1 0x01
4341 #define SUPPORT_DXT2 0x02
4342 #define SUPPORT_DXT3 0x04
4343 #define SUPPORT_DXT4 0x08
4344 #define SUPPORT_DXT5 0x10
4345 #define SUPPORT_YUY2 0x20
4346 #define SUPPORT_UYVY 0x40
4348 static HRESULT WINAPI test_block_formats_creation_cb(DDPIXELFORMAT *fmt, void *ctx)
4350 DWORD *supported_fmts = ctx;
4352 if (!(fmt->dwFlags & DDPF_FOURCC))
4353 return DDENUMRET_OK;
4355 switch (fmt->dwFourCC)
4357 case MAKEFOURCC('D','X','T','1'):
4358 *supported_fmts |= SUPPORT_DXT1;
4359 break;
4360 case MAKEFOURCC('D','X','T','2'):
4361 *supported_fmts |= SUPPORT_DXT2;
4362 break;
4363 case MAKEFOURCC('D','X','T','3'):
4364 *supported_fmts |= SUPPORT_DXT3;
4365 break;
4366 case MAKEFOURCC('D','X','T','4'):
4367 *supported_fmts |= SUPPORT_DXT4;
4368 break;
4369 case MAKEFOURCC('D','X','T','5'):
4370 *supported_fmts |= SUPPORT_DXT5;
4371 break;
4372 case MAKEFOURCC('Y','U','Y','2'):
4373 *supported_fmts |= SUPPORT_YUY2;
4374 break;
4375 case MAKEFOURCC('U','Y','V','Y'):
4376 *supported_fmts |= SUPPORT_UYVY;
4377 break;
4378 default:
4379 break;
4382 return DDENUMRET_OK;
4385 static void test_block_formats_creation(void)
4387 HRESULT hr, expect_hr;
4388 unsigned int i, j, w, h;
4389 HWND window;
4390 IDirectDraw4 *ddraw;
4391 IDirect3D3 *d3d;
4392 IDirect3DDevice3 *device;
4393 IDirectDrawSurface4 *surface;
4394 DWORD supported_fmts = 0, supported_overlay_fmts = 0;
4395 DWORD num_fourcc_codes = 0, *fourcc_codes;
4396 DDSURFACEDESC2 ddsd;
4397 DDCAPS hal_caps;
4398 void *mem;
4400 static const struct
4402 DWORD fourcc;
4403 const char *name;
4404 DWORD support_flag;
4405 unsigned int block_width;
4406 unsigned int block_height;
4407 unsigned int block_size;
4408 BOOL create_size_checked, overlay;
4410 formats[] =
4412 {MAKEFOURCC('D','X','T','1'), "D3DFMT_DXT1", SUPPORT_DXT1, 4, 4, 8, TRUE, FALSE},
4413 {MAKEFOURCC('D','X','T','2'), "D3DFMT_DXT2", SUPPORT_DXT2, 4, 4, 16, TRUE, FALSE},
4414 {MAKEFOURCC('D','X','T','3'), "D3DFMT_DXT3", SUPPORT_DXT3, 4, 4, 16, TRUE, FALSE},
4415 {MAKEFOURCC('D','X','T','4'), "D3DFMT_DXT4", SUPPORT_DXT4, 4, 4, 16, TRUE, FALSE},
4416 {MAKEFOURCC('D','X','T','5'), "D3DFMT_DXT5", SUPPORT_DXT5, 4, 4, 16, TRUE, FALSE},
4417 {MAKEFOURCC('Y','U','Y','2'), "D3DFMT_YUY2", SUPPORT_YUY2, 2, 1, 4, FALSE, TRUE },
4418 {MAKEFOURCC('U','Y','V','Y'), "D3DFMT_UYVY", SUPPORT_UYVY, 2, 1, 4, FALSE, TRUE },
4420 static const struct
4422 DWORD caps, caps2;
4423 const char *name;
4424 BOOL overlay;
4426 types[] =
4428 /* DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY fails to create any fourcc
4429 * surface with DDERR_INVALIDPIXELFORMAT. Don't care about it for now.
4431 * Nvidia returns E_FAIL on DXTN DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY.
4432 * Other hw / drivers successfully create those surfaces. Ignore them, this
4433 * suggests that no game uses this, otherwise Nvidia would support it. */
4435 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0,
4436 "videomemory texture", FALSE
4439 DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY, 0,
4440 "videomemory overlay", TRUE
4443 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0,
4444 "systemmemory texture", FALSE
4447 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
4448 "managed texture", FALSE
4451 enum size_type
4453 SIZE_TYPE_ZERO,
4454 SIZE_TYPE_PITCH,
4455 SIZE_TYPE_SIZE,
4457 static const struct
4459 DWORD flags;
4460 enum size_type size_type;
4461 int rel_size;
4462 HRESULT hr;
4464 user_mem_tests[] =
4466 {DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DD_OK},
4467 {DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
4468 {DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
4469 {DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
4470 {DDSD_LPSURFACE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
4471 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
4472 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
4473 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
4474 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 1, DD_OK},
4475 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, -1, DDERR_INVALIDPARAMS},
4476 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
4477 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
4478 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_SIZE, 0, DD_OK},
4479 {DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
4482 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4483 0, 0, 640, 480, 0, 0, 0, 0);
4485 if (!(device = create_device(window, DDSCL_NORMAL)))
4487 skip("Failed to create a 3D device, skipping test.\n");
4488 DestroyWindow(window);
4489 return;
4492 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
4493 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
4494 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **) &ddraw);
4495 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
4496 IDirect3D3_Release(d3d);
4498 hr = IDirect3DDevice3_EnumTextureFormats(device, test_block_formats_creation_cb,
4499 &supported_fmts);
4500 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
4502 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
4503 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
4504 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
4505 num_fourcc_codes * sizeof(*fourcc_codes));
4506 if (!fourcc_codes)
4507 goto cleanup;
4508 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
4509 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
4510 for (i = 0; i < num_fourcc_codes; i++)
4512 for (j = 0; j < sizeof(formats) / sizeof(*formats); j++)
4514 if (fourcc_codes[i] == formats[j].fourcc)
4515 supported_overlay_fmts |= formats[j].support_flag;
4518 HeapFree(GetProcessHeap(), 0, fourcc_codes);
4520 memset(&hal_caps, 0, sizeof(hal_caps));
4521 hal_caps.dwSize = sizeof(hal_caps);
4522 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
4523 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
4525 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * 2 * 16 + 1);
4527 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
4529 for (j = 0; j < sizeof(types) / sizeof(*types); j++)
4531 BOOL support;
4533 if (formats[i].overlay != types[j].overlay
4534 || (types[j].overlay && !(hal_caps.dwCaps & DDCAPS_OVERLAY)))
4535 continue;
4537 if (formats[i].overlay)
4538 support = supported_overlay_fmts & formats[i].support_flag;
4539 else
4540 support = supported_fmts & formats[i].support_flag;
4542 for (w = 1; w <= 8; w++)
4544 for (h = 1; h <= 8; h++)
4546 BOOL block_aligned = TRUE;
4547 BOOL todo = FALSE;
4549 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
4550 block_aligned = FALSE;
4552 memset(&ddsd, 0, sizeof(ddsd));
4553 ddsd.dwSize = sizeof(ddsd);
4554 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4555 ddsd.ddsCaps.dwCaps = types[j].caps;
4556 ddsd.ddsCaps.dwCaps2 = types[j].caps2;
4557 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
4558 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
4559 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
4560 ddsd.dwWidth = w;
4561 ddsd.dwHeight = h;
4563 /* TODO: Handle power of two limitations. I cannot test the pow2
4564 * behavior on windows because I have no hardware that doesn't at
4565 * least support np2_conditional. There's probably no HW that
4566 * supports DXTN textures but no conditional np2 textures. */
4567 if (!support && !(types[j].caps & DDSCAPS_SYSTEMMEMORY))
4568 expect_hr = DDERR_INVALIDPARAMS;
4569 else if (formats[i].create_size_checked && !block_aligned)
4571 expect_hr = DDERR_INVALIDPARAMS;
4572 if (!(types[j].caps & DDSCAPS_TEXTURE))
4573 todo = TRUE;
4575 else
4576 expect_hr = D3D_OK;
4578 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
4579 if (todo)
4580 todo_wine ok(hr == expect_hr,
4581 "Got unexpected hr %#x for format %s, resource type %s, size %ux%u, expected %#x.\n",
4582 hr, formats[i].name, types[j].name, w, h, expect_hr);
4583 else
4584 ok(hr == expect_hr,
4585 "Got unexpected hr %#x for format %s, resource type %s, size %ux%u, expected %#x.\n",
4586 hr, formats[i].name, types[j].name, w, h, expect_hr);
4588 if (SUCCEEDED(hr))
4589 IDirectDrawSurface4_Release(surface);
4594 if (formats[i].overlay)
4595 continue;
4597 for (j = 0; j < sizeof(user_mem_tests) / sizeof(*user_mem_tests); ++j)
4599 memset(&ddsd, 0, sizeof(ddsd));
4600 ddsd.dwSize = sizeof(ddsd);
4601 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | user_mem_tests[j].flags;
4602 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE;
4604 switch (user_mem_tests[j].size_type)
4606 case SIZE_TYPE_ZERO:
4607 U1(ddsd).dwLinearSize = 0;
4608 break;
4610 case SIZE_TYPE_PITCH:
4611 U1(ddsd).dwLinearSize = 2 * formats[i].block_size;
4612 break;
4614 case SIZE_TYPE_SIZE:
4615 U1(ddsd).dwLinearSize = 2 * 2 * formats[i].block_size;
4616 break;
4618 U1(ddsd).dwLinearSize += user_mem_tests[j].rel_size;
4620 ddsd.lpSurface = mem;
4621 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
4622 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
4623 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
4624 ddsd.dwWidth = 8;
4625 ddsd.dwHeight = 8;
4627 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
4628 ok(hr == user_mem_tests[j].hr, "Test %u: Got unexpected hr %#x, format %s.\n", j, hr, formats[i].name);
4630 if (FAILED(hr))
4631 continue;
4633 memset(&ddsd, 0, sizeof(ddsd));
4634 ddsd.dwSize = sizeof(ddsd);
4635 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
4636 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", j, hr);
4637 ok(ddsd.dwFlags == (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_LINEARSIZE),
4638 "Test %u: Got unexpected flags %#x.\n", j, ddsd.dwFlags);
4639 if (user_mem_tests[j].flags & DDSD_LPSURFACE)
4640 ok(U1(ddsd).dwLinearSize == ~0u, "Test %u: Got unexpected linear size %#x.\n",
4641 j, U1(ddsd).dwLinearSize);
4642 else
4643 ok(U1(ddsd).dwLinearSize == 2 * 2 * formats[i].block_size,
4644 "Test %u: Got unexpected linear size %#x, expected %#x.\n",
4645 j, U1(ddsd).dwLinearSize, 2 * 2 * formats[i].block_size);
4646 IDirectDrawSurface4_Release(surface);
4650 HeapFree(GetProcessHeap(), 0, mem);
4651 cleanup:
4652 IDirectDraw4_Release(ddraw);
4653 IDirect3DDevice3_Release(device);
4654 DestroyWindow(window);
4657 struct format_support_check
4659 const DDPIXELFORMAT *format;
4660 BOOL supported;
4663 static HRESULT WINAPI test_unsupported_formats_cb(DDPIXELFORMAT *fmt, void *ctx)
4665 struct format_support_check *format = ctx;
4667 if (!memcmp(format->format, fmt, sizeof(*fmt)))
4669 format->supported = TRUE;
4670 return DDENUMRET_CANCEL;
4673 return DDENUMRET_OK;
4676 static void test_unsupported_formats(void)
4678 HRESULT hr;
4679 BOOL expect_success;
4680 HWND window;
4681 IDirectDraw4 *ddraw;
4682 IDirect3D3 *d3d;
4683 IDirect3DDevice3 *device;
4684 IDirectDrawSurface4 *surface;
4685 DDSURFACEDESC2 ddsd;
4686 unsigned int i, j;
4687 DWORD expected_caps;
4688 static const struct
4690 const char *name;
4691 DDPIXELFORMAT fmt;
4693 formats[] =
4696 "D3DFMT_A8R8G8B8",
4698 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
4699 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
4703 "D3DFMT_P8",
4705 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
4706 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
4710 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
4712 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4713 0, 0, 640, 480, 0, 0, 0, 0);
4715 if (!(device = create_device(window, DDSCL_NORMAL)))
4717 skip("Failed to create a 3D device, skipping test.\n");
4718 DestroyWindow(window);
4719 return;
4722 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
4723 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
4724 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **) &ddraw);
4725 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
4726 IDirect3D3_Release(d3d);
4728 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
4730 struct format_support_check check = {&formats[i].fmt, FALSE};
4731 hr = IDirect3DDevice3_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
4732 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
4734 for (j = 0; j < sizeof(caps) / sizeof(*caps); j++)
4736 memset(&ddsd, 0, sizeof(ddsd));
4737 ddsd.dwSize = sizeof(ddsd);
4738 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4739 U4(ddsd).ddpfPixelFormat = formats[i].fmt;
4740 ddsd.dwWidth = 4;
4741 ddsd.dwHeight = 4;
4742 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
4744 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
4745 expect_success = FALSE;
4746 else
4747 expect_success = TRUE;
4749 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
4750 ok(SUCCEEDED(hr) == expect_success,
4751 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
4752 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
4753 if (FAILED(hr))
4754 continue;
4756 memset(&ddsd, 0, sizeof(ddsd));
4757 ddsd.dwSize = sizeof(ddsd);
4758 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
4759 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4761 if (caps[j] & DDSCAPS_VIDEOMEMORY)
4762 expected_caps = DDSCAPS_VIDEOMEMORY;
4763 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
4764 expected_caps = DDSCAPS_SYSTEMMEMORY;
4765 else if (check.supported)
4766 expected_caps = DDSCAPS_VIDEOMEMORY;
4767 else
4768 expected_caps = DDSCAPS_SYSTEMMEMORY;
4770 ok(ddsd.ddsCaps.dwCaps & expected_caps,
4771 "Expected capability %#x, format %s, input cap %#x.\n",
4772 expected_caps, formats[i].name, caps[j]);
4774 IDirectDrawSurface4_Release(surface);
4778 IDirectDraw4_Release(ddraw);
4779 IDirect3DDevice3_Release(device);
4780 DestroyWindow(window);
4783 static void test_rt_caps(void)
4785 PALETTEENTRY palette_entries[256];
4786 IDirectDrawPalette *palette;
4787 IDirectDraw4 *ddraw;
4788 DDPIXELFORMAT z_fmt;
4789 IDirect3D3 *d3d;
4790 unsigned int i;
4791 ULONG refcount;
4792 HWND window;
4793 HRESULT hr;
4795 static const DDPIXELFORMAT p8_fmt =
4797 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
4798 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
4801 const struct
4803 const DDPIXELFORMAT *pf;
4804 DWORD caps_in;
4805 DWORD caps_out;
4806 HRESULT create_device_hr;
4807 HRESULT set_rt_hr, alternative_set_rt_hr;
4809 test_data[] =
4812 NULL,
4813 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
4814 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4815 D3D_OK,
4816 D3D_OK,
4817 D3D_OK,
4820 NULL,
4821 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
4822 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4823 D3D_OK,
4824 D3D_OK,
4825 D3D_OK,
4828 NULL,
4829 DDSCAPS_OFFSCREENPLAIN,
4830 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4831 DDERR_INVALIDCAPS,
4832 DDERR_INVALIDCAPS,
4833 DDERR_INVALIDCAPS,
4836 NULL,
4837 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4838 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4839 D3DERR_SURFACENOTINVIDMEM,
4840 D3D_OK,
4841 D3D_OK,
4844 NULL,
4845 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4846 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4847 DDERR_INVALIDCAPS,
4848 DDERR_INVALIDCAPS,
4849 DDERR_INVALIDCAPS,
4852 NULL,
4853 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
4854 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4855 D3D_OK,
4856 D3D_OK,
4857 D3D_OK,
4860 NULL,
4861 DDSCAPS_3DDEVICE,
4862 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4863 D3D_OK,
4864 D3D_OK,
4865 D3D_OK,
4868 NULL,
4870 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4871 DDERR_INVALIDCAPS,
4872 DDERR_INVALIDCAPS,
4873 DDERR_INVALIDCAPS,
4876 NULL,
4877 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4878 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4879 D3DERR_SURFACENOTINVIDMEM,
4880 D3D_OK,
4881 D3D_OK,
4884 NULL,
4885 DDSCAPS_SYSTEMMEMORY,
4886 DDSCAPS_SYSTEMMEMORY,
4887 DDERR_INVALIDCAPS,
4888 DDERR_INVALIDCAPS,
4889 DDERR_INVALIDCAPS,
4892 &p8_fmt,
4894 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4895 DDERR_INVALIDCAPS,
4896 DDERR_INVALIDCAPS,
4897 DDERR_INVALIDCAPS,
4900 &p8_fmt,
4901 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
4902 ~0U /* AMD r200 */,
4903 DDERR_NOPALETTEATTACHED,
4904 DDERR_INVALIDCAPS,
4905 DDERR_INVALIDCAPS,
4908 &p8_fmt,
4909 DDSCAPS_OFFSCREENPLAIN,
4910 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4911 DDERR_INVALIDCAPS,
4912 DDERR_INVALIDCAPS,
4913 DDERR_INVALIDCAPS,
4916 &p8_fmt,
4917 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4918 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4919 DDERR_NOPALETTEATTACHED,
4920 DDERR_INVALIDCAPS,
4921 DDERR_INVALIDCAPS,
4924 &p8_fmt,
4925 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4926 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4927 DDERR_INVALIDCAPS,
4928 DDERR_INVALIDCAPS,
4929 DDERR_INVALIDCAPS,
4932 &z_fmt,
4933 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
4934 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
4935 DDERR_INVALIDCAPS,
4936 DDERR_INVALIDPIXELFORMAT,
4937 D3D_OK /* r200 */,
4940 &z_fmt,
4941 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
4942 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
4943 DDERR_INVALIDCAPS,
4944 DDERR_INVALIDPIXELFORMAT,
4945 D3D_OK /* r200 */,
4948 &z_fmt,
4949 DDSCAPS_ZBUFFER,
4950 DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
4951 DDERR_INVALIDCAPS,
4952 DDERR_INVALIDCAPS,
4953 DDERR_INVALIDCAPS,
4956 &z_fmt,
4957 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
4958 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
4959 DDERR_INVALIDCAPS,
4960 DDERR_INVALIDPIXELFORMAT,
4961 D3D_OK /* r200 */,
4964 &z_fmt,
4965 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
4966 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
4967 DDERR_INVALIDCAPS,
4968 DDERR_INVALIDCAPS,
4969 DDERR_INVALIDCAPS,
4973 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4974 0, 0, 640, 480, 0, 0, 0, 0);
4975 ddraw = create_ddraw();
4976 ok(!!ddraw, "Failed to create a ddraw object.\n");
4977 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4978 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4980 if (FAILED(IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
4982 skip("D3D interface is not available, skipping test.\n");
4983 goto done;
4986 memset(&z_fmt, 0, sizeof(z_fmt));
4987 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
4988 if (FAILED(hr) || !z_fmt.dwSize)
4990 skip("No depth buffer formats available, skipping test.\n");
4991 IDirect3D3_Release(d3d);
4992 goto done;
4995 memset(palette_entries, 0, sizeof(palette_entries));
4996 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
4997 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
4999 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
5001 IDirectDrawSurface4 *surface, *rt, *expected_rt, *tmp;
5002 DDSURFACEDESC2 surface_desc;
5003 IDirect3DDevice3 *device;
5005 memset(&surface_desc, 0, sizeof(surface_desc));
5006 surface_desc.dwSize = sizeof(surface_desc);
5007 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5008 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5009 if (test_data[i].pf)
5011 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5012 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5014 surface_desc.dwWidth = 640;
5015 surface_desc.dwHeight = 480;
5016 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5017 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
5018 i, test_data[i].caps_in, hr);
5020 memset(&surface_desc, 0, sizeof(surface_desc));
5021 surface_desc.dwSize = sizeof(surface_desc);
5022 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
5023 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5024 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
5025 "Test %u: Got unexpected caps %#x, expected %#x.\n",
5026 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5028 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
5029 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
5030 i, hr, test_data[i].create_device_hr);
5031 if (FAILED(hr))
5033 if (hr == DDERR_NOPALETTEATTACHED)
5035 hr = IDirectDrawSurface4_SetPalette(surface, palette);
5036 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
5037 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
5038 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
5039 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
5040 else
5041 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
5043 IDirectDrawSurface4_Release(surface);
5045 memset(&surface_desc, 0, sizeof(surface_desc));
5046 surface_desc.dwSize = sizeof(surface_desc);
5047 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5048 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5049 surface_desc.dwWidth = 640;
5050 surface_desc.dwHeight = 480;
5051 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5052 ok(SUCCEEDED(hr), "Test %u: Failed to create surface, hr %#x.\n", i, hr);
5054 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
5055 ok(SUCCEEDED(hr), "Test %u: Failed to create device, hr %#x.\n", i, hr);
5058 memset(&surface_desc, 0, sizeof(surface_desc));
5059 surface_desc.dwSize = sizeof(surface_desc);
5060 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5061 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5062 if (test_data[i].pf)
5064 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5065 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5067 surface_desc.dwWidth = 640;
5068 surface_desc.dwHeight = 480;
5069 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &rt, NULL);
5070 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
5071 i, test_data[i].caps_in, hr);
5073 hr = IDirect3DDevice3_SetRenderTarget(device, rt, 0);
5074 ok(hr == test_data[i].set_rt_hr || broken(hr == test_data[i].alternative_set_rt_hr),
5075 "Test %u: Got unexpected hr %#x, expected %#x.\n",
5076 i, hr, test_data[i].set_rt_hr);
5077 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
5078 expected_rt = rt;
5079 else
5080 expected_rt = surface;
5082 hr = IDirect3DDevice3_GetRenderTarget(device, &tmp);
5083 ok(SUCCEEDED(hr), "Test %u: Failed to get render target, hr %#x.\n", i, hr);
5084 ok(tmp == expected_rt, "Test %u: Got unexpected rt %p.\n", i, tmp);
5086 IDirectDrawSurface4_Release(tmp);
5087 IDirectDrawSurface4_Release(rt);
5088 refcount = IDirect3DDevice3_Release(device);
5089 ok(refcount == 0, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
5090 refcount = IDirectDrawSurface4_Release(surface);
5091 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
5094 IDirectDrawPalette_Release(palette);
5095 IDirect3D3_Release(d3d);
5097 done:
5098 refcount = IDirectDraw4_Release(ddraw);
5099 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5100 DestroyWindow(window);
5103 static void test_primary_caps(void)
5105 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
5106 IDirectDrawSurface4 *surface;
5107 DDSURFACEDESC2 surface_desc;
5108 IDirectDraw4 *ddraw;
5109 unsigned int i;
5110 ULONG refcount;
5111 HWND window;
5112 HRESULT hr;
5114 static const struct
5116 DWORD coop_level;
5117 DWORD caps_in;
5118 DWORD back_buffer_count;
5119 HRESULT hr;
5120 DWORD caps_out;
5122 test_data[] =
5125 DDSCL_NORMAL,
5126 DDSCAPS_PRIMARYSURFACE,
5127 ~0u,
5128 DD_OK,
5129 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
5132 DDSCL_NORMAL,
5133 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
5134 ~0u,
5135 DDERR_INVALIDCAPS,
5136 ~0u,
5139 DDSCL_NORMAL,
5140 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
5141 ~0u,
5142 DDERR_INVALIDCAPS,
5143 ~0u,
5146 DDSCL_NORMAL,
5147 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
5148 ~0u,
5149 DDERR_INVALIDCAPS,
5150 ~0u,
5153 DDSCL_NORMAL,
5154 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
5155 ~0u,
5156 DDERR_INVALIDCAPS,
5157 ~0u,
5160 DDSCL_NORMAL,
5161 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
5162 ~0u,
5163 DDERR_INVALIDCAPS,
5164 ~0u,
5167 DDSCL_NORMAL,
5168 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5169 ~0u,
5170 DDERR_INVALIDCAPS,
5171 ~0u,
5174 DDSCL_NORMAL,
5175 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5177 DDERR_INVALIDCAPS,
5178 ~0u,
5181 DDSCL_NORMAL,
5182 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5184 DDERR_NOEXCLUSIVEMODE,
5185 ~0u,
5188 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5189 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5191 DDERR_INVALIDCAPS,
5192 ~0u,
5195 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5196 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5198 DD_OK,
5199 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
5202 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5203 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
5205 DDERR_INVALIDCAPS,
5206 ~0u,
5209 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5210 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
5212 DDERR_INVALIDCAPS,
5213 ~0u,
5217 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5218 0, 0, 640, 480, 0, 0, 0, 0);
5219 ddraw = create_ddraw();
5220 ok(!!ddraw, "Failed to create a ddraw object.\n");
5222 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
5224 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
5225 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5227 memset(&surface_desc, 0, sizeof(surface_desc));
5228 surface_desc.dwSize = sizeof(surface_desc);
5229 surface_desc.dwFlags = DDSD_CAPS;
5230 if (test_data[i].back_buffer_count != ~0u)
5231 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
5232 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5233 U5(surface_desc).dwBackBufferCount = test_data[i].back_buffer_count;
5234 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5235 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
5236 if (FAILED(hr))
5237 continue;
5239 memset(&surface_desc, 0, sizeof(surface_desc));
5240 surface_desc.dwSize = sizeof(surface_desc);
5241 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
5242 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5243 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
5244 "Test %u: Got unexpected caps %#x, expected %#x.\n",
5245 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5247 IDirectDrawSurface4_Release(surface);
5250 refcount = IDirectDraw4_Release(ddraw);
5251 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5252 DestroyWindow(window);
5255 static void test_surface_lock(void)
5257 IDirectDraw4 *ddraw;
5258 IDirect3D3 *d3d = NULL;
5259 IDirectDrawSurface4 *surface;
5260 HRESULT hr;
5261 HWND window;
5262 unsigned int i;
5263 DDSURFACEDESC2 ddsd;
5264 ULONG refcount;
5265 DDPIXELFORMAT z_fmt;
5266 static const struct
5268 DWORD caps;
5269 DWORD caps2;
5270 const char *name;
5272 tests[] =
5275 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
5277 "videomemory offscreenplain"
5280 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5282 "systemmemory offscreenplain"
5285 DDSCAPS_PRIMARYSURFACE,
5287 "primary"
5290 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
5292 "videomemory texture"
5295 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
5296 DDSCAPS2_OPAQUE,
5297 "opaque videomemory texture"
5300 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
5302 "systemmemory texture"
5305 DDSCAPS_TEXTURE,
5306 DDSCAPS2_TEXTUREMANAGE,
5307 "managed texture"
5310 DDSCAPS_TEXTURE,
5311 DDSCAPS2_D3DTEXTUREMANAGE,
5312 "managed texture"
5315 DDSCAPS_TEXTURE,
5316 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_OPAQUE,
5317 "opaque managed texture"
5320 DDSCAPS_TEXTURE,
5321 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_OPAQUE,
5322 "opaque managed texture"
5325 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5327 "render target"
5330 DDSCAPS_ZBUFFER,
5332 "Z buffer"
5336 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5337 0, 0, 640, 480, 0, 0, 0, 0);
5338 ddraw = create_ddraw();
5339 ok(!!ddraw, "Failed to create a ddraw object.\n");
5340 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5341 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5343 if (FAILED(IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
5345 skip("D3D interface is not available, skipping test.\n");
5346 goto done;
5349 memset(&z_fmt, 0, sizeof(z_fmt));
5350 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
5351 if (FAILED(hr) || !z_fmt.dwSize)
5353 skip("No depth buffer formats available, skipping test.\n");
5354 goto done;
5357 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
5359 memset(&ddsd, 0, sizeof(ddsd));
5360 ddsd.dwSize = sizeof(ddsd);
5361 ddsd.dwFlags = DDSD_CAPS;
5362 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
5364 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
5365 ddsd.dwWidth = 64;
5366 ddsd.dwHeight = 64;
5368 if (tests[i].caps & DDSCAPS_ZBUFFER)
5370 ddsd.dwFlags |= DDSD_PIXELFORMAT;
5371 U4(ddsd).ddpfPixelFormat = z_fmt;
5373 ddsd.ddsCaps.dwCaps = tests[i].caps;
5374 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
5376 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5377 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
5379 memset(&ddsd, 0, sizeof(ddsd));
5380 ddsd.dwSize = sizeof(ddsd);
5381 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
5382 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
5383 if (SUCCEEDED(hr))
5385 hr = IDirectDrawSurface4_Unlock(surface, NULL);
5386 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
5389 IDirectDrawSurface4_Release(surface);
5392 done:
5393 if (d3d)
5394 IDirect3D3_Release(d3d);
5395 refcount = IDirectDraw4_Release(ddraw);
5396 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5397 DestroyWindow(window);
5400 static void test_surface_discard(void)
5402 IDirect3DDevice3 *device;
5403 IDirect3D3 *d3d;
5404 IDirectDraw4 *ddraw;
5405 HRESULT hr;
5406 HWND window;
5407 DDSURFACEDESC2 ddsd;
5408 IDirectDrawSurface4 *surface, *target;
5409 void *addr;
5410 static const struct
5412 DWORD caps, caps2;
5413 BOOL discard;
5415 tests[] =
5417 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, TRUE},
5418 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
5419 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, TRUE},
5420 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
5421 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE},
5422 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
5423 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE},
5424 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
5426 unsigned int i;
5428 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5429 0, 0, 640, 480, 0, 0, 0, 0);
5431 if (!(device = create_device(window, DDSCL_NORMAL)))
5433 skip("Failed to create a 3D device, skipping test.\n");
5434 DestroyWindow(window);
5435 return;
5437 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
5438 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5439 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
5440 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5441 hr = IDirect3DDevice3_GetRenderTarget(device, &target);
5442 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
5444 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
5446 BOOL discarded;
5448 memset(&ddsd, 0, sizeof(ddsd));
5449 ddsd.dwSize = sizeof(ddsd);
5450 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5451 ddsd.ddsCaps.dwCaps = tests[i].caps;
5452 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
5453 ddsd.dwWidth = 64;
5454 ddsd.dwHeight = 64;
5455 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5456 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x, case %u.\n", hr, i);
5458 memset(&ddsd, 0, sizeof(ddsd));
5459 ddsd.dwSize = sizeof(ddsd);
5460 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, 0, NULL);
5461 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5462 addr = ddsd.lpSurface;
5463 hr = IDirectDrawSurface4_Unlock(surface, NULL);
5464 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5466 memset(&ddsd, 0, sizeof(ddsd));
5467 ddsd.dwSize = sizeof(ddsd);
5468 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
5469 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5470 discarded = ddsd.lpSurface != addr;
5471 hr = IDirectDrawSurface4_Unlock(surface, NULL);
5472 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5474 hr = IDirectDrawSurface4_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
5475 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
5477 memset(&ddsd, 0, sizeof(ddsd));
5478 ddsd.dwSize = sizeof(ddsd);
5479 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
5480 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5481 discarded |= ddsd.lpSurface != addr;
5482 hr = IDirectDrawSurface4_Unlock(surface, NULL);
5483 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5485 IDirectDrawSurface4_Release(surface);
5487 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
5488 * AMD r500, evergreen). Windows XP, at least on AMD r200, does not. */
5489 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
5492 IDirectDrawSurface4_Release(target);
5493 IDirectDraw4_Release(ddraw);
5494 IDirect3D3_Release(d3d);
5495 IDirect3DDevice3_Release(device);
5496 DestroyWindow(window);
5499 static void test_flip(void)
5501 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
5502 IDirectDrawSurface4 *primary, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
5503 DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}};
5504 DDSURFACEDESC2 surface_desc;
5505 BOOL sysmem_primary;
5506 IDirectDraw4 *ddraw;
5507 D3DCOLOR color;
5508 ULONG refcount;
5509 HWND window;
5510 DDBLTFX fx;
5511 HRESULT hr;
5513 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5514 0, 0, 640, 480, 0, 0, 0, 0);
5515 ddraw = create_ddraw();
5516 ok(!!ddraw, "Failed to create a ddraw object.\n");
5518 hr = set_display_mode(ddraw, 640, 480);
5519 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
5520 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5521 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5523 memset(&surface_desc, 0, sizeof(surface_desc));
5524 surface_desc.dwSize = sizeof(surface_desc);
5525 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
5526 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
5527 U5(surface_desc).dwBackBufferCount = 3;
5528 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
5529 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5531 memset(&surface_desc, 0, sizeof(surface_desc));
5532 surface_desc.dwSize = sizeof(surface_desc);
5533 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &surface_desc);
5534 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5535 ok((surface_desc.ddsCaps.dwCaps & ~placement)
5536 == (DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX),
5537 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
5538 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
5540 hr = IDirectDrawSurface4_GetAttachedSurface(primary, &caps, &backbuffer1);
5541 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
5542 memset(&surface_desc, 0, sizeof(surface_desc));
5543 surface_desc.dwSize = sizeof(surface_desc);
5544 hr = IDirectDrawSurface4_GetSurfaceDesc(backbuffer1, &surface_desc);
5545 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5546 ok(!U5(surface_desc).dwBackBufferCount, "Got unexpected back buffer count %u.\n", U5(surface_desc).dwBackBufferCount);
5547 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_BACKBUFFER),
5548 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
5550 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
5551 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
5552 memset(&surface_desc, 0, sizeof(surface_desc));
5553 surface_desc.dwSize = sizeof(surface_desc);
5554 hr = IDirectDrawSurface4_GetSurfaceDesc(backbuffer2, &surface_desc);
5555 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5556 ok(!U5(surface_desc).dwBackBufferCount, "Got unexpected back buffer count %u.\n", U5(surface_desc).dwBackBufferCount);
5557 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
5558 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
5560 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
5561 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
5562 memset(&surface_desc, 0, sizeof(surface_desc));
5563 surface_desc.dwSize = sizeof(surface_desc);
5564 hr = IDirectDrawSurface4_GetSurfaceDesc(backbuffer3, &surface_desc);
5565 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5566 ok(!U5(surface_desc).dwBackBufferCount, "Got unexpected back buffer count %u.\n", U5(surface_desc).dwBackBufferCount);
5567 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
5568 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
5570 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer3, &caps, &surface);
5571 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
5572 ok(surface == primary, "Got unexpected surface %p, expected %p.\n", surface, primary);
5573 IDirectDrawSurface4_Release(surface);
5575 memset(&surface_desc, 0, sizeof(surface_desc));
5576 surface_desc.dwSize = sizeof(surface_desc);
5577 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5578 surface_desc.ddsCaps.dwCaps = 0;
5579 surface_desc.dwWidth = 640;
5580 surface_desc.dwHeight = 480;
5581 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5582 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5583 hr = IDirectDrawSurface4_Flip(primary, surface, DDFLIP_WAIT);
5584 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
5585 IDirectDrawSurface4_Release(surface);
5587 hr = IDirectDrawSurface4_Flip(primary, primary, DDFLIP_WAIT);
5588 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
5589 hr = IDirectDrawSurface4_Flip(backbuffer1, NULL, DDFLIP_WAIT);
5590 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
5591 hr = IDirectDrawSurface4_Flip(backbuffer2, NULL, DDFLIP_WAIT);
5592 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
5593 hr = IDirectDrawSurface4_Flip(backbuffer3, NULL, DDFLIP_WAIT);
5594 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
5596 memset(&fx, 0, sizeof(fx));
5597 fx.dwSize = sizeof(fx);
5598 U5(fx).dwFillColor = 0xffff0000;
5599 hr = IDirectDrawSurface4_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5600 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5601 U5(fx).dwFillColor = 0xff00ff00;
5602 hr = IDirectDrawSurface4_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5603 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5604 U5(fx).dwFillColor = 0xff0000ff;
5605 hr = IDirectDrawSurface4_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5606 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5608 hr = IDirectDrawSurface4_Flip(primary, NULL, DDFLIP_WAIT);
5609 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
5610 color = get_surface_color(backbuffer1, 320, 240);
5611 /* The testbot seems to just copy the contents of one surface to all the
5612 * others, instead of properly flipping. */
5613 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
5614 "Got unexpected color 0x%08x.\n", color);
5615 color = get_surface_color(backbuffer2, 320, 240);
5616 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
5617 U5(fx).dwFillColor = 0xffff0000;
5618 hr = IDirectDrawSurface4_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5619 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5621 hr = IDirectDrawSurface4_Flip(primary, NULL, DDFLIP_WAIT);
5622 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
5623 color = get_surface_color(backbuffer1, 320, 240);
5624 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
5625 "Got unexpected color 0x%08x.\n", color);
5626 color = get_surface_color(backbuffer2, 320, 240);
5627 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
5628 U5(fx).dwFillColor = 0xff00ff00;
5629 hr = IDirectDrawSurface4_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5630 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5632 hr = IDirectDrawSurface4_Flip(primary, NULL, DDFLIP_WAIT);
5633 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
5634 color = get_surface_color(backbuffer1, 320, 240);
5635 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
5636 "Got unexpected color 0x%08x.\n", color);
5637 color = get_surface_color(backbuffer2, 320, 240);
5638 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
5639 U5(fx).dwFillColor = 0xff0000ff;
5640 hr = IDirectDrawSurface4_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5641 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5643 hr = IDirectDrawSurface4_Flip(primary, backbuffer1, DDFLIP_WAIT);
5644 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
5645 color = get_surface_color(backbuffer2, 320, 240);
5646 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
5647 "Got unexpected color 0x%08x.\n", color);
5648 color = get_surface_color(backbuffer3, 320, 240);
5649 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
5650 U5(fx).dwFillColor = 0xffff0000;
5651 hr = IDirectDrawSurface4_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5652 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5654 hr = IDirectDrawSurface4_Flip(primary, backbuffer2, DDFLIP_WAIT);
5655 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
5656 color = get_surface_color(backbuffer1, 320, 240);
5657 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
5658 color = get_surface_color(backbuffer3, 320, 240);
5659 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
5660 "Got unexpected color 0x%08x.\n", color);
5661 U5(fx).dwFillColor = 0xff00ff00;
5662 hr = IDirectDrawSurface4_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5663 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5665 hr = IDirectDrawSurface4_Flip(primary, backbuffer3, DDFLIP_WAIT);
5666 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
5667 color = get_surface_color(backbuffer1, 320, 240);
5668 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
5669 "Got unexpected color 0x%08x.\n", color);
5670 color = get_surface_color(backbuffer2, 320, 240);
5671 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
5673 IDirectDrawSurface4_Release(backbuffer3);
5674 IDirectDrawSurface4_Release(backbuffer2);
5675 IDirectDrawSurface4_Release(backbuffer1);
5676 IDirectDrawSurface4_Release(primary);
5677 refcount = IDirectDraw4_Release(ddraw);
5678 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5679 DestroyWindow(window);
5682 static void reset_ddsd(DDSURFACEDESC2 *ddsd)
5684 memset(ddsd, 0, sizeof(*ddsd));
5685 ddsd->dwSize = sizeof(*ddsd);
5688 static void test_set_surface_desc(void)
5690 IDirectDraw4 *ddraw;
5691 HWND window;
5692 HRESULT hr;
5693 DDSURFACEDESC2 ddsd;
5694 IDirectDrawSurface4 *surface;
5695 BYTE data[16*16*4];
5696 ULONG ref;
5697 unsigned int i;
5698 static const struct
5700 DWORD caps, caps2;
5701 BOOL supported;
5702 const char *name;
5704 invalid_caps_tests[] =
5706 {DDSCAPS_VIDEOMEMORY, 0, FALSE, "videomemory plain"},
5707 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, TRUE, "systemmemory texture"},
5708 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE, "managed texture"},
5709 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE, "managed texture"},
5710 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, 0, FALSE, "systemmemory primary"},
5713 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5714 0, 0, 640, 480, 0, 0, 0, 0);
5715 ddraw = create_ddraw();
5716 ok(!!ddraw, "Failed to create a ddraw object.\n");
5717 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5718 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5720 reset_ddsd(&ddsd);
5721 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
5722 ddsd.dwWidth = 8;
5723 ddsd.dwHeight = 8;
5724 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5725 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
5726 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
5727 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5728 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5729 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
5730 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
5732 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5733 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5735 reset_ddsd(&ddsd);
5736 ddsd.dwFlags = DDSD_LPSURFACE;
5737 ddsd.lpSurface = data;
5738 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5739 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5741 /* Redundantly setting the same lpSurface is not an error. */
5742 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5743 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5744 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5745 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5746 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
5747 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
5749 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, 0, NULL);
5750 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5751 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
5752 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
5753 hr = IDirectDrawSurface4_Unlock(surface, NULL);
5754 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5756 reset_ddsd(&ddsd);
5757 ddsd.dwFlags = DDSD_LPSURFACE;
5758 ddsd.lpSurface = data;
5759 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 1);
5760 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
5762 ddsd.lpSurface = NULL;
5763 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5764 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
5766 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, NULL, 0);
5767 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
5769 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5770 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5771 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
5772 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
5773 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
5775 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
5776 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5777 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
5779 ddsd.dwFlags = DDSD_CAPS;
5780 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5781 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
5783 /* dwCaps = 0 is allowed, but ignored. Caps2 can be anything and is ignored too. */
5784 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
5785 ddsd.lpSurface = data;
5786 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5787 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
5788 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
5789 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5790 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
5791 ddsd.ddsCaps.dwCaps = 0;
5792 ddsd.ddsCaps.dwCaps2 = 0xdeadbeef;
5793 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5794 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5796 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5797 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5798 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
5799 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
5800 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
5802 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
5803 reset_ddsd(&ddsd);
5804 ddsd.dwFlags = DDSD_HEIGHT;
5805 ddsd.dwHeight = 16;
5806 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5807 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
5809 ddsd.lpSurface = data;
5810 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
5811 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5812 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5814 ddsd.dwHeight = 0;
5815 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5816 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
5818 reset_ddsd(&ddsd);
5819 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5820 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
5821 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
5822 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
5824 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0 */
5825 reset_ddsd(&ddsd);
5826 ddsd.dwFlags = DDSD_PITCH;
5827 U1(ddsd).lPitch = 8 * 4;
5828 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5829 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
5831 ddsd.dwFlags = DDSD_WIDTH;
5832 ddsd.dwWidth = 16;
5833 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5834 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
5836 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
5837 ddsd.lpSurface = data;
5838 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5839 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
5841 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
5842 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5843 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
5845 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5846 U1(ddsd).lPitch = 16 * 4;
5847 ddsd.dwWidth = 16;
5848 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5849 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5851 reset_ddsd(&ddsd);
5852 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5853 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5854 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
5855 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
5856 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
5858 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
5860 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
5861 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5862 U1(ddsd).lPitch = 4 * 4;
5863 ddsd.lpSurface = data;
5864 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5865 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
5867 U1(ddsd).lPitch = 4;
5868 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5869 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
5871 U1(ddsd).lPitch = 16 * 4 + 1;
5872 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5873 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
5875 U1(ddsd).lPitch = 16 * 4 + 3;
5876 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5877 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
5879 U1(ddsd).lPitch = -4;
5880 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5881 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
5883 U1(ddsd).lPitch = 16 * 4;
5884 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5885 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5887 reset_ddsd(&ddsd);
5888 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5889 U1(ddsd).lPitch = 0;
5890 ddsd.dwWidth = 16;
5891 ddsd.lpSurface = data;
5892 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5893 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
5895 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5896 U1(ddsd).lPitch = 16 * 4;
5897 ddsd.dwWidth = 0;
5898 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5899 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
5901 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
5902 ddsd.dwFlags = DDSD_PIXELFORMAT;
5903 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5904 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
5905 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
5906 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5907 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5908 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
5909 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5910 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
5912 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
5913 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5914 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5916 /* Can't set color keys. */
5917 reset_ddsd(&ddsd);
5918 ddsd.dwFlags = DDSD_CKSRCBLT;
5919 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
5920 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
5921 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5922 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
5924 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
5925 ddsd.lpSurface = data;
5926 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5927 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
5929 IDirectDrawSurface4_Release(surface);
5931 /* SetSurfaceDesc needs systemmemory surfaces.
5933 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing DDSD_LINEARSIZE is moot. */
5934 for (i = 0; i < sizeof(invalid_caps_tests) / sizeof(*invalid_caps_tests); i++)
5936 reset_ddsd(&ddsd);
5937 ddsd.dwFlags = DDSD_CAPS;
5938 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
5939 ddsd.ddsCaps.dwCaps2 = invalid_caps_tests[i].caps2;
5940 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
5942 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5943 ddsd.dwWidth = 8;
5944 ddsd.dwHeight = 8;
5945 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5946 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
5947 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
5948 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5949 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5950 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
5953 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5954 ok(SUCCEEDED(hr) || hr == DDERR_NODIRECTDRAWHW, "Failed to create surface, hr %#x.\n", hr);
5955 if (FAILED(hr))
5957 skip("Cannot create a %s surface, skipping vidmem SetSurfaceDesc test.\n",
5958 invalid_caps_tests[i].name);
5959 goto done;
5962 reset_ddsd(&ddsd);
5963 ddsd.dwFlags = DDSD_LPSURFACE;
5964 ddsd.lpSurface = data;
5965 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5966 if (invalid_caps_tests[i].supported)
5968 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5970 else
5972 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
5973 invalid_caps_tests[i].name, hr);
5975 /* Check priority of error conditions. */
5976 ddsd.dwFlags = DDSD_WIDTH;
5977 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5978 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
5979 invalid_caps_tests[i].name, hr);
5982 IDirectDrawSurface4_Release(surface);
5985 done:
5986 ref = IDirectDraw4_Release(ddraw);
5987 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
5988 DestroyWindow(window);
5991 static void test_user_memory_getdc(void)
5993 IDirectDraw4 *ddraw;
5994 HWND window;
5995 HRESULT hr;
5996 DDSURFACEDESC2 ddsd;
5997 IDirectDrawSurface4 *surface;
5998 DWORD data[16][16];
5999 ULONG ref;
6000 HDC dc;
6001 unsigned int x, y;
6003 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6004 0, 0, 640, 480, 0, 0, 0, 0);
6005 ddraw = create_ddraw();
6006 ok(!!ddraw, "Failed to create a ddraw object.\n");
6008 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6009 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6011 reset_ddsd(&ddsd);
6012 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6013 ddsd.dwWidth = 16;
6014 ddsd.dwHeight = 16;
6015 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6016 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6017 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6018 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6019 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6020 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6021 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6022 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6023 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6025 memset(data, 0xaa, sizeof(data));
6026 reset_ddsd(&ddsd);
6027 ddsd.dwFlags = DDSD_LPSURFACE;
6028 ddsd.lpSurface = data;
6029 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6030 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6032 hr = IDirectDrawSurface4_GetDC(surface, &dc);
6033 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6034 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
6035 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
6036 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
6037 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6039 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
6040 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
6042 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
6043 ddsd.lpSurface = data;
6044 ddsd.dwWidth = 4;
6045 ddsd.dwHeight = 8;
6046 U1(ddsd).lPitch = sizeof(*data);
6047 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6048 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6050 memset(data, 0xaa, sizeof(data));
6051 hr = IDirectDrawSurface4_GetDC(surface, &dc);
6052 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6053 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
6054 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
6055 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
6056 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6058 for (y = 0; y < 4; y++)
6060 for (x = 0; x < 4; x++)
6062 if ((x == 1 || x == 2) && (y == 1 || y == 2))
6063 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
6064 x, y, data[y][x]);
6065 else
6066 ok(data[y][x] == 0x00000000, "Expected color 0x00000000 on position %ux%u, got %#x.\n",
6067 x, y, data[y][x]);
6070 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
6071 data[0][5]);
6072 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
6073 data[7][3]);
6074 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
6075 data[7][4]);
6076 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
6077 data[8][0]);
6079 IDirectDrawSurface4_Release(surface);
6080 ref = IDirectDraw4_Release(ddraw);
6081 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6082 DestroyWindow(window);
6085 static void test_sysmem_overlay(void)
6087 IDirectDraw4 *ddraw;
6088 HWND window;
6089 HRESULT hr;
6090 DDSURFACEDESC2 ddsd;
6091 IDirectDrawSurface4 *surface;
6092 ULONG ref;
6094 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6095 0, 0, 640, 480, 0, 0, 0, 0);
6096 ddraw = create_ddraw();
6097 ok(!!ddraw, "Failed to create a ddraw object.\n");
6099 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6100 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6102 reset_ddsd(&ddsd);
6103 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
6104 ddsd.dwWidth = 16;
6105 ddsd.dwHeight = 16;
6106 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
6107 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6108 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6109 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6110 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6111 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6112 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6113 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6114 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
6116 ref = IDirectDraw4_Release(ddraw);
6117 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6118 DestroyWindow(window);
6121 static void test_primary_palette(void)
6123 DDSCAPS2 surface_caps = {DDSCAPS_FLIP, 0, 0, {0}};
6124 IDirectDrawSurface4 *primary, *backbuffer;
6125 PALETTEENTRY palette_entries[256];
6126 IDirectDrawPalette *palette, *tmp;
6127 DDSURFACEDESC2 surface_desc;
6128 IDirectDraw4 *ddraw;
6129 DWORD palette_caps;
6130 ULONG refcount;
6131 HWND window;
6132 HRESULT hr;
6134 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6135 0, 0, 640, 480, 0, 0, 0, 0);
6136 ddraw = create_ddraw();
6137 ok(!!ddraw, "Failed to create a ddraw object.\n");
6138 if (FAILED(IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
6140 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
6141 IDirectDraw4_Release(ddraw);
6142 DestroyWindow(window);
6143 return;
6145 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6146 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6148 memset(&surface_desc, 0, sizeof(surface_desc));
6149 surface_desc.dwSize = sizeof(surface_desc);
6150 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
6151 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
6152 U5(surface_desc).dwBackBufferCount = 1;
6153 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
6154 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6155 hr = IDirectDrawSurface4_GetAttachedSurface(primary, &surface_caps, &backbuffer);
6156 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
6158 memset(palette_entries, 0, sizeof(palette_entries));
6159 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
6160 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6161 refcount = get_refcount((IUnknown *)palette);
6162 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6164 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6165 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6166 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
6168 hr = IDirectDrawSurface4_SetPalette(primary, palette);
6169 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6171 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
6172 * and is generally somewhat broken with respect to 8 bpp / palette
6173 * handling. */
6174 if (SUCCEEDED(IDirectDrawSurface4_GetPalette(backbuffer, &tmp)))
6176 win_skip("Broken palette handling detected, skipping tests.\n");
6177 IDirectDrawPalette_Release(tmp);
6178 IDirectDrawPalette_Release(palette);
6179 /* The Windows 8 testbot keeps extra references to the primary and
6180 * backbuffer while in 8 bpp mode. */
6181 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
6182 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
6183 goto done;
6186 refcount = get_refcount((IUnknown *)palette);
6187 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6189 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6190 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6191 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
6192 "Got unexpected palette caps %#x.\n", palette_caps);
6194 hr = IDirectDrawSurface4_SetPalette(primary, NULL);
6195 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6196 refcount = get_refcount((IUnknown *)palette);
6197 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6199 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6200 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6201 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
6203 hr = IDirectDrawSurface4_SetPalette(primary, palette);
6204 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6205 refcount = get_refcount((IUnknown *)palette);
6206 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6208 hr = IDirectDrawSurface4_GetPalette(primary, &tmp);
6209 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
6210 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
6211 IDirectDrawPalette_Release(tmp);
6212 hr = IDirectDrawSurface4_GetPalette(backbuffer, &tmp);
6213 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6215 refcount = IDirectDrawPalette_Release(palette);
6216 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6217 refcount = IDirectDrawPalette_Release(palette);
6218 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6220 /* Note that this only seems to work when the palette is attached to the
6221 * primary surface. When attached to a regular surface, attempting to get
6222 * the palette here will cause an access violation. */
6223 hr = IDirectDrawSurface4_GetPalette(primary, &tmp);
6224 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6226 done:
6227 refcount = IDirectDrawSurface4_Release(backbuffer);
6228 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6229 refcount = IDirectDrawSurface4_Release(primary);
6230 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6231 refcount = IDirectDraw4_Release(ddraw);
6232 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6233 DestroyWindow(window);
6236 static HRESULT WINAPI surface_counter(IDirectDrawSurface4 *surface, DDSURFACEDESC2 *desc, void *context)
6238 UINT *surface_count = context;
6240 ++(*surface_count);
6241 IDirectDrawSurface_Release(surface);
6243 return DDENUMRET_OK;
6246 static void test_surface_attachment(void)
6248 IDirectDrawSurface4 *surface1, *surface2, *surface3, *surface4;
6249 IDirectDrawSurface *surface1v1, *surface2v1;
6250 DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, {0}};
6251 DDSURFACEDESC2 surface_desc;
6252 IDirectDraw4 *ddraw;
6253 UINT surface_count;
6254 ULONG refcount;
6255 HWND window;
6256 HRESULT hr;
6258 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6259 0, 0, 640, 480, 0, 0, 0, 0);
6260 ddraw = create_ddraw();
6261 ok(!!ddraw, "Failed to create a ddraw object.\n");
6262 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6263 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6265 memset(&surface_desc, 0, sizeof(surface_desc));
6266 surface_desc.dwSize = sizeof(surface_desc);
6267 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
6268 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
6269 U2(surface_desc).dwMipMapCount = 3;
6270 surface_desc.dwWidth = 128;
6271 surface_desc.dwHeight = 128;
6272 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6273 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6275 hr = IDirectDrawSurface4_GetAttachedSurface(surface1, &caps, &surface2);
6276 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
6277 hr = IDirectDrawSurface4_GetAttachedSurface(surface2, &caps, &surface3);
6278 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
6279 hr = IDirectDrawSurface4_GetAttachedSurface(surface3, &caps, &surface4);
6280 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
6282 surface_count = 0;
6283 IDirectDrawSurface4_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
6284 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
6285 surface_count = 0;
6286 IDirectDrawSurface4_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
6287 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
6288 surface_count = 0;
6289 IDirectDrawSurface4_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
6290 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
6292 memset(&surface_desc, 0, sizeof(surface_desc));
6293 surface_desc.dwSize = sizeof(surface_desc);
6294 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6295 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6296 surface_desc.dwWidth = 16;
6297 surface_desc.dwHeight = 16;
6298 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6299 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6301 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface4);
6302 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6303 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface1);
6304 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6305 hr = IDirectDrawSurface4_AddAttachedSurface(surface3, surface4);
6306 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6307 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface3);
6308 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6309 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface4);
6310 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6311 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface2);
6312 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6314 IDirectDrawSurface4_Release(surface4);
6316 memset(&surface_desc, 0, sizeof(surface_desc));
6317 surface_desc.dwSize = sizeof(surface_desc);
6318 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6319 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6320 surface_desc.dwWidth = 16;
6321 surface_desc.dwHeight = 16;
6322 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6323 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6325 if (SUCCEEDED(hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface4)))
6327 skip("Running on refrast, skipping some tests.\n");
6328 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface4);
6329 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6331 else
6333 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6334 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface1);
6335 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6336 hr = IDirectDrawSurface4_AddAttachedSurface(surface3, surface4);
6337 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6338 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface3);
6339 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6340 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface4);
6341 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6342 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface2);
6343 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6346 IDirectDrawSurface4_Release(surface4);
6347 IDirectDrawSurface4_Release(surface3);
6348 IDirectDrawSurface4_Release(surface2);
6349 IDirectDrawSurface4_Release(surface1);
6351 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6352 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6354 /* Try a single primary and two offscreen plain surfaces. */
6355 memset(&surface_desc, 0, sizeof(surface_desc));
6356 surface_desc.dwSize = sizeof(surface_desc);
6357 surface_desc.dwFlags = DDSD_CAPS;
6358 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
6359 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6360 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6362 memset(&surface_desc, 0, sizeof(surface_desc));
6363 surface_desc.dwSize = sizeof(surface_desc);
6364 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6365 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6366 surface_desc.dwWidth = registry_mode.dmPelsWidth;
6367 surface_desc.dwHeight = registry_mode.dmPelsHeight;
6368 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
6369 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6371 memset(&surface_desc, 0, sizeof(surface_desc));
6372 surface_desc.dwSize = sizeof(surface_desc);
6373 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6374 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6375 surface_desc.dwWidth = registry_mode.dmPelsWidth;
6376 surface_desc.dwHeight = registry_mode.dmPelsHeight;
6377 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
6378 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6380 /* This one has a different size. */
6381 memset(&surface_desc, 0, sizeof(surface_desc));
6382 surface_desc.dwSize = sizeof(surface_desc);
6383 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6384 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6385 surface_desc.dwWidth = 128;
6386 surface_desc.dwHeight = 128;
6387 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6388 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6390 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface2);
6391 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6392 /* Try the reverse without detaching first. */
6393 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface1);
6394 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
6395 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
6396 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6398 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface1);
6399 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6400 /* Try to detach reversed. */
6401 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
6402 ok(hr == DDERR_CANNOTDETACHSURFACE, "Got unexpected hr %#x.\n", hr);
6403 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface2, 0, surface1);
6404 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6406 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface3);
6407 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6408 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface2, 0, surface3);
6409 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6411 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface4);
6412 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6413 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface1);
6414 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6416 IDirectDrawSurface4_Release(surface4);
6417 IDirectDrawSurface4_Release(surface3);
6418 IDirectDrawSurface4_Release(surface2);
6419 IDirectDrawSurface4_Release(surface1);
6421 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
6422 memset(&surface_desc, 0, sizeof(surface_desc));
6423 surface_desc.dwSize = sizeof(surface_desc);
6424 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6425 surface_desc.dwWidth = 64;
6426 surface_desc.dwHeight = 64;
6427 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
6428 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
6429 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
6430 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
6431 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
6432 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
6433 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
6434 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6435 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6436 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
6437 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6439 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
6440 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
6441 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
6442 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
6443 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
6444 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6446 hr = IDirectDrawSurface4_QueryInterface(surface1, &IID_IDirectDrawSurface, (void **)&surface1v1);
6447 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
6448 hr = IDirectDrawSurface4_QueryInterface(surface2, &IID_IDirectDrawSurface, (void **)&surface2v1);
6449 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
6451 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface2);
6452 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6453 refcount = get_refcount((IUnknown *)surface2);
6454 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6455 refcount = get_refcount((IUnknown *)surface2v1);
6456 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6457 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface2);
6458 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
6459 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
6460 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6461 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
6462 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
6464 /* Attaching while already attached to other surface. */
6465 hr = IDirectDrawSurface4_AddAttachedSurface(surface3, surface2);
6466 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6467 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface3, 0, surface2);
6468 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6469 IDirectDrawSurface4_Release(surface3);
6471 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
6472 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6473 refcount = get_refcount((IUnknown *)surface2);
6474 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6475 refcount = get_refcount((IUnknown *)surface2v1);
6476 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6478 /* DeleteAttachedSurface() when attaching via IDirectDrawSurface. */
6479 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
6480 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6481 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
6482 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
6483 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
6484 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6485 refcount = IDirectDrawSurface4_Release(surface2);
6486 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6487 refcount = IDirectDrawSurface4_Release(surface1);
6488 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6490 /* Automatic detachment on release. */
6491 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
6492 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6493 refcount = get_refcount((IUnknown *)surface2v1);
6494 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6495 refcount = IDirectDrawSurface_Release(surface1v1);
6496 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6497 refcount = IDirectDrawSurface_Release(surface2v1);
6498 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6499 refcount = IDirectDraw4_Release(ddraw);
6500 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6501 DestroyWindow(window);
6504 static void test_private_data(void)
6506 IDirectDraw4 *ddraw;
6507 IDirectDrawSurface4 *surface, *surface2;
6508 DDSURFACEDESC2 surface_desc;
6509 ULONG refcount, refcount2, refcount3;
6510 IUnknown *ptr;
6511 DWORD size = sizeof(ptr);
6512 HRESULT hr;
6513 HWND window;
6514 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
6515 DWORD data[] = {1, 2, 3, 4};
6516 DDCAPS hal_caps;
6517 static const GUID ddraw_private_data_test_guid =
6519 0xfdb37466,
6520 0x428f,
6521 0x4edf,
6522 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
6524 static const GUID ddraw_private_data_test_guid2 =
6526 0x2e5afac2,
6527 0x87b5,
6528 0x4c10,
6529 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
6532 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6533 0, 0, 640, 480, 0, 0, 0, 0);
6534 ddraw = create_ddraw();
6535 ok(!!ddraw, "Failed to create a ddraw object.\n");
6536 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6537 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6539 reset_ddsd(&surface_desc);
6540 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
6541 surface_desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
6542 surface_desc.dwHeight = 4;
6543 surface_desc.dwWidth = 4;
6544 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6545 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6547 /* NULL pointers are not valid, but don't cause a crash. */
6548 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL,
6549 sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
6550 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6551 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 0, 0);
6552 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6553 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 1, 0);
6554 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6556 /* DDSPD_IUNKNOWNPOINTER needs sizeof(IUnknown *) bytes of data. */
6557 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
6558 0, DDSPD_IUNKNOWNPOINTER);
6559 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6560 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
6561 5, DDSPD_IUNKNOWNPOINTER);
6562 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6563 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
6564 sizeof(ddraw) * 2, DDSPD_IUNKNOWNPOINTER);
6565 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6567 /* Note that with a size != 0 and size != sizeof(IUnknown *) and
6568 * DDSPD_IUNKNOWNPOINTER set SetPrivateData in ddraw4 and ddraw7
6569 * erases the old content and returns an error. This behavior has
6570 * been fixed in d3d8 and d3d9. Unless an application is found
6571 * that depends on this we don't care about this behavior. */
6572 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
6573 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
6574 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
6575 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
6576 0, DDSPD_IUNKNOWNPOINTER);
6577 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6578 size = sizeof(ptr);
6579 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
6580 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
6581 hr = IDirectDrawSurface4_FreePrivateData(surface, &ddraw_private_data_test_guid);
6582 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
6584 refcount = get_refcount((IUnknown *)ddraw);
6585 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
6586 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
6587 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
6588 refcount2 = get_refcount((IUnknown *)ddraw);
6589 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
6591 hr = IDirectDrawSurface4_FreePrivateData(surface, &ddraw_private_data_test_guid);
6592 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
6593 refcount2 = get_refcount((IUnknown *)ddraw);
6594 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
6596 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
6597 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
6598 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
6599 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, surface,
6600 sizeof(surface), DDSPD_IUNKNOWNPOINTER);
6601 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
6602 refcount2 = get_refcount((IUnknown *)ddraw);
6603 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
6605 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
6606 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
6607 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
6608 size = 2 * sizeof(ptr);
6609 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
6610 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
6611 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
6612 refcount2 = get_refcount(ptr);
6613 /* Object is NOT addref'ed by the getter. */
6614 ok(ptr == (IUnknown *)ddraw, "Returned interface pointer is %p, expected %p.\n", ptr, ddraw);
6615 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
6617 ptr = (IUnknown *)0xdeadbeef;
6618 size = 1;
6619 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
6620 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
6621 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
6622 size = 2 * sizeof(ptr);
6623 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
6624 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6625 ok(size == 2 * sizeof(ptr), "Got unexpected size %u.\n", size);
6626 size = 1;
6627 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
6628 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
6629 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
6630 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
6631 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid2, NULL, NULL);
6632 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
6633 size = 0xdeadbabe;
6634 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid2, &ptr, &size);
6635 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
6636 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
6637 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
6638 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, NULL);
6639 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6641 refcount3 = IDirectDrawSurface4_Release(surface);
6642 ok(!refcount3, "Got unexpected refcount %u.\n", refcount3);
6644 /* Destroying the surface frees the reference held on the private data. It also frees
6645 * the reference the surface is holding on its creating object. */
6646 refcount2 = get_refcount((IUnknown *)ddraw);
6647 ok(refcount2 == refcount - 1, "Got unexpected refcount %u.\n", refcount2);
6649 memset(&hal_caps, 0, sizeof(hal_caps));
6650 hal_caps.dwSize = sizeof(hal_caps);
6651 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
6652 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6653 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) == (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
6655 reset_ddsd(&surface_desc);
6656 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT;
6657 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
6658 surface_desc.dwHeight = 4;
6659 surface_desc.dwWidth = 4;
6660 U2(surface_desc).dwMipMapCount = 2;
6661 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6662 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6663 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &surface2);
6664 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
6666 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, data, sizeof(data), 0);
6667 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
6668 hr = IDirectDrawSurface4_GetPrivateData(surface2, &ddraw_private_data_test_guid, NULL, NULL);
6669 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
6671 IDirectDrawSurface4_Release(surface2);
6672 IDirectDrawSurface4_Release(surface);
6674 else
6675 skip("Mipmapped textures not supported, skipping mipmap private data test.\n");
6677 refcount = IDirectDraw4_Release(ddraw);
6678 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6679 DestroyWindow(window);
6682 static void test_pixel_format(void)
6684 HWND window, window2 = NULL;
6685 HDC hdc, hdc2 = NULL;
6686 HMODULE gl = NULL;
6687 int format, test_format;
6688 PIXELFORMATDESCRIPTOR pfd;
6689 IDirectDraw4 *ddraw = NULL;
6690 IDirectDrawClipper *clipper = NULL;
6691 DDSURFACEDESC2 ddsd;
6692 IDirectDrawSurface4 *primary = NULL;
6693 DDBLTFX fx;
6694 HRESULT hr;
6696 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
6697 100, 100, 160, 160, NULL, NULL, NULL, NULL);
6698 if (!window)
6700 skip("Failed to create window\n");
6701 return;
6704 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
6705 100, 100, 160, 160, NULL, NULL, NULL, NULL);
6707 hdc = GetDC(window);
6708 if (!hdc)
6710 skip("Failed to get DC\n");
6711 goto cleanup;
6714 if (window2)
6715 hdc2 = GetDC(window2);
6717 gl = LoadLibraryA("opengl32.dll");
6718 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
6720 format = GetPixelFormat(hdc);
6721 ok(format == 0, "new window has pixel format %d\n", format);
6723 ZeroMemory(&pfd, sizeof(pfd));
6724 pfd.nSize = sizeof(pfd);
6725 pfd.nVersion = 1;
6726 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
6727 pfd.iPixelType = PFD_TYPE_RGBA;
6728 pfd.iLayerType = PFD_MAIN_PLANE;
6729 format = ChoosePixelFormat(hdc, &pfd);
6730 if (format <= 0)
6732 skip("no pixel format available\n");
6733 goto cleanup;
6736 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
6738 skip("failed to set pixel format\n");
6739 goto cleanup;
6742 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
6744 skip("failed to set pixel format on second window\n");
6745 if (hdc2)
6747 ReleaseDC(window2, hdc2);
6748 hdc2 = NULL;
6752 ddraw = create_ddraw();
6753 ok(!!ddraw, "Failed to create a ddraw object.\n");
6755 test_format = GetPixelFormat(hdc);
6756 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6758 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6759 if (FAILED(hr))
6761 skip("Failed to set cooperative level, hr %#x.\n", hr);
6762 goto cleanup;
6765 test_format = GetPixelFormat(hdc);
6766 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6768 if (hdc2)
6770 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL);
6771 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
6772 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
6773 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
6775 test_format = GetPixelFormat(hdc);
6776 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6778 test_format = GetPixelFormat(hdc2);
6779 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
6782 memset(&ddsd, 0, sizeof(ddsd));
6783 ddsd.dwSize = sizeof(ddsd);
6784 ddsd.dwFlags = DDSD_CAPS;
6785 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
6787 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
6788 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
6790 test_format = GetPixelFormat(hdc);
6791 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6793 if (hdc2)
6795 test_format = GetPixelFormat(hdc2);
6796 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
6799 if (clipper)
6801 hr = IDirectDrawSurface4_SetClipper(primary, clipper);
6802 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
6804 test_format = GetPixelFormat(hdc);
6805 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6807 test_format = GetPixelFormat(hdc2);
6808 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
6811 memset(&fx, 0, sizeof(fx));
6812 fx.dwSize = sizeof(fx);
6813 hr = IDirectDrawSurface4_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6814 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
6816 test_format = GetPixelFormat(hdc);
6817 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6819 if (hdc2)
6821 test_format = GetPixelFormat(hdc2);
6822 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
6825 cleanup:
6826 if (primary) IDirectDrawSurface4_Release(primary);
6827 if (clipper) IDirectDrawClipper_Release(clipper);
6828 if (ddraw) IDirectDraw4_Release(ddraw);
6829 if (gl) FreeLibrary(gl);
6830 if (hdc) ReleaseDC(window, hdc);
6831 if (hdc2) ReleaseDC(window2, hdc2);
6832 if (window) DestroyWindow(window);
6833 if (window2) DestroyWindow(window2);
6836 static void test_create_surface_pitch(void)
6838 IDirectDrawSurface4 *surface;
6839 DDSURFACEDESC2 surface_desc;
6840 IDirectDraw4 *ddraw;
6841 unsigned int i;
6842 ULONG refcount;
6843 HWND window;
6844 HRESULT hr;
6845 void *mem;
6847 static const struct
6849 DWORD placement;
6850 DWORD flags_in;
6851 DWORD pitch_in;
6852 HRESULT hr;
6853 DWORD flags_out;
6854 DWORD pitch_out32;
6855 DWORD pitch_out64;
6857 test_data[] =
6859 {DDSCAPS_VIDEOMEMORY, 0, 0, DD_OK,
6860 DDSD_PITCH, 0x100, 0x100},
6861 {DDSCAPS_VIDEOMEMORY, DDSD_PITCH, 0x104, DD_OK,
6862 DDSD_PITCH, 0x100, 0x100},
6863 {DDSCAPS_VIDEOMEMORY, DDSD_PITCH, 0x0f8, DD_OK,
6864 DDSD_PITCH, 0x100, 0x100},
6865 {DDSCAPS_VIDEOMEMORY, DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
6866 0, 0, 0 },
6867 {DDSCAPS_SYSTEMMEMORY, 0, 0, DD_OK,
6868 DDSD_PITCH, 0x100, 0x0fc},
6869 {DDSCAPS_SYSTEMMEMORY, DDSD_PITCH, 0x104, DD_OK,
6870 DDSD_PITCH, 0x100, 0x0fc},
6871 {DDSCAPS_SYSTEMMEMORY, DDSD_PITCH, 0x0f8, DD_OK,
6872 DDSD_PITCH, 0x100, 0x0fc},
6873 {DDSCAPS_SYSTEMMEMORY, DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
6874 DDSD_PITCH, 0x100, 0x0fc},
6875 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
6876 0, 0, 0 },
6877 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
6878 DDSD_PITCH, 0x100, 0x100},
6879 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE | DDSD_PITCH, 0x0fe, DDERR_INVALIDPARAMS,
6880 0, 0, 0 },
6881 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE | DDSD_PITCH, 0x0fc, DD_OK,
6882 DDSD_PITCH, 0x0fc, 0x0fc},
6883 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE | DDSD_PITCH, 0x0f8, DDERR_INVALIDPARAMS,
6884 0, 0, 0 },
6885 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x100, DDERR_INVALIDPARAMS,
6886 0, 0, 0 },
6887 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x3f00, DDERR_INVALIDPARAMS,
6888 0, 0, 0 },
6889 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, 0x100, DD_OK,
6890 DDSD_PITCH, 0x100, 0x100},
6892 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
6894 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6895 0, 0, 640, 480, 0, 0, 0, 0);
6896 ddraw = create_ddraw();
6897 ok(!!ddraw, "Failed to create a ddraw object.\n");
6898 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6899 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6901 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
6903 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
6905 memset(&surface_desc, 0, sizeof(surface_desc));
6906 surface_desc.dwSize = sizeof(surface_desc);
6907 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
6908 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | test_data[i].placement;
6909 surface_desc.dwWidth = 63;
6910 surface_desc.dwHeight = 63;
6911 U1(surface_desc).lPitch = test_data[i].pitch_in;
6912 surface_desc.lpSurface = mem;
6913 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
6914 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
6915 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
6916 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6917 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6918 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6919 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6920 ok(hr == test_data[i].hr || (test_data[i].placement == DDSCAPS_VIDEOMEMORY && hr == DDERR_NODIRECTDRAWHW),
6921 "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
6922 if (FAILED(hr))
6923 continue;
6925 memset(&surface_desc, 0, sizeof(surface_desc));
6926 surface_desc.dwSize = sizeof(surface_desc);
6927 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
6928 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
6929 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
6930 "Test %u: Got unexpected flags %#x, expected %#x.\n",
6931 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
6932 if (sizeof(void *) != sizeof(DWORD) && test_data[i].pitch_out32 != test_data[i].pitch_out64)
6933 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
6934 "Test %u: Got unexpected pitch %u, expected %u.\n",
6935 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
6936 else
6937 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
6938 "Test %u: Got unexpected pitch %u, expected %u.\n",
6939 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
6940 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
6942 IDirectDrawSurface4_Release(surface);
6945 HeapFree(GetProcessHeap(), 0, mem);
6946 refcount = IDirectDraw4_Release(ddraw);
6947 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6948 DestroyWindow(window);
6951 static void test_mipmap_lock(void)
6953 IDirectDrawSurface4 *surface, *surface2;
6954 DDSURFACEDESC2 surface_desc;
6955 IDirectDraw4 *ddraw;
6956 ULONG refcount;
6957 HWND window;
6958 HRESULT hr;
6959 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
6960 DDCAPS hal_caps;
6962 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6963 0, 0, 640, 480, 0, 0, 0, 0);
6964 ddraw = create_ddraw();
6965 ok(!!ddraw, "Failed to create a ddraw object.\n");
6966 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6967 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6969 memset(&hal_caps, 0, sizeof(hal_caps));
6970 hal_caps.dwSize = sizeof(hal_caps);
6971 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
6972 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6973 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
6975 skip("Mipmapped textures not supported, skipping mipmap lock test.\n");
6976 IDirectDraw4_Release(ddraw);
6977 DestroyWindow(window);
6978 return;
6981 memset(&surface_desc, 0, sizeof(surface_desc));
6982 surface_desc.dwSize = sizeof(surface_desc);
6983 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
6984 surface_desc.dwWidth = 4;
6985 surface_desc.dwHeight = 4;
6986 U2(surface_desc).dwMipMapCount = 2;
6987 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP
6988 | DDSCAPS_SYSTEMMEMORY;
6989 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6990 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6991 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &surface2);
6992 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
6994 memset(&surface_desc, 0, sizeof(surface_desc));
6995 surface_desc.dwSize = sizeof(surface_desc);
6996 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, 0, NULL);
6997 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6998 memset(&surface_desc, 0, sizeof(surface_desc));
6999 surface_desc.dwSize = sizeof(surface_desc);
7000 hr = IDirectDrawSurface4_Lock(surface2, NULL, &surface_desc, 0, NULL);
7001 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7002 IDirectDrawSurface4_Unlock(surface2, NULL);
7003 IDirectDrawSurface4_Unlock(surface, NULL);
7005 IDirectDrawSurface4_Release(surface2);
7006 IDirectDrawSurface4_Release(surface);
7007 refcount = IDirectDraw4_Release(ddraw);
7008 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7009 DestroyWindow(window);
7012 static void test_palette_complex(void)
7014 IDirectDrawSurface4 *surface, *mipmap, *tmp;
7015 DDSURFACEDESC2 surface_desc;
7016 IDirectDraw4 *ddraw;
7017 IDirectDrawPalette *palette, *palette2, *palette_mipmap;
7018 ULONG refcount;
7019 HWND window;
7020 HRESULT hr;
7021 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7022 DDCAPS hal_caps;
7023 PALETTEENTRY palette_entries[256];
7024 unsigned int i;
7025 HDC dc;
7026 RGBQUAD rgbquad;
7027 UINT count;
7029 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7030 0, 0, 640, 480, 0, 0, 0, 0);
7031 ddraw = create_ddraw();
7032 ok(!!ddraw, "Failed to create a ddraw object.\n");
7033 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7034 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7036 memset(&hal_caps, 0, sizeof(hal_caps));
7037 hal_caps.dwSize = sizeof(hal_caps);
7038 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
7039 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7040 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
7042 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
7043 IDirectDraw4_Release(ddraw);
7044 DestroyWindow(window);
7045 return;
7048 memset(&surface_desc, 0, sizeof(surface_desc));
7049 surface_desc.dwSize = sizeof(surface_desc);
7050 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7051 surface_desc.dwWidth = 128;
7052 surface_desc.dwHeight = 128;
7053 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7054 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7055 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7056 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
7057 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7058 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7060 memset(palette_entries, 0, sizeof(palette_entries));
7061 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7062 palette_entries, &palette, NULL);
7063 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7065 memset(palette_entries, 0, sizeof(palette_entries));
7066 palette_entries[1].peRed = 0xff;
7067 palette_entries[1].peGreen = 0x80;
7068 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7069 palette_entries, &palette_mipmap, NULL);
7070 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7072 palette2 = (void *)0xdeadbeef;
7073 hr = IDirectDrawSurface4_GetPalette(surface, &palette2);
7074 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
7075 ok(!palette2, "Got unexpected palette %p.\n", palette2);
7076 hr = IDirectDrawSurface4_SetPalette(surface, palette);
7077 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7078 hr = IDirectDrawSurface4_GetPalette(surface, &palette2);
7079 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
7080 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
7081 IDirectDrawPalette_Release(palette2);
7083 mipmap = surface;
7084 IDirectDrawSurface4_AddRef(mipmap);
7085 for (i = 0; i < 7; ++i)
7087 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
7088 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
7089 palette2 = (void *)0xdeadbeef;
7090 hr = IDirectDrawSurface4_GetPalette(tmp, &palette2);
7091 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
7092 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
7094 hr = IDirectDrawSurface4_SetPalette(tmp, palette_mipmap);
7095 ok(SUCCEEDED(hr), "Failed to set palette, i %u, hr %#x.\n", i, hr);
7097 hr = IDirectDrawSurface4_GetPalette(tmp, &palette2);
7098 ok(SUCCEEDED(hr), "Failed to get palette, i %u, hr %#x.\n", i, hr);
7099 ok(palette_mipmap == palette2, "Got unexpected palette %p.\n", palette2);
7100 IDirectDrawPalette_Release(palette2);
7102 hr = IDirectDrawSurface4_GetDC(tmp, &dc);
7103 ok(SUCCEEDED(hr), "Failed to get DC, i %u, hr %#x.\n", i, hr);
7104 count = GetDIBColorTable(dc, 1, 1, &rgbquad);
7105 ok(count == 1, "Expected count 1, got %u.\n", count);
7106 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x.\n", rgbquad.rgbRed);
7107 ok(rgbquad.rgbGreen == 0x80, "Expected rgbGreen = 0x80, got %#x.\n", rgbquad.rgbGreen);
7108 ok(rgbquad.rgbBlue == 0x0, "Expected rgbBlue = 0x0, got %#x.\n", rgbquad.rgbBlue);
7109 hr = IDirectDrawSurface4_ReleaseDC(tmp, dc);
7110 ok(SUCCEEDED(hr), "Failed to release DC, i %u, hr %#x.\n", i, hr);
7112 IDirectDrawSurface4_Release(mipmap);
7113 mipmap = tmp;
7116 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
7117 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7118 IDirectDrawSurface4_Release(mipmap);
7119 refcount = IDirectDrawSurface4_Release(surface);
7120 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7121 refcount = IDirectDrawPalette_Release(palette_mipmap);
7122 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7123 refcount = IDirectDrawPalette_Release(palette);
7124 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7126 refcount = IDirectDraw4_Release(ddraw);
7127 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7128 DestroyWindow(window);
7131 static void test_p8_rgb_blit(void)
7133 IDirectDrawSurface4 *src, *dst;
7134 DDSURFACEDESC2 surface_desc;
7135 IDirectDraw4 *ddraw;
7136 IDirectDrawPalette *palette;
7137 ULONG refcount;
7138 HWND window;
7139 HRESULT hr;
7140 PALETTEENTRY palette_entries[256];
7141 unsigned int x;
7142 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
7143 static const D3DCOLOR expected[] =
7145 0x00101010, 0x00010101, 0x00020202, 0x00030303,
7146 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
7148 D3DCOLOR color;
7150 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7151 0, 0, 640, 480, 0, 0, 0, 0);
7152 ddraw = create_ddraw();
7153 ok(!!ddraw, "Failed to create a ddraw object.\n");
7154 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7155 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7157 memset(palette_entries, 0, sizeof(palette_entries));
7158 palette_entries[1].peGreen = 0xff;
7159 palette_entries[2].peBlue = 0xff;
7160 palette_entries[3].peFlags = 0xff;
7161 palette_entries[4].peRed = 0xff;
7162 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7163 palette_entries, &palette, NULL);
7164 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7166 memset(&surface_desc, 0, sizeof(surface_desc));
7167 surface_desc.dwSize = sizeof(surface_desc);
7168 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7169 surface_desc.dwWidth = 8;
7170 surface_desc.dwHeight = 1;
7171 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7172 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7173 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7174 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
7175 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL);
7176 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7178 memset(&surface_desc, 0, sizeof(surface_desc));
7179 surface_desc.dwSize = sizeof(surface_desc);
7180 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7181 surface_desc.dwWidth = 8;
7182 surface_desc.dwHeight = 1;
7183 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7184 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7185 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
7186 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
7187 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7188 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7189 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7190 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
7191 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL);
7192 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7194 memset(&surface_desc, 0, sizeof(surface_desc));
7195 surface_desc.dwSize = sizeof(surface_desc);
7196 hr = IDirectDrawSurface4_Lock(src, NULL, &surface_desc, 0, NULL);
7197 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
7198 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
7199 hr = IDirectDrawSurface4_Unlock(src, NULL);
7200 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
7202 hr = IDirectDrawSurface4_SetPalette(src, palette);
7203 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7204 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
7205 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
7206 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
7207 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
7208 "Failed to blit, hr %#x.\n", hr);
7210 if (SUCCEEDED(hr))
7212 for (x = 0; x < sizeof(expected) / sizeof(*expected); x++)
7214 color = get_surface_color(dst, x, 0);
7215 todo_wine ok(compare_color(color, expected[x], 0),
7216 "Pixel %u: Got color %#x, expected %#x.\n",
7217 x, color, expected[x]);
7221 IDirectDrawSurface4_Release(src);
7222 IDirectDrawSurface4_Release(dst);
7223 IDirectDrawPalette_Release(palette);
7225 refcount = IDirectDraw4_Release(ddraw);
7226 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7227 DestroyWindow(window);
7230 static void test_material(void)
7232 D3DMATERIALHANDLE mat_handle, tmp;
7233 IDirect3DMaterial3 *material;
7234 IDirect3DViewport3 *viewport;
7235 IDirect3DDevice3 *device;
7236 IDirectDrawSurface4 *rt;
7237 D3DCOLOR color;
7238 ULONG refcount;
7239 unsigned int i;
7240 HWND window;
7241 HRESULT hr;
7242 BOOL valid;
7244 static struct
7246 struct vec3 position;
7247 struct vec3 normal;
7248 D3DCOLOR diffuse;
7250 quad1[] =
7252 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
7253 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
7254 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
7255 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
7257 quad2[] =
7259 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
7260 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
7261 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
7262 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
7264 static const struct
7266 void *data;
7267 BOOL material;
7268 D3DCOLOR expected_color;
7270 test_data[] =
7272 {quad1, TRUE, 0x0000ff00},
7273 {quad2, TRUE, 0x0000ff00},
7274 {quad1, FALSE, 0x00ffffff},
7275 {quad2, FALSE, 0x00ff0000},
7277 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
7279 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7280 0, 0, 640, 480, 0, 0, 0, 0);
7281 if (!(device = create_device(window, DDSCL_NORMAL)))
7283 skip("Failed to create a 3D device, skipping test.\n");
7284 DestroyWindow(window);
7285 return;
7288 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
7289 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
7291 viewport = create_viewport(device, 0, 0, 640, 480);
7292 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
7293 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
7295 material = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
7296 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
7297 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
7299 hr = IDirect3DDevice3_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
7300 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
7301 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
7302 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
7303 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
7304 hr = IDirect3DDevice3_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
7305 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
7306 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
7307 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, 0);
7308 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
7309 hr = IDirect3DDevice3_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
7310 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
7311 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
7313 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
7315 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect,
7316 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
7317 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
7319 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, test_data[i].material ? mat_handle : 0);
7320 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
7322 hr = IDirect3DDevice3_BeginScene(device);
7323 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
7324 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
7325 D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE, test_data[i].data, 4, 0);
7326 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7327 hr = IDirect3DDevice3_EndScene(device);
7328 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7329 color = get_surface_color(rt, 320, 240);
7330 ok(compare_color(color, test_data[i].expected_color, 1),
7331 "Got unexpected color 0x%08x, test %u.\n", color, i);
7334 destroy_material(material);
7335 material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
7336 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
7337 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
7339 hr = IDirect3DViewport3_SetBackground(viewport, mat_handle);
7340 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
7341 hr = IDirect3DViewport3_GetBackground(viewport, &tmp, &valid);
7342 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
7343 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
7344 ok(valid, "Got unexpected valid %#x.\n", valid);
7345 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7346 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
7347 color = get_surface_color(rt, 320, 240);
7348 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
7350 hr = IDirect3DViewport3_SetBackground(viewport, 0);
7351 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7352 hr = IDirect3DViewport3_GetBackground(viewport, &tmp, &valid);
7353 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
7354 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
7355 ok(valid, "Got unexpected valid %#x.\n", valid);
7356 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7357 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
7358 color = get_surface_color(rt, 320, 240);
7359 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
7361 destroy_viewport(device, viewport);
7362 viewport = create_viewport(device, 0, 0, 640, 480);
7364 hr = IDirect3DViewport3_GetBackground(viewport, &tmp, &valid);
7365 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
7366 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
7367 ok(!valid, "Got unexpected valid %#x.\n", valid);
7368 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7369 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
7370 color = get_surface_color(rt, 320, 240);
7371 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x.\n", color);
7373 destroy_viewport(device, viewport);
7374 destroy_material(material);
7375 IDirectDrawSurface4_Release(rt);
7376 refcount = IDirect3DDevice3_Release(device);
7377 ok(!refcount, "Device has %u references left.\n", refcount);
7378 DestroyWindow(window);
7381 static void test_palette_gdi(void)
7383 IDirectDrawSurface4 *surface, *primary;
7384 DDSURFACEDESC2 surface_desc;
7385 IDirectDraw4 *ddraw;
7386 IDirectDrawPalette *palette, *palette2;
7387 ULONG refcount;
7388 HWND window;
7389 HRESULT hr;
7390 PALETTEENTRY palette_entries[256];
7391 UINT i;
7392 HDC dc;
7393 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
7394 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
7395 * not the point of this test. */
7396 static const RGBQUAD expected1[] =
7398 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
7399 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
7401 static const RGBQUAD expected2[] =
7403 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
7404 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
7406 static const RGBQUAD expected3[] =
7408 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
7409 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
7411 HPALETTE ddraw_palette_handle;
7412 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
7413 RGBQUAD rgbquad[255];
7414 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
7416 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7417 0, 0, 640, 480, 0, 0, 0, 0);
7418 ddraw = create_ddraw();
7419 ok(!!ddraw, "Failed to create a ddraw object.\n");
7420 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7421 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7423 memset(&surface_desc, 0, sizeof(surface_desc));
7424 surface_desc.dwSize = sizeof(surface_desc);
7425 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7426 surface_desc.dwWidth = 16;
7427 surface_desc.dwHeight = 16;
7428 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7429 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7430 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7431 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
7432 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7433 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7435 /* Avoid colors from the Windows default palette. */
7436 memset(palette_entries, 0, sizeof(palette_entries));
7437 palette_entries[1].peRed = 0x01;
7438 palette_entries[2].peGreen = 0x02;
7439 palette_entries[3].peBlue = 0x03;
7440 palette_entries[4].peRed = 0x13;
7441 palette_entries[4].peGreen = 0x14;
7442 palette_entries[4].peBlue = 0x15;
7443 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7444 palette_entries, &palette, NULL);
7445 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7447 /* If there is no palette assigned and the display mode is not 8 bpp, some
7448 * drivers refuse to create a DC while others allow it. If a DC is created,
7449 * the DIB color table is uninitialized and contains random colors. No error
7450 * is generated when trying to read pixels and random garbage is returned.
7452 * The most likely explanation is that if the driver creates a DC, it (or
7453 * the higher-level runtime) uses GetSystemPaletteEntries to find the
7454 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
7455 * contains uninitialized garbage. See comments below for the P8 case. */
7457 hr = IDirectDrawSurface4_SetPalette(surface, palette);
7458 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7459 hr = IDirectDrawSurface4_GetDC(surface, &dc);
7460 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7461 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
7462 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
7463 "Got unexpected palette %p, expected %p.\n",
7464 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
7466 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7467 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7468 for (i = 0; i < sizeof(expected1) / sizeof(*expected1); i++)
7470 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
7471 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7472 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7473 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
7475 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7477 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7478 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7479 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7482 /* Update the palette while the DC is in use. This does not modify the DC. */
7483 palette_entries[4].peRed = 0x23;
7484 palette_entries[4].peGreen = 0x24;
7485 palette_entries[4].peBlue = 0x25;
7486 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
7487 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
7489 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
7490 ok(i == 1, "Expected count 1, got %u.\n", i);
7491 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
7492 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7493 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
7494 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
7496 /* Neither does re-setting the palette. */
7497 hr = IDirectDrawSurface4_SetPalette(surface, NULL);
7498 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7499 hr = IDirectDrawSurface4_SetPalette(surface, palette);
7500 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7502 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
7503 ok(i == 1, "Expected count 1, got %u.\n", i);
7504 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
7505 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7506 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
7507 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
7509 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
7510 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7512 /* Refresh the DC. This updates the palette. */
7513 hr = IDirectDrawSurface4_GetDC(surface, &dc);
7514 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7515 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7516 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7517 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
7519 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
7520 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7521 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7522 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
7524 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7526 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7527 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7528 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7530 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
7531 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7533 refcount = IDirectDrawSurface4_Release(surface);
7534 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7536 if (FAILED(IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
7538 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
7539 IDirectDrawPalette_Release(palette);
7540 IDirectDraw4_Release(ddraw);
7541 DestroyWindow(window);
7542 return;
7544 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
7545 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
7546 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7548 memset(&surface_desc, 0, sizeof(surface_desc));
7549 surface_desc.dwSize = sizeof(surface_desc);
7550 surface_desc.dwFlags = DDSD_CAPS;
7551 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7552 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
7553 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7555 hr = IDirectDrawSurface4_SetPalette(primary, palette);
7556 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7557 hr = IDirectDrawSurface4_GetDC(primary, &dc);
7558 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7559 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
7560 /* Windows 2000 on the testbot assigns a different palette to the primary. Refrast? */
7561 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE) || broken(TRUE),
7562 "Got unexpected palette %p, expected %p.\n",
7563 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
7564 SelectPalette(dc, ddraw_palette_handle, FALSE);
7566 /* The primary uses the system palette. In exclusive mode, the system palette matches
7567 * the ddraw palette attached to the primary, so the result is what you would expect
7568 * from a regular surface. Tests for the interaction between the ddraw palette and
7569 * the system palette are not included pending an application that depends on this.
7570 * The relation between those causes problems on Windows Vista and newer for games
7571 * like Age of Empires or StarCraft. Don't emulate it without a real need. */
7572 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7573 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7574 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
7576 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
7577 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7578 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7579 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
7581 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7583 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7584 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7585 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7587 hr = IDirectDrawSurface4_ReleaseDC(primary, dc);
7588 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7590 memset(&surface_desc, 0, sizeof(surface_desc));
7591 surface_desc.dwSize = sizeof(surface_desc);
7592 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7593 surface_desc.dwWidth = 16;
7594 surface_desc.dwHeight = 16;
7595 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7596 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7597 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7599 /* Here the offscreen surface appears to use the primary's palette,
7600 * but in all likelihood it is actually the system palette. */
7601 hr = IDirectDrawSurface4_GetDC(surface, &dc);
7602 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7603 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7604 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7605 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
7607 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
7608 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7609 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7610 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
7612 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7614 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7615 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7616 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7618 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
7619 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7621 /* On real hardware a change to the primary surface's palette applies immediately,
7622 * even on device contexts from offscreen surfaces that do not have their own
7623 * palette. On the testbot VMs this is not the case. Don't test this until we
7624 * know of an application that depends on this. */
7626 memset(palette_entries, 0, sizeof(palette_entries));
7627 palette_entries[1].peBlue = 0x40;
7628 palette_entries[2].peRed = 0x40;
7629 palette_entries[3].peGreen = 0x40;
7630 palette_entries[4].peRed = 0x12;
7631 palette_entries[4].peGreen = 0x34;
7632 palette_entries[4].peBlue = 0x56;
7633 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7634 palette_entries, &palette2, NULL);
7635 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7636 hr = IDirectDrawSurface4_SetPalette(surface, palette2);
7637 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7639 /* A palette assigned to the offscreen surface overrides the primary / system
7640 * palette. */
7641 hr = IDirectDrawSurface4_GetDC(surface, &dc);
7642 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7643 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7644 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7645 for (i = 0; i < sizeof(expected3) / sizeof(*expected3); i++)
7647 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
7648 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7649 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7650 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
7652 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7654 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7655 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7656 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7658 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
7659 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7661 refcount = IDirectDrawSurface4_Release(surface);
7662 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7664 /* The Windows 8 testbot keeps extra references to the primary and
7665 * backbuffer while in 8 bpp mode. */
7666 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
7667 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
7669 refcount = IDirectDrawSurface4_Release(primary);
7670 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7671 refcount = IDirectDrawPalette_Release(palette2);
7672 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7673 refcount = IDirectDrawPalette_Release(palette);
7674 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7675 refcount = IDirectDraw4_Release(ddraw);
7676 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7677 DestroyWindow(window);
7680 static void test_palette_alpha(void)
7682 IDirectDrawSurface4 *surface;
7683 DDSURFACEDESC2 surface_desc;
7684 IDirectDraw4 *ddraw;
7685 IDirectDrawPalette *palette;
7686 ULONG refcount;
7687 HWND window;
7688 HRESULT hr;
7689 PALETTEENTRY palette_entries[256];
7690 unsigned int i;
7691 static const struct
7693 DWORD caps, flags;
7694 BOOL attach_allowed;
7695 const char *name;
7697 test_data[] =
7699 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
7700 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
7701 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
7704 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7705 0, 0, 640, 480, 0, 0, 0, 0);
7706 ddraw = create_ddraw();
7707 ok(!!ddraw, "Failed to create a ddraw object.\n");
7708 if (FAILED(IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
7710 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
7711 IDirectDraw4_Release(ddraw);
7712 DestroyWindow(window);
7713 return;
7715 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7716 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7718 memset(palette_entries, 0, sizeof(palette_entries));
7719 palette_entries[1].peFlags = 0x42;
7720 palette_entries[2].peFlags = 0xff;
7721 palette_entries[3].peFlags = 0x80;
7722 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
7723 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7725 memset(palette_entries, 0x66, sizeof(palette_entries));
7726 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
7727 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
7728 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7729 palette_entries[0].peFlags);
7730 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7731 palette_entries[1].peFlags);
7732 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
7733 palette_entries[2].peFlags);
7734 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
7735 palette_entries[3].peFlags);
7737 IDirectDrawPalette_Release(palette);
7739 memset(palette_entries, 0, sizeof(palette_entries));
7740 palette_entries[1].peFlags = 0x42;
7741 palette_entries[1].peRed = 0xff;
7742 palette_entries[2].peFlags = 0xff;
7743 palette_entries[3].peFlags = 0x80;
7744 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
7745 palette_entries, &palette, NULL);
7746 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7748 memset(palette_entries, 0x66, sizeof(palette_entries));
7749 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
7750 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
7751 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7752 palette_entries[0].peFlags);
7753 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7754 palette_entries[1].peFlags);
7755 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
7756 palette_entries[2].peFlags);
7757 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
7758 palette_entries[3].peFlags);
7760 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); i++)
7762 memset(&surface_desc, 0, sizeof(surface_desc));
7763 surface_desc.dwSize = sizeof(surface_desc);
7764 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
7765 surface_desc.dwWidth = 128;
7766 surface_desc.dwHeight = 128;
7767 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
7768 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7769 ok(SUCCEEDED(hr), "Failed to create %s surface, hr %#x.\n", test_data[i].name, hr);
7771 hr = IDirectDrawSurface4_SetPalette(surface, palette);
7772 if (test_data[i].attach_allowed)
7773 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#x.\n", test_data[i].name, hr);
7774 else
7775 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x, %s surface.\n", hr, test_data[i].name);
7777 if (SUCCEEDED(hr))
7779 HDC dc;
7780 RGBQUAD rgbquad;
7781 UINT retval;
7783 hr = IDirectDrawSurface4_GetDC(surface, &dc);
7784 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
7785 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
7786 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
7787 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
7788 rgbquad.rgbRed, test_data[i].name);
7789 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
7790 rgbquad.rgbGreen, test_data[i].name);
7791 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
7792 rgbquad.rgbBlue, test_data[i].name);
7793 todo_wine ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
7794 rgbquad.rgbReserved, test_data[i].name);
7795 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
7796 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7798 IDirectDrawSurface4_Release(surface);
7801 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
7802 memset(&surface_desc, 0, sizeof(surface_desc));
7803 surface_desc.dwSize = sizeof(surface_desc);
7804 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7805 surface_desc.dwWidth = 128;
7806 surface_desc.dwHeight = 128;
7807 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7808 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7809 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
7810 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
7811 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7812 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7813 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7814 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7815 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7816 hr = IDirectDrawSurface4_SetPalette(surface, palette);
7817 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
7818 IDirectDrawSurface4_Release(surface);
7820 /* The Windows 8 testbot keeps extra references to the primary
7821 * while in 8 bpp mode. */
7822 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
7823 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
7825 refcount = IDirectDrawPalette_Release(palette);
7826 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7827 refcount = IDirectDraw4_Release(ddraw);
7828 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7829 DestroyWindow(window);
7832 static void test_vb_writeonly(void)
7834 IDirect3DDevice3 *device;
7835 IDirect3D3 *d3d;
7836 IDirect3DVertexBuffer *buffer;
7837 HWND window;
7838 HRESULT hr;
7839 D3DVERTEXBUFFERDESC desc;
7840 void *ptr;
7841 static const struct vec4 quad[] =
7843 { 0.0f, 480.0f, 0.0f, 1.0f},
7844 { 0.0f, 0.0f, 0.0f, 1.0f},
7845 {640.0f, 480.0f, 0.0f, 1.0f},
7846 {640.0f, 0.0f, 0.0f, 1.0f},
7849 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7850 0, 0, 640, 480, 0, 0, 0, 0);
7852 if (!(device = create_device(window, DDSCL_NORMAL)))
7854 skip("Failed to create a 3D device, skipping test.\n");
7855 DestroyWindow(window);
7856 return;
7859 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
7860 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
7862 memset(&desc, 0, sizeof(desc));
7863 desc.dwSize = sizeof(desc);
7864 desc.dwCaps = D3DVBCAPS_WRITEONLY;
7865 desc.dwFVF = D3DFVF_XYZRHW;
7866 desc.dwNumVertices = sizeof(quad) / sizeof(*quad);
7867 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &buffer, 0, NULL);
7868 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
7870 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, &ptr, NULL);
7871 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
7872 memcpy(ptr, quad, sizeof(quad));
7873 hr = IDirect3DVertexBuffer_Unlock(buffer);
7874 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
7876 hr = IDirect3DDevice3_BeginScene(device);
7877 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
7878 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
7879 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7880 hr = IDirect3DDevice3_EndScene(device);
7881 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7883 hr = IDirect3DVertexBuffer_Lock(buffer, 0, &ptr, NULL);
7884 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
7885 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
7886 hr = IDirect3DVertexBuffer_Unlock(buffer);
7887 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
7889 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_READONLY, &ptr, NULL);
7890 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
7891 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
7892 hr = IDirect3DVertexBuffer_Unlock(buffer);
7893 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
7895 IDirect3DVertexBuffer_Release(buffer);
7896 IDirect3D3_Release(d3d);
7897 IDirect3DDevice3_Release(device);
7898 DestroyWindow(window);
7901 static void test_lost_device(void)
7903 IDirectDrawSurface4 *surface;
7904 DDSURFACEDESC2 surface_desc;
7905 IDirectDraw4 *ddraw;
7906 ULONG refcount;
7907 HWND window;
7908 HRESULT hr;
7909 BOOL ret;
7911 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7912 0, 0, 640, 480, 0, 0, 0, 0);
7913 ddraw = create_ddraw();
7914 ok(!!ddraw, "Failed to create a ddraw object.\n");
7915 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7916 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7918 memset(&surface_desc, 0, sizeof(surface_desc));
7919 surface_desc.dwSize = sizeof(surface_desc);
7920 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
7921 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
7922 U5(surface_desc).dwBackBufferCount = 1;
7923 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7924 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7926 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
7927 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7928 hr = IDirectDrawSurface4_IsLost(surface);
7929 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7930 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
7931 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7933 ret = SetForegroundWindow(GetDesktopWindow());
7934 ok(ret, "Failed to set foreground window.\n");
7935 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
7936 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
7937 hr = IDirectDrawSurface4_IsLost(surface);
7938 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7939 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
7940 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7942 ret = SetForegroundWindow(window);
7943 ok(ret, "Failed to set foreground window.\n");
7944 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
7945 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7946 hr = IDirectDrawSurface4_IsLost(surface);
7947 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7948 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
7949 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7951 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
7952 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7953 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
7954 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7955 hr = IDirectDrawSurface4_IsLost(surface);
7956 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7957 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
7958 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7960 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7961 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7962 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
7963 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7964 hr = IDirectDrawSurface4_IsLost(surface);
7965 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7966 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
7967 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7969 /* Trying to restore the primary will crash, probably because flippable
7970 * surfaces can't exist in DDSCL_NORMAL. */
7971 IDirectDrawSurface4_Release(surface);
7972 memset(&surface_desc, 0, sizeof(surface_desc));
7973 surface_desc.dwSize = sizeof(surface_desc);
7974 surface_desc.dwFlags = DDSD_CAPS;
7975 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7976 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7977 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7979 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
7980 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7981 hr = IDirectDrawSurface4_IsLost(surface);
7982 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7984 ret = SetForegroundWindow(GetDesktopWindow());
7985 ok(ret, "Failed to set foreground window.\n");
7986 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
7987 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7988 hr = IDirectDrawSurface4_IsLost(surface);
7989 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7991 ret = SetForegroundWindow(window);
7992 ok(ret, "Failed to set foreground window.\n");
7993 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
7994 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7995 hr = IDirectDrawSurface4_IsLost(surface);
7996 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7998 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7999 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8000 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8001 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8002 hr = IDirectDrawSurface4_IsLost(surface);
8003 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8005 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
8006 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8007 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8008 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8009 hr = IDirectDrawSurface4_IsLost(surface);
8010 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8012 IDirectDrawSurface4_Release(surface);
8013 refcount = IDirectDraw4_Release(ddraw);
8014 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8015 DestroyWindow(window);
8018 static void test_surface_desc_lock(void)
8020 IDirectDrawSurface4 *surface;
8021 DDSURFACEDESC2 surface_desc;
8022 IDirectDraw4 *ddraw;
8023 ULONG refcount;
8024 HWND window;
8025 HRESULT hr;
8027 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8028 0, 0, 640, 480, 0, 0, 0, 0);
8029 ddraw = create_ddraw();
8030 ok(!!ddraw, "Failed to create a ddraw object.\n");
8031 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8032 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8034 memset(&surface_desc, 0, sizeof(surface_desc));
8035 surface_desc.dwSize = sizeof(surface_desc);
8036 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8037 surface_desc.dwWidth = 16;
8038 surface_desc.dwHeight = 16;
8039 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8040 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8041 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8043 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8044 surface_desc.dwSize = sizeof(surface_desc);
8045 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
8046 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8047 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8049 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8050 surface_desc.dwSize = sizeof(surface_desc);
8051 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, 0, NULL);
8052 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8053 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8054 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8055 surface_desc.dwSize = sizeof(surface_desc);
8056 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
8057 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8058 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8059 hr = IDirectDrawSurface4_Unlock(surface, NULL);
8060 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8062 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8063 surface_desc.dwSize = sizeof(surface_desc);
8064 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
8065 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8066 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8068 IDirectDrawSurface4_Release(surface);
8069 refcount = IDirectDraw4_Release(ddraw);
8070 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8071 DestroyWindow(window);
8074 static void test_signed_formats(void)
8076 HRESULT hr;
8077 IDirect3DDevice3 *device;
8078 IDirect3D3 *d3d;
8079 IDirectDraw4 *ddraw;
8080 IDirectDrawSurface4 *surface, *rt;
8081 IDirect3DTexture2 *texture;
8082 IDirect3DViewport3 *viewport;
8083 DDSURFACEDESC2 surface_desc;
8084 ULONG refcount;
8085 HWND window;
8086 D3DCOLOR color, expected_color;
8087 D3DRECT clear_rect;
8088 static struct
8090 struct vec3 position;
8091 struct vec2 texcoord;
8093 quad[] =
8095 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
8096 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
8097 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
8098 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
8100 /* See test_signed_formats() in dlls/d3d9/tests/visual.c for an explanation
8101 * of these values. */
8102 static const USHORT content_v8u8[4][4] =
8104 {0x0000, 0x7f7f, 0x8880, 0x0000},
8105 {0x0080, 0x8000, 0x7f00, 0x007f},
8106 {0x193b, 0xe8c8, 0x0808, 0xf8f8},
8107 {0x4444, 0xc0c0, 0xa066, 0x22e0},
8109 static const DWORD content_x8l8v8u8[4][4] =
8111 {0x00000000, 0x00ff7f7f, 0x00008880, 0x00ff0000},
8112 {0x00000080, 0x00008000, 0x00007f00, 0x0000007f},
8113 {0x0041193b, 0x0051e8c8, 0x00040808, 0x00fff8f8},
8114 {0x00824444, 0x0000c0c0, 0x00c2a066, 0x009222e0},
8116 static const USHORT content_l6v5u5[4][4] =
8118 {0x0000, 0xfdef, 0x0230, 0xfc00},
8119 {0x0010, 0x0200, 0x01e0, 0x000f},
8120 {0x4067, 0x53b9, 0x0421, 0xffff},
8121 {0x8108, 0x0318, 0xc28c, 0x909c},
8123 static const struct
8125 const char *name;
8126 const void *content;
8127 SIZE_T pixel_size;
8128 BOOL blue;
8129 unsigned int slop, slop_broken;
8130 DDPIXELFORMAT format;
8132 formats[] =
8135 "D3DFMT_V8U8", content_v8u8, sizeof(WORD), FALSE, 1, 0,
8137 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV, 0,
8138 {16}, {0x000000ff}, {0x0000ff00}, {0x00000000}, {0x00000000}
8142 "D3DFMT_X8L8V8U8", content_x8l8v8u8, sizeof(DWORD), TRUE, 1, 0,
8144 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
8145 {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}
8149 "D3DFMT_L6V5U5", content_l6v5u5, sizeof(WORD), TRUE, 4, 7,
8151 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
8152 {16}, {0x0000001f}, {0x000003e0}, {0x0000fc00}, {0x00000000}
8156 /* No V16U16 or Q8W8V8U8 support in ddraw. */
8158 static const D3DCOLOR expected_colors[4][4] =
8160 {0x00808080, 0x00fefeff, 0x00010780, 0x008080ff},
8161 {0x00018080, 0x00800180, 0x0080fe80, 0x00fe8080},
8162 {0x00ba98a0, 0x004767a8, 0x00888881, 0x007878ff},
8163 {0x00c3c3c0, 0x003f3f80, 0x00e51fe1, 0x005fa2c8},
8165 unsigned int i, width, x, y;
8166 D3DDEVICEDESC device_desc, hel_desc;
8168 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8169 0, 0, 640, 480, 0, 0, 0, 0);
8171 if (!(device = create_device(window, DDSCL_NORMAL)))
8173 skip("Failed to create a 3D device, skipping test.\n");
8174 DestroyWindow(window);
8175 return;
8178 memset(&device_desc, 0, sizeof(device_desc));
8179 device_desc.dwSize = sizeof(device_desc);
8180 memset(&hel_desc, 0, sizeof(hel_desc));
8181 hel_desc.dwSize = sizeof(hel_desc);
8182 hr = IDirect3DDevice3_GetCaps(device, &device_desc, &hel_desc);
8183 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
8184 if (!(device_desc.dwTextureOpCaps & D3DTEXOPCAPS_BLENDFACTORALPHA))
8186 skip("D3DTOP_BLENDFACTORALPHA not supported, skipping bumpmap format tests.\n");
8187 goto done;
8190 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
8191 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
8192 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
8193 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
8194 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
8195 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8197 memset(&surface_desc, 0, sizeof(surface_desc));
8198 surface_desc.dwSize = sizeof(surface_desc);
8199 hr = IDirectDrawSurface4_GetSurfaceDesc(rt, &surface_desc);
8200 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8201 viewport = create_viewport(device, 0, 0, surface_desc.dwWidth, surface_desc.dwHeight);
8202 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
8203 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
8204 U1(clear_rect).x1 = 0;
8205 U2(clear_rect).y1 = 0;
8206 U3(clear_rect).x2 = surface_desc.dwWidth;
8207 U4(clear_rect).y2 = surface_desc.dwHeight;
8209 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
8210 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8212 /* dst = tex * 0.5 + 1.0 * (1.0 - 0.5) = tex * 0.5 + 0.5 */
8213 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x80ffffff);
8214 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8215 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BLENDFACTORALPHA);
8216 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
8217 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
8218 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
8219 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
8220 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
8222 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
8224 for (width = 1; width < 5; width += 3)
8226 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
8227 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8229 memset(&surface_desc, 0, sizeof(surface_desc));
8230 surface_desc.dwSize = sizeof(surface_desc);
8231 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
8232 surface_desc.dwWidth = width;
8233 surface_desc.dwHeight = 4;
8234 U4(surface_desc).ddpfPixelFormat = formats[i].format;
8235 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
8236 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8237 if (FAILED(hr))
8239 skip("%s textures not supported, skipping.\n", formats[i].name);
8240 continue;
8242 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, format %s.\n", hr, formats[i].name);
8244 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
8245 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture2 interface, hr %#x, format %s.\n",
8246 hr, formats[i].name);
8247 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
8248 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x, format %s.\n", hr, formats[i].name);
8249 IDirect3DTexture2_Release(texture);
8251 memset(&surface_desc, 0, sizeof(surface_desc));
8252 surface_desc.dwSize = sizeof(surface_desc);
8253 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, 0, NULL);
8254 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, format %s.\n", hr, formats[i].name);
8255 for (y = 0; y < 4; y++)
8257 memcpy((char *)surface_desc.lpSurface + y * U1(surface_desc).lPitch,
8258 (char *)formats[i].content + y * 4 * formats[i].pixel_size,
8259 width * formats[i].pixel_size);
8261 hr = IDirectDrawSurface4_Unlock(surface, NULL);
8262 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, format %s.\n", hr, formats[i].name);
8264 hr = IDirect3DDevice3_BeginScene(device);
8265 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8266 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
8267 D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
8268 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8269 hr = IDirect3DDevice3_EndScene(device);
8270 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8272 for (y = 0; y < 4; y++)
8274 for (x = 0; x < width; x++)
8276 expected_color = expected_colors[y][x];
8277 if (!formats[i].blue)
8278 expected_color |= 0x000000ff;
8280 color = get_surface_color(rt, 80 + 160 * x, 60 + 120 * y);
8281 ok(compare_color(color, expected_color, formats[i].slop)
8282 || broken(compare_color(color, expected_color, formats[i].slop_broken)),
8283 "Expected color 0x%08x, got 0x%08x, format %s, location %ux%u.\n",
8284 expected_color, color, formats[i].name, x, y);
8288 IDirectDrawSurface4_Release(surface);
8292 destroy_viewport(device, viewport);
8293 IDirectDrawSurface4_Release(rt);
8294 IDirectDraw4_Release(ddraw);
8295 IDirect3D3_Release(d3d);
8297 done:
8298 refcount = IDirect3DDevice3_Release(device);
8299 ok(!refcount, "Device has %u references left.\n", refcount);
8300 DestroyWindow(window);
8303 static void test_color_fill(void)
8305 HRESULT hr;
8306 IDirect3DDevice3 *device;
8307 IDirect3D3 *d3d;
8308 IDirectDraw4 *ddraw;
8309 IDirectDrawSurface4 *surface, *surface2;
8310 DDSURFACEDESC2 surface_desc;
8311 DDPIXELFORMAT z_fmt;
8312 ULONG refcount;
8313 HWND window;
8314 unsigned int i;
8315 DDBLTFX fx;
8316 RECT rect = {5, 5, 7, 7};
8317 DWORD *color;
8318 DWORD supported_fmts = 0, num_fourcc_codes, *fourcc_codes;
8319 DDCAPS hal_caps;
8320 static const struct
8322 DWORD caps, caps2;
8323 HRESULT colorfill_hr, depthfill_hr;
8324 BOOL rop_success;
8325 const char *name;
8326 DWORD result;
8327 BOOL check_result;
8328 DDPIXELFORMAT format;
8330 tests[] =
8333 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
8334 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
8336 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
8337 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
8341 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
8342 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
8344 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
8345 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
8349 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
8350 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
8352 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
8353 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
8357 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
8358 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
8360 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
8361 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
8365 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
8366 DD_OK, DDERR_INVALIDPARAMS, TRUE, "managed texture RGB", 0xdeadbeef, TRUE,
8368 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
8369 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
8373 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY, 0,
8374 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0, FALSE,
8375 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
8378 DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY, 0,
8379 DDERR_INVALIDPARAMS, DD_OK, TRUE, "sysmem zbuffer", 0, FALSE,
8380 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
8383 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
8384 * different afterwards. DX9+ GPUs set one of the two luminance values
8385 * in each block, but AMD and Nvidia GPUs disagree on which luminance
8386 * value they set. r200 (dx8) just sets the entire block to the clear
8387 * value. */
8388 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
8389 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
8391 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
8392 {0}, {0}, {0}, {0}, {0}
8396 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
8397 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
8399 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
8400 {0}, {0}, {0}, {0}, {0}
8404 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
8405 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
8407 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
8408 {0}, {0}, {0}, {0}, {0}
8412 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
8413 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
8415 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
8416 {0}, {0}, {0}, {0}, {0}
8420 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
8421 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
8423 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
8424 {0}, {0}, {0}, {0}, {0}
8428 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
8429 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
8431 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
8432 {0}, {0}, {0}, {0}, {0}
8436 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
8437 * surface works, presumably because it is handled by the runtime instead of
8438 * the driver. */
8439 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
8440 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
8442 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
8443 {8}, {0}, {0}, {0}, {0}
8447 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
8448 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
8450 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
8451 {8}, {0}, {0}, {0}, {0}
8455 static const struct
8457 DWORD rop;
8458 const char *name;
8459 HRESULT hr;
8461 rops[] =
8463 {SRCCOPY, "SRCCOPY", DD_OK},
8464 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
8465 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
8466 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
8467 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
8468 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
8469 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
8470 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
8471 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
8472 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
8473 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
8474 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
8475 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
8476 {BLACKNESS, "BLACKNESS", DD_OK},
8477 {WHITENESS, "WHITENESS", DD_OK},
8478 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
8481 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8482 0, 0, 640, 480, 0, 0, 0, 0);
8484 if (!(device = create_device(window, DDSCL_NORMAL)))
8486 skip("Failed to create a 3D device, skipping test.\n");
8487 DestroyWindow(window);
8488 return;
8491 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
8492 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
8493 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
8494 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
8496 memset(&z_fmt, 0, sizeof(z_fmt));
8497 IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
8498 if (!z_fmt.dwSize)
8499 skip("No Z buffer formats supported, skipping Z buffer colorfill test.\n");
8501 IDirect3DDevice3_EnumTextureFormats(device, test_block_formats_creation_cb, &supported_fmts);
8502 if (!(supported_fmts & SUPPORT_DXT1))
8503 skip("DXT1 textures not supported, skipping DXT1 colorfill test.\n");
8505 IDirect3D3_Release(d3d);
8507 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
8508 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
8509 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8510 num_fourcc_codes * sizeof(*fourcc_codes));
8511 if (!fourcc_codes)
8512 goto done;
8513 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
8514 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
8515 for (i = 0; i < num_fourcc_codes; i++)
8517 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
8518 supported_fmts |= SUPPORT_YUY2;
8519 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
8520 supported_fmts |= SUPPORT_UYVY;
8522 HeapFree(GetProcessHeap(), 0, fourcc_codes);
8524 memset(&hal_caps, 0, sizeof(hal_caps));
8525 hal_caps.dwSize = sizeof(hal_caps);
8526 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
8527 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8529 if (!(supported_fmts & (SUPPORT_YUY2 | SUPPORT_UYVY)) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
8530 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
8532 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
8534 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
8535 memset(&fx, 0, sizeof(fx));
8536 fx.dwSize = sizeof(fx);
8537 U5(fx).dwFillColor = 0xdeadbeef;
8539 memset(&surface_desc, 0, sizeof(surface_desc));
8540 surface_desc.dwSize = sizeof(surface_desc);
8541 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8542 surface_desc.dwWidth = 64;
8543 surface_desc.dwHeight = 64;
8544 U4(surface_desc).ddpfPixelFormat = tests[i].format;
8545 surface_desc.ddsCaps.dwCaps = tests[i].caps;
8546 surface_desc.ddsCaps.dwCaps2 = tests[i].caps2;
8548 if (tests[i].format.dwFourCC == MAKEFOURCC('D','X','T','1') && !(supported_fmts & SUPPORT_DXT1))
8549 continue;
8550 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !(supported_fmts & SUPPORT_YUY2))
8551 continue;
8552 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !(supported_fmts & SUPPORT_UYVY))
8553 continue;
8554 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
8555 continue;
8557 if (tests[i].caps & DDSCAPS_ZBUFFER)
8559 if (!z_fmt.dwSize)
8560 continue;
8562 U4(surface_desc).ddpfPixelFormat = z_fmt;
8565 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8566 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, surface %s.\n", hr, tests[i].name);
8568 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8569 if (tests[i].format.dwFourCC)
8570 todo_wine ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
8571 hr, tests[i].colorfill_hr, tests[i].name);
8572 else
8573 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
8574 hr, tests[i].colorfill_hr, tests[i].name);
8576 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8577 if (tests[i].format.dwFourCC)
8578 todo_wine ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
8579 hr, tests[i].colorfill_hr, tests[i].name);
8580 else
8581 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
8582 hr, tests[i].colorfill_hr, tests[i].name);
8584 if (SUCCEEDED(hr) && tests[i].check_result)
8586 memset(&surface_desc, 0, sizeof(surface_desc));
8587 surface_desc.dwSize = sizeof(surface_desc);
8588 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
8589 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8590 color = surface_desc.lpSurface;
8591 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
8592 *color, tests[i].result, tests[i].name);
8593 hr = IDirectDrawSurface4_Unlock(surface, NULL);
8594 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8597 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8598 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
8599 hr, tests[i].depthfill_hr, tests[i].name);
8600 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8601 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
8602 hr, tests[i].depthfill_hr, tests[i].name);
8604 U5(fx).dwFillColor = 0xdeadbeef;
8605 fx.dwROP = BLACKNESS;
8606 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
8607 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
8608 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
8609 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
8610 U5(fx).dwFillColor, tests[i].name);
8612 if (SUCCEEDED(hr) && tests[i].check_result)
8614 memset(&surface_desc, 0, sizeof(surface_desc));
8615 surface_desc.dwSize = sizeof(surface_desc);
8616 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
8617 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8618 color = surface_desc.lpSurface;
8619 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
8620 *color, tests[i].name);
8621 hr = IDirectDrawSurface4_Unlock(surface, NULL);
8622 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8625 fx.dwROP = WHITENESS;
8626 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
8627 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
8628 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
8629 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
8630 U5(fx).dwFillColor, tests[i].name);
8632 if (SUCCEEDED(hr) && tests[i].check_result)
8634 memset(&surface_desc, 0, sizeof(surface_desc));
8635 surface_desc.dwSize = sizeof(surface_desc);
8636 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
8637 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8638 color = surface_desc.lpSurface;
8639 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
8640 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
8641 *color, tests[i].name);
8642 hr = IDirectDrawSurface4_Unlock(surface, NULL);
8643 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
8646 IDirectDrawSurface4_Release(surface);
8649 memset(&fx, 0, sizeof(fx));
8650 fx.dwSize = sizeof(fx);
8651 U5(fx).dwFillColor = 0xdeadbeef;
8652 fx.dwROP = WHITENESS;
8654 memset(&surface_desc, 0, sizeof(surface_desc));
8655 surface_desc.dwSize = sizeof(surface_desc);
8656 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8657 surface_desc.dwWidth = 64;
8658 surface_desc.dwHeight = 64;
8659 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8660 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
8661 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8662 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8663 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8664 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8665 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
8666 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8667 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8668 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
8669 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8671 /* No DDBLTFX. */
8672 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
8673 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8674 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
8675 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8677 /* Unused source rectangle. */
8678 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8679 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8680 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
8681 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8683 /* Unused source surface. */
8684 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8685 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8686 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
8687 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8688 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8689 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8690 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
8691 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8693 /* Inverted destination or source rectangle. */
8694 SetRect(&rect, 5, 7, 7, 5);
8695 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8696 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8697 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8698 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8699 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8700 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8701 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8702 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8703 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
8704 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8706 /* Negative rectangle. */
8707 SetRect(&rect, -1, -1, 5, 5);
8708 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8709 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8710 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8711 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8712 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8713 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8714 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8715 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8716 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
8717 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8719 /* Out of bounds rectangle. */
8720 SetRect(&rect, 0, 0, 65, 65);
8721 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8722 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8723 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
8724 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8726 /* Combine multiple flags. */
8727 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8728 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8729 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
8730 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8731 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
8732 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8734 for (i = 0; i < sizeof(rops) / sizeof(*rops); i++)
8736 fx.dwROP = rops[i].rop;
8737 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
8738 ok(hr == rops[i].hr, "Got unexpected hr %#x for rop %s.\n", hr, rops[i].name);
8741 IDirectDrawSurface4_Release(surface2);
8742 IDirectDrawSurface4_Release(surface);
8744 if (!z_fmt.dwSize)
8745 goto done;
8747 memset(&surface_desc, 0, sizeof(surface_desc));
8748 surface_desc.dwSize = sizeof(surface_desc);
8749 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8750 surface_desc.dwWidth = 64;
8751 surface_desc.dwHeight = 64;
8752 U4(surface_desc).ddpfPixelFormat = z_fmt;
8753 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
8754 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8755 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8756 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
8757 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8759 /* No DDBLTFX. */
8760 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
8761 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8763 /* Unused source rectangle. */
8764 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8765 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8767 /* Unused source surface. */
8768 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8769 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8770 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8771 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8773 /* Inverted destination or source rectangle. */
8774 SetRect(&rect, 5, 7, 7, 5);
8775 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8776 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8777 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8778 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8779 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8780 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8781 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8782 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8784 /* Negative rectangle. */
8785 SetRect(&rect, -1, -1, 5, 5);
8786 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8787 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8788 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8789 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
8790 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8791 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8792 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8793 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8795 /* Out of bounds rectangle. */
8796 SetRect(&rect, 0, 0, 65, 65);
8797 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8798 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
8800 /* Combine multiple flags. */
8801 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
8802 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8804 IDirectDrawSurface4_Release(surface2);
8805 IDirectDrawSurface4_Release(surface);
8807 done:
8808 IDirectDraw4_Release(ddraw);
8809 refcount = IDirect3DDevice3_Release(device);
8810 ok(!refcount, "Device has %u references left.\n", refcount);
8811 DestroyWindow(window);
8814 START_TEST(ddraw4)
8816 IDirectDraw4 *ddraw;
8817 DEVMODEW current_mode;
8819 if (!(ddraw = create_ddraw()))
8821 skip("Failed to create a ddraw object, skipping tests.\n");
8822 return;
8824 IDirectDraw4_Release(ddraw);
8826 memset(&current_mode, 0, sizeof(current_mode));
8827 current_mode.dmSize = sizeof(current_mode);
8828 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
8829 registry_mode.dmSize = sizeof(registry_mode);
8830 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
8831 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
8832 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
8834 skip("Current mode does not match registry mode, skipping test.\n");
8835 return;
8838 test_process_vertices();
8839 test_coop_level_create_device_window();
8840 test_clipper_blt();
8841 test_coop_level_d3d_state();
8842 test_surface_interface_mismatch();
8843 test_coop_level_threaded();
8844 test_depth_blit();
8845 test_texture_load_ckey();
8846 test_viewport();
8847 test_zenable();
8848 test_ck_rgba();
8849 test_ck_default();
8850 test_ck_complex();
8851 test_surface_qi();
8852 test_device_qi();
8853 test_wndproc();
8854 test_window_style();
8855 test_redundant_mode_set();
8856 test_coop_level_mode_set();
8857 test_coop_level_mode_set_multi();
8858 test_initialize();
8859 test_coop_level_surf_create();
8860 test_vb_discard();
8861 test_coop_level_multi_window();
8862 test_draw_strided();
8863 test_clear_rect_count();
8864 test_coop_level_versions();
8865 test_lighting_interface_versions();
8866 test_coop_level_activateapp();
8867 test_texturemanage();
8868 test_block_formats_creation();
8869 test_unsupported_formats();
8870 test_rt_caps();
8871 test_primary_caps();
8872 test_surface_lock();
8873 test_surface_discard();
8874 test_flip();
8875 test_set_surface_desc();
8876 test_user_memory_getdc();
8877 test_sysmem_overlay();
8878 test_primary_palette();
8879 test_surface_attachment();
8880 test_private_data();
8881 test_pixel_format();
8882 test_create_surface_pitch();
8883 test_mipmap_lock();
8884 test_palette_complex();
8885 test_p8_rgb_blit();
8886 test_material();
8887 test_palette_gdi();
8888 test_palette_alpha();
8889 test_vb_writeonly();
8890 test_lost_device();
8891 test_surface_desc_lock();
8892 test_signed_formats();
8893 test_color_fill();