ddraw/tests: Test matrices in TransformVertices.
[wine.git] / dlls / ddraw / tests / ddraw4.c
blob2c7eae141cca94163ab0b1a7193766b5e953fe2a
1 /*
2 * Copyright 2005 Antoine Chavasse (a.chavasse@gmail.com)
3 * Copyright 2008, 2011, 2012-2014 Stefan Dösinger for CodeWeavers
4 * Copyright 2011-2014 Henri Verbeet for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #define COBJMACROS
22 #include "wine/test.h"
23 #include <limits.h>
24 #include <math.h>
25 #include "d3d.h"
27 static BOOL is_ddraw64 = sizeof(DWORD) != sizeof(DWORD *);
28 static DEVMODEW registry_mode;
30 static HRESULT (WINAPI *pDwmIsCompositionEnabled)(BOOL *);
32 struct vec2
34 float x, y;
37 struct vec3
39 float x, y, z;
42 struct vec4
44 float x, y, z, w;
47 struct create_window_thread_param
49 HWND window;
50 HANDLE window_created;
51 HANDLE destroy_window;
52 HANDLE thread;
55 static BOOL compare_float(float f, float g, unsigned int ulps)
57 int x = *(int *)&f;
58 int y = *(int *)&g;
60 if (x < 0)
61 x = INT_MIN - x;
62 if (y < 0)
63 y = INT_MIN - y;
65 if (abs(x - y) > ulps)
66 return FALSE;
68 return TRUE;
71 static BOOL compare_vec4(const struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
73 return compare_float(vec->x, x, ulps)
74 && compare_float(vec->y, y, ulps)
75 && compare_float(vec->z, z, ulps)
76 && compare_float(vec->w, w, ulps);
79 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
81 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
82 c1 >>= 8; c2 >>= 8;
83 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
84 c1 >>= 8; c2 >>= 8;
85 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
86 c1 >>= 8; c2 >>= 8;
87 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
88 return TRUE;
91 static IDirectDrawSurface4 *create_overlay(IDirectDraw4 *ddraw,
92 unsigned int width, unsigned int height, DWORD format)
94 IDirectDrawSurface4 *surface;
95 DDSURFACEDESC2 desc;
97 memset(&desc, 0, sizeof(desc));
98 desc.dwSize = sizeof(desc);
99 desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
100 desc.dwWidth = width;
101 desc.dwHeight = height;
102 desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
103 U4(desc).ddpfPixelFormat.dwSize = sizeof(U4(desc).ddpfPixelFormat);
104 U4(desc).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
105 U4(desc).ddpfPixelFormat.dwFourCC = format;
107 if (FAILED(IDirectDraw4_CreateSurface(ddraw, &desc, &surface, NULL)))
108 return NULL;
109 return surface;
112 static DWORD WINAPI create_window_thread_proc(void *param)
114 struct create_window_thread_param *p = param;
115 DWORD res;
116 BOOL ret;
118 p->window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
119 0, 0, 640, 480, 0, 0, 0, 0);
120 ret = SetEvent(p->window_created);
121 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
123 for (;;)
125 MSG msg;
127 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
128 DispatchMessageA(&msg);
129 res = WaitForSingleObject(p->destroy_window, 100);
130 if (res == WAIT_OBJECT_0)
131 break;
132 if (res != WAIT_TIMEOUT)
134 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
135 break;
139 DestroyWindow(p->window);
141 return 0;
144 static void create_window_thread(struct create_window_thread_param *p)
146 DWORD res, tid;
148 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
149 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
150 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
151 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
152 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
153 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
154 res = WaitForSingleObject(p->window_created, INFINITE);
155 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
158 static void destroy_window_thread(struct create_window_thread_param *p)
160 SetEvent(p->destroy_window);
161 WaitForSingleObject(p->thread, INFINITE);
162 CloseHandle(p->destroy_window);
163 CloseHandle(p->window_created);
164 CloseHandle(p->thread);
167 static IDirectDrawSurface4 *get_depth_stencil(IDirect3DDevice3 *device)
169 IDirectDrawSurface4 *rt, *ret;
170 DDSCAPS2 caps = {DDSCAPS_ZBUFFER, 0, 0, {0}};
171 HRESULT hr;
173 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
174 ok(SUCCEEDED(hr), "Failed to get the render target, hr %#x.\n", hr);
175 hr = IDirectDrawSurface4_GetAttachedSurface(rt, &caps, &ret);
176 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
177 IDirectDrawSurface4_Release(rt);
178 return ret;
181 static HRESULT set_display_mode(IDirectDraw4 *ddraw, DWORD width, DWORD height)
183 if (SUCCEEDED(IDirectDraw4_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
184 return DD_OK;
185 return IDirectDraw4_SetDisplayMode(ddraw, width, height, 24, 0, 0);
188 static D3DCOLOR get_surface_color(IDirectDrawSurface4 *surface, UINT x, UINT y)
190 RECT rect = {x, y, x + 1, y + 1};
191 DDSURFACEDESC2 surface_desc;
192 D3DCOLOR color;
193 HRESULT hr;
195 memset(&surface_desc, 0, sizeof(surface_desc));
196 surface_desc.dwSize = sizeof(surface_desc);
198 hr = IDirectDrawSurface4_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
199 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
200 if (FAILED(hr))
201 return 0xdeadbeef;
203 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
205 hr = IDirectDrawSurface4_Unlock(surface, &rect);
206 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
208 return color;
211 static HRESULT CALLBACK enum_z_fmt(DDPIXELFORMAT *format, void *ctx)
213 DDPIXELFORMAT *z_fmt = ctx;
215 if (U1(*format).dwZBufferBitDepth > U1(*z_fmt).dwZBufferBitDepth)
216 *z_fmt = *format;
218 return DDENUMRET_OK;
221 static IDirectDraw4 *create_ddraw(void)
223 IDirectDraw4 *ddraw4;
224 IDirectDraw *ddraw1;
225 HRESULT hr;
227 if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
228 return NULL;
230 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw4, (void **)&ddraw4);
231 IDirectDraw_Release(ddraw1);
232 if (FAILED(hr))
233 return NULL;
235 return ddraw4;
238 static IDirect3DDevice3 *create_device(HWND window, DWORD coop_level)
240 IDirectDrawSurface4 *surface, *ds;
241 IDirect3DDevice3 *device = NULL;
242 DDSURFACEDESC2 surface_desc;
243 IDirectDraw4 *ddraw4;
244 DDPIXELFORMAT z_fmt;
245 IDirect3D3 *d3d3;
246 HRESULT hr;
248 if (!(ddraw4 = create_ddraw()))
249 return NULL;
251 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, coop_level);
252 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
254 memset(&surface_desc, 0, sizeof(surface_desc));
255 surface_desc.dwSize = sizeof(surface_desc);
256 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
257 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
258 surface_desc.dwWidth = 640;
259 surface_desc.dwHeight = 480;
261 hr = IDirectDraw4_CreateSurface(ddraw4, &surface_desc, &surface, NULL);
262 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
264 if (coop_level & DDSCL_NORMAL)
266 IDirectDrawClipper *clipper;
268 hr = IDirectDraw4_CreateClipper(ddraw4, 0, &clipper, NULL);
269 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
270 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
271 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
272 hr = IDirectDrawSurface4_SetClipper(surface, clipper);
273 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
274 IDirectDrawClipper_Release(clipper);
277 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirect3D3, (void **)&d3d3);
278 IDirectDraw4_Release(ddraw4);
279 if (FAILED(hr))
281 IDirectDrawSurface4_Release(surface);
282 return NULL;
285 memset(&z_fmt, 0, sizeof(z_fmt));
286 hr = IDirect3D3_EnumZBufferFormats(d3d3, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
287 if (FAILED(hr) || !z_fmt.dwSize)
289 IDirect3D3_Release(d3d3);
290 IDirectDrawSurface4_Release(surface);
291 return NULL;
294 memset(&surface_desc, 0, sizeof(surface_desc));
295 surface_desc.dwSize = sizeof(surface_desc);
296 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
297 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
298 U4(surface_desc).ddpfPixelFormat = z_fmt;
299 surface_desc.dwWidth = 640;
300 surface_desc.dwHeight = 480;
301 hr = IDirectDraw4_CreateSurface(ddraw4, &surface_desc, &ds, NULL);
302 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
303 if (FAILED(hr))
305 IDirect3D3_Release(d3d3);
306 IDirectDrawSurface4_Release(surface);
307 return NULL;
310 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
311 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
312 IDirectDrawSurface4_Release(ds);
313 if (FAILED(hr))
315 IDirect3D3_Release(d3d3);
316 IDirectDrawSurface4_Release(surface);
317 return NULL;
320 hr = IDirect3D3_CreateDevice(d3d3, &IID_IDirect3DHALDevice, surface, &device, NULL);
321 IDirect3D3_Release(d3d3);
322 IDirectDrawSurface4_Release(surface);
323 if (FAILED(hr))
324 return NULL;
326 return device;
329 static IDirect3DViewport3 *create_viewport(IDirect3DDevice3 *device, UINT x, UINT y, UINT w, UINT h)
331 IDirect3DViewport3 *viewport;
332 D3DVIEWPORT2 vp;
333 IDirect3D3 *d3d;
334 HRESULT hr;
336 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
337 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
338 hr = IDirect3D3_CreateViewport(d3d, &viewport, NULL);
339 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
340 hr = IDirect3DDevice3_AddViewport(device, viewport);
341 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
342 memset(&vp, 0, sizeof(vp));
343 vp.dwSize = sizeof(vp);
344 vp.dwX = x;
345 vp.dwY = y;
346 vp.dwWidth = w;
347 vp.dwHeight = h;
348 vp.dvClipX = -1.0f;
349 vp.dvClipY = 1.0f;
350 vp.dvClipWidth = 2.0f;
351 vp.dvClipHeight = 2.0f;
352 vp.dvMinZ = 0.0f;
353 vp.dvMaxZ = 1.0f;
354 hr = IDirect3DViewport3_SetViewport2(viewport, &vp);
355 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
356 IDirect3D3_Release(d3d);
358 return viewport;
361 static void destroy_viewport(IDirect3DDevice3 *device, IDirect3DViewport3 *viewport)
363 HRESULT hr;
365 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
366 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
367 IDirect3DViewport3_Release(viewport);
370 static IDirect3DMaterial3 *create_material(IDirect3DDevice3 *device, D3DMATERIAL *mat)
372 IDirect3DMaterial3 *material;
373 IDirect3D3 *d3d;
374 HRESULT hr;
376 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
377 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
378 hr = IDirect3D3_CreateMaterial(d3d, &material, NULL);
379 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
380 hr = IDirect3DMaterial3_SetMaterial(material, mat);
381 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
382 IDirect3D3_Release(d3d);
384 return material;
387 static IDirect3DMaterial3 *create_diffuse_material(IDirect3DDevice3 *device, float r, float g, float b, float a)
389 D3DMATERIAL mat;
391 memset(&mat, 0, sizeof(mat));
392 mat.dwSize = sizeof(mat);
393 U1(U(mat).diffuse).r = r;
394 U2(U(mat).diffuse).g = g;
395 U3(U(mat).diffuse).b = b;
396 U4(U(mat).diffuse).a = a;
398 return create_material(device, &mat);
401 static IDirect3DMaterial3 *create_specular_material(IDirect3DDevice3 *device,
402 float r, float g, float b, float a, float power)
404 D3DMATERIAL mat;
406 memset(&mat, 0, sizeof(mat));
407 mat.dwSize = sizeof(mat);
408 U1(U2(mat).specular).r = r;
409 U2(U2(mat).specular).g = g;
410 U3(U2(mat).specular).b = b;
411 U4(U2(mat).specular).a = a;
412 U4(mat).power = power;
414 return create_material(device, &mat);
417 static IDirect3DMaterial3 *create_emissive_material(IDirect3DDevice3 *device, float r, float g, float b, float a)
419 D3DMATERIAL mat;
421 memset(&mat, 0, sizeof(mat));
422 mat.dwSize = sizeof(mat);
423 U1(U3(mat).emissive).r = r;
424 U2(U3(mat).emissive).g = g;
425 U3(U3(mat).emissive).b = b;
426 U4(U3(mat).emissive).a = a;
428 return create_material(device, &mat);
431 static void destroy_material(IDirect3DMaterial3 *material)
433 IDirect3DMaterial3_Release(material);
436 struct message
438 UINT message;
439 BOOL check_wparam;
440 WPARAM expect_wparam;
443 static const struct message *expect_messages;
445 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
447 if (expect_messages && message == expect_messages->message)
449 if (expect_messages->check_wparam)
450 ok (wparam == expect_messages->expect_wparam,
451 "Got unexpected wparam %lx for message %x, expected %lx.\n",
452 wparam, message, expect_messages->expect_wparam);
454 ++expect_messages;
457 return DefWindowProcA(hwnd, message, wparam, lparam);
460 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
461 * interface. This prevents subsequent SetCooperativeLevel() calls on a
462 * different window from failing with DDERR_HWNDALREADYSET. */
463 static void fix_wndproc(HWND window, LONG_PTR proc)
465 IDirectDraw4 *ddraw;
466 HRESULT hr;
468 if (!(ddraw = create_ddraw()))
469 return;
471 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
472 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
473 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
474 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
475 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
477 IDirectDraw4_Release(ddraw);
480 static void test_process_vertices(void)
482 IDirect3DVertexBuffer *src_vb, *dst_vb;
483 IDirect3DViewport3 *viewport;
484 D3DVERTEXBUFFERDESC vb_desc;
485 IDirect3DDevice3 *device;
486 struct vec3 *src_data;
487 struct vec4 *dst_data;
488 IDirect3D3 *d3d3;
489 D3DVIEWPORT2 vp2;
490 D3DVIEWPORT vp1;
491 HWND window;
492 HRESULT hr;
494 static D3DMATRIX identity =
496 1.0f, 0.0f, 0.0f, 0.0f,
497 0.0f, 1.0f, 0.0f, 0.0f,
498 0.0f, 0.0f, 1.0f, 0.0f,
499 0.0f, 0.0f, 0.0f, 1.0f,
501 static D3DMATRIX projection =
503 1.0f, 0.0f, 0.0f, 0.0f,
504 0.0f, 1.0f, 0.0f, 0.0f,
505 0.0f, 0.0f, 1.0f, 0.0f,
506 6.0f, 7.0f, 8.0f, 1.0f,
509 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
510 0, 0, 640, 480, 0, 0, 0, 0);
511 if (!(device = create_device(window, DDSCL_NORMAL)))
513 skip("Failed to create a 3D device, skipping test.\n");
514 DestroyWindow(window);
515 return;
518 hr = IDirect3DDevice3_GetDirect3D(device, &d3d3);
519 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
521 memset(&vb_desc, 0, sizeof(vb_desc));
522 vb_desc.dwSize = sizeof(vb_desc);
523 vb_desc.dwFVF = D3DFVF_XYZ;
524 vb_desc.dwNumVertices = 3;
525 hr = IDirect3D3_CreateVertexBuffer(d3d3, &vb_desc, &src_vb, 0, NULL);
526 ok(SUCCEEDED(hr), "Failed to create source vertex buffer, hr %#x.\n", hr);
528 hr = IDirect3DVertexBuffer_Lock(src_vb, DDLOCK_WRITEONLY, (void **)&src_data, NULL);
529 ok(SUCCEEDED(hr), "Failed to lock source vertex buffer, hr %#x.\n", hr);
530 src_data[0].x = -1.0f;
531 src_data[0].y = -1.0f;
532 src_data[0].z = -1.0f;
533 src_data[1].x = 0.0f;
534 src_data[1].y = 0.0f;
535 src_data[1].z = 0.0f;
536 src_data[2].x = 1.0f;
537 src_data[2].y = 1.0f;
538 src_data[2].z = 1.0f;
539 hr = IDirect3DVertexBuffer_Unlock(src_vb);
540 ok(SUCCEEDED(hr), "Failed to unlock source vertex buffer, hr %#x.\n", hr);
542 memset(&vb_desc, 0, sizeof(vb_desc));
543 vb_desc.dwSize = sizeof(vb_desc);
544 vb_desc.dwFVF = D3DFVF_XYZRHW;
545 vb_desc.dwNumVertices = 3;
546 hr = IDirect3D3_CreateVertexBuffer(d3d3, &vb_desc, &dst_vb, 0, NULL);
547 ok(SUCCEEDED(hr), "Failed to create destination vertex buffer, hr %#x.\n", hr);
549 hr = IDirect3D3_CreateViewport(d3d3, &viewport, NULL);
550 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
551 hr = IDirect3DDevice3_AddViewport(device, viewport);
552 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
553 vp2.dwSize = sizeof(vp2);
554 vp2.dwX = 10;
555 vp2.dwY = 20;
556 vp2.dwWidth = 100;
557 vp2.dwHeight = 200;
558 vp2.dvClipX = 2.0f;
559 vp2.dvClipY = 3.0f;
560 vp2.dvClipWidth = 4.0f;
561 vp2.dvClipHeight = 5.0f;
562 vp2.dvMinZ = -2.0f;
563 vp2.dvMaxZ = 3.0f;
564 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2);
565 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
566 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
567 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
569 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
570 ok(SUCCEEDED(hr), "Failed to set world transformation, hr %#x.\n", hr);
571 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &identity);
572 ok(SUCCEEDED(hr), "Failed to set view transformation, hr %#x.\n", hr);
573 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity);
574 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
576 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
577 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
579 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
580 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
581 ok(compare_vec4(&dst_data[0], -6.500e+1f, +1.800e+2f, +2.000e-1f, +1.000e+0f, 4096),
582 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
583 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
584 ok(compare_vec4(&dst_data[1], -4.000e+1f, +1.400e+2f, +4.000e-1f, +1.000e+0f, 4096),
585 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
586 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
587 ok(compare_vec4(&dst_data[2], -1.500e+1f, +1.000e+2f, +6.000e-1f, +1.000e+0f, 4096),
588 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
589 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
590 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
591 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
593 hr = IDirect3DDevice3_MultiplyTransform(device, D3DTRANSFORMSTATE_PROJECTION, &projection);
594 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
596 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
597 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
599 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
600 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
601 ok(compare_vec4(&dst_data[0], +8.500e+1f, -1.000e+2f, +1.800e+0f, +1.000e+0f, 4096),
602 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
603 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
604 ok(compare_vec4(&dst_data[1], +1.100e+2f, -1.400e+2f, +2.000e+0f, +1.000e+0f, 4096),
605 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
606 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
607 ok(compare_vec4(&dst_data[2], +1.350e+2f, -1.800e+2f, +2.200e+0f, +1.000e+0f, 4096),
608 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
609 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
610 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
611 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
613 vp2.dwSize = sizeof(vp2);
614 vp2.dwX = 30;
615 vp2.dwY = 40;
616 vp2.dwWidth = 90;
617 vp2.dwHeight = 80;
618 vp2.dvClipX = 4.0f;
619 vp2.dvClipY = 6.0f;
620 vp2.dvClipWidth = 2.0f;
621 vp2.dvClipHeight = 4.0f;
622 vp2.dvMinZ = 3.0f;
623 vp2.dvMaxZ = -2.0f;
624 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2);
625 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
627 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
628 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
630 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
631 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
632 ok(compare_vec4(&dst_data[0], +7.500e+1f, +4.000e+1f, -8.000e-1f, +1.000e+0f, 4096),
633 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
634 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
635 ok(compare_vec4(&dst_data[1], +1.200e+2f, +2.000e+1f, -1.000e+0f, +1.000e+0f, 4096),
636 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
637 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
638 ok(compare_vec4(&dst_data[2], +1.650e+2f, +0.000e+0f, -1.200e+0f, +1.000e+0f, 4096),
639 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
640 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
641 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
642 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
644 vp1.dwSize = sizeof(vp1);
645 vp1.dwX = 30;
646 vp1.dwY = 40;
647 vp1.dwWidth = 90;
648 vp1.dwHeight = 80;
649 vp1.dvScaleX = 7.0f;
650 vp1.dvScaleY = 2.0f;
651 vp1.dvMaxX = 6.0f;
652 vp1.dvMaxY = 10.0f;
653 vp1.dvMinZ = -2.0f;
654 vp1.dvMaxZ = 3.0f;
655 hr = IDirect3DViewport3_SetViewport(viewport, &vp1);
656 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
658 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
659 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
661 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
662 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
663 ok(compare_vec4(&dst_data[0], +1.100e+2f, +6.800e+1f, +7.000e+0f, +1.000e+0f, 4096),
664 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
665 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
666 ok(compare_vec4(&dst_data[1], +1.170e+2f, +6.600e+1f, +8.000e+0f, +1.000e+0f, 4096),
667 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
668 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
669 ok(compare_vec4(&dst_data[2], +1.240e+2f, +6.400e+1f, +9.000e+0f, +1.000e+0f, 4096),
670 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
671 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
672 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
673 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
675 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
676 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
678 IDirect3DVertexBuffer_Release(dst_vb);
679 IDirect3DVertexBuffer_Release(src_vb);
680 IDirect3DViewport3_Release(viewport);
681 IDirect3D3_Release(d3d3);
682 IDirect3DDevice3_Release(device);
683 DestroyWindow(window);
686 static void test_coop_level_create_device_window(void)
688 HWND focus_window, device_window;
689 IDirectDraw4 *ddraw;
690 HRESULT hr;
692 focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
693 0, 0, 640, 480, 0, 0, 0, 0);
694 ddraw = create_ddraw();
695 ok(!!ddraw, "Failed to create a ddraw object.\n");
697 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
698 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
699 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
700 ok(!device_window, "Unexpected device window found.\n");
701 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
702 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
703 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
704 ok(!device_window, "Unexpected device window found.\n");
705 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
706 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
707 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
708 ok(!device_window, "Unexpected device window found.\n");
709 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
710 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
711 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
712 ok(!device_window, "Unexpected device window found.\n");
713 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
714 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
715 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
716 ok(!device_window, "Unexpected device window found.\n");
718 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
719 if (broken(hr == DDERR_INVALIDPARAMS))
721 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
722 IDirectDraw4_Release(ddraw);
723 DestroyWindow(focus_window);
724 return;
727 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
728 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
729 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
730 ok(!device_window, "Unexpected device window found.\n");
731 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
732 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
733 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
734 ok(!device_window, "Unexpected device window found.\n");
736 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
737 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
738 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
739 ok(!device_window, "Unexpected device window found.\n");
740 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
741 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
742 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
743 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
744 ok(!!device_window, "Device window not found.\n");
746 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
747 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
748 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
749 ok(!device_window, "Unexpected device window found.\n");
750 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
751 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
752 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
753 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
754 ok(!!device_window, "Device window not found.\n");
756 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
757 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
758 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
759 ok(!device_window, "Unexpected device window found.\n");
760 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
761 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
762 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
763 ok(!device_window, "Unexpected device window found.\n");
764 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
765 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
766 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
767 ok(!device_window, "Unexpected device window found.\n");
768 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
769 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
770 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
771 ok(!!device_window, "Device window not found.\n");
773 IDirectDraw4_Release(ddraw);
774 DestroyWindow(focus_window);
777 static void test_clipper_blt(void)
779 IDirectDrawSurface4 *src_surface, *dst_surface;
780 RECT client_rect, src_rect;
781 IDirectDrawClipper *clipper;
782 DDSURFACEDESC2 surface_desc;
783 unsigned int i, j, x, y;
784 IDirectDraw4 *ddraw;
785 RGNDATA *rgn_data;
786 D3DCOLOR color;
787 ULONG refcount;
788 HRGN r1, r2;
789 HWND window;
790 DDBLTFX fx;
791 HRESULT hr;
792 DWORD *ptr;
793 DWORD ret;
795 static const DWORD src_data[] =
797 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
798 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
799 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
801 static const D3DCOLOR expected1[] =
803 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
804 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
805 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
806 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
808 /* Nvidia on Windows seems to have an off-by-one error
809 * when processing source rectangles. Our left = 1 and
810 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
811 * read as well, but only for the edge pixels on the
812 * output image. The bug happens on the y axis as well,
813 * but we only read one row there, and all source rows
814 * contain the same data. This bug is not dependent on
815 * the presence of a clipper. */
816 static const D3DCOLOR expected1_broken[] =
818 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
819 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
820 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
821 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
823 static const D3DCOLOR expected2[] =
825 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
826 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
827 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
828 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
831 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
832 10, 10, 640, 480, 0, 0, 0, 0);
833 ShowWindow(window, SW_SHOW);
834 ddraw = create_ddraw();
835 ok(!!ddraw, "Failed to create a ddraw object.\n");
837 ret = GetClientRect(window, &client_rect);
838 ok(ret, "Failed to get client rect.\n");
839 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
840 ok(ret, "Failed to map client rect.\n");
842 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
843 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
845 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL);
846 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
847 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
848 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
849 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
850 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
851 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
852 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
853 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
854 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
855 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
856 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
857 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
858 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
859 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
860 "Got unexpected bounding rect %s, expected %s.\n",
861 wine_dbgstr_rect(&rgn_data->rdh.rcBound), wine_dbgstr_rect(&client_rect));
862 HeapFree(GetProcessHeap(), 0, rgn_data);
864 r1 = CreateRectRgn(0, 0, 320, 240);
865 ok(!!r1, "Failed to create region.\n");
866 r2 = CreateRectRgn(320, 240, 640, 480);
867 ok(!!r2, "Failed to create region.\n");
868 CombineRgn(r1, r1, r2, RGN_OR);
869 ret = GetRegionData(r1, 0, NULL);
870 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
871 ret = GetRegionData(r1, ret, rgn_data);
872 ok(!!ret, "Failed to get region data.\n");
874 DeleteObject(r2);
875 DeleteObject(r1);
877 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
878 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
879 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
880 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
881 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
882 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
884 HeapFree(GetProcessHeap(), 0, rgn_data);
886 memset(&surface_desc, 0, sizeof(surface_desc));
887 surface_desc.dwSize = sizeof(surface_desc);
888 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
889 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
890 surface_desc.dwWidth = 640;
891 surface_desc.dwHeight = 480;
892 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
893 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
894 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
895 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
896 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
897 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
899 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
900 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
901 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
902 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
904 memset(&fx, 0, sizeof(fx));
905 fx.dwSize = sizeof(fx);
906 hr = IDirectDrawSurface4_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
907 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
908 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
909 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
911 hr = IDirectDrawSurface4_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
912 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
913 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
914 ptr = surface_desc.lpSurface;
915 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
916 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
917 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
918 hr = IDirectDrawSurface4_Unlock(src_surface, NULL);
919 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
921 hr = IDirectDrawSurface4_SetClipper(dst_surface, clipper);
922 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
924 SetRect(&src_rect, 1, 1, 5, 2);
925 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
926 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
927 for (i = 0; i < 4; ++i)
929 for (j = 0; j < 4; ++j)
931 x = 80 * ((2 * j) + 1);
932 y = 60 * ((2 * i) + 1);
933 color = get_surface_color(dst_surface, x, y);
934 ok(compare_color(color, expected1[i * 4 + j], 1)
935 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
936 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
940 U5(fx).dwFillColor = 0xff0000ff;
941 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
942 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
943 for (i = 0; i < 4; ++i)
945 for (j = 0; j < 4; ++j)
947 x = 80 * ((2 * j) + 1);
948 y = 60 * ((2 * i) + 1);
949 color = get_surface_color(dst_surface, x, y);
950 ok(compare_color(color, expected2[i * 4 + j], 1),
951 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
955 hr = IDirectDrawSurface4_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
956 ok(hr == DDERR_BLTFASTCANTCLIP, "Got unexpected hr %#x.\n", hr);
958 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
959 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
960 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
961 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
962 DestroyWindow(window);
963 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
964 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
965 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
966 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
967 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
968 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
969 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
970 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
971 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
972 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
973 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
974 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
976 IDirectDrawSurface4_Release(dst_surface);
977 IDirectDrawSurface4_Release(src_surface);
978 refcount = IDirectDrawClipper_Release(clipper);
979 ok(!refcount, "Clipper has %u references left.\n", refcount);
980 IDirectDraw4_Release(ddraw);
983 static void test_coop_level_d3d_state(void)
985 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
986 IDirectDrawSurface4 *rt, *surface;
987 IDirect3DViewport3 *viewport;
988 IDirect3DDevice3 *device;
989 IDirectDraw4 *ddraw;
990 IDirect3D3 *d3d;
991 D3DCOLOR color;
992 DWORD value;
993 HWND window;
994 HRESULT hr;
996 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
997 0, 0, 640, 480, 0, 0, 0, 0);
998 if (!(device = create_device(window, DDSCL_NORMAL)))
1000 skip("Failed to create a 3D device, skipping test.\n");
1001 DestroyWindow(window);
1002 return;
1005 viewport = create_viewport(device, 0, 0, 640, 480);
1007 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1008 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1009 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
1010 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1011 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
1012 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1013 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1014 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
1015 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
1016 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
1017 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1018 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1019 color = get_surface_color(rt, 320, 240);
1020 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1022 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1023 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1024 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1025 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1026 IDirect3D3_Release(d3d);
1027 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1028 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1029 hr = IDirectDrawSurface4_IsLost(rt);
1030 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
1031 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
1032 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
1033 IDirectDraw4_Release(ddraw);
1035 hr = IDirect3DDevice3_GetRenderTarget(device, &surface);
1036 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1037 ok(surface == rt, "Got unexpected surface %p.\n", surface);
1038 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
1039 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1040 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
1041 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1042 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1043 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
1044 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
1045 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1046 color = get_surface_color(rt, 320, 240);
1047 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1049 destroy_viewport(device, viewport);
1050 IDirectDrawSurface4_Release(surface);
1051 IDirectDrawSurface4_Release(rt);
1052 IDirect3DDevice3_Release(device);
1053 DestroyWindow(window);
1056 static void test_surface_interface_mismatch(void)
1058 IDirectDraw4 *ddraw = NULL;
1059 IDirect3D3 *d3d = NULL;
1060 IDirectDrawSurface4 *surface = NULL, *ds;
1061 IDirectDrawSurface3 *surface3 = NULL;
1062 IDirect3DDevice3 *device = NULL;
1063 IDirect3DViewport3 *viewport = NULL;
1064 DDSURFACEDESC2 surface_desc;
1065 DDPIXELFORMAT z_fmt;
1066 ULONG refcount;
1067 HRESULT hr;
1068 D3DCOLOR color;
1069 HWND window;
1070 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1072 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1073 0, 0, 640, 480, 0, 0, 0, 0);
1074 ddraw = create_ddraw();
1075 ok(!!ddraw, "Failed to create a ddraw object.\n");
1076 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1077 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1079 memset(&surface_desc, 0, sizeof(surface_desc));
1080 surface_desc.dwSize = sizeof(surface_desc);
1081 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1082 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1083 surface_desc.dwWidth = 640;
1084 surface_desc.dwHeight = 480;
1086 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1087 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1089 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
1090 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface3, hr %#x.\n", hr);
1092 if (FAILED(IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
1094 skip("D3D interface is not available, skipping test.\n");
1095 goto cleanup;
1098 memset(&z_fmt, 0, sizeof(z_fmt));
1099 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
1100 if (FAILED(hr) || !z_fmt.dwSize)
1102 skip("No depth buffer formats available, skipping test.\n");
1103 goto cleanup;
1106 memset(&surface_desc, 0, sizeof(surface_desc));
1107 surface_desc.dwSize = sizeof(surface_desc);
1108 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
1109 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1110 U4(surface_desc).ddpfPixelFormat = z_fmt;
1111 surface_desc.dwWidth = 640;
1112 surface_desc.dwHeight = 480;
1113 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &ds, NULL);
1114 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
1115 if (FAILED(hr))
1116 goto cleanup;
1118 /* Using a different surface interface version still works */
1119 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
1120 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
1121 refcount = IDirectDrawSurface4_Release(ds);
1122 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
1123 if (FAILED(hr))
1124 goto cleanup;
1126 /* Here too */
1127 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface4 *)surface3, &device, NULL);
1128 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
1129 if (FAILED(hr))
1130 goto cleanup;
1132 viewport = create_viewport(device, 0, 0, 640, 480);
1134 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1135 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1136 color = get_surface_color(surface, 320, 240);
1137 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1139 cleanup:
1140 if (viewport)
1141 destroy_viewport(device, viewport);
1142 if (surface3) IDirectDrawSurface3_Release(surface3);
1143 if (surface) IDirectDrawSurface4_Release(surface);
1144 if (device) IDirect3DDevice3_Release(device);
1145 if (d3d) IDirect3D3_Release(d3d);
1146 if (ddraw) IDirectDraw4_Release(ddraw);
1147 DestroyWindow(window);
1150 static void test_coop_level_threaded(void)
1152 struct create_window_thread_param p;
1153 IDirectDraw4 *ddraw;
1154 HRESULT hr;
1156 ddraw = create_ddraw();
1157 ok(!!ddraw, "Failed to create a ddraw object.\n");
1158 create_window_thread(&p);
1160 hr = IDirectDraw4_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1161 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1163 IDirectDraw4_Release(ddraw);
1164 destroy_window_thread(&p);
1167 static void test_depth_blit(void)
1169 static struct
1171 float x, y, z;
1172 DWORD color;
1174 quad1[] =
1176 { -1.0, 1.0, 0.50f, 0xff00ff00},
1177 { 1.0, 1.0, 0.50f, 0xff00ff00},
1178 { -1.0, -1.0, 0.50f, 0xff00ff00},
1179 { 1.0, -1.0, 0.50f, 0xff00ff00},
1181 static const D3DCOLOR expected_colors[4][4] =
1183 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1184 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1185 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1186 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1188 DDSURFACEDESC2 ddsd_new, ddsd_existing;
1190 IDirect3DDevice3 *device;
1191 IDirectDrawSurface4 *ds1, *ds2, *ds3, *rt;
1192 IDirect3DViewport3 *viewport;
1193 RECT src_rect, dst_rect;
1194 unsigned int i, j;
1195 D3DCOLOR color;
1196 HRESULT hr;
1197 IDirect3D3 *d3d;
1198 IDirectDraw4 *ddraw;
1199 DDBLTFX fx;
1200 HWND window;
1201 D3DRECT d3drect;
1203 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1204 0, 0, 640, 480, 0, 0, 0, 0);
1205 if (!(device = create_device(window, DDSCL_NORMAL)))
1207 skip("Failed to create a 3D device, skipping test.\n");
1208 DestroyWindow(window);
1209 return;
1212 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1213 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
1214 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1215 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
1216 IDirect3D3_Release(d3d);
1218 ds1 = get_depth_stencil(device);
1220 memset(&ddsd_new, 0, sizeof(ddsd_new));
1221 ddsd_new.dwSize = sizeof(ddsd_new);
1222 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1223 ddsd_existing.dwSize = sizeof(ddsd_existing);
1224 hr = IDirectDrawSurface4_GetSurfaceDesc(ds1, &ddsd_existing);
1225 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
1226 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1227 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1228 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1229 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1230 U4(ddsd_new).ddpfPixelFormat = U4(ddsd_existing).ddpfPixelFormat;
1231 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1232 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1233 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1234 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1235 IDirectDraw4_Release(ddraw);
1237 viewport = create_viewport(device, 0, 0, ddsd_existing.dwWidth, ddsd_existing.dwHeight);
1238 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1239 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
1241 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1242 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
1243 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1244 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
1246 U1(d3drect).x1 = U2(d3drect).y1 = 0;
1247 U3(d3drect).x2 = ddsd_existing.dwWidth; U4(d3drect).y2 = ddsd_existing.dwHeight;
1248 hr = IDirect3DViewport3_Clear2(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
1249 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
1251 /* Partial blit. */
1252 SetRect(&src_rect, 0, 0, 320, 240);
1253 SetRect(&dst_rect, 0, 0, 320, 240);
1254 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1255 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1256 /* Different locations. */
1257 SetRect(&src_rect, 0, 0, 320, 240);
1258 SetRect(&dst_rect, 320, 240, 640, 480);
1259 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1260 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1261 /* Streched. */
1262 SetRect(&src_rect, 0, 0, 320, 240);
1263 SetRect(&dst_rect, 0, 0, 640, 480);
1264 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1265 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1266 /* Flipped. */
1267 SetRect(&src_rect, 0, 480, 640, 0);
1268 SetRect(&dst_rect, 0, 0, 640, 480);
1269 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1270 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1271 SetRect(&src_rect, 0, 0, 640, 480);
1272 SetRect(&dst_rect, 0, 480, 640, 0);
1273 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1274 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1275 /* Full, explicit. */
1276 SetRect(&src_rect, 0, 0, 640, 480);
1277 SetRect(&dst_rect, 0, 0, 640, 480);
1278 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1279 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1280 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1282 /* Depth blit inside a BeginScene / EndScene pair */
1283 hr = IDirect3DDevice3_BeginScene(device);
1284 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1285 /* From the current depth stencil */
1286 hr = IDirectDrawSurface4_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1287 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1288 /* To the current depth stencil */
1289 hr = IDirectDrawSurface4_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1290 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1291 /* Between unbound surfaces */
1292 hr = IDirectDrawSurface4_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1293 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1294 hr = IDirect3DDevice3_EndScene(device);
1295 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1297 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1298 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1299 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1300 * a reliable result(z = 0.0) */
1301 memset(&fx, 0, sizeof(fx));
1302 fx.dwSize = sizeof(fx);
1303 hr = IDirectDrawSurface4_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1304 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1306 hr = IDirect3DViewport3_Clear2(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
1307 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1308 SetRect(&dst_rect, 0, 0, 320, 240);
1309 hr = IDirectDrawSurface4_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1310 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1311 IDirectDrawSurface4_Release(ds3);
1312 IDirectDrawSurface4_Release(ds2);
1313 IDirectDrawSurface4_Release(ds1);
1315 hr = IDirect3DDevice3_BeginScene(device);
1316 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1317 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1318 quad1, 4, 0);
1319 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1320 hr = IDirect3DDevice3_EndScene(device);
1321 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1323 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1324 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1325 for (i = 0; i < 4; ++i)
1327 for (j = 0; j < 4; ++j)
1329 unsigned int x = 80 * ((2 * j) + 1);
1330 unsigned int y = 60 * ((2 * i) + 1);
1331 color = get_surface_color(rt, x, y);
1332 ok(compare_color(color, expected_colors[i][j], 1),
1333 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1336 IDirectDrawSurface4_Release(rt);
1338 destroy_viewport(device, viewport);
1339 IDirect3DDevice3_Release(device);
1340 DestroyWindow(window);
1343 static void test_texture_load_ckey(void)
1345 IDirectDraw4 *ddraw;
1346 IDirectDrawSurface4 *src;
1347 IDirectDrawSurface4 *dst;
1348 IDirect3DTexture2 *src_tex;
1349 IDirect3DTexture2 *dst_tex;
1350 DDSURFACEDESC2 ddsd;
1351 HRESULT hr;
1352 DDCOLORKEY ckey;
1354 ddraw = create_ddraw();
1355 ok(!!ddraw, "Failed to create a ddraw object.\n");
1356 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
1357 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1359 memset(&ddsd, 0, sizeof(ddsd));
1360 ddsd.dwSize = sizeof(ddsd);
1361 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1362 ddsd.dwHeight = 128;
1363 ddsd.dwWidth = 128;
1364 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1365 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &src, NULL);
1366 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1367 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1368 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &dst, NULL);
1369 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1371 hr = IDirectDrawSurface4_QueryInterface(src, &IID_IDirect3DTexture2, (void **)&src_tex);
1372 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get Direct3DTexture2 interface, hr %#x.\n", hr);
1373 if (FAILED(hr))
1375 /* 64 bit ddraw does not support d3d */
1376 skip("Could not get Direct3DTexture2 interface, skipping texture::Load color keying tests.\n");
1377 IDirectDrawSurface4_Release(dst);
1378 IDirectDrawSurface4_Release(src);
1379 IDirectDraw4_Release(ddraw);
1380 return;
1382 hr = IDirectDrawSurface4_QueryInterface(dst, &IID_IDirect3DTexture2, (void **)&dst_tex);
1383 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture2 interface, hr %#x.\n", hr);
1385 /* No surface has a color key */
1386 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1387 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1388 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1389 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1390 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1391 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1392 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1394 /* Source surface has a color key */
1395 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1396 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1397 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1398 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1399 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1400 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1401 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1402 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1403 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1405 /* Both surfaces have a color key: Dest ckey is overwritten */
1406 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1407 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1408 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1409 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1410 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1411 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1412 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1413 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1414 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1416 /* Only the destination has a color key: It is not deleted */
1417 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1418 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1419 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1420 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1421 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1422 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1423 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1424 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1425 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1426 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1428 IDirect3DTexture2_Release(dst_tex);
1429 IDirect3DTexture2_Release(src_tex);
1430 IDirectDrawSurface4_Release(dst);
1431 IDirectDrawSurface4_Release(src);
1432 IDirectDraw4_Release(ddraw);
1435 static ULONG get_refcount(IUnknown *test_iface)
1437 IUnknown_AddRef(test_iface);
1438 return IUnknown_Release(test_iface);
1441 static void test_viewport(void)
1443 IDirectDraw4 *ddraw;
1444 IDirect3D3 *d3d;
1445 HRESULT hr, old_d3d_ref;
1446 ULONG ref;
1447 IDirect3DViewport *viewport;
1448 IDirect3DViewport2 *viewport2;
1449 IDirect3DViewport3 *viewport3, *another_vp, *test_vp;
1450 IDirectDrawGammaControl *gamma;
1451 IUnknown *unknown;
1452 HWND window;
1453 IDirect3DDevice3 *device;
1455 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1456 0, 0, 640, 480, 0, 0, 0, 0);
1457 if (!(device = create_device(window, DDSCL_NORMAL)))
1459 skip("Failed to create a 3D device, skipping test.\n");
1460 DestroyWindow(window);
1461 return;
1463 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1464 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
1465 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1466 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
1467 old_d3d_ref = get_refcount((IUnknown *) d3d);
1469 hr = IDirect3D3_CreateViewport(d3d, &viewport3, NULL);
1470 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1471 ref = get_refcount((IUnknown *)viewport3);
1472 ok(ref == 1, "Initial IDirect3DViewport3 refcount is %u\n", ref);
1473 ref = get_refcount((IUnknown *)d3d);
1474 ok(ref == old_d3d_ref, "IDirect3D3 refcount is %u\n", ref);
1476 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1477 hr = IDirect3DViewport2_QueryInterface(viewport3, &IID_IDirectDrawGammaControl, (void **)&gamma);
1478 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
1479 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
1480 if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
1481 /* NULL iid: Segfaults */
1483 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IDirect3DViewport, (void **)&viewport);
1484 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport, hr %#x.\n", hr);
1485 if (viewport)
1487 ref = get_refcount((IUnknown *)viewport);
1488 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1489 ref = get_refcount((IUnknown *)viewport3);
1490 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1491 IDirect3DViewport_Release(viewport);
1492 viewport = NULL;
1495 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IDirect3DViewport3, (void **)&viewport2);
1496 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1497 if (viewport2)
1499 ref = get_refcount((IUnknown *)viewport2);
1500 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1501 ref = get_refcount((IUnknown *)viewport3);
1502 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1503 IDirect3DViewport3_Release(viewport2);
1506 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IUnknown, (void **)&unknown);
1507 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1508 if (unknown)
1510 ref = get_refcount((IUnknown *)viewport3);
1511 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1512 ref = get_refcount(unknown);
1513 ok(ref == 2, "IUnknown refcount is %u\n", ref);
1514 IUnknown_Release(unknown);
1517 /* AddViewport(NULL): Segfault */
1518 hr = IDirect3DDevice3_DeleteViewport(device, NULL);
1519 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1520 hr = IDirect3DDevice3_GetCurrentViewport(device, NULL);
1521 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1523 hr = IDirect3D3_CreateViewport(d3d, &another_vp, NULL);
1524 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1526 /* Setting a viewport not in the viewport list fails */
1527 hr = IDirect3DDevice3_SetCurrentViewport(device, another_vp);
1528 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1530 hr = IDirect3DDevice3_AddViewport(device, viewport3);
1531 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1532 ref = get_refcount((IUnknown *) viewport3);
1533 ok(ref == 2, "viewport3 refcount is %d\n", ref);
1534 hr = IDirect3DDevice3_AddViewport(device, another_vp);
1535 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1536 ref = get_refcount((IUnknown *) another_vp);
1537 ok(ref == 2, "another_vp refcount is %d\n", ref);
1539 test_vp = (IDirect3DViewport3 *) 0xbaadc0de;
1540 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1541 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1542 ok(test_vp == (IDirect3DViewport3 *) 0xbaadc0de, "Got unexpected pointer %p\n", test_vp);
1544 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport3);
1545 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1546 ref = get_refcount((IUnknown *) viewport3);
1547 ok(ref == 3, "viewport3 refcount is %d\n", ref);
1548 ref = get_refcount((IUnknown *) device);
1549 ok(ref == 1, "device refcount is %d\n", ref);
1551 test_vp = NULL;
1552 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1553 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1554 ok(test_vp == viewport3, "Got unexpected viewport %p\n", test_vp);
1555 ref = get_refcount((IUnknown *) viewport3);
1556 ok(ref == 4, "viewport3 refcount is %d\n", ref);
1557 if(test_vp) IDirect3DViewport3_Release(test_vp);
1559 /* GetCurrentViewport with a viewport set and NULL input param: Segfault */
1561 /* Cannot set the viewport to NULL */
1562 hr = IDirect3DDevice3_SetCurrentViewport(device, NULL);
1563 ok(hr == DDERR_INVALIDPARAMS, "Failed to set viewport to NULL, hr %#x.\n", hr);
1564 test_vp = NULL;
1565 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1566 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1567 ok(test_vp == viewport3, "Got unexpected viewport %p\n", test_vp);
1568 if(test_vp) IDirect3DViewport3_Release(test_vp);
1570 /* SetCurrentViewport properly releases the old viewport's reference */
1571 hr = IDirect3DDevice3_SetCurrentViewport(device, another_vp);
1572 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1573 ref = get_refcount((IUnknown *) viewport3);
1574 ok(ref == 2, "viewport3 refcount is %d\n", ref);
1575 ref = get_refcount((IUnknown *) another_vp);
1576 ok(ref == 3, "another_vp refcount is %d\n", ref);
1578 /* Unlike device2::DeleteViewport, device3::DeleteViewport releases the
1579 * reference held by SetCurrentViewport */
1580 hr = IDirect3DDevice3_DeleteViewport(device, another_vp);
1581 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1582 ref = get_refcount((IUnknown *) another_vp);
1583 ok(ref == 1, "another_vp refcount is %d\n", ref);
1585 /* GetCurrentViewport still fails */
1586 test_vp = NULL;
1587 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1588 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1589 ok(test_vp == NULL, "Got unexpected viewport %p\n", test_vp);
1590 if(test_vp) IDirect3DViewport3_Release(test_vp);
1592 /* Setting a different viewport doesn't have any surprises now */
1593 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport3);
1594 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1595 ref = get_refcount((IUnknown *) viewport3);
1596 ok(ref == 3, "viewport3 refcount is %d\n", ref);
1597 ref = get_refcount((IUnknown *) another_vp);
1598 ok(ref == 1, "another_vp refcount is %d\n", ref);
1600 /* Destroying the device removes the viewport and releases the reference */
1601 IDirect3DDevice3_Release(device);
1602 ref = get_refcount((IUnknown *) viewport3);
1603 ok(ref == 1, "viewport3 refcount is %d\n", ref);
1605 ref = IDirect3DViewport3_Release(another_vp);
1606 ok(ref == 0, "Got unexpected ref %d\n", ref);
1607 ref = IDirect3DViewport3_Release(viewport3);
1608 ok(ref == 0, "Got unexpected ref %d\n", ref);
1609 IDirect3D3_Release(d3d);
1610 DestroyWindow(window);
1611 IDirectDraw4_Release(ddraw);
1614 static void test_zenable(void)
1616 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1617 static struct
1619 struct vec4 position;
1620 D3DCOLOR diffuse;
1622 tquad[] =
1624 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xff00ff00},
1625 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xff00ff00},
1626 {{640.0f, 480.0f, 1.5f, 1.0f}, 0xff00ff00},
1627 {{640.0f, 0.0f, 1.5f, 1.0f}, 0xff00ff00},
1629 IDirect3DViewport3 *viewport;
1630 IDirect3DDevice3 *device;
1631 IDirectDrawSurface4 *rt;
1632 D3DCOLOR color;
1633 HWND window;
1634 HRESULT hr;
1635 UINT x, y;
1636 UINT i, j;
1638 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1639 0, 0, 640, 480, 0, 0, 0, 0);
1640 if (!(device = create_device(window, DDSCL_NORMAL)))
1642 skip("Failed to create a 3D device, skipping test.\n");
1643 DestroyWindow(window);
1644 return;
1647 viewport = create_viewport(device, 0, 0, 640, 480);
1648 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1649 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1651 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1652 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1654 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0f, 0);
1655 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1656 hr = IDirect3DDevice3_BeginScene(device);
1657 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1658 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, tquad, 4, 0);
1659 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1660 hr = IDirect3DDevice3_EndScene(device);
1661 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1663 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1664 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1665 for (i = 0; i < 4; ++i)
1667 for (j = 0; j < 4; ++j)
1669 x = 80 * ((2 * j) + 1);
1670 y = 60 * ((2 * i) + 1);
1671 color = get_surface_color(rt, x, y);
1672 ok(compare_color(color, 0x0000ff00, 1),
1673 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1676 IDirectDrawSurface4_Release(rt);
1678 destroy_viewport(device, viewport);
1679 IDirect3DDevice3_Release(device);
1680 DestroyWindow(window);
1683 static void test_ck_rgba(void)
1685 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1686 static struct
1688 struct vec4 position;
1689 struct vec2 texcoord;
1691 tquad[] =
1693 {{ 0.0f, 480.0f, 0.25f, 1.0f}, {0.0f, 0.0f}},
1694 {{ 0.0f, 0.0f, 0.25f, 1.0f}, {0.0f, 1.0f}},
1695 {{640.0f, 480.0f, 0.25f, 1.0f}, {1.0f, 0.0f}},
1696 {{640.0f, 0.0f, 0.25f, 1.0f}, {1.0f, 1.0f}},
1697 {{ 0.0f, 480.0f, 0.75f, 1.0f}, {0.0f, 0.0f}},
1698 {{ 0.0f, 0.0f, 0.75f, 1.0f}, {0.0f, 1.0f}},
1699 {{640.0f, 480.0f, 0.75f, 1.0f}, {1.0f, 0.0f}},
1700 {{640.0f, 0.0f, 0.75f, 1.0f}, {1.0f, 1.0f}},
1702 static const struct
1704 D3DCOLOR fill_color;
1705 BOOL color_key;
1706 BOOL blend;
1707 D3DCOLOR result1, result1_broken;
1708 D3DCOLOR result2, result2_broken;
1710 tests[] =
1712 /* r200 on Windows doesn't check the alpha component when applying the color
1713 * key, so the key matches on every texel. */
1714 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1715 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1716 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1717 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1718 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00ff0000, 0x00807f00, 0x000000ff},
1719 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x00ff0000, 0x0000ff00, 0x000000ff},
1720 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00, 0x00807f00, 0x00807f00},
1721 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1724 IDirectDrawSurface4 *surface;
1725 IDirect3DViewport3 *viewport;
1726 DDSURFACEDESC2 surface_desc;
1727 IDirect3DTexture2 *texture;
1728 IDirect3DDevice3 *device;
1729 IDirectDrawSurface4 *rt;
1730 IDirectDraw4 *ddraw;
1731 IDirect3D3 *d3d;
1732 D3DCOLOR color;
1733 HWND window;
1734 DDBLTFX fx;
1735 HRESULT hr;
1736 UINT i;
1738 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1739 0, 0, 640, 480, 0, 0, 0, 0);
1740 if (!(device = create_device(window, DDSCL_NORMAL)))
1742 skip("Failed to create a 3D device, skipping test.\n");
1743 DestroyWindow(window);
1744 return;
1747 viewport = create_viewport(device, 0, 0, 640, 480);
1748 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1749 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1751 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1752 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1753 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1754 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1755 IDirect3D3_Release(d3d);
1757 memset(&surface_desc, 0, sizeof(surface_desc));
1758 surface_desc.dwSize = sizeof(surface_desc);
1759 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1760 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1761 surface_desc.dwWidth = 256;
1762 surface_desc.dwHeight = 256;
1763 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1764 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1765 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1766 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1767 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1768 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1769 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1770 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1771 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1772 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1773 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1774 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1775 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1777 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
1778 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1779 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1780 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1781 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1782 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1784 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1785 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1787 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1789 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1790 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1791 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1792 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1794 memset(&fx, 0, sizeof(fx));
1795 fx.dwSize = sizeof(fx);
1796 U5(fx).dwFillColor = tests[i].fill_color;
1797 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1798 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1800 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect,
1801 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
1802 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1803 hr = IDirect3DDevice3_BeginScene(device);
1804 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1805 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1806 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1807 hr = IDirect3DDevice3_EndScene(device);
1808 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1810 color = get_surface_color(rt, 320, 240);
1811 ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
1812 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1813 tests[i].result1, i, color);
1815 U5(fx).dwFillColor = 0xff0000ff;
1816 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1817 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1819 hr = IDirect3DDevice3_BeginScene(device);
1820 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1821 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[4], 4, 0);
1822 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1823 hr = IDirect3DDevice3_EndScene(device);
1824 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1826 /* This tests that fragments that are masked out by the color key are
1827 * discarded, instead of just fully transparent. */
1828 color = get_surface_color(rt, 320, 240);
1829 ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
1830 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1831 tests[i].result2, i, color);
1834 IDirectDrawSurface4_Release(rt);
1835 IDirect3DTexture2_Release(texture);
1836 IDirectDrawSurface4_Release(surface);
1837 destroy_viewport(device, viewport);
1838 IDirectDraw4_Release(ddraw);
1839 IDirect3DDevice3_Release(device);
1840 DestroyWindow(window);
1843 static void test_ck_default(void)
1845 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1846 static struct
1848 struct vec4 position;
1849 struct vec2 texcoord;
1851 tquad[] =
1853 {{ 0.0f, 480.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
1854 {{ 0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
1855 {{640.0f, 480.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
1856 {{640.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
1858 IDirectDrawSurface4 *surface, *rt;
1859 IDirect3DViewport3 *viewport;
1860 DDSURFACEDESC2 surface_desc;
1861 IDirect3DTexture2 *texture;
1862 IDirect3DDevice3 *device;
1863 IDirectDraw4 *ddraw;
1864 IDirect3D3 *d3d;
1865 D3DCOLOR color;
1866 DWORD value;
1867 HWND window;
1868 DDBLTFX fx;
1869 HRESULT hr;
1871 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1872 0, 0, 640, 480, 0, 0, 0, 0);
1874 if (!(device = create_device(window, DDSCL_NORMAL)))
1876 skip("Failed to create a 3D device, skipping test.\n");
1877 DestroyWindow(window);
1878 return;
1881 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1882 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1883 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1884 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1885 IDirect3D3_Release(d3d);
1887 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1888 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1890 viewport = create_viewport(device, 0, 0, 640, 480);
1891 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1892 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1894 memset(&surface_desc, 0, sizeof(surface_desc));
1895 surface_desc.dwSize = sizeof(surface_desc);
1896 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1897 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1898 surface_desc.dwWidth = 256;
1899 surface_desc.dwHeight = 256;
1900 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1901 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
1902 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1903 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1904 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1905 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1906 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1907 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1908 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1909 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1910 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1911 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1912 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
1913 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1915 memset(&fx, 0, sizeof(fx));
1916 fx.dwSize = sizeof(fx);
1917 U5(fx).dwFillColor = 0x000000ff;
1918 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1919 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1921 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1922 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1923 hr = IDirect3DDevice3_BeginScene(device);
1924 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1925 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1926 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1927 ok(!value, "Got unexpected color keying state %#x.\n", value);
1928 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1929 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1930 hr = IDirect3DDevice3_EndScene(device);
1931 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1932 color = get_surface_color(rt, 320, 240);
1933 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1935 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1936 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1937 hr = IDirect3DDevice3_BeginScene(device);
1938 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1939 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1940 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1941 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1942 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1943 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1944 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1945 ok(!!value, "Got unexpected color keying state %#x.\n", value);
1946 hr = IDirect3DDevice3_EndScene(device);
1947 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1948 color = get_surface_color(rt, 320, 240);
1949 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1951 IDirect3DTexture_Release(texture);
1952 IDirectDrawSurface4_Release(surface);
1953 destroy_viewport(device, viewport);
1954 IDirectDrawSurface4_Release(rt);
1955 IDirect3DDevice3_Release(device);
1956 IDirectDraw4_Release(ddraw);
1957 DestroyWindow(window);
1960 static void test_ck_complex(void)
1962 IDirectDrawSurface4 *surface, *mipmap, *tmp;
1963 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
1964 DDSURFACEDESC2 surface_desc;
1965 IDirect3DDevice3 *device;
1966 DDCOLORKEY color_key;
1967 IDirectDraw4 *ddraw;
1968 IDirect3D3 *d3d;
1969 unsigned int i;
1970 ULONG refcount;
1971 HWND window;
1972 HRESULT hr;
1974 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1975 0, 0, 640, 480, 0, 0, 0, 0);
1976 if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
1978 skip("Failed to create a 3D device, skipping test.\n");
1979 DestroyWindow(window);
1980 return;
1982 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1983 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1984 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1985 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1986 IDirect3D3_Release(d3d);
1988 memset(&surface_desc, 0, sizeof(surface_desc));
1989 surface_desc.dwSize = sizeof(surface_desc);
1990 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1991 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1992 surface_desc.dwWidth = 128;
1993 surface_desc.dwHeight = 128;
1994 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1995 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1997 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1998 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1999 color_key.dwColorSpaceLowValue = 0x0000ff00;
2000 color_key.dwColorSpaceHighValue = 0x0000ff00;
2001 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2002 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2003 memset(&color_key, 0, sizeof(color_key));
2004 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2005 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2006 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2007 color_key.dwColorSpaceLowValue);
2008 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2009 color_key.dwColorSpaceHighValue);
2011 mipmap = surface;
2012 IDirectDrawSurface_AddRef(mipmap);
2013 for (i = 0; i < 7; ++i)
2015 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
2016 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
2018 hr = IDirectDrawSurface4_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2019 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
2020 color_key.dwColorSpaceLowValue = 0x000000ff;
2021 color_key.dwColorSpaceHighValue = 0x000000ff;
2022 hr = IDirectDrawSurface4_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2023 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x, i %u.\n", hr, i);
2024 memset(&color_key, 0, sizeof(color_key));
2025 hr = IDirectDrawSurface4_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2026 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x, i %u.\n", hr, i);
2027 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
2028 color_key.dwColorSpaceLowValue, i);
2029 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
2030 color_key.dwColorSpaceHighValue, i);
2032 IDirectDrawSurface_Release(mipmap);
2033 mipmap = tmp;
2036 memset(&color_key, 0, sizeof(color_key));
2037 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2038 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2039 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2040 color_key.dwColorSpaceLowValue);
2041 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2042 color_key.dwColorSpaceHighValue);
2044 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
2045 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
2046 IDirectDrawSurface_Release(mipmap);
2047 refcount = IDirectDrawSurface4_Release(surface);
2048 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2050 memset(&surface_desc, 0, sizeof(surface_desc));
2051 surface_desc.dwSize = sizeof(surface_desc);
2052 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
2053 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
2054 U5(surface_desc).dwBackBufferCount = 1;
2055 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2056 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2058 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2059 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
2060 color_key.dwColorSpaceLowValue = 0x0000ff00;
2061 color_key.dwColorSpaceHighValue = 0x0000ff00;
2062 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2063 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2064 memset(&color_key, 0, sizeof(color_key));
2065 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2066 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2067 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2068 color_key.dwColorSpaceLowValue);
2069 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2070 color_key.dwColorSpaceHighValue);
2072 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &tmp);
2073 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
2075 hr = IDirectDrawSurface4_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2076 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
2077 color_key.dwColorSpaceLowValue = 0x0000ff00;
2078 color_key.dwColorSpaceHighValue = 0x0000ff00;
2079 hr = IDirectDrawSurface4_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2080 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2081 memset(&color_key, 0, sizeof(color_key));
2082 hr = IDirectDrawSurface4_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2083 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2084 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2085 color_key.dwColorSpaceLowValue);
2086 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2087 color_key.dwColorSpaceHighValue);
2089 IDirectDrawSurface_Release(tmp);
2091 refcount = IDirectDrawSurface4_Release(surface);
2092 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2093 IDirectDraw4_Release(ddraw);
2094 refcount = IDirect3DDevice3_Release(device);
2095 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2096 DestroyWindow(window);
2099 struct qi_test
2101 REFIID iid;
2102 REFIID refcount_iid;
2103 HRESULT hr;
2106 static void test_qi(const char *test_name, IUnknown *base_iface,
2107 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
2109 ULONG refcount, expected_refcount;
2110 IUnknown *iface1, *iface2;
2111 HRESULT hr;
2112 UINT i, j;
2114 for (i = 0; i < entry_count; ++i)
2116 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
2117 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
2118 if (SUCCEEDED(hr))
2120 for (j = 0; j < entry_count; ++j)
2122 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
2123 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
2124 if (SUCCEEDED(hr))
2126 expected_refcount = 0;
2127 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
2128 ++expected_refcount;
2129 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
2130 ++expected_refcount;
2131 refcount = IUnknown_Release(iface2);
2132 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
2133 refcount, test_name, i, j, expected_refcount);
2137 expected_refcount = 0;
2138 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
2139 ++expected_refcount;
2140 refcount = IUnknown_Release(iface1);
2141 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
2142 refcount, test_name, i, expected_refcount);
2147 static void test_surface_qi(void)
2149 static const struct qi_test tests[] =
2151 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface4, S_OK },
2152 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface4, S_OK },
2153 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
2154 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2155 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
2156 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
2157 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
2158 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
2159 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
2160 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
2161 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
2162 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
2163 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
2164 {&IID_IDirect3D7, NULL, E_INVALIDARG },
2165 {&IID_IDirect3D3, NULL, E_INVALIDARG },
2166 {&IID_IDirect3D2, NULL, E_INVALIDARG },
2167 {&IID_IDirect3D, NULL, E_INVALIDARG },
2168 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
2169 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
2170 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
2171 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
2172 {&IID_IDirectDraw, NULL, E_INVALIDARG },
2173 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
2174 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
2175 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
2176 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
2177 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
2178 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
2179 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
2180 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
2181 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
2182 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
2183 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
2184 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
2185 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
2188 IDirectDrawSurface4 *surface;
2189 DDSURFACEDESC2 surface_desc;
2190 IDirect3DDevice3 *device;
2191 IDirectDraw4 *ddraw;
2192 HWND window;
2193 HRESULT hr;
2195 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
2197 win_skip("DirectDrawCreateEx not available, skipping test.\n");
2198 return;
2201 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2202 0, 0, 640, 480, 0, 0, 0, 0);
2203 /* Try to create a D3D device to see if the ddraw implementation supports
2204 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
2205 * doesn't support e.g. the IDirect3DTexture interfaces. */
2206 if (!(device = create_device(window, DDSCL_NORMAL)))
2208 skip("Failed to create a 3D device, skipping test.\n");
2209 DestroyWindow(window);
2210 return;
2212 IDirect3DDevice_Release(device);
2213 ddraw = create_ddraw();
2214 ok(!!ddraw, "Failed to create a ddraw object.\n");
2215 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2216 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2218 memset(&surface_desc, 0, sizeof(surface_desc));
2219 surface_desc.dwSize = sizeof(surface_desc);
2220 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2221 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2222 surface_desc.dwWidth = 512;
2223 surface_desc.dwHeight = 512;
2224 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2225 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2227 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface4, tests, sizeof(tests) / sizeof(*tests));
2229 IDirectDrawSurface4_Release(surface);
2230 IDirectDraw4_Release(ddraw);
2231 DestroyWindow(window);
2234 static void test_device_qi(void)
2236 static const struct qi_test tests[] =
2238 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
2239 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
2240 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
2241 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2242 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
2243 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
2244 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
2245 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
2246 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
2247 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
2248 {&IID_IDirect3DDevice3, &IID_IDirect3DDevice3, S_OK },
2249 {&IID_IDirect3DDevice2, &IID_IDirect3DDevice3, S_OK },
2250 {&IID_IDirect3DDevice, &IID_IDirect3DDevice3, S_OK },
2251 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2252 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2253 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2254 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2255 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2256 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2257 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2258 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2259 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2260 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2261 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2262 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2263 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2264 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2265 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2266 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2267 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2268 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2269 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2270 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2271 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2272 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2273 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2274 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2275 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2276 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2277 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2278 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2279 {&IID_IUnknown, &IID_IDirect3DDevice3, S_OK },
2282 IDirect3DDevice3 *device;
2283 HWND window;
2285 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2286 0, 0, 640, 480, 0, 0, 0, 0);
2287 if (!(device = create_device(window, DDSCL_NORMAL)))
2289 skip("Failed to create a 3D device, skipping test.\n");
2290 DestroyWindow(window);
2291 return;
2294 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice3, tests, sizeof(tests) / sizeof(*tests));
2296 IDirect3DDevice3_Release(device);
2297 DestroyWindow(window);
2300 static void test_wndproc(void)
2302 LONG_PTR proc, ddraw_proc;
2303 IDirectDraw4 *ddraw;
2304 WNDCLASSA wc = {0};
2305 HWND window;
2306 HRESULT hr;
2307 ULONG ref;
2309 static struct message messages[] =
2311 {WM_WINDOWPOSCHANGING, FALSE, 0},
2312 {WM_MOVE, FALSE, 0},
2313 {WM_SIZE, FALSE, 0},
2314 {WM_WINDOWPOSCHANGING, FALSE, 0},
2315 {WM_ACTIVATE, FALSE, 0},
2316 {WM_SETFOCUS, FALSE, 0},
2317 {0, FALSE, 0},
2320 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2321 ddraw = create_ddraw();
2322 ok(!!ddraw, "Failed to create a ddraw object.\n");
2324 wc.lpfnWndProc = test_proc;
2325 wc.lpszClassName = "ddraw_test_wndproc_wc";
2326 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2328 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2329 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
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 expect_messages = messages;
2335 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2336 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2337 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2338 expect_messages = NULL;
2339 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2340 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2341 (LONG_PTR)test_proc, proc);
2342 ref = IDirectDraw4_Release(ddraw);
2343 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2344 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2345 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2346 (LONG_PTR)test_proc, proc);
2348 /* DDSCL_NORMAL doesn't. */
2349 ddraw = create_ddraw();
2350 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2351 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2352 (LONG_PTR)test_proc, proc);
2353 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2354 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2355 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2356 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2357 (LONG_PTR)test_proc, proc);
2358 ref = IDirectDraw4_Release(ddraw);
2359 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2360 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2361 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2362 (LONG_PTR)test_proc, proc);
2364 /* The original window proc is only restored by ddraw if the current
2365 * window proc matches the one ddraw set. This also affects switching
2366 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2367 ddraw = create_ddraw();
2368 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2369 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2370 (LONG_PTR)test_proc, proc);
2371 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2372 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2373 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2374 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2375 (LONG_PTR)test_proc, proc);
2376 ddraw_proc = proc;
2377 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2378 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2379 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2380 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2381 (LONG_PTR)test_proc, proc);
2382 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2383 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2384 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2385 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2386 (LONG_PTR)test_proc, proc);
2387 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2388 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2389 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2390 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2391 (LONG_PTR)DefWindowProcA, proc);
2392 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2393 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2394 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
2395 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2396 (LONG_PTR)DefWindowProcA, proc);
2397 ref = IDirectDraw4_Release(ddraw);
2398 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2399 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2400 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2401 (LONG_PTR)test_proc, proc);
2403 ddraw = create_ddraw();
2404 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2405 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2406 (LONG_PTR)test_proc, proc);
2407 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2408 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2409 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2410 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2411 (LONG_PTR)test_proc, proc);
2412 ref = IDirectDraw4_Release(ddraw);
2413 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2414 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2415 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2416 (LONG_PTR)DefWindowProcA, proc);
2418 fix_wndproc(window, (LONG_PTR)test_proc);
2419 expect_messages = NULL;
2420 DestroyWindow(window);
2421 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2424 static void test_window_style(void)
2426 LONG style, exstyle, tmp, expected_style;
2427 RECT fullscreen_rect, r;
2428 IDirectDraw4 *ddraw;
2429 HWND window;
2430 HRESULT hr;
2431 ULONG ref;
2432 BOOL ret;
2434 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2435 0, 0, 100, 100, 0, 0, 0, 0);
2436 ddraw = create_ddraw();
2437 ok(!!ddraw, "Failed to create a ddraw object.\n");
2439 style = GetWindowLongA(window, GWL_STYLE);
2440 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2441 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2443 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2444 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2446 tmp = GetWindowLongA(window, GWL_STYLE);
2447 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2448 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2449 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2451 GetWindowRect(window, &r);
2452 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2453 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2454 GetClientRect(window, &r);
2455 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2457 ret = SetForegroundWindow(GetDesktopWindow());
2458 ok(ret, "Failed to set foreground window.\n");
2460 tmp = GetWindowLongA(window, GWL_STYLE);
2461 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2462 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2463 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2465 ret = SetForegroundWindow(window);
2466 ok(ret, "Failed to set foreground window.\n");
2467 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2468 * the next tests expect this. */
2469 ShowWindow(window, SW_HIDE);
2471 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2472 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2474 tmp = GetWindowLongA(window, GWL_STYLE);
2475 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2476 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2477 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2479 ShowWindow(window, SW_SHOW);
2480 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2481 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2483 tmp = GetWindowLongA(window, GWL_STYLE);
2484 expected_style = style | WS_VISIBLE;
2485 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2486 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2487 expected_style = exstyle | WS_EX_TOPMOST;
2488 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2490 ret = SetForegroundWindow(GetDesktopWindow());
2491 ok(ret, "Failed to set foreground window.\n");
2492 tmp = GetWindowLongA(window, GWL_STYLE);
2493 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
2494 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2495 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2496 expected_style = exstyle | WS_EX_TOPMOST;
2497 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2499 ref = IDirectDraw4_Release(ddraw);
2500 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2502 DestroyWindow(window);
2505 static void test_redundant_mode_set(void)
2507 DDSURFACEDESC2 surface_desc = {0};
2508 IDirectDraw4 *ddraw;
2509 HWND window;
2510 HRESULT hr;
2511 RECT r, s;
2512 ULONG ref;
2514 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2515 0, 0, 100, 100, 0, 0, 0, 0);
2516 ddraw = create_ddraw();
2517 ok(!!ddraw, "Failed to create a ddraw object.\n");
2519 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2520 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2522 surface_desc.dwSize = sizeof(surface_desc);
2523 hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc);
2524 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
2526 hr = IDirectDraw4_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2527 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2528 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2530 GetWindowRect(window, &r);
2531 r.right /= 2;
2532 r.bottom /= 2;
2533 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2534 GetWindowRect(window, &s);
2535 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2537 hr = IDirectDraw4_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2538 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2539 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2541 GetWindowRect(window, &s);
2542 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2544 ref = IDirectDraw4_Release(ddraw);
2545 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2547 DestroyWindow(window);
2550 static SIZE screen_size, screen_size2;
2552 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2554 if (message == WM_SIZE)
2556 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2557 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2560 return test_proc(hwnd, message, wparam, lparam);
2563 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2565 if (message == WM_SIZE)
2567 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
2568 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
2571 return test_proc(hwnd, message, wparam, lparam);
2574 struct test_coop_level_mode_set_enum_param
2576 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
2579 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC2 *surface_desc, void *context)
2581 struct test_coop_level_mode_set_enum_param *param = context;
2583 if (U1(U4(*surface_desc).ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
2584 return DDENUMRET_OK;
2585 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
2586 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
2587 return DDENUMRET_OK;
2589 if (!param->ddraw_width)
2591 param->ddraw_width = surface_desc->dwWidth;
2592 param->ddraw_height = surface_desc->dwHeight;
2593 return DDENUMRET_OK;
2595 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
2596 return DDENUMRET_OK;
2598 param->user32_width = surface_desc->dwWidth;
2599 param->user32_height = surface_desc->dwHeight;
2600 return DDENUMRET_CANCEL;
2603 static void test_coop_level_mode_set(void)
2605 IDirectDrawSurface4 *primary;
2606 RECT registry_rect, ddraw_rect, user32_rect, r;
2607 IDirectDraw4 *ddraw;
2608 DDSURFACEDESC2 ddsd;
2609 WNDCLASSA wc = {0};
2610 HWND window, window2;
2611 HRESULT hr;
2612 ULONG ref;
2613 MSG msg;
2614 struct test_coop_level_mode_set_enum_param param;
2615 DEVMODEW devmode;
2616 BOOL ret;
2617 LONG change_ret;
2619 static const struct message exclusive_messages[] =
2621 {WM_WINDOWPOSCHANGING, FALSE, 0},
2622 {WM_WINDOWPOSCHANGED, FALSE, 0},
2623 {WM_SIZE, FALSE, 0},
2624 {WM_DISPLAYCHANGE, FALSE, 0},
2625 {0, FALSE, 0},
2627 static const struct message exclusive_focus_loss_messages[] =
2629 {WM_ACTIVATE, TRUE, WA_INACTIVE},
2630 {WM_DISPLAYCHANGE, FALSE, 0},
2631 {WM_WINDOWPOSCHANGING, FALSE, 0},
2632 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
2633 * SW_MINIMIZED, causing a recursive window activation that does not
2634 * produce the same result in Wine yet. Ignore the difference for now.
2635 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
2636 {WM_WINDOWPOSCHANGED, FALSE, 0},
2637 {WM_MOVE, FALSE, 0},
2638 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2639 {WM_ACTIVATEAPP, TRUE, FALSE},
2640 {0, FALSE, 0},
2642 static const struct message exclusive_focus_restore_messages[] =
2644 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
2645 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
2646 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
2647 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
2648 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
2649 /* Native redundantly sets the window size here. */
2650 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
2651 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
2652 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
2653 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
2654 {0, FALSE, 0},
2656 static const struct message sc_restore_messages[] =
2658 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
2659 {WM_WINDOWPOSCHANGING, FALSE, 0},
2660 {WM_WINDOWPOSCHANGED, FALSE, 0},
2661 {WM_SIZE, TRUE, SIZE_RESTORED},
2662 {0, FALSE, 0},
2664 static const struct message sc_minimize_messages[] =
2666 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
2667 {WM_WINDOWPOSCHANGING, FALSE, 0},
2668 {WM_WINDOWPOSCHANGED, FALSE, 0},
2669 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2670 {0, FALSE, 0},
2672 static const struct message sc_maximize_messages[] =
2674 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
2675 {WM_WINDOWPOSCHANGING, FALSE, 0},
2676 {WM_WINDOWPOSCHANGED, FALSE, 0},
2677 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
2678 {0, FALSE, 0},
2681 static const struct message normal_messages[] =
2683 {WM_DISPLAYCHANGE, FALSE, 0},
2684 {0, FALSE, 0},
2687 ddraw = create_ddraw();
2688 ok(!!ddraw, "Failed to create a ddraw object.\n");
2690 memset(&param, 0, sizeof(param));
2691 hr = IDirectDraw4_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
2692 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2693 ref = IDirectDraw4_Release(ddraw);
2694 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2696 if (!param.user32_height)
2698 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
2699 return;
2702 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2703 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
2704 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
2706 memset(&devmode, 0, sizeof(devmode));
2707 devmode.dmSize = sizeof(devmode);
2708 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2709 devmode.dmPelsWidth = param.user32_width;
2710 devmode.dmPelsHeight = param.user32_height;
2711 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2712 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2714 ddraw = create_ddraw();
2715 ok(!!ddraw, "Failed to create a ddraw object.\n");
2717 wc.lpfnWndProc = mode_set_proc;
2718 wc.lpszClassName = "ddraw_test_wndproc_wc";
2719 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2720 wc.lpfnWndProc = mode_set_proc2;
2721 wc.lpszClassName = "ddraw_test_wndproc_wc2";
2722 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2724 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2725 0, 0, 100, 100, 0, 0, 0, 0);
2726 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
2727 0, 0, 100, 100, 0, 0, 0, 0);
2729 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2730 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2732 GetWindowRect(window, &r);
2733 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2734 wine_dbgstr_rect(&r));
2736 memset(&ddsd, 0, sizeof(ddsd));
2737 ddsd.dwSize = sizeof(ddsd);
2738 ddsd.dwFlags = DDSD_CAPS;
2739 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2741 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2742 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2743 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2744 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2745 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2746 param.user32_width, ddsd.dwWidth);
2747 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2748 param.user32_height, ddsd.dwHeight);
2750 GetWindowRect(window, &r);
2751 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2752 wine_dbgstr_rect(&r));
2754 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2755 expect_messages = exclusive_messages;
2756 screen_size.cx = 0;
2757 screen_size.cy = 0;
2759 hr = IDirectDrawSurface4_IsLost(primary);
2760 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2761 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2762 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2763 hr = IDirectDrawSurface4_IsLost(primary);
2764 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2766 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2767 expect_messages = NULL;
2768 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
2769 "Expected screen size %ux%u, got %ux%u.\n",
2770 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
2772 GetWindowRect(window, &r);
2773 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2774 wine_dbgstr_rect(&r));
2776 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2777 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2778 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2779 param.user32_width, ddsd.dwWidth);
2780 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2781 param.user32_height, ddsd.dwHeight);
2782 IDirectDrawSurface4_Release(primary);
2784 memset(&ddsd, 0, sizeof(ddsd));
2785 ddsd.dwSize = sizeof(ddsd);
2786 ddsd.dwFlags = DDSD_CAPS;
2787 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2789 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2790 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2791 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2792 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2793 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2794 param.ddraw_width, ddsd.dwWidth);
2795 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2796 param.ddraw_height, ddsd.dwHeight);
2798 GetWindowRect(window, &r);
2799 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2800 wine_dbgstr_rect(&r));
2802 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2803 expect_messages = exclusive_messages;
2804 screen_size.cx = 0;
2805 screen_size.cy = 0;
2807 hr = IDirectDrawSurface4_IsLost(primary);
2808 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2809 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2810 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2811 hr = IDirectDrawSurface4_IsLost(primary);
2812 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2814 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2815 expect_messages = NULL;
2816 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
2817 "Expected screen size %ux%u, got %ux%u.\n",
2818 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
2820 GetWindowRect(window, &r);
2821 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2822 wine_dbgstr_rect(&r));
2824 expect_messages = exclusive_focus_loss_messages;
2825 ret = SetForegroundWindow(GetDesktopWindow());
2826 ok(ret, "Failed to set foreground window.\n");
2827 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2828 memset(&devmode, 0, sizeof(devmode));
2829 devmode.dmSize = sizeof(devmode);
2830 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2831 ok(ret, "Failed to get display mode.\n");
2832 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2833 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
2834 devmode.dmPelsWidth, devmode.dmPelsHeight);
2836 expect_messages = exclusive_focus_restore_messages;
2837 ShowWindow(window, SW_RESTORE);
2838 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2840 GetWindowRect(window, &r);
2841 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2842 wine_dbgstr_rect(&r));
2843 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2844 ok(ret, "Failed to get display mode.\n");
2845 ok(devmode.dmPelsWidth == param.ddraw_width
2846 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpect screen size %ux%u.\n",
2847 devmode.dmPelsWidth, devmode.dmPelsHeight);
2849 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2850 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2851 /* Normally the primary should be restored here. Unfortunately this causes the
2852 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
2853 * testbot. Another Restore call would presumably avoid the crash, but it also moots
2854 * the point of the GetSurfaceDesc call. */
2856 expect_messages = sc_minimize_messages;
2857 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
2858 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2859 expect_messages = NULL;
2861 expect_messages = sc_restore_messages;
2862 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
2863 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2864 expect_messages = NULL;
2866 expect_messages = sc_maximize_messages;
2867 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
2868 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2869 expect_messages = NULL;
2871 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2872 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2874 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2875 expect_messages = exclusive_messages;
2876 screen_size.cx = 0;
2877 screen_size.cy = 0;
2879 hr = IDirectDrawSurface4_IsLost(primary);
2880 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2881 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
2882 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2883 hr = IDirectDrawSurface4_IsLost(primary);
2884 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2886 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2887 expect_messages = NULL;
2888 ok(screen_size.cx == registry_mode.dmPelsWidth
2889 && screen_size.cy == registry_mode.dmPelsHeight,
2890 "Expected screen size %ux%u, got %ux%u.\n",
2891 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
2893 GetWindowRect(window, &r);
2894 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2895 wine_dbgstr_rect(&r));
2897 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2898 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2899 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2900 param.ddraw_width, ddsd.dwWidth);
2901 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2902 param.ddraw_height, ddsd.dwHeight);
2903 IDirectDrawSurface4_Release(primary);
2905 /* For Wine. */
2906 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2907 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2909 memset(&ddsd, 0, sizeof(ddsd));
2910 ddsd.dwSize = sizeof(ddsd);
2911 ddsd.dwFlags = DDSD_CAPS;
2912 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2914 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2915 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2916 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2917 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2918 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2919 registry_mode.dmPelsWidth, ddsd.dwWidth);
2920 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2921 registry_mode.dmPelsHeight, ddsd.dwHeight);
2923 GetWindowRect(window, &r);
2924 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2925 wine_dbgstr_rect(&r));
2927 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2928 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2930 GetWindowRect(window, &r);
2931 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2932 wine_dbgstr_rect(&r));
2934 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2935 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2936 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2937 registry_mode.dmPelsWidth, ddsd.dwWidth);
2938 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2939 registry_mode.dmPelsHeight, ddsd.dwHeight);
2940 IDirectDrawSurface4_Release(primary);
2942 memset(&ddsd, 0, sizeof(ddsd));
2943 ddsd.dwSize = sizeof(ddsd);
2944 ddsd.dwFlags = DDSD_CAPS;
2945 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2947 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2948 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2949 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2950 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2951 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2952 registry_mode.dmPelsWidth, ddsd.dwWidth);
2953 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2954 registry_mode.dmPelsHeight, ddsd.dwHeight);
2956 GetWindowRect(window, &r);
2957 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2958 wine_dbgstr_rect(&r));
2960 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2961 expect_messages = normal_messages;
2962 screen_size.cx = 0;
2963 screen_size.cy = 0;
2965 hr = IDirectDrawSurface4_IsLost(primary);
2966 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2967 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2968 devmode.dmPelsWidth = param.user32_width;
2969 devmode.dmPelsHeight = param.user32_height;
2970 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2971 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2972 hr = IDirectDrawSurface4_IsLost(primary);
2973 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2975 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2976 expect_messages = NULL;
2977 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2979 GetWindowRect(window, &r);
2980 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2981 wine_dbgstr_rect(&r));
2983 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2984 expect_messages = normal_messages;
2985 screen_size.cx = 0;
2986 screen_size.cy = 0;
2988 hr = IDirectDrawSurface4_Restore(primary);
2989 todo_wine ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2990 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2991 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2992 hr = IDirectDrawSurface4_Restore(primary);
2993 todo_wine ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2994 hr = IDirectDrawSurface4_IsLost(primary);
2995 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2997 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2998 expect_messages = NULL;
2999 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3001 GetWindowRect(window, &r);
3002 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3003 wine_dbgstr_rect(&r));
3005 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3006 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3007 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3008 registry_mode.dmPelsWidth, ddsd.dwWidth);
3009 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3010 registry_mode.dmPelsHeight, ddsd.dwHeight);
3011 IDirectDrawSurface4_Release(primary);
3013 memset(&ddsd, 0, sizeof(ddsd));
3014 ddsd.dwSize = sizeof(ddsd);
3015 ddsd.dwFlags = DDSD_CAPS;
3016 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3018 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3019 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3020 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3021 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3022 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3023 param.ddraw_width, ddsd.dwWidth);
3024 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3025 param.ddraw_height, ddsd.dwHeight);
3027 GetWindowRect(window, &r);
3028 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3029 wine_dbgstr_rect(&r));
3031 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3032 expect_messages = normal_messages;
3033 screen_size.cx = 0;
3034 screen_size.cy = 0;
3036 hr = IDirectDrawSurface4_IsLost(primary);
3037 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3038 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
3039 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3040 hr = IDirectDrawSurface4_IsLost(primary);
3041 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3043 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3044 expect_messages = NULL;
3045 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3047 GetWindowRect(window, &r);
3048 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3049 wine_dbgstr_rect(&r));
3051 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3052 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3053 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3054 param.ddraw_width, ddsd.dwWidth);
3055 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3056 param.ddraw_height, ddsd.dwHeight);
3057 IDirectDrawSurface4_Release(primary);
3059 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3060 ok(ret, "Failed to get display mode.\n");
3061 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3062 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3063 "Expected resolution %ux%u, got %ux%u.\n",
3064 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3065 devmode.dmPelsWidth, devmode.dmPelsHeight);
3066 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3067 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3069 memset(&ddsd, 0, sizeof(ddsd));
3070 ddsd.dwSize = sizeof(ddsd);
3071 ddsd.dwFlags = DDSD_CAPS;
3072 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3074 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3075 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3076 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3077 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3078 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3079 registry_mode.dmPelsWidth, ddsd.dwWidth);
3080 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3081 registry_mode.dmPelsHeight, ddsd.dwHeight);
3083 GetWindowRect(window, &r);
3084 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3085 wine_dbgstr_rect(&r));
3087 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
3088 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
3089 * not DDSCL_FULLSCREEN. */
3090 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3091 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3093 GetWindowRect(window, &r);
3094 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3095 wine_dbgstr_rect(&r));
3097 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3098 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3099 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3100 registry_mode.dmPelsWidth, ddsd.dwWidth);
3101 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3102 registry_mode.dmPelsHeight, ddsd.dwHeight);
3103 IDirectDrawSurface4_Release(primary);
3105 memset(&ddsd, 0, sizeof(ddsd));
3106 ddsd.dwSize = sizeof(ddsd);
3107 ddsd.dwFlags = DDSD_CAPS;
3108 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3110 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3111 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3112 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3113 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3114 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3115 registry_mode.dmPelsWidth, ddsd.dwWidth);
3116 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3117 registry_mode.dmPelsHeight, ddsd.dwHeight);
3119 GetWindowRect(window, &r);
3120 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3121 wine_dbgstr_rect(&r));
3123 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3124 expect_messages = normal_messages;
3125 screen_size.cx = 0;
3126 screen_size.cy = 0;
3128 hr = IDirectDrawSurface4_IsLost(primary);
3129 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3130 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3131 devmode.dmPelsWidth = param.user32_width;
3132 devmode.dmPelsHeight = param.user32_height;
3133 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3134 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3135 hr = IDirectDrawSurface4_IsLost(primary);
3136 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3138 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3139 expect_messages = NULL;
3140 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3142 GetWindowRect(window, &r);
3143 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3144 wine_dbgstr_rect(&r));
3146 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3147 expect_messages = normal_messages;
3148 screen_size.cx = 0;
3149 screen_size.cy = 0;
3151 hr = IDirectDrawSurface4_Restore(primary);
3152 todo_wine ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3153 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3154 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3155 hr = IDirectDrawSurface4_Restore(primary);
3156 todo_wine ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3157 hr = IDirectDrawSurface4_IsLost(primary);
3158 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3160 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3161 expect_messages = NULL;
3162 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3164 GetWindowRect(window, &r);
3165 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3166 wine_dbgstr_rect(&r));
3168 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3169 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3170 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3171 registry_mode.dmPelsWidth, ddsd.dwWidth);
3172 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3173 registry_mode.dmPelsHeight, ddsd.dwHeight);
3174 IDirectDrawSurface4_Release(primary);
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 == param.ddraw_width, "Expected surface width %u, got %u.\n",
3186 param.ddraw_width, ddsd.dwWidth);
3187 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3188 param.ddraw_height, ddsd.dwHeight);
3190 GetWindowRect(window, &r);
3191 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3192 wine_dbgstr_rect(&r));
3194 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3195 expect_messages = normal_messages;
3196 screen_size.cx = 0;
3197 screen_size.cy = 0;
3199 hr = IDirectDrawSurface4_IsLost(primary);
3200 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3201 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
3202 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3203 hr = IDirectDrawSurface4_IsLost(primary);
3204 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3206 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3207 expect_messages = NULL;
3208 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3210 GetWindowRect(window, &r);
3211 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3212 wine_dbgstr_rect(&r));
3214 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3215 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3216 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3217 param.ddraw_width, ddsd.dwWidth);
3218 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3219 param.ddraw_height, ddsd.dwHeight);
3220 IDirectDrawSurface4_Release(primary);
3222 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3223 ok(ret, "Failed to get display mode.\n");
3224 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3225 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3226 "Expected resolution %ux%u, got %ux%u.\n",
3227 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3228 devmode.dmPelsWidth, devmode.dmPelsHeight);
3229 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3230 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3232 memset(&ddsd, 0, sizeof(ddsd));
3233 ddsd.dwSize = sizeof(ddsd);
3234 ddsd.dwFlags = DDSD_CAPS;
3235 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3237 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3238 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3239 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3240 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3241 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3242 registry_mode.dmPelsWidth, ddsd.dwWidth);
3243 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3244 registry_mode.dmPelsHeight, ddsd.dwHeight);
3245 IDirectDrawSurface4_Release(primary);
3247 GetWindowRect(window, &r);
3248 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3249 wine_dbgstr_rect(&r));
3251 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
3252 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3253 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3254 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3255 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3257 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3258 expect_messages = exclusive_messages;
3259 screen_size.cx = 0;
3260 screen_size.cy = 0;
3262 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3263 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3265 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3266 expect_messages = NULL;
3267 ok(screen_size.cx == registry_mode.dmPelsWidth
3268 && screen_size.cy == registry_mode.dmPelsHeight,
3269 "Expected screen size %ux%u, got %ux%u.\n",
3270 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3271 screen_size.cx, screen_size.cy);
3273 GetWindowRect(window, &r);
3274 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3275 wine_dbgstr_rect(&r));
3277 memset(&ddsd, 0, sizeof(ddsd));
3278 ddsd.dwSize = sizeof(ddsd);
3279 ddsd.dwFlags = DDSD_CAPS;
3280 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3282 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3283 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3284 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3285 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3286 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3287 registry_mode.dmPelsWidth, ddsd.dwWidth);
3288 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3289 registry_mode.dmPelsHeight, ddsd.dwHeight);
3290 IDirectDrawSurface4_Release(primary);
3292 /* The screen restore is a property of DDSCL_EXCLUSIVE */
3293 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3294 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3295 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3296 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3298 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3299 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3301 memset(&ddsd, 0, sizeof(ddsd));
3302 ddsd.dwSize = sizeof(ddsd);
3303 ddsd.dwFlags = DDSD_CAPS;
3304 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3306 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3307 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3308 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3309 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3310 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3311 param.ddraw_width, ddsd.dwWidth);
3312 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3313 param.ddraw_height, ddsd.dwHeight);
3314 IDirectDrawSurface4_Release(primary);
3316 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
3317 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3319 /* If the window is changed at the same time, messages are sent to the new window. */
3320 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3321 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3322 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3323 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3325 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3326 expect_messages = exclusive_messages;
3327 screen_size.cx = 0;
3328 screen_size.cy = 0;
3329 screen_size2.cx = 0;
3330 screen_size2.cy = 0;
3332 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3333 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3335 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3336 expect_messages = NULL;
3337 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n",
3338 screen_size.cx, screen_size.cy);
3339 ok(screen_size2.cx == registry_mode.dmPelsWidth && screen_size2.cy == registry_mode.dmPelsHeight,
3340 "Expected screen size 2 %ux%u, got %ux%u.\n",
3341 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size2.cx, screen_size2.cy);
3343 GetWindowRect(window, &r);
3344 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3345 wine_dbgstr_rect(&r));
3346 GetWindowRect(window2, &r);
3347 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3348 wine_dbgstr_rect(&r));
3350 memset(&ddsd, 0, sizeof(ddsd));
3351 ddsd.dwSize = sizeof(ddsd);
3352 ddsd.dwFlags = DDSD_CAPS;
3353 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3355 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3356 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3357 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3358 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3359 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3360 registry_mode.dmPelsWidth, ddsd.dwWidth);
3361 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3362 registry_mode.dmPelsHeight, ddsd.dwHeight);
3363 IDirectDrawSurface4_Release(primary);
3365 ref = IDirectDraw4_Release(ddraw);
3366 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3368 GetWindowRect(window, &r);
3369 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3370 wine_dbgstr_rect(&r));
3372 expect_messages = NULL;
3373 DestroyWindow(window);
3374 DestroyWindow(window2);
3375 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3376 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
3379 static void test_coop_level_mode_set_multi(void)
3381 IDirectDraw4 *ddraw1, *ddraw2;
3382 UINT w, h;
3383 HWND window;
3384 HRESULT hr;
3385 ULONG ref;
3387 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3388 0, 0, 100, 100, 0, 0, 0, 0);
3389 ddraw1 = create_ddraw();
3390 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3392 /* With just a single ddraw object, the display mode is restored on
3393 * release. */
3394 hr = set_display_mode(ddraw1, 800, 600);
3395 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3396 w = GetSystemMetrics(SM_CXSCREEN);
3397 ok(w == 800, "Got unexpected screen width %u.\n", w);
3398 h = GetSystemMetrics(SM_CYSCREEN);
3399 ok(h == 600, "Got unexpected screen height %u.\n", h);
3401 ref = IDirectDraw4_Release(ddraw1);
3402 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3403 w = GetSystemMetrics(SM_CXSCREEN);
3404 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3405 h = GetSystemMetrics(SM_CYSCREEN);
3406 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3408 /* When there are multiple ddraw objects, the display mode is restored to
3409 * the initial mode, before the first SetDisplayMode() call. */
3410 ddraw1 = create_ddraw();
3411 hr = set_display_mode(ddraw1, 800, 600);
3412 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3413 w = GetSystemMetrics(SM_CXSCREEN);
3414 ok(w == 800, "Got unexpected screen width %u.\n", w);
3415 h = GetSystemMetrics(SM_CYSCREEN);
3416 ok(h == 600, "Got unexpected screen height %u.\n", h);
3418 ddraw2 = create_ddraw();
3419 hr = set_display_mode(ddraw2, 640, 480);
3420 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3421 w = GetSystemMetrics(SM_CXSCREEN);
3422 ok(w == 640, "Got unexpected screen width %u.\n", w);
3423 h = GetSystemMetrics(SM_CYSCREEN);
3424 ok(h == 480, "Got unexpected screen height %u.\n", h);
3426 ref = IDirectDraw4_Release(ddraw2);
3427 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3428 w = GetSystemMetrics(SM_CXSCREEN);
3429 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3430 h = GetSystemMetrics(SM_CYSCREEN);
3431 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3433 ref = IDirectDraw4_Release(ddraw1);
3434 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3435 w = GetSystemMetrics(SM_CXSCREEN);
3436 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3437 h = GetSystemMetrics(SM_CYSCREEN);
3438 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3440 /* Regardless of release ordering. */
3441 ddraw1 = create_ddraw();
3442 hr = set_display_mode(ddraw1, 800, 600);
3443 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3444 w = GetSystemMetrics(SM_CXSCREEN);
3445 ok(w == 800, "Got unexpected screen width %u.\n", w);
3446 h = GetSystemMetrics(SM_CYSCREEN);
3447 ok(h == 600, "Got unexpected screen height %u.\n", h);
3449 ddraw2 = create_ddraw();
3450 hr = set_display_mode(ddraw2, 640, 480);
3451 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3452 w = GetSystemMetrics(SM_CXSCREEN);
3453 ok(w == 640, "Got unexpected screen width %u.\n", w);
3454 h = GetSystemMetrics(SM_CYSCREEN);
3455 ok(h == 480, "Got unexpected screen height %u.\n", h);
3457 ref = IDirectDraw4_Release(ddraw1);
3458 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3459 w = GetSystemMetrics(SM_CXSCREEN);
3460 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3461 h = GetSystemMetrics(SM_CYSCREEN);
3462 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3464 ref = IDirectDraw4_Release(ddraw2);
3465 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3466 w = GetSystemMetrics(SM_CXSCREEN);
3467 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3468 h = GetSystemMetrics(SM_CYSCREEN);
3469 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3471 /* But only for ddraw objects that called SetDisplayMode(). */
3472 ddraw1 = create_ddraw();
3473 ddraw2 = create_ddraw();
3474 hr = set_display_mode(ddraw2, 640, 480);
3475 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3476 w = GetSystemMetrics(SM_CXSCREEN);
3477 ok(w == 640, "Got unexpected screen width %u.\n", w);
3478 h = GetSystemMetrics(SM_CYSCREEN);
3479 ok(h == 480, "Got unexpected screen height %u.\n", h);
3481 ref = IDirectDraw4_Release(ddraw1);
3482 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3483 w = GetSystemMetrics(SM_CXSCREEN);
3484 ok(w == 640, "Got unexpected screen width %u.\n", w);
3485 h = GetSystemMetrics(SM_CYSCREEN);
3486 ok(h == 480, "Got unexpected screen height %u.\n", h);
3488 ref = IDirectDraw4_Release(ddraw2);
3489 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3490 w = GetSystemMetrics(SM_CXSCREEN);
3491 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3492 h = GetSystemMetrics(SM_CYSCREEN);
3493 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3495 /* If there's a ddraw object that's currently in exclusive mode, it blocks
3496 * restoring the display mode. */
3497 ddraw1 = create_ddraw();
3498 hr = set_display_mode(ddraw1, 800, 600);
3499 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3500 w = GetSystemMetrics(SM_CXSCREEN);
3501 ok(w == 800, "Got unexpected screen width %u.\n", w);
3502 h = GetSystemMetrics(SM_CYSCREEN);
3503 ok(h == 600, "Got unexpected screen height %u.\n", h);
3505 ddraw2 = create_ddraw();
3506 hr = set_display_mode(ddraw2, 640, 480);
3507 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3508 w = GetSystemMetrics(SM_CXSCREEN);
3509 ok(w == 640, "Got unexpected screen width %u.\n", w);
3510 h = GetSystemMetrics(SM_CYSCREEN);
3511 ok(h == 480, "Got unexpected screen height %u.\n", h);
3513 hr = IDirectDraw4_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3514 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3516 ref = IDirectDraw4_Release(ddraw1);
3517 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3518 w = GetSystemMetrics(SM_CXSCREEN);
3519 ok(w == 640, "Got unexpected screen width %u.\n", w);
3520 h = GetSystemMetrics(SM_CYSCREEN);
3521 ok(h == 480, "Got unexpected screen height %u.\n", h);
3523 ref = IDirectDraw4_Release(ddraw2);
3524 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3525 w = GetSystemMetrics(SM_CXSCREEN);
3526 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3527 h = GetSystemMetrics(SM_CYSCREEN);
3528 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3530 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3531 ddraw1 = create_ddraw();
3532 hr = set_display_mode(ddraw1, 800, 600);
3533 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3534 w = GetSystemMetrics(SM_CXSCREEN);
3535 ok(w == 800, "Got unexpected screen width %u.\n", w);
3536 h = GetSystemMetrics(SM_CYSCREEN);
3537 ok(h == 600, "Got unexpected screen height %u.\n", h);
3539 hr = IDirectDraw4_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3540 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3542 ddraw2 = create_ddraw();
3543 hr = set_display_mode(ddraw2, 640, 480);
3544 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3546 ref = IDirectDraw4_Release(ddraw1);
3547 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3548 w = GetSystemMetrics(SM_CXSCREEN);
3549 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3550 h = GetSystemMetrics(SM_CYSCREEN);
3551 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3553 ref = IDirectDraw4_Release(ddraw2);
3554 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3555 w = GetSystemMetrics(SM_CXSCREEN);
3556 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3557 h = GetSystemMetrics(SM_CYSCREEN);
3558 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3560 DestroyWindow(window);
3563 static void test_initialize(void)
3565 IDirectDraw4 *ddraw;
3566 HRESULT hr;
3568 ddraw = create_ddraw();
3569 ok(!!ddraw, "Failed to create a ddraw object.\n");
3571 hr = IDirectDraw4_Initialize(ddraw, NULL);
3572 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
3573 IDirectDraw4_Release(ddraw);
3575 CoInitialize(NULL);
3576 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw4, (void **)&ddraw);
3577 ok(SUCCEEDED(hr), "Failed to create IDirectDraw4 instance, hr %#x.\n", hr);
3578 hr = IDirectDraw4_Initialize(ddraw, NULL);
3579 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
3580 hr = IDirectDraw4_Initialize(ddraw, NULL);
3581 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
3582 IDirectDraw4_Release(ddraw);
3583 CoUninitialize();
3586 static void test_coop_level_surf_create(void)
3588 IDirectDrawSurface4 *surface;
3589 IDirectDraw4 *ddraw;
3590 DDSURFACEDESC2 ddsd;
3591 HRESULT hr;
3593 ddraw = create_ddraw();
3594 ok(!!ddraw, "Failed to create a ddraw object.\n");
3596 memset(&ddsd, 0, sizeof(ddsd));
3597 ddsd.dwSize = sizeof(ddsd);
3598 ddsd.dwFlags = DDSD_CAPS;
3599 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3600 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
3601 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3603 IDirectDraw4_Release(ddraw);
3606 static void test_vb_discard(void)
3608 static const struct vec4 quad[] =
3610 { 0.0f, 480.0f, 0.0f, 1.0f},
3611 { 0.0f, 0.0f, 0.0f, 1.0f},
3612 {640.0f, 480.0f, 0.0f, 1.0f},
3613 {640.0f, 0.0f, 0.0f, 1.0f},
3616 IDirect3DDevice3 *device;
3617 IDirect3D3 *d3d;
3618 IDirect3DVertexBuffer *buffer;
3619 HWND window;
3620 HRESULT hr;
3621 D3DVERTEXBUFFERDESC desc;
3622 BYTE *data;
3623 static const unsigned int vbsize = 16;
3624 unsigned int i;
3626 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3627 0, 0, 640, 480, 0, 0, 0, 0);
3629 if (!(device = create_device(window, DDSCL_NORMAL)))
3631 skip("Failed to create a 3D device, skipping test.\n");
3632 DestroyWindow(window);
3633 return;
3636 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
3637 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
3639 memset(&desc, 0, sizeof(desc));
3640 desc.dwSize = sizeof(desc);
3641 desc.dwCaps = D3DVBCAPS_WRITEONLY;
3642 desc.dwFVF = D3DFVF_XYZRHW;
3643 desc.dwNumVertices = vbsize;
3644 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &buffer, 0, NULL);
3645 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3647 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3648 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3649 memcpy(data, quad, sizeof(quad));
3650 hr = IDirect3DVertexBuffer_Unlock(buffer);
3651 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3653 hr = IDirect3DDevice3_BeginScene(device);
3654 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3655 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
3656 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3657 hr = IDirect3DDevice3_EndScene(device);
3658 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3660 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3661 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3662 memset(data, 0xaa, sizeof(struct vec4) * vbsize);
3663 hr = IDirect3DVertexBuffer_Unlock(buffer);
3664 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3666 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3667 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3668 for (i = 0; i < sizeof(struct vec4) * vbsize; i++)
3670 if (data[i] != 0xaa)
3672 ok(FALSE, "Vertex buffer data byte %u is 0x%02x, expected 0xaa\n", i, data[i]);
3673 break;
3676 hr = IDirect3DVertexBuffer_Unlock(buffer);
3677 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3679 IDirect3DVertexBuffer_Release(buffer);
3680 IDirect3D3_Release(d3d);
3681 IDirect3DDevice3_Release(device);
3682 DestroyWindow(window);
3685 static void test_coop_level_multi_window(void)
3687 HWND window1, window2;
3688 IDirectDraw4 *ddraw;
3689 HRESULT hr;
3691 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
3692 0, 0, 640, 480, 0, 0, 0, 0);
3693 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
3694 0, 0, 640, 480, 0, 0, 0, 0);
3695 ddraw = create_ddraw();
3696 ok(!!ddraw, "Failed to create a ddraw object.\n");
3698 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
3699 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3700 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3701 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3702 ok(IsWindow(window1), "Window 1 was destroyed.\n");
3703 ok(IsWindow(window2), "Window 2 was destroyed.\n");
3705 IDirectDraw4_Release(ddraw);
3706 DestroyWindow(window2);
3707 DestroyWindow(window1);
3710 static void test_draw_strided(void)
3712 static struct vec3 position[] =
3714 {-1.0, -1.0, 0.0},
3715 {-1.0, 1.0, 0.0},
3716 { 1.0, 1.0, 0.0},
3717 { 1.0, -1.0, 0.0},
3719 static DWORD diffuse[] =
3721 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
3723 static WORD indices[] =
3725 0, 1, 2, 2, 3, 0
3728 IDirectDrawSurface4 *rt;
3729 IDirect3DDevice3 *device;
3730 D3DCOLOR color;
3731 HWND window;
3732 HRESULT hr;
3733 D3DDRAWPRIMITIVESTRIDEDDATA strided;
3734 IDirect3DViewport3 *viewport;
3735 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3737 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3738 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);
3749 viewport = create_viewport(device, 0, 0, 640, 480);
3750 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
3751 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
3752 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
3753 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
3755 hr = IDirect3DDevice3_BeginScene(device);
3756 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3758 memset(&strided, 0x55, sizeof(strided));
3759 strided.position.lpvData = position;
3760 strided.position.dwStride = sizeof(*position);
3761 strided.diffuse.lpvData = diffuse;
3762 strided.diffuse.dwStride = sizeof(*diffuse);
3763 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE,
3764 &strided, 4, indices, 6, 0);
3765 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3767 hr = IDirect3DDevice3_EndScene(device);
3768 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3770 color = get_surface_color(rt, 320, 240);
3771 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3773 IDirect3DViewport3_Release(viewport);
3774 IDirectDrawSurface4_Release(rt);
3775 IDirect3DDevice3_Release(device);
3776 DestroyWindow(window);
3779 static void test_lighting(void)
3781 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3782 static D3DMATRIX mat =
3784 1.0f, 0.0f, 0.0f, 0.0f,
3785 0.0f, 1.0f, 0.0f, 0.0f,
3786 0.0f, 0.0f, 1.0f, 0.0f,
3787 0.0f, 0.0f, 0.0f, 1.0f,
3789 mat_singular =
3791 1.0f, 0.0f, 1.0f, 0.0f,
3792 0.0f, 1.0f, 0.0f, 0.0f,
3793 1.0f, 0.0f, 1.0f, 0.0f,
3794 0.0f, 0.0f, 0.5f, 1.0f,
3796 mat_transf =
3798 0.0f, 0.0f, 1.0f, 0.0f,
3799 0.0f, 1.0f, 0.0f, 0.0f,
3800 -1.0f, 0.0f, 0.0f, 0.0f,
3801 10.f, 10.0f, 10.0f, 1.0f,
3803 mat_nonaffine =
3805 1.0f, 0.0f, 0.0f, 0.0f,
3806 0.0f, 1.0f, 0.0f, 0.0f,
3807 0.0f, 0.0f, 1.0f, -1.0f,
3808 10.f, 10.0f, 10.0f, 0.0f,
3810 static struct
3812 struct vec3 position;
3813 DWORD diffuse;
3815 unlitquad[] =
3817 {{-1.0f, -1.0f, 0.1f}, 0xffff0000},
3818 {{-1.0f, 0.0f, 0.1f}, 0xffff0000},
3819 {{ 0.0f, 0.0f, 0.1f}, 0xffff0000},
3820 {{ 0.0f, -1.0f, 0.1f}, 0xffff0000},
3822 litquad[] =
3824 {{-1.0f, 0.0f, 0.1f}, 0xff00ff00},
3825 {{-1.0f, 1.0f, 0.1f}, 0xff00ff00},
3826 {{ 0.0f, 1.0f, 0.1f}, 0xff00ff00},
3827 {{ 0.0f, 0.0f, 0.1f}, 0xff00ff00},
3829 static struct
3831 struct vec3 position;
3832 struct vec3 normal;
3833 DWORD diffuse;
3835 unlitnquad[] =
3837 {{0.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3838 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3839 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3840 {{1.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3842 litnquad[] =
3844 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3845 {{0.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3846 {{1.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3847 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3849 nquad[] =
3851 {{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3852 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3853 {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3854 {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3856 rotatedquad[] =
3858 {{-10.0f, -11.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3859 {{-10.0f, -9.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3860 {{-10.0f, -9.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3861 {{-10.0f, -11.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3863 translatedquad[] =
3865 {{-11.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3866 {{-11.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3867 {{ -9.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3868 {{ -9.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3870 static WORD indices[] = {0, 1, 2, 2, 3, 0};
3871 static const struct
3873 D3DMATRIX *world_matrix;
3874 void *quad;
3875 DWORD expected;
3876 const char *message;
3878 tests[] =
3880 {&mat, nquad, 0x000000ff, "Lit quad with light"},
3881 {&mat_singular, nquad, 0x000000b4, "Lit quad with singular world matrix"},
3882 {&mat_transf, rotatedquad, 0x000000ff, "Lit quad with transformation matrix"},
3883 {&mat_nonaffine, translatedquad, 0x000000ff, "Lit quad with non-affine matrix"},
3886 HWND window;
3887 IDirect3D3 *d3d;
3888 IDirect3DDevice3 *device;
3889 IDirectDrawSurface4 *rt;
3890 IDirect3DViewport3 *viewport;
3891 IDirect3DMaterial3 *material;
3892 IDirect3DLight *light;
3893 D3DMATERIALHANDLE mat_handle;
3894 D3DLIGHT2 light_desc;
3895 HRESULT hr;
3896 DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
3897 DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
3898 D3DCOLOR color;
3899 ULONG refcount;
3900 unsigned int i;
3902 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3903 0, 0, 640, 480, 0, 0, 0, 0);
3904 if (!(device = create_device(window, DDSCL_NORMAL)))
3906 skip("Failed to create a 3D device, skipping test.\n");
3907 DestroyWindow(window);
3908 return;
3911 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
3912 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
3914 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
3915 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3917 viewport = create_viewport(device, 0, 0, 640, 480);
3918 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
3919 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
3921 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
3922 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3924 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
3925 ok(SUCCEEDED(hr), "Failed to set world transformation, hr %#x.\n", hr);
3926 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
3927 ok(SUCCEEDED(hr), "Failed to set view transformation, hr %#x.\n", hr);
3928 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
3929 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
3930 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
3931 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
3932 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
3933 ok(SUCCEEDED(hr), "Failed to disable zbuffer, hr %#x.\n", hr);
3934 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
3935 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
3936 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
3937 ok(SUCCEEDED(hr), "Failed to disable stencil buffer, hr %#x.\n", hr);
3938 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
3939 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
3941 hr = IDirect3DDevice3_BeginScene(device);
3942 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3944 /* There is no D3DRENDERSTATE_LIGHTING on ddraw < 7. */
3945 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3946 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
3947 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, unlitquad, 4,
3948 indices, 6, 0);
3949 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3951 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
3952 ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
3953 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, litquad, 4,
3954 indices, 6, 0);
3955 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3957 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3958 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
3959 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, unlitnquad, 4,
3960 indices, 6, 0);
3961 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3963 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
3964 ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
3965 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, litnquad, 4,
3966 indices, 6, 0);
3967 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3969 hr = IDirect3DDevice3_EndScene(device);
3970 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3972 color = get_surface_color(rt, 160, 360);
3973 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x.\n", color);
3974 color = get_surface_color(rt, 160, 120);
3975 ok(color == 0x0000ff00, "Lit quad without normals has color 0x%08x.\n", color);
3976 color = get_surface_color(rt, 480, 360);
3977 ok(color == 0x000000ff, "Unlit quad with normals has color 0x%08x.\n", color);
3978 color = get_surface_color(rt, 480, 120);
3979 ok(color == 0x00ffff00, "Lit quad with normals has color 0x%08x.\n", color);
3981 material = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
3982 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
3983 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
3984 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
3985 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
3987 hr = IDirect3D3_CreateLight(d3d, &light, NULL);
3988 ok(SUCCEEDED(hr), "Failed to create a light object, hr %#x.\n", hr);
3989 memset(&light_desc, 0, sizeof(light_desc));
3990 light_desc.dwSize = sizeof(light_desc);
3991 light_desc.dltType = D3DLIGHT_DIRECTIONAL;
3992 U1(light_desc.dcvColor).r = 1.0f;
3993 U2(light_desc.dcvColor).g = 1.0f;
3994 U3(light_desc.dcvColor).b = 1.0f;
3995 U4(light_desc.dcvColor).a = 1.0f;
3996 U3(light_desc.dvDirection).z = 1.0f;
3997 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
3998 ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
3999 hr = IDirect3DViewport3_AddLight(viewport, light);
4000 ok(SUCCEEDED(hr), "Failed to add a light to the viewport, hr %#x.\n", hr);
4002 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
4003 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4005 hr = IDirect3DDevice3_BeginScene(device);
4006 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4008 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, nquad,
4009 4, indices, 6, 0);
4010 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4012 hr = IDirect3DDevice3_EndScene(device);
4013 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4015 color = get_surface_color(rt, 320, 240);
4016 ok(color == 0x00000000, "Lit quad with no light has color 0x%08x.\n", color);
4018 light_desc.dwFlags = D3DLIGHT_ACTIVE;
4019 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
4020 ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
4022 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
4024 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
4025 ok(SUCCEEDED(hr), "Failed to set world transformation, hr %#x.\n", hr);
4027 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
4028 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4030 hr = IDirect3DDevice3_BeginScene(device);
4031 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4033 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, tests[i].quad,
4034 4, indices, 6, 0);
4035 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4037 hr = IDirect3DDevice3_EndScene(device);
4038 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4040 color = get_surface_color(rt, 320, 240);
4041 ok(color == tests[i].expected, "%s has color 0x%08x.\n", tests[i].message, color);
4044 hr = IDirect3DViewport3_DeleteLight(viewport, light);
4045 ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#x.\n", hr);
4046 IDirect3DLight_Release(light);
4047 destroy_material(material);
4048 IDirect3DViewport3_Release(viewport);
4049 IDirectDrawSurface4_Release(rt);
4050 refcount = IDirect3DDevice3_Release(device);
4051 ok(!refcount, "Device has %u references left.\n", refcount);
4052 IDirect3D3_Release(d3d);
4053 DestroyWindow(window);
4056 static void test_specular_lighting(void)
4058 static const unsigned int vertices_side = 5;
4059 const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
4060 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
4061 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
4062 static D3DMATRIX mat =
4064 1.0f, 0.0f, 0.0f, 0.0f,
4065 0.0f, 1.0f, 0.0f, 0.0f,
4066 0.0f, 0.0f, 1.0f, 0.0f,
4067 0.0f, 0.0f, 0.0f, 1.0f,
4069 static D3DLIGHT2 directional =
4071 sizeof(D3DLIGHT2),
4072 D3DLIGHT_DIRECTIONAL,
4073 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4074 {{0.0f}, {0.0f}, {0.0f}},
4075 {{0.0f}, {0.0f}, {1.0f}},
4077 point =
4079 sizeof(D3DLIGHT2),
4080 D3DLIGHT_POINT,
4081 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4082 {{0.0f}, {0.0f}, {0.0f}},
4083 {{0.0f}, {0.0f}, {0.0f}},
4084 100.0f,
4085 0.0f,
4086 0.0f, 0.0f, 1.0f,
4088 spot =
4090 sizeof(D3DLIGHT2),
4091 D3DLIGHT_SPOT,
4092 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4093 {{0.0f}, {0.0f}, {0.0f}},
4094 {{0.0f}, {0.0f}, {1.0f}},
4095 100.0f,
4096 1.0f,
4097 0.0f, 0.0f, 1.0f,
4098 M_PI / 12.0f, M_PI / 3.0f
4100 parallelpoint =
4102 sizeof(D3DLIGHT2),
4103 D3DLIGHT_PARALLELPOINT,
4104 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4105 {{0.5f}, {0.0f}, {-1.0f}},
4106 {{0.0f}, {0.0f}, {0.0f}},
4108 static const struct expected_color
4110 unsigned int x, y;
4111 D3DCOLOR color;
4113 expected_directional[] =
4115 {160, 120, 0x003c3c3c},
4116 {320, 120, 0x00717171},
4117 {480, 120, 0x003c3c3c},
4118 {160, 240, 0x00717171},
4119 {320, 240, 0x00ffffff},
4120 {480, 240, 0x00717171},
4121 {160, 360, 0x003c3c3c},
4122 {320, 360, 0x00717171},
4123 {480, 360, 0x003c3c3c},
4125 expected_point[] =
4127 {160, 120, 0x00000000},
4128 {320, 120, 0x00090909},
4129 {480, 120, 0x00000000},
4130 {160, 240, 0x00090909},
4131 {320, 240, 0x00fafafa},
4132 {480, 240, 0x00090909},
4133 {160, 360, 0x00000000},
4134 {320, 360, 0x00090909},
4135 {480, 360, 0x00000000},
4137 expected_spot[] =
4139 {160, 120, 0x00000000},
4140 {320, 120, 0x00020202},
4141 {480, 120, 0x00000000},
4142 {160, 240, 0x00020202},
4143 {320, 240, 0x00fafafa},
4144 {480, 240, 0x00020202},
4145 {160, 360, 0x00000000},
4146 {320, 360, 0x00020202},
4147 {480, 360, 0x00000000},
4149 expected_parallelpoint[] =
4151 {160, 120, 0x00050505},
4152 {320, 120, 0x002c2c2c},
4153 {480, 120, 0x006e6e6e},
4154 {160, 240, 0x00090909},
4155 {320, 240, 0x00717171},
4156 {480, 240, 0x00ffffff},
4157 {160, 360, 0x00050505},
4158 {320, 360, 0x002c2c2c},
4159 {480, 360, 0x006e6e6e},
4161 static const struct
4163 D3DLIGHT2 *light;
4164 BOOL local_viewer;
4165 const struct expected_color *expected;
4166 unsigned int expected_count;
4168 tests[] =
4170 /* D3DRENDERSTATE_LOCALVIEWER does not exist in D3D < 7 (the behavior is
4171 * the one you get on newer D3D versions with it set as TRUE). */
4172 {&directional, FALSE, expected_directional,
4173 sizeof(expected_directional) / sizeof(expected_directional[0])},
4174 {&directional, TRUE, expected_directional,
4175 sizeof(expected_directional) / sizeof(expected_directional[0])},
4176 {&point, TRUE, expected_point,
4177 sizeof(expected_point) / sizeof(expected_point[0])},
4178 {&spot, TRUE, expected_spot,
4179 sizeof(expected_spot) / sizeof(expected_spot[0])},
4180 {&parallelpoint, TRUE, expected_parallelpoint,
4181 sizeof(expected_parallelpoint) / sizeof(expected_parallelpoint[0])},
4183 IDirect3D3 *d3d;
4184 IDirect3DDevice3 *device;
4185 IDirectDrawSurface4 *rt;
4186 IDirect3DViewport3 *viewport;
4187 IDirect3DMaterial3 *material;
4188 IDirect3DLight *light;
4189 D3DMATERIALHANDLE mat_handle;
4190 D3DCOLOR color;
4191 ULONG refcount;
4192 HWND window;
4193 HRESULT hr;
4194 unsigned int i, j, x, y;
4195 struct
4197 struct vec3 position;
4198 struct vec3 normal;
4199 } *quad;
4200 WORD *indices;
4202 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4203 0, 0, 640, 480, 0, 0, 0, 0);
4204 if (!(device = create_device(window, DDSCL_NORMAL)))
4206 skip("Failed to create a 3D device, skipping test.\n");
4207 DestroyWindow(window);
4208 return;
4211 quad = HeapAlloc(GetProcessHeap(), 0, vertices_side * vertices_side * sizeof(*quad));
4212 indices = HeapAlloc(GetProcessHeap(), 0, indices_count * sizeof(*indices));
4213 for (i = 0, y = 0; y < vertices_side; ++y)
4215 for (x = 0; x < vertices_side; ++x)
4217 quad[i].position.x = x * 2.0f / (vertices_side - 1) - 1.0f;
4218 quad[i].position.y = y * 2.0f / (vertices_side - 1) - 1.0f;
4219 quad[i].position.z = 1.0f;
4220 quad[i].normal.x = 0.0f;
4221 quad[i].normal.y = 0.0f;
4222 quad[i++].normal.z = -1.0f;
4225 for (i = 0, y = 0; y < (vertices_side - 1); ++y)
4227 for (x = 0; x < (vertices_side - 1); ++x)
4229 indices[i++] = y * vertices_side + x + 1;
4230 indices[i++] = y * vertices_side + x;
4231 indices[i++] = (y + 1) * vertices_side + x;
4232 indices[i++] = y * vertices_side + x + 1;
4233 indices[i++] = (y + 1) * vertices_side + x;
4234 indices[i++] = (y + 1) * vertices_side + x + 1;
4238 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
4239 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
4241 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
4242 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4244 viewport = create_viewport(device, 0, 0, 640, 480);
4245 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
4246 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
4248 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
4249 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
4250 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
4251 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
4252 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
4253 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
4254 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
4255 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
4256 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
4257 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
4258 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4259 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
4261 material = create_specular_material(device, 1.0f, 1.0f, 1.0f, 1.0f, 30.0f);
4262 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
4263 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
4264 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
4265 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
4267 hr = IDirect3D3_CreateLight(d3d, &light, NULL);
4268 ok(SUCCEEDED(hr), "Failed to create a light object, hr %#x.\n", hr);
4269 hr = IDirect3DViewport3_AddLight(viewport, light);
4270 ok(SUCCEEDED(hr), "Failed to add a light to the viewport, hr %#x.\n", hr);
4272 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
4273 ok(SUCCEEDED(hr), "Failed to enable specular lighting, hr %#x.\n", hr);
4275 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
4277 tests[i].light->dwFlags = D3DLIGHT_ACTIVE;
4278 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)tests[i].light);
4279 ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
4281 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LOCALVIEWER, tests[i].local_viewer);
4282 ok(SUCCEEDED(hr), "Failed to set local viewer state, hr %#x.\n", hr);
4284 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
4285 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4287 hr = IDirect3DDevice3_BeginScene(device);
4288 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4290 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, quad,
4291 vertices_side * vertices_side, indices, indices_count, 0);
4292 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4294 hr = IDirect3DDevice3_EndScene(device);
4295 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4297 for (j = 0; j < tests[i].expected_count; ++j)
4299 color = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
4300 ok(compare_color(color, tests[i].expected[j].color, 1),
4301 "Expected color 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
4302 tests[i].expected[j].color, tests[i].expected[j].x,
4303 tests[i].expected[j].y, color, i);
4307 hr = IDirect3DViewport3_DeleteLight(viewport, light);
4308 ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#x.\n", hr);
4309 IDirect3DLight_Release(light);
4310 destroy_material(material);
4311 IDirect3DViewport3_Release(viewport);
4312 IDirectDrawSurface4_Release(rt);
4313 refcount = IDirect3DDevice3_Release(device);
4314 ok(!refcount, "Device has %u references left.\n", refcount);
4315 IDirect3D3_Release(d3d);
4316 DestroyWindow(window);
4317 HeapFree(GetProcessHeap(), 0, indices);
4318 HeapFree(GetProcessHeap(), 0, quad);
4321 static void test_clear_rect_count(void)
4323 IDirectDrawSurface4 *rt;
4324 IDirect3DDevice3 *device;
4325 D3DCOLOR color;
4326 HWND window;
4327 HRESULT hr;
4328 IDirect3DViewport3 *viewport;
4329 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
4331 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4332 0, 0, 640, 480, 0, 0, 0, 0);
4333 if (!(device = create_device(window, DDSCL_NORMAL)))
4335 skip("Failed to create a 3D device, skipping test.\n");
4336 DestroyWindow(window);
4337 return;
4340 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
4341 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4343 viewport = create_viewport(device, 0, 0, 640, 480);
4344 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
4345 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
4346 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00ffffff, 0.0f, 0);
4347 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
4348 hr = IDirect3DViewport3_Clear2(viewport, 0, &clear_rect, D3DCLEAR_TARGET, 0x00ff0000, 0.0f, 0);
4349 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
4350 hr = IDirect3DViewport3_Clear2(viewport, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 0.0f, 0);
4351 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
4352 hr = IDirect3DViewport3_Clear2(viewport, 1, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
4353 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
4355 color = get_surface_color(rt, 320, 240);
4356 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x000000ff, 1)),
4357 "Got unexpected color 0x%08x.\n", color);
4359 IDirect3DViewport3_Release(viewport);
4360 IDirectDrawSurface4_Release(rt);
4361 IDirect3DDevice3_Release(device);
4362 DestroyWindow(window);
4365 static BOOL test_mode_restored(IDirectDraw4 *ddraw, HWND window)
4367 DDSURFACEDESC2 ddsd1, ddsd2;
4368 HRESULT hr;
4370 memset(&ddsd1, 0, sizeof(ddsd1));
4371 ddsd1.dwSize = sizeof(ddsd1);
4372 hr = IDirectDraw4_GetDisplayMode(ddraw, &ddsd1);
4373 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4375 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4376 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4377 hr = set_display_mode(ddraw, 640, 480);
4378 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
4379 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4380 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4382 memset(&ddsd2, 0, sizeof(ddsd2));
4383 ddsd2.dwSize = sizeof(ddsd2);
4384 hr = IDirectDraw4_GetDisplayMode(ddraw, &ddsd2);
4385 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4386 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
4387 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4389 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
4392 static void test_coop_level_versions(void)
4394 HWND window;
4395 IDirectDraw *ddraw;
4396 HRESULT hr;
4397 BOOL restored;
4398 IDirectDrawSurface *surface;
4399 IDirectDraw4 *ddraw4;
4400 DDSURFACEDESC ddsd;
4402 window = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
4403 0, 0, 640, 480, 0, 0, 0, 0);
4405 ddraw4 = create_ddraw();
4406 ok(!!ddraw4, "Failed to create a ddraw object.\n");
4407 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
4408 restored = test_mode_restored(ddraw4, window);
4409 ok(restored, "Display mode not restored in new ddraw object\n");
4411 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
4412 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
4413 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4415 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4416 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4417 restored = test_mode_restored(ddraw4, window);
4418 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
4420 /* A successful one does */
4421 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4422 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4423 restored = test_mode_restored(ddraw4, window);
4424 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
4426 IDirectDraw_Release(ddraw);
4427 IDirectDraw4_Release(ddraw4);
4429 ddraw4 = create_ddraw();
4430 ok(!!ddraw4, "Failed to create a ddraw object.\n");
4431 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
4432 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4434 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
4435 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4436 restored = test_mode_restored(ddraw4, window);
4437 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
4439 IDirectDraw_Release(ddraw);
4440 IDirectDraw4_Release(ddraw4);
4442 /* A failing call does not restore the ddraw2+ behavior */
4443 ddraw4 = create_ddraw();
4444 ok(!!ddraw4, "Failed to create a ddraw object.\n");
4445 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
4446 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4448 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4449 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4450 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4451 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4452 restored = test_mode_restored(ddraw4, window);
4453 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
4455 IDirectDraw_Release(ddraw);
4456 IDirectDraw4_Release(ddraw4);
4458 /* Neither does a sequence of successful calls with the new interface */
4459 ddraw4 = create_ddraw();
4460 ok(!!ddraw4, "Failed to create a ddraw object.\n");
4461 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
4462 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4464 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4465 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4466 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4467 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4468 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_NORMAL);
4469 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4471 restored = test_mode_restored(ddraw4, window);
4472 ok(!restored, "Display mode restored after ddraw1-ddraw4 SetCooperativeLevel() call sequence\n");
4473 IDirectDraw_Release(ddraw);
4474 IDirectDraw4_Release(ddraw4);
4476 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
4477 ddraw4 = create_ddraw();
4478 ok(!!ddraw4, "Failed to create a ddraw object.\n");
4479 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
4480 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4482 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_NORMAL);
4483 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4485 memset(&ddsd, 0, sizeof(ddsd));
4486 ddsd.dwSize = sizeof(ddsd);
4487 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4488 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4489 ddsd.dwWidth = ddsd.dwHeight = 8;
4490 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4491 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
4492 IDirectDrawSurface_Release(surface);
4493 restored = test_mode_restored(ddraw4, window);
4494 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
4496 IDirectDraw_Release(ddraw);
4497 IDirectDraw4_Release(ddraw4);
4498 DestroyWindow(window);
4501 static void test_lighting_interface_versions(void)
4503 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
4504 IDirect3DMaterial3 *emissive;
4505 IDirect3DViewport3 *viewport;
4506 IDirect3DDevice3 *device;
4507 IDirectDrawSurface4 *rt;
4508 D3DCOLOR color;
4509 HWND window;
4510 HRESULT hr;
4511 D3DMATERIALHANDLE mat_handle;
4512 DWORD rs;
4513 unsigned int i;
4514 ULONG ref;
4515 static D3DVERTEX quad[] =
4517 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4518 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4519 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4520 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4523 #define FVF_COLORVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_SPECULAR)
4524 static struct
4526 struct vec3 position;
4527 struct vec3 normal;
4528 DWORD diffuse, specular;
4530 quad2[] =
4532 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4533 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4534 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4535 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4538 static D3DLVERTEX lquad[] =
4540 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4541 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4542 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4543 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4546 #define FVF_LVERTEX2 (D3DFVF_LVERTEX & ~D3DFVF_RESERVED1)
4547 static struct
4549 struct vec3 position;
4550 DWORD diffuse, specular;
4551 struct vec2 texcoord;
4553 lquad2[] =
4555 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4556 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4557 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4558 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4561 static D3DTLVERTEX tlquad[] =
4563 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4564 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4565 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4566 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4569 static const struct
4571 DWORD vertextype;
4572 void *data;
4573 DWORD d3drs_lighting, d3drs_specular;
4574 DWORD draw_flags;
4575 D3DCOLOR color;
4577 tests[] =
4579 /* Lighting is enabled when all of these conditions are met:
4580 * 1) No pretransformed position(D3DFVF_XYZRHW)
4581 * 2) Normals are available (D3DFVF_NORMAL)
4582 * 3) D3DDP_DONOTLIGHT is not set.
4584 * D3DRENDERSTATE_LIGHTING is ignored, it is not defined
4585 * in this d3d version */
4587 /* 0 */
4588 { D3DFVF_VERTEX, quad, FALSE, FALSE, 0, 0x0000ff00},
4589 { D3DFVF_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
4590 { D3DFVF_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
4591 { D3DFVF_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
4592 { D3DFVF_VERTEX, quad, FALSE, TRUE, 0, 0x0000ff00},
4593 { D3DFVF_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
4594 { D3DFVF_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
4595 { D3DFVF_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
4597 /* 8 */
4598 { FVF_COLORVERTEX, quad2, FALSE, FALSE, 0, 0x0000ff00},
4599 { FVF_COLORVERTEX, quad2, TRUE, FALSE, 0, 0x0000ff00},
4600 { FVF_COLORVERTEX, quad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4601 { FVF_COLORVERTEX, quad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4602 /* The specular color in the vertex is ignored because
4603 * D3DRENDERSTATE_COLORVERTEX is not enabled */
4604 { FVF_COLORVERTEX, quad2, FALSE, TRUE, 0, 0x0000ff00},
4605 { FVF_COLORVERTEX, quad2, TRUE, TRUE, 0, 0x0000ff00},
4606 { FVF_COLORVERTEX, quad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4607 { FVF_COLORVERTEX, quad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4609 /* 16 */
4610 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
4611 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, 0, 0x00ff0000},
4612 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4613 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4614 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
4615 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, 0, 0x00ff8080},
4616 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4617 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4619 /* 24 */
4620 { FVF_LVERTEX2, lquad2, FALSE, FALSE, 0, 0x00ff0000},
4621 { FVF_LVERTEX2, lquad2, TRUE, FALSE, 0, 0x00ff0000},
4622 { FVF_LVERTEX2, lquad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4623 { FVF_LVERTEX2, lquad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4624 { FVF_LVERTEX2, lquad2, FALSE, TRUE, 0, 0x00ff8080},
4625 { FVF_LVERTEX2, lquad2, TRUE, TRUE, 0, 0x00ff8080},
4626 { FVF_LVERTEX2, lquad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4627 { FVF_LVERTEX2, lquad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4629 /* 32 */
4630 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
4631 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
4632 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4633 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4634 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
4635 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
4636 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4637 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4640 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4641 0, 0, 640, 480, 0, 0, 0, 0);
4643 if (!(device = create_device(window, DDSCL_NORMAL)))
4645 skip("Failed to create a 3D device, skipping test.\n");
4646 DestroyWindow(window);
4647 return;
4650 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
4651 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4653 viewport = create_viewport(device, 0, 0, 640, 480);
4654 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
4655 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
4657 emissive = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
4658 hr = IDirect3DMaterial3_GetHandle(emissive, device, &mat_handle);
4659 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
4660 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
4661 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
4662 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
4663 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr);
4665 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
4666 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#x.\n", hr);
4667 ok(rs == FALSE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#x, expected FALSE.\n", rs);
4669 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4671 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff202020, 0.0f, 0);
4672 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4674 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
4675 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#x.\n", hr);
4676 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
4677 tests[i].d3drs_specular);
4678 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#x.\n", hr);
4680 hr = IDirect3DDevice3_BeginScene(device);
4681 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4682 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
4683 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
4684 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4685 hr = IDirect3DDevice3_EndScene(device);
4686 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4688 color = get_surface_color(rt, 320, 240);
4689 ok(compare_color(color, tests[i].color, 1),
4690 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
4691 color, tests[i].color, i);
4694 destroy_material(emissive);
4695 IDirectDrawSurface4_Release(rt);
4696 ref = IDirect3DDevice3_Release(device);
4697 ok(ref == 0, "Device not properly released, refcount %u.\n", ref);
4698 DestroyWindow(window);
4701 static struct
4703 BOOL received;
4704 IDirectDraw4 *ddraw;
4705 HWND window;
4706 DWORD coop_level;
4707 } activateapp_testdata;
4709 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
4711 if (message == WM_ACTIVATEAPP)
4713 if (activateapp_testdata.ddraw)
4715 HRESULT hr;
4716 activateapp_testdata.received = FALSE;
4717 hr = IDirectDraw4_SetCooperativeLevel(activateapp_testdata.ddraw,
4718 activateapp_testdata.window, activateapp_testdata.coop_level);
4719 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
4720 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
4722 activateapp_testdata.received = TRUE;
4725 return DefWindowProcA(hwnd, message, wparam, lparam);
4728 static void test_coop_level_activateapp(void)
4730 IDirectDraw4 *ddraw;
4731 HRESULT hr;
4732 HWND window;
4733 WNDCLASSA wc = {0};
4734 DDSURFACEDESC2 ddsd;
4735 IDirectDrawSurface4 *surface;
4737 ddraw = create_ddraw();
4738 ok(!!ddraw, "Failed to create a ddraw object.\n");
4740 wc.lpfnWndProc = activateapp_test_proc;
4741 wc.lpszClassName = "ddraw_test_wndproc_wc";
4742 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4744 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
4745 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
4747 /* Exclusive with window already active. */
4748 SetForegroundWindow(window);
4749 activateapp_testdata.received = FALSE;
4750 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4751 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4752 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
4753 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4754 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4756 /* Exclusive with window not active. */
4757 SetForegroundWindow(GetDesktopWindow());
4758 activateapp_testdata.received = FALSE;
4759 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4760 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4761 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4762 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4763 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4765 /* Normal with window not active, then exclusive with the same window. */
4766 SetForegroundWindow(GetDesktopWindow());
4767 activateapp_testdata.received = FALSE;
4768 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4769 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4770 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
4771 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4772 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4773 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4774 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4775 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4777 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
4778 SetForegroundWindow(GetDesktopWindow());
4779 activateapp_testdata.received = FALSE;
4780 activateapp_testdata.ddraw = ddraw;
4781 activateapp_testdata.window = window;
4782 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
4783 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4784 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4785 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4786 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4787 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4789 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
4790 * succeeding. Another switch to exclusive and back to normal is needed to release the
4791 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
4792 * WM_ACTIVATEAPP messages. */
4793 activateapp_testdata.ddraw = NULL;
4794 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4795 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4796 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4797 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4799 /* Setting DDSCL_NORMAL with recursive invocation. */
4800 SetForegroundWindow(GetDesktopWindow());
4801 activateapp_testdata.received = FALSE;
4802 activateapp_testdata.ddraw = ddraw;
4803 activateapp_testdata.window = window;
4804 activateapp_testdata.coop_level = DDSCL_NORMAL;
4805 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4806 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4807 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4809 /* DDraw is in exlusive mode now. */
4810 memset(&ddsd, 0, sizeof(ddsd));
4811 ddsd.dwSize = sizeof(ddsd);
4812 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
4813 U5(ddsd).dwBackBufferCount = 1;
4814 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
4815 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
4816 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4817 IDirectDrawSurface4_Release(surface);
4819 /* Recover again, just to be sure. */
4820 activateapp_testdata.ddraw = NULL;
4821 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4822 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4823 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4824 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4826 DestroyWindow(window);
4827 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
4828 IDirectDraw4_Release(ddraw);
4831 static void test_texturemanage(void)
4833 IDirectDraw4 *ddraw;
4834 HRESULT hr;
4835 DDSURFACEDESC2 ddsd;
4836 IDirectDrawSurface4 *surface;
4837 unsigned int i;
4838 DDCAPS hal_caps, hel_caps;
4839 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
4840 static const struct
4842 DWORD caps_in, caps2_in;
4843 HRESULT hr;
4844 DWORD caps_out, caps2_out;
4846 tests[] =
4848 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4849 ~0U, ~0U},
4850 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4851 ~0U, ~0U},
4852 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4853 ~0U, ~0U},
4854 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4855 ~0U, ~0U},
4856 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DD_OK,
4857 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE},
4858 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DD_OK,
4859 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE},
4860 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
4861 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_LOCALVIDMEM, 0},
4862 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
4863 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0},
4865 {0, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4866 ~0U, ~0U},
4867 {0, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4868 ~0U, ~0U},
4869 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4870 ~0U, ~0U},
4871 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4872 ~0U, ~0U},
4873 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4874 ~0U, ~0U},
4875 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4876 ~0U, ~0U},
4877 {DDSCAPS_VIDEOMEMORY, 0, DD_OK,
4878 DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY, 0},
4879 {DDSCAPS_SYSTEMMEMORY, 0, DD_OK,
4880 DDSCAPS_SYSTEMMEMORY, 0},
4883 ddraw = create_ddraw();
4884 ok(!!ddraw, "Failed to create a ddraw object.\n");
4885 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4886 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4888 memset(&hal_caps, 0, sizeof(hal_caps));
4889 hal_caps.dwSize = sizeof(hal_caps);
4890 memset(&hel_caps, 0, sizeof(hel_caps));
4891 hel_caps.dwSize = sizeof(hel_caps);
4892 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, &hel_caps);
4893 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
4894 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
4896 skip("Managed textures not supported, skipping managed texture test.\n");
4897 IDirectDraw4_Release(ddraw);
4898 return;
4901 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4903 memset(&ddsd, 0, sizeof(ddsd));
4904 ddsd.dwSize = sizeof(ddsd);
4905 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4906 ddsd.ddsCaps.dwCaps = tests[i].caps_in;
4907 ddsd.ddsCaps.dwCaps2 = tests[i].caps2_in;
4908 ddsd.dwWidth = 4;
4909 ddsd.dwHeight = 4;
4911 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
4912 ok(hr == tests[i].hr, "Got unexpected, hr %#x, case %u.\n", hr, i);
4913 if (FAILED(hr))
4914 continue;
4916 memset(&ddsd, 0, sizeof(ddsd));
4917 ddsd.dwSize = sizeof(ddsd);
4918 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
4919 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4921 ok(ddsd.ddsCaps.dwCaps == tests[i].caps_out,
4922 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
4923 tests[i].caps_in, tests[i].caps2_in, tests[i].caps_out, ddsd.ddsCaps.dwCaps, i);
4924 ok(ddsd.ddsCaps.dwCaps2 == tests[i].caps2_out,
4925 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
4926 tests[i].caps_in, tests[i].caps2_in, tests[i].caps2_out, ddsd.ddsCaps.dwCaps2, i);
4928 IDirectDrawSurface4_Release(surface);
4931 IDirectDraw4_Release(ddraw);
4934 #define SUPPORT_DXT1 0x01
4935 #define SUPPORT_DXT2 0x02
4936 #define SUPPORT_DXT3 0x04
4937 #define SUPPORT_DXT4 0x08
4938 #define SUPPORT_DXT5 0x10
4939 #define SUPPORT_YUY2 0x20
4940 #define SUPPORT_UYVY 0x40
4942 static HRESULT WINAPI test_block_formats_creation_cb(DDPIXELFORMAT *fmt, void *ctx)
4944 DWORD *supported_fmts = ctx;
4946 if (!(fmt->dwFlags & DDPF_FOURCC))
4947 return DDENUMRET_OK;
4949 switch (fmt->dwFourCC)
4951 case MAKEFOURCC('D','X','T','1'):
4952 *supported_fmts |= SUPPORT_DXT1;
4953 break;
4954 case MAKEFOURCC('D','X','T','2'):
4955 *supported_fmts |= SUPPORT_DXT2;
4956 break;
4957 case MAKEFOURCC('D','X','T','3'):
4958 *supported_fmts |= SUPPORT_DXT3;
4959 break;
4960 case MAKEFOURCC('D','X','T','4'):
4961 *supported_fmts |= SUPPORT_DXT4;
4962 break;
4963 case MAKEFOURCC('D','X','T','5'):
4964 *supported_fmts |= SUPPORT_DXT5;
4965 break;
4966 case MAKEFOURCC('Y','U','Y','2'):
4967 *supported_fmts |= SUPPORT_YUY2;
4968 break;
4969 case MAKEFOURCC('U','Y','V','Y'):
4970 *supported_fmts |= SUPPORT_UYVY;
4971 break;
4972 default:
4973 break;
4976 return DDENUMRET_OK;
4979 static void test_block_formats_creation(void)
4981 HRESULT hr, expect_hr;
4982 unsigned int i, j, w, h;
4983 HWND window;
4984 IDirectDraw4 *ddraw;
4985 IDirect3D3 *d3d;
4986 IDirect3DDevice3 *device;
4987 IDirectDrawSurface4 *surface;
4988 DWORD supported_fmts = 0, supported_overlay_fmts = 0;
4989 DWORD num_fourcc_codes = 0, *fourcc_codes;
4990 DDSURFACEDESC2 ddsd;
4991 DDCAPS hal_caps;
4992 void *mem;
4994 static const struct
4996 DWORD fourcc;
4997 const char *name;
4998 DWORD support_flag;
4999 unsigned int block_width;
5000 unsigned int block_height;
5001 unsigned int block_size;
5002 BOOL create_size_checked, overlay;
5004 formats[] =
5006 {MAKEFOURCC('D','X','T','1'), "D3DFMT_DXT1", SUPPORT_DXT1, 4, 4, 8, TRUE, FALSE},
5007 {MAKEFOURCC('D','X','T','2'), "D3DFMT_DXT2", SUPPORT_DXT2, 4, 4, 16, TRUE, FALSE},
5008 {MAKEFOURCC('D','X','T','3'), "D3DFMT_DXT3", SUPPORT_DXT3, 4, 4, 16, TRUE, FALSE},
5009 {MAKEFOURCC('D','X','T','4'), "D3DFMT_DXT4", SUPPORT_DXT4, 4, 4, 16, TRUE, FALSE},
5010 {MAKEFOURCC('D','X','T','5'), "D3DFMT_DXT5", SUPPORT_DXT5, 4, 4, 16, TRUE, FALSE},
5011 {MAKEFOURCC('Y','U','Y','2'), "D3DFMT_YUY2", SUPPORT_YUY2, 2, 1, 4, FALSE, TRUE },
5012 {MAKEFOURCC('U','Y','V','Y'), "D3DFMT_UYVY", SUPPORT_UYVY, 2, 1, 4, FALSE, TRUE },
5014 static const struct
5016 DWORD caps, caps2;
5017 const char *name;
5018 BOOL overlay;
5020 types[] =
5022 /* DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY fails to create any fourcc
5023 * surface with DDERR_INVALIDPIXELFORMAT. Don't care about it for now.
5025 * Nvidia returns E_FAIL on DXTN DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY.
5026 * Other hw / drivers successfully create those surfaces. Ignore them, this
5027 * suggests that no game uses this, otherwise Nvidia would support it. */
5029 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0,
5030 "videomemory texture", FALSE
5033 DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY, 0,
5034 "videomemory overlay", TRUE
5037 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0,
5038 "systemmemory texture", FALSE
5041 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
5042 "managed texture", FALSE
5045 enum size_type
5047 SIZE_TYPE_ZERO,
5048 SIZE_TYPE_PITCH,
5049 SIZE_TYPE_SIZE,
5051 static const struct
5053 DWORD flags;
5054 enum size_type size_type;
5055 int rel_size;
5056 HRESULT hr;
5058 user_mem_tests[] =
5060 {DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DD_OK},
5061 {DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
5062 {DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
5063 {DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
5064 {DDSD_LPSURFACE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
5065 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
5066 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
5067 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
5068 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 1, DD_OK},
5069 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, -1, DDERR_INVALIDPARAMS},
5070 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
5071 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
5072 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_SIZE, 0, DD_OK},
5073 {DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
5076 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5077 0, 0, 640, 480, 0, 0, 0, 0);
5079 if (!(device = create_device(window, DDSCL_NORMAL)))
5081 skip("Failed to create a 3D device, skipping test.\n");
5082 DestroyWindow(window);
5083 return;
5086 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
5087 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5088 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **) &ddraw);
5089 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5090 IDirect3D3_Release(d3d);
5092 hr = IDirect3DDevice3_EnumTextureFormats(device, test_block_formats_creation_cb,
5093 &supported_fmts);
5094 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
5096 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
5097 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
5098 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5099 num_fourcc_codes * sizeof(*fourcc_codes));
5100 if (!fourcc_codes)
5101 goto cleanup;
5102 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
5103 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
5104 for (i = 0; i < num_fourcc_codes; i++)
5106 for (j = 0; j < sizeof(formats) / sizeof(*formats); j++)
5108 if (fourcc_codes[i] == formats[j].fourcc)
5109 supported_overlay_fmts |= formats[j].support_flag;
5112 HeapFree(GetProcessHeap(), 0, fourcc_codes);
5114 memset(&hal_caps, 0, sizeof(hal_caps));
5115 hal_caps.dwSize = sizeof(hal_caps);
5116 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
5117 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5119 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * 2 * 16 + 1);
5121 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
5123 for (j = 0; j < sizeof(types) / sizeof(*types); j++)
5125 BOOL support;
5127 if (formats[i].overlay != types[j].overlay
5128 || (types[j].overlay && !(hal_caps.dwCaps & DDCAPS_OVERLAY)))
5129 continue;
5131 if (formats[i].overlay)
5132 support = supported_overlay_fmts & formats[i].support_flag;
5133 else
5134 support = supported_fmts & formats[i].support_flag;
5136 for (w = 1; w <= 8; w++)
5138 for (h = 1; h <= 8; h++)
5140 BOOL block_aligned = TRUE;
5141 BOOL todo = FALSE;
5143 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
5144 block_aligned = FALSE;
5146 memset(&ddsd, 0, sizeof(ddsd));
5147 ddsd.dwSize = sizeof(ddsd);
5148 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5149 ddsd.ddsCaps.dwCaps = types[j].caps;
5150 ddsd.ddsCaps.dwCaps2 = types[j].caps2;
5151 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5152 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
5153 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
5154 ddsd.dwWidth = w;
5155 ddsd.dwHeight = h;
5157 /* TODO: Handle power of two limitations. I cannot test the pow2
5158 * behavior on windows because I have no hardware that doesn't at
5159 * least support np2_conditional. There's probably no HW that
5160 * supports DXTN textures but no conditional np2 textures. */
5161 if (!support && !(types[j].caps & DDSCAPS_SYSTEMMEMORY))
5162 expect_hr = DDERR_INVALIDPARAMS;
5163 else if (formats[i].create_size_checked && !block_aligned)
5165 expect_hr = DDERR_INVALIDPARAMS;
5166 if (!(types[j].caps & DDSCAPS_TEXTURE))
5167 todo = TRUE;
5169 else
5170 expect_hr = D3D_OK;
5172 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5173 todo_wine_if (todo)
5174 ok(hr == expect_hr,
5175 "Got unexpected hr %#x for format %s, resource type %s, size %ux%u, expected %#x.\n",
5176 hr, formats[i].name, types[j].name, w, h, expect_hr);
5178 if (SUCCEEDED(hr))
5179 IDirectDrawSurface4_Release(surface);
5184 if (formats[i].overlay)
5185 continue;
5187 for (j = 0; j < sizeof(user_mem_tests) / sizeof(*user_mem_tests); ++j)
5189 memset(&ddsd, 0, sizeof(ddsd));
5190 ddsd.dwSize = sizeof(ddsd);
5191 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | user_mem_tests[j].flags;
5192 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE;
5194 switch (user_mem_tests[j].size_type)
5196 case SIZE_TYPE_ZERO:
5197 U1(ddsd).dwLinearSize = 0;
5198 break;
5200 case SIZE_TYPE_PITCH:
5201 U1(ddsd).dwLinearSize = 2 * formats[i].block_size;
5202 break;
5204 case SIZE_TYPE_SIZE:
5205 U1(ddsd).dwLinearSize = 2 * 2 * formats[i].block_size;
5206 break;
5208 U1(ddsd).dwLinearSize += user_mem_tests[j].rel_size;
5210 ddsd.lpSurface = mem;
5211 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5212 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
5213 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
5214 ddsd.dwWidth = 8;
5215 ddsd.dwHeight = 8;
5217 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5218 ok(hr == user_mem_tests[j].hr, "Test %u: Got unexpected hr %#x, format %s.\n", j, hr, formats[i].name);
5220 if (FAILED(hr))
5221 continue;
5223 memset(&ddsd, 0, sizeof(ddsd));
5224 ddsd.dwSize = sizeof(ddsd);
5225 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5226 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", j, hr);
5227 ok(ddsd.dwFlags == (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_LINEARSIZE),
5228 "Test %u: Got unexpected flags %#x.\n", j, ddsd.dwFlags);
5229 if (user_mem_tests[j].flags & DDSD_LPSURFACE)
5230 ok(U1(ddsd).dwLinearSize == ~0u, "Test %u: Got unexpected linear size %#x.\n",
5231 j, U1(ddsd).dwLinearSize);
5232 else
5233 ok(U1(ddsd).dwLinearSize == 2 * 2 * formats[i].block_size,
5234 "Test %u: Got unexpected linear size %#x, expected %#x.\n",
5235 j, U1(ddsd).dwLinearSize, 2 * 2 * formats[i].block_size);
5236 IDirectDrawSurface4_Release(surface);
5240 HeapFree(GetProcessHeap(), 0, mem);
5241 cleanup:
5242 IDirectDraw4_Release(ddraw);
5243 IDirect3DDevice3_Release(device);
5244 DestroyWindow(window);
5247 struct format_support_check
5249 const DDPIXELFORMAT *format;
5250 BOOL supported;
5253 static HRESULT WINAPI test_unsupported_formats_cb(DDPIXELFORMAT *fmt, void *ctx)
5255 struct format_support_check *format = ctx;
5257 if (!memcmp(format->format, fmt, sizeof(*fmt)))
5259 format->supported = TRUE;
5260 return DDENUMRET_CANCEL;
5263 return DDENUMRET_OK;
5266 static void test_unsupported_formats(void)
5268 HRESULT hr;
5269 BOOL expect_success;
5270 HWND window;
5271 IDirectDraw4 *ddraw;
5272 IDirect3D3 *d3d;
5273 IDirect3DDevice3 *device;
5274 IDirectDrawSurface4 *surface;
5275 DDSURFACEDESC2 ddsd;
5276 unsigned int i, j;
5277 DWORD expected_caps;
5278 static const struct
5280 const char *name;
5281 DDPIXELFORMAT fmt;
5283 formats[] =
5286 "D3DFMT_A8R8G8B8",
5288 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
5289 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
5293 "D3DFMT_P8",
5295 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5296 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
5300 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
5302 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5303 0, 0, 640, 480, 0, 0, 0, 0);
5305 if (!(device = create_device(window, DDSCL_NORMAL)))
5307 skip("Failed to create a 3D device, skipping test.\n");
5308 DestroyWindow(window);
5309 return;
5312 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
5313 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5314 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **) &ddraw);
5315 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5316 IDirect3D3_Release(d3d);
5318 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
5320 struct format_support_check check = {&formats[i].fmt, FALSE};
5321 hr = IDirect3DDevice3_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
5322 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
5324 for (j = 0; j < sizeof(caps) / sizeof(*caps); j++)
5326 memset(&ddsd, 0, sizeof(ddsd));
5327 ddsd.dwSize = sizeof(ddsd);
5328 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5329 U4(ddsd).ddpfPixelFormat = formats[i].fmt;
5330 ddsd.dwWidth = 4;
5331 ddsd.dwHeight = 4;
5332 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
5334 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
5335 expect_success = FALSE;
5336 else
5337 expect_success = TRUE;
5339 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5340 ok(SUCCEEDED(hr) == expect_success,
5341 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
5342 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
5343 if (FAILED(hr))
5344 continue;
5346 memset(&ddsd, 0, sizeof(ddsd));
5347 ddsd.dwSize = sizeof(ddsd);
5348 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5349 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5351 if (caps[j] & DDSCAPS_VIDEOMEMORY)
5352 expected_caps = DDSCAPS_VIDEOMEMORY;
5353 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
5354 expected_caps = DDSCAPS_SYSTEMMEMORY;
5355 else if (check.supported)
5356 expected_caps = DDSCAPS_VIDEOMEMORY;
5357 else
5358 expected_caps = DDSCAPS_SYSTEMMEMORY;
5360 ok(ddsd.ddsCaps.dwCaps & expected_caps,
5361 "Expected capability %#x, format %s, input cap %#x.\n",
5362 expected_caps, formats[i].name, caps[j]);
5364 IDirectDrawSurface4_Release(surface);
5368 IDirectDraw4_Release(ddraw);
5369 IDirect3DDevice3_Release(device);
5370 DestroyWindow(window);
5373 static void test_rt_caps(void)
5375 PALETTEENTRY palette_entries[256];
5376 IDirectDrawPalette *palette;
5377 IDirectDraw4 *ddraw;
5378 DDPIXELFORMAT z_fmt;
5379 IDirect3D3 *d3d;
5380 unsigned int i;
5381 ULONG refcount;
5382 HWND window;
5383 HRESULT hr;
5385 static const DDPIXELFORMAT p8_fmt =
5387 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5388 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
5391 const struct
5393 const DDPIXELFORMAT *pf;
5394 DWORD caps_in;
5395 DWORD caps_out;
5396 HRESULT create_device_hr;
5397 HRESULT set_rt_hr, alternative_set_rt_hr;
5399 test_data[] =
5402 NULL,
5403 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5404 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5405 D3D_OK,
5406 D3D_OK,
5407 D3D_OK,
5410 NULL,
5411 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5412 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5413 D3D_OK,
5414 D3D_OK,
5415 D3D_OK,
5418 NULL,
5419 DDSCAPS_OFFSCREENPLAIN,
5420 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5421 DDERR_INVALIDCAPS,
5422 DDERR_INVALIDCAPS,
5423 DDERR_INVALIDCAPS,
5426 NULL,
5427 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5428 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5429 D3DERR_SURFACENOTINVIDMEM,
5430 D3D_OK,
5431 D3D_OK,
5434 NULL,
5435 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5436 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5437 DDERR_INVALIDCAPS,
5438 DDERR_INVALIDCAPS,
5439 DDERR_INVALIDCAPS,
5442 NULL,
5443 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5444 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5445 D3D_OK,
5446 D3D_OK,
5447 D3D_OK,
5450 NULL,
5451 DDSCAPS_3DDEVICE,
5452 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5453 D3D_OK,
5454 D3D_OK,
5455 D3D_OK,
5458 NULL,
5460 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5461 DDERR_INVALIDCAPS,
5462 DDERR_INVALIDCAPS,
5463 DDERR_INVALIDCAPS,
5466 NULL,
5467 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5468 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5469 D3DERR_SURFACENOTINVIDMEM,
5470 D3D_OK,
5471 D3D_OK,
5474 NULL,
5475 DDSCAPS_SYSTEMMEMORY,
5476 DDSCAPS_SYSTEMMEMORY,
5477 DDERR_INVALIDCAPS,
5478 DDERR_INVALIDCAPS,
5479 DDERR_INVALIDCAPS,
5482 &p8_fmt,
5484 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5485 DDERR_INVALIDCAPS,
5486 DDERR_INVALIDCAPS,
5487 DDERR_INVALIDCAPS,
5490 &p8_fmt,
5491 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5492 ~0U /* AMD r200 */,
5493 DDERR_NOPALETTEATTACHED,
5494 DDERR_INVALIDCAPS,
5495 DDERR_INVALIDCAPS,
5498 &p8_fmt,
5499 DDSCAPS_OFFSCREENPLAIN,
5500 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5501 DDERR_INVALIDCAPS,
5502 DDERR_INVALIDCAPS,
5503 DDERR_INVALIDCAPS,
5506 &p8_fmt,
5507 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5508 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5509 DDERR_NOPALETTEATTACHED,
5510 DDERR_INVALIDCAPS,
5511 DDERR_INVALIDCAPS,
5514 &p8_fmt,
5515 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5516 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5517 DDERR_INVALIDCAPS,
5518 DDERR_INVALIDCAPS,
5519 DDERR_INVALIDCAPS,
5522 &z_fmt,
5523 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
5524 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5525 DDERR_INVALIDCAPS,
5526 DDERR_INVALIDPIXELFORMAT,
5527 D3D_OK /* r200 */,
5530 &z_fmt,
5531 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5532 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5533 DDERR_INVALIDCAPS,
5534 DDERR_INVALIDPIXELFORMAT,
5535 D3D_OK /* r200 */,
5538 &z_fmt,
5539 DDSCAPS_ZBUFFER,
5540 DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5541 DDERR_INVALIDCAPS,
5542 DDERR_INVALIDCAPS,
5543 DDERR_INVALIDCAPS,
5546 &z_fmt,
5547 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5548 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5549 DDERR_INVALIDCAPS,
5550 DDERR_INVALIDPIXELFORMAT,
5551 D3D_OK /* r200 */,
5554 &z_fmt,
5555 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5556 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5557 DDERR_INVALIDCAPS,
5558 DDERR_INVALIDCAPS,
5559 DDERR_INVALIDCAPS,
5563 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5564 0, 0, 640, 480, 0, 0, 0, 0);
5565 ddraw = create_ddraw();
5566 ok(!!ddraw, "Failed to create a ddraw object.\n");
5567 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5568 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5570 if (FAILED(IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
5572 skip("D3D interface is not available, skipping test.\n");
5573 goto done;
5576 memset(&z_fmt, 0, sizeof(z_fmt));
5577 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
5578 if (FAILED(hr) || !z_fmt.dwSize)
5580 skip("No depth buffer formats available, skipping test.\n");
5581 IDirect3D3_Release(d3d);
5582 goto done;
5585 memset(palette_entries, 0, sizeof(palette_entries));
5586 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
5587 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5589 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
5591 IDirectDrawSurface4 *surface, *rt, *expected_rt, *tmp;
5592 DDSURFACEDESC2 surface_desc;
5593 IDirect3DDevice3 *device;
5595 memset(&surface_desc, 0, sizeof(surface_desc));
5596 surface_desc.dwSize = sizeof(surface_desc);
5597 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5598 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5599 if (test_data[i].pf)
5601 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5602 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5604 surface_desc.dwWidth = 640;
5605 surface_desc.dwHeight = 480;
5606 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5607 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
5608 i, test_data[i].caps_in, hr);
5610 memset(&surface_desc, 0, sizeof(surface_desc));
5611 surface_desc.dwSize = sizeof(surface_desc);
5612 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
5613 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5614 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
5615 "Test %u: Got unexpected caps %#x, expected %#x.\n",
5616 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5618 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
5619 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
5620 i, hr, test_data[i].create_device_hr);
5621 if (FAILED(hr))
5623 if (hr == DDERR_NOPALETTEATTACHED)
5625 hr = IDirectDrawSurface4_SetPalette(surface, palette);
5626 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
5627 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
5628 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
5629 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
5630 else
5631 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
5633 IDirectDrawSurface4_Release(surface);
5635 memset(&surface_desc, 0, sizeof(surface_desc));
5636 surface_desc.dwSize = sizeof(surface_desc);
5637 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5638 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5639 surface_desc.dwWidth = 640;
5640 surface_desc.dwHeight = 480;
5641 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5642 ok(SUCCEEDED(hr), "Test %u: Failed to create surface, hr %#x.\n", i, hr);
5644 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
5645 ok(SUCCEEDED(hr), "Test %u: Failed to create device, hr %#x.\n", i, hr);
5648 memset(&surface_desc, 0, sizeof(surface_desc));
5649 surface_desc.dwSize = sizeof(surface_desc);
5650 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5651 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5652 if (test_data[i].pf)
5654 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5655 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5657 surface_desc.dwWidth = 640;
5658 surface_desc.dwHeight = 480;
5659 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &rt, NULL);
5660 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
5661 i, test_data[i].caps_in, hr);
5663 hr = IDirect3DDevice3_SetRenderTarget(device, rt, 0);
5664 ok(hr == test_data[i].set_rt_hr || broken(hr == test_data[i].alternative_set_rt_hr),
5665 "Test %u: Got unexpected hr %#x, expected %#x.\n",
5666 i, hr, test_data[i].set_rt_hr);
5667 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
5668 expected_rt = rt;
5669 else
5670 expected_rt = surface;
5672 hr = IDirect3DDevice3_GetRenderTarget(device, &tmp);
5673 ok(SUCCEEDED(hr), "Test %u: Failed to get render target, hr %#x.\n", i, hr);
5674 ok(tmp == expected_rt, "Test %u: Got unexpected rt %p.\n", i, tmp);
5676 IDirectDrawSurface4_Release(tmp);
5677 IDirectDrawSurface4_Release(rt);
5678 refcount = IDirect3DDevice3_Release(device);
5679 ok(refcount == 0, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
5680 refcount = IDirectDrawSurface4_Release(surface);
5681 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
5684 IDirectDrawPalette_Release(palette);
5685 IDirect3D3_Release(d3d);
5687 done:
5688 refcount = IDirectDraw4_Release(ddraw);
5689 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5690 DestroyWindow(window);
5693 static void test_primary_caps(void)
5695 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
5696 IDirectDrawSurface4 *surface;
5697 DDSURFACEDESC2 surface_desc;
5698 IDirectDraw4 *ddraw;
5699 unsigned int i;
5700 ULONG refcount;
5701 HWND window;
5702 HRESULT hr;
5704 static const struct
5706 DWORD coop_level;
5707 DWORD caps_in;
5708 DWORD back_buffer_count;
5709 HRESULT hr;
5710 DWORD caps_out;
5712 test_data[] =
5715 DDSCL_NORMAL,
5716 DDSCAPS_PRIMARYSURFACE,
5717 ~0u,
5718 DD_OK,
5719 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
5722 DDSCL_NORMAL,
5723 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
5724 ~0u,
5725 DDERR_INVALIDCAPS,
5726 ~0u,
5729 DDSCL_NORMAL,
5730 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
5731 ~0u,
5732 DDERR_INVALIDCAPS,
5733 ~0u,
5736 DDSCL_NORMAL,
5737 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
5738 ~0u,
5739 DDERR_INVALIDCAPS,
5740 ~0u,
5743 DDSCL_NORMAL,
5744 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
5745 ~0u,
5746 DDERR_INVALIDCAPS,
5747 ~0u,
5750 DDSCL_NORMAL,
5751 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
5752 ~0u,
5753 DDERR_INVALIDCAPS,
5754 ~0u,
5757 DDSCL_NORMAL,
5758 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5759 ~0u,
5760 DDERR_INVALIDCAPS,
5761 ~0u,
5764 DDSCL_NORMAL,
5765 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5767 DDERR_INVALIDCAPS,
5768 ~0u,
5771 DDSCL_NORMAL,
5772 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5774 DDERR_NOEXCLUSIVEMODE,
5775 ~0u,
5778 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5779 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5781 DDERR_INVALIDCAPS,
5782 ~0u,
5785 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5786 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5788 DD_OK,
5789 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
5792 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5793 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
5795 DDERR_INVALIDCAPS,
5796 ~0u,
5799 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5800 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
5802 DDERR_INVALIDCAPS,
5803 ~0u,
5807 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5808 0, 0, 640, 480, 0, 0, 0, 0);
5809 ddraw = create_ddraw();
5810 ok(!!ddraw, "Failed to create a ddraw object.\n");
5812 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
5814 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
5815 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5817 memset(&surface_desc, 0, sizeof(surface_desc));
5818 surface_desc.dwSize = sizeof(surface_desc);
5819 surface_desc.dwFlags = DDSD_CAPS;
5820 if (test_data[i].back_buffer_count != ~0u)
5821 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
5822 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5823 U5(surface_desc).dwBackBufferCount = test_data[i].back_buffer_count;
5824 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5825 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
5826 if (FAILED(hr))
5827 continue;
5829 memset(&surface_desc, 0, sizeof(surface_desc));
5830 surface_desc.dwSize = sizeof(surface_desc);
5831 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
5832 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5833 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
5834 "Test %u: Got unexpected caps %#x, expected %#x.\n",
5835 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5837 IDirectDrawSurface4_Release(surface);
5840 refcount = IDirectDraw4_Release(ddraw);
5841 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5842 DestroyWindow(window);
5845 static void test_surface_lock(void)
5847 IDirectDraw4 *ddraw;
5848 IDirect3D3 *d3d = NULL;
5849 IDirectDrawSurface4 *surface;
5850 HRESULT hr;
5851 HWND window;
5852 unsigned int i;
5853 DDSURFACEDESC2 ddsd;
5854 ULONG refcount;
5855 DDPIXELFORMAT z_fmt;
5856 static const struct
5858 DWORD caps;
5859 DWORD caps2;
5860 const char *name;
5862 tests[] =
5865 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
5867 "videomemory offscreenplain"
5870 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5872 "systemmemory offscreenplain"
5875 DDSCAPS_PRIMARYSURFACE,
5877 "primary"
5880 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
5882 "videomemory texture"
5885 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
5886 DDSCAPS2_OPAQUE,
5887 "opaque videomemory texture"
5890 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
5892 "systemmemory texture"
5895 DDSCAPS_TEXTURE,
5896 DDSCAPS2_TEXTUREMANAGE,
5897 "managed texture"
5900 DDSCAPS_TEXTURE,
5901 DDSCAPS2_D3DTEXTUREMANAGE,
5902 "managed texture"
5905 DDSCAPS_TEXTURE,
5906 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_OPAQUE,
5907 "opaque managed texture"
5910 DDSCAPS_TEXTURE,
5911 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_OPAQUE,
5912 "opaque managed texture"
5915 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5917 "render target"
5920 DDSCAPS_ZBUFFER,
5922 "Z buffer"
5926 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5927 0, 0, 640, 480, 0, 0, 0, 0);
5928 ddraw = create_ddraw();
5929 ok(!!ddraw, "Failed to create a ddraw object.\n");
5930 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5931 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5933 if (FAILED(IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
5935 skip("D3D interface is not available, skipping test.\n");
5936 goto done;
5939 memset(&z_fmt, 0, sizeof(z_fmt));
5940 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
5941 if (FAILED(hr) || !z_fmt.dwSize)
5943 skip("No depth buffer formats available, skipping test.\n");
5944 goto done;
5947 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
5949 memset(&ddsd, 0, sizeof(ddsd));
5950 ddsd.dwSize = sizeof(ddsd);
5951 ddsd.dwFlags = DDSD_CAPS;
5952 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
5954 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
5955 ddsd.dwWidth = 64;
5956 ddsd.dwHeight = 64;
5958 if (tests[i].caps & DDSCAPS_ZBUFFER)
5960 ddsd.dwFlags |= DDSD_PIXELFORMAT;
5961 U4(ddsd).ddpfPixelFormat = z_fmt;
5963 ddsd.ddsCaps.dwCaps = tests[i].caps;
5964 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
5966 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5967 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
5969 memset(&ddsd, 0, sizeof(ddsd));
5970 ddsd.dwSize = sizeof(ddsd);
5971 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
5972 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
5973 if (SUCCEEDED(hr))
5975 hr = IDirectDrawSurface4_Unlock(surface, NULL);
5976 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
5979 IDirectDrawSurface4_Release(surface);
5982 done:
5983 if (d3d)
5984 IDirect3D3_Release(d3d);
5985 refcount = IDirectDraw4_Release(ddraw);
5986 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5987 DestroyWindow(window);
5990 static void test_surface_discard(void)
5992 IDirect3DDevice3 *device;
5993 IDirect3D3 *d3d;
5994 IDirectDraw4 *ddraw;
5995 HRESULT hr;
5996 HWND window;
5997 DDSURFACEDESC2 ddsd;
5998 IDirectDrawSurface4 *surface, *target;
5999 void *addr;
6000 static const struct
6002 DWORD caps, caps2;
6003 BOOL discard;
6005 tests[] =
6007 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, TRUE},
6008 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
6009 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, TRUE},
6010 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
6011 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE},
6012 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
6013 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE},
6014 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
6016 unsigned int i;
6018 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6019 0, 0, 640, 480, 0, 0, 0, 0);
6021 if (!(device = create_device(window, DDSCL_NORMAL)))
6023 skip("Failed to create a 3D device, skipping test.\n");
6024 DestroyWindow(window);
6025 return;
6027 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
6028 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
6029 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
6030 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
6031 hr = IDirect3DDevice3_GetRenderTarget(device, &target);
6032 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
6034 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
6036 BOOL discarded;
6038 memset(&ddsd, 0, sizeof(ddsd));
6039 ddsd.dwSize = sizeof(ddsd);
6040 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6041 ddsd.ddsCaps.dwCaps = tests[i].caps;
6042 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
6043 ddsd.dwWidth = 64;
6044 ddsd.dwHeight = 64;
6045 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6046 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x, case %u.\n", hr, i);
6048 memset(&ddsd, 0, sizeof(ddsd));
6049 ddsd.dwSize = sizeof(ddsd);
6050 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, 0, NULL);
6051 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6052 addr = ddsd.lpSurface;
6053 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6054 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6056 memset(&ddsd, 0, sizeof(ddsd));
6057 ddsd.dwSize = sizeof(ddsd);
6058 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
6059 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6060 discarded = ddsd.lpSurface != addr;
6061 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6062 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6064 hr = IDirectDrawSurface4_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
6065 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
6067 memset(&ddsd, 0, sizeof(ddsd));
6068 ddsd.dwSize = sizeof(ddsd);
6069 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
6070 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6071 discarded |= ddsd.lpSurface != addr;
6072 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6073 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6075 IDirectDrawSurface4_Release(surface);
6077 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
6078 * AMD r500, evergreen). Windows XP, at least on AMD r200, does not. */
6079 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
6082 IDirectDrawSurface4_Release(target);
6083 IDirectDraw4_Release(ddraw);
6084 IDirect3D3_Release(d3d);
6085 IDirect3DDevice3_Release(device);
6086 DestroyWindow(window);
6089 static void test_flip(void)
6091 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
6092 IDirectDrawSurface4 *frontbuffer, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
6093 DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}};
6094 DDSURFACEDESC2 surface_desc;
6095 BOOL sysmem_primary;
6096 IDirectDraw4 *ddraw;
6097 DWORD expected_caps;
6098 unsigned int i;
6099 D3DCOLOR color;
6100 ULONG refcount;
6101 HWND window;
6102 DDBLTFX fx;
6103 HRESULT hr;
6105 static const struct
6107 const char *name;
6108 DWORD caps;
6110 test_data[] =
6112 {"PRIMARYSURFACE", DDSCAPS_PRIMARYSURFACE},
6113 {"OFFSCREENPLAIN", DDSCAPS_OFFSCREENPLAIN},
6114 {"TEXTURE", DDSCAPS_TEXTURE},
6117 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6118 0, 0, 640, 480, 0, 0, 0, 0);
6119 ddraw = create_ddraw();
6120 ok(!!ddraw, "Failed to create a ddraw object.\n");
6122 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6123 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6125 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
6127 memset(&surface_desc, 0, sizeof(surface_desc));
6128 surface_desc.dwSize = sizeof(surface_desc);
6129 surface_desc.dwFlags = DDSD_CAPS;
6130 if (!(test_data[i].caps & DDSCAPS_PRIMARYSURFACE))
6131 surface_desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6132 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
6133 surface_desc.dwWidth = 512;
6134 surface_desc.dwHeight = 512;
6135 U5(surface_desc).dwBackBufferCount = 3;
6136 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6137 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6139 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
6140 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
6141 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6142 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6144 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
6145 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
6146 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6147 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6149 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
6150 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6151 todo_wine_if(test_data[i].caps & DDSCAPS_TEXTURE)
6152 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
6153 if (FAILED(hr))
6154 continue;
6156 memset(&surface_desc, 0, sizeof(surface_desc));
6157 surface_desc.dwSize = sizeof(surface_desc);
6158 hr = IDirectDrawSurface4_GetSurfaceDesc(frontbuffer, &surface_desc);
6159 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6160 expected_caps = DDSCAPS_FRONTBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
6161 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
6162 expected_caps |= DDSCAPS_VISIBLE;
6163 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6164 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6165 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
6167 hr = IDirectDrawSurface4_GetAttachedSurface(frontbuffer, &caps, &backbuffer1);
6168 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6169 memset(&surface_desc, 0, sizeof(surface_desc));
6170 surface_desc.dwSize = sizeof(surface_desc);
6171 hr = IDirectDrawSurface4_GetSurfaceDesc(backbuffer1, &surface_desc);
6172 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6173 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6174 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6175 expected_caps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER);
6176 expected_caps |= DDSCAPS_BACKBUFFER;
6177 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6178 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6180 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
6181 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6182 memset(&surface_desc, 0, sizeof(surface_desc));
6183 surface_desc.dwSize = sizeof(surface_desc);
6184 hr = IDirectDrawSurface4_GetSurfaceDesc(backbuffer2, &surface_desc);
6185 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6186 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6187 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6188 expected_caps &= ~DDSCAPS_BACKBUFFER;
6189 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6190 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6192 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
6193 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6194 memset(&surface_desc, 0, sizeof(surface_desc));
6195 surface_desc.dwSize = sizeof(surface_desc);
6196 hr = IDirectDrawSurface4_GetSurfaceDesc(backbuffer3, &surface_desc);
6197 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6198 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6199 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6200 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6201 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6203 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer3, &caps, &surface);
6204 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6205 ok(surface == frontbuffer, "%s: Got unexpected surface %p, expected %p.\n",
6206 test_data[i].name, surface, frontbuffer);
6207 IDirectDrawSurface4_Release(surface);
6209 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
6210 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
6211 hr = IDirectDrawSurface4_IsLost(frontbuffer);
6212 ok(hr == DD_OK, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6213 hr = IDirectDrawSurface4_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6214 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
6215 ok(hr == DDERR_NOEXCLUSIVEMODE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6216 else
6217 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6218 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6219 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
6220 hr = IDirectDrawSurface4_IsLost(frontbuffer);
6221 todo_wine ok(hr == DDERR_SURFACELOST, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6222 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
6223 ok(SUCCEEDED(hr), "%s: Failed to restore surfaces, hr %#x.\n", test_data[i].name, hr);
6225 memset(&surface_desc, 0, sizeof(surface_desc));
6226 surface_desc.dwSize = sizeof(surface_desc);
6227 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6228 surface_desc.ddsCaps.dwCaps = 0;
6229 surface_desc.dwWidth = 640;
6230 surface_desc.dwHeight = 480;
6231 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6232 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
6233 hr = IDirectDrawSurface4_Flip(frontbuffer, surface, DDFLIP_WAIT);
6234 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6235 IDirectDrawSurface4_Release(surface);
6237 hr = IDirectDrawSurface4_Flip(frontbuffer, frontbuffer, DDFLIP_WAIT);
6238 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6239 hr = IDirectDrawSurface4_Flip(backbuffer1, NULL, DDFLIP_WAIT);
6240 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6241 hr = IDirectDrawSurface4_Flip(backbuffer2, NULL, DDFLIP_WAIT);
6242 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6243 hr = IDirectDrawSurface4_Flip(backbuffer3, NULL, DDFLIP_WAIT);
6244 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6246 memset(&fx, 0, sizeof(fx));
6247 fx.dwSize = sizeof(fx);
6248 U5(fx).dwFillColor = 0xffff0000;
6249 hr = IDirectDrawSurface4_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6250 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
6251 U5(fx).dwFillColor = 0xff00ff00;
6252 hr = IDirectDrawSurface4_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6253 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
6254 U5(fx).dwFillColor = 0xff0000ff;
6255 hr = IDirectDrawSurface4_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6256 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
6258 hr = IDirectDrawSurface4_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6259 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6260 color = get_surface_color(backbuffer1, 320, 240);
6261 /* The testbot seems to just copy the contents of one surface to all the
6262 * others, instead of properly flipping. */
6263 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6264 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6265 color = get_surface_color(backbuffer2, 320, 240);
6266 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6267 U5(fx).dwFillColor = 0xffff0000;
6268 hr = IDirectDrawSurface4_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6269 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
6271 hr = IDirectDrawSurface4_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6272 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6273 color = get_surface_color(backbuffer1, 320, 240);
6274 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6275 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6276 color = get_surface_color(backbuffer2, 320, 240);
6277 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6278 U5(fx).dwFillColor = 0xff00ff00;
6279 hr = IDirectDrawSurface4_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6280 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
6282 hr = IDirectDrawSurface4_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6283 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6284 color = get_surface_color(backbuffer1, 320, 240);
6285 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6286 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6287 color = get_surface_color(backbuffer2, 320, 240);
6288 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6289 U5(fx).dwFillColor = 0xff0000ff;
6290 hr = IDirectDrawSurface4_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6291 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
6293 hr = IDirectDrawSurface4_Flip(frontbuffer, backbuffer1, DDFLIP_WAIT);
6294 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6295 color = get_surface_color(backbuffer2, 320, 240);
6296 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6297 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6298 color = get_surface_color(backbuffer3, 320, 240);
6299 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6300 U5(fx).dwFillColor = 0xffff0000;
6301 hr = IDirectDrawSurface4_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6302 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
6304 hr = IDirectDrawSurface4_Flip(frontbuffer, backbuffer2, DDFLIP_WAIT);
6305 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6306 color = get_surface_color(backbuffer1, 320, 240);
6307 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6308 color = get_surface_color(backbuffer3, 320, 240);
6309 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6310 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6311 U5(fx).dwFillColor = 0xff00ff00;
6312 hr = IDirectDrawSurface4_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6313 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
6315 hr = IDirectDrawSurface4_Flip(frontbuffer, backbuffer3, DDFLIP_WAIT);
6316 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6317 color = get_surface_color(backbuffer1, 320, 240);
6318 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6319 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6320 color = get_surface_color(backbuffer2, 320, 240);
6321 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6323 IDirectDrawSurface4_Release(backbuffer3);
6324 IDirectDrawSurface4_Release(backbuffer2);
6325 IDirectDrawSurface4_Release(backbuffer1);
6326 IDirectDrawSurface4_Release(frontbuffer);
6329 refcount = IDirectDraw4_Release(ddraw);
6330 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6331 DestroyWindow(window);
6334 static void reset_ddsd(DDSURFACEDESC2 *ddsd)
6336 memset(ddsd, 0, sizeof(*ddsd));
6337 ddsd->dwSize = sizeof(*ddsd);
6340 static void test_set_surface_desc(void)
6342 IDirectDraw4 *ddraw;
6343 HWND window;
6344 HRESULT hr;
6345 DDSURFACEDESC2 ddsd;
6346 IDirectDrawSurface4 *surface;
6347 BYTE data[16*16*4];
6348 ULONG ref;
6349 unsigned int i;
6350 static const struct
6352 DWORD caps, caps2;
6353 BOOL supported;
6354 const char *name;
6356 invalid_caps_tests[] =
6358 {DDSCAPS_VIDEOMEMORY, 0, FALSE, "videomemory plain"},
6359 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, TRUE, "systemmemory texture"},
6360 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE, "managed texture"},
6361 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE, "managed texture"},
6362 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, 0, FALSE, "systemmemory primary"},
6365 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6366 0, 0, 640, 480, 0, 0, 0, 0);
6367 ddraw = create_ddraw();
6368 ok(!!ddraw, "Failed to create a ddraw object.\n");
6369 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6370 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6372 reset_ddsd(&ddsd);
6373 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6374 ddsd.dwWidth = 8;
6375 ddsd.dwHeight = 8;
6376 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6377 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6378 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6379 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6380 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6381 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6382 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6384 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6385 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6387 reset_ddsd(&ddsd);
6388 ddsd.dwFlags = DDSD_LPSURFACE;
6389 ddsd.lpSurface = data;
6390 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6391 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6393 /* Redundantly setting the same lpSurface is not an error. */
6394 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6395 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6396 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6397 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6398 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6399 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
6401 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, 0, NULL);
6402 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6403 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6404 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
6405 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6406 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6408 reset_ddsd(&ddsd);
6409 ddsd.dwFlags = DDSD_LPSURFACE;
6410 ddsd.lpSurface = data;
6411 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 1);
6412 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
6414 ddsd.lpSurface = NULL;
6415 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6416 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
6418 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, NULL, 0);
6419 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
6421 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6422 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6423 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6424 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6425 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6427 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
6428 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6429 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
6431 ddsd.dwFlags = DDSD_CAPS;
6432 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6433 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
6435 /* dwCaps = 0 is allowed, but ignored. Caps2 can be anything and is ignored too. */
6436 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
6437 ddsd.lpSurface = data;
6438 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6439 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6440 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6441 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6442 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6443 ddsd.ddsCaps.dwCaps = 0;
6444 ddsd.ddsCaps.dwCaps2 = 0xdeadbeef;
6445 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6446 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6448 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6449 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6450 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6451 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6452 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6454 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
6455 reset_ddsd(&ddsd);
6456 ddsd.dwFlags = DDSD_HEIGHT;
6457 ddsd.dwHeight = 16;
6458 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6459 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
6461 ddsd.lpSurface = data;
6462 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
6463 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6464 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6466 ddsd.dwHeight = 0;
6467 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6468 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
6470 reset_ddsd(&ddsd);
6471 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6472 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
6473 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6474 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6476 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0 */
6477 reset_ddsd(&ddsd);
6478 ddsd.dwFlags = DDSD_PITCH;
6479 U1(ddsd).lPitch = 8 * 4;
6480 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6481 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
6483 ddsd.dwFlags = DDSD_WIDTH;
6484 ddsd.dwWidth = 16;
6485 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6486 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
6488 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
6489 ddsd.lpSurface = data;
6490 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6491 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
6493 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
6494 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6495 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
6497 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6498 U1(ddsd).lPitch = 16 * 4;
6499 ddsd.dwWidth = 16;
6500 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6501 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6503 reset_ddsd(&ddsd);
6504 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6505 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6506 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6507 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6508 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
6510 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
6512 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
6513 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6514 U1(ddsd).lPitch = 4 * 4;
6515 ddsd.lpSurface = data;
6516 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6517 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
6519 U1(ddsd).lPitch = 4;
6520 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6521 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
6523 U1(ddsd).lPitch = 16 * 4 + 1;
6524 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6525 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
6527 U1(ddsd).lPitch = 16 * 4 + 3;
6528 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6529 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
6531 U1(ddsd).lPitch = -4;
6532 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6533 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
6535 U1(ddsd).lPitch = 16 * 4;
6536 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6537 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6539 reset_ddsd(&ddsd);
6540 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6541 U1(ddsd).lPitch = 0;
6542 ddsd.dwWidth = 16;
6543 ddsd.lpSurface = data;
6544 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6545 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
6547 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6548 U1(ddsd).lPitch = 16 * 4;
6549 ddsd.dwWidth = 0;
6550 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6551 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
6553 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
6554 ddsd.dwFlags = DDSD_PIXELFORMAT;
6555 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6556 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6557 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6558 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6559 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6560 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6561 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6562 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
6564 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
6565 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6566 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6568 /* Can't set color keys. */
6569 reset_ddsd(&ddsd);
6570 ddsd.dwFlags = DDSD_CKSRCBLT;
6571 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
6572 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
6573 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6574 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
6576 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
6577 ddsd.lpSurface = data;
6578 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6579 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
6581 IDirectDrawSurface4_Release(surface);
6583 /* SetSurfaceDesc needs systemmemory surfaces.
6585 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing DDSD_LINEARSIZE is moot. */
6586 for (i = 0; i < sizeof(invalid_caps_tests) / sizeof(*invalid_caps_tests); i++)
6588 reset_ddsd(&ddsd);
6589 ddsd.dwFlags = DDSD_CAPS;
6590 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
6591 ddsd.ddsCaps.dwCaps2 = invalid_caps_tests[i].caps2;
6592 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
6594 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6595 ddsd.dwWidth = 8;
6596 ddsd.dwHeight = 8;
6597 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6598 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6599 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6600 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6601 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6602 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6605 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6606 ok(SUCCEEDED(hr) || hr == DDERR_NODIRECTDRAWHW, "Failed to create surface, hr %#x.\n", hr);
6607 if (FAILED(hr))
6609 skip("Cannot create a %s surface, skipping vidmem SetSurfaceDesc test.\n",
6610 invalid_caps_tests[i].name);
6611 goto done;
6614 reset_ddsd(&ddsd);
6615 ddsd.dwFlags = DDSD_LPSURFACE;
6616 ddsd.lpSurface = data;
6617 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6618 if (invalid_caps_tests[i].supported)
6620 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6622 else
6624 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
6625 invalid_caps_tests[i].name, hr);
6627 /* Check priority of error conditions. */
6628 ddsd.dwFlags = DDSD_WIDTH;
6629 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6630 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
6631 invalid_caps_tests[i].name, hr);
6634 IDirectDrawSurface4_Release(surface);
6637 done:
6638 ref = IDirectDraw4_Release(ddraw);
6639 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6640 DestroyWindow(window);
6643 static void test_user_memory_getdc(void)
6645 IDirectDraw4 *ddraw;
6646 HWND window;
6647 HRESULT hr;
6648 DDSURFACEDESC2 ddsd;
6649 IDirectDrawSurface4 *surface;
6650 DWORD data[16][16];
6651 HBITMAP bitmap;
6652 DIBSECTION dib;
6653 ULONG ref;
6654 int size;
6655 HDC dc;
6656 unsigned int x, y;
6658 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6659 0, 0, 640, 480, 0, 0, 0, 0);
6660 ddraw = create_ddraw();
6661 ok(!!ddraw, "Failed to create a ddraw object.\n");
6663 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6664 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6666 reset_ddsd(&ddsd);
6667 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6668 ddsd.dwWidth = 16;
6669 ddsd.dwHeight = 16;
6670 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6671 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6672 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6673 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6674 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6675 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6676 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6677 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6678 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6680 memset(data, 0xaa, sizeof(data));
6681 reset_ddsd(&ddsd);
6682 ddsd.dwFlags = DDSD_LPSURFACE;
6683 ddsd.lpSurface = data;
6684 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6685 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6687 hr = IDirectDrawSurface4_GetDC(surface, &dc);
6688 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6689 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
6690 ok(!!bitmap, "Failed to get bitmap.\n");
6691 size = GetObjectA(bitmap, sizeof(dib), &dib);
6692 ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
6693 ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
6694 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
6695 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
6696 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
6697 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6699 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
6700 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
6702 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
6703 ddsd.lpSurface = data;
6704 ddsd.dwWidth = 4;
6705 ddsd.dwHeight = 8;
6706 U1(ddsd).lPitch = sizeof(*data);
6707 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6708 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6710 memset(data, 0xaa, sizeof(data));
6711 hr = IDirectDrawSurface4_GetDC(surface, &dc);
6712 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6713 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
6714 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
6715 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
6716 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6718 for (y = 0; y < 4; y++)
6720 for (x = 0; x < 4; x++)
6722 if ((x == 1 || x == 2) && (y == 1 || y == 2))
6723 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
6724 x, y, data[y][x]);
6725 else
6726 ok(data[y][x] == 0x00000000, "Expected color 0x00000000 on position %ux%u, got %#x.\n",
6727 x, y, data[y][x]);
6730 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
6731 data[0][5]);
6732 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
6733 data[7][3]);
6734 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
6735 data[7][4]);
6736 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
6737 data[8][0]);
6739 IDirectDrawSurface4_Release(surface);
6740 ref = IDirectDraw4_Release(ddraw);
6741 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6742 DestroyWindow(window);
6745 static void test_sysmem_overlay(void)
6747 IDirectDraw4 *ddraw;
6748 HWND window;
6749 HRESULT hr;
6750 DDSURFACEDESC2 ddsd;
6751 IDirectDrawSurface4 *surface;
6752 ULONG ref;
6754 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6755 0, 0, 640, 480, 0, 0, 0, 0);
6756 ddraw = create_ddraw();
6757 ok(!!ddraw, "Failed to create a ddraw object.\n");
6759 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6760 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6762 reset_ddsd(&ddsd);
6763 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
6764 ddsd.dwWidth = 16;
6765 ddsd.dwHeight = 16;
6766 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
6767 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6768 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6769 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6770 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6771 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6772 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6773 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6774 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
6776 ref = IDirectDraw4_Release(ddraw);
6777 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6778 DestroyWindow(window);
6781 static void test_primary_palette(void)
6783 DDSCAPS2 surface_caps = {DDSCAPS_FLIP, 0, 0, {0}};
6784 IDirectDrawSurface4 *primary, *backbuffer;
6785 PALETTEENTRY palette_entries[256];
6786 IDirectDrawPalette *palette, *tmp;
6787 DDSURFACEDESC2 surface_desc;
6788 IDirectDraw4 *ddraw;
6789 DWORD palette_caps;
6790 ULONG refcount;
6791 HWND window;
6792 HRESULT hr;
6794 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6795 0, 0, 640, 480, 0, 0, 0, 0);
6796 ddraw = create_ddraw();
6797 ok(!!ddraw, "Failed to create a ddraw object.\n");
6798 if (FAILED(IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
6800 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
6801 IDirectDraw4_Release(ddraw);
6802 DestroyWindow(window);
6803 return;
6805 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6806 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6808 memset(&surface_desc, 0, sizeof(surface_desc));
6809 surface_desc.dwSize = sizeof(surface_desc);
6810 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
6811 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
6812 U5(surface_desc).dwBackBufferCount = 1;
6813 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
6814 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6815 hr = IDirectDrawSurface4_GetAttachedSurface(primary, &surface_caps, &backbuffer);
6816 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
6818 memset(palette_entries, 0, sizeof(palette_entries));
6819 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
6820 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6821 refcount = get_refcount((IUnknown *)palette);
6822 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6824 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6825 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6826 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
6828 hr = IDirectDrawSurface4_SetPalette(primary, palette);
6829 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6831 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
6832 * and is generally somewhat broken with respect to 8 bpp / palette
6833 * handling. */
6834 if (SUCCEEDED(IDirectDrawSurface4_GetPalette(backbuffer, &tmp)))
6836 win_skip("Broken palette handling detected, skipping tests.\n");
6837 IDirectDrawPalette_Release(tmp);
6838 IDirectDrawPalette_Release(palette);
6839 /* The Windows 8 testbot keeps extra references to the primary and
6840 * backbuffer while in 8 bpp mode. */
6841 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
6842 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
6843 goto done;
6846 refcount = get_refcount((IUnknown *)palette);
6847 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6849 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6850 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6851 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
6852 "Got unexpected palette caps %#x.\n", palette_caps);
6854 hr = IDirectDrawSurface4_SetPalette(primary, NULL);
6855 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6856 refcount = get_refcount((IUnknown *)palette);
6857 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6859 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6860 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6861 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
6863 hr = IDirectDrawSurface4_SetPalette(primary, palette);
6864 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6865 refcount = get_refcount((IUnknown *)palette);
6866 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6868 hr = IDirectDrawSurface4_GetPalette(primary, &tmp);
6869 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
6870 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
6871 IDirectDrawPalette_Release(tmp);
6872 hr = IDirectDrawSurface4_GetPalette(backbuffer, &tmp);
6873 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6875 refcount = IDirectDrawPalette_Release(palette);
6876 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6877 refcount = IDirectDrawPalette_Release(palette);
6878 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6880 /* Note that this only seems to work when the palette is attached to the
6881 * primary surface. When attached to a regular surface, attempting to get
6882 * the palette here will cause an access violation. */
6883 hr = IDirectDrawSurface4_GetPalette(primary, &tmp);
6884 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6886 done:
6887 refcount = IDirectDrawSurface4_Release(backbuffer);
6888 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6889 refcount = IDirectDrawSurface4_Release(primary);
6890 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6891 refcount = IDirectDraw4_Release(ddraw);
6892 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6893 DestroyWindow(window);
6896 static HRESULT WINAPI surface_counter(IDirectDrawSurface4 *surface, DDSURFACEDESC2 *desc, void *context)
6898 UINT *surface_count = context;
6900 ++(*surface_count);
6901 IDirectDrawSurface_Release(surface);
6903 return DDENUMRET_OK;
6906 static void test_surface_attachment(void)
6908 IDirectDrawSurface4 *surface1, *surface2, *surface3, *surface4;
6909 IDirectDrawSurface *surface1v1, *surface2v1;
6910 DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, {0}};
6911 DDSURFACEDESC2 surface_desc;
6912 IDirectDraw4 *ddraw;
6913 UINT surface_count;
6914 ULONG refcount;
6915 HWND window;
6916 HRESULT hr;
6918 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6919 0, 0, 640, 480, 0, 0, 0, 0);
6920 ddraw = create_ddraw();
6921 ok(!!ddraw, "Failed to create a ddraw object.\n");
6922 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6923 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6925 memset(&surface_desc, 0, sizeof(surface_desc));
6926 surface_desc.dwSize = sizeof(surface_desc);
6927 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
6928 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
6929 U2(surface_desc).dwMipMapCount = 3;
6930 surface_desc.dwWidth = 128;
6931 surface_desc.dwHeight = 128;
6932 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6933 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6935 hr = IDirectDrawSurface4_GetAttachedSurface(surface1, &caps, &surface2);
6936 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
6937 hr = IDirectDrawSurface4_GetAttachedSurface(surface2, &caps, &surface3);
6938 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
6939 hr = IDirectDrawSurface4_GetAttachedSurface(surface3, &caps, &surface4);
6940 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
6942 surface_count = 0;
6943 IDirectDrawSurface4_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
6944 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
6945 surface_count = 0;
6946 IDirectDrawSurface4_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
6947 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
6948 surface_count = 0;
6949 IDirectDrawSurface4_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
6950 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
6952 memset(&surface_desc, 0, sizeof(surface_desc));
6953 surface_desc.dwSize = sizeof(surface_desc);
6954 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6955 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6956 surface_desc.dwWidth = 16;
6957 surface_desc.dwHeight = 16;
6958 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6959 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6961 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface4);
6962 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6963 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface1);
6964 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6965 hr = IDirectDrawSurface4_AddAttachedSurface(surface3, surface4);
6966 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6967 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface3);
6968 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6969 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface4);
6970 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6971 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface2);
6972 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6974 IDirectDrawSurface4_Release(surface4);
6976 memset(&surface_desc, 0, sizeof(surface_desc));
6977 surface_desc.dwSize = sizeof(surface_desc);
6978 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6979 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6980 surface_desc.dwWidth = 16;
6981 surface_desc.dwHeight = 16;
6982 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6983 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6985 if (SUCCEEDED(hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface4)))
6987 skip("Running on refrast, skipping some tests.\n");
6988 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface4);
6989 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6991 else
6993 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6994 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface1);
6995 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6996 hr = IDirectDrawSurface4_AddAttachedSurface(surface3, surface4);
6997 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6998 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface3);
6999 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7000 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface4);
7001 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7002 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface2);
7003 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7006 IDirectDrawSurface4_Release(surface4);
7007 IDirectDrawSurface4_Release(surface3);
7008 IDirectDrawSurface4_Release(surface2);
7009 IDirectDrawSurface4_Release(surface1);
7011 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7012 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7014 /* Try a single primary and two offscreen plain surfaces. */
7015 memset(&surface_desc, 0, sizeof(surface_desc));
7016 surface_desc.dwSize = sizeof(surface_desc);
7017 surface_desc.dwFlags = DDSD_CAPS;
7018 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7019 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7020 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7022 memset(&surface_desc, 0, sizeof(surface_desc));
7023 surface_desc.dwSize = sizeof(surface_desc);
7024 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7025 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7026 surface_desc.dwWidth = registry_mode.dmPelsWidth;
7027 surface_desc.dwHeight = registry_mode.dmPelsHeight;
7028 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7029 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7031 memset(&surface_desc, 0, sizeof(surface_desc));
7032 surface_desc.dwSize = sizeof(surface_desc);
7033 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7034 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7035 surface_desc.dwWidth = registry_mode.dmPelsWidth;
7036 surface_desc.dwHeight = registry_mode.dmPelsHeight;
7037 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7038 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7040 /* This one has a different size. */
7041 memset(&surface_desc, 0, sizeof(surface_desc));
7042 surface_desc.dwSize = sizeof(surface_desc);
7043 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7044 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7045 surface_desc.dwWidth = 128;
7046 surface_desc.dwHeight = 128;
7047 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7048 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7050 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface2);
7051 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7052 /* Try the reverse without detaching first. */
7053 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface1);
7054 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
7055 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
7056 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7058 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface1);
7059 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7060 /* Try to detach reversed. */
7061 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
7062 ok(hr == DDERR_CANNOTDETACHSURFACE, "Got unexpected hr %#x.\n", hr);
7063 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface2, 0, surface1);
7064 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7066 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface3);
7067 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7068 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface2, 0, surface3);
7069 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7071 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface4);
7072 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7073 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface1);
7074 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7076 IDirectDrawSurface4_Release(surface4);
7077 IDirectDrawSurface4_Release(surface3);
7078 IDirectDrawSurface4_Release(surface2);
7079 IDirectDrawSurface4_Release(surface1);
7081 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
7082 memset(&surface_desc, 0, sizeof(surface_desc));
7083 surface_desc.dwSize = sizeof(surface_desc);
7084 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7085 surface_desc.dwWidth = 64;
7086 surface_desc.dwHeight = 64;
7087 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
7088 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7089 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
7090 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
7091 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
7092 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
7093 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
7094 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7095 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7096 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7097 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7099 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
7100 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
7101 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
7102 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
7103 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7104 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7106 hr = IDirectDrawSurface4_QueryInterface(surface1, &IID_IDirectDrawSurface, (void **)&surface1v1);
7107 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
7108 hr = IDirectDrawSurface4_QueryInterface(surface2, &IID_IDirectDrawSurface, (void **)&surface2v1);
7109 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
7111 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface2);
7112 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7113 refcount = get_refcount((IUnknown *)surface2);
7114 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7115 refcount = get_refcount((IUnknown *)surface2v1);
7116 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7117 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface2);
7118 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
7119 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7120 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7121 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
7122 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
7124 /* Attaching while already attached to other surface. */
7125 hr = IDirectDrawSurface4_AddAttachedSurface(surface3, surface2);
7126 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7127 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface3, 0, surface2);
7128 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7129 IDirectDrawSurface4_Release(surface3);
7131 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
7132 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7133 refcount = get_refcount((IUnknown *)surface2);
7134 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7135 refcount = get_refcount((IUnknown *)surface2v1);
7136 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7138 /* DeleteAttachedSurface() when attaching via IDirectDrawSurface. */
7139 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7140 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7141 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
7142 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
7143 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
7144 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7145 refcount = IDirectDrawSurface4_Release(surface2);
7146 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7147 refcount = IDirectDrawSurface4_Release(surface1);
7148 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7150 /* Automatic detachment on release. */
7151 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7152 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7153 refcount = get_refcount((IUnknown *)surface2v1);
7154 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7155 refcount = IDirectDrawSurface_Release(surface1v1);
7156 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7157 refcount = IDirectDrawSurface_Release(surface2v1);
7158 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7159 refcount = IDirectDraw4_Release(ddraw);
7160 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7161 DestroyWindow(window);
7164 static void test_private_data(void)
7166 IDirectDraw4 *ddraw;
7167 IDirectDrawSurface4 *surface, *surface2;
7168 DDSURFACEDESC2 surface_desc;
7169 ULONG refcount, refcount2, refcount3;
7170 IUnknown *ptr;
7171 DWORD size = sizeof(ptr);
7172 HRESULT hr;
7173 HWND window;
7174 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7175 DWORD data[] = {1, 2, 3, 4};
7176 DDCAPS hal_caps;
7177 static const GUID ddraw_private_data_test_guid =
7179 0xfdb37466,
7180 0x428f,
7181 0x4edf,
7182 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
7184 static const GUID ddraw_private_data_test_guid2 =
7186 0x2e5afac2,
7187 0x87b5,
7188 0x4c10,
7189 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
7192 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7193 0, 0, 640, 480, 0, 0, 0, 0);
7194 ddraw = create_ddraw();
7195 ok(!!ddraw, "Failed to create a ddraw object.\n");
7196 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7197 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7199 reset_ddsd(&surface_desc);
7200 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
7201 surface_desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
7202 surface_desc.dwHeight = 4;
7203 surface_desc.dwWidth = 4;
7204 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7205 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7207 /* NULL pointers are not valid, but don't cause a crash. */
7208 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL,
7209 sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
7210 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7211 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 0, 0);
7212 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7213 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 1, 0);
7214 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7216 /* DDSPD_IUNKNOWNPOINTER needs sizeof(IUnknown *) bytes of data. */
7217 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7218 0, DDSPD_IUNKNOWNPOINTER);
7219 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7220 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7221 5, DDSPD_IUNKNOWNPOINTER);
7222 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7223 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7224 sizeof(ddraw) * 2, DDSPD_IUNKNOWNPOINTER);
7225 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7227 /* Note that with a size != 0 and size != sizeof(IUnknown *) and
7228 * DDSPD_IUNKNOWNPOINTER set SetPrivateData in ddraw4 and ddraw7
7229 * erases the old content and returns an error. This behavior has
7230 * been fixed in d3d8 and d3d9. Unless an application is found
7231 * that depends on this we don't care about this behavior. */
7232 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7233 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7234 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7235 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7236 0, DDSPD_IUNKNOWNPOINTER);
7237 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7238 size = sizeof(ptr);
7239 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7240 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7241 hr = IDirectDrawSurface4_FreePrivateData(surface, &ddraw_private_data_test_guid);
7242 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7244 refcount = get_refcount((IUnknown *)ddraw);
7245 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7246 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7247 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7248 refcount2 = get_refcount((IUnknown *)ddraw);
7249 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
7251 hr = IDirectDrawSurface4_FreePrivateData(surface, &ddraw_private_data_test_guid);
7252 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7253 refcount2 = get_refcount((IUnknown *)ddraw);
7254 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
7256 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7257 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7258 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7259 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, surface,
7260 sizeof(surface), DDSPD_IUNKNOWNPOINTER);
7261 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7262 refcount2 = get_refcount((IUnknown *)ddraw);
7263 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
7265 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7266 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7267 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7268 size = 2 * sizeof(ptr);
7269 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7270 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7271 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7272 refcount2 = get_refcount(ptr);
7273 /* Object is NOT addref'ed by the getter. */
7274 ok(ptr == (IUnknown *)ddraw, "Returned interface pointer is %p, expected %p.\n", ptr, ddraw);
7275 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
7277 ptr = (IUnknown *)0xdeadbeef;
7278 size = 1;
7279 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
7280 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7281 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7282 size = 2 * sizeof(ptr);
7283 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
7284 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7285 ok(size == 2 * sizeof(ptr), "Got unexpected size %u.\n", size);
7286 size = 1;
7287 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7288 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7289 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7290 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7291 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid2, NULL, NULL);
7292 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7293 size = 0xdeadbabe;
7294 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid2, &ptr, &size);
7295 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7296 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7297 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
7298 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, NULL);
7299 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7301 refcount3 = IDirectDrawSurface4_Release(surface);
7302 ok(!refcount3, "Got unexpected refcount %u.\n", refcount3);
7304 /* Destroying the surface frees the reference held on the private data. It also frees
7305 * the reference the surface is holding on its creating object. */
7306 refcount2 = get_refcount((IUnknown *)ddraw);
7307 ok(refcount2 == refcount - 1, "Got unexpected refcount %u.\n", refcount2);
7309 memset(&hal_caps, 0, sizeof(hal_caps));
7310 hal_caps.dwSize = sizeof(hal_caps);
7311 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
7312 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7313 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) == (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
7315 reset_ddsd(&surface_desc);
7316 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT;
7317 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7318 surface_desc.dwHeight = 4;
7319 surface_desc.dwWidth = 4;
7320 U2(surface_desc).dwMipMapCount = 2;
7321 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7322 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7323 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &surface2);
7324 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7326 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, data, sizeof(data), 0);
7327 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7328 hr = IDirectDrawSurface4_GetPrivateData(surface2, &ddraw_private_data_test_guid, NULL, NULL);
7329 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7331 IDirectDrawSurface4_Release(surface2);
7332 IDirectDrawSurface4_Release(surface);
7334 else
7335 skip("Mipmapped textures not supported, skipping mipmap private data test.\n");
7337 refcount = IDirectDraw4_Release(ddraw);
7338 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7339 DestroyWindow(window);
7342 static void test_pixel_format(void)
7344 HWND window, window2 = NULL;
7345 HDC hdc, hdc2 = NULL;
7346 HMODULE gl = NULL;
7347 int format, test_format;
7348 PIXELFORMATDESCRIPTOR pfd;
7349 IDirectDraw4 *ddraw = NULL;
7350 IDirectDrawClipper *clipper = NULL;
7351 DDSURFACEDESC2 ddsd;
7352 IDirectDrawSurface4 *primary = NULL;
7353 DDBLTFX fx;
7354 HRESULT hr;
7356 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7357 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7358 if (!window)
7360 skip("Failed to create window\n");
7361 return;
7364 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7365 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7367 hdc = GetDC(window);
7368 if (!hdc)
7370 skip("Failed to get DC\n");
7371 goto cleanup;
7374 if (window2)
7375 hdc2 = GetDC(window2);
7377 gl = LoadLibraryA("opengl32.dll");
7378 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
7380 format = GetPixelFormat(hdc);
7381 ok(format == 0, "new window has pixel format %d\n", format);
7383 ZeroMemory(&pfd, sizeof(pfd));
7384 pfd.nSize = sizeof(pfd);
7385 pfd.nVersion = 1;
7386 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
7387 pfd.iPixelType = PFD_TYPE_RGBA;
7388 pfd.iLayerType = PFD_MAIN_PLANE;
7389 format = ChoosePixelFormat(hdc, &pfd);
7390 if (format <= 0)
7392 skip("no pixel format available\n");
7393 goto cleanup;
7396 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
7398 skip("failed to set pixel format\n");
7399 goto cleanup;
7402 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
7404 skip("failed to set pixel format on second window\n");
7405 if (hdc2)
7407 ReleaseDC(window2, hdc2);
7408 hdc2 = NULL;
7412 ddraw = create_ddraw();
7413 ok(!!ddraw, "Failed to create a ddraw object.\n");
7415 test_format = GetPixelFormat(hdc);
7416 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7418 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7419 if (FAILED(hr))
7421 skip("Failed to set cooperative level, hr %#x.\n", hr);
7422 goto cleanup;
7425 test_format = GetPixelFormat(hdc);
7426 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7428 if (hdc2)
7430 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL);
7431 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
7432 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
7433 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
7435 test_format = GetPixelFormat(hdc);
7436 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7438 test_format = GetPixelFormat(hdc2);
7439 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7442 memset(&ddsd, 0, sizeof(ddsd));
7443 ddsd.dwSize = sizeof(ddsd);
7444 ddsd.dwFlags = DDSD_CAPS;
7445 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7447 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
7448 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
7450 test_format = GetPixelFormat(hdc);
7451 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7453 if (hdc2)
7455 test_format = GetPixelFormat(hdc2);
7456 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7459 if (clipper)
7461 hr = IDirectDrawSurface4_SetClipper(primary, clipper);
7462 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
7464 test_format = GetPixelFormat(hdc);
7465 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7467 test_format = GetPixelFormat(hdc2);
7468 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7471 memset(&fx, 0, sizeof(fx));
7472 fx.dwSize = sizeof(fx);
7473 hr = IDirectDrawSurface4_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7474 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
7476 test_format = GetPixelFormat(hdc);
7477 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7479 if (hdc2)
7481 test_format = GetPixelFormat(hdc2);
7482 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7485 cleanup:
7486 if (primary) IDirectDrawSurface4_Release(primary);
7487 if (clipper) IDirectDrawClipper_Release(clipper);
7488 if (ddraw) IDirectDraw4_Release(ddraw);
7489 if (gl) FreeLibrary(gl);
7490 if (hdc) ReleaseDC(window, hdc);
7491 if (hdc2) ReleaseDC(window2, hdc2);
7492 if (window) DestroyWindow(window);
7493 if (window2) DestroyWindow(window2);
7496 static void test_create_surface_pitch(void)
7498 IDirectDrawSurface4 *surface;
7499 DDSURFACEDESC2 surface_desc;
7500 IDirectDraw4 *ddraw;
7501 unsigned int i;
7502 ULONG refcount;
7503 HWND window;
7504 HRESULT hr;
7505 void *mem;
7507 static const struct
7509 DWORD caps;
7510 DWORD flags_in;
7511 DWORD pitch_in;
7512 HRESULT hr;
7513 DWORD flags_out;
7514 DWORD pitch_out32;
7515 DWORD pitch_out64;
7517 test_data[] =
7519 /* 0 */
7520 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7521 0, 0, DD_OK,
7522 DDSD_PITCH, 0x100, 0x100},
7523 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7524 DDSD_PITCH, 0x104, DD_OK,
7525 DDSD_PITCH, 0x100, 0x100},
7526 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7527 DDSD_PITCH, 0x0f8, DD_OK,
7528 DDSD_PITCH, 0x100, 0x100},
7529 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7530 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
7531 0, 0, 0 },
7532 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7533 0, 0, DD_OK,
7534 DDSD_PITCH, 0x100, 0x0fc},
7535 /* 5 */
7536 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7537 DDSD_PITCH, 0x104, DD_OK,
7538 DDSD_PITCH, 0x100, 0x0fc},
7539 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7540 DDSD_PITCH, 0x0f8, DD_OK,
7541 DDSD_PITCH, 0x100, 0x0fc},
7542 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7543 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
7544 DDSD_PITCH, 0x100, 0x0fc},
7545 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7546 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
7547 0, 0, 0 },
7548 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7549 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
7550 DDSD_PITCH, 0x100, 0x100},
7551 /* 10 */
7552 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7553 DDSD_LPSURFACE | DDSD_PITCH, 0x0fe, DDERR_INVALIDPARAMS,
7554 0, 0, 0 },
7555 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7556 DDSD_LPSURFACE | DDSD_PITCH, 0x0fc, DD_OK,
7557 DDSD_PITCH, 0x0fc, 0x0fc},
7558 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7559 DDSD_LPSURFACE | DDSD_PITCH, 0x0f8, DDERR_INVALIDPARAMS,
7560 0, 0, 0 },
7561 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7562 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x100, DDERR_INVALIDPARAMS,
7563 0, 0, 0 },
7564 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7565 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x3f00, DDERR_INVALIDPARAMS,
7566 0, 0, 0 },
7567 /* 15 */
7568 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7569 DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, 0x100, DD_OK,
7570 DDSD_PITCH, 0x100, 0x100},
7571 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
7572 0, 0, DDERR_INVALIDCAPS,
7573 0, 0, 0 },
7574 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7575 0, 0, DD_OK,
7576 DDSD_PITCH, 0x100, 0 },
7577 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7578 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
7579 0, 0, 0 },
7580 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
7581 0, 0, DDERR_INVALIDCAPS,
7582 0, 0, 0 },
7583 /* 20 */
7584 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7585 0, 0, DD_OK,
7586 DDSD_PITCH, 0x100, 0 },
7587 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7588 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
7589 DDSD_PITCH, 0x100, 0 },
7591 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
7593 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7594 0, 0, 640, 480, 0, 0, 0, 0);
7595 ddraw = create_ddraw();
7596 ok(!!ddraw, "Failed to create a ddraw object.\n");
7597 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7598 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7600 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
7602 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
7604 memset(&surface_desc, 0, sizeof(surface_desc));
7605 surface_desc.dwSize = sizeof(surface_desc);
7606 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
7607 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
7608 surface_desc.dwWidth = 63;
7609 surface_desc.dwHeight = 63;
7610 U1(surface_desc).lPitch = test_data[i].pitch_in;
7611 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7612 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
7613 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
7614 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7615 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7616 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7617 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7618 if (test_data[i].flags_in & DDSD_LPSURFACE)
7620 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
7621 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, expected_hr);
7622 surface_desc.lpSurface = mem;
7623 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7625 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
7626 continue;
7627 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
7628 if (FAILED(hr))
7629 continue;
7631 memset(&surface_desc, 0, sizeof(surface_desc));
7632 surface_desc.dwSize = sizeof(surface_desc);
7633 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
7634 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
7635 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
7636 "Test %u: Got unexpected flags %#x, expected %#x.\n",
7637 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
7638 /* The pitch for textures seems to be implementation specific. */
7639 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
7641 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
7642 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
7643 "Test %u: Got unexpected pitch %u, expected %u.\n",
7644 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
7645 else
7646 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
7647 "Test %u: Got unexpected pitch %u, expected %u.\n",
7648 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
7650 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
7652 IDirectDrawSurface4_Release(surface);
7655 HeapFree(GetProcessHeap(), 0, mem);
7656 refcount = IDirectDraw4_Release(ddraw);
7657 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7658 DestroyWindow(window);
7661 static void test_mipmap(void)
7663 IDirectDrawSurface4 *surface, *surface2;
7664 DDSURFACEDESC2 surface_desc;
7665 IDirectDraw4 *ddraw;
7666 unsigned int i;
7667 ULONG refcount;
7668 HWND window;
7669 HRESULT hr;
7670 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7671 DDCAPS hal_caps;
7673 static const struct
7675 DWORD flags;
7676 DWORD caps;
7677 DWORD width;
7678 DWORD height;
7679 DWORD mipmap_count_in;
7680 HRESULT hr;
7681 DWORD mipmap_count_out;
7683 tests[] =
7685 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
7686 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS, 0},
7687 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
7688 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS, 0},
7689 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 6},
7690 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 6},
7693 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7694 0, 0, 640, 480, 0, 0, 0, 0);
7695 ddraw = create_ddraw();
7696 ok(!!ddraw, "Failed to create a ddraw object.\n");
7697 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7698 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7700 memset(&hal_caps, 0, sizeof(hal_caps));
7701 hal_caps.dwSize = sizeof(hal_caps);
7702 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
7703 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7704 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
7706 skip("Mipmapped textures not supported, skipping tests.\n");
7707 IDirectDraw4_Release(ddraw);
7708 DestroyWindow(window);
7709 return;
7712 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
7714 memset(&surface_desc, 0, sizeof(surface_desc));
7715 surface_desc.dwSize = sizeof(surface_desc);
7716 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
7717 surface_desc.ddsCaps.dwCaps = tests[i].caps;
7718 surface_desc.dwWidth = tests[i].width;
7719 surface_desc.dwHeight = tests[i].height;
7720 if (tests[i].flags & DDSD_MIPMAPCOUNT)
7721 U2(surface_desc).dwMipMapCount = tests[i].mipmap_count_in;
7722 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7723 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
7724 if (FAILED(hr))
7725 continue;
7727 memset(&surface_desc, 0, sizeof(surface_desc));
7728 surface_desc.dwSize = sizeof(surface_desc);
7729 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
7730 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
7731 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
7732 "Test %u: Got unexpected flags %#x.\n", i, surface_desc.dwFlags);
7733 ok(U2(surface_desc).dwMipMapCount == tests[i].mipmap_count_out,
7734 "Test %u: Got unexpected mipmap count %u.\n", i, U2(surface_desc).dwMipMapCount);
7736 if (U2(surface_desc).dwMipMapCount > 1)
7738 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &surface2);
7739 ok(SUCCEEDED(hr), "Test %u: Failed to get attached surface, hr %#x.\n", i, hr);
7741 memset(&surface_desc, 0, sizeof(surface_desc));
7742 surface_desc.dwSize = sizeof(surface_desc);
7743 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, 0, NULL);
7744 ok(SUCCEEDED(hr), "Test %u: Failed to lock surface, hr %#x.\n", i, hr);
7745 memset(&surface_desc, 0, sizeof(surface_desc));
7746 surface_desc.dwSize = sizeof(surface_desc);
7747 hr = IDirectDrawSurface4_Lock(surface2, NULL, &surface_desc, 0, NULL);
7748 ok(SUCCEEDED(hr), "Test %u: Failed to lock surface, hr %#x.\n", i, hr);
7749 IDirectDrawSurface4_Unlock(surface2, NULL);
7750 IDirectDrawSurface4_Unlock(surface, NULL);
7752 IDirectDrawSurface4_Release(surface2);
7755 IDirectDrawSurface4_Release(surface);
7758 refcount = IDirectDraw4_Release(ddraw);
7759 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7760 DestroyWindow(window);
7763 static void test_palette_complex(void)
7765 IDirectDrawSurface4 *surface, *mipmap, *tmp;
7766 DDSURFACEDESC2 surface_desc;
7767 IDirectDraw4 *ddraw;
7768 IDirectDrawPalette *palette, *palette2, *palette_mipmap;
7769 ULONG refcount;
7770 HWND window;
7771 HRESULT hr;
7772 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7773 DDCAPS hal_caps;
7774 PALETTEENTRY palette_entries[256];
7775 unsigned int i;
7776 HDC dc;
7777 RGBQUAD rgbquad;
7778 UINT count;
7780 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7781 0, 0, 640, 480, 0, 0, 0, 0);
7782 ddraw = create_ddraw();
7783 ok(!!ddraw, "Failed to create a ddraw object.\n");
7784 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7785 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7787 memset(&hal_caps, 0, sizeof(hal_caps));
7788 hal_caps.dwSize = sizeof(hal_caps);
7789 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
7790 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7791 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
7793 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
7794 IDirectDraw4_Release(ddraw);
7795 DestroyWindow(window);
7796 return;
7799 memset(&surface_desc, 0, sizeof(surface_desc));
7800 surface_desc.dwSize = sizeof(surface_desc);
7801 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7802 surface_desc.dwWidth = 128;
7803 surface_desc.dwHeight = 128;
7804 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7805 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7806 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7807 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
7808 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7809 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7811 memset(palette_entries, 0, sizeof(palette_entries));
7812 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7813 palette_entries, &palette, NULL);
7814 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7816 memset(palette_entries, 0, sizeof(palette_entries));
7817 palette_entries[1].peRed = 0xff;
7818 palette_entries[1].peGreen = 0x80;
7819 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7820 palette_entries, &palette_mipmap, NULL);
7821 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7823 palette2 = (void *)0xdeadbeef;
7824 hr = IDirectDrawSurface4_GetPalette(surface, &palette2);
7825 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
7826 ok(!palette2, "Got unexpected palette %p.\n", palette2);
7827 hr = IDirectDrawSurface4_SetPalette(surface, palette);
7828 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7829 hr = IDirectDrawSurface4_GetPalette(surface, &palette2);
7830 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
7831 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
7832 IDirectDrawPalette_Release(palette2);
7834 mipmap = surface;
7835 IDirectDrawSurface4_AddRef(mipmap);
7836 for (i = 0; i < 7; ++i)
7838 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
7839 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
7840 palette2 = (void *)0xdeadbeef;
7841 hr = IDirectDrawSurface4_GetPalette(tmp, &palette2);
7842 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
7843 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
7845 hr = IDirectDrawSurface4_SetPalette(tmp, palette_mipmap);
7846 ok(SUCCEEDED(hr), "Failed to set palette, i %u, hr %#x.\n", i, hr);
7848 hr = IDirectDrawSurface4_GetPalette(tmp, &palette2);
7849 ok(SUCCEEDED(hr), "Failed to get palette, i %u, hr %#x.\n", i, hr);
7850 ok(palette_mipmap == palette2, "Got unexpected palette %p.\n", palette2);
7851 IDirectDrawPalette_Release(palette2);
7853 hr = IDirectDrawSurface4_GetDC(tmp, &dc);
7854 ok(SUCCEEDED(hr), "Failed to get DC, i %u, hr %#x.\n", i, hr);
7855 count = GetDIBColorTable(dc, 1, 1, &rgbquad);
7856 ok(count == 1, "Expected count 1, got %u.\n", count);
7857 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x.\n", rgbquad.rgbRed);
7858 ok(rgbquad.rgbGreen == 0x80, "Expected rgbGreen = 0x80, got %#x.\n", rgbquad.rgbGreen);
7859 ok(rgbquad.rgbBlue == 0x0, "Expected rgbBlue = 0x0, got %#x.\n", rgbquad.rgbBlue);
7860 hr = IDirectDrawSurface4_ReleaseDC(tmp, dc);
7861 ok(SUCCEEDED(hr), "Failed to release DC, i %u, hr %#x.\n", i, hr);
7863 IDirectDrawSurface4_Release(mipmap);
7864 mipmap = tmp;
7867 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
7868 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7869 IDirectDrawSurface4_Release(mipmap);
7870 refcount = IDirectDrawSurface4_Release(surface);
7871 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7872 refcount = IDirectDrawPalette_Release(palette_mipmap);
7873 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7874 refcount = IDirectDrawPalette_Release(palette);
7875 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7877 refcount = IDirectDraw4_Release(ddraw);
7878 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7879 DestroyWindow(window);
7882 static BOOL ddraw_is_warp(IDirectDraw4 *ddraw)
7884 DDDEVICEIDENTIFIER identifier;
7885 HRESULT hr;
7887 if (!strcmp(winetest_platform, "wine"))
7888 return FALSE;
7890 hr = IDirectDraw4_GetDeviceIdentifier(ddraw, &identifier, 0);
7891 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#x.\n", hr);
7892 return !!strstr(identifier.szDriver, "warp");
7895 static void test_p8_blit(void)
7897 IDirectDrawSurface4 *src, *dst, *dst_p8;
7898 DDSURFACEDESC2 surface_desc;
7899 IDirectDraw4 *ddraw;
7900 IDirectDrawPalette *palette, *palette2;
7901 ULONG refcount;
7902 HWND window;
7903 HRESULT hr;
7904 PALETTEENTRY palette_entries[256];
7905 unsigned int x;
7906 DDBLTFX fx;
7907 BOOL is_warp;
7908 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
7909 static const BYTE src_data2[] = {0x10, 0x5, 0x4, 0x3, 0x2, 0x1, 0xff, 0x80};
7910 static const BYTE expected_p8[] = {0x10, 0x1, 0x4, 0x3, 0x4, 0x5, 0xff, 0x80};
7911 static const D3DCOLOR expected[] =
7913 0x00101010, 0x00010101, 0x00020202, 0x00030303,
7914 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
7916 D3DCOLOR color;
7918 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7919 0, 0, 640, 480, 0, 0, 0, 0);
7920 ddraw = create_ddraw();
7921 ok(!!ddraw, "Failed to create a ddraw object.\n");
7922 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7923 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7924 is_warp = ddraw_is_warp(ddraw);
7926 memset(palette_entries, 0, sizeof(palette_entries));
7927 palette_entries[1].peGreen = 0xff;
7928 palette_entries[2].peBlue = 0xff;
7929 palette_entries[3].peFlags = 0xff;
7930 palette_entries[4].peRed = 0xff;
7931 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7932 palette_entries, &palette, NULL);
7933 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7934 palette_entries[1].peBlue = 0xff;
7935 palette_entries[2].peGreen = 0xff;
7936 palette_entries[3].peRed = 0xff;
7937 palette_entries[4].peFlags = 0x0;
7938 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7939 palette_entries, &palette2, NULL);
7940 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7942 memset(&surface_desc, 0, sizeof(surface_desc));
7943 surface_desc.dwSize = sizeof(surface_desc);
7944 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7945 surface_desc.dwWidth = 8;
7946 surface_desc.dwHeight = 1;
7947 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7948 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7949 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7950 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
7951 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL);
7952 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7953 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_p8, NULL);
7954 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7955 hr = IDirectDrawSurface4_SetPalette(dst_p8, palette2);
7956 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7958 memset(&surface_desc, 0, sizeof(surface_desc));
7959 surface_desc.dwSize = sizeof(surface_desc);
7960 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7961 surface_desc.dwWidth = 8;
7962 surface_desc.dwHeight = 1;
7963 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7964 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7965 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
7966 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
7967 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7968 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7969 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7970 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
7971 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL);
7972 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7974 memset(&surface_desc, 0, sizeof(surface_desc));
7975 surface_desc.dwSize = sizeof(surface_desc);
7976 hr = IDirectDrawSurface4_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
7977 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
7978 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
7979 hr = IDirectDrawSurface4_Unlock(src, NULL);
7980 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
7982 hr = IDirectDrawSurface4_Lock(dst_p8, NULL, &surface_desc, DDLOCK_WAIT, NULL);
7983 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
7984 memcpy(surface_desc.lpSurface, src_data2, sizeof(src_data2));
7985 hr = IDirectDrawSurface4_Unlock(dst_p8, NULL);
7986 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
7988 hr = IDirectDrawSurface4_SetPalette(src, palette);
7989 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7990 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
7991 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
7992 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
7993 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
7994 "Failed to blit, hr %#x.\n", hr);
7996 if (SUCCEEDED(hr))
7998 for (x = 0; x < sizeof(expected) / sizeof(*expected); x++)
8000 color = get_surface_color(dst, x, 0);
8001 todo_wine ok(compare_color(color, expected[x], 0),
8002 "Pixel %u: Got color %#x, expected %#x.\n",
8003 x, color, expected[x]);
8007 memset(&fx, 0, sizeof(fx));
8008 fx.dwSize = sizeof(fx);
8009 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x2;
8010 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x2;
8011 hr = IDirectDrawSurface4_Blt(dst_p8, NULL, src, NULL, DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &fx);
8012 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
8014 hr = IDirectDrawSurface4_Lock(dst_p8, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
8015 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
8016 /* A color keyed P8 blit doesn't do anything on WARP - it just leaves the data in the destination
8017 * surface untouched. P8 blits without color keys work. Error checking (DDBLT_KEYSRC without a key
8018 * for example) also works as expected.
8020 * Using DDBLT_KEYSRC instead of DDBLT_KEYSRCOVERRIDE doesn't change this. Doing this blit with
8021 * the display mode set to P8 doesn't help either. */
8022 ok(!memcmp(surface_desc.lpSurface, expected_p8, sizeof(expected_p8))
8023 || broken(is_warp && !memcmp(surface_desc.lpSurface, src_data2, sizeof(src_data2))),
8024 "Got unexpected P8 color key blit result.\n");
8025 hr = IDirectDrawSurface4_Unlock(dst_p8, NULL);
8026 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
8028 IDirectDrawSurface4_Release(src);
8029 IDirectDrawSurface4_Release(dst);
8030 IDirectDrawSurface4_Release(dst_p8);
8031 IDirectDrawPalette_Release(palette);
8032 IDirectDrawPalette_Release(palette2);
8034 refcount = IDirectDraw4_Release(ddraw);
8035 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8036 DestroyWindow(window);
8039 static void test_material(void)
8041 D3DMATERIALHANDLE mat_handle, tmp;
8042 IDirect3DMaterial3 *material;
8043 IDirect3DViewport3 *viewport;
8044 IDirect3DDevice3 *device;
8045 IDirectDrawSurface4 *rt;
8046 D3DCOLOR color;
8047 ULONG refcount;
8048 unsigned int i;
8049 HWND window;
8050 HRESULT hr;
8051 BOOL valid;
8053 static struct
8055 struct vec3 position;
8056 struct vec3 normal;
8057 D3DCOLOR diffuse;
8059 quad1[] =
8061 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
8062 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
8063 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
8064 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
8066 quad2[] =
8068 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
8069 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
8070 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
8071 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
8073 static const struct
8075 void *data;
8076 BOOL material;
8077 D3DCOLOR expected_color;
8079 test_data[] =
8081 {quad1, TRUE, 0x0000ff00},
8082 {quad2, TRUE, 0x0000ff00},
8083 {quad1, FALSE, 0x00ffffff},
8084 {quad2, FALSE, 0x00ff0000},
8086 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
8088 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8089 0, 0, 640, 480, 0, 0, 0, 0);
8090 if (!(device = create_device(window, DDSCL_NORMAL)))
8092 skip("Failed to create a 3D device, skipping test.\n");
8093 DestroyWindow(window);
8094 return;
8097 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
8098 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8100 viewport = create_viewport(device, 0, 0, 640, 480);
8101 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
8102 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
8104 material = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
8105 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
8106 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
8108 hr = IDirect3DDevice3_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
8109 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
8110 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
8111 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
8112 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
8113 hr = IDirect3DDevice3_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
8114 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
8115 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
8116 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, 0);
8117 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
8118 hr = IDirect3DDevice3_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
8119 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
8120 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
8122 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
8124 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect,
8125 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
8126 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8128 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, test_data[i].material ? mat_handle : 0);
8129 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
8131 hr = IDirect3DDevice3_BeginScene(device);
8132 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8133 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
8134 D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE, test_data[i].data, 4, 0);
8135 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8136 hr = IDirect3DDevice3_EndScene(device);
8137 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8138 color = get_surface_color(rt, 320, 240);
8139 ok(compare_color(color, test_data[i].expected_color, 1),
8140 "Got unexpected color 0x%08x, test %u.\n", color, i);
8143 destroy_material(material);
8144 material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
8145 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
8146 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
8148 hr = IDirect3DViewport3_SetBackground(viewport, mat_handle);
8149 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
8150 hr = IDirect3DViewport3_GetBackground(viewport, &tmp, &valid);
8151 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
8152 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
8153 ok(valid, "Got unexpected valid %#x.\n", valid);
8154 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8155 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8156 color = get_surface_color(rt, 320, 240);
8157 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
8159 hr = IDirect3DViewport3_SetBackground(viewport, 0);
8160 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8161 hr = IDirect3DViewport3_GetBackground(viewport, &tmp, &valid);
8162 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
8163 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
8164 ok(valid, "Got unexpected valid %#x.\n", valid);
8165 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8166 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8167 color = get_surface_color(rt, 320, 240);
8168 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
8170 destroy_viewport(device, viewport);
8171 viewport = create_viewport(device, 0, 0, 640, 480);
8173 hr = IDirect3DViewport3_GetBackground(viewport, &tmp, &valid);
8174 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
8175 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
8176 ok(!valid, "Got unexpected valid %#x.\n", valid);
8177 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8178 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8179 color = get_surface_color(rt, 320, 240);
8180 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x.\n", color);
8182 destroy_viewport(device, viewport);
8183 destroy_material(material);
8184 IDirectDrawSurface4_Release(rt);
8185 refcount = IDirect3DDevice3_Release(device);
8186 ok(!refcount, "Device has %u references left.\n", refcount);
8187 DestroyWindow(window);
8190 static void test_palette_gdi(void)
8192 IDirectDrawSurface4 *surface, *primary;
8193 DDSURFACEDESC2 surface_desc;
8194 IDirectDraw4 *ddraw;
8195 IDirectDrawPalette *palette, *palette2;
8196 ULONG refcount;
8197 HWND window;
8198 HRESULT hr;
8199 PALETTEENTRY palette_entries[256];
8200 UINT i;
8201 HDC dc;
8202 DDBLTFX fx;
8203 RECT r;
8204 COLORREF color;
8205 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
8206 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
8207 * not the point of this test. */
8208 static const RGBQUAD expected1[] =
8210 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8211 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
8213 static const RGBQUAD expected2[] =
8215 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8216 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
8218 static const RGBQUAD expected3[] =
8220 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
8221 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
8223 HPALETTE ddraw_palette_handle;
8224 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
8225 RGBQUAD rgbquad[255];
8226 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
8228 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8229 0, 0, 640, 480, 0, 0, 0, 0);
8230 ddraw = create_ddraw();
8231 ok(!!ddraw, "Failed to create a ddraw object.\n");
8232 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8233 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8235 memset(&surface_desc, 0, sizeof(surface_desc));
8236 surface_desc.dwSize = sizeof(surface_desc);
8237 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8238 surface_desc.dwWidth = 16;
8239 surface_desc.dwHeight = 16;
8240 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8241 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8242 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8243 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
8244 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8245 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8247 /* Avoid colors from the Windows default palette. */
8248 memset(palette_entries, 0, sizeof(palette_entries));
8249 palette_entries[1].peRed = 0x01;
8250 palette_entries[2].peGreen = 0x02;
8251 palette_entries[3].peBlue = 0x03;
8252 palette_entries[4].peRed = 0x13;
8253 palette_entries[4].peGreen = 0x14;
8254 palette_entries[4].peBlue = 0x15;
8255 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8256 palette_entries, &palette, NULL);
8257 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8259 /* If there is no palette assigned and the display mode is not 8 bpp, some
8260 * drivers refuse to create a DC while others allow it. If a DC is created,
8261 * the DIB color table is uninitialized and contains random colors. No error
8262 * is generated when trying to read pixels and random garbage is returned.
8264 * The most likely explanation is that if the driver creates a DC, it (or
8265 * the higher-level runtime) uses GetSystemPaletteEntries to find the
8266 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
8267 * contains uninitialized garbage. See comments below for the P8 case. */
8269 hr = IDirectDrawSurface4_SetPalette(surface, palette);
8270 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8271 hr = IDirectDrawSurface4_GetDC(surface, &dc);
8272 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8273 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8274 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8275 "Got unexpected palette %p, expected %p.\n",
8276 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8278 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
8279 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
8280 for (i = 0; i < sizeof(expected1) / sizeof(*expected1); i++)
8282 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
8283 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8284 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8285 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
8287 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
8289 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8290 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8291 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8294 /* Update the palette while the DC is in use. This does not modify the DC. */
8295 palette_entries[4].peRed = 0x23;
8296 palette_entries[4].peGreen = 0x24;
8297 palette_entries[4].peBlue = 0x25;
8298 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
8299 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8301 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8302 ok(i == 1, "Expected count 1, got %u.\n", i);
8303 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8304 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8305 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8306 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8308 /* Neither does re-setting the palette. */
8309 hr = IDirectDrawSurface4_SetPalette(surface, NULL);
8310 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8311 hr = IDirectDrawSurface4_SetPalette(surface, palette);
8312 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8314 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8315 ok(i == 1, "Expected count 1, got %u.\n", i);
8316 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8317 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8318 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8319 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8321 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
8322 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8324 /* Refresh the DC. This updates the palette. */
8325 hr = IDirectDrawSurface4_GetDC(surface, &dc);
8326 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8327 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
8328 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
8329 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
8331 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8332 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8333 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8334 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8336 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
8338 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8339 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8340 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8342 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
8343 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8345 refcount = IDirectDrawSurface4_Release(surface);
8346 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8348 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
8349 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8350 if (FAILED(IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8352 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8353 IDirectDrawPalette_Release(palette);
8354 IDirectDraw4_Release(ddraw);
8355 DestroyWindow(window);
8356 return;
8358 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
8360 memset(&surface_desc, 0, sizeof(surface_desc));
8361 surface_desc.dwSize = sizeof(surface_desc);
8362 surface_desc.dwFlags = DDSD_CAPS;
8363 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8364 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
8365 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8367 memset(&fx, 0, sizeof(fx));
8368 fx.dwSize = sizeof(fx);
8369 fx.dwFillColor = 3;
8370 SetRect(&r, 0, 0, 319, 479);
8371 hr = IDirectDrawSurface4_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8372 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
8373 SetRect(&r, 320, 0, 639, 479);
8374 fx.dwFillColor = 4;
8375 hr = IDirectDrawSurface4_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8376 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
8378 hr = IDirectDrawSurface4_SetPalette(primary, palette);
8379 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8380 hr = IDirectDrawSurface4_GetDC(primary, &dc);
8381 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8383 color = GetPixel(dc, 160, 240);
8384 ok(color == 0x00030000, "Clear index 3: Got unexpected color 0x%08x.\n", color);
8385 color = GetPixel(dc, 480, 240);
8386 ok(color == 0x00252423, "Clear index 4: Got unexpected color 0x%08x.\n", color);
8388 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8389 /* Windows 2000 on the testbot assigns a different palette to the primary. Refrast? */
8390 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE) || broken(TRUE),
8391 "Got unexpected palette %p, expected %p.\n",
8392 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8393 SelectPalette(dc, ddraw_palette_handle, FALSE);
8395 /* The primary uses the system palette. In exclusive mode, the system palette matches
8396 * the ddraw palette attached to the primary, so the result is what you would expect
8397 * from a regular surface. Tests for the interaction between the ddraw palette and
8398 * the system palette are not included pending an application that depends on this.
8399 * The relation between those causes problems on Windows Vista and newer for games
8400 * like Age of Empires or StarCraft. Don't emulate it without a real need. */
8401 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
8402 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
8403 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
8405 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8406 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8407 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8408 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8410 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
8412 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8413 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8414 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8416 hr = IDirectDrawSurface4_ReleaseDC(primary, dc);
8417 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8419 memset(&surface_desc, 0, sizeof(surface_desc));
8420 surface_desc.dwSize = sizeof(surface_desc);
8421 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8422 surface_desc.dwWidth = 16;
8423 surface_desc.dwHeight = 16;
8424 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8425 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8426 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8428 /* Here the offscreen surface appears to use the primary's palette,
8429 * but in all likelihood it is actually the system palette. */
8430 hr = IDirectDrawSurface4_GetDC(surface, &dc);
8431 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8432 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
8433 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
8434 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
8436 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8437 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8438 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8439 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8441 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
8443 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8444 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8445 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8447 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
8448 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8450 /* On real hardware a change to the primary surface's palette applies immediately,
8451 * even on device contexts from offscreen surfaces that do not have their own
8452 * palette. On the testbot VMs this is not the case. Don't test this until we
8453 * know of an application that depends on this. */
8455 memset(palette_entries, 0, sizeof(palette_entries));
8456 palette_entries[1].peBlue = 0x40;
8457 palette_entries[2].peRed = 0x40;
8458 palette_entries[3].peGreen = 0x40;
8459 palette_entries[4].peRed = 0x12;
8460 palette_entries[4].peGreen = 0x34;
8461 palette_entries[4].peBlue = 0x56;
8462 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8463 palette_entries, &palette2, NULL);
8464 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8465 hr = IDirectDrawSurface4_SetPalette(surface, palette2);
8466 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8468 /* A palette assigned to the offscreen surface overrides the primary / system
8469 * palette. */
8470 hr = IDirectDrawSurface4_GetDC(surface, &dc);
8471 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8472 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
8473 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
8474 for (i = 0; i < sizeof(expected3) / sizeof(*expected3); i++)
8476 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
8477 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8478 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8479 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
8481 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
8483 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8484 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8485 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8487 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
8488 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8490 refcount = IDirectDrawSurface4_Release(surface);
8491 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8493 /* The Windows 8 testbot keeps extra references to the primary and
8494 * backbuffer while in 8 bpp mode. */
8495 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
8496 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
8498 refcount = IDirectDrawSurface4_Release(primary);
8499 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8500 refcount = IDirectDrawPalette_Release(palette2);
8501 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8502 refcount = IDirectDrawPalette_Release(palette);
8503 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8504 refcount = IDirectDraw4_Release(ddraw);
8505 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8506 DestroyWindow(window);
8509 static void test_palette_alpha(void)
8511 IDirectDrawSurface4 *surface;
8512 DDSURFACEDESC2 surface_desc;
8513 IDirectDraw4 *ddraw;
8514 IDirectDrawPalette *palette;
8515 ULONG refcount;
8516 HWND window;
8517 HRESULT hr;
8518 PALETTEENTRY palette_entries[256];
8519 unsigned int i;
8520 static const struct
8522 DWORD caps, flags;
8523 BOOL attach_allowed;
8524 const char *name;
8526 test_data[] =
8528 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
8529 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
8530 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
8533 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8534 0, 0, 640, 480, 0, 0, 0, 0);
8535 ddraw = create_ddraw();
8536 ok(!!ddraw, "Failed to create a ddraw object.\n");
8537 if (FAILED(IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8539 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8540 IDirectDraw4_Release(ddraw);
8541 DestroyWindow(window);
8542 return;
8544 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8545 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8547 memset(palette_entries, 0, sizeof(palette_entries));
8548 palette_entries[1].peFlags = 0x42;
8549 palette_entries[2].peFlags = 0xff;
8550 palette_entries[3].peFlags = 0x80;
8551 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
8552 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8554 memset(palette_entries, 0x66, sizeof(palette_entries));
8555 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
8556 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
8557 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8558 palette_entries[0].peFlags);
8559 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8560 palette_entries[1].peFlags);
8561 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
8562 palette_entries[2].peFlags);
8563 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
8564 palette_entries[3].peFlags);
8566 IDirectDrawPalette_Release(palette);
8568 memset(palette_entries, 0, sizeof(palette_entries));
8569 palette_entries[1].peFlags = 0x42;
8570 palette_entries[1].peRed = 0xff;
8571 palette_entries[2].peFlags = 0xff;
8572 palette_entries[3].peFlags = 0x80;
8573 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
8574 palette_entries, &palette, NULL);
8575 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8577 memset(palette_entries, 0x66, sizeof(palette_entries));
8578 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
8579 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
8580 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8581 palette_entries[0].peFlags);
8582 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8583 palette_entries[1].peFlags);
8584 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
8585 palette_entries[2].peFlags);
8586 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
8587 palette_entries[3].peFlags);
8589 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); i++)
8591 memset(&surface_desc, 0, sizeof(surface_desc));
8592 surface_desc.dwSize = sizeof(surface_desc);
8593 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
8594 surface_desc.dwWidth = 128;
8595 surface_desc.dwHeight = 128;
8596 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
8597 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8598 ok(SUCCEEDED(hr), "Failed to create %s surface, hr %#x.\n", test_data[i].name, hr);
8600 hr = IDirectDrawSurface4_SetPalette(surface, palette);
8601 if (test_data[i].attach_allowed)
8602 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#x.\n", test_data[i].name, hr);
8603 else
8604 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x, %s surface.\n", hr, test_data[i].name);
8606 if (SUCCEEDED(hr))
8608 HDC dc;
8609 RGBQUAD rgbquad;
8610 UINT retval;
8612 hr = IDirectDrawSurface4_GetDC(surface, &dc);
8613 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
8614 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
8615 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
8616 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
8617 rgbquad.rgbRed, test_data[i].name);
8618 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
8619 rgbquad.rgbGreen, test_data[i].name);
8620 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
8621 rgbquad.rgbBlue, test_data[i].name);
8622 todo_wine ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
8623 rgbquad.rgbReserved, test_data[i].name);
8624 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
8625 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8627 IDirectDrawSurface4_Release(surface);
8630 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
8631 memset(&surface_desc, 0, sizeof(surface_desc));
8632 surface_desc.dwSize = sizeof(surface_desc);
8633 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8634 surface_desc.dwWidth = 128;
8635 surface_desc.dwHeight = 128;
8636 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8637 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8638 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
8639 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8640 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8641 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8642 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8643 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8644 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8645 hr = IDirectDrawSurface4_SetPalette(surface, palette);
8646 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
8647 IDirectDrawSurface4_Release(surface);
8649 /* The Windows 8 testbot keeps extra references to the primary
8650 * while in 8 bpp mode. */
8651 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
8652 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
8654 refcount = IDirectDrawPalette_Release(palette);
8655 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8656 refcount = IDirectDraw4_Release(ddraw);
8657 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8658 DestroyWindow(window);
8661 static void test_vb_writeonly(void)
8663 IDirect3DDevice3 *device;
8664 IDirect3D3 *d3d;
8665 IDirect3DVertexBuffer *buffer;
8666 HWND window;
8667 HRESULT hr;
8668 D3DVERTEXBUFFERDESC desc;
8669 void *ptr;
8670 static const struct vec4 quad[] =
8672 { 0.0f, 480.0f, 0.0f, 1.0f},
8673 { 0.0f, 0.0f, 0.0f, 1.0f},
8674 {640.0f, 480.0f, 0.0f, 1.0f},
8675 {640.0f, 0.0f, 0.0f, 1.0f},
8678 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8679 0, 0, 640, 480, 0, 0, 0, 0);
8681 if (!(device = create_device(window, DDSCL_NORMAL)))
8683 skip("Failed to create a 3D device, skipping test.\n");
8684 DestroyWindow(window);
8685 return;
8688 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
8689 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
8691 memset(&desc, 0, sizeof(desc));
8692 desc.dwSize = sizeof(desc);
8693 desc.dwCaps = D3DVBCAPS_WRITEONLY;
8694 desc.dwFVF = D3DFVF_XYZRHW;
8695 desc.dwNumVertices = sizeof(quad) / sizeof(*quad);
8696 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &buffer, 0, NULL);
8697 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
8699 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, &ptr, NULL);
8700 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8701 memcpy(ptr, quad, sizeof(quad));
8702 hr = IDirect3DVertexBuffer_Unlock(buffer);
8703 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8705 hr = IDirect3DDevice3_BeginScene(device);
8706 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8707 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
8708 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8709 hr = IDirect3DDevice3_EndScene(device);
8710 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8712 hr = IDirect3DVertexBuffer_Lock(buffer, 0, &ptr, NULL);
8713 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8714 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
8715 hr = IDirect3DVertexBuffer_Unlock(buffer);
8716 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8718 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_READONLY, &ptr, NULL);
8719 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8720 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
8721 hr = IDirect3DVertexBuffer_Unlock(buffer);
8722 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8724 IDirect3DVertexBuffer_Release(buffer);
8725 IDirect3D3_Release(d3d);
8726 IDirect3DDevice3_Release(device);
8727 DestroyWindow(window);
8730 static void test_lost_device(void)
8732 IDirectDrawSurface4 *surface;
8733 DDSURFACEDESC2 surface_desc;
8734 HWND window1, window2;
8735 IDirectDraw4 *ddraw;
8736 ULONG refcount;
8737 HRESULT hr;
8738 BOOL ret;
8740 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8741 0, 0, 640, 480, 0, 0, 0, 0);
8742 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8743 0, 0, 640, 480, 0, 0, 0, 0);
8744 ddraw = create_ddraw();
8745 ok(!!ddraw, "Failed to create a ddraw object.\n");
8746 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8747 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8749 memset(&surface_desc, 0, sizeof(surface_desc));
8750 surface_desc.dwSize = sizeof(surface_desc);
8751 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8752 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8753 U5(surface_desc).dwBackBufferCount = 1;
8754 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8755 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8757 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8758 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8759 hr = IDirectDrawSurface4_IsLost(surface);
8760 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8761 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8762 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8764 ret = SetForegroundWindow(GetDesktopWindow());
8765 ok(ret, "Failed to set foreground window.\n");
8766 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8767 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8768 hr = IDirectDrawSurface4_IsLost(surface);
8769 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8770 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8771 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8773 ret = SetForegroundWindow(window1);
8774 ok(ret, "Failed to set foreground window.\n");
8775 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8776 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8777 hr = IDirectDrawSurface4_IsLost(surface);
8778 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8779 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8780 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8782 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
8783 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8784 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8785 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8786 hr = IDirectDrawSurface4_IsLost(surface);
8787 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8788 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8789 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8791 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
8792 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8793 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8794 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8795 hr = IDirectDrawSurface4_IsLost(surface);
8796 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8797 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8798 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8800 /* Trying to restore the primary will crash, probably because flippable
8801 * surfaces can't exist in DDSCL_NORMAL. */
8802 IDirectDrawSurface4_Release(surface);
8803 memset(&surface_desc, 0, sizeof(surface_desc));
8804 surface_desc.dwSize = sizeof(surface_desc);
8805 surface_desc.dwFlags = DDSD_CAPS;
8806 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8807 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8808 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8810 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8811 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8812 hr = IDirectDrawSurface4_IsLost(surface);
8813 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8815 ret = SetForegroundWindow(GetDesktopWindow());
8816 ok(ret, "Failed to set foreground window.\n");
8817 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8818 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8819 hr = IDirectDrawSurface4_IsLost(surface);
8820 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8822 ret = SetForegroundWindow(window1);
8823 ok(ret, "Failed to set foreground window.\n");
8824 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8825 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8826 hr = IDirectDrawSurface4_IsLost(surface);
8827 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8829 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8830 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8831 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8832 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8833 hr = IDirectDrawSurface4_IsLost(surface);
8834 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8836 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
8837 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8838 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8839 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8840 hr = IDirectDrawSurface4_IsLost(surface);
8841 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8843 IDirectDrawSurface4_Release(surface);
8844 memset(&surface_desc, 0, sizeof(surface_desc));
8845 surface_desc.dwSize = sizeof(surface_desc);
8846 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8847 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8848 U5(surface_desc).dwBackBufferCount = 1;
8849 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8850 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8852 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8853 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8854 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8855 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8856 hr = IDirectDrawSurface4_IsLost(surface);
8857 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8858 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8859 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8861 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
8862 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8863 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8864 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8865 hr = IDirectDrawSurface4_IsLost(surface);
8866 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8867 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8868 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8870 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
8871 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8872 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8873 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8874 hr = IDirectDrawSurface4_IsLost(surface);
8875 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8876 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8877 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8879 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
8880 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8881 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8882 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8883 hr = IDirectDrawSurface4_IsLost(surface);
8884 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8885 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8886 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8888 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
8889 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8890 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8891 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8892 hr = IDirectDrawSurface4_IsLost(surface);
8893 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8894 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8895 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8897 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8898 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8899 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8900 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8901 hr = IDirectDrawSurface4_IsLost(surface);
8902 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8903 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8904 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8906 IDirectDrawSurface4_Release(surface);
8907 refcount = IDirectDraw4_Release(ddraw);
8908 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8909 DestroyWindow(window2);
8910 DestroyWindow(window1);
8913 static void test_surface_desc_lock(void)
8915 IDirectDrawSurface4 *surface;
8916 DDSURFACEDESC2 surface_desc;
8917 IDirectDraw4 *ddraw;
8918 ULONG refcount;
8919 HWND window;
8920 HRESULT hr;
8922 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8923 0, 0, 640, 480, 0, 0, 0, 0);
8924 ddraw = create_ddraw();
8925 ok(!!ddraw, "Failed to create a ddraw object.\n");
8926 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8927 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8929 memset(&surface_desc, 0, sizeof(surface_desc));
8930 surface_desc.dwSize = sizeof(surface_desc);
8931 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8932 surface_desc.dwWidth = 16;
8933 surface_desc.dwHeight = 16;
8934 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8935 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8936 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8938 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8939 surface_desc.dwSize = sizeof(surface_desc);
8940 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
8941 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8942 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8944 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8945 surface_desc.dwSize = sizeof(surface_desc);
8946 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, 0, NULL);
8947 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8948 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8949 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8950 surface_desc.dwSize = sizeof(surface_desc);
8951 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
8952 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8953 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8954 hr = IDirectDrawSurface4_Unlock(surface, NULL);
8955 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8957 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8958 surface_desc.dwSize = sizeof(surface_desc);
8959 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
8960 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8961 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8963 IDirectDrawSurface4_Release(surface);
8964 refcount = IDirectDraw4_Release(ddraw);
8965 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8966 DestroyWindow(window);
8969 static void test_signed_formats(void)
8971 HRESULT hr;
8972 IDirect3DDevice3 *device;
8973 IDirect3D3 *d3d;
8974 IDirectDraw4 *ddraw;
8975 IDirectDrawSurface4 *surface, *rt;
8976 IDirect3DTexture2 *texture;
8977 IDirect3DViewport3 *viewport;
8978 DDSURFACEDESC2 surface_desc;
8979 ULONG refcount;
8980 HWND window;
8981 D3DCOLOR color, expected_color;
8982 D3DRECT clear_rect;
8983 static struct
8985 struct vec3 position;
8986 struct vec2 texcoord;
8988 quad[] =
8990 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
8991 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
8992 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
8993 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
8995 /* See test_signed_formats() in dlls/d3d9/tests/visual.c for an explanation
8996 * of these values. */
8997 static const USHORT content_v8u8[4][4] =
8999 {0x0000, 0x7f7f, 0x8880, 0x0000},
9000 {0x0080, 0x8000, 0x7f00, 0x007f},
9001 {0x193b, 0xe8c8, 0x0808, 0xf8f8},
9002 {0x4444, 0xc0c0, 0xa066, 0x22e0},
9004 static const DWORD content_x8l8v8u8[4][4] =
9006 {0x00000000, 0x00ff7f7f, 0x00008880, 0x00ff0000},
9007 {0x00000080, 0x00008000, 0x00007f00, 0x0000007f},
9008 {0x0041193b, 0x0051e8c8, 0x00040808, 0x00fff8f8},
9009 {0x00824444, 0x0000c0c0, 0x00c2a066, 0x009222e0},
9011 static const USHORT content_l6v5u5[4][4] =
9013 {0x0000, 0xfdef, 0x0230, 0xfc00},
9014 {0x0010, 0x0200, 0x01e0, 0x000f},
9015 {0x4067, 0x53b9, 0x0421, 0xffff},
9016 {0x8108, 0x0318, 0xc28c, 0x909c},
9018 static const struct
9020 const char *name;
9021 const void *content;
9022 SIZE_T pixel_size;
9023 BOOL blue;
9024 unsigned int slop, slop_broken;
9025 DDPIXELFORMAT format;
9027 formats[] =
9030 "D3DFMT_V8U8", content_v8u8, sizeof(WORD), FALSE, 1, 0,
9032 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV, 0,
9033 {16}, {0x000000ff}, {0x0000ff00}, {0x00000000}, {0x00000000}
9037 "D3DFMT_X8L8V8U8", content_x8l8v8u8, sizeof(DWORD), TRUE, 1, 0,
9039 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
9040 {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}
9044 "D3DFMT_L6V5U5", content_l6v5u5, sizeof(WORD), TRUE, 4, 7,
9046 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
9047 {16}, {0x0000001f}, {0x000003e0}, {0x0000fc00}, {0x00000000}
9051 /* No V16U16 or Q8W8V8U8 support in ddraw. */
9053 static const D3DCOLOR expected_colors[4][4] =
9055 {0x00808080, 0x00fefeff, 0x00010780, 0x008080ff},
9056 {0x00018080, 0x00800180, 0x0080fe80, 0x00fe8080},
9057 {0x00ba98a0, 0x004767a8, 0x00888881, 0x007878ff},
9058 {0x00c3c3c0, 0x003f3f80, 0x00e51fe1, 0x005fa2c8},
9060 unsigned int i, width, x, y;
9061 D3DDEVICEDESC device_desc, hel_desc;
9063 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9064 0, 0, 640, 480, 0, 0, 0, 0);
9066 if (!(device = create_device(window, DDSCL_NORMAL)))
9068 skip("Failed to create a 3D device, skipping test.\n");
9069 DestroyWindow(window);
9070 return;
9073 memset(&device_desc, 0, sizeof(device_desc));
9074 device_desc.dwSize = sizeof(device_desc);
9075 memset(&hel_desc, 0, sizeof(hel_desc));
9076 hel_desc.dwSize = sizeof(hel_desc);
9077 hr = IDirect3DDevice3_GetCaps(device, &device_desc, &hel_desc);
9078 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9079 if (!(device_desc.dwTextureOpCaps & D3DTEXOPCAPS_BLENDFACTORALPHA))
9081 skip("D3DTOP_BLENDFACTORALPHA not supported, skipping bumpmap format tests.\n");
9082 goto done;
9085 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
9086 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9087 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
9088 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
9089 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
9090 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9092 memset(&surface_desc, 0, sizeof(surface_desc));
9093 surface_desc.dwSize = sizeof(surface_desc);
9094 hr = IDirectDrawSurface4_GetSurfaceDesc(rt, &surface_desc);
9095 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9096 viewport = create_viewport(device, 0, 0, surface_desc.dwWidth, surface_desc.dwHeight);
9097 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
9098 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
9099 U1(clear_rect).x1 = 0;
9100 U2(clear_rect).y1 = 0;
9101 U3(clear_rect).x2 = surface_desc.dwWidth;
9102 U4(clear_rect).y2 = surface_desc.dwHeight;
9104 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
9105 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9107 /* dst = tex * 0.5 + 1.0 * (1.0 - 0.5) = tex * 0.5 + 0.5 */
9108 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x80ffffff);
9109 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9110 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BLENDFACTORALPHA);
9111 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9112 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9113 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9114 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
9115 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9117 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
9119 for (width = 1; width < 5; width += 3)
9121 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
9122 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
9124 memset(&surface_desc, 0, sizeof(surface_desc));
9125 surface_desc.dwSize = sizeof(surface_desc);
9126 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
9127 surface_desc.dwWidth = width;
9128 surface_desc.dwHeight = 4;
9129 U4(surface_desc).ddpfPixelFormat = formats[i].format;
9130 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
9131 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9132 if (FAILED(hr))
9134 skip("%s textures not supported, skipping.\n", formats[i].name);
9135 continue;
9137 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, format %s.\n", hr, formats[i].name);
9139 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9140 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture2 interface, hr %#x, format %s.\n",
9141 hr, formats[i].name);
9142 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
9143 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x, format %s.\n", hr, formats[i].name);
9144 IDirect3DTexture2_Release(texture);
9146 memset(&surface_desc, 0, sizeof(surface_desc));
9147 surface_desc.dwSize = sizeof(surface_desc);
9148 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, 0, NULL);
9149 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, format %s.\n", hr, formats[i].name);
9150 for (y = 0; y < 4; y++)
9152 memcpy((char *)surface_desc.lpSurface + y * U1(surface_desc).lPitch,
9153 (char *)formats[i].content + y * 4 * formats[i].pixel_size,
9154 width * formats[i].pixel_size);
9156 hr = IDirectDrawSurface4_Unlock(surface, NULL);
9157 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, format %s.\n", hr, formats[i].name);
9159 hr = IDirect3DDevice3_BeginScene(device);
9160 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9161 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9162 D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
9163 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9164 hr = IDirect3DDevice3_EndScene(device);
9165 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9167 for (y = 0; y < 4; y++)
9169 for (x = 0; x < width; x++)
9171 expected_color = expected_colors[y][x];
9172 if (!formats[i].blue)
9173 expected_color |= 0x000000ff;
9175 color = get_surface_color(rt, 80 + 160 * x, 60 + 120 * y);
9176 ok(compare_color(color, expected_color, formats[i].slop)
9177 || broken(compare_color(color, expected_color, formats[i].slop_broken)),
9178 "Expected color 0x%08x, got 0x%08x, format %s, location %ux%u.\n",
9179 expected_color, color, formats[i].name, x, y);
9183 IDirectDrawSurface4_Release(surface);
9187 destroy_viewport(device, viewport);
9188 IDirectDrawSurface4_Release(rt);
9189 IDirectDraw4_Release(ddraw);
9190 IDirect3D3_Release(d3d);
9192 done:
9193 refcount = IDirect3DDevice3_Release(device);
9194 ok(!refcount, "Device has %u references left.\n", refcount);
9195 DestroyWindow(window);
9198 static void test_color_fill(void)
9200 HRESULT hr;
9201 IDirect3DDevice3 *device;
9202 IDirect3D3 *d3d;
9203 IDirectDraw4 *ddraw;
9204 IDirectDrawSurface4 *surface, *surface2;
9205 DDSURFACEDESC2 surface_desc;
9206 DDPIXELFORMAT z_fmt;
9207 ULONG refcount;
9208 HWND window;
9209 unsigned int i;
9210 DDBLTFX fx;
9211 RECT rect = {5, 5, 7, 7};
9212 DWORD *color;
9213 DWORD supported_fmts = 0, num_fourcc_codes, *fourcc_codes;
9214 DDCAPS hal_caps;
9215 static const struct
9217 DWORD caps, caps2;
9218 HRESULT colorfill_hr, depthfill_hr;
9219 BOOL rop_success;
9220 const char *name;
9221 DWORD result;
9222 BOOL check_result;
9223 DDPIXELFORMAT format;
9225 tests[] =
9228 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9229 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
9231 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9232 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9236 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
9237 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
9239 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9240 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9244 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
9245 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
9247 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9248 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9252 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
9253 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
9255 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9256 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9260 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
9261 DD_OK, DDERR_INVALIDPARAMS, TRUE, "managed texture RGB", 0xdeadbeef, TRUE,
9263 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9264 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9268 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY, 0,
9269 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0, FALSE,
9270 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
9273 DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY, 0,
9274 DDERR_INVALIDPARAMS, DD_OK, TRUE, "sysmem zbuffer", 0, FALSE,
9275 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
9278 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
9279 * different afterwards. DX9+ GPUs set one of the two luminance values
9280 * in each block, but AMD and Nvidia GPUs disagree on which luminance
9281 * value they set. r200 (dx8) just sets the entire block to the clear
9282 * value. */
9283 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9284 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
9286 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
9287 {0}, {0}, {0}, {0}, {0}
9291 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9292 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
9294 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
9295 {0}, {0}, {0}, {0}, {0}
9299 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
9300 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
9302 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
9303 {0}, {0}, {0}, {0}, {0}
9307 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
9308 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
9310 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
9311 {0}, {0}, {0}, {0}, {0}
9315 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
9316 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
9318 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
9319 {0}, {0}, {0}, {0}, {0}
9323 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
9324 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
9326 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
9327 {0}, {0}, {0}, {0}, {0}
9331 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
9332 * surface works, presumably because it is handled by the runtime instead of
9333 * the driver. */
9334 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9335 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
9337 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
9338 {8}, {0}, {0}, {0}, {0}
9342 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
9343 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
9345 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
9346 {8}, {0}, {0}, {0}, {0}
9350 static const struct
9352 DWORD rop;
9353 const char *name;
9354 HRESULT hr;
9356 rops[] =
9358 {SRCCOPY, "SRCCOPY", DD_OK},
9359 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
9360 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
9361 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
9362 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
9363 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
9364 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
9365 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
9366 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
9367 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
9368 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
9369 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
9370 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
9371 {BLACKNESS, "BLACKNESS", DD_OK},
9372 {WHITENESS, "WHITENESS", DD_OK},
9373 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
9376 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9377 0, 0, 640, 480, 0, 0, 0, 0);
9379 if (!(device = create_device(window, DDSCL_NORMAL)))
9381 skip("Failed to create a 3D device, skipping test.\n");
9382 DestroyWindow(window);
9383 return;
9386 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
9387 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9388 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
9389 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
9391 memset(&z_fmt, 0, sizeof(z_fmt));
9392 IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
9393 if (!z_fmt.dwSize)
9394 skip("No Z buffer formats supported, skipping Z buffer colorfill test.\n");
9396 IDirect3DDevice3_EnumTextureFormats(device, test_block_formats_creation_cb, &supported_fmts);
9397 if (!(supported_fmts & SUPPORT_DXT1))
9398 skip("DXT1 textures not supported, skipping DXT1 colorfill test.\n");
9400 IDirect3D3_Release(d3d);
9402 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
9403 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
9404 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
9405 num_fourcc_codes * sizeof(*fourcc_codes));
9406 if (!fourcc_codes)
9407 goto done;
9408 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
9409 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
9410 for (i = 0; i < num_fourcc_codes; i++)
9412 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
9413 supported_fmts |= SUPPORT_YUY2;
9414 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
9415 supported_fmts |= SUPPORT_UYVY;
9417 HeapFree(GetProcessHeap(), 0, fourcc_codes);
9419 memset(&hal_caps, 0, sizeof(hal_caps));
9420 hal_caps.dwSize = sizeof(hal_caps);
9421 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
9422 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9424 if (!(supported_fmts & (SUPPORT_YUY2 | SUPPORT_UYVY)) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
9425 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
9427 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
9429 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
9430 memset(&fx, 0, sizeof(fx));
9431 fx.dwSize = sizeof(fx);
9432 U5(fx).dwFillColor = 0xdeadbeef;
9434 memset(&surface_desc, 0, sizeof(surface_desc));
9435 surface_desc.dwSize = sizeof(surface_desc);
9436 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9437 surface_desc.dwWidth = 64;
9438 surface_desc.dwHeight = 64;
9439 U4(surface_desc).ddpfPixelFormat = tests[i].format;
9440 surface_desc.ddsCaps.dwCaps = tests[i].caps;
9441 surface_desc.ddsCaps.dwCaps2 = tests[i].caps2;
9443 if (tests[i].format.dwFourCC == MAKEFOURCC('D','X','T','1') && !(supported_fmts & SUPPORT_DXT1))
9444 continue;
9445 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !(supported_fmts & SUPPORT_YUY2))
9446 continue;
9447 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !(supported_fmts & SUPPORT_UYVY))
9448 continue;
9449 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
9450 continue;
9452 if (tests[i].caps & DDSCAPS_ZBUFFER)
9454 if (!z_fmt.dwSize)
9455 continue;
9457 U4(surface_desc).ddpfPixelFormat = z_fmt;
9460 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9461 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, surface %s.\n", hr, tests[i].name);
9463 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9464 todo_wine_if (tests[i].format.dwFourCC)
9465 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9466 hr, tests[i].colorfill_hr, tests[i].name);
9468 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9469 todo_wine_if (tests[i].format.dwFourCC)
9470 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9471 hr, tests[i].colorfill_hr, tests[i].name);
9473 if (SUCCEEDED(hr) && tests[i].check_result)
9475 memset(&surface_desc, 0, sizeof(surface_desc));
9476 surface_desc.dwSize = sizeof(surface_desc);
9477 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9478 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9479 color = surface_desc.lpSurface;
9480 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
9481 *color, tests[i].result, tests[i].name);
9482 hr = IDirectDrawSurface4_Unlock(surface, NULL);
9483 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9486 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9487 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9488 hr, tests[i].depthfill_hr, tests[i].name);
9489 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9490 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9491 hr, tests[i].depthfill_hr, tests[i].name);
9493 U5(fx).dwFillColor = 0xdeadbeef;
9494 fx.dwROP = BLACKNESS;
9495 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9496 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
9497 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
9498 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
9499 U5(fx).dwFillColor, tests[i].name);
9501 if (SUCCEEDED(hr) && tests[i].check_result)
9503 memset(&surface_desc, 0, sizeof(surface_desc));
9504 surface_desc.dwSize = sizeof(surface_desc);
9505 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9506 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9507 color = surface_desc.lpSurface;
9508 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
9509 *color, tests[i].name);
9510 hr = IDirectDrawSurface4_Unlock(surface, NULL);
9511 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9514 fx.dwROP = WHITENESS;
9515 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9516 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
9517 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
9518 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
9519 U5(fx).dwFillColor, tests[i].name);
9521 if (SUCCEEDED(hr) && tests[i].check_result)
9523 memset(&surface_desc, 0, sizeof(surface_desc));
9524 surface_desc.dwSize = sizeof(surface_desc);
9525 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9526 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9527 color = surface_desc.lpSurface;
9528 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
9529 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
9530 *color, tests[i].name);
9531 hr = IDirectDrawSurface4_Unlock(surface, NULL);
9532 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9535 IDirectDrawSurface4_Release(surface);
9538 memset(&fx, 0, sizeof(fx));
9539 fx.dwSize = sizeof(fx);
9540 U5(fx).dwFillColor = 0xdeadbeef;
9541 fx.dwROP = WHITENESS;
9543 memset(&surface_desc, 0, sizeof(surface_desc));
9544 surface_desc.dwSize = sizeof(surface_desc);
9545 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9546 surface_desc.dwWidth = 64;
9547 surface_desc.dwHeight = 64;
9548 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9549 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
9550 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9551 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9552 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9553 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9554 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
9555 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9556 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9557 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
9558 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9560 /* No DDBLTFX. */
9561 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
9562 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9563 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
9564 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9566 /* Unused source rectangle. */
9567 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9568 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9569 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9570 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9572 /* Unused source surface. */
9573 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9574 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9575 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9576 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9577 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9578 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9579 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9580 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9582 /* Inverted destination or source rectangle. */
9583 SetRect(&rect, 5, 7, 7, 5);
9584 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9585 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9586 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9587 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9588 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9589 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9590 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9591 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9592 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9593 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9595 /* Negative rectangle. */
9596 SetRect(&rect, -1, -1, 5, 5);
9597 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9598 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9599 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9600 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9601 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9602 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9603 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9604 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9605 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9606 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9608 /* Out of bounds rectangle. */
9609 SetRect(&rect, 0, 0, 65, 65);
9610 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9611 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9612 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9613 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9615 /* Combine multiple flags. */
9616 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9617 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9618 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
9619 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9620 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
9621 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9623 for (i = 0; i < sizeof(rops) / sizeof(*rops); i++)
9625 fx.dwROP = rops[i].rop;
9626 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9627 ok(hr == rops[i].hr, "Got unexpected hr %#x for rop %s.\n", hr, rops[i].name);
9630 IDirectDrawSurface4_Release(surface2);
9631 IDirectDrawSurface4_Release(surface);
9633 if (!z_fmt.dwSize)
9634 goto done;
9636 memset(&surface_desc, 0, sizeof(surface_desc));
9637 surface_desc.dwSize = sizeof(surface_desc);
9638 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9639 surface_desc.dwWidth = 64;
9640 surface_desc.dwHeight = 64;
9641 U4(surface_desc).ddpfPixelFormat = z_fmt;
9642 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
9643 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9644 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9645 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
9646 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9648 /* No DDBLTFX. */
9649 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
9650 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9652 /* Unused source rectangle. */
9653 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9654 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9656 /* Unused source surface. */
9657 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9658 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9659 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9660 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9662 /* Inverted destination or source rectangle. */
9663 SetRect(&rect, 5, 7, 7, 5);
9664 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9665 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9666 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9667 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9668 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9669 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9670 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9671 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9673 /* Negative rectangle. */
9674 SetRect(&rect, -1, -1, 5, 5);
9675 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9676 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9677 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9678 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9679 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9680 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9681 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9682 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9684 /* Out of bounds rectangle. */
9685 SetRect(&rect, 0, 0, 65, 65);
9686 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9687 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9689 /* Combine multiple flags. */
9690 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9691 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9693 IDirectDrawSurface4_Release(surface2);
9694 IDirectDrawSurface4_Release(surface);
9696 done:
9697 IDirectDraw4_Release(ddraw);
9698 refcount = IDirect3DDevice3_Release(device);
9699 ok(!refcount, "Device has %u references left.\n", refcount);
9700 DestroyWindow(window);
9703 static void test_texcoordindex(void)
9705 static struct
9707 struct vec3 pos;
9708 struct vec2 texcoord1;
9709 struct vec2 texcoord2;
9710 struct vec2 texcoord3;
9712 quad[] =
9714 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f}},
9715 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f}},
9716 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}},
9717 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}},
9719 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_TEX3;
9720 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
9721 IDirect3DDevice3 *device;
9722 IDirect3D3 *d3d;
9723 IDirectDraw4 *ddraw;
9724 IDirectDrawSurface4 *rt;
9725 IDirect3DViewport3 *viewport;
9726 HWND window;
9727 HRESULT hr;
9728 IDirectDrawSurface4 *surface1, *surface2;
9729 IDirect3DTexture2 *texture1, *texture2;
9730 DDSURFACEDESC2 surface_desc;
9731 ULONG refcount;
9732 D3DCOLOR color;
9733 DWORD *ptr;
9735 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9736 0, 0, 640, 480, 0, 0, 0, 0);
9737 if (!(device = create_device(window, DDSCL_NORMAL)))
9739 skip("Failed to create a 3D device, skipping test.\n");
9740 DestroyWindow(window);
9741 return;
9744 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
9745 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
9746 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
9747 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
9748 IDirect3D3_Release(d3d);
9750 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
9751 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9753 memset(&surface_desc, 0, sizeof(surface_desc));
9754 surface_desc.dwSize = sizeof(surface_desc);
9755 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9756 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9757 surface_desc.dwWidth = 2;
9758 surface_desc.dwHeight = 2;
9759 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9760 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
9761 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9762 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9763 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9764 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9765 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
9766 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
9767 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9768 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
9769 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9771 memset(&surface_desc, 0, sizeof(surface_desc));
9772 surface_desc.dwSize = sizeof(surface_desc);
9773 hr = IDirectDrawSurface4_Lock(surface1, 0, &surface_desc, 0, NULL);
9774 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9775 ptr = surface_desc.lpSurface;
9776 ptr[0] = 0xff000000;
9777 ptr[1] = 0xff00ff00;
9778 ptr += surface_desc.lPitch / sizeof(*ptr);
9779 ptr[0] = 0xff0000ff;
9780 ptr[1] = 0xff00ffff;
9781 hr = IDirectDrawSurface4_Unlock(surface1, NULL);
9782 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9784 memset(&surface_desc, 0, sizeof(surface_desc));
9785 surface_desc.dwSize = sizeof(surface_desc);
9786 hr = IDirectDrawSurface4_Lock(surface2, 0, &surface_desc, 0, NULL);
9787 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9788 ptr = surface_desc.lpSurface;
9789 ptr[0] = 0xff000000;
9790 ptr[1] = 0xff0000ff;
9791 ptr += surface_desc.lPitch / sizeof(*ptr);
9792 ptr[0] = 0xffff0000;
9793 ptr[1] = 0xffff00ff;
9794 hr = IDirectDrawSurface4_Unlock(surface2, 0);
9795 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9797 viewport = create_viewport(device, 0, 0, 640, 480);
9798 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
9799 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
9801 hr = IDirectDrawSurface4_QueryInterface(surface1, &IID_IDirect3DTexture2, (void **)&texture1);
9802 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
9803 hr = IDirectDrawSurface4_QueryInterface(surface2, &IID_IDirect3DTexture2, (void **)&texture2);
9804 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
9805 hr = IDirect3DDevice3_SetTexture(device, 0, texture1);
9806 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9807 hr = IDirect3DDevice3_SetTexture(device, 1, texture2);
9808 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9809 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
9810 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9811 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9812 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
9813 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9814 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
9815 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD);
9816 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
9817 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9818 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
9819 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
9820 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
9821 hr = IDirect3DDevice3_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
9822 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
9824 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_TEXCOORDINDEX, 1);
9825 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
9826 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 0);
9827 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
9829 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
9830 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
9832 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
9833 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9835 hr = IDirect3DDevice3_BeginScene(device);
9836 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9837 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
9838 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9839 hr = IDirect3DDevice3_EndScene(device);
9840 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9842 color = get_surface_color(rt, 160, 120);
9843 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9844 color = get_surface_color(rt, 480, 120);
9845 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
9846 color = get_surface_color(rt, 160, 360);
9847 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
9848 color = get_surface_color(rt, 480, 360);
9849 ok(compare_color(color, 0x00ffffff, 2), "Got unexpected color 0x%08x.\n", color);
9851 /* D3DTSS_TEXTURETRANSFORMFLAGS was introduced in D3D7, can't test it here. */
9853 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 2);
9854 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
9856 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
9857 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9859 hr = IDirect3DDevice3_BeginScene(device);
9860 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9861 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
9862 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9863 hr = IDirect3DDevice3_EndScene(device);
9864 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9866 color = get_surface_color(rt, 160, 120);
9867 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9868 color = get_surface_color(rt, 480, 120);
9869 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
9870 color = get_surface_color(rt, 160, 360);
9871 ok(compare_color(color, 0x00ff00ff, 2), "Got unexpected color 0x%08x.\n", color);
9872 color = get_surface_color(rt, 480, 360);
9873 ok(compare_color(color, 0x00ffff00, 2), "Got unexpected color 0x%08x.\n", color);
9875 IDirect3DTexture2_Release(texture2);
9876 IDirect3DTexture2_Release(texture1);
9877 IDirectDrawSurface4_Release(surface2);
9878 IDirectDrawSurface4_Release(surface1);
9880 destroy_viewport(device, viewport);
9882 IDirectDrawSurface4_Release(rt);
9883 IDirectDraw_Release(ddraw);
9884 refcount = IDirect3DDevice3_Release(device);
9885 ok(!refcount, "Device has %u references left.\n", refcount);
9886 DestroyWindow(window);
9889 static BOOL ddraw_is_nvidia(IDirectDraw4 *ddraw)
9891 DDDEVICEIDENTIFIER identifier;
9892 HRESULT hr;
9894 if (!strcmp(winetest_platform, "wine"))
9895 return FALSE;
9897 hr = IDirectDraw4_GetDeviceIdentifier(ddraw, &identifier, 0);
9898 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#x.\n", hr);
9899 return identifier.dwVendorId == 0x10de;
9902 static void test_colorkey_precision(void)
9904 static struct
9906 struct vec3 pos;
9907 struct vec2 texcoord;
9909 quad[] =
9911 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
9912 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
9913 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
9914 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
9916 IDirect3DDevice3 *device;
9917 IDirect3D3 *d3d;
9918 IDirectDraw4 *ddraw;
9919 IDirectDrawSurface4 *rt;
9920 IDirect3DViewport3 *viewport;
9921 HWND window;
9922 HRESULT hr;
9923 IDirectDrawSurface4 *src, *dst, *texture;
9924 IDirect3DTexture2 *d3d_texture;
9925 DDSURFACEDESC2 surface_desc, lock_desc;
9926 ULONG refcount;
9927 D3DCOLOR color;
9928 unsigned int t, c;
9929 DDCOLORKEY ckey;
9930 DDBLTFX fx;
9931 DWORD data[4] = {0}, color_mask;
9932 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
9933 BOOL is_nvidia, is_warp;
9934 static const struct
9936 unsigned int max, shift, bpp, clear;
9937 const char *name;
9938 BOOL skip_nv;
9939 DDPIXELFORMAT fmt;
9941 tests[] =
9944 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8", FALSE,
9946 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
9947 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
9952 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel", FALSE,
9954 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
9955 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
9960 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel", FALSE,
9962 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
9963 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
9968 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4", TRUE,
9970 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9971 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
9976 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9977 0, 0, 640, 480, 0, 0, 0, 0);
9978 if (!(device = create_device(window, DDSCL_NORMAL)))
9980 skip("Failed to create a 3D device, skipping test.\n");
9981 DestroyWindow(window);
9982 return;
9985 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
9986 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
9987 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
9988 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
9989 IDirect3D3_Release(d3d);
9990 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
9991 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9993 is_nvidia = ddraw_is_nvidia(ddraw);
9994 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
9995 * (color key doesn't match although the values are equal), and a false
9996 * positive when the color key is 0 and the texture contains the value 1.
9997 * I don't want to mark this broken unconditionally since this would
9998 * essentially disable the test on Windows. Also on random occasions
9999 * 254 == 255 and 255 != 255.*/
10000 is_warp = ddraw_is_warp(ddraw);
10002 viewport = create_viewport(device, 0, 0, 640, 480);
10003 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
10004 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
10006 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10007 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
10008 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
10009 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
10010 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
10011 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
10012 /* Multiply the texture read result with 0, that way the result color if the key doesn't
10013 * match is constant. In theory color keying works without reading the texture result
10014 * (meaning we could just op=arg1, arg1=tfactor), but the Geforce7 Windows driver begs
10015 * to differ. */
10016 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
10017 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10018 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10019 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10020 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
10021 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10022 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x00000000);
10023 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10025 memset(&fx, 0, sizeof(fx));
10026 fx.dwSize = sizeof(fx);
10027 memset(&lock_desc, 0, sizeof(lock_desc));
10028 lock_desc.dwSize = sizeof(lock_desc);
10030 for (t = 0; t < sizeof(tests) / sizeof(*tests); ++t)
10032 if (is_nvidia && tests[t].skip_nv)
10034 win_skip("Skipping test %s on Nvidia Windows drivers.\n", tests[t].name);
10035 continue;
10038 memset(&surface_desc, 0, sizeof(surface_desc));
10039 surface_desc.dwSize = sizeof(surface_desc);
10040 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10041 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10042 surface_desc.dwWidth = 4;
10043 surface_desc.dwHeight = 1;
10044 U4(surface_desc).ddpfPixelFormat = tests[t].fmt;
10045 /* Windows XP (at least with the r200 driver, other drivers untested) produces
10046 * garbage when doing color keyed texture->texture blits. */
10047 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL);
10048 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10049 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL);
10050 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10052 fx.dwFillColor = tests[t].clear;
10053 /* On the w8 testbot (WARP driver) the blit result has different values in the
10054 * X channel. */
10055 color_mask = U2(tests[t].fmt).dwRBitMask
10056 | U3(tests[t].fmt).dwGBitMask
10057 | U4(tests[t].fmt).dwBBitMask;
10059 for (c = 0; c <= tests[t].max; ++c)
10061 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
10062 * texture after it has been set once... */
10063 surface_desc.dwFlags |= DDSD_CKSRCBLT;
10064 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10065 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
10066 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
10067 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &texture, NULL);
10068 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10069 hr = IDirectDrawSurface4_QueryInterface(texture, &IID_IDirect3DTexture2, (void **)&d3d_texture);
10070 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
10071 hr = IDirect3DDevice3_SetTexture(device, 0, d3d_texture);
10072 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
10074 hr = IDirectDrawSurface4_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10075 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
10077 hr = IDirectDrawSurface4_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
10078 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10079 switch (tests[t].bpp)
10081 case 4:
10082 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
10083 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
10084 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
10085 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
10086 break;
10088 case 2:
10089 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
10090 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
10091 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
10092 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
10093 break;
10095 hr = IDirectDrawSurface4_Unlock(src, 0);
10096 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10097 hr = IDirectDrawSurface4_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
10098 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
10100 ckey.dwColorSpaceLowValue = c << tests[t].shift;
10101 ckey.dwColorSpaceHighValue = c << tests[t].shift;
10102 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
10103 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10105 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
10106 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
10108 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
10109 hr = IDirectDrawSurface4_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
10110 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10111 switch (tests[t].bpp)
10113 case 4:
10114 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
10115 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
10116 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
10117 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
10118 break;
10120 case 2:
10121 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
10122 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
10123 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
10124 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
10125 break;
10127 hr = IDirectDrawSurface4_Unlock(dst, 0);
10128 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10130 if (!c)
10132 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10133 tests[t].clear, data[0], tests[t].name, c);
10135 if (data[3] == tests[t].clear)
10137 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
10138 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
10139 * even when a different surface is used. The blit itself doesn't draw anything,
10140 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
10141 * never be masked out by the key.
10143 * On Windows 10 the problem is worse, Blt just hangs. For this reason the ARGB4444
10144 * test is disabled entirely.
10146 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
10147 * terrible on WARP. */
10148 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
10149 IDirect3DTexture2_Release(d3d_texture);
10150 IDirectDrawSurface4_Release(texture);
10151 IDirectDrawSurface4_Release(src);
10152 IDirectDrawSurface4_Release(dst);
10153 goto done;
10156 else
10157 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10158 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
10160 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10161 tests[t].clear, data[1], tests[t].name, c);
10163 if (c == tests[t].max)
10164 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10165 tests[t].clear, data[2], tests[t].name, c);
10166 else
10167 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10168 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
10170 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
10171 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10173 hr = IDirect3DDevice3_BeginScene(device);
10174 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10175 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
10176 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10177 hr = IDirect3DDevice3_EndScene(device);
10178 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10180 color = get_surface_color(rt, 80, 240);
10181 if (!c)
10182 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10183 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10184 color, tests[t].name, c);
10185 else
10186 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
10187 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10188 color, tests[t].name, c);
10190 color = get_surface_color(rt, 240, 240);
10191 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10192 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10193 color, tests[t].name, c);
10195 color = get_surface_color(rt, 400, 240);
10196 if (c == tests[t].max)
10197 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10198 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10199 color, tests[t].name, c);
10200 else
10201 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
10202 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10203 color, tests[t].name, c);
10205 IDirect3DTexture2_Release(d3d_texture);
10206 IDirectDrawSurface4_Release(texture);
10208 IDirectDrawSurface4_Release(src);
10209 IDirectDrawSurface4_Release(dst);
10211 done:
10213 destroy_viewport(device, viewport);
10214 IDirectDrawSurface4_Release(rt);
10215 IDirectDraw4_Release(ddraw);
10216 refcount = IDirect3DDevice3_Release(device);
10217 ok(!refcount, "Device has %u references left.\n", refcount);
10218 DestroyWindow(window);
10221 static void test_range_colorkey(void)
10223 IDirectDraw4 *ddraw;
10224 HWND window;
10225 HRESULT hr;
10226 IDirectDrawSurface4 *surface;
10227 DDSURFACEDESC2 surface_desc;
10228 ULONG refcount;
10229 DDCOLORKEY ckey;
10231 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10232 0, 0, 640, 480, 0, 0, 0, 0);
10233 ddraw = create_ddraw();
10234 ok(!!ddraw, "Failed to create a ddraw object.\n");
10235 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10236 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10238 memset(&surface_desc, 0, sizeof(surface_desc));
10239 surface_desc.dwSize = sizeof(surface_desc);
10240 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
10241 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10242 surface_desc.dwWidth = 1;
10243 surface_desc.dwHeight = 1;
10244 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10245 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10246 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10247 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10248 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10249 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
10251 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
10252 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10253 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
10254 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10255 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10257 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
10258 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10259 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10260 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10262 /* Same for DDSCAPS_OFFSCREENPLAIN. */
10263 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10264 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10265 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
10266 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10267 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10269 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
10270 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10271 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10272 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10274 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10275 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10276 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10277 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10279 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
10280 ckey.dwColorSpaceLowValue = 0x00000000;
10281 ckey.dwColorSpaceHighValue = 0x00000001;
10282 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10283 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10285 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10286 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10287 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10288 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10290 ckey.dwColorSpaceLowValue = 0x00000001;
10291 ckey.dwColorSpaceHighValue = 0x00000000;
10292 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10293 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10295 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10296 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10297 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10298 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10300 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
10301 ckey.dwColorSpaceLowValue = 0x00000000;
10302 ckey.dwColorSpaceHighValue = 0x00000000;
10303 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10304 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10306 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
10307 ckey.dwColorSpaceLowValue = 0x00000001;
10308 ckey.dwColorSpaceHighValue = 0x00000000;
10309 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10310 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10311 ckey.dwColorSpaceLowValue = 0x00000000;
10312 ckey.dwColorSpaceHighValue = 0x00000001;
10313 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10314 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10315 /* Range destination keys don't work either. */
10316 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
10317 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10319 /* Just to show it's not because of A, R, and G having equal values. */
10320 ckey.dwColorSpaceLowValue = 0x00000000;
10321 ckey.dwColorSpaceHighValue = 0x01010101;
10322 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10323 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10325 /* None of these operations modified the key. */
10326 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10327 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10328 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10329 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10331 IDirectDrawSurface4_Release(surface),
10332 refcount = IDirectDraw4_Release(ddraw);
10333 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
10334 DestroyWindow(window);
10337 static void test_shademode(void)
10339 IDirect3DVertexBuffer *vb_strip, *vb_list, *buffer;
10340 IDirect3DViewport3 *viewport;
10341 IDirect3DDevice3 *device;
10342 D3DVERTEXBUFFERDESC desc;
10343 IDirectDrawSurface4 *rt;
10344 DWORD color0, color1;
10345 void *data = NULL;
10346 IDirect3D3 *d3d;
10347 ULONG refcount;
10348 UINT i, count;
10349 HWND window;
10350 HRESULT hr;
10351 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
10352 static const struct
10354 struct vec3 position;
10355 DWORD diffuse;
10357 quad_strip[] =
10359 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
10360 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
10361 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
10362 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
10364 quad_list[] =
10366 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
10367 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
10368 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
10370 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
10371 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
10372 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
10374 static const struct
10376 DWORD primtype;
10377 DWORD shademode;
10378 DWORD color0, color1;
10380 tests[] =
10382 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x0000ff00},
10383 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
10384 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
10385 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
10386 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
10387 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
10390 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10391 0, 0, 640, 480, 0, 0, 0, 0);
10393 if (!(device = create_device(window, DDSCL_NORMAL)))
10395 skip("Failed to create a 3D device, skipping test.\n");
10396 DestroyWindow(window);
10397 return;
10400 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
10401 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
10402 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
10403 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10405 viewport = create_viewport(device, 0, 0, 640, 480);
10406 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
10407 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
10409 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
10410 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
10412 memset(&desc, 0, sizeof(desc));
10413 desc.dwSize = sizeof(desc);
10414 desc.dwCaps = D3DVBCAPS_WRITEONLY;
10415 desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
10416 desc.dwNumVertices = sizeof(quad_strip) / sizeof(*quad_strip);
10417 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &vb_strip, 0, NULL);
10418 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
10419 hr = IDirect3DVertexBuffer_Lock(vb_strip, 0, &data, NULL);
10420 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
10421 memcpy(data, quad_strip, sizeof(quad_strip));
10422 hr = IDirect3DVertexBuffer_Unlock(vb_strip);
10423 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
10425 desc.dwNumVertices = sizeof(quad_list) / sizeof(*quad_list);
10426 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &vb_list, 0, NULL);
10427 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
10428 hr = IDirect3DVertexBuffer_Lock(vb_list, 0, &data, NULL);
10429 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
10430 memcpy(data, quad_list, sizeof(quad_list));
10431 hr = IDirect3DVertexBuffer_Unlock(vb_list);
10432 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
10434 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
10435 * the color fixups we have to do for FLAT shading will be dependent on that. */
10437 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
10439 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
10440 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
10442 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
10443 ok(hr == D3D_OK, "Failed to set shade mode, hr %#x.\n", hr);
10445 hr = IDirect3DDevice3_BeginScene(device);
10446 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10447 buffer = tests[i].primtype == D3DPT_TRIANGLESTRIP ? vb_strip : vb_list;
10448 count = tests[i].primtype == D3DPT_TRIANGLESTRIP ? 4 : 6;
10449 hr = IDirect3DDevice3_DrawPrimitiveVB(device, tests[i].primtype, buffer, 0, count, 0);
10450 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10451 hr = IDirect3DDevice3_EndScene(device);
10452 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10454 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
10455 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
10457 /* For D3DSHADE_FLAT it should take the color of the first vertex of
10458 * each triangle. This requires EXT_provoking_vertex or similar
10459 * functionality being available. */
10460 /* PHONG should be the same as GOURAUD, since no hardware implements
10461 * this. */
10462 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
10463 i, color0, tests[i].color0);
10464 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
10465 i, color1, tests[i].color1);
10468 IDirect3DVertexBuffer_Release(vb_strip);
10469 IDirect3DVertexBuffer_Release(vb_list);
10470 destroy_viewport(device, viewport);
10471 IDirectDrawSurface4_Release(rt);
10472 IDirect3D3_Release(d3d);
10473 refcount = IDirect3DDevice3_Release(device);
10474 ok(!refcount, "Device has %u references left.\n", refcount);
10475 DestroyWindow(window);
10478 static void test_lockrect_invalid(void)
10480 unsigned int i, r;
10481 IDirectDraw4 *ddraw;
10482 IDirectDrawSurface4 *surface;
10483 HWND window;
10484 HRESULT hr;
10485 DDSURFACEDESC2 surface_desc;
10486 DDCAPS hal_caps;
10487 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
10488 static RECT valid[] =
10490 {60, 60, 68, 68},
10491 {60, 60, 60, 68},
10492 {60, 60, 68, 60},
10493 {120, 60, 128, 68},
10494 {60, 120, 68, 128},
10496 static RECT invalid[] =
10498 {68, 60, 60, 68}, /* left > right */
10499 {60, 68, 68, 60}, /* top > bottom */
10500 {-8, 60, 0, 68}, /* left < surface */
10501 {60, -8, 68, 0}, /* top < surface */
10502 {-16, 60, -8, 68}, /* right < surface */
10503 {60, -16, 68, -8}, /* bottom < surface */
10504 {60, 60, 136, 68}, /* right > surface */
10505 {60, 60, 68, 136}, /* bottom > surface */
10506 {136, 60, 144, 68}, /* left > surface */
10507 {60, 136, 68, 144}, /* top > surface */
10509 static const struct
10511 DWORD caps, caps2;
10512 const char *name;
10513 HRESULT hr;
10515 resources[] =
10517 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", DDERR_INVALIDPARAMS},
10518 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", DDERR_INVALIDPARAMS},
10519 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", DDERR_INVALIDPARAMS},
10520 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", DDERR_INVALIDPARAMS},
10521 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", DDERR_INVALIDPARAMS},
10524 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10525 0, 0, 640, 480, 0, 0, 0, 0);
10526 ddraw = create_ddraw();
10527 ok(!!ddraw, "Failed to create a ddraw object.\n");
10528 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10529 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10531 memset(&hal_caps, 0, sizeof(hal_caps));
10532 hal_caps.dwSize = sizeof(hal_caps);
10533 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
10534 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
10535 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
10536 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
10538 skip("Required surface types not supported, skipping test.\n");
10539 goto done;
10542 for (r = 0; r < sizeof(resources) / sizeof(*resources); ++r)
10544 memset(&surface_desc, 0, sizeof(surface_desc));
10545 surface_desc.dwSize = sizeof(surface_desc);
10546 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10547 surface_desc.ddsCaps.dwCaps = resources[r].caps;
10548 surface_desc.ddsCaps.dwCaps2 = resources[r].caps2;
10549 surface_desc.dwWidth = 128;
10550 surface_desc.dwHeight = 128;
10551 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10552 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10553 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10554 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xff0000;
10555 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x00ff00;
10556 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000ff;
10558 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10559 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, resources[r].name);
10561 hr = IDirectDrawSurface4_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
10562 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
10564 for (i = 0; i < sizeof(valid) / sizeof(*valid); ++i)
10566 RECT *rect = &valid[i];
10568 memset(&surface_desc, 0, sizeof(surface_desc));
10569 surface_desc.dwSize = sizeof(surface_desc);
10571 hr = IDirectDrawSurface4_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
10572 ok(SUCCEEDED(hr), "Lock failed (%#x) for rect %s, type %s.\n",
10573 hr, wine_dbgstr_rect(rect), resources[r].name);
10575 hr = IDirectDrawSurface4_Unlock(surface, NULL);
10576 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
10579 for (i = 0; i < sizeof(invalid) / sizeof(*invalid); ++i)
10581 RECT *rect = &invalid[i];
10583 memset(&surface_desc, 1, sizeof(surface_desc));
10584 surface_desc.dwSize = sizeof(surface_desc);
10586 hr = IDirectDrawSurface4_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
10587 ok(hr == resources[r].hr, "Lock returned %#x for rect %s, type %s.\n",
10588 hr, wine_dbgstr_rect(rect), resources[r].name);
10589 if (SUCCEEDED(hr))
10591 hr = IDirectDrawSurface4_Unlock(surface, NULL);
10592 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
10594 else
10595 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
10598 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
10599 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#x, type %s.\n",
10600 hr, resources[r].name);
10601 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
10602 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#x, type %s.\n",
10603 hr, resources[r].name);
10604 hr = IDirectDrawSurface4_Unlock(surface, NULL);
10605 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
10607 hr = IDirectDrawSurface4_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
10608 ok(SUCCEEDED(hr), "Lock(rect = %s) failed (%#x).\n", wine_dbgstr_rect(&valid[0]), hr);
10609 hr = IDirectDrawSurface4_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
10610 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = %s) failed (%#x).\n",
10611 wine_dbgstr_rect(&valid[0]), hr);
10613 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
10614 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
10616 hr = IDirectDrawSurface4_Unlock(surface, NULL);
10617 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
10619 IDirectDrawSurface4_Release(surface);
10622 done:
10623 IDirectDraw4_Release(ddraw);
10624 DestroyWindow(window);
10627 static void test_yv12_overlay(void)
10629 IDirectDrawSurface4 *src_surface, *dst_surface;
10630 RECT rect = {13, 17, 14, 18};
10631 unsigned int offset, y;
10632 DDSURFACEDESC2 desc;
10633 unsigned char *base;
10634 IDirectDraw4 *ddraw;
10635 HWND window;
10636 HRESULT hr;
10638 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10639 0, 0, 640, 480, 0, 0, 0, 0);
10640 ddraw = create_ddraw();
10641 ok(!!ddraw, "Failed to create a ddraw object.\n");
10642 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10643 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10645 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
10647 skip("Failed to create a YV12 overlay, skipping test.\n");
10648 goto done;
10651 memset(&desc, 0, sizeof(desc));
10652 desc.dwSize = sizeof(desc);
10653 hr = IDirectDrawSurface4_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
10654 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10656 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
10657 "Got unexpected flags %#x.\n", desc.dwFlags);
10658 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
10659 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
10660 "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps);
10661 ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth);
10662 ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight);
10663 /* The overlay pitch seems to have 256 byte alignment. */
10664 ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch);
10666 /* Fill the surface with some data for the blit test. */
10667 base = desc.lpSurface;
10668 /* Luminance */
10669 for (y = 0; y < desc.dwHeight; ++y)
10671 memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth);
10673 /* V */
10674 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
10676 memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth);
10678 /* U */
10679 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
10681 memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth);
10684 hr = IDirectDrawSurface4_Unlock(src_surface, NULL);
10685 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10687 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
10688 * other block-based formats like DXT the entire Y channel is stored in
10689 * one big chunk of memory, followed by the chroma channels. So partial
10690 * locks do not really make sense. Show that they are allowed nevertheless
10691 * and the offset points into the luminance data. */
10692 hr = IDirectDrawSurface4_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
10693 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10694 offset = ((const unsigned char *)desc.lpSurface - base);
10695 ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n",
10696 offset, rect.top * U1(desc).lPitch + rect.left);
10697 hr = IDirectDrawSurface4_Unlock(src_surface, NULL);
10698 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10700 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
10702 /* Windows XP with a Radeon X1600 GPU refuses to create a second
10703 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
10704 skip("Failed to create a second YV12 surface, skipping blit test.\n");
10705 IDirectDrawSurface4_Release(src_surface);
10706 goto done;
10709 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
10710 /* VMware rejects YV12 blits. This behavior has not been seen on real
10711 * hardware yet, so mark it broken. */
10712 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr);
10714 if (SUCCEEDED(hr))
10716 memset(&desc, 0, sizeof(desc));
10717 desc.dwSize = sizeof(desc);
10718 hr = IDirectDrawSurface4_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
10719 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10721 base = desc.lpSurface;
10722 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
10723 base += desc.dwHeight * U1(desc).lPitch;
10724 todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
10725 base += desc.dwHeight / 4 * U1(desc).lPitch;
10726 todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
10728 hr = IDirectDrawSurface4_Unlock(dst_surface, NULL);
10729 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10732 IDirectDrawSurface4_Release(dst_surface);
10733 IDirectDrawSurface4_Release(src_surface);
10734 done:
10735 IDirectDraw4_Release(ddraw);
10736 DestroyWindow(window);
10739 static BOOL dwm_enabled(void)
10741 BOOL ret = FALSE;
10743 if (!strcmp(winetest_platform, "wine"))
10744 return FALSE;
10745 if (!pDwmIsCompositionEnabled)
10746 return FALSE;
10747 if (FAILED(pDwmIsCompositionEnabled(&ret)))
10748 return FALSE;
10749 return ret;
10752 static void test_offscreen_overlay(void)
10754 IDirectDrawSurface4 *overlay, *offscreen, *primary;
10755 DDSURFACEDESC2 surface_desc;
10756 IDirectDraw4 *ddraw;
10757 HWND window;
10758 HRESULT hr;
10759 HDC dc;
10761 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10762 0, 0, 640, 480, 0, 0, 0, 0);
10763 ddraw = create_ddraw();
10764 ok(!!ddraw, "Failed to create a ddraw object.\n");
10765 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10766 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10768 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
10770 skip("Failed to create a UYVY overlay, skipping test.\n");
10771 goto done;
10774 memset(&surface_desc, 0, sizeof(surface_desc));
10775 surface_desc.dwSize = sizeof(surface_desc);
10776 surface_desc.dwFlags = DDSD_CAPS;
10777 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
10778 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
10779 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
10781 /* On Windows 7, and probably Vista, UpdateOverlay() will return
10782 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
10783 * surface prevents this by disabling the dwm. */
10784 hr = IDirectDrawSurface4_GetDC(primary, &dc);
10785 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
10786 hr = IDirectDrawSurface4_ReleaseDC(primary, dc);
10787 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
10789 /* Try to overlay a NULL surface. */
10790 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
10791 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10792 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
10793 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10795 /* Try to overlay an offscreen surface. */
10796 memset(&surface_desc, 0, sizeof(surface_desc));
10797 surface_desc.dwSize = sizeof(surface_desc);
10798 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
10799 surface_desc.dwWidth = 64;
10800 surface_desc.dwHeight = 64;
10801 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10802 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10803 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10804 U4(surface_desc).ddpfPixelFormat.dwFourCC = 0;
10805 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
10806 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
10807 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
10808 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
10809 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
10810 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
10812 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
10813 ok(SUCCEEDED(hr) || broken(hr == DDERR_OUTOFCAPS && dwm_enabled()),
10814 "Failed to update overlay, hr %#x.\n", hr);
10816 /* Try to overlay the primary with a non-overlay surface. */
10817 hr = IDirectDrawSurface4_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
10818 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
10819 hr = IDirectDrawSurface4_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_HIDE, NULL);
10820 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
10822 IDirectDrawSurface4_Release(offscreen);
10823 IDirectDrawSurface4_Release(primary);
10824 IDirectDrawSurface4_Release(overlay);
10825 done:
10826 IDirectDraw4_Release(ddraw);
10827 DestroyWindow(window);
10830 static void test_overlay_rect(void)
10832 IDirectDrawSurface4 *overlay, *primary = NULL;
10833 DDSURFACEDESC2 surface_desc;
10834 RECT rect = {0, 0, 64, 64};
10835 IDirectDraw4 *ddraw;
10836 LONG pos_x, pos_y;
10837 HRESULT hr, hr2;
10838 HWND window;
10839 HDC dc;
10841 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10842 0, 0, 640, 480, 0, 0, 0, 0);
10843 ddraw = create_ddraw();
10844 ok(!!ddraw, "Failed to create a ddraw object.\n");
10845 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10846 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10848 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
10850 skip("Failed to create a UYVY overlay, skipping test.\n");
10851 goto done;
10854 memset(&surface_desc, 0, sizeof(surface_desc));
10855 surface_desc.dwSize = sizeof(surface_desc);
10856 surface_desc.dwFlags = DDSD_CAPS;
10857 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
10858 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
10859 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
10861 /* On Windows 7, and probably Vista, UpdateOverlay() will return
10862 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
10863 * surface prevents this by disabling the dwm. */
10864 hr = IDirectDrawSurface4_GetDC(primary, &dc);
10865 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
10866 hr = IDirectDrawSurface4_ReleaseDC(primary, dc);
10867 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
10869 /* On Windows 8 and newer DWM can't be turned off, making overlays unusable. */
10870 if (dwm_enabled())
10872 win_skip("Cannot disable DWM, skipping overlay test.\n");
10873 goto done;
10876 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is
10877 * used. This is not true in Windows Vista and earlier, but changed in
10878 * Windows 7. */
10879 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
10880 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
10881 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
10882 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
10883 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
10884 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10886 /* Show that the overlay position is the (top, left) coordinate of the
10887 * destination rectangle. */
10888 OffsetRect(&rect, 32, 16);
10889 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
10890 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
10891 pos_x = -1; pos_y = -1;
10892 hr = IDirectDrawSurface4_GetOverlayPosition(overlay, &pos_x, &pos_y);
10893 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
10894 ok(pos_x == rect.left, "Got unexpected pos_x %d, expected %d.\n", pos_x, rect.left);
10895 ok(pos_y == rect.top, "Got unexpected pos_y %d, expected %d.\n", pos_y, rect.top);
10897 /* Passing a NULL dest rect sets the position to 0/0. Visually it can be
10898 * seen that the overlay overlays the whole primary(==screen). */
10899 hr2 = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
10900 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS || hr2 == DDERR_OUTOFCAPS, "Got unexpected hr %#x.\n", hr2);
10901 hr = IDirectDrawSurface4_GetOverlayPosition(overlay, &pos_x, &pos_y);
10902 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
10903 if (SUCCEEDED(hr2))
10905 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
10906 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
10908 else
10910 ok(pos_x == 32, "Got unexpected pos_x %d.\n", pos_x);
10911 ok(pos_y == 16, "Got unexpected pos_y %d.\n", pos_y);
10914 /* The position cannot be retrieved when the overlay is not shown. */
10915 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
10916 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
10917 pos_x = -1; pos_y = -1;
10918 hr = IDirectDrawSurface4_GetOverlayPosition(overlay, &pos_x, &pos_y);
10919 ok(hr == DDERR_OVERLAYNOTVISIBLE, "Got unexpected hr %#x.\n", hr);
10920 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
10921 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
10923 IDirectDrawSurface4_Release(overlay);
10924 done:
10925 if (primary)
10926 IDirectDrawSurface4_Release(primary);
10927 IDirectDraw4_Release(ddraw);
10928 DestroyWindow(window);
10931 static void test_blt(void)
10933 IDirectDrawSurface4 *surface, *rt;
10934 DDSURFACEDESC2 surface_desc;
10935 IDirect3DDevice3 *device;
10936 IDirectDraw4 *ddraw;
10937 IDirect3D3 *d3d;
10938 unsigned int i;
10939 ULONG refcount;
10940 HWND window;
10941 HRESULT hr;
10943 static struct
10945 RECT src_rect;
10946 RECT dst_rect;
10947 HRESULT hr;
10949 test_data[] =
10951 {{160, 0, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit. */
10952 {{160, 480, 640, 0}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, flipped source. */
10953 {{640, 0, 160, 480}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, mirrored source. */
10954 {{160, 0, 480, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched x. */
10955 {{160, 160, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched y. */
10956 {{ 0, 0, 640, 480}, { 0, 0, 640, 480}, DD_OK}, /* Full surface blit. */
10957 {{ 0, 0, 640, 480}, { 0, 480, 640, 0}, DDERR_INVALIDRECT}, /* Full surface, flipped destination. */
10958 {{ 0, 0, 640, 480}, {640, 0, 0, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored destination. */
10959 {{ 0, 480, 640, 0}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, flipped source. */
10960 {{640, 0, 0, 480}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored source. */
10963 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10964 0, 0, 640, 480, 0, 0, 0, 0);
10965 if (!(device = create_device(window, DDSCL_NORMAL)))
10967 skip("Failed to create a 3D device, skipping test.\n");
10968 DestroyWindow(window);
10969 return;
10972 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
10973 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
10974 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
10975 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
10976 IDirect3D3_Release(d3d);
10977 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
10978 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10980 memset(&surface_desc, 0, sizeof(surface_desc));
10981 surface_desc.dwSize = sizeof(surface_desc);
10982 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
10983 surface_desc.dwWidth = 640;
10984 surface_desc.dwHeight = 480;
10985 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10986 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10987 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10989 hr = IDirectDrawSurface_Blt(surface, NULL, surface, NULL, 0, NULL);
10990 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
10992 hr = IDirectDrawSurface_Blt(surface, NULL, rt, NULL, 0, NULL);
10993 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
10995 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
10997 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
10998 surface, &test_data[i].src_rect, DDBLT_WAIT, NULL);
10999 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
11001 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
11002 rt, &test_data[i].src_rect, DDBLT_WAIT, NULL);
11003 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
11006 IDirectDrawSurface4_Release(surface);
11007 IDirectDrawSurface4_Release(rt);
11008 IDirectDraw4_Release(ddraw);
11009 refcount = IDirect3DDevice3_Release(device);
11010 ok(!refcount, "Device has %u references left.\n", refcount);
11011 DestroyWindow(window);
11014 static void test_color_clamping(void)
11016 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
11017 static D3DMATRIX mat =
11019 1.0f, 0.0f, 0.0f, 0.0f,
11020 0.0f, 1.0f, 0.0f, 0.0f,
11021 0.0f, 0.0f, 1.0f, 0.0f,
11022 0.0f, 0.0f, 0.0f, 1.0f,
11024 static struct vec3 quad[] =
11026 {-1.0f, -1.0f, 0.1f},
11027 {-1.0f, 1.0f, 0.1f},
11028 { 1.0f, -1.0f, 0.1f},
11029 { 1.0f, 1.0f, 0.1f},
11031 IDirect3DViewport3 *viewport;
11032 IDirect3DDevice3 *device;
11033 IDirectDrawSurface4 *rt;
11034 ULONG refcount;
11035 D3DCOLOR color;
11036 HWND window;
11037 HRESULT hr;
11039 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
11040 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11042 if (!(device = create_device(window, DDSCL_NORMAL)))
11044 skip("Failed to create a 3D device, skipping test.\n");
11045 DestroyWindow(window);
11046 return;
11049 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
11050 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11052 viewport = create_viewport(device, 0, 0, 640, 480);
11053 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
11054 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
11056 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
11057 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
11058 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
11059 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
11060 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
11061 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
11062 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
11063 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
11064 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
11065 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
11066 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
11067 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
11068 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
11069 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
11070 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
11071 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
11072 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
11073 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
11075 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0xff404040);
11076 ok(SUCCEEDED(hr), "Failed to set texture factor, hr %#x.\n", hr);
11077 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_ADD);
11078 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11079 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
11080 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11081 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_SPECULAR);
11082 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11083 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_MODULATE);
11084 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11085 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TFACTOR);
11086 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11087 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
11088 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11090 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
11091 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
11093 hr = IDirect3DDevice3_BeginScene(device);
11094 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11096 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
11097 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11099 hr = IDirect3DDevice3_EndScene(device);
11100 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11102 color = get_surface_color(rt, 320, 240);
11103 ok(compare_color(color, 0x00404040, 1), "Got unexpected color 0x%08x.\n", color);
11105 destroy_viewport(device, viewport);
11106 IDirectDrawSurface4_Release(rt);
11107 refcount = IDirect3DDevice3_Release(device);
11108 ok(!refcount, "Device has %u references left.\n", refcount);
11109 DestroyWindow(window);
11112 static void test_getdc(void)
11114 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
11115 IDirectDrawSurface4 *surface, *surface2, *tmp;
11116 DDSURFACEDESC2 surface_desc, map_desc;
11117 IDirectDraw4 *ddraw;
11118 unsigned int i;
11119 HWND window;
11120 HDC dc, dc2;
11121 HRESULT hr;
11123 static const struct
11125 const char *name;
11126 DDPIXELFORMAT format;
11127 BOOL getdc_supported;
11128 HRESULT alt_result;
11130 test_data[] =
11132 {"D3DFMT_A8R8G8B8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11133 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}}, TRUE},
11134 {"D3DFMT_X8R8G8B8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
11135 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}}, TRUE},
11136 {"D3DFMT_R5G6B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11137 {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}}, TRUE},
11138 {"D3DFMT_X1R5G5B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11139 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}}, TRUE},
11140 {"D3DFMT_A1R5G5B5", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
11141 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}}, TRUE},
11142 {"D3DFMT_A4R4G4B4", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
11143 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11144 {"D3DFMT_X4R4G4B4", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11145 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11146 {"D3DFMT_A2R10G10B10", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11147 {0xc0000000}, {0x3ff00000}, {0x000ffc00}, {0x000003ff}}, TRUE},
11148 {"D3DFMT_A8B8G8R8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11149 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11150 {"D3DFMT_X8B8G8R8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
11151 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11152 {"D3DFMT_R3G3B2", {sizeof(test_data->format), DDPF_RGB, 0, {8},
11153 {0x000000e0}, {0x0000001c}, {0x00000003}, {0x00000000}}, FALSE},
11154 /* GetDC() on a P8 surface fails unless the display mode is 8 bpp.
11155 * This is not implemented in wine yet, so disable the test for now.
11156 * Succeeding P8 GetDC() calls are tested in the ddraw:visual test.
11157 {"D3DFMT_P8", {sizeof(test_data->format), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0, {8 },
11158 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11160 {"D3DFMT_L8", {sizeof(test_data->format), DDPF_LUMINANCE, 0, {8},
11161 {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11162 {"D3DFMT_A8L8", {sizeof(test_data->format), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0, {16},
11163 {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}}, FALSE},
11164 {"D3DFMT_DXT1", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'), {0},
11165 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11166 {"D3DFMT_DXT2", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'), {0},
11167 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11168 {"D3DFMT_DXT3", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'), {0},
11169 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11170 {"D3DFMT_DXT4", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'), {0},
11171 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11172 {"D3DFMT_DXT5", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'), {0},
11173 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11176 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
11177 0, 0, 640, 480, 0, 0, 0, 0);
11178 ddraw = create_ddraw();
11179 ok(!!ddraw, "Failed to create a ddraw object.\n");
11180 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11181 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11183 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
11185 memset(&surface_desc, 0, sizeof(surface_desc));
11186 surface_desc.dwSize = sizeof(surface_desc);
11187 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11188 surface_desc.dwWidth = 64;
11189 surface_desc.dwHeight = 64;
11190 U4(surface_desc).ddpfPixelFormat = test_data[i].format;
11191 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11193 if (FAILED(IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11195 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11196 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
11197 if (FAILED(hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11199 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
11200 continue;
11204 dc = (void *)0x1234;
11205 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11206 if (test_data[i].getdc_supported)
11207 ok(SUCCEEDED(hr) || (test_data[i].alt_result && hr == test_data[i].alt_result),
11208 "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11209 else
11210 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11212 if (SUCCEEDED(hr))
11214 unsigned int width_bytes;
11215 DIBSECTION dib;
11216 HBITMAP bitmap;
11217 DWORD type;
11218 int size;
11220 type = GetObjectType(dc);
11221 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
11222 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
11223 type = GetObjectType(bitmap);
11224 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
11226 size = GetObjectA(bitmap, sizeof(dib), &dib);
11227 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, test_data[i].name);
11228 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
11229 dib.dsBm.bmType, test_data[i].name);
11230 ok(dib.dsBm.bmWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
11231 dib.dsBm.bmWidth, test_data[i].name);
11232 ok(dib.dsBm.bmHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
11233 dib.dsBm.bmHeight, test_data[i].name);
11234 width_bytes = ((dib.dsBm.bmWidth * U1(test_data[i].format).dwRGBBitCount + 31) >> 3) & ~3;
11235 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
11236 dib.dsBm.bmWidthBytes, test_data[i].name);
11237 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
11238 dib.dsBm.bmPlanes, test_data[i].name);
11239 ok(dib.dsBm.bmBitsPixel == U1(test_data[i].format).dwRGBBitCount,
11240 "Got unexpected bit count %d for format %s.\n",
11241 dib.dsBm.bmBitsPixel, test_data[i].name);
11242 ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n",
11243 dib.dsBm.bmBits, test_data[i].name);
11245 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
11246 dib.dsBmih.biSize, test_data[i].name);
11247 ok(dib.dsBmih.biWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
11248 dib.dsBmih.biHeight, test_data[i].name);
11249 ok(dib.dsBmih.biHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
11250 dib.dsBmih.biHeight, test_data[i].name);
11251 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
11252 dib.dsBmih.biPlanes, test_data[i].name);
11253 ok(dib.dsBmih.biBitCount == U1(test_data[i].format).dwRGBBitCount,
11254 "Got unexpected bit count %u for format %s.\n",
11255 dib.dsBmih.biBitCount, test_data[i].name);
11256 ok(dib.dsBmih.biCompression == (U1(test_data[i].format).dwRGBBitCount == 16 ? BI_BITFIELDS : BI_RGB)
11257 || broken(U2(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
11258 "Got unexpected compression %#x for format %s.\n",
11259 dib.dsBmih.biCompression, test_data[i].name);
11260 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
11261 dib.dsBmih.biSizeImage, test_data[i].name);
11262 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
11263 dib.dsBmih.biXPelsPerMeter, test_data[i].name);
11264 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
11265 dib.dsBmih.biYPelsPerMeter, test_data[i].name);
11266 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
11267 dib.dsBmih.biClrUsed, test_data[i].name);
11268 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
11269 dib.dsBmih.biClrImportant, test_data[i].name);
11271 if (dib.dsBmih.biCompression == BI_BITFIELDS)
11273 ok((dib.dsBitfields[0] == U2(test_data[i].format).dwRBitMask
11274 && dib.dsBitfields[1] == U3(test_data[i].format).dwGBitMask
11275 && dib.dsBitfields[2] == U4(test_data[i].format).dwBBitMask)
11276 || broken(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2]),
11277 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
11278 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
11280 else
11282 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
11283 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
11284 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
11286 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, test_data[i].name);
11287 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, test_data[i].name);
11289 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11290 ok(hr == DD_OK, "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11292 else
11294 ok(!dc, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
11297 IDirectDrawSurface4_Release(surface);
11299 if (FAILED(hr))
11300 continue;
11302 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
11303 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
11304 if (FAILED(hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11306 skip("Failed to create mip-mapped texture for format %s (hr %#x), skipping tests.\n",
11307 test_data[i].name, hr);
11308 continue;
11311 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &tmp);
11312 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
11313 hr = IDirectDrawSurface4_GetAttachedSurface(tmp, &caps, &surface2);
11314 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
11315 IDirectDrawSurface4_Release(tmp);
11317 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11318 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11319 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11320 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11321 hr = IDirectDrawSurface4_GetDC(surface2, &dc);
11322 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11323 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc);
11324 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11326 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11327 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11328 dc2 = (void *)0x1234;
11329 hr = IDirectDrawSurface4_GetDC(surface, &dc2);
11330 ok(hr == DDERR_DCALREADYCREATED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11331 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
11332 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11333 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11334 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11335 ok(hr == DDERR_NODC, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11337 map_desc.dwSize = sizeof(map_desc);
11338 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11339 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11340 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11341 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11342 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11343 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11344 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11345 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11347 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11348 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11349 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11350 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11351 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11352 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11354 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11355 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11356 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11357 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11358 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11359 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11360 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11361 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11363 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11364 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11365 hr = IDirectDrawSurface4_GetDC(surface2, &dc2);
11366 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11367 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc2);
11368 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11369 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11370 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11372 hr = IDirectDrawSurface4_GetDC(surface2, &dc);
11373 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11374 hr = IDirectDrawSurface4_GetDC(surface, &dc2);
11375 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11376 hr = IDirectDrawSurface4_ReleaseDC(surface, dc2);
11377 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11378 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc);
11379 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11381 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11382 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11383 hr = IDirectDrawSurface4_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11384 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11385 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
11386 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11387 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11388 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11390 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11391 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11392 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11393 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11394 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11395 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11396 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11397 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11399 hr = IDirectDrawSurface4_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11400 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11401 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11402 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11403 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11404 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11405 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
11406 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11408 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11409 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11410 hr = IDirectDrawSurface4_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11411 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11412 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
11413 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11414 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11415 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11417 hr = IDirectDrawSurface4_GetDC(surface2, &dc);
11418 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11419 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11420 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11421 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11422 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11423 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc);
11424 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11426 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11427 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11428 hr = IDirectDrawSurface4_GetDC(surface2, &dc);
11429 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11430 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11431 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11432 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc);
11433 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11434 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11435 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11437 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
11438 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11439 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11440 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11441 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
11442 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11443 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11444 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11445 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
11446 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11448 IDirectDrawSurface4_Release(surface2);
11449 IDirectDrawSurface4_Release(surface);
11452 IDirectDraw4_Release(ddraw);
11453 DestroyWindow(window);
11456 static void test_draw_primitive(void)
11458 static WORD indices[] = {0, 1, 2, 3};
11459 static struct vec3 quad[] =
11461 {-1.0f, -1.0f, 0.0f},
11462 {-1.0f, 1.0f, 0.0f},
11463 { 1.0f, -1.0f, 0.0f},
11464 { 1.0f, 1.0f, 0.0f},
11466 D3DDRAWPRIMITIVESTRIDEDDATA strided;
11467 IDirect3DViewport3 *viewport;
11468 D3DVERTEXBUFFERDESC vb_desc;
11469 IDirect3DVertexBuffer *vb;
11470 IDirect3DDevice3 *device;
11471 IDirect3D3 *d3d;
11472 ULONG refcount;
11473 HWND window;
11474 HRESULT hr;
11475 void *data;
11477 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
11478 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11480 if (!(device = create_device(window, DDSCL_NORMAL)))
11482 skip("Failed to create a 3D device, skipping test.\n");
11483 DestroyWindow(window);
11484 return;
11487 viewport = create_viewport(device, 0, 0, 640, 480);
11488 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
11489 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
11491 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
11492 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
11494 memset(&vb_desc, 0, sizeof(vb_desc));
11495 vb_desc.dwSize = sizeof(vb_desc);
11496 vb_desc.dwFVF = D3DFVF_XYZ;
11497 vb_desc.dwNumVertices = 4;
11498 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &vb, 0, NULL);
11499 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
11501 IDirect3D3_Release(d3d);
11503 memset(&strided, 0, sizeof(strided));
11505 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, NULL, 0, 0);
11506 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11507 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device,
11508 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, NULL, 0, 0);
11509 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11510 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, NULL, 0, 0);
11511 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11512 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, 0);
11513 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11514 hr = IDirect3DDevice3_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, 0);
11515 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11516 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, 0);
11517 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11519 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, indices, 4, 0);
11520 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11521 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device,
11522 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, indices, 4, 0);
11523 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11524 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, indices, 4, 0);
11525 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11527 strided.position.lpvData = quad;
11528 strided.position.dwStride = sizeof(*quad);
11529 hr = IDirect3DVertexBuffer_Lock(vb, 0, &data, NULL);
11530 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
11531 memcpy(data, quad, sizeof(quad));
11532 hr = IDirect3DVertexBuffer_Unlock(vb);
11533 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
11535 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, NULL, 0, 0);
11536 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11537 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device,
11538 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, NULL, 0, 0);
11539 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11540 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, NULL, 0, 0);
11541 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11542 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
11543 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11544 hr = IDirect3DDevice3_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, 0);
11545 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11546 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
11547 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11548 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, indices, 4, 0);
11549 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11550 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device,
11551 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, indices, 4, 0);
11552 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11553 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, indices, 4, 0);
11554 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11556 IDirect3DVertexBuffer_Release(vb);
11557 destroy_viewport(device, viewport);
11558 refcount = IDirect3DDevice3_Release(device);
11559 ok(!refcount, "Device has %u references left.\n", refcount);
11560 DestroyWindow(window);
11563 static void test_edge_antialiasing_blending(void)
11565 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
11566 IDirectDrawSurface4 *offscreen, *ds;
11567 D3DDEVICEDESC hal_desc, hel_desc;
11568 IDirect3DViewport3 *viewport;
11569 DDSURFACEDESC2 surface_desc;
11570 IDirect3DDevice3 *device;
11571 IDirectDraw4 *ddraw;
11572 IDirect3D3 *d3d;
11573 ULONG refcount;
11574 D3DCOLOR color;
11575 HWND window;
11576 HRESULT hr;
11578 static D3DMATRIX mat =
11580 1.0f, 0.0f, 0.0f, 0.0f,
11581 0.0f, 1.0f, 0.0f, 0.0f,
11582 0.0f, 0.0f, 1.0f, 0.0f,
11583 0.0f, 0.0f, 0.0f, 1.0f,
11585 static struct
11587 struct vec3 position;
11588 DWORD diffuse;
11590 green_quad[] =
11592 {{-1.0f, -1.0f, 0.1f}, 0x7f00ff00},
11593 {{-1.0f, 1.0f, 0.1f}, 0x7f00ff00},
11594 {{ 1.0f, -1.0f, 0.1f}, 0x7f00ff00},
11595 {{ 1.0f, 1.0f, 0.1f}, 0x7f00ff00},
11597 static struct
11599 struct vec3 position;
11600 DWORD diffuse;
11602 red_quad[] =
11604 {{-1.0f, -1.0f, 0.1f}, 0xccff0000},
11605 {{-1.0f, 1.0f, 0.1f}, 0xccff0000},
11606 {{ 1.0f, -1.0f, 0.1f}, 0xccff0000},
11607 {{ 1.0f, 1.0f, 0.1f}, 0xccff0000},
11610 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
11611 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11612 if (!(device = create_device(window, DDSCL_NORMAL)))
11614 skip("Failed to create a 3D device.\n");
11615 DestroyWindow(window);
11616 return;
11619 memset(&hal_desc, 0, sizeof(hal_desc));
11620 hal_desc.dwSize = sizeof(hal_desc);
11621 memset(&hel_desc, 0, sizeof(hel_desc));
11622 hel_desc.dwSize = sizeof(hel_desc);
11623 hr = IDirect3DDevice3_GetCaps(device, &hal_desc, &hel_desc);
11624 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
11625 trace("HAL line edge antialiasing support: %#x.\n",
11626 hal_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
11627 trace("HAL triangle edge antialiasing support: %#x.\n",
11628 hal_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
11629 trace("HEL line edge antialiasing support: %#x.\n",
11630 hel_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
11631 trace("HEL triangle edge antialiasing support: %#x.\n",
11632 hel_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
11634 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
11635 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
11636 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
11637 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
11638 IDirect3D3_Release(d3d);
11640 memset(&surface_desc, 0, sizeof(surface_desc));
11641 surface_desc.dwSize = sizeof(surface_desc);
11642 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
11643 surface_desc.dwWidth = 640;
11644 surface_desc.dwHeight = 480;
11645 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
11646 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
11647 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
11648 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
11649 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
11650 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
11651 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
11652 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
11653 ok(hr == D3D_OK, "Creating the offscreen render target failed, hr %#x.\n", hr);
11655 ds = get_depth_stencil(device);
11656 hr = IDirectDrawSurface_AddAttachedSurface(offscreen, ds);
11657 todo_wine ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
11658 IDirectDrawSurface_Release(ds);
11660 hr = IDirect3DDevice3_SetRenderTarget(device, offscreen, 0);
11661 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
11663 viewport = create_viewport(device, 0, 0, 640, 480);
11664 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
11665 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
11667 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
11668 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
11669 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
11670 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
11671 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
11672 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
11673 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
11674 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
11675 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
11676 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
11677 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
11678 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
11679 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
11680 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
11681 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
11682 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
11683 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
11684 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
11686 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
11687 ok(SUCCEEDED(hr), "Failed to enable blending, hr %#x.\n", hr);
11688 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
11689 ok(SUCCEEDED(hr), "Failed to set src blend, hr %#x.\n", hr);
11690 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
11691 ok(SUCCEEDED(hr), "Failed to set dest blend, hr %#x.\n", hr);
11693 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
11694 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11695 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
11696 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11697 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
11698 ok(SUCCEEDED(hr), "Failed to set alpha op, hr %#x.\n", hr);
11699 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
11700 ok(SUCCEEDED(hr), "Failed to set alpha arg, hr %#x.\n", hr);
11702 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
11703 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
11704 hr = IDirect3DDevice3_BeginScene(device);
11705 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11706 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
11707 green_quad, 4, 0);
11708 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11709 hr = IDirect3DDevice3_EndScene(device);
11710 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11711 color = get_surface_color(offscreen, 320, 240);
11712 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
11714 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
11715 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
11716 hr = IDirect3DDevice3_BeginScene(device);
11717 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11718 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
11719 red_quad, 4, 0);
11720 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11721 hr = IDirect3DDevice3_EndScene(device);
11722 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11723 color = get_surface_color(offscreen, 320, 240);
11724 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
11726 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
11727 ok(SUCCEEDED(hr), "Failed to disable blending, hr %#x.\n", hr);
11729 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
11730 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
11731 hr = IDirect3DDevice3_BeginScene(device);
11732 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11733 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
11734 green_quad, 4, 0);
11735 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11736 hr = IDirect3DDevice3_EndScene(device);
11737 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11738 color = get_surface_color(offscreen, 320, 240);
11739 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
11741 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
11742 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
11743 hr = IDirect3DDevice3_BeginScene(device);
11744 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11745 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
11746 red_quad, 4, 0);
11747 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11748 hr = IDirect3DDevice3_EndScene(device);
11749 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11750 color = get_surface_color(offscreen, 320, 240);
11751 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
11753 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_EDGEANTIALIAS, TRUE);
11754 ok(SUCCEEDED(hr), "Failed to enable edge antialiasing, hr %#x.\n", hr);
11756 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
11757 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
11758 hr = IDirect3DDevice3_BeginScene(device);
11759 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11760 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
11761 green_quad, 4, 0);
11762 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11763 hr = IDirect3DDevice3_EndScene(device);
11764 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11765 color = get_surface_color(offscreen, 320, 240);
11766 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
11768 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
11769 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
11770 hr = IDirect3DDevice3_BeginScene(device);
11771 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11772 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
11773 red_quad, 4, 0);
11774 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11775 hr = IDirect3DDevice3_EndScene(device);
11776 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11777 color = get_surface_color(offscreen, 320, 240);
11778 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
11780 IDirectDrawSurface4_Release(offscreen);
11781 IDirectDraw3_Release(ddraw);
11782 destroy_viewport(device, viewport);
11783 refcount = IDirect3DDevice3_Release(device);
11784 ok(!refcount, "Device has %u references left.\n", refcount);
11785 DestroyWindow(window);
11788 START_TEST(ddraw4)
11790 IDirectDraw4 *ddraw;
11791 DEVMODEW current_mode;
11792 HMODULE dwmapi;
11794 if (!(ddraw = create_ddraw()))
11796 skip("Failed to create a ddraw object, skipping tests.\n");
11797 return;
11799 IDirectDraw4_Release(ddraw);
11801 memset(&current_mode, 0, sizeof(current_mode));
11802 current_mode.dmSize = sizeof(current_mode);
11803 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
11804 registry_mode.dmSize = sizeof(registry_mode);
11805 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
11806 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
11807 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
11809 skip("Current mode does not match registry mode, skipping test.\n");
11810 return;
11813 if ((dwmapi = LoadLibraryA("dwmapi.dll")))
11814 pDwmIsCompositionEnabled = (void *)GetProcAddress(dwmapi, "DwmIsCompositionEnabled");
11816 test_process_vertices();
11817 test_coop_level_create_device_window();
11818 test_clipper_blt();
11819 test_coop_level_d3d_state();
11820 test_surface_interface_mismatch();
11821 test_coop_level_threaded();
11822 test_depth_blit();
11823 test_texture_load_ckey();
11824 test_viewport();
11825 test_zenable();
11826 test_ck_rgba();
11827 test_ck_default();
11828 test_ck_complex();
11829 test_surface_qi();
11830 test_device_qi();
11831 test_wndproc();
11832 test_window_style();
11833 test_redundant_mode_set();
11834 test_coop_level_mode_set();
11835 test_coop_level_mode_set_multi();
11836 test_initialize();
11837 test_coop_level_surf_create();
11838 test_vb_discard();
11839 test_coop_level_multi_window();
11840 test_draw_strided();
11841 test_lighting();
11842 test_specular_lighting();
11843 test_clear_rect_count();
11844 test_coop_level_versions();
11845 test_lighting_interface_versions();
11846 test_coop_level_activateapp();
11847 test_texturemanage();
11848 test_block_formats_creation();
11849 test_unsupported_formats();
11850 test_rt_caps();
11851 test_primary_caps();
11852 test_surface_lock();
11853 test_surface_discard();
11854 test_flip();
11855 test_set_surface_desc();
11856 test_user_memory_getdc();
11857 test_sysmem_overlay();
11858 test_primary_palette();
11859 test_surface_attachment();
11860 test_private_data();
11861 test_pixel_format();
11862 test_create_surface_pitch();
11863 test_mipmap();
11864 test_palette_complex();
11865 test_p8_blit();
11866 test_material();
11867 test_palette_gdi();
11868 test_palette_alpha();
11869 test_vb_writeonly();
11870 test_lost_device();
11871 test_surface_desc_lock();
11872 test_signed_formats();
11873 test_color_fill();
11874 test_texcoordindex();
11875 test_colorkey_precision();
11876 test_range_colorkey();
11877 test_shademode();
11878 test_lockrect_invalid();
11879 test_yv12_overlay();
11880 test_offscreen_overlay();
11881 test_overlay_rect();
11882 test_blt();
11883 test_color_clamping();
11884 test_getdc();
11885 test_draw_primitive();
11886 test_edge_antialiasing_blending();