ddraw/tests: Fix double assigment to the same lvalue (coccinellery).
[wine.git] / dlls / ddraw / tests / ddraw1.c
blobc682466026a91cca56084980bd31bd997d012f7e
1 /*
2 * Copyright 2005 Antoine Chavasse (a.chavasse@gmail.com)
3 * Copyright 2008, 2011, 2012-2013 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 "d3d.h"
26 static BOOL is_ddraw64 = sizeof(DWORD) != sizeof(DWORD *);
27 static DEVMODEW registry_mode;
29 static HRESULT (WINAPI *pDwmIsCompositionEnabled)(BOOL *);
31 #ifndef ARRAY_SIZE
32 #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
33 #endif
35 struct vec4
37 float x, y, z, w;
40 struct create_window_thread_param
42 HWND window;
43 HANDLE window_created;
44 HANDLE destroy_window;
45 HANDLE thread;
48 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
50 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
51 c1 >>= 8; c2 >>= 8;
52 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
53 c1 >>= 8; c2 >>= 8;
54 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
55 c1 >>= 8; c2 >>= 8;
56 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
57 return TRUE;
60 static BOOL compare_float(float f, float g, unsigned int ulps)
62 int x = *(int *)&f;
63 int y = *(int *)&g;
65 if (x < 0)
66 x = INT_MIN - x;
67 if (y < 0)
68 y = INT_MIN - y;
70 if (abs(x - y) > ulps)
71 return FALSE;
73 return TRUE;
76 static BOOL compare_vec4(const struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
78 return compare_float(vec->x, x, ulps)
79 && compare_float(vec->y, y, ulps)
80 && compare_float(vec->z, z, ulps)
81 && compare_float(vec->w, w, ulps);
84 static BOOL ddraw_is_warp(IDirectDraw *ddraw)
86 IDirectDraw4 *ddraw4;
87 DDDEVICEIDENTIFIER identifier;
88 HRESULT hr;
90 if (!strcmp(winetest_platform, "wine"))
91 return FALSE;
93 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw4, (void **)&ddraw4);
94 ok(SUCCEEDED(hr), "Failed to get IDirectDraw4 interface, hr %#x.\n", hr);
95 hr = IDirectDraw4_GetDeviceIdentifier(ddraw4, &identifier, 0);
96 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#x.\n", hr);
97 IDirectDraw4_Release(ddraw4);
99 return !!strstr(identifier.szDriver, "warp");
102 static BOOL ddraw_is_nvidia(IDirectDraw *ddraw)
104 IDirectDraw4 *ddraw4;
105 DDDEVICEIDENTIFIER identifier;
106 HRESULT hr;
108 if (!strcmp(winetest_platform, "wine"))
109 return FALSE;
111 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw4, (void **)&ddraw4);
112 ok(SUCCEEDED(hr), "Failed to get IDirectDraw4 interface, hr %#x.\n", hr);
113 hr = IDirectDraw4_GetDeviceIdentifier(ddraw4, &identifier, 0);
114 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#x.\n", hr);
115 IDirectDraw4_Release(ddraw4);
117 return identifier.dwVendorId == 0x10de;
120 static BOOL ddraw_is_intel(IDirectDraw *ddraw)
122 IDirectDraw4 *ddraw4;
123 DDDEVICEIDENTIFIER identifier;
124 HRESULT hr;
126 if (!strcmp(winetest_platform, "wine"))
127 return FALSE;
129 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw4, (void **)&ddraw4);
130 ok(SUCCEEDED(hr), "Failed to get IDirectDraw4 interface, hr %#x.\n", hr);
131 hr = IDirectDraw4_GetDeviceIdentifier(ddraw4, &identifier, 0);
132 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#x.\n", hr);
133 IDirectDraw4_Release(ddraw4);
135 return identifier.dwVendorId == 0x8086;
138 static IDirectDrawSurface *create_overlay(IDirectDraw *ddraw,
139 unsigned int width, unsigned int height, DWORD format)
141 IDirectDrawSurface *surface;
142 DDSURFACEDESC desc;
144 memset(&desc, 0, sizeof(desc));
145 desc.dwSize = sizeof(desc);
146 desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
147 desc.dwWidth = width;
148 desc.dwHeight = height;
149 desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
150 desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
151 desc.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
152 desc.ddpfPixelFormat.dwFourCC = format;
154 if (FAILED(IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL)))
155 return NULL;
156 return surface;
159 static DWORD WINAPI create_window_thread_proc(void *param)
161 struct create_window_thread_param *p = param;
162 DWORD res;
163 BOOL ret;
165 p->window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
166 0, 0, 640, 480, 0, 0, 0, 0);
167 ret = SetEvent(p->window_created);
168 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
170 for (;;)
172 MSG msg;
174 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
175 DispatchMessageA(&msg);
176 res = WaitForSingleObject(p->destroy_window, 100);
177 if (res == WAIT_OBJECT_0)
178 break;
179 if (res != WAIT_TIMEOUT)
181 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
182 break;
186 DestroyWindow(p->window);
188 return 0;
191 static void create_window_thread(struct create_window_thread_param *p)
193 DWORD res, tid;
195 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
196 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
197 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
198 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
199 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
200 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
201 res = WaitForSingleObject(p->window_created, INFINITE);
202 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
205 static void destroy_window_thread(struct create_window_thread_param *p)
207 SetEvent(p->destroy_window);
208 WaitForSingleObject(p->thread, INFINITE);
209 CloseHandle(p->destroy_window);
210 CloseHandle(p->window_created);
211 CloseHandle(p->thread);
214 static HRESULT set_display_mode(IDirectDraw *ddraw, DWORD width, DWORD height)
216 if (SUCCEEDED(IDirectDraw_SetDisplayMode(ddraw, width, height, 32)))
217 return DD_OK;
218 return IDirectDraw_SetDisplayMode(ddraw, width, height, 24);
221 static D3DCOLOR get_surface_color(IDirectDrawSurface *surface, UINT x, UINT y)
223 RECT rect = {x, y, x + 1, y + 1};
224 DDSURFACEDESC surface_desc;
225 D3DCOLOR color;
226 HRESULT hr;
228 memset(&surface_desc, 0, sizeof(surface_desc));
229 surface_desc.dwSize = sizeof(surface_desc);
231 hr = IDirectDrawSurface_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
232 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
233 if (FAILED(hr))
234 return 0xdeadbeef;
236 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
238 hr = IDirectDrawSurface_Unlock(surface, NULL);
239 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
241 return color;
244 static void emit_process_vertices(void **ptr, DWORD flags, WORD base_idx, DWORD vertex_count)
246 D3DINSTRUCTION *inst = *ptr;
247 D3DPROCESSVERTICES *pv = (D3DPROCESSVERTICES *)(inst + 1);
249 inst->bOpcode = D3DOP_PROCESSVERTICES;
250 inst->bSize = sizeof(*pv);
251 inst->wCount = 1;
253 pv->dwFlags = flags;
254 pv->wStart = base_idx;
255 pv->wDest = 0;
256 pv->dwCount = vertex_count;
257 pv->dwReserved = 0;
259 *ptr = pv + 1;
262 static void emit_set_ts(void **ptr, D3DTRANSFORMSTATETYPE state, DWORD value)
264 D3DINSTRUCTION *inst = *ptr;
265 D3DSTATE *ts = (D3DSTATE *)(inst + 1);
267 inst->bOpcode = D3DOP_STATETRANSFORM;
268 inst->bSize = sizeof(*ts);
269 inst->wCount = 1;
271 U1(*ts).dtstTransformStateType = state;
272 U2(*ts).dwArg[0] = value;
274 *ptr = ts + 1;
277 static void emit_set_ls(void **ptr, D3DLIGHTSTATETYPE state, DWORD value)
279 D3DINSTRUCTION *inst = *ptr;
280 D3DSTATE *ls = (D3DSTATE *)(inst + 1);
282 inst->bOpcode = D3DOP_STATELIGHT;
283 inst->bSize = sizeof(*ls);
284 inst->wCount = 1;
286 U1(*ls).dlstLightStateType = state;
287 U2(*ls).dwArg[0] = value;
289 *ptr = ls + 1;
292 static void emit_set_rs(void **ptr, D3DRENDERSTATETYPE state, DWORD value)
294 D3DINSTRUCTION *inst = *ptr;
295 D3DSTATE *rs = (D3DSTATE *)(inst + 1);
297 inst->bOpcode = D3DOP_STATERENDER;
298 inst->bSize = sizeof(*rs);
299 inst->wCount = 1;
301 U1(*rs).drstRenderStateType = state;
302 U2(*rs).dwArg[0] = value;
304 *ptr = rs + 1;
307 static void emit_tquad(void **ptr, WORD base_idx)
309 D3DINSTRUCTION *inst = *ptr;
310 D3DTRIANGLE *tri = (D3DTRIANGLE *)(inst + 1);
312 inst->bOpcode = D3DOP_TRIANGLE;
313 inst->bSize = sizeof(*tri);
314 inst->wCount = 2;
316 U1(*tri).v1 = base_idx;
317 U2(*tri).v2 = base_idx + 1;
318 U3(*tri).v3 = base_idx + 2;
319 tri->wFlags = D3DTRIFLAG_START;
320 ++tri;
322 U1(*tri).v1 = base_idx + 2;
323 U2(*tri).v2 = base_idx + 1;
324 U3(*tri).v3 = base_idx + 3;
325 tri->wFlags = D3DTRIFLAG_ODD;
326 ++tri;
328 *ptr = tri;
331 static void emit_tquad_tlist(void **ptr, WORD base_idx)
333 D3DINSTRUCTION *inst = *ptr;
334 D3DTRIANGLE *tri = (D3DTRIANGLE *)(inst + 1);
336 inst->bOpcode = D3DOP_TRIANGLE;
337 inst->bSize = sizeof(*tri);
338 inst->wCount = 2;
340 U1(*tri).v1 = base_idx;
341 U2(*tri).v2 = base_idx + 1;
342 U3(*tri).v3 = base_idx + 2;
343 tri->wFlags = D3DTRIFLAG_START;
344 ++tri;
346 U1(*tri).v1 = base_idx + 2;
347 U2(*tri).v2 = base_idx + 3;
348 U3(*tri).v3 = base_idx;
349 tri->wFlags = D3DTRIFLAG_START;
350 ++tri;
352 *ptr = tri;
355 static void emit_texture_load(void **ptr, D3DTEXTUREHANDLE dst_texture,
356 D3DTEXTUREHANDLE src_texture)
358 D3DINSTRUCTION *instruction = *ptr;
359 D3DTEXTURELOAD *texture_load = (D3DTEXTURELOAD *)(instruction + 1);
361 instruction->bOpcode = D3DOP_TEXTURELOAD;
362 instruction->bSize = sizeof(*texture_load);
363 instruction->wCount = 1;
365 texture_load->hDestTexture = dst_texture;
366 texture_load->hSrcTexture = src_texture;
367 ++texture_load;
369 *ptr = texture_load;
372 static void emit_end(void **ptr)
374 D3DINSTRUCTION *inst = *ptr;
376 inst->bOpcode = D3DOP_EXIT;
377 inst->bSize = 0;
378 inst->wCount = 0;
380 *ptr = inst + 1;
383 static void set_execute_data(IDirect3DExecuteBuffer *execute_buffer, UINT vertex_count, UINT offset, UINT len)
385 D3DEXECUTEDATA exec_data;
386 HRESULT hr;
388 memset(&exec_data, 0, sizeof(exec_data));
389 exec_data.dwSize = sizeof(exec_data);
390 exec_data.dwVertexCount = vertex_count;
391 exec_data.dwInstructionOffset = offset;
392 exec_data.dwInstructionLength = len;
393 hr = IDirect3DExecuteBuffer_SetExecuteData(execute_buffer, &exec_data);
394 ok(SUCCEEDED(hr), "Failed to set execute data, hr %#x.\n", hr);
397 static DWORD get_device_z_depth(IDirect3DDevice *device)
399 DDSCAPS caps = {DDSCAPS_ZBUFFER};
400 IDirectDrawSurface *ds, *rt;
401 DDSURFACEDESC desc;
402 HRESULT hr;
404 if (FAILED(IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt)))
405 return 0;
407 hr = IDirectDrawSurface_GetAttachedSurface(rt, &caps, &ds);
408 IDirectDrawSurface_Release(rt);
409 if (FAILED(hr))
410 return 0;
412 desc.dwSize = sizeof(desc);
413 hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
414 IDirectDrawSurface_Release(ds);
415 if (FAILED(hr))
416 return 0;
418 return U2(desc).dwZBufferBitDepth;
421 static IDirectDraw *create_ddraw(void)
423 IDirectDraw *ddraw;
425 if (FAILED(DirectDrawCreate(NULL, &ddraw, NULL)))
426 return NULL;
428 return ddraw;
431 static IDirect3DDevice *create_device(IDirectDraw *ddraw, HWND window, DWORD coop_level)
433 static const DWORD z_depths[] = {32, 24, 16};
434 IDirectDrawSurface *surface, *ds;
435 IDirect3DDevice *device = NULL;
436 DDSURFACEDESC surface_desc;
437 unsigned int i;
438 HRESULT hr;
440 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, coop_level);
441 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
443 memset(&surface_desc, 0, sizeof(surface_desc));
444 surface_desc.dwSize = sizeof(surface_desc);
445 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
446 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
447 surface_desc.dwWidth = 640;
448 surface_desc.dwHeight = 480;
450 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
451 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
453 if (coop_level & DDSCL_NORMAL)
455 IDirectDrawClipper *clipper;
457 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
458 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
459 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
460 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
461 hr = IDirectDrawSurface_SetClipper(surface, clipper);
462 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
463 IDirectDrawClipper_Release(clipper);
466 /* We used to use EnumDevices() for this, but it seems
467 * D3DDEVICEDESC.dwDeviceZBufferBitDepth only has a very casual
468 * relationship with reality. */
469 for (i = 0; i < sizeof(z_depths) / sizeof(*z_depths); ++i)
471 memset(&surface_desc, 0, sizeof(surface_desc));
472 surface_desc.dwSize = sizeof(surface_desc);
473 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
474 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
475 U2(surface_desc).dwZBufferBitDepth = z_depths[i];
476 surface_desc.dwWidth = 640;
477 surface_desc.dwHeight = 480;
478 if (FAILED(IDirectDraw_CreateSurface(ddraw, &surface_desc, &ds, NULL)))
479 continue;
481 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
482 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
483 IDirectDrawSurface_Release(ds);
484 if (FAILED(hr))
485 continue;
487 if (SUCCEEDED(IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device)))
488 break;
490 IDirectDrawSurface_DeleteAttachedSurface(surface, 0, ds);
493 IDirectDrawSurface_Release(surface);
494 return device;
497 static IDirect3DViewport *create_viewport(IDirect3DDevice *device, UINT x, UINT y, UINT w, UINT h)
499 IDirect3DViewport *viewport;
500 D3DVIEWPORT vp;
501 IDirect3D *d3d;
502 HRESULT hr;
504 hr = IDirect3DDevice_GetDirect3D(device, &d3d);
505 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
506 hr = IDirect3D_CreateViewport(d3d, &viewport, NULL);
507 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
508 hr = IDirect3DDevice_AddViewport(device, viewport);
509 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
510 memset(&vp, 0, sizeof(vp));
511 vp.dwSize = sizeof(vp);
512 vp.dwX = x;
513 vp.dwY = y;
514 vp.dwWidth = w;
515 vp.dwHeight = h;
516 vp.dvScaleX = (float)w / 2.0f;
517 vp.dvScaleY = (float)h / 2.0f;
518 vp.dvMaxX = 1.0f;
519 vp.dvMaxY = 1.0f;
520 vp.dvMinZ = 0.0f;
521 vp.dvMaxZ = 1.0f;
522 hr = IDirect3DViewport_SetViewport(viewport, &vp);
523 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
524 IDirect3D_Release(d3d);
526 return viewport;
529 static void viewport_set_background(IDirect3DDevice *device, IDirect3DViewport *viewport,
530 IDirect3DMaterial *material)
532 D3DMATERIALHANDLE material_handle;
533 HRESULT hr;
535 hr = IDirect3DMaterial2_GetHandle(material, device, &material_handle);
536 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
537 hr = IDirect3DViewport2_SetBackground(viewport, material_handle);
538 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
541 static void destroy_viewport(IDirect3DDevice *device, IDirect3DViewport *viewport)
543 HRESULT hr;
545 hr = IDirect3DDevice_DeleteViewport(device, viewport);
546 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
547 IDirect3DViewport_Release(viewport);
550 static IDirect3DMaterial *create_material(IDirect3DDevice *device, D3DMATERIAL *mat)
552 IDirect3DMaterial *material;
553 IDirect3D *d3d;
554 HRESULT hr;
556 hr = IDirect3DDevice_GetDirect3D(device, &d3d);
557 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
558 hr = IDirect3D_CreateMaterial(d3d, &material, NULL);
559 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
560 hr = IDirect3DMaterial_SetMaterial(material, mat);
561 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
562 IDirect3D_Release(d3d);
564 return material;
567 static IDirect3DMaterial *create_diffuse_material(IDirect3DDevice *device, float r, float g, float b, float a)
569 D3DMATERIAL mat;
571 memset(&mat, 0, sizeof(mat));
572 mat.dwSize = sizeof(mat);
573 U1(U(mat).diffuse).r = r;
574 U2(U(mat).diffuse).g = g;
575 U3(U(mat).diffuse).b = b;
576 U4(U(mat).diffuse).a = a;
578 return create_material(device, &mat);
581 static IDirect3DMaterial *create_emissive_material(IDirect3DDevice *device, float r, float g, float b, float a)
583 D3DMATERIAL mat;
585 memset(&mat, 0, sizeof(mat));
586 mat.dwSize = sizeof(mat);
587 U1(U3(mat).emissive).r = r;
588 U2(U3(mat).emissive).g = g;
589 U3(U3(mat).emissive).b = b;
590 U4(U3(mat).emissive).a = a;
592 return create_material(device, &mat);
595 static void destroy_material(IDirect3DMaterial *material)
597 IDirect3DMaterial_Release(material);
600 struct message
602 UINT message;
603 BOOL check_wparam;
604 WPARAM expect_wparam;
607 static const struct message *expect_messages;
609 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
611 if (expect_messages && message == expect_messages->message)
613 if (expect_messages->check_wparam)
614 ok (wparam == expect_messages->expect_wparam,
615 "Got unexpected wparam %lx for message %x, expected %lx.\n",
616 wparam, message, expect_messages->expect_wparam);
618 ++expect_messages;
621 return DefWindowProcA(hwnd, message, wparam, lparam);
624 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
625 * interface. This prevents subsequent SetCooperativeLevel() calls on a
626 * different window from failing with DDERR_HWNDALREADYSET. */
627 static void fix_wndproc(HWND window, LONG_PTR proc)
629 IDirectDraw *ddraw;
630 HRESULT hr;
632 if (!(ddraw = create_ddraw()))
633 return;
635 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
636 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
637 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
638 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
639 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
641 IDirectDraw_Release(ddraw);
644 static HRESULT CALLBACK restore_callback(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
646 HRESULT hr = IDirectDrawSurface_Restore(surface);
647 ok(SUCCEEDED(hr) || hr == DDERR_IMPLICITLYCREATED, "Failed to restore surface, hr %#x.\n", hr);
648 IDirectDrawSurface_Release(surface);
650 return DDENUMRET_OK;
653 static HRESULT restore_surfaces(IDirectDraw *ddraw)
655 return IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
656 NULL, NULL, restore_callback);
659 static void test_coop_level_create_device_window(void)
661 HWND focus_window, device_window;
662 IDirectDraw *ddraw;
663 HRESULT hr;
665 focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
666 0, 0, 640, 480, 0, 0, 0, 0);
667 ddraw = create_ddraw();
668 ok(!!ddraw, "Failed to create a ddraw object.\n");
670 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
671 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
672 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
673 ok(!device_window, "Unexpected device window found.\n");
674 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
675 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
676 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
677 ok(!device_window, "Unexpected device window found.\n");
678 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
679 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
680 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
681 ok(!device_window, "Unexpected device window found.\n");
682 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
683 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
684 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
685 ok(!device_window, "Unexpected device window found.\n");
686 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
687 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
688 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
689 ok(!device_window, "Unexpected device window found.\n");
691 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
692 if (broken(hr == DDERR_INVALIDPARAMS))
694 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
695 IDirectDraw_Release(ddraw);
696 DestroyWindow(focus_window);
697 return;
700 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
701 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
702 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
703 ok(!device_window, "Unexpected device window found.\n");
704 hr = IDirectDraw_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
705 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
706 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
707 ok(!device_window, "Unexpected device window found.\n");
709 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
710 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
711 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
712 ok(!device_window, "Unexpected device window found.\n");
713 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
714 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
715 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
716 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
717 ok(!!device_window, "Device window not found.\n");
719 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
720 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
721 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
722 ok(!device_window, "Unexpected device window found.\n");
723 hr = IDirectDraw_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
724 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
725 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
726 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
727 ok(!!device_window, "Device window not found.\n");
729 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
730 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
731 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
732 ok(!device_window, "Unexpected device window found.\n");
733 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
734 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
735 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
736 ok(!device_window, "Unexpected device window found.\n");
737 hr = IDirectDraw_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
738 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
739 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
740 ok(!device_window, "Unexpected device window found.\n");
741 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
742 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
743 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
744 ok(!!device_window, "Device window not found.\n");
746 IDirectDraw_Release(ddraw);
747 DestroyWindow(focus_window);
750 static void test_clipper_blt(void)
752 IDirectDrawSurface *src_surface, *dst_surface;
753 RECT client_rect, src_rect;
754 IDirectDrawClipper *clipper;
755 DDSURFACEDESC surface_desc;
756 unsigned int i, j, x, y;
757 IDirectDraw *ddraw;
758 RGNDATA *rgn_data;
759 D3DCOLOR color;
760 ULONG refcount;
761 HRGN r1, r2;
762 HWND window;
763 DDBLTFX fx;
764 HRESULT hr;
765 DWORD *ptr;
766 DWORD ret;
768 static const DWORD src_data[] =
770 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
771 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
772 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
774 static const D3DCOLOR expected1[] =
776 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
777 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
778 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
779 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
781 /* Nvidia on Windows seems to have an off-by-one error
782 * when processing source rectangles. Our left = 1 and
783 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
784 * read as well, but only for the edge pixels on the
785 * output image. The bug happens on the y axis as well,
786 * but we only read one row there, and all source rows
787 * contain the same data. This bug is not dependent on
788 * the presence of a clipper. */
789 static const D3DCOLOR expected1_broken[] =
791 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
792 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
793 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
794 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
796 static const D3DCOLOR expected2[] =
798 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
799 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
800 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
801 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
804 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
805 10, 10, 640, 480, 0, 0, 0, 0);
806 ShowWindow(window, SW_SHOW);
807 ddraw = create_ddraw();
808 ok(!!ddraw, "Failed to create a ddraw object.\n");
810 ret = GetClientRect(window, &client_rect);
811 ok(ret, "Failed to get client rect.\n");
812 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
813 ok(ret, "Failed to map client rect.\n");
815 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
816 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
818 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
819 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
820 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
821 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
822 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
823 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
824 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
825 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
826 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
827 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
828 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
829 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
830 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
831 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
832 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
833 "Got unexpected bounding rect %s, expected %s.\n",
834 wine_dbgstr_rect(&rgn_data->rdh.rcBound), wine_dbgstr_rect(&client_rect));
835 HeapFree(GetProcessHeap(), 0, rgn_data);
837 r1 = CreateRectRgn(0, 0, 320, 240);
838 ok(!!r1, "Failed to create region.\n");
839 r2 = CreateRectRgn(320, 240, 640, 480);
840 ok(!!r2, "Failed to create region.\n");
841 CombineRgn(r1, r1, r2, RGN_OR);
842 ret = GetRegionData(r1, 0, NULL);
843 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
844 ret = GetRegionData(r1, ret, rgn_data);
845 ok(!!ret, "Failed to get region data.\n");
847 DeleteObject(r2);
848 DeleteObject(r1);
850 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
851 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
852 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
853 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
854 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
855 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
857 HeapFree(GetProcessHeap(), 0, rgn_data);
859 memset(&surface_desc, 0, sizeof(surface_desc));
860 surface_desc.dwSize = sizeof(surface_desc);
861 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
862 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
863 surface_desc.dwWidth = 640;
864 surface_desc.dwHeight = 480;
865 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
866 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
867 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
868 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
869 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
870 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
872 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
873 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
874 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
875 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
877 memset(&fx, 0, sizeof(fx));
878 fx.dwSize = sizeof(fx);
879 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
880 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
881 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
882 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
884 hr = IDirectDrawSurface_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
885 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
886 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
887 ptr = surface_desc.lpSurface;
888 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
889 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
890 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
891 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
892 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
894 hr = IDirectDrawSurface_SetClipper(dst_surface, clipper);
895 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
897 SetRect(&src_rect, 1, 1, 5, 2);
898 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
899 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
900 for (i = 0; i < 4; ++i)
902 for (j = 0; j < 4; ++j)
904 x = 80 * ((2 * j) + 1);
905 y = 60 * ((2 * i) + 1);
906 color = get_surface_color(dst_surface, x, y);
907 ok(compare_color(color, expected1[i * 4 + j], 1)
908 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
909 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
913 U5(fx).dwFillColor = 0xff0000ff;
914 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
915 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
916 for (i = 0; i < 4; ++i)
918 for (j = 0; j < 4; ++j)
920 x = 80 * ((2 * j) + 1);
921 y = 60 * ((2 * i) + 1);
922 color = get_surface_color(dst_surface, x, y);
923 ok(compare_color(color, expected2[i * 4 + j], 1),
924 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
928 hr = IDirectDrawSurface_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
929 ok(hr == DDERR_BLTFASTCANTCLIP || broken(hr == E_NOTIMPL /* NT4 */), "Got unexpected hr %#x.\n", hr);
931 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
932 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
933 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
934 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
935 DestroyWindow(window);
936 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
937 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
938 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
939 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
940 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
941 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
942 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
943 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
944 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
945 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
946 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
947 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
949 IDirectDrawSurface_Release(dst_surface);
950 IDirectDrawSurface_Release(src_surface);
951 refcount = IDirectDrawClipper_Release(clipper);
952 ok(!refcount, "Clipper has %u references left.\n", refcount);
953 IDirectDraw_Release(ddraw);
956 static void test_coop_level_d3d_state(void)
958 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
959 IDirectDrawSurface *rt, *surface;
960 IDirect3DMaterial *background;
961 IDirect3DViewport *viewport;
962 IDirect3DDevice *device;
963 D3DMATERIAL material;
964 IDirectDraw *ddraw;
965 D3DCOLOR color;
966 HWND window;
967 HRESULT hr;
969 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
970 0, 0, 640, 480, 0, 0, 0, 0);
971 ddraw = create_ddraw();
972 ok(!!ddraw, "Failed to create a ddraw object.\n");
973 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
975 skip("Failed to create a 3D device, skipping test.\n");
976 IDirectDraw_Release(ddraw);
977 DestroyWindow(window);
978 return;
981 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
982 viewport = create_viewport(device, 0, 0, 640, 480);
983 viewport_set_background(device, viewport, background);
985 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
986 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
987 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
988 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
989 color = get_surface_color(rt, 320, 240);
990 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
992 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
993 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
994 hr = IDirectDrawSurface_IsLost(rt);
995 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
996 hr = restore_surfaces(ddraw);
997 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
999 memset(&material, 0, sizeof(material));
1000 material.dwSize = sizeof(material);
1001 U1(U(material).diffuse).r = 0.0f;
1002 U2(U(material).diffuse).g = 1.0f;
1003 U3(U(material).diffuse).b = 0.0f;
1004 U4(U(material).diffuse).a = 1.0f;
1005 hr = IDirect3DMaterial_SetMaterial(background, &material);
1006 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
1008 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&surface);
1009 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1010 ok(surface == rt, "Got unexpected surface %p.\n", surface);
1011 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1012 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1013 color = get_surface_color(rt, 320, 240);
1014 ok(compare_color(color, 0x0000ff00, 1) || broken(compare_color(color, 0x00000000, 1)),
1015 "Got unexpected color 0x%08x.\n", color);
1017 destroy_viewport(device, viewport);
1018 destroy_material(background);
1019 IDirectDrawSurface_Release(surface);
1020 IDirectDrawSurface_Release(rt);
1021 IDirect3DDevice_Release(device);
1022 IDirectDraw_Release(ddraw);
1023 DestroyWindow(window);
1026 static void test_surface_interface_mismatch(void)
1028 IDirectDraw *ddraw = NULL;
1029 IDirectDrawSurface *surface = NULL, *ds;
1030 IDirectDrawSurface3 *surface3 = NULL;
1031 IDirect3DDevice *device = NULL;
1032 IDirect3DViewport *viewport = NULL;
1033 IDirect3DMaterial *background = NULL;
1034 DDSURFACEDESC surface_desc;
1035 DWORD z_depth = 0;
1036 ULONG refcount;
1037 HRESULT hr;
1038 D3DCOLOR color;
1039 HWND window;
1040 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1042 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1043 0, 0, 640, 480, 0, 0, 0, 0);
1044 ddraw = create_ddraw();
1045 ok(!!ddraw, "Failed to create a ddraw object.\n");
1046 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1048 skip("Failed to create a 3D device, skipping test.\n");
1049 IDirectDraw_Release(ddraw);
1050 DestroyWindow(window);
1051 return;
1053 z_depth = get_device_z_depth(device);
1054 ok(!!z_depth, "Failed to get device z depth.\n");
1055 IDirect3DDevice_Release(device);
1056 device = NULL;
1058 memset(&surface_desc, 0, sizeof(surface_desc));
1059 surface_desc.dwSize = sizeof(surface_desc);
1060 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1061 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1062 surface_desc.dwWidth = 640;
1063 surface_desc.dwHeight = 480;
1065 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1066 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1068 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
1069 if (FAILED(hr))
1071 skip("Failed to get the IDirectDrawSurface3 interface, skipping test.\n");
1072 goto cleanup;
1075 memset(&surface_desc, 0, sizeof(surface_desc));
1076 surface_desc.dwSize = sizeof(surface_desc);
1077 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
1078 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1079 U2(surface_desc).dwZBufferBitDepth = z_depth;
1080 surface_desc.dwWidth = 640;
1081 surface_desc.dwHeight = 480;
1082 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &ds, NULL);
1083 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
1084 if (FAILED(hr))
1085 goto cleanup;
1087 /* Using a different surface interface version still works */
1088 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
1089 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
1090 refcount = IDirectDrawSurface_Release(ds);
1091 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
1092 if (FAILED(hr))
1093 goto cleanup;
1095 /* Here too */
1096 hr = IDirectDrawSurface3_QueryInterface(surface3, &IID_IDirect3DHALDevice, (void **)&device);
1097 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
1098 if (FAILED(hr))
1099 goto cleanup;
1101 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1102 viewport = create_viewport(device, 0, 0, 640, 480);
1103 viewport_set_background(device, viewport, background);
1105 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1106 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1107 color = get_surface_color(surface, 320, 240);
1108 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1110 cleanup:
1111 if (viewport)
1112 destroy_viewport(device, viewport);
1113 if (background)
1114 destroy_material(background);
1115 if (surface3) IDirectDrawSurface3_Release(surface3);
1116 if (surface) IDirectDrawSurface_Release(surface);
1117 if (device) IDirect3DDevice_Release(device);
1118 if (ddraw) IDirectDraw_Release(ddraw);
1119 DestroyWindow(window);
1122 static void test_coop_level_threaded(void)
1124 struct create_window_thread_param p;
1125 IDirectDraw *ddraw;
1126 HRESULT hr;
1128 ddraw = create_ddraw();
1129 ok(!!ddraw, "Failed to create a ddraw object.\n");
1130 create_window_thread(&p);
1132 hr = IDirectDraw_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1133 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1135 IDirectDraw_Release(ddraw);
1136 destroy_window_thread(&p);
1139 static ULONG get_refcount(IUnknown *test_iface)
1141 IUnknown_AddRef(test_iface);
1142 return IUnknown_Release(test_iface);
1145 static void test_viewport(void)
1147 IDirectDraw *ddraw;
1148 IDirect3D *d3d;
1149 HRESULT hr;
1150 ULONG ref;
1151 IDirect3DViewport *viewport, *another_vp;
1152 IDirect3DViewport2 *viewport2;
1153 IDirect3DViewport3 *viewport3;
1154 IDirectDrawGammaControl *gamma;
1155 IUnknown *unknown;
1156 IDirect3DDevice *device;
1157 HWND window;
1159 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1160 0, 0, 640, 480, 0, 0, 0, 0);
1161 ddraw = create_ddraw();
1162 ok(!!ddraw, "Failed to create a ddraw object.\n");
1163 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1165 skip("Failed to create a 3D device, skipping test.\n");
1166 IDirectDraw_Release(ddraw);
1167 DestroyWindow(window);
1168 return;
1171 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
1172 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1173 ref = get_refcount((IUnknown *) d3d);
1174 ok(ref == 2, "IDirect3D refcount is %d\n", ref);
1176 hr = IDirect3D_CreateViewport(d3d, &viewport, NULL);
1177 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1178 ref = get_refcount((IUnknown *)viewport);
1179 ok(ref == 1, "Initial IDirect3DViewport refcount is %u\n", ref);
1180 ref = get_refcount((IUnknown *)d3d);
1181 ok(ref == 2, "IDirect3D refcount is %u\n", ref);
1183 /* E_FAIL return values are returned by Winetestbot Windows NT machines. While not supporting
1184 * newer interfaces is legitimate for old ddraw versions, E_FAIL violates Microsoft's rules
1185 * for QueryInterface, hence the broken() */
1186 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1187 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirectDrawGammaControl, (void **)&gamma);
1188 ok(hr == E_NOINTERFACE || broken(hr == E_FAIL), "Got unexpected hr %#x.\n", hr);
1189 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
1190 if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
1191 /* NULL iid: Segfaults */
1193 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirect3DViewport2, (void **)&viewport2);
1194 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE || broken(hr == E_FAIL),
1195 "Failed to QI IDirect3DViewport2, hr %#x.\n", hr);
1196 if (viewport2)
1198 ref = get_refcount((IUnknown *)viewport);
1199 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1200 ref = get_refcount((IUnknown *)viewport2);
1201 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1202 IDirect3DViewport2_Release(viewport2);
1203 viewport2 = NULL;
1206 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirect3DViewport3, (void **)&viewport3);
1207 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE || broken(hr == E_FAIL),
1208 "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1209 if (viewport3)
1211 ref = get_refcount((IUnknown *)viewport);
1212 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1213 ref = get_refcount((IUnknown *)viewport3);
1214 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1215 IDirect3DViewport3_Release(viewport3);
1218 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IUnknown, (void **)&unknown);
1219 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1220 if (unknown)
1222 ref = get_refcount((IUnknown *)viewport);
1223 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1224 ref = get_refcount(unknown);
1225 ok(ref == 2, "IUnknown refcount is %u\n", ref);
1226 IUnknown_Release(unknown);
1229 /* AddViewport(NULL): Segfault */
1230 hr = IDirect3DDevice_DeleteViewport(device, NULL);
1231 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1233 hr = IDirect3D_CreateViewport(d3d, &another_vp, NULL);
1234 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1236 hr = IDirect3DDevice_AddViewport(device, viewport);
1237 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1238 ref = get_refcount((IUnknown *) viewport);
1239 ok(ref == 2, "IDirect3DViewport refcount is %d\n", ref);
1240 hr = IDirect3DDevice_AddViewport(device, another_vp);
1241 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1242 ref = get_refcount((IUnknown *) another_vp);
1243 ok(ref == 2, "IDirect3DViewport refcount is %d\n", ref);
1245 hr = IDirect3DDevice_DeleteViewport(device, another_vp);
1246 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1247 ref = get_refcount((IUnknown *) another_vp);
1248 ok(ref == 1, "IDirect3DViewport refcount is %d\n", ref);
1250 IDirect3DDevice_Release(device);
1251 ref = get_refcount((IUnknown *) viewport);
1252 ok(ref == 1, "IDirect3DViewport refcount is %d\n", ref);
1254 IDirect3DViewport_Release(another_vp);
1255 IDirect3D_Release(d3d);
1256 IDirect3DViewport_Release(viewport);
1257 DestroyWindow(window);
1258 IDirectDraw_Release(ddraw);
1261 static void test_zenable(void)
1263 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1264 static D3DTLVERTEX tquad[] =
1266 {{ 0.0f}, {480.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1267 {{ 0.0f}, { 0.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1268 {{640.0f}, {480.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1269 {{640.0f}, { 0.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1271 IDirect3DExecuteBuffer *execute_buffer;
1272 D3DEXECUTEBUFFERDESC exec_desc;
1273 IDirect3DMaterial *background;
1274 IDirect3DViewport *viewport;
1275 IDirect3DDevice *device;
1276 IDirectDrawSurface *rt;
1277 IDirectDraw *ddraw;
1278 UINT inst_length;
1279 D3DCOLOR color;
1280 HWND window;
1281 HRESULT hr;
1282 UINT x, y;
1283 UINT i, j;
1284 void *ptr;
1286 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1287 0, 0, 640, 480, 0, 0, 0, 0);
1288 ddraw = create_ddraw();
1289 ok(!!ddraw, "Failed to create a ddraw object.\n");
1290 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1292 skip("Failed to create a 3D device, skipping test.\n");
1293 IDirectDraw_Release(ddraw);
1294 DestroyWindow(window);
1295 return;
1298 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1299 viewport = create_viewport(device, 0, 0, 640, 480);
1300 viewport_set_background(device, viewport, background);
1302 memset(&exec_desc, 0, sizeof(exec_desc));
1303 exec_desc.dwSize = sizeof(exec_desc);
1304 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1305 exec_desc.dwBufferSize = 1024;
1306 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1308 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1309 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1310 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1311 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1312 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1313 ptr = ((BYTE *)exec_desc.lpData) + sizeof(tquad);
1314 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
1315 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1316 emit_tquad(&ptr, 0);
1317 emit_end(&ptr);
1318 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
1319 inst_length -= sizeof(tquad);
1320 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1321 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1323 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1324 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1325 hr = IDirect3DDevice_BeginScene(device);
1326 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1327 set_execute_data(execute_buffer, 4, sizeof(tquad), inst_length);
1328 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1329 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1330 hr = IDirect3DDevice_EndScene(device);
1331 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1333 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1334 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1335 for (i = 0; i < 4; ++i)
1337 for (j = 0; j < 4; ++j)
1339 x = 80 * ((2 * j) + 1);
1340 y = 60 * ((2 * i) + 1);
1341 color = get_surface_color(rt, x, y);
1342 ok(compare_color(color, 0x0000ff00, 1),
1343 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1346 IDirectDrawSurface_Release(rt);
1348 destroy_viewport(device, viewport);
1349 IDirect3DExecuteBuffer_Release(execute_buffer);
1350 destroy_material(background);
1351 IDirect3DDevice_Release(device);
1352 IDirectDraw_Release(ddraw);
1353 DestroyWindow(window);
1356 static void test_ck_rgba(void)
1358 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1359 static D3DTLVERTEX tquad[] =
1361 {{ 0.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1362 {{ 0.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1363 {{640.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1364 {{640.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1365 {{ 0.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1366 {{ 0.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1367 {{640.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1368 {{640.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1370 /* Supposedly there was no D3DRENDERSTATE_COLORKEYENABLE in D3D < 5.
1371 * Maybe the WARP driver on Windows 8 ignores setting it via the older
1372 * device interface but it's buggy in that the internal state is not
1373 * initialized, or possibly toggling D3DRENDERSTATE_COLORKEYENABLE /
1374 * D3DRENDERSTATE_ALPHABLENDENABLE has unintended side effects.
1375 * Checking the W8 test results it seems like test 1 fails most of the time
1376 * and test 0 fails very rarely. */
1377 static const struct
1379 D3DCOLOR fill_color;
1380 BOOL color_key;
1381 BOOL blend;
1382 D3DCOLOR result1, result1_r200, result1_warp;
1383 D3DCOLOR result2, result2_r200, result2_warp;
1385 tests[] =
1387 /* r200 on Windows doesn't check the alpha component when applying the color
1388 * key, so the key matches on every texel. */
1389 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x00ff0000, 0x0000ff00,
1390 0x000000ff, 0x000000ff, 0x0000ff00},
1391 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x00ff0000, 0x0000ff00,
1392 0x000000ff, 0x000000ff, 0x0000ff00},
1393 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1394 0x0000ff00, 0x0000ff00, 0x0000ff00},
1395 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1396 0x0000ff00, 0x0000ff00, 0x0000ff00},
1397 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00ff0000, 0x00807f00,
1398 0x00807f00, 0x000000ff, 0x00807f00},
1399 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x00ff0000, 0x0000ff00,
1400 0x0000ff00, 0x000000ff, 0x0000ff00},
1401 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00, 0x00807f00,
1402 0x00807f00, 0x00807f00, 0x00807f00},
1403 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1404 0x0000ff00, 0x0000ff00, 0x0000ff00},
1407 IDirect3DExecuteBuffer *execute_buffer;
1408 D3DTEXTUREHANDLE texture_handle;
1409 D3DEXECUTEBUFFERDESC exec_desc;
1410 IDirect3DMaterial *background;
1411 IDirectDrawSurface *surface;
1412 IDirect3DViewport *viewport;
1413 DDSURFACEDESC surface_desc;
1414 IDirect3DTexture *texture;
1415 IDirect3DDevice *device;
1416 IDirectDrawSurface *rt;
1417 IDirectDraw *ddraw;
1418 D3DCOLOR color;
1419 HWND window;
1420 DDBLTFX fx;
1421 HRESULT hr;
1422 UINT i;
1424 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1425 0, 0, 640, 480, 0, 0, 0, 0);
1426 ddraw = create_ddraw();
1427 ok(!!ddraw, "Failed to create a ddraw object.\n");
1428 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1430 skip("Failed to create a 3D device, skipping test.\n");
1431 IDirectDraw_Release(ddraw);
1432 DestroyWindow(window);
1433 return;
1436 background = create_diffuse_material(device, 1.0, 0.0f, 0.0f, 1.0f);
1437 viewport = create_viewport(device, 0, 0, 640, 480);
1438 viewport_set_background(device, viewport, background);
1440 memset(&surface_desc, 0, sizeof(surface_desc));
1441 surface_desc.dwSize = sizeof(surface_desc);
1442 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1443 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1444 surface_desc.dwWidth = 256;
1445 surface_desc.dwHeight = 256;
1446 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1447 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1448 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1449 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1450 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1451 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1452 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1453 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1454 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1455 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1456 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1457 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
1458 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1459 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
1460 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1461 IDirect3DTexture_Release(texture);
1463 memset(&exec_desc, 0, sizeof(exec_desc));
1464 exec_desc.dwSize = sizeof(exec_desc);
1465 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1466 exec_desc.dwBufferSize = 1024;
1467 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1468 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1469 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1471 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1472 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1474 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1476 UINT draw1_len, draw2_len;
1477 void *ptr;
1479 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1480 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1481 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1482 ptr = ((BYTE *)exec_desc.lpData) + sizeof(tquad);
1483 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
1484 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1485 emit_set_rs(&ptr, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1486 emit_set_rs(&ptr, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1487 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1488 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1489 emit_tquad(&ptr, 0);
1490 emit_end(&ptr);
1491 draw1_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - sizeof(tquad);
1492 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 4, 4);
1493 emit_tquad(&ptr, 0);
1494 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1495 emit_end(&ptr);
1496 draw2_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw1_len;
1497 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1498 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1500 memset(&fx, 0, sizeof(fx));
1501 fx.dwSize = sizeof(fx);
1502 U5(fx).dwFillColor = tests[i].fill_color;
1503 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1504 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1506 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
1507 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1508 hr = IDirect3DDevice_BeginScene(device);
1509 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1510 set_execute_data(execute_buffer, 8, sizeof(tquad), draw1_len);
1511 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1512 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1513 hr = IDirect3DDevice_EndScene(device);
1514 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1516 color = get_surface_color(rt, 320, 240);
1517 ok(compare_color(color, tests[i].result1, 1)
1518 || broken(compare_color(color, tests[i].result1_r200, 1))
1519 || broken(compare_color(color, tests[i].result1_warp, 1)),
1520 "Got unexpected color 0x%08x for test %u.\n", color, i);
1522 U5(fx).dwFillColor = 0xff0000ff;
1523 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1524 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1526 hr = IDirect3DDevice_BeginScene(device);
1527 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1528 set_execute_data(execute_buffer, 8, sizeof(tquad) + draw1_len, draw2_len);
1529 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1530 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1531 hr = IDirect3DDevice_EndScene(device);
1532 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1534 /* This tests that fragments that are masked out by the color key are
1535 * discarded, instead of just fully transparent. */
1536 color = get_surface_color(rt, 320, 240);
1537 ok(compare_color(color, tests[i].result2, 1)
1538 || broken(compare_color(color, tests[i].result2_r200, 1))
1539 || broken(compare_color(color, tests[i].result2_warp, 1)),
1540 "Got unexpected color 0x%08x for test %u.\n", color, i);
1543 IDirectDrawSurface_Release(rt);
1544 IDirect3DExecuteBuffer_Release(execute_buffer);
1545 IDirectDrawSurface_Release(surface);
1546 destroy_viewport(device, viewport);
1547 destroy_material(background);
1548 IDirect3DDevice_Release(device);
1549 IDirectDraw_Release(ddraw);
1550 DestroyWindow(window);
1553 static void test_ck_default(void)
1555 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1556 static D3DTLVERTEX tquad[] =
1558 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1559 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1560 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1561 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1563 IDirect3DExecuteBuffer *execute_buffer;
1564 IDirectDrawSurface *surface, *rt;
1565 D3DTEXTUREHANDLE texture_handle;
1566 D3DEXECUTEBUFFERDESC exec_desc;
1567 IDirect3DMaterial *background;
1568 UINT draw1_offset, draw1_len;
1569 UINT draw2_offset, draw2_len;
1570 UINT draw3_offset, draw3_len;
1571 UINT draw4_offset, draw4_len;
1572 IDirect3DViewport *viewport;
1573 DDSURFACEDESC surface_desc;
1574 IDirect3DTexture *texture;
1575 IDirect3DDevice *device;
1576 IDirectDraw *ddraw;
1577 D3DCOLOR color;
1578 HWND window;
1579 DDBLTFX fx;
1580 HRESULT hr;
1581 void *ptr;
1583 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1584 0, 0, 640, 480, 0, 0, 0, 0);
1585 ddraw = create_ddraw();
1586 ok(!!ddraw, "Failed to create a ddraw object.\n");
1587 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1589 skip("Failed to create a 3D device, skipping test.\n");
1590 IDirectDraw_Release(ddraw);
1591 DestroyWindow(window);
1592 return;
1595 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1596 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1598 background = create_diffuse_material(device, 0.0, 1.0f, 0.0f, 1.0f);
1599 viewport = create_viewport(device, 0, 0, 640, 480);
1600 viewport_set_background(device, viewport, background);
1602 memset(&surface_desc, 0, sizeof(surface_desc));
1603 surface_desc.dwSize = sizeof(surface_desc);
1604 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1605 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1606 surface_desc.dwWidth = 256;
1607 surface_desc.dwHeight = 256;
1608 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1609 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
1610 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1611 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1612 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1613 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1614 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1615 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1616 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1617 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1618 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
1619 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1620 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
1621 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1622 IDirect3DTexture_Release(texture);
1624 memset(&fx, 0, sizeof(fx));
1625 fx.dwSize = sizeof(fx);
1626 U5(fx).dwFillColor = 0x000000ff;
1627 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1628 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1630 memset(&exec_desc, 0, sizeof(exec_desc));
1631 exec_desc.dwSize = sizeof(exec_desc);
1632 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1633 exec_desc.dwBufferSize = 1024;
1634 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1635 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1636 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1638 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1639 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1640 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1641 ptr = (BYTE *)exec_desc.lpData + sizeof(tquad);
1642 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
1643 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1644 emit_tquad(&ptr, 0);
1645 emit_end(&ptr);
1646 draw1_offset = sizeof(tquad);
1647 draw1_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw1_offset;
1648 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
1649 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, FALSE);
1650 emit_tquad(&ptr, 0);
1651 emit_end(&ptr);
1652 draw2_offset = draw1_offset + draw1_len;
1653 draw2_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw2_offset;
1654 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
1655 emit_tquad(&ptr, 0);
1656 emit_end(&ptr);
1657 draw3_offset = draw2_offset + draw2_len;
1658 draw3_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw3_offset;
1659 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
1660 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1661 emit_tquad(&ptr, 0);
1662 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1663 emit_end(&ptr);
1664 draw4_offset = draw3_offset + draw3_len;
1665 draw4_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw4_offset;
1666 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1667 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1669 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1670 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1671 hr = IDirect3DDevice_BeginScene(device);
1672 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1673 set_execute_data(execute_buffer, 4, draw1_offset, draw1_len);
1674 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1675 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1676 hr = IDirect3DDevice_EndScene(device);
1677 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1678 color = get_surface_color(rt, 320, 240);
1679 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1681 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1682 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1683 hr = IDirect3DDevice_BeginScene(device);
1684 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1685 set_execute_data(execute_buffer, 4, draw2_offset, draw2_len);
1686 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1687 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1688 hr = IDirect3DDevice_EndScene(device);
1689 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1690 color = get_surface_color(rt, 320, 240);
1691 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1693 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1694 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1695 hr = IDirect3DDevice_BeginScene(device);
1696 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1697 set_execute_data(execute_buffer, 4, draw3_offset, draw3_len);
1698 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1699 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1700 hr = IDirect3DDevice_EndScene(device);
1701 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1702 color = get_surface_color(rt, 320, 240);
1703 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1705 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1706 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1707 hr = IDirect3DDevice_BeginScene(device);
1708 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1709 set_execute_data(execute_buffer, 4, draw4_offset, draw4_len);
1710 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1711 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1712 hr = IDirect3DDevice_EndScene(device);
1713 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1714 color = get_surface_color(rt, 320, 240);
1715 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1717 IDirect3DExecuteBuffer_Release(execute_buffer);
1718 IDirectDrawSurface_Release(surface);
1719 destroy_viewport(device, viewport);
1720 destroy_material(background);
1721 IDirectDrawSurface_Release(rt);
1722 IDirect3DDevice_Release(device);
1723 IDirectDraw_Release(ddraw);
1724 DestroyWindow(window);
1727 static void test_ck_complex(void)
1729 IDirectDrawSurface *surface, *mipmap, *tmp;
1730 DDSCAPS caps = {DDSCAPS_COMPLEX};
1731 DDSURFACEDESC surface_desc;
1732 IDirect3DDevice *device;
1733 DDCOLORKEY color_key;
1734 IDirectDraw *ddraw;
1735 unsigned int i;
1736 ULONG refcount;
1737 HWND window;
1738 HRESULT hr;
1740 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1741 0, 0, 640, 480, 0, 0, 0, 0);
1742 ddraw = create_ddraw();
1743 ok(!!ddraw, "Failed to create a ddraw object.\n");
1744 if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
1746 skip("Failed to create a 3D device, skipping test.\n");
1747 DestroyWindow(window);
1748 IDirectDraw2_Release(ddraw);
1749 return;
1751 IDirect3DDevice_Release(device);
1753 memset(&surface_desc, 0, sizeof(surface_desc));
1754 surface_desc.dwSize = sizeof(surface_desc);
1755 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1756 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1757 surface_desc.dwWidth = 128;
1758 surface_desc.dwHeight = 128;
1759 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1760 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1762 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1763 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1764 color_key.dwColorSpaceLowValue = 0x0000ff00;
1765 color_key.dwColorSpaceHighValue = 0x0000ff00;
1766 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1767 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1768 memset(&color_key, 0, sizeof(color_key));
1769 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1770 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1771 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1772 color_key.dwColorSpaceLowValue);
1773 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1774 color_key.dwColorSpaceHighValue);
1776 mipmap = surface;
1777 IDirectDrawSurface_AddRef(mipmap);
1778 for (i = 0; i < 7; ++i)
1780 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
1781 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1783 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1784 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1785 color_key.dwColorSpaceLowValue = 0x000000ff;
1786 color_key.dwColorSpaceHighValue = 0x000000ff;
1787 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1788 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x, i %u.\n", hr, i);
1789 memset(&color_key, 0, sizeof(color_key));
1790 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1791 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x, i %u.\n", hr, i);
1792 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
1793 color_key.dwColorSpaceLowValue, i);
1794 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
1795 color_key.dwColorSpaceHighValue, i);
1797 IDirectDrawSurface_Release(mipmap);
1798 mipmap = tmp;
1801 memset(&color_key, 0, sizeof(color_key));
1802 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1803 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1804 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1805 color_key.dwColorSpaceLowValue);
1806 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1807 color_key.dwColorSpaceHighValue);
1809 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
1810 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1811 IDirectDrawSurface_Release(mipmap);
1812 refcount = IDirectDrawSurface_Release(surface);
1813 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1815 memset(&surface_desc, 0, sizeof(surface_desc));
1816 surface_desc.dwSize = sizeof(surface_desc);
1817 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1818 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
1819 surface_desc.dwBackBufferCount = 1;
1820 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1821 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1823 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1824 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1825 color_key.dwColorSpaceLowValue = 0x0000ff00;
1826 color_key.dwColorSpaceHighValue = 0x0000ff00;
1827 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1828 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1829 memset(&color_key, 0, sizeof(color_key));
1830 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1831 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1832 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1833 color_key.dwColorSpaceLowValue);
1834 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1835 color_key.dwColorSpaceHighValue);
1837 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &tmp);
1838 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
1840 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1841 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1842 color_key.dwColorSpaceLowValue = 0x0000ff00;
1843 color_key.dwColorSpaceHighValue = 0x0000ff00;
1844 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1845 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1846 memset(&color_key, 0, sizeof(color_key));
1847 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1848 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1849 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1850 color_key.dwColorSpaceLowValue);
1851 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1852 color_key.dwColorSpaceHighValue);
1854 IDirectDrawSurface_Release(tmp);
1856 refcount = IDirectDrawSurface_Release(surface);
1857 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1858 refcount = IDirectDraw_Release(ddraw);
1859 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1860 DestroyWindow(window);
1863 struct qi_test
1865 REFIID iid;
1866 REFIID refcount_iid;
1867 HRESULT hr;
1870 static void test_qi(const char *test_name, IUnknown *base_iface,
1871 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1873 ULONG refcount, expected_refcount;
1874 IUnknown *iface1, *iface2;
1875 HRESULT hr;
1876 UINT i, j;
1878 for (i = 0; i < entry_count; ++i)
1880 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1881 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1882 if (SUCCEEDED(hr))
1884 for (j = 0; j < entry_count; ++j)
1886 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1887 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1888 if (SUCCEEDED(hr))
1890 expected_refcount = 0;
1891 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1892 ++expected_refcount;
1893 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1894 ++expected_refcount;
1895 refcount = IUnknown_Release(iface2);
1896 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1897 refcount, test_name, i, j, expected_refcount);
1901 expected_refcount = 0;
1902 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1903 ++expected_refcount;
1904 refcount = IUnknown_Release(iface1);
1905 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1906 refcount, test_name, i, expected_refcount);
1911 static void test_surface_qi(void)
1913 static const struct qi_test tests[] =
1915 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
1916 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
1917 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1918 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1919 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1920 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1921 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1922 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1923 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1924 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1925 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1926 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1927 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1928 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1929 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1930 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1931 {&IID_IDirect3D, NULL, E_INVALIDARG },
1932 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1933 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1934 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1935 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1936 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1937 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1938 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1939 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1940 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1941 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1942 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1943 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1944 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1945 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1946 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1947 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1948 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1949 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1952 IDirectDrawSurface *surface;
1953 DDSURFACEDESC surface_desc;
1954 IDirect3DDevice *device;
1955 IDirectDraw *ddraw;
1956 HWND window;
1957 HRESULT hr;
1959 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1961 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1962 return;
1965 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1966 0, 0, 640, 480, 0, 0, 0, 0);
1967 ddraw = create_ddraw();
1968 ok(!!ddraw, "Failed to create a ddraw object.\n");
1969 /* Try to create a D3D device to see if the ddraw implementation supports
1970 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
1971 * doesn't support e.g. the IDirect3DTexture interfaces. */
1972 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1974 skip("Failed to create a 3D device, skipping test.\n");
1975 IDirectDraw_Release(ddraw);
1976 DestroyWindow(window);
1977 return;
1979 IDirect3DDevice_Release(device);
1981 memset(&surface_desc, 0, sizeof(surface_desc));
1982 surface_desc.dwSize = sizeof(surface_desc);
1983 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1984 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1985 surface_desc.dwWidth = 512;
1986 surface_desc.dwHeight = 512;
1987 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, (IDirectDrawSurface **)0xdeadbeef, NULL);
1988 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
1989 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1990 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1992 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
1994 IDirectDrawSurface_Release(surface);
1995 IDirectDraw_Release(ddraw);
1996 DestroyWindow(window);
1999 static void test_device_qi(void)
2001 static const struct qi_test tests[] =
2003 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
2004 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
2005 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
2006 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2007 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
2008 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
2009 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
2010 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
2011 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
2012 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
2013 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
2014 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
2015 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
2016 {&IID_IDirect3DHALDevice, &IID_IDirectDrawSurface, S_OK },
2017 {&IID_IDirect3D7, NULL, E_INVALIDARG },
2018 {&IID_IDirect3D3, NULL, E_INVALIDARG },
2019 {&IID_IDirect3D2, NULL, E_INVALIDARG },
2020 {&IID_IDirect3D, NULL, E_INVALIDARG },
2021 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
2022 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
2023 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
2024 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
2025 {&IID_IDirectDraw, NULL, E_INVALIDARG },
2026 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
2027 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
2028 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
2029 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
2030 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
2031 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
2032 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
2033 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
2034 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
2035 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
2036 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
2037 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
2038 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
2042 IDirect3DDevice *device;
2043 IDirectDraw *ddraw;
2044 HWND window;
2046 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
2048 win_skip("DirectDrawCreateEx not available, skipping test.\n");
2049 return;
2052 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2053 0, 0, 640, 480, 0, 0, 0, 0);
2054 ddraw = create_ddraw();
2055 ok(!!ddraw, "Failed to create a ddraw object.\n");
2056 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2058 skip("Failed to create a 3D device, skipping test.\n");
2059 IDirectDraw_Release(ddraw);
2060 DestroyWindow(window);
2061 return;
2064 test_qi("device_qi", (IUnknown *)device, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
2066 IDirect3DDevice_Release(device);
2067 IDirectDraw_Release(ddraw);
2068 DestroyWindow(window);
2071 static void test_wndproc(void)
2073 LONG_PTR proc, ddraw_proc;
2074 IDirectDraw *ddraw;
2075 WNDCLASSA wc = {0};
2076 HWND window;
2077 HRESULT hr;
2078 ULONG ref;
2080 static struct message messages[] =
2082 {WM_WINDOWPOSCHANGING, FALSE, 0},
2083 {WM_MOVE, FALSE, 0},
2084 {WM_SIZE, FALSE, 0},
2085 {WM_WINDOWPOSCHANGING, FALSE, 0},
2086 {WM_ACTIVATE, FALSE, 0},
2087 {WM_SETFOCUS, FALSE, 0},
2088 {0, FALSE, 0},
2091 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2092 ddraw = create_ddraw();
2093 ok(!!ddraw, "Failed to create a ddraw object.\n");
2095 wc.lpfnWndProc = test_proc;
2096 wc.lpszClassName = "ddraw_test_wndproc_wc";
2097 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2099 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2100 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2102 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2103 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2104 (LONG_PTR)test_proc, proc);
2105 expect_messages = messages;
2106 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2107 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2108 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2109 expect_messages = NULL;
2110 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2111 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2112 (LONG_PTR)test_proc, proc);
2113 ref = IDirectDraw_Release(ddraw);
2114 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2115 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2116 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2117 (LONG_PTR)test_proc, proc);
2119 /* DDSCL_NORMAL doesn't. */
2120 ddraw = create_ddraw();
2121 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2122 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2123 (LONG_PTR)test_proc, proc);
2124 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2125 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2126 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2127 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2128 (LONG_PTR)test_proc, proc);
2129 ref = IDirectDraw_Release(ddraw);
2130 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2131 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2132 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2133 (LONG_PTR)test_proc, proc);
2135 /* The original window proc is only restored by ddraw if the current
2136 * window proc matches the one ddraw set. This also affects switching
2137 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2138 ddraw = create_ddraw();
2139 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2140 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2141 (LONG_PTR)test_proc, proc);
2142 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2143 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2144 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2145 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2146 (LONG_PTR)test_proc, proc);
2147 ddraw_proc = proc;
2148 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2149 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2150 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2151 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2152 (LONG_PTR)test_proc, proc);
2153 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2154 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2155 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2156 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2157 (LONG_PTR)test_proc, proc);
2158 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2159 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2160 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2161 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2162 (LONG_PTR)DefWindowProcA, proc);
2163 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2164 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2165 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
2166 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2167 (LONG_PTR)DefWindowProcA, proc);
2168 ref = IDirectDraw_Release(ddraw);
2169 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2170 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2171 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2172 (LONG_PTR)test_proc, proc);
2174 ddraw = create_ddraw();
2175 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2176 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2177 (LONG_PTR)test_proc, proc);
2178 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2179 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2180 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2181 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2182 (LONG_PTR)test_proc, proc);
2183 ref = IDirectDraw_Release(ddraw);
2184 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2185 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2186 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2187 (LONG_PTR)DefWindowProcA, proc);
2189 fix_wndproc(window, (LONG_PTR)test_proc);
2190 expect_messages = NULL;
2191 DestroyWindow(window);
2192 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2195 static void test_window_style(void)
2197 LONG style, exstyle, tmp, expected_style;
2198 RECT fullscreen_rect, r;
2199 IDirectDraw *ddraw;
2200 HWND window;
2201 HRESULT hr;
2202 ULONG ref;
2203 BOOL ret;
2205 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2206 0, 0, 100, 100, 0, 0, 0, 0);
2207 ddraw = create_ddraw();
2208 ok(!!ddraw, "Failed to create a ddraw object.\n");
2210 style = GetWindowLongA(window, GWL_STYLE);
2211 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2212 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2214 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2215 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2217 tmp = GetWindowLongA(window, GWL_STYLE);
2218 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2219 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2220 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2222 GetWindowRect(window, &r);
2223 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2224 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2225 GetClientRect(window, &r);
2226 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2228 ret = SetForegroundWindow(GetDesktopWindow());
2229 ok(ret, "Failed to set foreground window.\n");
2231 tmp = GetWindowLongA(window, GWL_STYLE);
2232 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2233 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2234 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2236 ret = SetForegroundWindow(window);
2237 ok(ret, "Failed to set foreground window.\n");
2238 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2239 * the next tests expect this. */
2240 ShowWindow(window, SW_HIDE);
2242 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2243 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2245 tmp = GetWindowLongA(window, GWL_STYLE);
2246 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2247 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2248 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2250 ShowWindow(window, SW_SHOW);
2251 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2252 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2254 tmp = GetWindowLongA(window, GWL_STYLE);
2255 expected_style = style | WS_VISIBLE;
2256 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2257 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2258 expected_style = exstyle | WS_EX_TOPMOST;
2259 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2261 ret = SetForegroundWindow(GetDesktopWindow());
2262 ok(ret, "Failed to set foreground window.\n");
2263 tmp = GetWindowLongA(window, GWL_STYLE);
2264 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
2265 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2266 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2267 expected_style = exstyle | WS_EX_TOPMOST;
2268 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2270 ref = IDirectDraw_Release(ddraw);
2271 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2273 DestroyWindow(window);
2276 static void test_redundant_mode_set(void)
2278 DDSURFACEDESC surface_desc = {0};
2279 IDirectDraw *ddraw;
2280 HWND window;
2281 HRESULT hr;
2282 RECT r, s;
2283 ULONG ref;
2285 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2286 0, 0, 100, 100, 0, 0, 0, 0);
2287 ddraw = create_ddraw();
2288 ok(!!ddraw, "Failed to create a ddraw object.\n");
2290 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2291 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2293 surface_desc.dwSize = sizeof(surface_desc);
2294 hr = IDirectDraw_GetDisplayMode(ddraw, &surface_desc);
2295 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
2297 hr = IDirectDraw_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2298 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
2299 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2301 GetWindowRect(window, &r);
2302 r.right /= 2;
2303 r.bottom /= 2;
2304 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2305 GetWindowRect(window, &s);
2306 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2308 hr = IDirectDraw_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2309 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
2310 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2312 GetWindowRect(window, &s);
2313 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2315 ref = IDirectDraw_Release(ddraw);
2316 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2318 DestroyWindow(window);
2321 static SIZE screen_size;
2323 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2325 if (message == WM_SIZE)
2327 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2328 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2331 return test_proc(hwnd, message, wparam, lparam);
2334 struct test_coop_level_mode_set_enum_param
2336 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
2339 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC *surface_desc, void *context)
2341 struct test_coop_level_mode_set_enum_param *param = context;
2343 if (U1(surface_desc->ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
2344 return DDENUMRET_OK;
2345 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
2346 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
2347 return DDENUMRET_OK;
2349 if (!param->ddraw_width)
2351 param->ddraw_width = surface_desc->dwWidth;
2352 param->ddraw_height = surface_desc->dwHeight;
2353 return DDENUMRET_OK;
2355 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
2356 return DDENUMRET_OK;
2358 param->user32_width = surface_desc->dwWidth;
2359 param->user32_height = surface_desc->dwHeight;
2360 return DDENUMRET_CANCEL;
2363 static void test_coop_level_mode_set(void)
2365 IDirectDrawSurface *primary;
2366 RECT registry_rect, ddraw_rect, user32_rect, r;
2367 IDirectDraw *ddraw;
2368 DDSURFACEDESC ddsd;
2369 WNDCLASSA wc = {0};
2370 HWND window;
2371 HRESULT hr;
2372 ULONG ref;
2373 MSG msg;
2374 struct test_coop_level_mode_set_enum_param param;
2375 DEVMODEW devmode;
2376 BOOL ret;
2377 LONG change_ret;
2379 static const struct message exclusive_messages[] =
2381 {WM_WINDOWPOSCHANGING, FALSE, 0},
2382 {WM_WINDOWPOSCHANGED, FALSE, 0},
2383 {WM_SIZE, FALSE, 0},
2384 {WM_DISPLAYCHANGE, FALSE, 0},
2385 {0, FALSE, 0},
2387 static const struct message exclusive_focus_loss_messages[] =
2389 {WM_ACTIVATE, TRUE, WA_INACTIVE},
2390 {WM_DISPLAYCHANGE, FALSE, 0},
2391 {WM_WINDOWPOSCHANGING, FALSE, 0},
2392 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
2393 * SW_MINIMIZED, causing a recursive window activation that does not
2394 * produce the same result in Wine yet. Ignore the difference for now.
2395 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
2396 {WM_WINDOWPOSCHANGED, FALSE, 0},
2397 {WM_MOVE, FALSE, 0},
2398 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2399 {WM_ACTIVATEAPP, TRUE, FALSE},
2400 {0, FALSE, 0},
2402 static const struct message exclusive_focus_restore_messages[] =
2404 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
2405 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
2406 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
2407 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
2408 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
2409 /* Native redundantly sets the window size here. */
2410 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
2411 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
2412 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
2413 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
2414 {0, FALSE, 0},
2416 static const struct message sc_restore_messages[] =
2418 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
2419 {WM_WINDOWPOSCHANGING, FALSE, 0},
2420 {WM_WINDOWPOSCHANGED, FALSE, 0},
2421 {WM_SIZE, TRUE, SIZE_RESTORED},
2422 {0, FALSE, 0},
2424 static const struct message sc_minimize_messages[] =
2426 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
2427 {WM_WINDOWPOSCHANGING, FALSE, 0},
2428 {WM_WINDOWPOSCHANGED, FALSE, 0},
2429 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2430 {0, FALSE, 0},
2432 static const struct message sc_maximize_messages[] =
2434 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
2435 {WM_WINDOWPOSCHANGING, FALSE, 0},
2436 {WM_WINDOWPOSCHANGED, FALSE, 0},
2437 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
2438 {0, FALSE, 0},
2441 static const struct message normal_messages[] =
2443 {WM_DISPLAYCHANGE, FALSE, 0},
2444 {0, FALSE, 0},
2447 ddraw = create_ddraw();
2448 ok(!!ddraw, "Failed to create a ddraw object.\n");
2450 memset(&param, 0, sizeof(param));
2451 hr = IDirectDraw_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
2452 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2453 ref = IDirectDraw_Release(ddraw);
2454 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2456 if (!param.user32_height)
2458 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
2459 return;
2462 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2463 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
2464 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
2466 memset(&devmode, 0, sizeof(devmode));
2467 devmode.dmSize = sizeof(devmode);
2468 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2469 devmode.dmPelsWidth = param.user32_width;
2470 devmode.dmPelsHeight = param.user32_height;
2471 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2472 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2474 ddraw = create_ddraw();
2475 ok(!!ddraw, "Failed to create a ddraw object.\n");
2477 wc.lpfnWndProc = mode_set_proc;
2478 wc.lpszClassName = "ddraw_test_wndproc_wc";
2479 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2481 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2482 0, 0, 100, 100, 0, 0, 0, 0);
2484 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2485 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2487 GetWindowRect(window, &r);
2488 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2489 wine_dbgstr_rect(&r));
2491 memset(&ddsd, 0, sizeof(ddsd));
2492 ddsd.dwSize = sizeof(ddsd);
2493 ddsd.dwFlags = DDSD_CAPS;
2494 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2496 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2497 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2498 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2499 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2500 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2501 param.user32_width, ddsd.dwWidth);
2502 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2503 param.user32_height, ddsd.dwHeight);
2505 GetWindowRect(window, &r);
2506 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2507 wine_dbgstr_rect(&r));
2509 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2510 expect_messages = exclusive_messages;
2511 screen_size.cx = 0;
2512 screen_size.cy = 0;
2514 hr = IDirectDrawSurface_IsLost(primary);
2515 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2516 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2517 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2518 hr = IDirectDrawSurface_IsLost(primary);
2519 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2521 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2522 expect_messages = NULL;
2523 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
2524 "Expected screen size %ux%u, got %ux%u.\n",
2525 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
2527 GetWindowRect(window, &r);
2528 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2529 wine_dbgstr_rect(&r));
2531 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2532 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2533 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2534 param.user32_width, ddsd.dwWidth);
2535 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2536 param.user32_height, ddsd.dwHeight);
2537 IDirectDrawSurface_Release(primary);
2539 memset(&ddsd, 0, sizeof(ddsd));
2540 ddsd.dwSize = sizeof(ddsd);
2541 ddsd.dwFlags = DDSD_CAPS;
2542 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2544 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2545 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2546 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2547 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2548 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2549 param.ddraw_width, ddsd.dwWidth);
2550 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2551 param.ddraw_height, ddsd.dwHeight);
2553 GetWindowRect(window, &r);
2554 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2555 wine_dbgstr_rect(&r));
2557 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2558 expect_messages = exclusive_messages;
2559 screen_size.cx = 0;
2560 screen_size.cy = 0;
2562 hr = IDirectDrawSurface_IsLost(primary);
2563 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2564 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2565 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2566 hr = IDirectDrawSurface_IsLost(primary);
2567 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2569 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2570 expect_messages = NULL;
2571 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
2572 "Expected screen size %ux%u, got %ux%u.\n",
2573 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
2575 GetWindowRect(window, &r);
2576 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2577 wine_dbgstr_rect(&r));
2579 expect_messages = exclusive_focus_loss_messages;
2580 ret = SetForegroundWindow(GetDesktopWindow());
2581 ok(ret, "Failed to set foreground window.\n");
2582 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2583 memset(&devmode, 0, sizeof(devmode));
2584 devmode.dmSize = sizeof(devmode);
2585 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2586 ok(ret, "Failed to get display mode.\n");
2587 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2588 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
2589 devmode.dmPelsWidth, devmode.dmPelsHeight);
2591 expect_messages = exclusive_focus_restore_messages;
2592 ShowWindow(window, SW_RESTORE);
2593 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2595 GetWindowRect(window, &r);
2596 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2597 wine_dbgstr_rect(&r));
2598 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2599 ok(ret, "Failed to get display mode.\n");
2600 ok(devmode.dmPelsWidth == param.ddraw_width
2601 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpect screen size %ux%u.\n",
2602 devmode.dmPelsWidth, devmode.dmPelsHeight);
2604 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2605 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2606 /* Normally the primary should be restored here. Unfortunately this causes the
2607 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
2608 * testbot. Another Restore call would presumably avoid the crash, but it also moots
2609 * the point of the GetSurfaceDesc call. */
2611 expect_messages = sc_minimize_messages;
2612 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
2613 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2614 expect_messages = NULL;
2616 expect_messages = sc_restore_messages;
2617 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
2618 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2619 expect_messages = NULL;
2621 expect_messages = sc_maximize_messages;
2622 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
2623 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2624 expect_messages = NULL;
2626 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2627 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2629 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2630 expect_messages = exclusive_messages;
2631 screen_size.cx = 0;
2632 screen_size.cy = 0;
2634 hr = IDirectDrawSurface_IsLost(primary);
2635 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2636 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2637 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2638 hr = IDirectDrawSurface_IsLost(primary);
2639 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2641 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2642 expect_messages = NULL;
2643 ok(screen_size.cx == registry_mode.dmPelsWidth
2644 && screen_size.cy == registry_mode.dmPelsHeight,
2645 "Expected screen size %ux%u, got %ux%u.\n",
2646 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
2648 GetWindowRect(window, &r);
2649 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2650 wine_dbgstr_rect(&r));
2652 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2653 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2654 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2655 param.ddraw_width, ddsd.dwWidth);
2656 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2657 param.ddraw_height, ddsd.dwHeight);
2658 IDirectDrawSurface_Release(primary);
2660 /* For Wine. */
2661 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2662 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2664 memset(&ddsd, 0, sizeof(ddsd));
2665 ddsd.dwSize = sizeof(ddsd);
2666 ddsd.dwFlags = DDSD_CAPS;
2667 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2669 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2670 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2671 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2672 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2673 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2674 registry_mode.dmPelsWidth, ddsd.dwWidth);
2675 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2676 registry_mode.dmPelsHeight, ddsd.dwHeight);
2678 GetWindowRect(window, &r);
2679 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2680 wine_dbgstr_rect(&r));
2682 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2683 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2685 GetWindowRect(window, &r);
2686 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2687 wine_dbgstr_rect(&r));
2689 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2690 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2691 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2692 registry_mode.dmPelsWidth, ddsd.dwWidth);
2693 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2694 registry_mode.dmPelsHeight, ddsd.dwHeight);
2695 IDirectDrawSurface_Release(primary);
2697 memset(&ddsd, 0, sizeof(ddsd));
2698 ddsd.dwSize = sizeof(ddsd);
2699 ddsd.dwFlags = DDSD_CAPS;
2700 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2702 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2703 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2704 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2705 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2706 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2707 registry_mode.dmPelsWidth, ddsd.dwWidth);
2708 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2709 registry_mode.dmPelsHeight, ddsd.dwHeight);
2711 GetWindowRect(window, &r);
2712 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2713 wine_dbgstr_rect(&r));
2715 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2716 expect_messages = normal_messages;
2717 screen_size.cx = 0;
2718 screen_size.cy = 0;
2720 hr = IDirectDrawSurface_IsLost(primary);
2721 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2722 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2723 devmode.dmPelsWidth = param.user32_width;
2724 devmode.dmPelsHeight = param.user32_height;
2725 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2726 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2727 hr = IDirectDrawSurface_IsLost(primary);
2728 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2730 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2731 expect_messages = NULL;
2732 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2734 GetWindowRect(window, &r);
2735 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2736 wine_dbgstr_rect(&r));
2738 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2739 expect_messages = normal_messages;
2740 screen_size.cx = 0;
2741 screen_size.cy = 0;
2743 hr = IDirectDrawSurface_Restore(primary);
2744 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2745 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2746 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
2748 win_skip("Broken SetDisplayMode(), skipping remaining tests.\n");
2749 IDirectDrawSurface_Release(primary);
2750 IDirectDraw_Release(ddraw);
2751 goto done;
2753 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2754 hr = IDirectDrawSurface_Restore(primary);
2755 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2756 hr = IDirectDrawSurface_IsLost(primary);
2757 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2759 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2760 expect_messages = NULL;
2761 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2763 GetWindowRect(window, &r);
2764 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2765 wine_dbgstr_rect(&r));
2767 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2768 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2769 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2770 registry_mode.dmPelsWidth, ddsd.dwWidth);
2771 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2772 registry_mode.dmPelsHeight, ddsd.dwHeight);
2773 IDirectDrawSurface_Release(primary);
2775 memset(&ddsd, 0, sizeof(ddsd));
2776 ddsd.dwSize = sizeof(ddsd);
2777 ddsd.dwFlags = DDSD_CAPS;
2778 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2780 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2781 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2782 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2783 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2784 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2785 param.ddraw_width, ddsd.dwWidth);
2786 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2787 param.ddraw_height, ddsd.dwHeight);
2789 GetWindowRect(window, &r);
2790 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2791 wine_dbgstr_rect(&r));
2793 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2794 expect_messages = normal_messages;
2795 screen_size.cx = 0;
2796 screen_size.cy = 0;
2798 hr = IDirectDrawSurface_IsLost(primary);
2799 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2800 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2801 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2802 hr = IDirectDrawSurface_IsLost(primary);
2803 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2805 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2806 expect_messages = NULL;
2807 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2809 GetWindowRect(window, &r);
2810 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2811 wine_dbgstr_rect(&r));
2813 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2814 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2815 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2816 param.ddraw_width, ddsd.dwWidth);
2817 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2818 param.ddraw_height, ddsd.dwHeight);
2819 IDirectDrawSurface_Release(primary);
2821 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2822 ok(ret, "Failed to get display mode.\n");
2823 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2824 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
2825 "Expected resolution %ux%u, got %ux%u.\n",
2826 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
2827 devmode.dmPelsWidth, devmode.dmPelsHeight);
2828 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2829 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2831 memset(&ddsd, 0, sizeof(ddsd));
2832 ddsd.dwSize = sizeof(ddsd);
2833 ddsd.dwFlags = DDSD_CAPS;
2834 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2836 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2837 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2838 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2839 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2840 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2841 registry_mode.dmPelsWidth, ddsd.dwWidth);
2842 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2843 registry_mode.dmPelsHeight, ddsd.dwHeight);
2845 GetWindowRect(window, &r);
2846 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2847 wine_dbgstr_rect(&r));
2849 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2850 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2851 * not DDSCL_FULLSCREEN. */
2852 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2853 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2855 GetWindowRect(window, &r);
2856 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2857 wine_dbgstr_rect(&r));
2859 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2860 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2861 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2862 registry_mode.dmPelsWidth, ddsd.dwWidth);
2863 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2864 registry_mode.dmPelsHeight, ddsd.dwHeight);
2865 IDirectDrawSurface_Release(primary);
2867 memset(&ddsd, 0, sizeof(ddsd));
2868 ddsd.dwSize = sizeof(ddsd);
2869 ddsd.dwFlags = DDSD_CAPS;
2870 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2872 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2873 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2874 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2875 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2876 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2877 registry_mode.dmPelsWidth, ddsd.dwWidth);
2878 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2879 registry_mode.dmPelsHeight, ddsd.dwHeight);
2881 GetWindowRect(window, &r);
2882 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2883 wine_dbgstr_rect(&r));
2885 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2886 expect_messages = normal_messages;
2887 screen_size.cx = 0;
2888 screen_size.cy = 0;
2890 hr = IDirectDrawSurface_IsLost(primary);
2891 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2892 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2893 devmode.dmPelsWidth = param.user32_width;
2894 devmode.dmPelsHeight = param.user32_height;
2895 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2896 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2897 hr = IDirectDrawSurface_IsLost(primary);
2898 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2900 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2901 expect_messages = NULL;
2902 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2904 GetWindowRect(window, &r);
2905 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2906 wine_dbgstr_rect(&r));
2908 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2909 expect_messages = normal_messages;
2910 screen_size.cx = 0;
2911 screen_size.cy = 0;
2913 hr = IDirectDrawSurface_Restore(primary);
2914 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2915 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2916 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2917 hr = IDirectDrawSurface_Restore(primary);
2918 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2919 hr = IDirectDrawSurface_IsLost(primary);
2920 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2922 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2923 expect_messages = NULL;
2924 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2926 GetWindowRect(window, &r);
2927 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2928 wine_dbgstr_rect(&r));
2930 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2931 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2932 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2933 registry_mode.dmPelsWidth, ddsd.dwWidth);
2934 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2935 registry_mode.dmPelsHeight, ddsd.dwHeight);
2936 IDirectDrawSurface_Release(primary);
2938 memset(&ddsd, 0, sizeof(ddsd));
2939 ddsd.dwSize = sizeof(ddsd);
2940 ddsd.dwFlags = DDSD_CAPS;
2941 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2943 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2944 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2945 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2946 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2947 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2948 param.ddraw_width, ddsd.dwWidth);
2949 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2950 param.ddraw_height, ddsd.dwHeight);
2952 GetWindowRect(window, &r);
2953 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2954 wine_dbgstr_rect(&r));
2956 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2957 expect_messages = normal_messages;
2958 screen_size.cx = 0;
2959 screen_size.cy = 0;
2961 hr = IDirectDrawSurface_IsLost(primary);
2962 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2963 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2964 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2965 hr = IDirectDrawSurface_IsLost(primary);
2966 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2968 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2969 expect_messages = NULL;
2970 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2972 GetWindowRect(window, &r);
2973 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2974 wine_dbgstr_rect(&r));
2976 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2977 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2978 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2979 param.ddraw_width, ddsd.dwWidth);
2980 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2981 param.ddraw_height, ddsd.dwHeight);
2982 IDirectDrawSurface_Release(primary);
2984 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2985 ok(ret, "Failed to get display mode.\n");
2986 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2987 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
2988 "Expected resolution %ux%u, got %ux%u.\n",
2989 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
2990 devmode.dmPelsWidth, devmode.dmPelsHeight);
2991 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2992 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2994 memset(&ddsd, 0, sizeof(ddsd));
2995 ddsd.dwSize = sizeof(ddsd);
2996 ddsd.dwFlags = DDSD_CAPS;
2997 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2999 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
3000 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3001 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3002 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3003 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3004 registry_mode.dmPelsWidth, ddsd.dwWidth);
3005 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3006 registry_mode.dmPelsHeight, ddsd.dwHeight);
3007 IDirectDrawSurface_Release(primary);
3009 GetWindowRect(window, &r);
3010 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3011 wine_dbgstr_rect(&r));
3013 /* Unlike ddraw2-7, changing from EXCLUSIVE to NORMAL does not restore the resolution */
3014 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3015 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3016 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3017 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3019 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3020 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3022 memset(&ddsd, 0, sizeof(ddsd));
3023 ddsd.dwSize = sizeof(ddsd);
3024 ddsd.dwFlags = DDSD_CAPS;
3025 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3027 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
3028 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3029 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3030 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3031 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3032 param.ddraw_width, ddsd.dwWidth);
3033 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3034 param.ddraw_height, ddsd.dwHeight);
3035 IDirectDrawSurface_Release(primary);
3036 hr = IDirectDraw_RestoreDisplayMode(ddraw);
3037 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3039 ref = IDirectDraw_Release(ddraw);
3040 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3042 GetWindowRect(window, &r);
3043 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3044 wine_dbgstr_rect(&r));
3046 done:
3047 expect_messages = NULL;
3048 DestroyWindow(window);
3049 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3052 static void test_coop_level_mode_set_multi(void)
3054 IDirectDraw *ddraw1, *ddraw2;
3055 UINT w, h;
3056 HWND window;
3057 HRESULT hr;
3058 ULONG ref;
3060 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3061 0, 0, 100, 100, 0, 0, 0, 0);
3062 ddraw1 = create_ddraw();
3063 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3065 /* With just a single ddraw object, the display mode is restored on
3066 * release. */
3067 hr = set_display_mode(ddraw1, 800, 600);
3068 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
3070 win_skip("Broken SetDisplayMode(), skipping test.\n");
3071 IDirectDraw_Release(ddraw1);
3072 DestroyWindow(window);
3073 return;
3075 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3076 w = GetSystemMetrics(SM_CXSCREEN);
3077 ok(w == 800, "Got unexpected screen width %u.\n", w);
3078 h = GetSystemMetrics(SM_CYSCREEN);
3079 ok(h == 600, "Got unexpected screen height %u.\n", h);
3081 ref = IDirectDraw_Release(ddraw1);
3082 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3083 w = GetSystemMetrics(SM_CXSCREEN);
3084 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3085 h = GetSystemMetrics(SM_CYSCREEN);
3086 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3088 /* When there are multiple ddraw objects, the display mode is restored to
3089 * the initial mode, before the first SetDisplayMode() call. */
3090 ddraw1 = create_ddraw();
3091 hr = set_display_mode(ddraw1, 800, 600);
3092 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3093 w = GetSystemMetrics(SM_CXSCREEN);
3094 ok(w == 800, "Got unexpected screen width %u.\n", w);
3095 h = GetSystemMetrics(SM_CYSCREEN);
3096 ok(h == 600, "Got unexpected screen height %u.\n", h);
3098 ddraw2 = create_ddraw();
3099 hr = set_display_mode(ddraw2, 640, 480);
3100 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3101 w = GetSystemMetrics(SM_CXSCREEN);
3102 ok(w == 640, "Got unexpected screen width %u.\n", w);
3103 h = GetSystemMetrics(SM_CYSCREEN);
3104 ok(h == 480, "Got unexpected screen height %u.\n", h);
3106 ref = IDirectDraw_Release(ddraw2);
3107 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3108 w = GetSystemMetrics(SM_CXSCREEN);
3109 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3110 h = GetSystemMetrics(SM_CYSCREEN);
3111 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3113 ref = IDirectDraw_Release(ddraw1);
3114 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3115 w = GetSystemMetrics(SM_CXSCREEN);
3116 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3117 h = GetSystemMetrics(SM_CYSCREEN);
3118 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3120 /* Regardless of release ordering. */
3121 ddraw1 = create_ddraw();
3122 hr = set_display_mode(ddraw1, 800, 600);
3123 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3124 w = GetSystemMetrics(SM_CXSCREEN);
3125 ok(w == 800, "Got unexpected screen width %u.\n", w);
3126 h = GetSystemMetrics(SM_CYSCREEN);
3127 ok(h == 600, "Got unexpected screen height %u.\n", h);
3129 ddraw2 = create_ddraw();
3130 hr = set_display_mode(ddraw2, 640, 480);
3131 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3132 w = GetSystemMetrics(SM_CXSCREEN);
3133 ok(w == 640, "Got unexpected screen width %u.\n", w);
3134 h = GetSystemMetrics(SM_CYSCREEN);
3135 ok(h == 480, "Got unexpected screen height %u.\n", h);
3137 ref = IDirectDraw_Release(ddraw1);
3138 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3139 w = GetSystemMetrics(SM_CXSCREEN);
3140 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3141 h = GetSystemMetrics(SM_CYSCREEN);
3142 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3144 ref = IDirectDraw_Release(ddraw2);
3145 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3146 w = GetSystemMetrics(SM_CXSCREEN);
3147 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3148 h = GetSystemMetrics(SM_CYSCREEN);
3149 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3151 /* But only for ddraw objects that called SetDisplayMode(). */
3152 ddraw1 = create_ddraw();
3153 ddraw2 = create_ddraw();
3154 hr = set_display_mode(ddraw2, 640, 480);
3155 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3156 w = GetSystemMetrics(SM_CXSCREEN);
3157 ok(w == 640, "Got unexpected screen width %u.\n", w);
3158 h = GetSystemMetrics(SM_CYSCREEN);
3159 ok(h == 480, "Got unexpected screen height %u.\n", h);
3161 ref = IDirectDraw_Release(ddraw1);
3162 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3163 w = GetSystemMetrics(SM_CXSCREEN);
3164 ok(w == 640, "Got unexpected screen width %u.\n", w);
3165 h = GetSystemMetrics(SM_CYSCREEN);
3166 ok(h == 480, "Got unexpected screen height %u.\n", h);
3168 ref = IDirectDraw_Release(ddraw2);
3169 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3170 w = GetSystemMetrics(SM_CXSCREEN);
3171 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3172 h = GetSystemMetrics(SM_CYSCREEN);
3173 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3175 /* If there's a ddraw object that's currently in exclusive mode, it blocks
3176 * restoring the display mode. */
3177 ddraw1 = create_ddraw();
3178 hr = set_display_mode(ddraw1, 800, 600);
3179 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3180 w = GetSystemMetrics(SM_CXSCREEN);
3181 ok(w == 800, "Got unexpected screen width %u.\n", w);
3182 h = GetSystemMetrics(SM_CYSCREEN);
3183 ok(h == 600, "Got unexpected screen height %u.\n", h);
3185 ddraw2 = create_ddraw();
3186 hr = set_display_mode(ddraw2, 640, 480);
3187 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3188 w = GetSystemMetrics(SM_CXSCREEN);
3189 ok(w == 640, "Got unexpected screen width %u.\n", w);
3190 h = GetSystemMetrics(SM_CYSCREEN);
3191 ok(h == 480, "Got unexpected screen height %u.\n", h);
3193 hr = IDirectDraw_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3194 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3196 ref = IDirectDraw_Release(ddraw1);
3197 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3198 w = GetSystemMetrics(SM_CXSCREEN);
3199 ok(w == 640, "Got unexpected screen width %u.\n", w);
3200 h = GetSystemMetrics(SM_CYSCREEN);
3201 ok(h == 480, "Got unexpected screen height %u.\n", h);
3203 ref = IDirectDraw_Release(ddraw2);
3204 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3205 w = GetSystemMetrics(SM_CXSCREEN);
3206 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3207 h = GetSystemMetrics(SM_CYSCREEN);
3208 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3210 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3211 ddraw1 = create_ddraw();
3212 hr = set_display_mode(ddraw1, 800, 600);
3213 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3214 w = GetSystemMetrics(SM_CXSCREEN);
3215 ok(w == 800, "Got unexpected screen width %u.\n", w);
3216 h = GetSystemMetrics(SM_CYSCREEN);
3217 ok(h == 600, "Got unexpected screen height %u.\n", h);
3219 hr = IDirectDraw_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3220 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3222 ddraw2 = create_ddraw();
3223 hr = set_display_mode(ddraw2, 640, 480);
3224 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3226 ref = IDirectDraw_Release(ddraw1);
3227 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3228 w = GetSystemMetrics(SM_CXSCREEN);
3229 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3230 h = GetSystemMetrics(SM_CYSCREEN);
3231 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3233 ref = IDirectDraw_Release(ddraw2);
3234 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3235 w = GetSystemMetrics(SM_CXSCREEN);
3236 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3237 h = GetSystemMetrics(SM_CYSCREEN);
3238 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3240 DestroyWindow(window);
3243 static void test_initialize(void)
3245 IDirectDraw *ddraw;
3246 IDirect3D *d3d;
3247 HRESULT hr;
3249 ddraw = create_ddraw();
3250 ok(!!ddraw, "Failed to create a ddraw object.\n");
3252 hr = IDirectDraw_Initialize(ddraw, NULL);
3253 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
3254 IDirectDraw_Release(ddraw);
3256 CoInitialize(NULL);
3257 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw, (void **)&ddraw);
3258 ok(SUCCEEDED(hr), "Failed to create IDirectDraw instance, hr %#x.\n", hr);
3259 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
3260 if (SUCCEEDED(hr))
3262 /* IDirect3D_Initialize() just returns DDERR_ALREADYINITIALIZED. */
3263 hr = IDirect3D_Initialize(d3d, NULL);
3264 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
3265 IDirect3D_Release(d3d);
3267 else
3268 skip("D3D interface is not available, skipping test.\n");
3269 hr = IDirectDraw_Initialize(ddraw, NULL);
3270 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
3271 hr = IDirectDraw_Initialize(ddraw, NULL);
3272 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
3273 IDirectDraw_Release(ddraw);
3274 CoUninitialize();
3276 if (0) /* This crashes on the W2KPROSP4 testbot. */
3278 CoInitialize(NULL);
3279 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirect3D, (void **)&d3d);
3280 ok(hr == E_NOINTERFACE, "CoCreateInstance returned hr %#x, expected E_NOINTERFACE.\n", hr);
3281 CoUninitialize();
3285 static void test_coop_level_surf_create(void)
3287 IDirectDrawSurface *surface;
3288 IDirectDraw *ddraw;
3289 DDSURFACEDESC ddsd;
3290 HRESULT hr;
3292 ddraw = create_ddraw();
3293 ok(!!ddraw, "Failed to create a ddraw object.\n");
3295 memset(&ddsd, 0, sizeof(ddsd));
3296 ddsd.dwSize = sizeof(ddsd);
3297 ddsd.dwFlags = DDSD_CAPS;
3298 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3299 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3300 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3302 IDirectDraw_Release(ddraw);
3305 static void test_coop_level_multi_window(void)
3307 HWND window1, window2;
3308 IDirectDraw *ddraw;
3309 HRESULT hr;
3311 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
3312 0, 0, 640, 480, 0, 0, 0, 0);
3313 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
3314 0, 0, 640, 480, 0, 0, 0, 0);
3315 ddraw = create_ddraw();
3316 ok(!!ddraw, "Failed to create a ddraw object.\n");
3318 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
3319 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3320 hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3321 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3322 ok(IsWindow(window1), "Window 1 was destroyed.\n");
3323 ok(IsWindow(window2), "Window 2 was destroyed.\n");
3325 IDirectDraw_Release(ddraw);
3326 DestroyWindow(window2);
3327 DestroyWindow(window1);
3330 static void test_clear_rect_count(void)
3332 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3333 IDirect3DMaterial *white, *red, *green, *blue;
3334 IDirect3DViewport *viewport;
3335 IDirect3DDevice *device;
3336 IDirectDrawSurface *rt;
3337 IDirectDraw *ddraw;
3338 D3DCOLOR color;
3339 HWND window;
3340 HRESULT hr;
3342 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3343 0, 0, 640, 480, 0, 0, 0, 0);
3344 ddraw = create_ddraw();
3345 ok(!!ddraw, "Failed to create a ddraw object.\n");
3346 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3348 skip("Failed to create a 3D device, skipping test.\n");
3349 IDirectDraw_Release(ddraw);
3350 DestroyWindow(window);
3351 return;
3354 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
3355 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3357 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
3358 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
3359 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
3360 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
3361 viewport = create_viewport(device, 0, 0, 640, 480);
3363 viewport_set_background(device, viewport, white);
3364 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
3365 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3366 viewport_set_background(device, viewport, red);
3367 hr = IDirect3DViewport_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
3368 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3369 viewport_set_background(device, viewport, green);
3370 hr = IDirect3DViewport_Clear(viewport, 0, NULL, D3DCLEAR_TARGET);
3371 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3372 viewport_set_background(device, viewport, blue);
3373 hr = IDirect3DViewport_Clear(viewport, 1, NULL, D3DCLEAR_TARGET);
3374 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3376 color = get_surface_color(rt, 320, 240);
3377 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x000000ff, 1)),
3378 "Got unexpected color 0x%08x.\n", color);
3380 IDirectDrawSurface_Release(rt);
3381 destroy_viewport(device, viewport);
3382 destroy_material(white);
3383 destroy_material(red);
3384 destroy_material(green);
3385 destroy_material(blue);
3386 IDirect3DDevice_Release(device);
3387 IDirectDraw_Release(ddraw);
3388 DestroyWindow(window);
3391 static struct
3393 BOOL received;
3394 IDirectDraw *ddraw;
3395 HWND window;
3396 DWORD coop_level;
3397 } activateapp_testdata;
3399 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3401 if (message == WM_ACTIVATEAPP)
3403 if (activateapp_testdata.ddraw)
3405 HRESULT hr;
3406 activateapp_testdata.received = FALSE;
3407 hr = IDirectDraw_SetCooperativeLevel(activateapp_testdata.ddraw,
3408 activateapp_testdata.window, activateapp_testdata.coop_level);
3409 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
3410 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
3412 activateapp_testdata.received = TRUE;
3415 return DefWindowProcA(hwnd, message, wparam, lparam);
3418 static void test_coop_level_activateapp(void)
3420 IDirectDraw *ddraw;
3421 HRESULT hr;
3422 HWND window;
3423 WNDCLASSA wc = {0};
3424 DDSURFACEDESC ddsd;
3425 IDirectDrawSurface *surface;
3427 ddraw = create_ddraw();
3428 ok(!!ddraw, "Failed to create a ddraw object.\n");
3430 wc.lpfnWndProc = activateapp_test_proc;
3431 wc.lpszClassName = "ddraw_test_wndproc_wc";
3432 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3434 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
3435 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
3437 /* Exclusive with window already active. */
3438 SetForegroundWindow(window);
3439 activateapp_testdata.received = FALSE;
3440 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3441 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3442 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
3443 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3444 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3446 /* Exclusive with window not active. */
3447 SetForegroundWindow(GetDesktopWindow());
3448 activateapp_testdata.received = FALSE;
3449 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3450 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3451 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3452 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3453 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3455 /* Normal with window not active, then exclusive with the same window. */
3456 SetForegroundWindow(GetDesktopWindow());
3457 activateapp_testdata.received = FALSE;
3458 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3459 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3460 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
3461 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3462 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3463 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3464 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3465 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3467 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
3468 SetForegroundWindow(GetDesktopWindow());
3469 activateapp_testdata.received = FALSE;
3470 activateapp_testdata.ddraw = ddraw;
3471 activateapp_testdata.window = window;
3472 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
3473 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3474 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3475 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3476 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3477 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3479 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
3480 * succeeding. Another switch to exclusive and back to normal is needed to release the
3481 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
3482 * WM_ACTIVATEAPP messages. */
3483 activateapp_testdata.ddraw = NULL;
3484 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3485 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3486 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3487 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3489 /* Setting DDSCL_NORMAL with recursive invocation. */
3490 SetForegroundWindow(GetDesktopWindow());
3491 activateapp_testdata.received = FALSE;
3492 activateapp_testdata.ddraw = ddraw;
3493 activateapp_testdata.window = window;
3494 activateapp_testdata.coop_level = DDSCL_NORMAL;
3495 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3496 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3497 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3499 /* DDraw is in exclusive mode now. */
3500 memset(&ddsd, 0, sizeof(ddsd));
3501 ddsd.dwSize = sizeof(ddsd);
3502 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
3503 ddsd.dwBackBufferCount = 1;
3504 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
3505 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3506 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3507 IDirectDrawSurface_Release(surface);
3509 /* Recover again, just to be sure. */
3510 activateapp_testdata.ddraw = NULL;
3511 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3512 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3513 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3514 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3516 DestroyWindow(window);
3517 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3518 IDirectDraw_Release(ddraw);
3521 struct format_support_check
3523 const DDPIXELFORMAT *format;
3524 BOOL supported;
3527 static HRESULT WINAPI test_unsupported_formats_cb(DDSURFACEDESC *desc, void *ctx)
3529 struct format_support_check *format = ctx;
3531 if (!memcmp(format->format, &desc->ddpfPixelFormat, sizeof(*format->format)))
3533 format->supported = TRUE;
3534 return DDENUMRET_CANCEL;
3537 return DDENUMRET_OK;
3540 static void test_unsupported_formats(void)
3542 HRESULT hr;
3543 BOOL expect_success;
3544 HWND window;
3545 IDirectDraw *ddraw;
3546 IDirect3DDevice *device;
3547 IDirectDrawSurface *surface;
3548 DDSURFACEDESC ddsd;
3549 unsigned int i, j;
3550 DWORD expected_caps;
3551 static const struct
3553 const char *name;
3554 DDPIXELFORMAT fmt;
3556 formats[] =
3559 "D3DFMT_A8R8G8B8",
3561 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3562 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
3566 "D3DFMT_P8",
3568 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
3569 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3573 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
3575 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3576 0, 0, 640, 480, 0, 0, 0, 0);
3577 ddraw = create_ddraw();
3578 ok(!!ddraw, "Failed to create a ddraw object.\n");
3579 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3581 skip("Failed to create a 3D device, skipping test.\n");
3582 IDirectDraw_Release(ddraw);
3583 DestroyWindow(window);
3584 return;
3587 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
3589 struct format_support_check check = {&formats[i].fmt, FALSE};
3590 hr = IDirect3DDevice_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
3591 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
3593 for (j = 0; j < sizeof(caps) / sizeof(*caps); j++)
3595 memset(&ddsd, 0, sizeof(ddsd));
3596 ddsd.dwSize = sizeof(ddsd);
3597 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
3598 ddsd.ddpfPixelFormat = formats[i].fmt;
3599 ddsd.dwWidth = 4;
3600 ddsd.dwHeight = 4;
3601 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
3603 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
3604 expect_success = FALSE;
3605 else
3606 expect_success = TRUE;
3608 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3609 ok(SUCCEEDED(hr) == expect_success,
3610 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
3611 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
3612 if (FAILED(hr))
3613 continue;
3615 memset(&ddsd, 0, sizeof(ddsd));
3616 ddsd.dwSize = sizeof(ddsd);
3617 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
3618 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3620 if (caps[j] & DDSCAPS_VIDEOMEMORY)
3621 expected_caps = DDSCAPS_VIDEOMEMORY;
3622 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
3623 expected_caps = DDSCAPS_SYSTEMMEMORY;
3624 else if (check.supported)
3625 expected_caps = DDSCAPS_VIDEOMEMORY;
3626 else
3627 expected_caps = DDSCAPS_SYSTEMMEMORY;
3629 ok(ddsd.ddsCaps.dwCaps & expected_caps,
3630 "Expected capability %#x, format %s, input cap %#x.\n",
3631 expected_caps, formats[i].name, caps[j]);
3633 IDirectDrawSurface_Release(surface);
3637 IDirect3DDevice_Release(device);
3638 IDirectDraw_Release(ddraw);
3639 DestroyWindow(window);
3642 static void test_rt_caps(void)
3644 PALETTEENTRY palette_entries[256];
3645 IDirectDrawPalette *palette;
3646 IDirect3DDevice *device;
3647 IDirectDraw *ddraw;
3648 DWORD z_depth = 0;
3649 unsigned int i;
3650 ULONG refcount;
3651 HWND window;
3652 HRESULT hr;
3654 static const DDPIXELFORMAT p8_fmt =
3656 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
3657 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
3660 static const struct
3662 const DDPIXELFORMAT *pf;
3663 DWORD caps_in;
3664 DWORD caps_out;
3665 HRESULT create_device_hr;
3666 BOOL create_may_fail;
3668 test_data[] =
3671 NULL,
3672 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
3673 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3674 D3D_OK,
3675 FALSE,
3678 NULL,
3679 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3680 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3681 D3D_OK,
3682 FALSE,
3685 NULL,
3686 DDSCAPS_OFFSCREENPLAIN,
3687 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3688 DDERR_INVALIDCAPS,
3689 FALSE,
3692 NULL,
3693 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3694 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3695 D3DERR_SURFACENOTINVIDMEM,
3696 FALSE,
3699 NULL,
3700 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3701 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3702 DDERR_INVALIDCAPS,
3703 FALSE,
3706 NULL,
3707 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
3708 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3709 D3D_OK,
3710 FALSE,
3713 NULL,
3714 DDSCAPS_3DDEVICE,
3715 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3716 D3D_OK,
3717 FALSE,
3720 NULL,
3722 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3723 DDERR_INVALIDCAPS,
3724 FALSE,
3727 NULL,
3728 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3729 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3730 D3DERR_SURFACENOTINVIDMEM,
3731 FALSE,
3734 NULL,
3735 DDSCAPS_SYSTEMMEMORY,
3736 DDSCAPS_SYSTEMMEMORY,
3737 DDERR_INVALIDCAPS,
3738 FALSE,
3741 &p8_fmt,
3743 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3744 DDERR_INVALIDCAPS,
3745 FALSE,
3748 &p8_fmt,
3749 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3750 ~0U /* AMD r200 */ ,
3751 DDERR_NOPALETTEATTACHED,
3752 FALSE,
3755 &p8_fmt,
3756 DDSCAPS_OFFSCREENPLAIN,
3757 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3758 DDERR_INVALIDCAPS,
3759 FALSE,
3762 &p8_fmt,
3763 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3764 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3765 DDERR_NOPALETTEATTACHED,
3766 FALSE,
3769 &p8_fmt,
3770 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3771 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3772 DDERR_INVALIDCAPS,
3773 FALSE,
3776 NULL,
3777 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
3778 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
3779 DDERR_INVALIDCAPS,
3780 TRUE /* AMD Evergreen */,
3783 NULL,
3784 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3785 ~0U /* AMD Evergreen */,
3786 DDERR_INVALIDCAPS,
3787 FALSE,
3790 NULL,
3791 DDSCAPS_ZBUFFER,
3792 ~0U /* AMD Evergreen */,
3793 DDERR_INVALIDCAPS,
3794 FALSE,
3797 NULL,
3798 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3799 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3800 DDERR_INVALIDCAPS,
3801 TRUE /* Nvidia Kepler */,
3804 NULL,
3805 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
3806 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
3807 DDERR_INVALIDCAPS,
3808 TRUE /* Nvidia Kepler */,
3812 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3813 0, 0, 640, 480, 0, 0, 0, 0);
3814 ddraw = create_ddraw();
3815 ok(!!ddraw, "Failed to create a ddraw object.\n");
3816 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3818 skip("Failed to create a 3D device, skipping test.\n");
3819 IDirectDraw_Release(ddraw);
3820 DestroyWindow(window);
3821 return;
3823 z_depth = get_device_z_depth(device);
3824 ok(!!z_depth, "Failed to get device z depth.\n");
3825 IDirect3DDevice_Release(device);
3827 memset(palette_entries, 0, sizeof(palette_entries));
3828 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
3829 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
3831 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
3833 IDirectDrawSurface *surface;
3834 DDSURFACEDESC surface_desc;
3835 IDirect3DDevice *device;
3837 memset(&surface_desc, 0, sizeof(surface_desc));
3838 surface_desc.dwSize = sizeof(surface_desc);
3839 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3840 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
3841 if (test_data[i].pf)
3843 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
3844 surface_desc.ddpfPixelFormat = *test_data[i].pf;
3846 if (test_data[i].caps_in & DDSCAPS_ZBUFFER)
3848 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
3849 U2(surface_desc).dwZBufferBitDepth = z_depth;
3851 surface_desc.dwWidth = 640;
3852 surface_desc.dwHeight = 480;
3853 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
3854 ok(SUCCEEDED(hr) || broken(test_data[i].create_may_fail),
3855 "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
3856 i, test_data[i].caps_in, hr);
3857 if (FAILED(hr))
3858 continue;
3860 memset(&surface_desc, 0, sizeof(surface_desc));
3861 surface_desc.dwSize = sizeof(surface_desc);
3862 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
3863 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
3864 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
3865 "Test %u: Got unexpected caps %#x, expected %#x.\n",
3866 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
3868 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device);
3869 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
3870 i, hr, test_data[i].create_device_hr);
3871 if (hr == DDERR_NOPALETTEATTACHED)
3873 hr = IDirectDrawSurface_SetPalette(surface, palette);
3874 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
3875 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device);
3876 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
3877 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
3878 else
3879 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
3881 if (SUCCEEDED(hr))
3883 refcount = IDirect3DDevice_Release(device);
3884 ok(refcount == 1, "Test %u: Got unexpected refcount %u.\n", i, refcount);
3887 refcount = IDirectDrawSurface_Release(surface);
3888 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
3891 IDirectDrawPalette_Release(palette);
3892 refcount = IDirectDraw_Release(ddraw);
3893 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
3894 DestroyWindow(window);
3897 static void test_primary_caps(void)
3899 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
3900 IDirectDrawSurface *surface;
3901 DDSURFACEDESC surface_desc;
3902 IDirectDraw *ddraw;
3903 unsigned int i;
3904 ULONG refcount;
3905 HWND window;
3906 HRESULT hr;
3908 static const struct
3910 DWORD coop_level;
3911 DWORD caps_in;
3912 DWORD back_buffer_count;
3913 HRESULT hr;
3914 DWORD caps_out;
3916 test_data[] =
3919 DDSCL_NORMAL,
3920 DDSCAPS_PRIMARYSURFACE,
3921 ~0u,
3922 DD_OK,
3923 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
3926 DDSCL_NORMAL,
3927 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
3928 ~0u,
3929 DDERR_INVALIDCAPS,
3930 ~0u,
3933 DDSCL_NORMAL,
3934 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
3935 ~0u,
3936 DD_OK,
3937 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
3940 DDSCL_NORMAL,
3941 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
3942 ~0u,
3943 DDERR_INVALIDCAPS,
3944 ~0u,
3947 DDSCL_NORMAL,
3948 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
3949 ~0u,
3950 DDERR_INVALIDCAPS,
3951 ~0u,
3954 DDSCL_NORMAL,
3955 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
3956 ~0u,
3957 DDERR_INVALIDCAPS,
3958 ~0u,
3961 DDSCL_NORMAL,
3962 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3963 ~0u,
3964 DDERR_INVALIDCAPS,
3965 ~0u,
3968 DDSCL_NORMAL,
3969 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3971 DDERR_INVALIDCAPS,
3972 ~0u,
3975 DDSCL_NORMAL,
3976 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3978 DDERR_NOEXCLUSIVEMODE,
3979 ~0u,
3982 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3983 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3985 DDERR_INVALIDCAPS,
3986 ~0u,
3989 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3990 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3992 DD_OK,
3993 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
3996 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3997 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
3999 DDERR_INVALIDCAPS,
4000 ~0u,
4003 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4004 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
4006 DDERR_INVALIDCAPS,
4007 ~0u,
4011 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4012 0, 0, 640, 480, 0, 0, 0, 0);
4013 ddraw = create_ddraw();
4014 ok(!!ddraw, "Failed to create a ddraw object.\n");
4016 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
4018 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
4019 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4021 memset(&surface_desc, 0, sizeof(surface_desc));
4022 surface_desc.dwSize = sizeof(surface_desc);
4023 surface_desc.dwFlags = DDSD_CAPS;
4024 if (test_data[i].back_buffer_count != ~0u)
4025 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
4026 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
4027 surface_desc.dwBackBufferCount = test_data[i].back_buffer_count;
4028 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4029 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
4030 if (FAILED(hr))
4031 continue;
4033 memset(&surface_desc, 0, sizeof(surface_desc));
4034 surface_desc.dwSize = sizeof(surface_desc);
4035 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
4036 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
4037 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
4038 "Test %u: Got unexpected caps %#x, expected %#x.\n",
4039 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
4041 IDirectDrawSurface_Release(surface);
4044 refcount = IDirectDraw_Release(ddraw);
4045 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4046 DestroyWindow(window);
4049 static void test_surface_lock(void)
4051 IDirectDraw *ddraw;
4052 IDirectDrawSurface *surface;
4053 IDirect3DDevice *device;
4054 HRESULT hr;
4055 HWND window;
4056 unsigned int i;
4057 DDSURFACEDESC ddsd;
4058 ULONG refcount;
4059 DWORD z_depth = 0;
4060 static const struct
4062 DWORD caps;
4063 const char *name;
4065 tests[] =
4068 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
4069 "videomemory offscreenplain"
4072 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4073 "systemmemory offscreenplain"
4076 DDSCAPS_PRIMARYSURFACE,
4077 "primary"
4080 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
4081 "videomemory texture"
4084 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
4085 "systemmemory texture"
4088 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
4089 "render target"
4092 DDSCAPS_ZBUFFER,
4093 "Z buffer"
4097 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4098 0, 0, 640, 480, 0, 0, 0, 0);
4099 ddraw = create_ddraw();
4100 ok(!!ddraw, "Failed to create a ddraw object.\n");
4101 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4103 skip("Failed to create a 3D device, skipping test.\n");
4104 IDirectDraw_Release(ddraw);
4105 DestroyWindow(window);
4106 return;
4108 z_depth = get_device_z_depth(device);
4109 ok(!!z_depth, "Failed to get device z depth.\n");
4110 IDirect3DDevice_Release(device);
4112 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4114 memset(&ddsd, 0, sizeof(ddsd));
4115 ddsd.dwSize = sizeof(ddsd);
4116 ddsd.dwFlags = DDSD_CAPS;
4117 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
4119 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
4120 ddsd.dwWidth = 64;
4121 ddsd.dwHeight = 64;
4123 if (tests[i].caps & DDSCAPS_ZBUFFER)
4125 ddsd.dwFlags |= DDSD_ZBUFFERBITDEPTH;
4126 U2(ddsd).dwZBufferBitDepth = z_depth;
4128 ddsd.ddsCaps.dwCaps = tests[i].caps;
4130 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4131 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
4133 memset(&ddsd, 0, sizeof(ddsd));
4134 ddsd.dwSize = sizeof(ddsd);
4135 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
4136 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
4137 if (SUCCEEDED(hr))
4139 hr = IDirectDrawSurface_Unlock(surface, NULL);
4140 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
4143 memset(&ddsd, 0, sizeof(ddsd));
4144 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
4145 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, tests[i].name);
4147 IDirectDrawSurface_Release(surface);
4150 refcount = IDirectDraw_Release(ddraw);
4151 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4152 DestroyWindow(window);
4155 static void test_surface_discard(void)
4157 IDirectDraw *ddraw;
4158 IDirect3DDevice *device;
4159 HRESULT hr;
4160 HWND window;
4161 DDSURFACEDESC ddsd;
4162 IDirectDrawSurface *surface, *target;
4163 void *addr;
4164 static const struct
4166 DWORD caps;
4167 BOOL discard;
4169 tests[] =
4171 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, TRUE},
4172 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, FALSE},
4173 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, TRUE},
4174 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, FALSE},
4176 unsigned int i;
4178 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4179 0, 0, 640, 480, 0, 0, 0, 0);
4180 ddraw = create_ddraw();
4181 ok(!!ddraw, "Failed to create a ddraw object.\n");
4182 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4184 skip("Failed to create a 3D device, skipping test.\n");
4185 IDirectDraw_Release(ddraw);
4186 DestroyWindow(window);
4187 return;
4190 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&target);
4191 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4193 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4195 BOOL discarded;
4197 memset(&ddsd, 0, sizeof(ddsd));
4198 ddsd.dwSize = sizeof(ddsd);
4199 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4200 ddsd.ddsCaps.dwCaps = tests[i].caps;
4201 ddsd.dwWidth = 64;
4202 ddsd.dwHeight = 64;
4203 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4204 if (FAILED(hr))
4206 skip("Failed to create surface, skipping.\n");
4207 continue;
4210 memset(&ddsd, 0, sizeof(ddsd));
4211 ddsd.dwSize = sizeof(ddsd);
4212 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
4213 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4214 addr = ddsd.lpSurface;
4215 hr = IDirectDrawSurface_Unlock(surface, NULL);
4216 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4218 memset(&ddsd, 0, sizeof(ddsd));
4219 ddsd.dwSize = sizeof(ddsd);
4220 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
4221 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4222 discarded = ddsd.lpSurface != addr;
4223 hr = IDirectDrawSurface_Unlock(surface, NULL);
4224 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4226 hr = IDirectDrawSurface_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
4227 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
4229 memset(&ddsd, 0, sizeof(ddsd));
4230 ddsd.dwSize = sizeof(ddsd);
4231 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
4232 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4233 discarded |= ddsd.lpSurface != addr;
4234 hr = IDirectDrawSurface_Unlock(surface, NULL);
4235 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4237 IDirectDrawSurface_Release(surface);
4239 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
4240 * AMD r500, evergreen). Windows XP, at least on AMD r200, never changes the pointer. */
4241 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
4244 IDirectDrawSurface_Release(target);
4245 IDirect3DDevice_Release(device);
4246 IDirectDraw_Release(ddraw);
4247 DestroyWindow(window);
4250 static void test_flip(void)
4252 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
4253 IDirectDrawSurface *frontbuffer, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
4254 DDSCAPS caps = {DDSCAPS_FLIP};
4255 DDSURFACEDESC surface_desc;
4256 BOOL sysmem_primary;
4257 IDirectDraw *ddraw;
4258 DWORD expected_caps;
4259 unsigned int i;
4260 D3DCOLOR color;
4261 ULONG refcount;
4262 HWND window;
4263 DDBLTFX fx;
4264 HRESULT hr;
4266 static const struct
4268 const char *name;
4269 DWORD caps;
4271 test_data[] =
4273 {"PRIMARYSURFACE", DDSCAPS_PRIMARYSURFACE},
4274 {"OFFSCREENPLAIN", DDSCAPS_OFFSCREENPLAIN},
4275 {"TEXTURE", DDSCAPS_TEXTURE},
4278 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4279 0, 0, 640, 480, 0, 0, 0, 0);
4280 ddraw = create_ddraw();
4281 ok(!!ddraw, "Failed to create a ddraw object.\n");
4283 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4284 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4286 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
4288 /* Creating a flippable texture induces a BSoD on some versions of the
4289 * Intel graphics driver. At least Intel GMA 950 with driver version
4290 * 6.14.10.4926 on Windows XP SP3 is affected. */
4291 if ((test_data[i].caps & DDSCAPS_TEXTURE) && ddraw_is_intel(ddraw))
4293 win_skip("Skipping flippable texture test.\n");
4294 continue;
4297 memset(&surface_desc, 0, sizeof(surface_desc));
4298 surface_desc.dwSize = sizeof(surface_desc);
4299 surface_desc.dwFlags = DDSD_CAPS;
4300 if (!(test_data[i].caps & DDSCAPS_PRIMARYSURFACE))
4301 surface_desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
4302 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
4303 surface_desc.dwWidth = 512;
4304 surface_desc.dwHeight = 512;
4305 surface_desc.dwBackBufferCount = 3;
4306 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
4307 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4309 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
4310 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
4311 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
4312 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4314 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
4315 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
4316 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
4317 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4319 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
4320 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
4321 todo_wine_if(test_data[i].caps & DDSCAPS_TEXTURE)
4322 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
4323 if (FAILED(hr))
4324 continue;
4326 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
4327 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
4328 hr = IDirectDrawSurface_IsLost(frontbuffer);
4329 ok(hr == DD_OK, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4330 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
4331 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
4332 ok(hr == DDERR_NOEXCLUSIVEMODE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4333 else
4334 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
4335 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4336 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
4337 hr = IDirectDrawSurface_IsLost(frontbuffer);
4338 todo_wine ok(hr == DDERR_SURFACELOST, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4339 hr = restore_surfaces(ddraw);
4340 ok(SUCCEEDED(hr), "%s: Failed to restore surfaces, hr %#x.\n", test_data[i].name, hr);
4342 memset(&surface_desc, 0, sizeof(surface_desc));
4343 surface_desc.dwSize = sizeof(surface_desc);
4344 hr = IDirectDrawSurface_GetSurfaceDesc(frontbuffer, &surface_desc);
4345 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
4346 expected_caps = DDSCAPS_FRONTBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
4347 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
4348 expected_caps |= DDSCAPS_VISIBLE;
4349 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
4350 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
4351 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
4353 hr = IDirectDrawSurface_GetAttachedSurface(frontbuffer, &caps, &backbuffer1);
4354 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
4355 memset(&surface_desc, 0, sizeof(surface_desc));
4356 surface_desc.dwSize = sizeof(surface_desc);
4357 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer1, &surface_desc);
4358 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
4359 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
4360 test_data[i].name, surface_desc.dwBackBufferCount);
4361 expected_caps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER);
4362 expected_caps |= DDSCAPS_BACKBUFFER;
4363 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
4364 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
4366 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
4367 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
4368 memset(&surface_desc, 0, sizeof(surface_desc));
4369 surface_desc.dwSize = sizeof(surface_desc);
4370 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer2, &surface_desc);
4371 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
4372 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
4373 test_data[i].name, surface_desc.dwBackBufferCount);
4374 expected_caps &= ~DDSCAPS_BACKBUFFER;
4375 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
4376 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
4378 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
4379 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
4380 memset(&surface_desc, 0, sizeof(surface_desc));
4381 surface_desc.dwSize = sizeof(surface_desc);
4382 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer3, &surface_desc);
4383 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
4384 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
4385 test_data[i].name, surface_desc.dwBackBufferCount);
4386 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
4387 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
4389 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer3, &caps, &surface);
4390 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
4391 ok(surface == frontbuffer, "%s: Got unexpected surface %p, expected %p.\n",
4392 test_data[i].name, surface, frontbuffer);
4393 IDirectDrawSurface_Release(surface);
4395 memset(&surface_desc, 0, sizeof(surface_desc));
4396 surface_desc.dwSize = sizeof(surface_desc);
4397 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4398 surface_desc.ddsCaps.dwCaps = 0;
4399 surface_desc.dwWidth = 640;
4400 surface_desc.dwHeight = 480;
4401 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4402 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
4403 hr = IDirectDrawSurface_Flip(frontbuffer, surface, DDFLIP_WAIT);
4404 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4405 IDirectDrawSurface_Release(surface);
4407 hr = IDirectDrawSurface_Flip(frontbuffer, frontbuffer, DDFLIP_WAIT);
4408 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4409 hr = IDirectDrawSurface_Flip(backbuffer1, NULL, DDFLIP_WAIT);
4410 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4411 hr = IDirectDrawSurface_Flip(backbuffer2, NULL, DDFLIP_WAIT);
4412 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4413 hr = IDirectDrawSurface_Flip(backbuffer3, NULL, DDFLIP_WAIT);
4414 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4416 memset(&fx, 0, sizeof(fx));
4417 fx.dwSize = sizeof(fx);
4418 U5(fx).dwFillColor = 0xffff0000;
4419 hr = IDirectDrawSurface_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4420 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4421 U5(fx).dwFillColor = 0xff00ff00;
4422 hr = IDirectDrawSurface_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4423 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4424 U5(fx).dwFillColor = 0xff0000ff;
4425 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4426 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4428 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
4429 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
4430 color = get_surface_color(backbuffer1, 320, 240);
4431 /* The testbot seems to just copy the contents of one surface to all the
4432 * others, instead of properly flipping. */
4433 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
4434 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4435 color = get_surface_color(backbuffer2, 320, 240);
4436 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4437 U5(fx).dwFillColor = 0xffff0000;
4438 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4439 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4441 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
4442 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
4443 color = get_surface_color(backbuffer1, 320, 240);
4444 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
4445 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4446 color = get_surface_color(backbuffer2, 320, 240);
4447 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4448 U5(fx).dwFillColor = 0xff00ff00;
4449 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4450 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4452 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
4453 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
4454 color = get_surface_color(backbuffer1, 320, 240);
4455 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
4456 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4457 color = get_surface_color(backbuffer2, 320, 240);
4458 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4459 U5(fx).dwFillColor = 0xff0000ff;
4460 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4461 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4463 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer1, DDFLIP_WAIT);
4464 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
4465 color = get_surface_color(backbuffer2, 320, 240);
4466 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
4467 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4468 color = get_surface_color(backbuffer3, 320, 240);
4469 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4470 U5(fx).dwFillColor = 0xffff0000;
4471 hr = IDirectDrawSurface_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4472 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4474 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer2, DDFLIP_WAIT);
4475 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
4476 color = get_surface_color(backbuffer1, 320, 240);
4477 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4478 color = get_surface_color(backbuffer3, 320, 240);
4479 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
4480 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4481 U5(fx).dwFillColor = 0xff00ff00;
4482 hr = IDirectDrawSurface_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4483 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4485 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer3, DDFLIP_WAIT);
4486 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
4487 color = get_surface_color(backbuffer1, 320, 240);
4488 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
4489 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4490 color = get_surface_color(backbuffer2, 320, 240);
4491 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4493 IDirectDrawSurface_Release(backbuffer3);
4494 IDirectDrawSurface_Release(backbuffer2);
4495 IDirectDrawSurface_Release(backbuffer1);
4496 IDirectDrawSurface_Release(frontbuffer);
4499 refcount = IDirectDraw_Release(ddraw);
4500 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4501 DestroyWindow(window);
4504 static void test_sysmem_overlay(void)
4506 IDirectDraw *ddraw;
4507 HWND window;
4508 HRESULT hr;
4509 DDSURFACEDESC ddsd;
4510 IDirectDrawSurface *surface;
4511 ULONG ref;
4513 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4514 0, 0, 640, 480, 0, 0, 0, 0);
4515 ddraw = create_ddraw();
4516 ok(!!ddraw, "Failed to create a ddraw object.\n");
4518 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4519 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4521 memset(&ddsd, 0, sizeof(ddsd));
4522 ddsd.dwSize = sizeof(ddsd);
4523 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
4524 ddsd.dwWidth = 16;
4525 ddsd.dwHeight = 16;
4526 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
4527 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4528 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
4529 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
4530 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4531 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4532 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4533 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4534 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
4536 ref = IDirectDraw_Release(ddraw);
4537 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
4538 DestroyWindow(window);
4541 static void test_primary_palette(void)
4543 DDSCAPS surface_caps = {DDSCAPS_FLIP};
4544 IDirectDrawSurface *primary, *backbuffer;
4545 PALETTEENTRY palette_entries[256];
4546 IDirectDrawPalette *palette, *tmp;
4547 DDSURFACEDESC surface_desc;
4548 IDirectDraw *ddraw;
4549 DWORD palette_caps;
4550 ULONG refcount;
4551 HWND window;
4552 HRESULT hr;
4554 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4555 0, 0, 640, 480, 0, 0, 0, 0);
4556 ddraw = create_ddraw();
4557 ok(!!ddraw, "Failed to create a ddraw object.\n");
4558 if (FAILED(IDirectDraw_SetDisplayMode(ddraw, 640, 480, 8)))
4560 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
4561 IDirectDraw_Release(ddraw);
4562 DestroyWindow(window);
4563 return;
4565 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4566 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4568 memset(&surface_desc, 0, sizeof(surface_desc));
4569 surface_desc.dwSize = sizeof(surface_desc);
4570 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
4571 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
4572 surface_desc.dwBackBufferCount = 1;
4573 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
4574 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4575 hr = IDirectDrawSurface_GetAttachedSurface(primary, &surface_caps, &backbuffer);
4576 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
4578 memset(palette_entries, 0, sizeof(palette_entries));
4579 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
4580 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
4581 refcount = get_refcount((IUnknown *)palette);
4582 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4584 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
4585 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
4586 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
4588 hr = IDirectDrawSurface_SetPalette(primary, palette);
4589 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
4591 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
4592 * and is generally somewhat broken with respect to 8 bpp / palette
4593 * handling. */
4594 if (SUCCEEDED(IDirectDrawSurface_GetPalette(backbuffer, &tmp)))
4596 win_skip("Broken palette handling detected, skipping tests.\n");
4597 IDirectDrawPalette_Release(tmp);
4598 IDirectDrawPalette_Release(palette);
4599 /* The Windows 8 testbot keeps extra references to the primary and
4600 * backbuffer while in 8 bpp mode. */
4601 hr = IDirectDraw_RestoreDisplayMode(ddraw);
4602 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
4603 goto done;
4606 refcount = get_refcount((IUnknown *)palette);
4607 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4609 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
4610 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
4611 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
4612 "Got unexpected palette caps %#x.\n", palette_caps);
4614 hr = IDirectDrawSurface_SetPalette(primary, NULL);
4615 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
4616 refcount = get_refcount((IUnknown *)palette);
4617 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4619 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
4620 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
4621 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
4623 hr = IDirectDrawSurface_SetPalette(primary, palette);
4624 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
4625 refcount = get_refcount((IUnknown *)palette);
4626 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4628 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
4629 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
4630 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
4631 IDirectDrawPalette_Release(tmp);
4632 hr = IDirectDrawSurface_GetPalette(backbuffer, &tmp);
4633 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
4635 refcount = IDirectDrawPalette_Release(palette);
4636 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4637 refcount = IDirectDrawPalette_Release(palette);
4638 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4640 /* Note that this only seems to work when the palette is attached to the
4641 * primary surface. When attached to a regular surface, attempting to get
4642 * the palette here will cause an access violation. */
4643 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
4644 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
4646 hr = IDirectDrawSurface_IsLost(primary);
4647 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
4649 memset(&surface_desc, 0, sizeof(surface_desc));
4650 surface_desc.dwSize = sizeof(surface_desc);
4651 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
4652 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4653 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
4654 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
4655 ok(U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == 8, "Got unexpected bit count %u.\n",
4656 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
4658 hr = set_display_mode(ddraw, 640, 480);
4659 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
4661 memset(&surface_desc, 0, sizeof(surface_desc));
4662 surface_desc.dwSize = sizeof(surface_desc);
4663 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
4664 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4665 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
4666 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
4667 ok(U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == 32
4668 || U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == 24,
4669 "Got unexpected bit count %u.\n", U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
4671 hr = IDirectDrawSurface_IsLost(primary);
4672 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
4673 hr = IDirectDrawSurface_Restore(primary);
4674 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
4675 hr = IDirectDrawSurface_IsLost(primary);
4676 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
4678 memset(&surface_desc, 0, sizeof(surface_desc));
4679 surface_desc.dwSize = sizeof(surface_desc);
4680 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
4681 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4682 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
4683 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
4684 ok(U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == 32
4685 || U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == 24,
4686 "Got unexpected bit count %u.\n", U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
4688 done:
4689 refcount = IDirectDrawSurface_Release(backbuffer);
4690 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4691 refcount = IDirectDrawSurface_Release(primary);
4692 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4693 refcount = IDirectDraw_Release(ddraw);
4694 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4695 DestroyWindow(window);
4698 static HRESULT WINAPI surface_counter(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
4700 UINT *surface_count = context;
4702 ++(*surface_count);
4703 IDirectDrawSurface_Release(surface);
4705 return DDENUMRET_OK;
4708 static void test_surface_attachment(void)
4710 IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
4711 DDSCAPS caps = {DDSCAPS_TEXTURE};
4712 DDSURFACEDESC surface_desc;
4713 IDirectDraw *ddraw;
4714 UINT surface_count;
4715 ULONG refcount;
4716 HWND window;
4717 HRESULT hr;
4719 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4720 0, 0, 640, 480, 0, 0, 0, 0);
4721 ddraw = create_ddraw();
4722 ok(!!ddraw, "Failed to create a ddraw object.\n");
4723 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4724 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4726 memset(&surface_desc, 0, sizeof(surface_desc));
4727 surface_desc.dwSize = sizeof(surface_desc);
4728 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
4729 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
4730 U2(surface_desc).dwMipMapCount = 3;
4731 surface_desc.dwWidth = 128;
4732 surface_desc.dwHeight = 128;
4733 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
4734 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4736 hr = IDirectDrawSurface_GetAttachedSurface(surface1, &caps, &surface2);
4737 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
4738 hr = IDirectDrawSurface_GetAttachedSurface(surface2, &caps, &surface3);
4739 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
4740 hr = IDirectDrawSurface_GetAttachedSurface(surface3, &caps, &surface4);
4741 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
4743 surface_count = 0;
4744 IDirectDrawSurface_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
4745 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
4746 surface_count = 0;
4747 IDirectDrawSurface_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
4748 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
4749 surface_count = 0;
4750 IDirectDrawSurface_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
4751 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
4753 memset(&surface_desc, 0, sizeof(surface_desc));
4754 surface_desc.dwSize = sizeof(surface_desc);
4755 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4756 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
4757 surface_desc.dwWidth = 16;
4758 surface_desc.dwHeight = 16;
4759 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
4760 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4762 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
4763 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4764 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
4765 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4766 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
4767 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4768 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
4769 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4770 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
4771 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4772 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
4773 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4775 IDirectDrawSurface_Release(surface4);
4777 memset(&surface_desc, 0, sizeof(surface_desc));
4778 surface_desc.dwSize = sizeof(surface_desc);
4779 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4780 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
4781 surface_desc.dwWidth = 16;
4782 surface_desc.dwHeight = 16;
4783 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
4784 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4786 if (SUCCEEDED(hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4)))
4788 skip("Running on refrast, skipping some tests.\n");
4789 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface4);
4790 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4792 else
4794 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4795 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
4796 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4797 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
4798 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4799 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
4800 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4801 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
4802 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4803 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
4804 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4807 IDirectDrawSurface_Release(surface4);
4808 IDirectDrawSurface_Release(surface3);
4809 IDirectDrawSurface_Release(surface2);
4810 IDirectDrawSurface_Release(surface1);
4812 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4813 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4815 /* Try a single primary and two offscreen plain surfaces. */
4816 memset(&surface_desc, 0, sizeof(surface_desc));
4817 surface_desc.dwSize = sizeof(surface_desc);
4818 surface_desc.dwFlags = DDSD_CAPS;
4819 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4820 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
4821 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4823 memset(&surface_desc, 0, sizeof(surface_desc));
4824 surface_desc.dwSize = sizeof(surface_desc);
4825 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4826 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4827 surface_desc.dwWidth = registry_mode.dmPelsWidth;
4828 surface_desc.dwHeight = registry_mode.dmPelsHeight;
4829 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
4830 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4832 memset(&surface_desc, 0, sizeof(surface_desc));
4833 surface_desc.dwSize = sizeof(surface_desc);
4834 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4835 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4836 surface_desc.dwWidth = registry_mode.dmPelsWidth;
4837 surface_desc.dwHeight = registry_mode.dmPelsHeight;
4838 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
4839 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4841 /* This one has a different size. */
4842 memset(&surface_desc, 0, sizeof(surface_desc));
4843 surface_desc.dwSize = sizeof(surface_desc);
4844 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4845 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4846 surface_desc.dwWidth = 128;
4847 surface_desc.dwHeight = 128;
4848 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
4849 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4851 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4852 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4853 /* Try the reverse without detaching first. */
4854 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
4855 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
4856 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
4857 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4859 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
4860 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4861 /* Try to detach reversed. */
4862 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
4863 ok(hr == DDERR_CANNOTDETACHSURFACE, "Got unexpected hr %#x.\n", hr);
4864 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
4865 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4867 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
4868 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4869 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
4870 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4872 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
4873 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4874 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
4875 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4877 IDirectDrawSurface_Release(surface4);
4878 IDirectDrawSurface_Release(surface3);
4879 IDirectDrawSurface_Release(surface2);
4880 IDirectDrawSurface_Release(surface1);
4882 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
4883 memset(&surface_desc, 0, sizeof(surface_desc));
4884 surface_desc.dwSize = sizeof(surface_desc);
4885 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4886 surface_desc.dwWidth = 64;
4887 surface_desc.dwHeight = 64;
4888 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
4889 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
4890 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
4891 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
4892 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xf800;
4893 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x07e0;
4894 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x001f;
4895 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
4896 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4897 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
4898 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4900 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
4901 surface_desc.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
4902 U1(surface_desc.ddpfPixelFormat).dwZBufferBitDepth = 16;
4903 U3(surface_desc.ddpfPixelFormat).dwZBitMask = 0x0000ffff;
4904 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
4905 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4907 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4908 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4909 refcount = get_refcount((IUnknown *)surface2);
4910 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4911 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4912 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
4914 /* Attaching while already attached to other surface. */
4915 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface2);
4916 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4917 hr = IDirectDrawSurface_DeleteAttachedSurface(surface3, 0, surface2);
4918 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4919 IDirectDrawSurface_Release(surface3);
4921 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
4922 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4923 refcount = get_refcount((IUnknown *)surface2);
4924 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4926 /* Automatic detachment on release. */
4927 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4928 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4929 refcount = get_refcount((IUnknown *)surface2);
4930 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4931 refcount = IDirectDrawSurface_Release(surface1);
4932 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4933 refcount = IDirectDrawSurface_Release(surface2);
4934 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4935 refcount = IDirectDraw_Release(ddraw);
4936 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4937 DestroyWindow(window);
4940 static void test_pixel_format(void)
4942 HWND window, window2 = NULL;
4943 HDC hdc, hdc2 = NULL;
4944 HMODULE gl = NULL;
4945 int format, test_format;
4946 PIXELFORMATDESCRIPTOR pfd;
4947 IDirectDraw *ddraw = NULL;
4948 IDirectDrawClipper *clipper = NULL;
4949 DDSURFACEDESC ddsd;
4950 IDirectDrawSurface *primary = NULL;
4951 DDBLTFX fx;
4952 HRESULT hr;
4954 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4955 100, 100, 160, 160, NULL, NULL, NULL, NULL);
4956 if (!window)
4958 skip("Failed to create window\n");
4959 return;
4962 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4963 100, 100, 160, 160, NULL, NULL, NULL, NULL);
4965 hdc = GetDC(window);
4966 if (!hdc)
4968 skip("Failed to get DC\n");
4969 goto cleanup;
4972 if (window2)
4973 hdc2 = GetDC(window2);
4975 gl = LoadLibraryA("opengl32.dll");
4976 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
4978 format = GetPixelFormat(hdc);
4979 ok(format == 0, "new window has pixel format %d\n", format);
4981 ZeroMemory(&pfd, sizeof(pfd));
4982 pfd.nSize = sizeof(pfd);
4983 pfd.nVersion = 1;
4984 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
4985 pfd.iPixelType = PFD_TYPE_RGBA;
4986 pfd.iLayerType = PFD_MAIN_PLANE;
4987 format = ChoosePixelFormat(hdc, &pfd);
4988 if (format <= 0)
4990 skip("no pixel format available\n");
4991 goto cleanup;
4994 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
4996 skip("failed to set pixel format\n");
4997 goto cleanup;
5000 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
5002 skip("failed to set pixel format on second window\n");
5003 if (hdc2)
5005 ReleaseDC(window2, hdc2);
5006 hdc2 = NULL;
5010 ddraw = create_ddraw();
5011 ok(!!ddraw, "Failed to create a ddraw object.\n");
5013 test_format = GetPixelFormat(hdc);
5014 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5016 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5017 if (FAILED(hr))
5019 skip("Failed to set cooperative level, hr %#x.\n", hr);
5020 goto cleanup;
5023 test_format = GetPixelFormat(hdc);
5024 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5026 if (hdc2)
5028 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
5029 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
5030 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
5031 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
5033 test_format = GetPixelFormat(hdc);
5034 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5036 test_format = GetPixelFormat(hdc2);
5037 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
5040 memset(&ddsd, 0, sizeof(ddsd));
5041 ddsd.dwSize = sizeof(ddsd);
5042 ddsd.dwFlags = DDSD_CAPS;
5043 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
5045 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
5046 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
5048 test_format = GetPixelFormat(hdc);
5049 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5051 if (hdc2)
5053 test_format = GetPixelFormat(hdc2);
5054 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
5057 if (clipper)
5059 hr = IDirectDrawSurface_SetClipper(primary, clipper);
5060 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
5062 test_format = GetPixelFormat(hdc);
5063 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5065 test_format = GetPixelFormat(hdc2);
5066 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
5069 memset(&fx, 0, sizeof(fx));
5070 fx.dwSize = sizeof(fx);
5071 hr = IDirectDrawSurface_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5072 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
5074 test_format = GetPixelFormat(hdc);
5075 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5077 if (hdc2)
5079 test_format = GetPixelFormat(hdc2);
5080 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
5083 cleanup:
5084 if (primary) IDirectDrawSurface_Release(primary);
5085 if (clipper) IDirectDrawClipper_Release(clipper);
5086 if (ddraw) IDirectDraw_Release(ddraw);
5087 if (gl) FreeLibrary(gl);
5088 if (hdc) ReleaseDC(window, hdc);
5089 if (hdc2) ReleaseDC(window2, hdc2);
5090 if (window) DestroyWindow(window);
5091 if (window2) DestroyWindow(window2);
5094 static void test_create_surface_pitch(void)
5096 IDirectDrawSurface *surface;
5097 DDSURFACEDESC surface_desc;
5098 IDirectDraw *ddraw;
5099 unsigned int i;
5100 ULONG refcount;
5101 HWND window;
5102 HRESULT hr;
5103 void *mem;
5105 static const struct
5107 DWORD caps;
5108 DWORD flags_in;
5109 DWORD pitch_in;
5110 HRESULT hr;
5111 DWORD flags_out;
5112 DWORD pitch_out32;
5113 DWORD pitch_out64;
5115 test_data[] =
5117 /* 0 */
5118 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
5119 0, 0, DD_OK,
5120 DDSD_PITCH, 0x100, 0x100},
5121 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
5122 DDSD_PITCH, 0x104, DD_OK,
5123 DDSD_PITCH, 0x100, 0x100},
5124 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
5125 DDSD_PITCH, 0x0f8, DD_OK,
5126 DDSD_PITCH, 0x100, 0x100},
5127 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
5128 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
5129 0, 0, 0 },
5130 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
5131 0, 0, DD_OK,
5132 DDSD_PITCH, 0x100, 0x0fc},
5133 /* 5 */
5134 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
5135 DDSD_PITCH, 0x104, DD_OK,
5136 DDSD_PITCH, 0x100, 0x0fc},
5137 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
5138 DDSD_PITCH, 0x0f8, DD_OK,
5139 DDSD_PITCH, 0x100, 0x0fc},
5140 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
5141 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
5142 DDSD_PITCH, 0x100, 0x0fc},
5143 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
5144 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
5145 0, 0, 0 },
5146 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
5147 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDPARAMS,
5148 0, 0, 0 },
5149 /* 10 */
5150 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
5151 0, 0, DDERR_INVALIDCAPS,
5152 0, 0, 0 },
5153 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
5154 0, 0, DD_OK,
5155 DDSD_PITCH, 0x100, 0 },
5156 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
5157 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
5158 0, 0, 0 },
5159 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
5160 0, 0, DDERR_INVALIDCAPS,
5161 0, 0, 0 },
5162 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
5163 0, 0, DD_OK,
5164 DDSD_PITCH, 0x100, 0 },
5165 /* 15 */
5166 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
5167 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDPARAMS,
5168 0, 0, 0 },
5170 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
5172 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5173 0, 0, 640, 480, 0, 0, 0, 0);
5174 ddraw = create_ddraw();
5175 ok(!!ddraw, "Failed to create a ddraw object.\n");
5176 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5177 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5179 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
5181 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
5183 memset(&surface_desc, 0, sizeof(surface_desc));
5184 surface_desc.dwSize = sizeof(surface_desc);
5185 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
5186 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
5187 surface_desc.dwWidth = 63;
5188 surface_desc.dwHeight = 63;
5189 U1(surface_desc).lPitch = test_data[i].pitch_in;
5190 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
5191 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
5192 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
5193 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5194 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5195 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5196 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5197 if (test_data[i].flags_in & DDSD_LPSURFACE)
5199 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
5200 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, expected_hr);
5201 surface_desc.lpSurface = mem;
5202 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5204 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
5205 continue;
5206 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
5207 if (FAILED(hr))
5208 continue;
5210 memset(&surface_desc, 0, sizeof(surface_desc));
5211 surface_desc.dwSize = sizeof(surface_desc);
5212 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
5213 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5214 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
5215 "Test %u: Got unexpected flags %#x, expected %#x.\n",
5216 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
5217 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
5219 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
5220 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
5221 "Test %u: Got unexpected pitch %u, expected %u.\n",
5222 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
5223 else
5224 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
5225 "Test %u: Got unexpected pitch %u, expected %u.\n",
5226 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
5228 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
5230 IDirectDrawSurface_Release(surface);
5233 HeapFree(GetProcessHeap(), 0, mem);
5234 refcount = IDirectDraw_Release(ddraw);
5235 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5236 DestroyWindow(window);
5239 static void test_mipmap(void)
5241 IDirectDrawSurface *surface, *surface2;
5242 DDSURFACEDESC surface_desc;
5243 IDirectDraw *ddraw;
5244 unsigned int i;
5245 ULONG refcount;
5246 HWND window;
5247 HRESULT hr;
5248 DDSCAPS caps = {DDSCAPS_COMPLEX};
5249 DDCAPS hal_caps;
5251 static const struct
5253 DWORD flags;
5254 DWORD caps;
5255 DWORD width;
5256 DWORD height;
5257 DWORD mipmap_count_in;
5258 HRESULT hr;
5259 DWORD mipmap_count_out;
5261 tests[] =
5263 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
5264 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS, 0},
5265 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
5266 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS, 0},
5267 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 6},
5268 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 6},
5271 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5272 0, 0, 640, 480, 0, 0, 0, 0);
5273 ddraw = create_ddraw();
5274 ok(!!ddraw, "Failed to create a ddraw object.\n");
5275 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5276 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5278 memset(&hal_caps, 0, sizeof(hal_caps));
5279 hal_caps.dwSize = sizeof(hal_caps);
5280 hr = IDirectDraw_GetCaps(ddraw, &hal_caps, NULL);
5281 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5282 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
5284 skip("Mipmapped textures not supported, skipping tests.\n");
5285 IDirectDraw_Release(ddraw);
5286 DestroyWindow(window);
5287 return;
5290 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
5292 memset(&surface_desc, 0, sizeof(surface_desc));
5293 surface_desc.dwSize = sizeof(surface_desc);
5294 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
5295 surface_desc.ddsCaps.dwCaps = tests[i].caps;
5296 surface_desc.dwWidth = tests[i].width;
5297 surface_desc.dwHeight = tests[i].height;
5298 if (tests[i].flags & DDSD_MIPMAPCOUNT)
5299 U2(surface_desc).dwMipMapCount = tests[i].mipmap_count_in;
5300 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5301 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
5302 if (FAILED(hr))
5303 continue;
5305 memset(&surface_desc, 0, sizeof(surface_desc));
5306 surface_desc.dwSize = sizeof(surface_desc);
5307 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
5308 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5309 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
5310 "Test %u: Got unexpected flags %#x.\n", i, surface_desc.dwFlags);
5311 ok(U2(surface_desc).dwMipMapCount == tests[i].mipmap_count_out,
5312 "Test %u: Got unexpected mipmap count %u.\n", i, U2(surface_desc).dwMipMapCount);
5314 if (U2(surface_desc).dwMipMapCount > 1)
5316 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &surface2);
5317 ok(SUCCEEDED(hr), "Test %u: Failed to get attached surface, hr %#x.\n", i, hr);
5319 memset(&surface_desc, 0, sizeof(surface_desc));
5320 surface_desc.dwSize = sizeof(surface_desc);
5321 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, 0, NULL);
5322 ok(SUCCEEDED(hr), "Test %u: Failed to lock surface, hr %#x.\n", i, hr);
5323 memset(&surface_desc, 0, sizeof(surface_desc));
5324 surface_desc.dwSize = sizeof(surface_desc);
5325 hr = IDirectDrawSurface_Lock(surface2, NULL, &surface_desc, 0, NULL);
5326 ok(SUCCEEDED(hr), "Test %u: Failed to lock surface, hr %#x.\n", i, hr);
5327 IDirectDrawSurface_Unlock(surface2, NULL);
5328 IDirectDrawSurface_Unlock(surface, NULL);
5330 IDirectDrawSurface_Release(surface2);
5333 IDirectDrawSurface_Release(surface);
5336 refcount = IDirectDraw_Release(ddraw);
5337 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5338 DestroyWindow(window);
5341 static void test_palette_complex(void)
5343 IDirectDrawSurface *surface, *mipmap, *tmp;
5344 DDSURFACEDESC surface_desc;
5345 IDirectDraw *ddraw;
5346 IDirectDrawPalette *palette, *palette2, *palette_mipmap;
5347 ULONG refcount;
5348 HWND window;
5349 HRESULT hr;
5350 DDSCAPS caps = {DDSCAPS_COMPLEX};
5351 DDCAPS hal_caps;
5352 PALETTEENTRY palette_entries[256];
5353 unsigned int i;
5354 HDC dc;
5355 RGBQUAD rgbquad;
5356 UINT count;
5358 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5359 0, 0, 640, 480, 0, 0, 0, 0);
5360 ddraw = create_ddraw();
5361 ok(!!ddraw, "Failed to create a ddraw object.\n");
5362 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5363 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5365 memset(&hal_caps, 0, sizeof(hal_caps));
5366 hal_caps.dwSize = sizeof(hal_caps);
5367 hr = IDirectDraw_GetCaps(ddraw, &hal_caps, NULL);
5368 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5369 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
5371 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
5372 IDirectDraw_Release(ddraw);
5373 DestroyWindow(window);
5374 return;
5377 memset(&surface_desc, 0, sizeof(surface_desc));
5378 surface_desc.dwSize = sizeof(surface_desc);
5379 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5380 surface_desc.dwWidth = 128;
5381 surface_desc.dwHeight = 128;
5382 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
5383 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
5384 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
5385 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
5386 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5387 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5389 memset(palette_entries, 0, sizeof(palette_entries));
5390 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
5391 palette_entries, &palette, NULL);
5392 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5394 memset(palette_entries, 0, sizeof(palette_entries));
5395 palette_entries[1].peRed = 0xff;
5396 palette_entries[1].peGreen = 0x80;
5397 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
5398 palette_entries, &palette_mipmap, NULL);
5399 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5401 palette2 = (void *)0xdeadbeef;
5402 hr = IDirectDrawSurface_GetPalette(surface, &palette2);
5403 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
5404 ok(!palette2, "Got unexpected palette %p.\n", palette2);
5405 hr = IDirectDrawSurface_SetPalette(surface, palette);
5406 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5407 hr = IDirectDrawSurface_GetPalette(surface, &palette2);
5408 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
5409 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
5410 IDirectDrawPalette_Release(palette2);
5412 mipmap = surface;
5413 IDirectDrawSurface_AddRef(mipmap);
5414 for (i = 0; i < 7; ++i)
5416 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
5417 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
5418 palette2 = (void *)0xdeadbeef;
5419 hr = IDirectDrawSurface_GetPalette(tmp, &palette2);
5420 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
5421 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
5423 hr = IDirectDrawSurface_SetPalette(tmp, palette_mipmap);
5424 ok(SUCCEEDED(hr), "Failed to set palette, i %u, hr %#x.\n", i, hr);
5426 hr = IDirectDrawSurface_GetPalette(tmp, &palette2);
5427 ok(SUCCEEDED(hr), "Failed to get palette, i %u, hr %#x.\n", i, hr);
5428 ok(palette_mipmap == palette2, "Got unexpected palette %p.\n", palette2);
5429 IDirectDrawPalette_Release(palette2);
5431 hr = IDirectDrawSurface_GetDC(tmp, &dc);
5432 ok(SUCCEEDED(hr), "Failed to get DC, i %u, hr %#x.\n", i, hr);
5433 count = GetDIBColorTable(dc, 1, 1, &rgbquad);
5434 ok(count == 1, "Expected count 1, got %u.\n", count);
5435 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x.\n", rgbquad.rgbRed);
5436 ok(rgbquad.rgbGreen == 0x80, "Expected rgbGreen = 0x80, got %#x.\n", rgbquad.rgbGreen);
5437 ok(rgbquad.rgbBlue == 0x0, "Expected rgbBlue = 0x0, got %#x.\n", rgbquad.rgbBlue);
5438 hr = IDirectDrawSurface_ReleaseDC(tmp, dc);
5439 ok(SUCCEEDED(hr), "Failed to release DC, i %u, hr %#x.\n", i, hr);
5441 IDirectDrawSurface_Release(mipmap);
5442 mipmap = tmp;
5445 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
5446 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5447 IDirectDrawSurface_Release(mipmap);
5448 refcount = IDirectDrawSurface_Release(surface);
5449 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5450 refcount = IDirectDrawPalette_Release(palette_mipmap);
5451 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5452 refcount = IDirectDrawPalette_Release(palette);
5453 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5455 refcount = IDirectDraw_Release(ddraw);
5456 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5457 DestroyWindow(window);
5460 static void test_p8_blit(void)
5462 IDirectDrawSurface *src, *dst, *dst_p8;
5463 DDSURFACEDESC surface_desc;
5464 IDirectDraw *ddraw;
5465 IDirectDrawPalette *palette, *palette2;
5466 ULONG refcount;
5467 HWND window;
5468 HRESULT hr;
5469 PALETTEENTRY palette_entries[256];
5470 unsigned int x;
5471 DDBLTFX fx;
5472 BOOL is_warp;
5473 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
5474 static const BYTE src_data2[] = {0x10, 0x5, 0x4, 0x3, 0x2, 0x1, 0xff, 0x80};
5475 static const BYTE expected_p8[] = {0x10, 0x1, 0x4, 0x3, 0x4, 0x5, 0xff, 0x80};
5476 static const D3DCOLOR expected[] =
5478 0x00101010, 0x00010101, 0x00020202, 0x00030303,
5479 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
5481 D3DCOLOR color;
5483 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5484 0, 0, 640, 480, 0, 0, 0, 0);
5485 ddraw = create_ddraw();
5486 ok(!!ddraw, "Failed to create a ddraw object.\n");
5487 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5488 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5489 is_warp = ddraw_is_warp(ddraw);
5491 memset(palette_entries, 0, sizeof(palette_entries));
5492 palette_entries[1].peGreen = 0xff;
5493 palette_entries[2].peBlue = 0xff;
5494 palette_entries[3].peFlags = 0xff;
5495 palette_entries[4].peRed = 0xff;
5496 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
5497 palette_entries, &palette, NULL);
5498 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5499 palette_entries[1].peBlue = 0xff;
5500 palette_entries[2].peGreen = 0xff;
5501 palette_entries[3].peRed = 0xff;
5502 palette_entries[4].peFlags = 0x0;
5503 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
5504 palette_entries, &palette2, NULL);
5505 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5507 memset(&surface_desc, 0, sizeof(surface_desc));
5508 surface_desc.dwSize = sizeof(surface_desc);
5509 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5510 surface_desc.dwWidth = 8;
5511 surface_desc.dwHeight = 1;
5512 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5513 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
5514 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
5515 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
5516 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src, NULL);
5517 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5518 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst_p8, NULL);
5519 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5520 hr = IDirectDrawSurface_SetPalette(dst_p8, palette2);
5521 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5523 memset(&surface_desc, 0, sizeof(surface_desc));
5524 surface_desc.dwSize = sizeof(surface_desc);
5525 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5526 surface_desc.dwWidth = 8;
5527 surface_desc.dwHeight = 1;
5528 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5529 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
5530 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
5531 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
5532 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5533 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5534 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5535 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
5536 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst, NULL);
5537 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5539 memset(&surface_desc, 0, sizeof(surface_desc));
5540 surface_desc.dwSize = sizeof(surface_desc);
5541 hr = IDirectDrawSurface_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
5542 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
5543 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
5544 hr = IDirectDrawSurface_Unlock(src, NULL);
5545 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
5547 hr = IDirectDrawSurface_Lock(dst_p8, NULL, &surface_desc, DDLOCK_WAIT, NULL);
5548 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
5549 memcpy(surface_desc.lpSurface, src_data2, sizeof(src_data2));
5550 hr = IDirectDrawSurface_Unlock(dst_p8, NULL);
5551 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
5553 hr = IDirectDrawSurface_SetPalette(src, palette);
5554 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5555 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
5556 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
5557 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
5558 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
5559 "Failed to blit, hr %#x.\n", hr);
5561 if (SUCCEEDED(hr))
5563 for (x = 0; x < sizeof(expected) / sizeof(*expected); x++)
5565 color = get_surface_color(dst, x, 0);
5566 todo_wine ok(compare_color(color, expected[x], 0),
5567 "Pixel %u: Got color %#x, expected %#x.\n",
5568 x, color, expected[x]);
5572 memset(&fx, 0, sizeof(fx));
5573 fx.dwSize = sizeof(fx);
5574 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x2;
5575 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x2;
5576 hr = IDirectDrawSurface_Blt(dst_p8, NULL, src, NULL, DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &fx);
5577 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
5579 hr = IDirectDrawSurface_Lock(dst_p8, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
5580 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
5581 /* A color keyed P8 blit doesn't do anything on WARP - it just leaves the data in the destination
5582 * surface untouched. P8 blits without color keys work. Error checking (DDBLT_KEYSRC without a key
5583 * for example) also works as expected.
5585 * Using DDBLT_KEYSRC instead of DDBLT_KEYSRCOVERRIDE doesn't change this. Doing this blit with
5586 * the display mode set to P8 doesn't help either. */
5587 ok(!memcmp(surface_desc.lpSurface, expected_p8, sizeof(expected_p8))
5588 || broken(is_warp && !memcmp(surface_desc.lpSurface, src_data2, sizeof(src_data2))),
5589 "Got unexpected P8 color key blit result.\n");
5590 hr = IDirectDrawSurface_Unlock(dst_p8, NULL);
5591 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
5593 IDirectDrawSurface_Release(src);
5594 IDirectDrawSurface_Release(dst);
5595 IDirectDrawSurface_Release(dst_p8);
5596 IDirectDrawPalette_Release(palette);
5597 IDirectDrawPalette_Release(palette2);
5599 refcount = IDirectDraw_Release(ddraw);
5600 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5601 DestroyWindow(window);
5604 static void test_material(void)
5606 IDirect3DMaterial *background, *material;
5607 IDirect3DExecuteBuffer *execute_buffer;
5608 D3DMATERIALHANDLE mat_handle, tmp;
5609 D3DEXECUTEBUFFERDESC exec_desc;
5610 IDirect3DViewport *viewport;
5611 IDirect3DDevice *device;
5612 IDirectDrawSurface *rt;
5613 IDirectDraw *ddraw;
5614 UINT inst_length;
5615 D3DCOLOR color;
5616 ULONG refcount;
5617 unsigned int i;
5618 HWND window;
5619 HRESULT hr;
5620 BOOL valid;
5621 void *ptr;
5623 static D3DVERTEX quad[] =
5625 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
5626 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
5627 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
5628 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
5630 static const struct
5632 BOOL material;
5633 D3DCOLOR expected_color;
5635 test_data[] =
5637 {TRUE, 0x0000ff00},
5638 {FALSE, 0x00ffffff},
5640 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
5642 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5643 0, 0, 640, 480, 0, 0, 0, 0);
5644 ddraw = create_ddraw();
5645 ok(!!ddraw, "Failed to create a ddraw object.\n");
5646 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
5648 skip("Failed to create a 3D device, skipping test.\n");
5649 DestroyWindow(window);
5650 return;
5653 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
5654 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
5656 background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
5657 viewport = create_viewport(device, 0, 0, 640, 480);
5658 viewport_set_background(device, viewport, background);
5660 material = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
5661 hr = IDirect3DMaterial_GetHandle(material, device, &mat_handle);
5662 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
5664 memset(&exec_desc, 0, sizeof(exec_desc));
5665 exec_desc.dwSize = sizeof(exec_desc);
5666 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
5667 exec_desc.dwBufferSize = 1024;
5668 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
5670 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
5671 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
5673 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
5675 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
5676 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
5678 memcpy(exec_desc.lpData, quad, sizeof(quad));
5679 ptr = ((BYTE *)exec_desc.lpData) + sizeof(quad);
5680 emit_set_ls(&ptr, D3DLIGHTSTATE_MATERIAL, test_data[i].material ? mat_handle : 0);
5681 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORMLIGHT, 0, 4);
5682 emit_tquad(&ptr, 0);
5683 emit_end(&ptr);
5684 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
5685 inst_length -= sizeof(quad);
5687 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
5688 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
5690 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
5691 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
5693 hr = IDirect3DDevice_BeginScene(device);
5694 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5695 set_execute_data(execute_buffer, 4, sizeof(quad), inst_length);
5696 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
5697 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
5698 hr = IDirect3DDevice_EndScene(device);
5699 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5700 color = get_surface_color(rt, 320, 240);
5701 if (test_data[i].material)
5702 todo_wine ok(compare_color(color, test_data[i].expected_color, 1)
5703 /* The Windows 8 testbot appears to return undefined results. */
5704 || broken(TRUE),
5705 "Got unexpected color 0x%08x, test %u.\n", color, i);
5706 else
5707 ok(compare_color(color, test_data[i].expected_color, 1),
5708 "Got unexpected color 0x%08x, test %u.\n", color, i);
5711 destroy_material(material);
5712 material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
5713 hr = IDirect3DMaterial_GetHandle(material, device, &mat_handle);
5714 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
5716 hr = IDirect3DViewport_SetBackground(viewport, mat_handle);
5717 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
5718 hr = IDirect3DViewport_GetBackground(viewport, &tmp, &valid);
5719 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
5720 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
5721 ok(valid, "Got unexpected valid %#x.\n", valid);
5722 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
5723 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
5724 color = get_surface_color(rt, 320, 240);
5725 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
5727 hr = IDirect3DViewport_SetBackground(viewport, 0);
5728 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
5729 hr = IDirect3DViewport_GetBackground(viewport, &tmp, &valid);
5730 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
5731 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
5732 ok(valid, "Got unexpected valid %#x.\n", valid);
5733 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
5734 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
5735 color = get_surface_color(rt, 320, 240);
5736 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
5738 destroy_viewport(device, viewport);
5739 viewport = create_viewport(device, 0, 0, 640, 480);
5741 hr = IDirect3DViewport_GetBackground(viewport, &tmp, &valid);
5742 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
5743 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
5744 ok(!valid, "Got unexpected valid %#x.\n", valid);
5745 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
5746 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
5747 color = get_surface_color(rt, 320, 240);
5748 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x.\n", color);
5750 IDirect3DExecuteBuffer_Release(execute_buffer);
5751 destroy_viewport(device, viewport);
5752 destroy_material(background);
5753 destroy_material(material);
5754 IDirectDrawSurface_Release(rt);
5755 refcount = IDirect3DDevice_Release(device);
5756 ok(!refcount, "Device has %u references left.\n", refcount);
5757 refcount = IDirectDraw_Release(ddraw);
5758 ok(!refcount, "Ddraw object has %u references left.\n", refcount);
5759 DestroyWindow(window);
5762 static void test_lighting(void)
5764 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
5765 static D3DMATRIX mat =
5767 1.0f, 0.0f, 0.0f, 0.0f,
5768 0.0f, 1.0f, 0.0f, 0.0f,
5769 0.0f, 0.0f, 1.0f, 0.0f,
5770 0.0f, 0.0f, 0.0f, 1.0f,
5772 mat_singular =
5774 1.0f, 0.0f, 1.0f, 0.0f,
5775 0.0f, 1.0f, 0.0f, 0.0f,
5776 1.0f, 0.0f, 1.0f, 0.0f,
5777 0.0f, 0.0f, 0.5f, 1.0f,
5779 mat_transf =
5781 0.0f, 0.0f, 1.0f, 0.0f,
5782 0.0f, 1.0f, 0.0f, 0.0f,
5783 -1.0f, 0.0f, 0.0f, 0.0f,
5784 10.f, 10.0f, 10.0f, 1.0f,
5786 mat_nonaffine =
5788 1.0f, 0.0f, 0.0f, 0.0f,
5789 0.0f, 1.0f, 0.0f, 0.0f,
5790 0.0f, 0.0f, 1.0f, -1.0f,
5791 10.f, 10.0f, 10.0f, 0.0f,
5793 static D3DLVERTEX unlitquad[] =
5795 {{-1.0f}, {-1.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
5796 {{-1.0f}, { 0.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
5797 {{ 0.0f}, { 0.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
5798 {{ 0.0f}, {-1.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
5800 litquad[] =
5802 {{-1.0f}, { 0.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
5803 {{-1.0f}, { 1.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
5804 {{ 0.0f}, { 1.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
5805 {{ 0.0f}, { 0.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
5807 static D3DVERTEX unlitnquad[] =
5809 {{0.0f}, {-1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
5810 {{0.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
5811 {{1.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
5812 {{1.0f}, {-1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
5814 litnquad[] =
5816 {{0.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
5817 {{0.0f}, { 1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
5818 {{1.0f}, { 1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
5819 {{1.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
5821 nquad[] =
5823 {{-1.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
5824 {{-1.0f}, { 1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
5825 {{ 1.0f}, { 1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
5826 {{ 1.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
5828 rotatedquad[] =
5830 {{-10.0f}, {-11.0f}, {11.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
5831 {{-10.0f}, { -9.0f}, {11.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
5832 {{-10.0f}, { -9.0f}, { 9.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
5833 {{-10.0f}, {-11.0f}, { 9.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
5835 translatedquad[] =
5837 {{-11.0f}, {-11.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
5838 {{-11.0f}, { -9.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
5839 {{ -9.0f}, { -9.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
5840 {{ -9.0f}, {-11.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
5842 static const struct
5844 D3DMATRIX *world_matrix;
5845 void *quad;
5846 DWORD expected;
5847 const char *message;
5849 tests[] =
5851 {&mat, nquad, 0x000000ff, "Lit quad with light"},
5852 {&mat_singular, nquad, 0x000000b4, "Lit quad with singular world matrix"},
5853 {&mat_transf, rotatedquad, 0x000000ff, "Lit quad with transformation matrix"},
5854 {&mat_nonaffine, translatedquad, 0x000000ff, "Lit quad with non-affine matrix"},
5857 HWND window;
5858 IDirect3D *d3d;
5859 IDirect3DDevice *device;
5860 IDirectDraw *ddraw;
5861 IDirectDrawSurface *rt;
5862 IDirect3DViewport *viewport;
5863 IDirect3DMaterial *material;
5864 IDirect3DLight *light;
5865 IDirect3DExecuteBuffer *execute_buffer;
5866 D3DEXECUTEBUFFERDESC exec_desc;
5867 D3DMATERIALHANDLE mat_handle;
5868 D3DMATRIXHANDLE world_handle, view_handle, proj_handle;
5869 D3DLIGHT light_desc;
5870 HRESULT hr;
5871 D3DCOLOR color;
5872 void *ptr;
5873 UINT inst_length;
5874 ULONG refcount;
5875 unsigned int i;
5877 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5878 0, 0, 640, 480, 0, 0, 0, 0);
5879 ddraw = create_ddraw();
5880 ok(!!ddraw, "Failed to create a ddraw object.\n");
5881 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
5883 skip("Failed to create a 3D device, skipping test.\n");
5884 IDirectDraw_Release(ddraw);
5885 DestroyWindow(window);
5886 return;
5889 hr = IDirect3DDevice_GetDirect3D(device, &d3d);
5890 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
5892 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
5893 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
5895 viewport = create_viewport(device, 0, 0, 640, 480);
5896 material = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
5897 viewport_set_background(device, viewport, material);
5899 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
5900 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
5902 hr = IDirect3DDevice_CreateMatrix(device, &world_handle);
5903 ok(hr == D3D_OK, "Creating a matrix object failed, hr %#x.\n", hr);
5904 hr = IDirect3DDevice_SetMatrix(device, world_handle, &mat);
5905 ok(hr == D3D_OK, "Setting a matrix object failed, hr %#x.\n", hr);
5906 hr = IDirect3DDevice_CreateMatrix(device, &view_handle);
5907 ok(hr == D3D_OK, "Creating a matrix object failed, hr %#x.\n", hr);
5908 hr = IDirect3DDevice_SetMatrix(device, view_handle, &mat);
5909 ok(hr == D3D_OK, "Setting a matrix object failed, hr %#x.\n", hr);
5910 hr = IDirect3DDevice_CreateMatrix(device, &proj_handle);
5911 ok(hr == D3D_OK, "Creating a matrix object failed, hr %#x.\n", hr);
5912 hr = IDirect3DDevice_SetMatrix(device, proj_handle, &mat);
5913 ok(hr == D3D_OK, "Setting a matrix object failed, hr %#x.\n", hr);
5915 memset(&exec_desc, 0, sizeof(exec_desc));
5916 exec_desc.dwSize = sizeof(exec_desc);
5917 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
5918 exec_desc.dwBufferSize = 1024;
5919 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
5921 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
5922 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
5924 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
5925 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
5927 memcpy(exec_desc.lpData, unlitquad, sizeof(unlitquad));
5928 ptr = ((BYTE *)exec_desc.lpData) + sizeof(unlitquad);
5929 emit_set_ts(&ptr, D3DTRANSFORMSTATE_WORLD, world_handle);
5930 emit_set_ts(&ptr, D3DTRANSFORMSTATE_VIEW, view_handle);
5931 emit_set_ts(&ptr, D3DTRANSFORMSTATE_PROJECTION, proj_handle);
5932 emit_set_rs(&ptr, D3DRENDERSTATE_CLIPPING, FALSE);
5933 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, FALSE);
5934 emit_set_rs(&ptr, D3DRENDERSTATE_FOGENABLE, FALSE);
5935 emit_set_rs(&ptr, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
5936 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORM, 0, 4);
5937 emit_tquad_tlist(&ptr, 0);
5938 emit_end(&ptr);
5939 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
5940 inst_length -= sizeof(unlitquad);
5942 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
5943 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
5945 hr = IDirect3DDevice_BeginScene(device);
5946 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5948 set_execute_data(execute_buffer, 4, sizeof(unlitquad), inst_length);
5949 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
5950 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
5952 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
5953 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
5955 memcpy(exec_desc.lpData, litquad, sizeof(litquad));
5956 ptr = ((BYTE *)exec_desc.lpData) + sizeof(litquad);
5957 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORM, 0, 4);
5958 emit_tquad_tlist(&ptr, 0);
5959 emit_end(&ptr);
5960 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
5961 inst_length -= sizeof(litquad);
5963 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
5964 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
5966 set_execute_data(execute_buffer, 4, sizeof(litquad), inst_length);
5967 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
5968 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
5970 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
5971 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
5973 memcpy(exec_desc.lpData, unlitnquad, sizeof(unlitnquad));
5974 ptr = ((BYTE *)exec_desc.lpData) + sizeof(unlitnquad);
5975 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORMLIGHT, 0, 4);
5976 emit_tquad_tlist(&ptr, 0);
5977 emit_end(&ptr);
5978 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
5979 inst_length -= sizeof(unlitnquad);
5981 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
5982 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
5984 set_execute_data(execute_buffer, 4, sizeof(unlitnquad), inst_length);
5985 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
5986 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
5988 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
5989 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
5991 memcpy(exec_desc.lpData, litnquad, sizeof(litnquad));
5992 ptr = ((BYTE *)exec_desc.lpData) + sizeof(litnquad);
5993 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORMLIGHT, 0, 4);
5994 emit_tquad_tlist(&ptr, 0);
5995 emit_end(&ptr);
5996 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
5997 inst_length -= sizeof(litnquad);
5999 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
6000 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
6002 set_execute_data(execute_buffer, 4, sizeof(litnquad), inst_length);
6003 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
6004 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
6006 hr = IDirect3DDevice_EndScene(device);
6007 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6009 color = get_surface_color(rt, 160, 360);
6010 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x.\n", color);
6011 color = get_surface_color(rt, 160, 120);
6012 ok(color == 0x0000ff00, "Lit quad without normals has color 0x%08x.\n", color);
6013 color = get_surface_color(rt, 480, 360);
6014 ok(color == 0x00ffffff, "Unlit quad with normals has color 0x%08x.\n", color);
6015 color = get_surface_color(rt, 480, 120);
6016 ok(color == 0x00ffffff, "Lit quad with normals has color 0x%08x.\n", color);
6018 hr = IDirect3DMaterial_GetHandle(material, device, &mat_handle);
6019 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
6021 hr = IDirect3D_CreateLight(d3d, &light, NULL);
6022 ok(SUCCEEDED(hr), "Failed to create a light object, hr %#x.\n", hr);
6023 memset(&light_desc, 0, sizeof(light_desc));
6024 light_desc.dwSize = sizeof(light_desc);
6025 light_desc.dltType = D3DLIGHT_DIRECTIONAL;
6026 U1(light_desc.dcvColor).r = 0.0f;
6027 U2(light_desc.dcvColor).g = 0.0f;
6028 U3(light_desc.dcvColor).b = 1.0f;
6029 U4(light_desc.dcvColor).a = 1.0f;
6030 U3(light_desc.dvDirection).z = 1.0f;
6031 hr = IDirect3DLight_SetLight(light, &light_desc);
6032 ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
6033 hr = IDirect3DViewport_AddLight(viewport, light);
6034 ok(SUCCEEDED(hr), "Failed to add a light to the viewport, hr %#x.\n", hr);
6036 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
6038 hr = IDirect3DDevice_SetMatrix(device, world_handle, tests[i].world_matrix);
6039 ok(hr == D3D_OK, "Setting a matrix object failed, hr %#x.\n", hr);
6041 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6042 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
6044 hr = IDirect3DDevice_BeginScene(device);
6045 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6047 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
6048 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
6050 memcpy(exec_desc.lpData, tests[i].quad, sizeof(nquad));
6051 ptr = ((BYTE *)exec_desc.lpData) + sizeof(nquad);
6052 emit_set_ls(&ptr, D3DLIGHTSTATE_MATERIAL, mat_handle);
6053 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORMLIGHT, 0, 4);
6054 emit_tquad_tlist(&ptr, 0);
6055 emit_end(&ptr);
6056 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
6057 inst_length -= sizeof(nquad);
6059 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
6060 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
6062 set_execute_data(execute_buffer, 4, sizeof(nquad), inst_length);
6063 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
6064 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
6066 hr = IDirect3DDevice_EndScene(device);
6067 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6069 color = get_surface_color(rt, 320, 240);
6070 todo_wine ok(color == tests[i].expected, "%s has color 0x%08x.\n", tests[i].message, color);
6073 IDirect3DExecuteBuffer_Release(execute_buffer);
6074 IDirect3DDevice_DeleteMatrix(device, world_handle);
6075 IDirect3DDevice_DeleteMatrix(device, view_handle);
6076 IDirect3DDevice_DeleteMatrix(device, proj_handle);
6077 hr = IDirect3DViewport_DeleteLight(viewport, light);
6078 ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#x.\n", hr);
6079 IDirect3DLight_Release(light);
6080 destroy_material(material);
6081 destroy_viewport(device, viewport);
6082 IDirectDrawSurface_Release(rt);
6083 refcount = IDirect3DDevice_Release(device);
6084 ok(!refcount, "Device has %u references left.\n", refcount);
6085 IDirect3D_Release(d3d);
6086 refcount = IDirectDraw_Release(ddraw);
6087 ok(!refcount, "Ddraw object has %u references left.\n", refcount);
6088 DestroyWindow(window);
6091 static void test_palette_gdi(void)
6093 IDirectDrawSurface *surface, *primary;
6094 DDSURFACEDESC surface_desc;
6095 IDirectDraw *ddraw;
6096 IDirectDrawPalette *palette, *palette2;
6097 ULONG refcount;
6098 HWND window;
6099 HRESULT hr;
6100 PALETTEENTRY palette_entries[256];
6101 UINT i;
6102 HDC dc;
6103 DDBLTFX fx;
6104 RECT r;
6105 COLORREF color;
6106 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
6107 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
6108 * not the point of this test. */
6109 static const RGBQUAD expected1[] =
6111 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
6112 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
6114 static const RGBQUAD expected2[] =
6116 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
6117 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
6119 static const RGBQUAD expected3[] =
6121 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
6122 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
6124 HPALETTE ddraw_palette_handle;
6125 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
6126 RGBQUAD rgbquad[255];
6127 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
6129 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6130 0, 0, 640, 480, 0, 0, 0, 0);
6131 ddraw = create_ddraw();
6132 ok(!!ddraw, "Failed to create a ddraw object.\n");
6133 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6134 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6136 memset(&surface_desc, 0, sizeof(surface_desc));
6137 surface_desc.dwSize = sizeof(surface_desc);
6138 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6139 surface_desc.dwWidth = 16;
6140 surface_desc.dwHeight = 16;
6141 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6142 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6143 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
6144 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
6145 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6146 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6148 /* Avoid colors from the Windows default palette. */
6149 memset(palette_entries, 0, sizeof(palette_entries));
6150 palette_entries[1].peRed = 0x01;
6151 palette_entries[2].peGreen = 0x02;
6152 palette_entries[3].peBlue = 0x03;
6153 palette_entries[4].peRed = 0x13;
6154 palette_entries[4].peGreen = 0x14;
6155 palette_entries[4].peBlue = 0x15;
6156 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
6157 palette_entries, &palette, NULL);
6158 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6160 /* If there is no palette assigned and the display mode is not 8 bpp, some
6161 * drivers refuse to create a DC while others allow it. If a DC is created,
6162 * the DIB color table is uninitialized and contains random colors. No error
6163 * is generated when trying to read pixels and random garbage is returned.
6165 * The most likely explanation is that if the driver creates a DC, it (or
6166 * the higher-level runtime) uses GetSystemPaletteEntries to find the
6167 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
6168 * contains uninitialized garbage. See comments below for the P8 case. */
6170 hr = IDirectDrawSurface_SetPalette(surface, palette);
6171 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6172 hr = IDirectDrawSurface_GetDC(surface, &dc);
6173 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6174 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
6175 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
6176 "Got unexpected palette %p, expected %p.\n",
6177 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
6179 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
6180 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
6181 for (i = 0; i < sizeof(expected1) / sizeof(*expected1); i++)
6183 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
6184 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
6185 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
6186 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
6188 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
6190 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
6191 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
6192 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
6195 /* Update the palette while the DC is in use. This does not modify the DC. */
6196 palette_entries[4].peRed = 0x23;
6197 palette_entries[4].peGreen = 0x24;
6198 palette_entries[4].peBlue = 0x25;
6199 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
6200 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
6202 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
6203 ok(i == 1, "Expected count 1, got %u.\n", i);
6204 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
6205 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
6206 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
6207 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
6209 /* Neither does re-setting the palette. */
6210 hr = IDirectDrawSurface_SetPalette(surface, NULL);
6211 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6212 hr = IDirectDrawSurface_SetPalette(surface, palette);
6213 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6215 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
6216 ok(i == 1, "Expected count 1, got %u.\n", i);
6217 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
6218 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
6219 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
6220 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
6222 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
6223 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6225 /* Refresh the DC. This updates the palette. */
6226 hr = IDirectDrawSurface_GetDC(surface, &dc);
6227 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6228 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
6229 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
6230 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
6232 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
6233 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
6234 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
6235 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
6237 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
6239 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
6240 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
6241 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
6243 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
6244 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6246 refcount = IDirectDrawSurface_Release(surface);
6247 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6249 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
6250 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6251 if (FAILED(IDirectDraw_SetDisplayMode(ddraw, 640, 480, 8)))
6253 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
6254 IDirectDrawPalette_Release(palette);
6255 IDirectDraw_Release(ddraw);
6256 DestroyWindow(window);
6257 return;
6259 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
6261 memset(&surface_desc, 0, sizeof(surface_desc));
6262 surface_desc.dwSize = sizeof(surface_desc);
6263 surface_desc.dwFlags = DDSD_CAPS;
6264 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
6265 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
6266 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6268 memset(&fx, 0, sizeof(fx));
6269 fx.dwSize = sizeof(fx);
6270 U5(fx).dwFillColor = 3;
6271 SetRect(&r, 0, 0, 319, 479);
6272 hr = IDirectDrawSurface_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6273 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
6274 SetRect(&r, 320, 0, 639, 479);
6275 U5(fx).dwFillColor = 4;
6276 hr = IDirectDrawSurface_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6277 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
6279 hr = IDirectDrawSurface_SetPalette(primary, palette);
6280 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6281 hr = IDirectDrawSurface_GetDC(primary, &dc);
6282 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6284 color = GetPixel(dc, 160, 240);
6285 ok(color == 0x00030000, "Clear index 3: Got unexpected color 0x%08x.\n", color);
6286 color = GetPixel(dc, 480, 240);
6287 ok(color == 0x00252423, "Clear index 4: Got unexpected color 0x%08x.\n", color);
6289 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
6290 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
6291 "Got unexpected palette %p, expected %p.\n",
6292 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
6293 SelectPalette(dc, ddraw_palette_handle, FALSE);
6295 /* The primary uses the system palette. In exclusive mode, the system palette matches
6296 * the ddraw palette attached to the primary, so the result is what you would expect
6297 * from a regular surface. Tests for the interaction between the ddraw palette and
6298 * the system palette are not included pending an application that depends on this.
6299 * The relation between those causes problems on Windows Vista and newer for games
6300 * like Age of Empires or StarCraft. Don't emulate it without a real need. */
6301 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
6302 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
6303 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
6305 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
6306 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
6307 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
6308 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
6310 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
6312 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
6313 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
6314 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
6316 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
6317 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6319 memset(&surface_desc, 0, sizeof(surface_desc));
6320 surface_desc.dwSize = sizeof(surface_desc);
6321 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6322 surface_desc.dwWidth = 16;
6323 surface_desc.dwHeight = 16;
6324 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6325 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6326 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6328 /* Here the offscreen surface appears to use the primary's palette,
6329 * but in all likelihood it is actually the system palette. */
6330 hr = IDirectDrawSurface_GetDC(surface, &dc);
6331 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6332 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
6333 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
6334 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
6336 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
6337 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
6338 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
6339 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
6341 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
6343 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
6344 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
6345 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
6347 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
6348 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6350 /* On real hardware a change to the primary surface's palette applies immediately,
6351 * even on device contexts from offscreen surfaces that do not have their own
6352 * palette. On the testbot VMs this is not the case. Don't test this until we
6353 * know of an application that depends on this. */
6355 memset(palette_entries, 0, sizeof(palette_entries));
6356 palette_entries[1].peBlue = 0x40;
6357 palette_entries[2].peRed = 0x40;
6358 palette_entries[3].peGreen = 0x40;
6359 palette_entries[4].peRed = 0x12;
6360 palette_entries[4].peGreen = 0x34;
6361 palette_entries[4].peBlue = 0x56;
6362 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
6363 palette_entries, &palette2, NULL);
6364 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6365 hr = IDirectDrawSurface_SetPalette(surface, palette2);
6366 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6368 /* A palette assigned to the offscreen surface overrides the primary / system
6369 * palette. */
6370 hr = IDirectDrawSurface_GetDC(surface, &dc);
6371 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6372 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
6373 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
6374 for (i = 0; i < sizeof(expected3) / sizeof(*expected3); i++)
6376 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
6377 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
6378 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
6379 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
6381 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
6383 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
6384 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
6385 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
6387 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
6388 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6390 refcount = IDirectDrawSurface_Release(surface);
6391 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6393 /* The Windows 8 testbot keeps extra references to the primary and
6394 * backbuffer while in 8 bpp mode. */
6395 hr = IDirectDraw_RestoreDisplayMode(ddraw);
6396 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
6398 refcount = IDirectDrawSurface_Release(primary);
6399 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6400 refcount = IDirectDrawPalette_Release(palette2);
6401 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6402 refcount = IDirectDrawPalette_Release(palette);
6403 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6404 refcount = IDirectDraw_Release(ddraw);
6405 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6406 DestroyWindow(window);
6409 static void test_palette_alpha(void)
6411 IDirectDrawSurface *surface;
6412 DDSURFACEDESC surface_desc;
6413 IDirectDraw *ddraw;
6414 IDirectDrawPalette *palette;
6415 ULONG refcount;
6416 HWND window;
6417 HRESULT hr;
6418 PALETTEENTRY palette_entries[256];
6419 unsigned int i;
6420 static const struct
6422 DWORD caps, flags;
6423 BOOL attach_allowed;
6424 const char *name;
6426 test_data[] =
6428 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
6429 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
6430 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
6433 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6434 0, 0, 640, 480, 0, 0, 0, 0);
6435 ddraw = create_ddraw();
6436 ok(!!ddraw, "Failed to create a ddraw object.\n");
6437 if (FAILED(IDirectDraw_SetDisplayMode(ddraw, 640, 480, 8)))
6439 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
6440 IDirectDraw_Release(ddraw);
6441 DestroyWindow(window);
6442 return;
6444 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6445 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6447 memset(palette_entries, 0, sizeof(palette_entries));
6448 palette_entries[1].peFlags = 0x42;
6449 palette_entries[2].peFlags = 0xff;
6450 palette_entries[3].peFlags = 0x80;
6451 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
6452 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6454 memset(palette_entries, 0x66, sizeof(palette_entries));
6455 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
6456 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
6457 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
6458 palette_entries[0].peFlags);
6459 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
6460 palette_entries[1].peFlags);
6461 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
6462 palette_entries[2].peFlags);
6463 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
6464 palette_entries[3].peFlags);
6466 IDirectDrawPalette_Release(palette);
6468 memset(palette_entries, 0, sizeof(palette_entries));
6469 palette_entries[1].peFlags = 0x42;
6470 palette_entries[1].peRed = 0xff;
6471 palette_entries[2].peFlags = 0xff;
6472 palette_entries[3].peFlags = 0x80;
6473 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
6474 palette_entries, &palette, NULL);
6475 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6477 memset(palette_entries, 0x66, sizeof(palette_entries));
6478 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
6479 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
6480 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
6481 palette_entries[0].peFlags);
6482 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
6483 palette_entries[1].peFlags);
6484 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
6485 palette_entries[2].peFlags);
6486 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
6487 palette_entries[3].peFlags);
6489 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); i++)
6491 memset(&surface_desc, 0, sizeof(surface_desc));
6492 surface_desc.dwSize = sizeof(surface_desc);
6493 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
6494 surface_desc.dwWidth = 128;
6495 surface_desc.dwHeight = 128;
6496 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
6497 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6498 ok(SUCCEEDED(hr), "Failed to create %s surface, hr %#x.\n", test_data[i].name, hr);
6500 hr = IDirectDrawSurface_SetPalette(surface, palette);
6501 if (test_data[i].attach_allowed)
6502 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#x.\n", test_data[i].name, hr);
6503 else
6504 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x, %s surface.\n", hr, test_data[i].name);
6506 if (SUCCEEDED(hr))
6508 HDC dc;
6509 RGBQUAD rgbquad;
6510 UINT retval;
6512 hr = IDirectDrawSurface_GetDC(surface, &dc);
6513 ok(SUCCEEDED(hr) || broken(hr == DDERR_CANTCREATEDC) /* Win2k testbot */,
6514 "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
6515 if (SUCCEEDED(hr))
6517 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
6518 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
6519 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
6520 rgbquad.rgbRed, test_data[i].name);
6521 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
6522 rgbquad.rgbGreen, test_data[i].name);
6523 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
6524 rgbquad.rgbBlue, test_data[i].name);
6525 ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
6526 rgbquad.rgbReserved, test_data[i].name);
6527 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
6528 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6531 IDirectDrawSurface_Release(surface);
6534 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
6535 memset(&surface_desc, 0, sizeof(surface_desc));
6536 surface_desc.dwSize = sizeof(surface_desc);
6537 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6538 surface_desc.dwWidth = 128;
6539 surface_desc.dwHeight = 128;
6540 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6541 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6542 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
6543 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
6544 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6545 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6546 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
6547 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6548 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6549 hr = IDirectDrawSurface_SetPalette(surface, palette);
6550 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
6551 IDirectDrawSurface_Release(surface);
6553 /* The Windows 8 testbot keeps extra references to the primary
6554 * while in 8 bpp mode. */
6555 hr = IDirectDraw_RestoreDisplayMode(ddraw);
6556 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
6558 refcount = IDirectDrawPalette_Release(palette);
6559 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6560 refcount = IDirectDraw_Release(ddraw);
6561 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6562 DestroyWindow(window);
6565 static void test_lost_device(void)
6567 IDirectDrawSurface *surface;
6568 DDSURFACEDESC surface_desc;
6569 HWND window1, window2;
6570 IDirectDraw *ddraw;
6571 ULONG refcount;
6572 HRESULT hr;
6573 BOOL ret;
6575 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6576 0, 0, 640, 480, 0, 0, 0, 0);
6577 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6578 0, 0, 640, 480, 0, 0, 0, 0);
6579 ddraw = create_ddraw();
6580 ok(!!ddraw, "Failed to create a ddraw object.\n");
6581 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6582 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6584 memset(&surface_desc, 0, sizeof(surface_desc));
6585 surface_desc.dwSize = sizeof(surface_desc);
6586 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
6587 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
6588 surface_desc.dwBackBufferCount = 1;
6589 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6590 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6592 hr = IDirectDrawSurface_IsLost(surface);
6593 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6594 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6595 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6597 ret = SetForegroundWindow(GetDesktopWindow());
6598 ok(ret, "Failed to set foreground window.\n");
6599 hr = IDirectDrawSurface_IsLost(surface);
6600 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
6601 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6602 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
6604 ret = SetForegroundWindow(window1);
6605 ok(ret, "Failed to set foreground window.\n");
6606 hr = IDirectDrawSurface_IsLost(surface);
6607 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
6608 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6609 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
6611 hr = restore_surfaces(ddraw);
6612 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6613 hr = IDirectDrawSurface_IsLost(surface);
6614 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6615 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6616 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6618 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
6619 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6620 hr = IDirectDrawSurface_IsLost(surface);
6621 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6622 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6623 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
6625 /* Trying to restore the primary will crash, probably because flippable
6626 * surfaces can't exist in DDSCL_NORMAL. */
6627 IDirectDrawSurface_Release(surface);
6628 memset(&surface_desc, 0, sizeof(surface_desc));
6629 surface_desc.dwSize = sizeof(surface_desc);
6630 surface_desc.dwFlags = DDSD_CAPS;
6631 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
6632 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6633 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6635 hr = IDirectDrawSurface_IsLost(surface);
6636 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6638 ret = SetForegroundWindow(GetDesktopWindow());
6639 ok(ret, "Failed to set foreground window.\n");
6640 hr = IDirectDrawSurface_IsLost(surface);
6641 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6643 ret = SetForegroundWindow(window1);
6644 ok(ret, "Failed to set foreground window.\n");
6645 hr = IDirectDrawSurface_IsLost(surface);
6646 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6648 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6649 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6650 hr = IDirectDrawSurface_IsLost(surface);
6651 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
6653 hr = restore_surfaces(ddraw);
6654 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6655 hr = IDirectDrawSurface_IsLost(surface);
6656 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6658 IDirectDrawSurface_Release(surface);
6659 memset(&surface_desc, 0, sizeof(surface_desc));
6660 surface_desc.dwSize = sizeof(surface_desc);
6661 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
6662 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
6663 surface_desc.dwBackBufferCount = 1;
6664 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6665 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6667 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6668 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6669 hr = IDirectDrawSurface_IsLost(surface);
6670 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6671 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6672 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6674 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
6675 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6676 hr = IDirectDrawSurface_IsLost(surface);
6677 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6678 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6679 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
6681 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
6682 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6683 hr = IDirectDrawSurface_IsLost(surface);
6684 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6685 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6686 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
6688 hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
6689 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6690 hr = IDirectDrawSurface_IsLost(surface);
6691 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6692 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6693 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
6695 hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
6696 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6697 hr = IDirectDrawSurface_IsLost(surface);
6698 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6699 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6700 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
6702 hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6703 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6704 hr = IDirectDrawSurface_IsLost(surface);
6705 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
6706 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6707 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
6709 IDirectDrawSurface_Release(surface);
6710 refcount = IDirectDraw_Release(ddraw);
6711 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6712 DestroyWindow(window2);
6713 DestroyWindow(window1);
6716 static void test_surface_desc_lock(void)
6718 IDirectDrawSurface *surface;
6719 DDSURFACEDESC surface_desc;
6720 IDirectDraw *ddraw;
6721 ULONG refcount;
6722 HWND window;
6723 HRESULT hr;
6725 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6726 0, 0, 640, 480, 0, 0, 0, 0);
6727 ddraw = create_ddraw();
6728 ok(!!ddraw, "Failed to create a ddraw object.\n");
6729 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6730 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6732 memset(&surface_desc, 0, sizeof(surface_desc));
6733 surface_desc.dwSize = sizeof(surface_desc);
6734 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6735 surface_desc.dwWidth = 16;
6736 surface_desc.dwHeight = 16;
6737 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6738 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6739 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6741 memset(&surface_desc, 0xaa, sizeof(surface_desc));
6742 surface_desc.dwSize = sizeof(surface_desc);
6743 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
6744 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6745 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
6747 memset(&surface_desc, 0xaa, sizeof(surface_desc));
6748 surface_desc.dwSize = sizeof(surface_desc);
6749 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, 0, NULL);
6750 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6751 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
6752 memset(&surface_desc, 0xaa, sizeof(surface_desc));
6753 surface_desc.dwSize = sizeof(surface_desc);
6754 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
6755 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6756 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
6757 hr = IDirectDrawSurface_Unlock(surface, NULL);
6758 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6760 memset(&surface_desc, 0xaa, sizeof(surface_desc));
6761 surface_desc.dwSize = sizeof(surface_desc);
6762 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
6763 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6764 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
6766 IDirectDrawSurface_Release(surface);
6767 refcount = IDirectDraw_Release(ddraw);
6768 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6769 DestroyWindow(window);
6772 static void test_texturemapblend(void)
6774 HRESULT hr;
6775 DDSURFACEDESC ddsd;
6776 D3DEXECUTEBUFFERDESC exec_desc;
6777 DDBLTFX fx;
6778 static RECT rect = {0, 0, 64, 128};
6779 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
6780 DDCOLORKEY ckey;
6781 IDirectDrawSurface *surface, *rt;
6782 IDirect3DTexture *texture;
6783 D3DTEXTUREHANDLE texture_handle;
6784 HWND window;
6785 IDirectDraw *ddraw;
6786 IDirect3DDevice *device;
6787 IDirect3DMaterial *material;
6788 IDirect3DViewport *viewport;
6789 IDirect3DExecuteBuffer *execute_buffer;
6790 UINT inst_length;
6791 void *ptr;
6792 ULONG ref;
6793 D3DCOLOR color;
6795 static const D3DTLVERTEX test1_quads[] =
6797 {{0.0f}, {0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {0.0f}, {0.0f}},
6798 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {0.0f}, {1.0f}},
6799 {{640.0f}, {0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {1.0f}, {0.0f}},
6800 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {1.0f}, {1.0f}},
6801 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {0.0f}, {0.0f}},
6802 {{0.0f}, {480.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {0.0f}, {1.0f}},
6803 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {1.0f}, {0.0f}},
6804 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {1.0f}, {1.0f}},
6806 test2_quads[] =
6808 {{0.0f}, {0.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {0.0f}, {0.0f}},
6809 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {0.0f}, {1.0f}},
6810 {{640.0f}, {0.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {1.0f}, {0.0f}},
6811 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {1.0f}, {1.0f}},
6812 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {0.0f}, {0.0f}},
6813 {{0.0f}, {480.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {0.0f}, {1.0f}},
6814 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {1.0f}, {0.0f}},
6815 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {1.0f}, {1.0f}},
6818 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6819 0, 0, 640, 480, 0, 0, 0, 0);
6820 ddraw = create_ddraw();
6821 ok(!!ddraw, "Failed to create a ddraw object.\n");
6822 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
6824 skip("Failed to create a 3D device, skipping test.\n");
6825 DestroyWindow(window);
6826 IDirectDraw_Release(ddraw);
6827 return;
6830 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
6831 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
6833 material = create_diffuse_material(device, 0.0f, 0.0f, 0.0f, 1.0f);
6834 viewport = create_viewport(device, 0, 0, 640, 480);
6835 viewport_set_background(device, viewport, material);
6837 memset(&exec_desc, 0, sizeof(exec_desc));
6838 exec_desc.dwSize = sizeof(exec_desc);
6839 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
6840 exec_desc.dwBufferSize = 1024;
6841 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
6842 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
6843 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
6845 /* Test alpha with DDPF_ALPHAPIXELS texture - should be taken from texture alpha channel.
6847 * The vertex alpha is completely ignored in this case, so case 1 and 2 combined are not
6848 * a D3DTOP_MODULATE with texture alpha = 0xff in case 2 (no alpha in texture). */
6849 memset(&ddsd, 0, sizeof(ddsd));
6850 ddsd.dwSize = sizeof(ddsd);
6851 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
6852 ddsd.dwHeight = 128;
6853 ddsd.dwWidth = 128;
6854 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6855 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
6856 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
6857 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
6858 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6859 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6860 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
6861 U5(ddsd.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
6862 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
6863 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6865 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
6866 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
6867 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
6868 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
6870 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6871 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
6873 memset(&fx, 0, sizeof(fx));
6874 fx.dwSize = sizeof(fx);
6875 U5(fx).dwFillColor = 0xff0000ff;
6876 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6877 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
6878 U5(fx).dwFillColor = 0x800000ff;
6879 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6880 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
6882 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
6883 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
6885 memcpy(exec_desc.lpData, test1_quads, sizeof(test1_quads));
6887 ptr = ((BYTE *)exec_desc.lpData) + sizeof(test1_quads);
6888 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 8);
6889 emit_set_rs(&ptr, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
6890 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
6891 emit_set_rs(&ptr, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
6892 emit_set_rs(&ptr, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
6893 /* The history of D3DRENDERSTATE_ALPHABLENDENABLE is quite a mess. In the
6894 * first D3D release there was a D3DRENDERSTATE_BLENDENABLE (enum value 27).
6895 * D3D5 introduced a new and separate D3DRENDERSTATE_ALPHABLENDENABLE (42)
6896 * together with D3DRENDERSTATE_COLORKEYENABLE (41). The docs aren't all
6897 * that clear but they mention that D3DRENDERSTATE_BLENDENABLE overrides the
6898 * two new states.
6899 * Then D3D6 came and got rid of the new D3DRENDERSTATE_ALPHABLENDENABLE
6900 * state (42), renaming the older D3DRENDERSTATE_BLENDENABLE enum (27)
6901 * as D3DRENDERSTATE_ALPHABLENDENABLE.
6902 * There is a comment in the D3D6 docs which mentions that hardware
6903 * rasterizers always used D3DRENDERSTATE_BLENDENABLE to just toggle alpha
6904 * blending while prior to D3D5 software rasterizers toggled both color
6905 * keying and alpha blending according to it. What I gather is that, from
6906 * D3D6 onwards, D3DRENDERSTATE_ALPHABLENDENABLE always only toggles the
6907 * alpha blending state.
6908 * These tests seem to show that actual, current hardware follows the D3D6
6909 * behavior even when using the original D3D interfaces, for the HAL device
6910 * at least. */
6911 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
6912 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
6913 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
6915 emit_tquad(&ptr, 0);
6916 emit_tquad(&ptr, 4);
6917 emit_end(&ptr);
6919 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
6920 inst_length -= sizeof(test1_quads);
6921 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
6922 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
6923 set_execute_data(execute_buffer, 8, sizeof(test1_quads), inst_length);
6925 hr = IDirect3DDevice_BeginScene(device);
6926 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6927 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_UNCLIPPED);
6928 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
6929 hr = IDirect3DDevice_EndScene(device);
6930 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6932 color = get_surface_color(rt, 5, 5);
6933 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
6934 color = get_surface_color(rt, 400, 5);
6935 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
6936 color = get_surface_color(rt, 5, 245);
6937 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
6938 color = get_surface_color(rt, 400, 245);
6939 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
6941 IDirect3DTexture_Release(texture);
6942 ref = IDirectDrawSurface_Release(surface);
6943 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
6945 /* Test alpha with texture that has no alpha channel - alpha should be taken from diffuse vertex color. */
6946 memset(&ddsd, 0, sizeof(ddsd));
6947 ddsd.dwSize = sizeof(ddsd);
6948 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
6949 ddsd.dwHeight = 128;
6950 ddsd.dwWidth = 128;
6951 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6952 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
6953 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
6954 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
6955 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6956 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6957 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
6959 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
6960 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6962 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
6963 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
6964 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
6965 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
6967 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6968 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
6970 U5(fx).dwFillColor = 0xff0000ff;
6971 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6972 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
6973 U5(fx).dwFillColor = 0x800000ff;
6974 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6975 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
6977 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
6978 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
6980 ptr = ((BYTE *)exec_desc.lpData) + sizeof(test1_quads);
6981 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 8);
6982 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
6984 emit_tquad(&ptr, 0);
6985 emit_tquad(&ptr, 4);
6986 emit_end(&ptr);
6988 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
6989 inst_length -= sizeof(test1_quads);
6990 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
6991 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
6992 set_execute_data(execute_buffer, 8, sizeof(test1_quads), inst_length);
6994 hr = IDirect3DDevice_BeginScene(device);
6995 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6996 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_UNCLIPPED);
6997 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
6998 hr = IDirect3DDevice_EndScene(device);
6999 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7001 color = get_surface_color(rt, 5, 5);
7002 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
7003 color = get_surface_color(rt, 400, 5);
7004 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
7005 color = get_surface_color(rt, 5, 245);
7006 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
7007 color = get_surface_color(rt, 400, 245);
7008 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
7010 IDirect3DTexture_Release(texture);
7011 ref = IDirectDrawSurface_Release(surface);
7012 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
7014 /* Test RGB - should multiply color components from diffuse vertex color and texture. */
7015 memset(&ddsd, 0, sizeof(ddsd));
7016 ddsd.dwSize = sizeof(ddsd);
7017 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
7018 ddsd.dwHeight = 128;
7019 ddsd.dwWidth = 128;
7020 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
7021 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
7022 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
7023 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
7024 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7025 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7026 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
7027 U5(ddsd.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
7028 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
7029 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7031 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
7032 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
7033 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
7034 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
7036 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7037 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
7039 U5(fx).dwFillColor = 0x00ffffff;
7040 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7041 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
7042 U5(fx).dwFillColor = 0x00ffff80;
7043 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7044 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
7046 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
7047 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
7049 memcpy(exec_desc.lpData, test2_quads, sizeof(test2_quads));
7051 ptr = ((BYTE *)exec_desc.lpData) + sizeof(test2_quads);
7052 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 8);
7053 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
7054 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
7056 emit_tquad(&ptr, 0);
7057 emit_tquad(&ptr, 4);
7058 emit_end(&ptr);
7060 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
7061 inst_length -= sizeof(test2_quads);
7062 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
7063 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
7064 set_execute_data(execute_buffer, 8, sizeof(test2_quads), inst_length);
7066 hr = IDirect3DDevice_BeginScene(device);
7067 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
7068 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_UNCLIPPED);
7069 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
7070 hr = IDirect3DDevice_EndScene(device);
7071 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7073 /* WARP (Win8 testbot) emulates color keying with the alpha channel like Wine does,
7074 * but even applies it when there's no color key assigned. The surface alpha is zero
7075 * here, so nothing gets drawn.
7077 * The ddraw2 version of this test draws these quads with color keying off due to
7078 * different defaults in ddraw1 and ddraw2. */
7079 color = get_surface_color(rt, 5, 5);
7080 ok(compare_color(color, 0x00ff0040, 2) || broken(compare_color(color, 0x00000000, 1)),
7081 "Got unexpected color 0x%08x.\n", color);
7082 color = get_surface_color(rt, 400, 5);
7083 ok(compare_color(color, 0x00ff0080, 2) || broken(compare_color(color, 0x00000000, 1)),
7084 "Got unexpected color 0x%08x.\n", color);
7085 color = get_surface_color(rt, 5, 245);
7086 ok(compare_color(color, 0x00800080, 2) || broken(compare_color(color, 0x00000000, 1)),
7087 "Got unexpected color 0x%08x.\n", color);
7088 color = get_surface_color(rt, 400, 245);
7089 ok(compare_color(color, 0x008000ff, 2) || broken(compare_color(color, 0x00000000, 1)),
7090 "Got unexpected color 0x%08x.\n", color);
7092 IDirect3DTexture_Release(texture);
7093 ref = IDirectDrawSurface_Release(surface);
7094 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
7096 /* Test alpha again, now with color keyed texture (colorkey emulation in wine can interfere). */
7097 memset(&ddsd, 0, sizeof(ddsd));
7098 ddsd.dwSize = sizeof(ddsd);
7099 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
7100 ddsd.dwHeight = 128;
7101 ddsd.dwWidth = 128;
7102 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
7103 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
7104 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
7105 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 16;
7106 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xf800;
7107 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x07e0;
7108 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x001f;
7110 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
7111 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7113 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
7114 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
7115 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
7116 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
7118 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7119 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
7121 U5(fx).dwFillColor = 0xf800;
7122 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7123 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
7124 U5(fx).dwFillColor = 0x001f;
7125 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7126 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
7128 ckey.dwColorSpaceLowValue = 0x001f;
7129 ckey.dwColorSpaceHighValue = 0x001f;
7130 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
7131 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
7133 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
7134 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
7136 memcpy(exec_desc.lpData, test1_quads, sizeof(test1_quads));
7138 ptr = ((BYTE *)exec_desc.lpData) + sizeof(test1_quads);
7139 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 8);
7140 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
7141 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
7142 /* D3DRENDERSTATE_COLORKEYENABLE is supposed to be on by default on version
7143 * 1 devices, but for some reason it randomly defaults to FALSE on the W8
7144 * testbot. This is either the fault of Windows 8 or the WARP driver.
7145 * Also D3DRENDERSTATE_COLORKEYENABLE was introduced in D3D 5 aka version 2
7146 * devices only, which might imply this doesn't actually do anything on
7147 * WARP. */
7148 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
7150 emit_tquad(&ptr, 0);
7151 emit_tquad(&ptr, 4);
7152 emit_end(&ptr);
7154 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
7155 inst_length -= sizeof(test1_quads);
7156 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
7157 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
7158 set_execute_data(execute_buffer, 8, sizeof(test1_quads), inst_length);
7160 hr = IDirect3DDevice_BeginScene(device);
7161 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
7162 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_UNCLIPPED);
7163 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
7164 hr = IDirect3DDevice_EndScene(device);
7165 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7167 /* Allow broken WARP results (colorkey disabled). */
7168 color = get_surface_color(rt, 5, 5);
7169 ok(compare_color(color, 0x00000000, 2) || broken(compare_color(color, 0x000000ff, 2)),
7170 "Got unexpected color 0x%08x.\n", color);
7171 color = get_surface_color(rt, 400, 5);
7172 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
7173 color = get_surface_color(rt, 5, 245);
7174 ok(compare_color(color, 0x00000000, 2) || broken(compare_color(color, 0x00000080, 2)),
7175 "Got unexpected color 0x%08x.\n", color);
7176 color = get_surface_color(rt, 400, 245);
7177 ok(compare_color(color, 0x00800000, 2), "Got unexpected color 0x%08x.\n", color);
7179 IDirect3DTexture_Release(texture);
7180 ref = IDirectDrawSurface_Release(surface);
7181 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
7183 ref = IDirect3DExecuteBuffer_Release(execute_buffer);
7184 ok(ref == 0, "Execute buffer not properly released, refcount %u.\n", ref);
7185 destroy_viewport(device, viewport);
7186 ref = IDirect3DMaterial_Release(material);
7187 ok(ref == 0, "Material not properly released, refcount %u.\n", ref);
7188 IDirectDrawSurface_Release(rt);
7189 IDirect3DDevice_Release(device);
7190 ref = IDirectDraw_Release(ddraw);
7191 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
7192 DestroyWindow(window);
7195 static void test_viewport_clear_rect(void)
7197 HRESULT hr;
7198 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
7199 static D3DRECT clear_rect2 = {{90}, {90}, {110}, {110}};
7200 IDirectDrawSurface *rt;
7201 HWND window;
7202 IDirectDraw *ddraw;
7203 IDirect3DDevice *device;
7204 IDirect3DMaterial *red, *green;
7205 IDirect3DViewport *viewport, *viewport2;
7206 ULONG ref;
7207 D3DCOLOR color;
7209 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7210 0, 0, 640, 480, 0, 0, 0, 0);
7211 ddraw = create_ddraw();
7212 ok(!!ddraw, "Failed to create a ddraw object.\n");
7213 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
7215 skip("Failed to create a 3D device, skipping test.\n");
7216 DestroyWindow(window);
7217 IDirectDraw_Release(ddraw);
7218 return;
7221 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
7222 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
7224 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
7225 viewport = create_viewport(device, 0, 0, 640, 480);
7226 viewport_set_background(device, viewport, red);
7227 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7228 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
7230 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
7231 viewport2 = create_viewport(device, 100, 100, 20, 20);
7232 viewport_set_background(device, viewport2, green);
7233 hr = IDirect3DViewport_Clear(viewport2, 1, &clear_rect2, D3DCLEAR_TARGET);
7234 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
7236 color = get_surface_color(rt, 85, 85); /* Outside both. */
7237 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
7238 color = get_surface_color(rt, 95, 95); /* Outside vp, inside rect. */
7239 /* AMD GPUs ignore the viewport dimensions and only care about the rectangle. */
7240 ok(compare_color(color, 0x00ff0000, 1) || broken(compare_color(color, 0x0000ff00, 1)),
7241 "Got unexpected color 0x%08x.\n", color);
7242 color = get_surface_color(rt, 105, 105); /* Inside both. */
7243 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
7244 color = get_surface_color(rt, 115, 115); /* Inside vp, outside rect. */
7245 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
7246 color = get_surface_color(rt, 125, 125); /* Outside both. */
7247 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
7249 destroy_viewport(device, viewport2);
7250 destroy_material(green);
7251 destroy_viewport(device, viewport);
7252 destroy_material(red);
7253 IDirectDrawSurface_Release(rt);
7254 IDirect3DDevice_Release(device);
7255 ref = IDirectDraw_Release(ddraw);
7256 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
7257 DestroyWindow(window);
7260 static void test_color_fill(void)
7262 HRESULT hr;
7263 IDirect3DDevice *device;
7264 IDirectDraw *ddraw;
7265 IDirectDrawSurface *surface, *surface2;
7266 DDSURFACEDESC surface_desc;
7267 ULONG refcount;
7268 HWND window;
7269 unsigned int i;
7270 DDBLTFX fx;
7271 RECT rect = {5, 5, 7, 7};
7272 DWORD *color;
7273 DWORD num_fourcc_codes, *fourcc_codes;
7274 DDCAPS hal_caps;
7275 BOOL support_uyvy = FALSE, support_yuy2 = FALSE;
7276 static const struct
7278 DWORD caps;
7279 HRESULT colorfill_hr, depthfill_hr;
7280 BOOL rop_success;
7281 const char *name;
7282 DWORD result;
7283 BOOL check_result;
7284 DDPIXELFORMAT format;
7286 tests[] =
7289 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
7290 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
7292 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
7293 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
7297 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
7298 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
7300 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
7301 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
7305 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
7306 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
7308 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
7309 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
7313 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
7314 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
7316 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
7317 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
7321 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY,
7322 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0, FALSE,
7323 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
7326 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
7327 * different afterwards. DX9+ GPUs set one of the two luminance values
7328 * in each block, but AMD and Nvidia GPUs disagree on which luminance
7329 * value they set. r200 (dx8) just sets the entire block to the clear
7330 * value. */
7331 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
7332 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
7334 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
7335 {0}, {0}, {0}, {0}, {0}
7339 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
7340 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
7342 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
7343 {0}, {0}, {0}, {0}, {0}
7347 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY,
7348 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
7350 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
7351 {0}, {0}, {0}, {0}, {0}
7355 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY,
7356 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
7358 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
7359 {0}, {0}, {0}, {0}, {0}
7363 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
7364 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
7366 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
7367 {0}, {0}, {0}, {0}, {0}
7371 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
7372 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
7374 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
7375 {0}, {0}, {0}, {0}, {0}
7379 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
7380 * surface works, presumably because it is handled by the runtime instead of
7381 * the driver. */
7382 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
7383 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
7385 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
7386 {8}, {0}, {0}, {0}, {0}
7390 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
7391 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
7393 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
7394 {8}, {0}, {0}, {0}, {0}
7398 static const struct
7400 DWORD rop;
7401 const char *name;
7402 HRESULT hr;
7404 rops[] =
7406 {SRCCOPY, "SRCCOPY", DD_OK},
7407 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
7408 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
7409 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
7410 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
7411 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
7412 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
7413 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
7414 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
7415 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
7416 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
7417 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
7418 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
7419 {BLACKNESS, "BLACKNESS", DD_OK},
7420 {WHITENESS, "WHITENESS", DD_OK},
7421 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
7424 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7425 0, 0, 640, 480, 0, 0, 0, 0);
7426 ddraw = create_ddraw();
7427 ok(!!ddraw, "Failed to create a ddraw object.\n");
7428 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
7430 skip("Failed to create a 3D device, skipping test.\n");
7431 DestroyWindow(window);
7432 IDirectDraw_Release(ddraw);
7433 return;
7436 hr = IDirectDraw_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
7437 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
7438 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7439 num_fourcc_codes * sizeof(*fourcc_codes));
7440 if (!fourcc_codes)
7441 goto done;
7442 hr = IDirectDraw_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
7443 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
7444 for (i = 0; i < num_fourcc_codes; i++)
7446 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
7447 support_yuy2 = TRUE;
7448 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
7449 support_uyvy = TRUE;
7451 HeapFree(GetProcessHeap(), 0, fourcc_codes);
7453 memset(&hal_caps, 0, sizeof(hal_caps));
7454 hal_caps.dwSize = sizeof(hal_caps);
7455 hr = IDirectDraw_GetCaps(ddraw, &hal_caps, NULL);
7456 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7458 if ((!support_yuy2 && !support_uyvy) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
7459 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
7461 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
7463 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
7464 memset(&fx, 0, sizeof(fx));
7465 fx.dwSize = sizeof(fx);
7466 U5(fx).dwFillColor = 0xdeadbeef;
7468 memset(&surface_desc, 0, sizeof(surface_desc));
7469 surface_desc.dwSize = sizeof(surface_desc);
7470 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7471 surface_desc.dwWidth = 64;
7472 surface_desc.dwHeight = 64;
7473 surface_desc.ddpfPixelFormat = tests[i].format;
7474 surface_desc.ddsCaps.dwCaps = tests[i].caps;
7476 if (tests[i].caps & DDSCAPS_TEXTURE)
7478 struct format_support_check check = {&tests[i].format, FALSE};
7479 hr = IDirect3DDevice_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
7480 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
7481 if (!check.supported)
7482 continue;
7485 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !support_yuy2)
7486 continue;
7487 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !support_uyvy)
7488 continue;
7489 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
7490 continue;
7492 if (tests[i].caps & DDSCAPS_ZBUFFER)
7494 surface_desc.dwFlags &= ~DDSD_PIXELFORMAT;
7495 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
7496 U2(surface_desc).dwZBufferBitDepth = get_device_z_depth(device);
7499 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7500 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, surface %s.\n", hr, tests[i].name);
7502 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7503 todo_wine_if (tests[i].format.dwFourCC)
7504 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
7505 hr, tests[i].colorfill_hr, tests[i].name);
7507 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7508 todo_wine_if (tests[i].format.dwFourCC)
7509 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
7510 hr, tests[i].colorfill_hr, tests[i].name);
7512 if (SUCCEEDED(hr) && tests[i].check_result)
7514 memset(&surface_desc, 0, sizeof(surface_desc));
7515 surface_desc.dwSize = sizeof(surface_desc);
7516 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
7517 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
7518 color = surface_desc.lpSurface;
7519 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
7520 *color, tests[i].result, tests[i].name);
7521 hr = IDirectDrawSurface_Unlock(surface, NULL);
7522 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
7525 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7526 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
7527 hr, tests[i].depthfill_hr, tests[i].name);
7528 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7529 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
7530 hr, tests[i].depthfill_hr, tests[i].name);
7532 U5(fx).dwFillColor = 0xdeadbeef;
7533 fx.dwROP = BLACKNESS;
7534 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
7535 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
7536 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
7537 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
7538 U5(fx).dwFillColor, tests[i].name);
7540 if (SUCCEEDED(hr) && tests[i].check_result)
7542 memset(&surface_desc, 0, sizeof(surface_desc));
7543 surface_desc.dwSize = sizeof(surface_desc);
7544 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
7545 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
7546 color = surface_desc.lpSurface;
7547 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
7548 *color, tests[i].name);
7549 hr = IDirectDrawSurface_Unlock(surface, NULL);
7550 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
7553 fx.dwROP = WHITENESS;
7554 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
7555 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
7556 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
7557 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
7558 U5(fx).dwFillColor, tests[i].name);
7560 if (SUCCEEDED(hr) && tests[i].check_result)
7562 memset(&surface_desc, 0, sizeof(surface_desc));
7563 surface_desc.dwSize = sizeof(surface_desc);
7564 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
7565 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
7566 color = surface_desc.lpSurface;
7567 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
7568 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
7569 *color, tests[i].name);
7570 hr = IDirectDrawSurface_Unlock(surface, NULL);
7571 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
7574 IDirectDrawSurface_Release(surface);
7577 memset(&fx, 0, sizeof(fx));
7578 fx.dwSize = sizeof(fx);
7579 U5(fx).dwFillColor = 0xdeadbeef;
7580 fx.dwROP = WHITENESS;
7582 memset(&surface_desc, 0, sizeof(surface_desc));
7583 surface_desc.dwSize = sizeof(surface_desc);
7584 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7585 surface_desc.dwWidth = 64;
7586 surface_desc.dwHeight = 64;
7587 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
7588 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
7589 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
7590 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7591 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7592 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
7593 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
7594 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7595 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7596 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7597 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7599 /* No DDBLTFX. */
7600 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
7601 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7602 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
7603 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7605 /* Unused source rectangle. */
7606 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7607 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
7608 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
7609 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
7611 /* Unused source surface. */
7612 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7613 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7614 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
7615 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
7616 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7617 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7618 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
7619 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
7621 /* Inverted destination or source rectangle. */
7622 SetRect(&rect, 5, 7, 7, 5);
7623 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7624 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
7625 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7626 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
7627 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7628 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7629 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7630 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7631 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
7632 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
7634 /* Negative rectangle. */
7635 SetRect(&rect, -1, -1, 5, 5);
7636 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7637 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
7638 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7639 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
7640 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7641 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7642 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7643 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7644 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
7645 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
7647 /* Out of bounds rectangle. */
7648 SetRect(&rect, 0, 0, 65, 65);
7649 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7650 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
7651 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
7652 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
7654 /* Combine multiple flags. */
7655 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7656 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
7657 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
7658 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7659 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
7660 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7662 for (i = 0; i < sizeof(rops) / sizeof(*rops); i++)
7664 fx.dwROP = rops[i].rop;
7665 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
7666 ok(hr == rops[i].hr, "Got unexpected hr %#x for rop %s.\n", hr, rops[i].name);
7669 IDirectDrawSurface_Release(surface2);
7670 IDirectDrawSurface_Release(surface);
7672 memset(&surface_desc, 0, sizeof(surface_desc));
7673 surface_desc.dwSize = sizeof(surface_desc);
7674 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_ZBUFFERBITDEPTH;
7675 surface_desc.dwWidth = 64;
7676 surface_desc.dwHeight = 64;
7677 U2(surface_desc).dwZBufferBitDepth = get_device_z_depth(device);
7678 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
7679 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7680 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7681 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7682 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7684 /* No DDBLTFX. */
7685 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
7686 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7688 /* Unused source rectangle. */
7689 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7690 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
7692 /* Unused source surface. */
7693 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7694 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7695 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7696 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7698 /* Inverted destination or source rectangle. */
7699 SetRect(&rect, 5, 7, 7, 5);
7700 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7701 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
7702 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7703 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
7704 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7705 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7706 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7707 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7709 /* Negative rectangle. */
7710 SetRect(&rect, -1, -1, 5, 5);
7711 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7712 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
7713 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7714 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
7715 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7716 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7717 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7718 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7720 /* Out of bounds rectangle. */
7721 SetRect(&rect, 0, 0, 65, 65);
7722 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7723 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
7725 /* Combine multiple flags. */
7726 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7727 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7729 IDirectDrawSurface_Release(surface2);
7730 IDirectDrawSurface_Release(surface);
7732 done:
7733 IDirect3DDevice_Release(device);
7734 refcount = IDirectDraw_Release(ddraw);
7735 ok(refcount == 0, "Ddraw object not properly released, refcount %u.\n", refcount);
7736 DestroyWindow(window);
7739 static void test_colorkey_precision(void)
7741 static D3DTLVERTEX quad[] =
7743 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0x00000000}, {0x00000000}, {0.0f}, {1.0f}},
7744 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0x00000000}, {0x00000000}, {0.0f}, {0.0f}},
7745 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0x00000000}, {0x00000000}, {1.0f}, {1.0f}},
7746 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0x00000000}, {0x00000000}, {1.0f}, {0.0f}},
7748 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
7749 IDirect3DDevice *device;
7750 IDirectDraw *ddraw;
7751 IDirectDrawSurface *rt;
7752 IDirect3DViewport *viewport;
7753 IDirect3DExecuteBuffer *execute_buffer;
7754 D3DEXECUTEBUFFERDESC exec_desc;
7755 UINT inst_length;
7756 void *ptr;
7757 HWND window;
7758 HRESULT hr;
7759 IDirectDrawSurface *src, *dst, *texture;
7760 D3DTEXTUREHANDLE handle;
7761 IDirect3DTexture *d3d_texture;
7762 IDirect3DMaterial *green;
7763 DDSURFACEDESC surface_desc, lock_desc;
7764 ULONG refcount;
7765 D3DCOLOR color;
7766 unsigned int t, c;
7767 DDCOLORKEY ckey;
7768 DDBLTFX fx;
7769 DWORD data[4] = {0}, color_mask;
7770 BOOL is_nvidia, is_warp;
7771 static const struct
7773 unsigned int max, shift, bpp, clear;
7774 const char *name;
7775 BOOL skip_nv;
7776 DDPIXELFORMAT fmt;
7778 tests[] =
7781 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8", FALSE,
7783 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
7784 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
7789 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel", FALSE,
7791 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
7792 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
7797 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel", FALSE,
7799 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
7800 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
7805 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4", TRUE,
7807 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
7808 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
7813 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7814 0, 0, 640, 480, 0, 0, 0, 0);
7815 ddraw = create_ddraw();
7816 ok(!!ddraw, "Failed to create a ddraw object.\n");
7817 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
7819 skip("Failed to create a 3D device, skipping test.\n");
7820 DestroyWindow(window);
7821 IDirectDraw_Release(ddraw);
7822 return;
7824 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
7825 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
7827 is_nvidia = ddraw_is_nvidia(ddraw);
7828 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
7829 * (color key doesn't match although the values are equal), and a false
7830 * positive when the color key is 0 and the texture contains the value 1.
7831 * I don't want to mark this broken unconditionally since this would
7832 * essentially disable the test on Windows. Also on random occasions
7833 * 254 == 255 and 255 != 255.*/
7834 is_warp = ddraw_is_warp(ddraw);
7836 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
7837 viewport = create_viewport(device, 0, 0, 640, 480);
7838 viewport_set_background(device, viewport, green);
7840 memset(&exec_desc, 0, sizeof(exec_desc));
7841 exec_desc.dwSize = sizeof(exec_desc);
7842 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
7843 exec_desc.dwBufferSize = 1024;
7844 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
7845 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
7846 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
7848 memset(&fx, 0, sizeof(fx));
7849 fx.dwSize = sizeof(fx);
7850 memset(&lock_desc, 0, sizeof(lock_desc));
7851 lock_desc.dwSize = sizeof(lock_desc);
7853 for (t = 0; t < sizeof(tests) / sizeof(*tests); ++t)
7855 if (is_nvidia && tests[t].skip_nv)
7857 win_skip("Skipping test %s on Nvidia Windows drivers.\n", tests[t].name);
7858 continue;
7861 memset(&surface_desc, 0, sizeof(surface_desc));
7862 surface_desc.dwSize = sizeof(surface_desc);
7863 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7864 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7865 surface_desc.dwWidth = 4;
7866 surface_desc.dwHeight = 1;
7867 surface_desc.ddpfPixelFormat = tests[t].fmt;
7868 /* Windows XP (at least with the r200 driver, other drivers untested) produces
7869 * garbage when doing color keyed texture->texture blits. */
7870 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src, NULL);
7871 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7872 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst, NULL);
7873 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7875 U5(fx).dwFillColor = tests[t].clear;
7876 /* On the w8 testbot (WARP driver) the blit result has different values in the
7877 * X channel. */
7878 color_mask = U2(tests[t].fmt).dwRBitMask
7879 | U3(tests[t].fmt).dwGBitMask
7880 | U4(tests[t].fmt).dwBBitMask;
7882 for (c = 0; c <= tests[t].max; ++c)
7884 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
7885 * texture after it has been set once... */
7886 surface_desc.dwFlags |= DDSD_CKSRCBLT;
7887 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
7888 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
7889 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
7890 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &texture, NULL);
7891 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7893 hr = IDirectDrawSurface_QueryInterface(texture, &IID_IDirect3DTexture, (void **)&d3d_texture);
7894 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
7895 hr = IDirect3DTexture_GetHandle(d3d_texture, device, &handle);
7896 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
7897 IDirect3DTexture_Release(d3d_texture);
7899 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
7900 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
7902 memcpy(exec_desc.lpData, quad, sizeof(quad));
7904 ptr = ((BYTE *)exec_desc.lpData) + sizeof(quad);
7905 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 8);
7906 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
7907 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, handle);
7908 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATEALPHA);
7909 /* D3DRENDERSTATE_COLORKEYENABLE is supposed to be on by default on version
7910 * 1 devices, but for some reason it randomly defaults to FALSE on the W8
7911 * testbot. This is either the fault of Windows 8 or the WARP driver.
7912 * Also D3DRENDERSTATE_COLORKEYENABLE was introduced in D3D 5 aka version 2
7913 * devices only, which might imply this doesn't actually do anything on
7914 * WARP. */
7915 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
7917 emit_tquad(&ptr, 0);
7918 emit_tquad(&ptr, 4);
7919 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
7920 emit_end(&ptr);
7922 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
7923 inst_length -= sizeof(quad);
7924 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
7925 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
7926 set_execute_data(execute_buffer, 8, sizeof(quad), inst_length);
7928 hr = IDirectDrawSurface_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7929 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
7931 hr = IDirectDrawSurface_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
7932 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7933 switch (tests[t].bpp)
7935 case 4:
7936 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
7937 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
7938 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
7939 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
7940 break;
7942 case 2:
7943 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
7944 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
7945 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
7946 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
7947 break;
7949 hr = IDirectDrawSurface_Unlock(src, 0);
7950 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7951 hr = IDirectDrawSurface_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
7952 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
7954 ckey.dwColorSpaceLowValue = c << tests[t].shift;
7955 ckey.dwColorSpaceHighValue = c << tests[t].shift;
7956 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
7957 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
7959 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
7960 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
7962 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
7963 hr = IDirectDrawSurface_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
7964 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7965 switch (tests[t].bpp)
7967 case 4:
7968 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
7969 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
7970 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
7971 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
7972 break;
7974 case 2:
7975 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
7976 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
7977 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
7978 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
7979 break;
7981 hr = IDirectDrawSurface_Unlock(dst, 0);
7982 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7984 if (!c)
7986 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
7987 tests[t].clear, data[0], tests[t].name, c);
7989 if (data[3] == tests[t].clear)
7991 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
7992 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
7993 * even when a different surface is used. The blit itself doesn't draw anything,
7994 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
7995 * never be masked out by the key.
7997 * On Windows 10 the problem is worse, Blt just hangs. For this reason the ARGB4444
7998 * test is disabled entirely.
8000 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
8001 * terrible on WARP. */
8002 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
8003 IDirectDrawSurface_Release(texture);
8004 IDirectDrawSurface_Release(src);
8005 IDirectDrawSurface_Release(dst);
8006 goto done;
8009 else
8010 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
8011 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
8013 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
8014 tests[t].clear, data[1], tests[t].name, c);
8016 if (c == tests[t].max)
8017 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
8018 tests[t].clear, data[2], tests[t].name, c);
8019 else
8020 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
8021 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
8023 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8024 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
8026 hr = IDirect3DDevice_BeginScene(device);
8027 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8028 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_UNCLIPPED);
8029 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8030 hr = IDirect3DDevice_EndScene(device);
8031 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8033 color = get_surface_color(rt, 80, 240);
8034 if (!c)
8035 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
8036 "Got unexpected color 0x%08x, format %s, c=%u.\n",
8037 color, tests[t].name, c);
8038 else
8039 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
8040 "Got unexpected color 0x%08x, format %s, c=%u.\n",
8041 color, tests[t].name, c);
8043 color = get_surface_color(rt, 240, 240);
8044 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
8045 "Got unexpected color 0x%08x, format %s, c=%u.\n",
8046 color, tests[t].name, c);
8048 color = get_surface_color(rt, 400, 240);
8049 if (c == tests[t].max)
8050 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
8051 "Got unexpected color 0x%08x, format %s, c=%u.\n",
8052 color, tests[t].name, c);
8053 else
8054 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
8055 "Got unexpected color 0x%08x, format %s, c=%u.\n",
8056 color, tests[t].name, c);
8058 IDirectDrawSurface_Release(texture);
8060 IDirectDrawSurface_Release(src);
8061 IDirectDrawSurface_Release(dst);
8063 done:
8065 destroy_viewport(device, viewport);
8066 destroy_material(green);
8067 IDirectDrawSurface_Release(rt);
8068 IDirect3DExecuteBuffer_Release(execute_buffer);
8069 IDirect3DDevice_Release(device);
8070 refcount = IDirectDraw_Release(ddraw);
8071 ok(refcount == 0, "Ddraw object not properly released, refcount %u.\n", refcount);
8072 DestroyWindow(window);
8075 static void test_range_colorkey(void)
8077 IDirectDraw *ddraw;
8078 HWND window;
8079 HRESULT hr;
8080 IDirectDrawSurface *surface;
8081 DDSURFACEDESC surface_desc;
8082 ULONG refcount;
8083 DDCOLORKEY ckey;
8085 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8086 0, 0, 640, 480, 0, 0, 0, 0);
8087 ddraw = create_ddraw();
8088 ok(!!ddraw, "Failed to create a ddraw object.\n");
8089 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8090 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8092 memset(&surface_desc, 0, sizeof(surface_desc));
8093 surface_desc.dwSize = sizeof(surface_desc);
8094 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
8095 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
8096 surface_desc.dwWidth = 1;
8097 surface_desc.dwHeight = 1;
8098 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
8099 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
8100 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8101 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8102 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
8103 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
8105 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
8106 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
8107 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
8108 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8109 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
8111 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
8112 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
8113 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8114 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
8116 /* Same for DDSCAPS_OFFSCREENPLAIN. */
8117 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8118 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
8119 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
8120 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8121 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
8123 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
8124 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
8125 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8126 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
8128 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
8129 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
8130 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8131 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8133 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
8134 ckey.dwColorSpaceLowValue = 0x00000000;
8135 ckey.dwColorSpaceHighValue = 0x00000001;
8136 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
8137 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
8139 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
8140 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
8141 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
8142 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
8144 ckey.dwColorSpaceLowValue = 0x00000001;
8145 ckey.dwColorSpaceHighValue = 0x00000000;
8146 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
8147 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
8149 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
8150 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
8151 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
8152 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
8154 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
8155 ckey.dwColorSpaceLowValue = 0x00000000;
8156 ckey.dwColorSpaceHighValue = 0x00000000;
8157 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
8158 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
8160 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
8161 ckey.dwColorSpaceLowValue = 0x00000001;
8162 ckey.dwColorSpaceHighValue = 0x00000000;
8163 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
8164 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
8165 ckey.dwColorSpaceLowValue = 0x00000000;
8166 ckey.dwColorSpaceHighValue = 0x00000001;
8167 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
8168 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
8169 /* Range destination keys don't work either. */
8170 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
8171 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
8173 /* Just to show it's not because of A, R, and G having equal values. */
8174 ckey.dwColorSpaceLowValue = 0x00000000;
8175 ckey.dwColorSpaceHighValue = 0x01010101;
8176 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
8177 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
8179 /* None of these operations modified the key. */
8180 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
8181 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
8182 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
8183 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
8185 IDirectDrawSurface_Release(surface),
8186 refcount = IDirectDraw_Release(ddraw);
8187 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8188 DestroyWindow(window);
8191 static void test_shademode(void)
8193 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
8194 IDirect3DExecuteBuffer *execute_buffer;
8195 D3DEXECUTEBUFFERDESC exec_desc;
8196 IDirect3DMaterial *background;
8197 IDirect3DViewport *viewport;
8198 IDirect3DDevice *device;
8199 IDirectDrawSurface *rt;
8200 const D3DLVERTEX *quad;
8201 DWORD color0, color1;
8202 UINT i, inst_length;
8203 IDirectDraw *ddraw;
8204 ULONG refcount;
8205 HWND window;
8206 HRESULT hr;
8207 void *ptr;
8208 static const D3DLVERTEX quad_strip[] =
8210 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}},
8211 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
8212 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
8213 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffffffff}},
8215 quad_list[] =
8217 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
8218 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}},
8219 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
8220 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffffffff}},
8222 static const struct
8224 DWORD primtype;
8225 DWORD shademode;
8226 DWORD color0, color1;
8228 tests[] =
8230 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
8231 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
8232 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
8233 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
8234 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x000000ff, 0x0000ff00},
8235 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
8238 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8239 0, 0, 640, 480, 0, 0, 0, 0);
8240 ddraw = create_ddraw();
8241 ok(!!ddraw, "Failed to create a ddraw object.\n");
8242 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
8244 skip("Failed to create a 3D device, skipping test.\n");
8245 IDirectDraw_Release(ddraw);
8246 DestroyWindow(window);
8247 return;
8250 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
8251 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8253 background = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
8254 viewport = create_viewport(device, 0, 0, 640, 480);
8255 viewport_set_background(device, viewport, background);
8257 memset(&exec_desc, 0, sizeof(exec_desc));
8258 exec_desc.dwSize = sizeof(exec_desc);
8259 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
8260 exec_desc.dwBufferSize = 1024;
8261 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
8263 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
8264 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
8266 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
8267 * the color fixups we have to do for FLAT shading will be dependent on that. */
8269 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
8271 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8272 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8274 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
8275 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
8277 quad = tests[i].primtype == D3DPT_TRIANGLESTRIP ? quad_strip : quad_list;
8278 memcpy(exec_desc.lpData, quad, sizeof(quad_strip));
8279 ptr = ((BYTE *)exec_desc.lpData) + sizeof(quad_strip);
8280 emit_set_rs(&ptr, D3DRENDERSTATE_CLIPPING, FALSE);
8281 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, FALSE);
8282 emit_set_rs(&ptr, D3DRENDERSTATE_FOGENABLE, FALSE);
8283 emit_set_rs(&ptr, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
8284 emit_set_rs(&ptr, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
8286 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORM, 0, 4);
8287 if (tests[i].primtype == D3DPT_TRIANGLESTRIP)
8288 emit_tquad(&ptr, 0);
8289 else
8290 emit_tquad_tlist(&ptr, 0);
8291 emit_end(&ptr);
8292 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
8293 inst_length -= sizeof(quad_strip);
8295 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
8296 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
8298 hr = IDirect3DDevice_BeginScene(device);
8299 set_execute_data(execute_buffer, 4, sizeof(quad_strip), inst_length);
8300 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
8301 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
8302 hr = IDirect3DDevice_EndScene(device);
8303 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8305 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
8306 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
8308 /* For D3DSHADE_FLAT it should take the color of the first vertex of
8309 * each triangle. This requires EXT_provoking_vertex or similar
8310 * functionality being available. */
8311 /* PHONG should be the same as GOURAUD, since no hardware implements
8312 * this. */
8313 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
8314 i, color0, tests[i].color0);
8315 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
8316 i, color1, tests[i].color1);
8319 IDirect3DExecuteBuffer_Release(execute_buffer);
8320 destroy_viewport(device, viewport);
8321 destroy_material(background);
8322 IDirectDrawSurface_Release(rt);
8323 refcount = IDirect3DDevice_Release(device);
8324 ok(!refcount, "Device has %u references left.\n", refcount);
8325 IDirectDraw_Release(ddraw);
8326 DestroyWindow(window);
8329 static void test_lockrect_invalid(void)
8331 unsigned int i, r;
8332 IDirectDraw *ddraw;
8333 IDirectDrawSurface *surface;
8334 HWND window;
8335 HRESULT hr;
8336 DDSURFACEDESC surface_desc;
8337 DDCAPS hal_caps;
8338 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
8339 static RECT valid[] =
8341 {60, 60, 68, 68},
8342 {60, 60, 60, 68},
8343 {60, 60, 68, 60},
8344 {120, 60, 128, 68},
8345 {60, 120, 68, 128},
8347 static RECT invalid[] =
8349 {68, 60, 60, 68}, /* left > right */
8350 {60, 68, 68, 60}, /* top > bottom */
8351 {-8, 60, 0, 68}, /* left < surface */
8352 {60, -8, 68, 0}, /* top < surface */
8353 {-16, 60, -8, 68}, /* right < surface */
8354 {60, -16, 68, -8}, /* bottom < surface */
8355 {60, 60, 136, 68}, /* right > surface */
8356 {60, 60, 68, 136}, /* bottom > surface */
8357 {136, 60, 144, 68}, /* left > surface */
8358 {60, 136, 68, 144}, /* top > surface */
8360 static const struct
8362 DWORD caps;
8363 const char *name;
8364 HRESULT hr;
8366 resources[] =
8368 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, "sysmem offscreenplain", DDERR_INVALIDPARAMS},
8369 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, "vidmem offscreenplain", DDERR_INVALIDPARAMS},
8370 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "sysmem texture", DDERR_INVALIDPARAMS},
8371 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "vidmem texture", DDERR_INVALIDPARAMS},
8374 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8375 0, 0, 640, 480, 0, 0, 0, 0);
8376 ddraw = create_ddraw();
8377 ok(!!ddraw, "Failed to create a ddraw object.\n");
8378 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8379 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8381 memset(&hal_caps, 0, sizeof(hal_caps));
8382 hal_caps.dwSize = sizeof(hal_caps);
8383 hr = IDirectDraw_GetCaps(ddraw, &hal_caps, NULL);
8384 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8385 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
8387 skip("Required surface types not supported, skipping test.\n");
8388 goto done;
8391 for (r = 0; r < sizeof(resources) / sizeof(*resources); ++r)
8393 memset(&surface_desc, 0, sizeof(surface_desc));
8394 surface_desc.dwSize = sizeof(surface_desc);
8395 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8396 surface_desc.ddsCaps.dwCaps = resources[r].caps;
8397 surface_desc.dwWidth = 128;
8398 surface_desc.dwHeight = 128;
8399 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
8400 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
8401 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
8402 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xff0000;
8403 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x00ff00;
8404 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x0000ff;
8406 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8407 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, resources[r].name);
8409 hr = IDirectDrawSurface_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
8410 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
8412 for (i = 0; i < sizeof(valid) / sizeof(*valid); ++i)
8414 RECT *rect = &valid[i];
8416 memset(&surface_desc, 0, sizeof(surface_desc));
8417 surface_desc.dwSize = sizeof(surface_desc);
8419 hr = IDirectDrawSurface_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
8420 ok(SUCCEEDED(hr), "Lock failed (%#x) for rect %s, type %s.\n",
8421 hr, wine_dbgstr_rect(rect), resources[r].name);
8423 hr = IDirectDrawSurface_Unlock(surface, NULL);
8424 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
8427 for (i = 0; i < sizeof(invalid) / sizeof(*invalid); ++i)
8429 RECT *rect = &invalid[i];
8431 memset(&surface_desc, 1, sizeof(surface_desc));
8432 surface_desc.dwSize = sizeof(surface_desc);
8434 hr = IDirectDrawSurface_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
8435 ok(hr == resources[r].hr, "Lock returned %#x for rect %s, type %s.\n",
8436 hr, wine_dbgstr_rect(rect), resources[r].name);
8437 if (SUCCEEDED(hr))
8439 hr = IDirectDrawSurface_Unlock(surface, NULL);
8440 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
8442 else
8443 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8446 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
8447 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#x, type %s.\n",
8448 hr, resources[r].name);
8449 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
8450 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#x, type %s.\n",
8451 hr, resources[r].name);
8452 hr = IDirectDrawSurface_Unlock(surface, NULL);
8453 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
8455 hr = IDirectDrawSurface_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
8456 ok(SUCCEEDED(hr), "Lock(rect = %s) failed (%#x).\n", wine_dbgstr_rect(&valid[0]), hr);
8457 hr = IDirectDrawSurface_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
8458 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = %s) failed (%#x).\n",
8459 wine_dbgstr_rect(&valid[0]), hr);
8461 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
8462 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
8464 hr = IDirectDrawSurface_Unlock(surface, NULL);
8465 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
8467 IDirectDrawSurface_Release(surface);
8470 done:
8471 IDirectDraw_Release(ddraw);
8472 DestroyWindow(window);
8475 static void test_yv12_overlay(void)
8477 IDirectDrawSurface *src_surface, *dst_surface;
8478 RECT rect = {13, 17, 14, 18};
8479 unsigned int offset, y;
8480 unsigned char *base;
8481 DDSURFACEDESC desc;
8482 IDirectDraw *ddraw;
8483 HWND window;
8484 HRESULT hr;
8486 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8487 0, 0, 640, 480, 0, 0, 0, 0);
8488 ddraw = create_ddraw();
8489 ok(!!ddraw, "Failed to create a ddraw object.\n");
8490 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8491 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8493 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
8495 skip("Failed to create a YV12 overlay, skipping test.\n");
8496 goto done;
8499 memset(&desc, 0, sizeof(desc));
8500 desc.dwSize = sizeof(desc);
8501 hr = IDirectDrawSurface_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
8502 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8504 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
8505 "Got unexpected flags %#x.\n", desc.dwFlags);
8506 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
8507 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
8508 "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps);
8509 ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth);
8510 ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight);
8511 /* The overlay pitch seems to have 256 byte alignment. */
8512 ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch);
8514 /* Fill the surface with some data for the blit test. */
8515 base = desc.lpSurface;
8516 /* Luminance */
8517 for (y = 0; y < desc.dwHeight; ++y)
8519 memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth);
8521 /* V */
8522 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
8524 memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth);
8526 /* U */
8527 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
8529 memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth);
8532 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
8533 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8535 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
8536 * other block-based formats like DXT the entire Y channel is stored in
8537 * one big chunk of memory, followed by the chroma channels. So partial
8538 * locks do not really make sense. Show that they are allowed nevertheless
8539 * and the offset points into the luminance data. */
8540 hr = IDirectDrawSurface_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
8541 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8542 offset = ((const unsigned char *)desc.lpSurface - base);
8543 ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n",
8544 offset, rect.top * U1(desc).lPitch + rect.left);
8545 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
8546 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8548 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
8550 /* Windows XP with a Radeon X1600 GPU refuses to create a second
8551 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
8552 skip("Failed to create a second YV12 surface, skipping blit test.\n");
8553 IDirectDrawSurface_Release(src_surface);
8554 goto done;
8557 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
8558 /* VMware rejects YV12 blits. This behavior has not been seen on real
8559 * hardware yet, so mark it broken. */
8560 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr);
8562 if (SUCCEEDED(hr))
8564 memset(&desc, 0, sizeof(desc));
8565 desc.dwSize = sizeof(desc);
8566 hr = IDirectDrawSurface_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
8567 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8569 base = desc.lpSurface;
8570 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
8571 base += desc.dwHeight * U1(desc).lPitch;
8572 todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
8573 base += desc.dwHeight / 4 * U1(desc).lPitch;
8574 todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
8576 hr = IDirectDrawSurface_Unlock(dst_surface, NULL);
8577 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8580 IDirectDrawSurface_Release(dst_surface);
8581 IDirectDrawSurface_Release(src_surface);
8582 done:
8583 IDirectDraw_Release(ddraw);
8584 DestroyWindow(window);
8587 static BOOL dwm_enabled(void)
8589 BOOL ret = FALSE;
8591 if (!strcmp(winetest_platform, "wine"))
8592 return FALSE;
8593 if (!pDwmIsCompositionEnabled)
8594 return FALSE;
8595 if (FAILED(pDwmIsCompositionEnabled(&ret)))
8596 return FALSE;
8597 return ret;
8600 static void test_offscreen_overlay(void)
8602 IDirectDrawSurface *overlay, *offscreen, *primary;
8603 DDSURFACEDESC surface_desc;
8604 IDirectDraw *ddraw;
8605 HWND window;
8606 HRESULT hr;
8607 HDC dc;
8609 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8610 0, 0, 640, 480, 0, 0, 0, 0);
8611 ddraw = create_ddraw();
8612 ok(!!ddraw, "Failed to create a ddraw object.\n");
8613 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8614 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8616 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
8618 skip("Failed to create a UYVY overlay, skipping test.\n");
8619 goto done;
8622 memset(&surface_desc, 0, sizeof(surface_desc));
8623 surface_desc.dwSize = sizeof(surface_desc);
8624 surface_desc.dwFlags = DDSD_CAPS;
8625 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8626 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
8627 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
8629 /* On Windows 7, and probably Vista, UpdateOverlay() will return
8630 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
8631 * surface prevents this by disabling the dwm. */
8632 hr = IDirectDrawSurface_GetDC(primary, &dc);
8633 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8634 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
8635 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8637 /* Try to overlay a NULL surface. */
8638 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
8639 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8640 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
8641 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8643 /* Try to overlay an offscreen surface. */
8644 memset(&surface_desc, 0, sizeof(surface_desc));
8645 surface_desc.dwSize = sizeof(surface_desc);
8646 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
8647 surface_desc.dwWidth = 64;
8648 surface_desc.dwHeight = 64;
8649 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8650 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
8651 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
8652 surface_desc.ddpfPixelFormat.dwFourCC = 0;
8653 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
8654 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xf800;
8655 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x07e0;
8656 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x001f;
8657 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
8658 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
8660 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
8661 ok(SUCCEEDED(hr) || broken(hr == DDERR_OUTOFCAPS && dwm_enabled()),
8662 "Failed to update overlay, hr %#x.\n", hr);
8664 /* Try to overlay the primary with a non-overlay surface. */
8665 hr = IDirectDrawSurface_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
8666 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
8667 hr = IDirectDrawSurface_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_HIDE, NULL);
8668 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
8670 IDirectDrawSurface_Release(offscreen);
8671 IDirectDrawSurface_Release(primary);
8672 IDirectDrawSurface_Release(overlay);
8673 done:
8674 IDirectDraw_Release(ddraw);
8675 DestroyWindow(window);
8678 static void test_overlay_rect(void)
8680 IDirectDrawSurface *overlay, *primary = NULL;
8681 DDSURFACEDESC surface_desc;
8682 RECT rect = {0, 0, 64, 64};
8683 IDirectDraw *ddraw;
8684 LONG pos_x, pos_y;
8685 HRESULT hr, hr2;
8686 HWND window;
8687 HDC dc;
8689 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8690 0, 0, 640, 480, 0, 0, 0, 0);
8691 ddraw = create_ddraw();
8692 ok(!!ddraw, "Failed to create a ddraw object.\n");
8693 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8694 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8696 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
8698 skip("Failed to create a UYVY overlay, skipping test.\n");
8699 goto done;
8702 memset(&surface_desc, 0, sizeof(surface_desc));
8703 surface_desc.dwSize = sizeof(surface_desc);
8704 surface_desc.dwFlags = DDSD_CAPS;
8705 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8706 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
8707 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
8709 /* On Windows 7, and probably Vista, UpdateOverlay() will return
8710 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
8711 * surface prevents this by disabling the dwm. */
8712 hr = IDirectDrawSurface_GetDC(primary, &dc);
8713 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8714 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
8715 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8717 /* On Windows 8 and newer DWM can't be turned off, making overlays unusable. */
8718 if (dwm_enabled())
8720 win_skip("Cannot disable DWM, skipping overlay test.\n");
8721 goto done;
8724 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is
8725 * used. This is not true in Windows Vista and earlier, but changed in
8726 * Windows 7. */
8727 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
8728 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
8729 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
8730 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
8731 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
8732 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8734 /* Show that the overlay position is the (top, left) coordinate of the
8735 * destination rectangle. */
8736 OffsetRect(&rect, 32, 16);
8737 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
8738 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
8739 pos_x = -1; pos_y = -1;
8740 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
8741 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
8742 ok(pos_x == rect.left, "Got unexpected pos_x %d, expected %d.\n", pos_x, rect.left);
8743 ok(pos_y == rect.top, "Got unexpected pos_y %d, expected %d.\n", pos_y, rect.top);
8745 /* Passing a NULL dest rect sets the position to 0/0. Visually it can be
8746 * seen that the overlay overlays the whole primary(==screen). */
8747 hr2 = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
8748 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS || hr2 == DDERR_OUTOFCAPS, "Got unexpected hr %#x.\n", hr2);
8749 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
8750 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
8751 if (SUCCEEDED(hr2))
8753 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
8754 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
8756 else
8758 ok(pos_x == 32, "Got unexpected pos_x %d.\n", pos_x);
8759 ok(pos_y == 16, "Got unexpected pos_y %d.\n", pos_y);
8762 /* The position cannot be retrieved when the overlay is not shown. */
8763 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
8764 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
8765 pos_x = -1; pos_y = -1;
8766 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
8767 ok(hr == DDERR_OVERLAYNOTVISIBLE, "Got unexpected hr %#x.\n", hr);
8768 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
8769 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
8771 IDirectDrawSurface_Release(overlay);
8772 done:
8773 if (primary)
8774 IDirectDrawSurface_Release(primary);
8775 IDirectDraw_Release(ddraw);
8776 DestroyWindow(window);
8779 static void test_blt(void)
8781 IDirectDrawSurface *surface, *rt;
8782 DDSURFACEDESC surface_desc;
8783 IDirect3DDevice *device;
8784 IDirectDraw *ddraw;
8785 unsigned int i;
8786 ULONG refcount;
8787 HWND window;
8788 HRESULT hr;
8790 static struct
8792 RECT src_rect;
8793 RECT dst_rect;
8794 HRESULT hr;
8796 test_data[] =
8798 {{160, 0, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit. */
8799 {{160, 480, 640, 0}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, flipped source. */
8800 {{640, 0, 160, 480}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, mirrored source. */
8801 {{160, 0, 480, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched x. */
8802 {{160, 160, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched y. */
8803 {{ 0, 0, 640, 480}, { 0, 0, 640, 480}, DD_OK}, /* Full surface blit. */
8804 {{ 0, 0, 640, 480}, { 0, 480, 640, 0}, DDERR_INVALIDRECT}, /* Full surface, flipped destination. */
8805 {{ 0, 0, 640, 480}, {640, 0, 0, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored destination. */
8806 {{ 0, 480, 640, 0}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, flipped source. */
8807 {{640, 0, 0, 480}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored source. */
8810 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8811 0, 0, 640, 480, 0, 0, 0, 0);
8812 ddraw = create_ddraw();
8813 ok(!!ddraw, "Failed to create a ddraw object.\n");
8814 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
8816 skip("Failed to create a 3D device, skipping test.\n");
8817 IDirectDraw_Release(ddraw);
8818 DestroyWindow(window);
8819 return;
8822 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
8823 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8825 memset(&surface_desc, 0, sizeof(surface_desc));
8826 surface_desc.dwSize = sizeof(surface_desc);
8827 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
8828 surface_desc.dwWidth = 640;
8829 surface_desc.dwHeight = 480;
8830 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8831 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8832 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8834 hr = IDirectDrawSurface_Blt(surface, NULL, surface, NULL, 0, NULL);
8835 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
8837 hr = IDirectDrawSurface_Blt(surface, NULL, rt, NULL, 0, NULL);
8838 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
8840 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
8842 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
8843 surface, &test_data[i].src_rect, DDBLT_WAIT, NULL);
8844 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
8846 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
8847 rt, &test_data[i].src_rect, DDBLT_WAIT, NULL);
8848 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
8851 IDirectDrawSurface_Release(surface);
8852 IDirectDrawSurface_Release(rt);
8853 refcount = IDirect3DDevice_Release(device);
8854 ok(!refcount, "Device has %u references left.\n", refcount);
8855 IDirectDraw_Release(ddraw);
8856 DestroyWindow(window);
8859 static void test_getdc(void)
8861 IDirectDrawSurface *surface, *surface2, *tmp;
8862 DDSURFACEDESC surface_desc, map_desc;
8863 DDSCAPS caps = {DDSCAPS_COMPLEX};
8864 IDirectDraw *ddraw;
8865 unsigned int i;
8866 HWND window;
8867 HDC dc, dc2;
8868 HRESULT hr;
8870 static const struct
8872 const char *name;
8873 DDPIXELFORMAT format;
8874 BOOL getdc_supported;
8875 HRESULT alt_result;
8877 test_data[] =
8879 {"D3DFMT_A8R8G8B8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
8880 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}}, TRUE},
8881 {"D3DFMT_X8R8G8B8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
8882 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}}, TRUE},
8883 {"D3DFMT_R5G6B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
8884 {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}}, TRUE},
8885 {"D3DFMT_X1R5G5B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
8886 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}}, TRUE},
8887 {"D3DFMT_A1R5G5B5", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
8888 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}}, TRUE},
8889 {"D3DFMT_A4R4G4B4", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
8890 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
8891 {"D3DFMT_X4R4G4B4", {sizeof(test_data->format), DDPF_RGB, 0, {16},
8892 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
8893 {"D3DFMT_A2R10G10B10", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
8894 {0xc0000000}, {0x3ff00000}, {0x000ffc00}, {0x000003ff}}, TRUE},
8895 {"D3DFMT_A8B8G8R8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
8896 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
8897 {"D3DFMT_X8B8G8R8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
8898 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
8899 {"D3DFMT_R3G3B2", {sizeof(test_data->format), DDPF_RGB, 0, {8},
8900 {0x000000e0}, {0x0000001c}, {0x00000003}, {0x00000000}}, FALSE},
8901 /* GetDC() on a P8 surface fails unless the display mode is 8 bpp.
8902 * This is not implemented in wine yet, so disable the test for now.
8903 * Succeeding P8 GetDC() calls are tested in the ddraw:visual test.
8904 {"D3DFMT_P8", {sizeof(test_data->format), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0, {8 },
8905 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
8907 {"D3DFMT_L8", {sizeof(test_data->format), DDPF_LUMINANCE, 0, {8},
8908 {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
8909 {"D3DFMT_A8L8", {sizeof(test_data->format), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0, {16},
8910 {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}}, FALSE},
8911 {"D3DFMT_DXT1", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'), {0},
8912 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
8913 {"D3DFMT_DXT2", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'), {0},
8914 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
8915 {"D3DFMT_DXT3", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'), {0},
8916 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
8917 {"D3DFMT_DXT4", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'), {0},
8918 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
8919 {"D3DFMT_DXT5", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'), {0},
8920 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
8923 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8924 0, 0, 640, 480, 0, 0, 0, 0);
8925 ddraw = create_ddraw();
8926 ok(!!ddraw, "Failed to create a ddraw object.\n");
8927 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8928 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8930 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
8932 memset(&surface_desc, 0, sizeof(surface_desc));
8933 surface_desc.dwSize = sizeof(surface_desc);
8934 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8935 surface_desc.dwWidth = 64;
8936 surface_desc.dwHeight = 64;
8937 surface_desc.ddpfPixelFormat = test_data[i].format;
8938 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8940 if (FAILED(IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
8942 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
8943 if (FAILED(hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
8945 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
8946 continue;
8950 dc = (void *)0x1234;
8951 hr = IDirectDrawSurface_GetDC(surface, &dc);
8952 if (test_data[i].getdc_supported)
8953 ok(SUCCEEDED(hr) || (test_data[i].alt_result && hr == test_data[i].alt_result),
8954 "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
8955 else
8956 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
8958 if (SUCCEEDED(hr))
8960 unsigned int width_bytes;
8961 DIBSECTION dib;
8962 HBITMAP bitmap;
8963 DWORD type;
8964 int size;
8966 type = GetObjectType(dc);
8967 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
8968 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
8969 type = GetObjectType(bitmap);
8970 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
8972 size = GetObjectA(bitmap, sizeof(dib), &dib);
8973 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, test_data[i].name);
8974 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
8975 dib.dsBm.bmType, test_data[i].name);
8976 ok(dib.dsBm.bmWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
8977 dib.dsBm.bmWidth, test_data[i].name);
8978 ok(dib.dsBm.bmHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
8979 dib.dsBm.bmHeight, test_data[i].name);
8980 width_bytes = ((dib.dsBm.bmWidth * U1(test_data[i].format).dwRGBBitCount + 31) >> 3) & ~3;
8981 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
8982 dib.dsBm.bmWidthBytes, test_data[i].name);
8983 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
8984 dib.dsBm.bmPlanes, test_data[i].name);
8985 ok(dib.dsBm.bmBitsPixel == U1(test_data[i].format).dwRGBBitCount,
8986 "Got unexpected bit count %d for format %s.\n",
8987 dib.dsBm.bmBitsPixel, test_data[i].name);
8988 ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n",
8989 dib.dsBm.bmBits, test_data[i].name);
8991 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
8992 dib.dsBmih.biSize, test_data[i].name);
8993 ok(dib.dsBmih.biWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
8994 dib.dsBmih.biHeight, test_data[i].name);
8995 ok(dib.dsBmih.biHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
8996 dib.dsBmih.biHeight, test_data[i].name);
8997 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
8998 dib.dsBmih.biPlanes, test_data[i].name);
8999 ok(dib.dsBmih.biBitCount == U1(test_data[i].format).dwRGBBitCount,
9000 "Got unexpected bit count %u for format %s.\n",
9001 dib.dsBmih.biBitCount, test_data[i].name);
9002 ok(dib.dsBmih.biCompression == (U1(test_data[i].format).dwRGBBitCount == 16 ? BI_BITFIELDS : BI_RGB)
9003 || broken(U1(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
9004 "Got unexpected compression %#x for format %s.\n",
9005 dib.dsBmih.biCompression, test_data[i].name);
9006 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
9007 dib.dsBmih.biSizeImage, test_data[i].name);
9008 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
9009 dib.dsBmih.biXPelsPerMeter, test_data[i].name);
9010 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
9011 dib.dsBmih.biYPelsPerMeter, test_data[i].name);
9012 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
9013 dib.dsBmih.biClrUsed, test_data[i].name);
9014 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
9015 dib.dsBmih.biClrImportant, test_data[i].name);
9017 if (dib.dsBmih.biCompression == BI_BITFIELDS)
9019 ok((dib.dsBitfields[0] == U2(test_data[i].format).dwRBitMask
9020 && dib.dsBitfields[1] == U3(test_data[i].format).dwGBitMask
9021 && dib.dsBitfields[2] == U4(test_data[i].format).dwBBitMask)
9022 || broken(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2]),
9023 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
9024 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
9026 else
9028 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
9029 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
9030 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
9032 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, test_data[i].name);
9033 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, test_data[i].name);
9035 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
9036 ok(hr == DD_OK, "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9038 else
9040 ok(!dc, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
9043 IDirectDrawSurface_Release(surface);
9045 if (FAILED(hr))
9046 continue;
9048 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
9049 if (FAILED(hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
9051 skip("Failed to create mip-mapped texture for format %s (hr %#x), skipping tests.\n",
9052 test_data[i].name, hr);
9053 continue;
9056 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &tmp);
9057 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
9058 hr = IDirectDrawSurface_GetAttachedSurface(tmp, &caps, &surface2);
9059 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
9060 IDirectDrawSurface_Release(tmp);
9062 hr = IDirectDrawSurface_GetDC(surface, &dc);
9063 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9064 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
9065 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9066 hr = IDirectDrawSurface_GetDC(surface2, &dc);
9067 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9068 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
9069 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9071 hr = IDirectDrawSurface_GetDC(surface, &dc);
9072 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9073 dc2 = (void *)0x1234;
9074 hr = IDirectDrawSurface_GetDC(surface, &dc2);
9075 ok(hr == DDERR_DCALREADYCREATED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9076 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
9077 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
9078 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9079 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
9080 ok(hr == DDERR_NODC, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9082 map_desc.dwSize = sizeof(map_desc);
9083 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
9084 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
9085 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
9086 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9087 hr = IDirectDrawSurface_Unlock(surface, NULL);
9088 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
9089 hr = IDirectDrawSurface_Unlock(surface, NULL);
9090 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9092 hr = IDirectDrawSurface_GetDC(surface, &dc);
9093 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9094 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
9095 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9096 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
9097 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9099 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
9100 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
9101 hr = IDirectDrawSurface_GetDC(surface, &dc);
9102 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9103 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
9104 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9105 hr = IDirectDrawSurface_Unlock(surface, NULL);
9106 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
9108 hr = IDirectDrawSurface_GetDC(surface, &dc);
9109 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9110 hr = IDirectDrawSurface_GetDC(surface2, &dc2);
9111 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9112 hr = IDirectDrawSurface_ReleaseDC(surface2, dc2);
9113 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9114 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
9115 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9117 hr = IDirectDrawSurface_GetDC(surface2, &dc);
9118 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9119 hr = IDirectDrawSurface_GetDC(surface, &dc2);
9120 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9121 hr = IDirectDrawSurface_ReleaseDC(surface, dc2);
9122 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9123 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
9124 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9126 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
9127 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
9128 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
9129 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
9130 hr = IDirectDrawSurface_Unlock(surface2, NULL);
9131 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
9132 hr = IDirectDrawSurface_Unlock(surface, NULL);
9133 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
9135 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
9136 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
9137 hr = IDirectDrawSurface_GetDC(surface, &dc);
9138 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9139 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
9140 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9141 hr = IDirectDrawSurface_Unlock(surface, NULL);
9142 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
9144 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
9145 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
9146 hr = IDirectDrawSurface_GetDC(surface, &dc);
9147 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9148 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
9149 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9150 hr = IDirectDrawSurface_Unlock(surface2, NULL);
9151 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
9153 hr = IDirectDrawSurface_GetDC(surface, &dc);
9154 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9155 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
9156 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
9157 hr = IDirectDrawSurface_Unlock(surface2, NULL);
9158 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
9159 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
9160 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9162 hr = IDirectDrawSurface_GetDC(surface2, &dc);
9163 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9164 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
9165 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
9166 hr = IDirectDrawSurface_Unlock(surface, NULL);
9167 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
9168 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
9169 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9171 hr = IDirectDrawSurface_Unlock(surface, NULL);
9172 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9173 hr = IDirectDrawSurface_GetDC(surface2, &dc);
9174 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9175 hr = IDirectDrawSurface_Unlock(surface, NULL);
9176 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9177 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
9178 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9179 hr = IDirectDrawSurface_Unlock(surface, NULL);
9180 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9182 hr = IDirectDrawSurface_Unlock(surface2, NULL);
9183 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9184 hr = IDirectDrawSurface_GetDC(surface, &dc);
9185 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9186 hr = IDirectDrawSurface_Unlock(surface2, NULL);
9187 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9188 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
9189 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9190 hr = IDirectDrawSurface_Unlock(surface2, NULL);
9191 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9193 IDirectDrawSurface_Release(surface2);
9194 IDirectDrawSurface_Release(surface);
9197 IDirectDraw_Release(ddraw);
9198 DestroyWindow(window);
9201 /* TransformVertices always writes 32 bytes regardless of the input / output stride.
9202 * The stride is honored for navigating to the next vertex. 3 floats input position
9203 * are read, and 16 bytes extra vertex data are copied around. */
9204 struct transform_input
9206 float x, y, z, unused1; /* Position data, transformed. */
9207 DWORD v1, v2, v3, v4; /* Extra data, e.g. color and texture coords, copied. */
9208 DWORD unused2;
9211 struct transform_output
9213 float x, y, z, w;
9214 DWORD v1, v2, v3, v4;
9215 DWORD unused3, unused4;
9218 static void test_transform_vertices(void)
9220 IDirect3DDevice *device;
9221 IDirectDrawSurface *rt;
9222 IDirectDraw *ddraw;
9223 ULONG refcount;
9224 HWND window;
9225 HRESULT hr;
9226 D3DCOLOR color;
9227 IDirect3DViewport *viewport;
9228 IDirect3DExecuteBuffer *execute_buffer;
9229 IDirect3DMaterial *background;
9230 D3DEXECUTEBUFFERDESC exec_desc;
9231 UINT inst_length;
9232 void *ptr;
9233 D3DMATRIXHANDLE world_handle, view_handle, proj_handle;
9234 static struct transform_input position_tests[] =
9236 { 0.0f, 0.0f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
9237 { 1.0f, 1.0f, 1.0f, 8.0f, 6, 7, 8, 9, 10},
9238 {-1.0f, -1.0f, -1.0f, 4.0f, 11, 12, 13, 14, 15},
9239 { 0.5f, 0.5f, 0.5f, 2.0f, 16, 17, 18, 19, 20},
9240 {-0.5f, -0.5f, -0.5f, 1.0f, ~1U, ~2U, ~3U, ~4U, ~5U},
9241 {-0.5f, -0.5f, 0.0f, 0.0f, ~6U, ~7U, ~8U, ~9U, ~0U},
9243 static struct transform_input cliptest[] =
9245 { 25.59f, 25.59f, 1.0f, 0.0f, 1, 2, 3, 4, 5},
9246 { 25.61f, 25.61f, 1.01f, 0.0f, 1, 2, 3, 4, 5},
9247 {-25.59f, -25.59f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
9248 {-25.61f, -25.61f, -0.01f, 0.0f, 1, 2, 3, 4, 5},
9250 static struct transform_input offscreentest[] =
9252 {128.1f, 0.0f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
9254 struct transform_output out[ARRAY_SIZE(position_tests)];
9255 D3DHVERTEX out_h[ARRAY_SIZE(position_tests)];
9256 D3DTRANSFORMDATA transformdata;
9257 static const D3DVIEWPORT vp_template =
9259 sizeof(vp_template), 0, 0, 256, 256, 5.0f, 5.0f, 256.0f, 256.0f, -25.0f, 60.0f
9261 D3DVIEWPORT vp_data =
9263 sizeof(vp_data), 0, 0, 256, 256, 1.0f, 1.0f, 256.0f, 256.0f, 0.0f, 1.0f
9265 unsigned int i;
9266 DWORD offscreen;
9267 static D3DMATRIX mat_scale =
9269 2.0f, 0.0f, 0.0f, 0.0f,
9270 0.0f, 2.0f, 0.0f, 0.0f,
9271 0.0f, 0.0f, 2.0f, 0.0f,
9272 0.0f, 0.0f, 0.0f, 1.0f,
9274 mat_translate1 =
9276 1.0f, 0.0f, 0.0f, 0.0f,
9277 0.0f, 1.0f, 0.0f, 0.0f,
9278 0.0f, 0.0f, 1.0f, 0.0f,
9279 1.0f, 0.0f, 0.0f, 1.0f,
9281 mat_translate2 =
9283 1.0f, 0.0f, 0.0f, 0.0f,
9284 0.0f, 1.0f, 0.0f, 0.0f,
9285 0.0f, 0.0f, 1.0f, 0.0f,
9286 0.0f, 1.0f, 0.0f, 1.0f,
9288 static const D3DLVERTEX quad[] =
9290 {{-0.75f},{-0.5f }, {0.0f}, 0, {0xffff0000}},
9291 {{-0.75f},{ 0.25f}, {0.0f}, 0, {0xffff0000}},
9292 {{ 0.5f}, {-0.5f }, {0.0f}, 0, {0xffff0000}},
9293 {{ 0.5f}, { 0.25f}, {0.0f}, 0, {0xffff0000}},
9295 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
9298 for (i = 0; i < ARRAY_SIZE(out); ++i)
9300 out[i].unused3 = 0xdeadbeef;
9301 out[i].unused4 = 0xcafecafe;
9304 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9305 0, 0, 640, 480, 0, 0, 0, 0);
9306 ddraw = create_ddraw();
9307 ok(!!ddraw, "Failed to create a ddraw object.\n");
9308 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
9310 skip("Failed to create a 3D device, skipping test.\n");
9311 IDirectDraw_Release(ddraw);
9312 DestroyWindow(window);
9313 return;
9316 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
9317 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9319 viewport = create_viewport(device, 0, 0, 256, 256);
9320 hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
9321 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
9323 memset(&transformdata, 0, sizeof(transformdata));
9324 transformdata.dwSize = sizeof(transformdata);
9325 transformdata.lpIn = position_tests;
9326 transformdata.dwInSize = sizeof(position_tests[0]);
9327 transformdata.lpOut = out;
9328 transformdata.dwOutSize = sizeof(out[0]);
9329 transformdata.lpHOut = NULL;
9331 hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(position_tests),
9332 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
9333 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9334 ok(!offscreen, "Offscreen is %x.\n", offscreen);
9336 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
9338 static const struct vec4 cmp[] =
9340 {128.0f, 128.0f, 0.0f, 1.0f}, {129.0f, 127.0f, 1.0f, 1.0f}, {127.0f, 129.0f, -1.0f, 1.0f},
9341 {128.5f, 127.5f, 0.5f, 1.0f}, {127.5f, 128.5f, -0.5f, 1.0f}, {127.5f, 128.5f, 0.0f, 1.0f}
9344 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
9345 "Vertex %u differs. Got %f %f %f %f.\n", i,
9346 out[i].x, out[i].y, out[i].z, out[i].w);
9347 ok(out[i].v1 == position_tests[i].v1 && out[i].v2 == position_tests[i].v2
9348 && out[i].v3 == position_tests[i].v3 && out[i].v4 == position_tests[i].v4,
9349 "Vertex %u payload is %u %u %u %u.\n", i, out[i].v1, out[i].v2, out[i].v3, out[i].v4);
9350 ok(out[i].unused3 == 0xdeadbeef && out[i].unused4 == 0xcafecafe,
9351 "Vertex %u unused data is %#x, %#x.\n", i, out[i].unused3, out[i].unused4);
9354 vp_data = vp_template;
9355 hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
9356 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
9357 offscreen = 0xdeadbeef;
9358 hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(position_tests),
9359 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
9360 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9361 ok(!offscreen, "Offscreen is %x.\n", offscreen);
9363 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
9365 static const struct vec4 cmp[] =
9367 {128.0f, 128.0f, 0.0f, 1.0f}, {133.0f, 123.0f, 1.0f, 1.0f}, {123.0f, 133.0f, -1.0f, 1.0f},
9368 {130.5f, 125.5f, 0.5f, 1.0f}, {125.5f, 130.5f, -0.5f, 1.0f}, {125.5f, 130.5f, 0.0f, 1.0f}
9370 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
9371 "Vertex %u differs. Got %f %f %f %f.\n", i,
9372 out[i].x, out[i].y, out[i].z, out[i].w);
9375 vp_data.dwX = 10;
9376 vp_data.dwY = 20;
9377 hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
9378 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
9379 offscreen = 0xdeadbeef;
9380 hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(position_tests),
9381 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
9382 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9383 ok(!offscreen, "Offscreen is %x.\n", offscreen);
9384 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
9386 static const struct vec4 cmp[] =
9388 {138.0f, 148.0f, 0.0f, 1.0f}, {143.0f, 143.0f, 1.0f, 1.0f}, {133.0f, 153.0f, -1.0f, 1.0f},
9389 {140.5f, 145.5f, 0.5f, 1.0f}, {135.5f, 150.5f, -0.5f, 1.0f}, {135.5f, 150.5f, 0.0f, 1.0f}
9391 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
9392 "Vertex %u differs. Got %f %f %f %f.\n", i,
9393 out[i].x, out[i].y, out[i].z, out[i].w);
9396 transformdata.lpHOut = out_h;
9397 offscreen = 0xdeadbeef;
9398 hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(position_tests),
9399 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
9400 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9401 ok(!offscreen, "Offscreen is %x.\n", offscreen);
9402 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
9404 static const D3DHVERTEX cmp_h[] =
9406 {0, { 0.0f}, { 0.0f}, { 0.0f}}, {0, { 1.0f}, { 1.0f}, {1.0f}},
9407 {D3DCLIP_FRONT, {-1.0f}, {-1.0f}, {-1.0f}}, {0, { 0.5f}, { 0.5f}, {0.5f}},
9408 {D3DCLIP_FRONT, {-0.5f}, {-0.5f}, {-0.5f}}, {0, {-0.5f}, {-0.5f}, {0.0f}}
9410 ok(compare_float(U1(cmp_h[i]).hx, U1(out_h[i]).hx, 4096)
9411 && compare_float(U2(cmp_h[i]).hy, U2(out_h[i]).hy, 4096)
9412 && compare_float(U3(cmp_h[i]).hz, U3(out_h[i]).hz, 4096)
9413 && cmp_h[i].dwFlags == out_h[i].dwFlags,
9414 "HVertex %u differs. Got %#x %f %f %f.\n", i,
9415 out_h[i].dwFlags, U1(out_h[i]).hx, U2(out_h[i]).hy, U3(out_h[i]).hz);
9417 /* No scheme has been found behind those return values. It seems to be
9418 * whatever data windows has when throwing the vertex away. Modify the
9419 * input test vertices to test this more. Depending on the input data
9420 * it can happen that the z coord gets written into y, or similar things. */
9421 if (0)
9423 static const struct vec4 cmp[] =
9425 {138.0f, 148.0f, 0.0f, 1.0f}, {143.0f, 143.0f, 1.0f, 1.0f}, { -1.0f, -1.0f, 0.5f, 1.0f},
9426 {140.5f, 145.5f, 0.5f, 1.0f}, { -0.5f, -0.5f, -0.5f, 1.0f}, {135.5f, 150.5f, 0.0f, 1.0f}
9428 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
9429 "Vertex %u differs. Got %f %f %f %f.\n", i,
9430 out[i].x, out[i].y, out[i].z, out[i].w);
9434 transformdata.lpIn = cliptest;
9435 transformdata.dwInSize = sizeof(cliptest[0]);
9436 offscreen = 0xdeadbeef;
9437 hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(cliptest),
9438 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
9439 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9440 ok(!offscreen, "Offscreen is %x.\n", offscreen);
9441 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
9443 static const DWORD flags[] =
9446 D3DCLIP_RIGHT | D3DCLIP_BACK | D3DCLIP_TOP,
9448 D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
9450 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
9453 vp_data = vp_template;
9454 vp_data.dwWidth = 10;
9455 vp_data.dwHeight = 1000;
9456 hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
9457 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
9458 offscreen = 0xdeadbeef;
9459 hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(cliptest),
9460 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
9461 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9462 ok(!offscreen, "Offscreen is %x.\n", offscreen);
9463 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
9465 static const DWORD flags[] =
9467 D3DCLIP_RIGHT,
9468 D3DCLIP_RIGHT | D3DCLIP_BACK,
9469 D3DCLIP_LEFT,
9470 D3DCLIP_LEFT | D3DCLIP_FRONT,
9472 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
9475 vp_data = vp_template;
9476 vp_data.dwWidth = 256;
9477 vp_data.dwHeight = 256;
9478 vp_data.dvScaleX = 1;
9479 vp_data.dvScaleY = 1;
9480 hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
9481 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
9482 hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(cliptest),
9483 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
9484 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9485 ok(!offscreen, "Offscreen is %x.\n", offscreen);
9486 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
9488 static const DWORD flags[] =
9491 D3DCLIP_BACK,
9493 D3DCLIP_FRONT,
9495 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
9498 /* Finally try to figure out how the DWORD dwOffscreen works.
9499 * It is a logical AND of the vertices' dwFlags members. */
9500 vp_data = vp_template;
9501 vp_data.dwWidth = 5;
9502 vp_data.dwHeight = 5;
9503 vp_data.dvScaleX = 10000.0f;
9504 vp_data.dvScaleY = 10000.0f;
9505 hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
9506 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
9507 transformdata.lpIn = cliptest;
9508 offscreen = 0xdeadbeef;
9509 hr = IDirect3DViewport_TransformVertices(viewport, 1,
9510 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
9511 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9512 ok(!offscreen, "Offscreen is %x.\n", offscreen);
9514 offscreen = 0xdeadbeef;
9515 hr = IDirect3DViewport_TransformVertices(viewport, 1,
9516 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
9517 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9518 ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
9519 offscreen = 0xdeadbeef;
9520 hr = IDirect3DViewport_TransformVertices(viewport, 2,
9521 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
9522 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9523 ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
9524 hr = IDirect3DViewport_TransformVertices(viewport, 3,
9525 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
9526 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9527 ok(!offscreen, "Offscreen is %x.\n", offscreen);
9529 transformdata.lpIn = cliptest + 1;
9530 hr = IDirect3DViewport_TransformVertices(viewport, 1,
9531 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
9532 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9533 ok(offscreen == (D3DCLIP_BACK | D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
9535 transformdata.lpIn = cliptest + 2;
9536 hr = IDirect3DViewport_TransformVertices(viewport, 1,
9537 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
9538 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9539 ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
9540 offscreen = 0xdeadbeef;
9541 hr = IDirect3DViewport_TransformVertices(viewport, 2,
9542 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
9543 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9544 ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
9546 transformdata.lpIn = cliptest + 3;
9547 hr = IDirect3DViewport_TransformVertices(viewport, 1,
9548 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
9549 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9550 ok(offscreen == (D3DCLIP_FRONT | D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
9552 transformdata.lpIn = offscreentest;
9553 transformdata.dwInSize = sizeof(offscreentest[0]);
9554 vp_data = vp_template;
9555 vp_data.dwWidth = 257;
9556 vp_data.dwHeight = 257;
9557 vp_data.dvScaleX = 1.0f;
9558 vp_data.dvScaleY = 1.0f;
9559 hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
9560 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
9561 offscreen = 0xdeadbeef;
9562 hr = IDirect3DViewport_TransformVertices(viewport, 1,
9563 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
9564 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9565 ok(!offscreen, "Offscreen is %x.\n", offscreen);
9567 vp_data.dwWidth = 256;
9568 vp_data.dwHeight = 256;
9569 hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
9570 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
9571 hr = IDirect3DViewport_TransformVertices(viewport, 1,
9572 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
9573 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9574 ok(offscreen == D3DCLIP_RIGHT, "Offscreen is %x.\n", offscreen);
9576 /* Test the effect of Matrices.
9578 * Basically the x coordinate ends up as ((x + 1) * 2 + 0) * 5 and
9579 * y as ((y + 0) * 2 + 1) * 5. The 5 comes from dvScaleX/Y, 2 from
9580 * the view matrix and the +1's from the world and projection matrix. */
9581 vp_data.dwX = 0;
9582 vp_data.dwY = 0;
9583 vp_data.dwWidth = 256;
9584 vp_data.dwHeight = 256;
9585 vp_data.dvScaleX = 5.0f;
9586 vp_data.dvScaleY = 5.0f;
9587 vp_data.dvMinZ = 0.0f;
9588 vp_data.dvMaxZ = 1.0f;
9589 hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
9590 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
9592 hr = IDirect3DDevice_CreateMatrix(device, &world_handle);
9593 ok(hr == D3D_OK, "Creating a matrix object failed, hr %#x.\n", hr);
9594 hr = IDirect3DDevice_SetMatrix(device, world_handle, &mat_translate1);
9595 ok(hr == D3D_OK, "Setting a matrix object failed, hr %#x.\n", hr);
9597 hr = IDirect3DDevice_CreateMatrix(device, &view_handle);
9598 ok(hr == D3D_OK, "Creating a matrix object failed, hr %#x.\n", hr);
9599 hr = IDirect3DDevice_SetMatrix(device, view_handle, &mat_scale);
9600 ok(hr == D3D_OK, "Setting a matrix object failed, hr %#x.\n", hr);
9602 hr = IDirect3DDevice_CreateMatrix(device, &proj_handle);
9603 ok(hr == D3D_OK, "Creating a matrix object failed, hr %#x.\n", hr);
9604 hr = IDirect3DDevice_SetMatrix(device, proj_handle, &mat_translate2);
9605 ok(hr == D3D_OK, "Setting a matrix object failed, hr %#x.\n", hr);
9607 memset(&exec_desc, 0, sizeof(exec_desc));
9608 exec_desc.dwSize = sizeof(exec_desc);
9609 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
9610 exec_desc.dwBufferSize = 1024;
9611 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
9612 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
9613 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
9615 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
9616 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
9617 ptr = (BYTE *)exec_desc.lpData;
9618 emit_set_ts(&ptr, D3DTRANSFORMSTATE_WORLD, world_handle);
9619 emit_set_ts(&ptr, D3DTRANSFORMSTATE_VIEW, view_handle);
9620 emit_set_ts(&ptr, D3DTRANSFORMSTATE_PROJECTION, proj_handle);
9621 emit_end(&ptr);
9622 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
9623 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
9624 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
9626 set_execute_data(execute_buffer, 0, 0, inst_length);
9627 hr = IDirect3DDevice_BeginScene(device);
9628 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9629 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
9630 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
9631 hr = IDirect3DDevice_EndScene(device);
9632 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9634 transformdata.lpIn = position_tests;
9635 transformdata.dwInSize = sizeof(position_tests[0]);
9636 hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(position_tests),
9637 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
9638 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9640 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
9642 static const struct vec4 cmp[] =
9644 {138.0f, 123.0f, 0.0f, 1.0f}, {148.0f, 113.0f, 2.0f, 1.0f}, {128.0f, 133.0f, -2.0f, 1.0f},
9645 {143.0f, 118.0f, 1.0f, 1.0f}, {133.0f, 128.0f, -1.0f, 1.0f}, {133.0f, 128.0f, 0.0f, 1.0f}
9648 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
9649 "Vertex %u differs. Got %f %f %f %f.\n", i,
9650 out[i].x, out[i].y, out[i].z, out[i].w);
9653 /* Invalid flags. */
9654 offscreen = 0xdeadbeef;
9655 hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(position_tests),
9656 &transformdata, 0, &offscreen);
9657 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
9658 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
9660 /* NULL transform data. */
9661 hr = IDirect3DViewport_TransformVertices(viewport, 1,
9662 NULL, D3DTRANSFORM_UNCLIPPED, &offscreen);
9663 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
9664 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
9665 hr = IDirect3DViewport_TransformVertices(viewport, 0,
9666 NULL, D3DTRANSFORM_UNCLIPPED, &offscreen);
9667 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
9668 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
9670 /* NULL transform data and NULL dwOffscreen.
9672 * Valid transform data + NULL dwOffscreen -> crash. */
9673 hr = IDirect3DViewport_TransformVertices(viewport, 1,
9674 NULL, D3DTRANSFORM_UNCLIPPED, NULL);
9675 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
9677 /* No vertices. */
9678 hr = IDirect3DViewport_TransformVertices(viewport, 0,
9679 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
9680 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9681 ok(!offscreen, "Offscreen is %x.\n", offscreen);
9682 hr = IDirect3DViewport_TransformVertices(viewport, 0,
9683 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
9684 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9685 ok(offscreen == ~0U, "Offscreen is %x.\n", offscreen);
9687 /* Invalid sizes. */
9688 offscreen = 0xdeadbeef;
9689 transformdata.dwSize = sizeof(transformdata) - 1;
9690 hr = IDirect3DViewport_TransformVertices(viewport, 1,
9691 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
9692 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
9693 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
9694 transformdata.dwSize = sizeof(transformdata) + 1;
9695 hr = IDirect3DViewport_TransformVertices(viewport, 1,
9696 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
9697 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
9698 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
9700 /* NULL lpIn or lpOut -> crash, except when transforming 0 vertices. */
9701 transformdata.dwSize = sizeof(transformdata);
9702 transformdata.lpIn = NULL;
9703 transformdata.lpOut = NULL;
9704 offscreen = 0xdeadbeef;
9705 hr = IDirect3DViewport_TransformVertices(viewport, 0,
9706 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
9707 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
9708 ok(offscreen == ~0U, "Offscreen is %x.\n", offscreen);
9710 /* Test how vertices are transformed by execute buffers. */
9711 vp_data.dwX = 20;
9712 vp_data.dwY = 20;
9713 vp_data.dwWidth = 200;
9714 vp_data.dwHeight = 400;
9715 vp_data.dvScaleX = 20.0f;
9716 vp_data.dvScaleY = 50.0f;
9717 vp_data.dvMinZ = 0.0f;
9718 vp_data.dvMaxZ = 1.0f;
9719 hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
9720 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
9722 background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 0.0f);
9723 viewport_set_background(device, viewport, background);
9724 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9725 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
9727 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
9728 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
9729 memcpy(exec_desc.lpData, quad, sizeof(quad));
9730 ptr = ((BYTE *)exec_desc.lpData) + sizeof(quad);
9731 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORM, 0, 4);
9732 emit_tquad(&ptr, 0);
9733 emit_end(&ptr);
9734 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
9735 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
9736 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
9738 set_execute_data(execute_buffer, 4, sizeof(quad), inst_length);
9739 hr = IDirect3DDevice_BeginScene(device);
9740 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9741 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
9742 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
9743 hr = IDirect3DDevice_EndScene(device);
9744 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9746 color = get_surface_color(rt, 128, 143);
9747 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
9748 color = get_surface_color(rt, 132, 143);
9749 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
9750 color = get_surface_color(rt, 128, 147);
9751 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
9752 color = get_surface_color(rt, 132, 147);
9753 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
9755 color = get_surface_color(rt, 177, 217);
9756 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
9757 color = get_surface_color(rt, 181, 217);
9758 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
9759 color = get_surface_color(rt, 177, 221);
9760 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
9761 color = get_surface_color(rt, 181, 221);
9762 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
9764 IDirect3DDevice_DeleteMatrix(device, world_handle);
9765 IDirect3DDevice_DeleteMatrix(device, view_handle);
9766 IDirect3DDevice_DeleteMatrix(device, proj_handle);
9767 IDirect3DExecuteBuffer_Release(execute_buffer);
9769 IDirectDrawSurface_Release(rt);
9770 destroy_viewport(device, viewport);
9771 IDirect3DMaterial_Release(background);
9772 refcount = IDirect3DDevice_Release(device);
9773 ok(!refcount, "Device has %u references left.\n", refcount);
9774 IDirectDraw_Release(ddraw);
9775 DestroyWindow(window);
9778 static void test_display_mode_surface_pixel_format(void)
9780 unsigned int width, height, bpp;
9781 IDirectDrawSurface *surface;
9782 DDSURFACEDESC surface_desc;
9783 IDirectDraw *ddraw;
9784 ULONG refcount;
9785 HWND window;
9786 HRESULT hr;
9788 if (!(ddraw = create_ddraw()))
9790 skip("Failed to create ddraw.\n");
9791 return;
9794 surface_desc.dwSize = sizeof(surface_desc);
9795 hr = IDirectDraw_GetDisplayMode(ddraw, &surface_desc);
9796 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
9797 width = surface_desc.dwWidth;
9798 height = surface_desc.dwHeight;
9800 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9801 0, 0, width, height, NULL, NULL, NULL, NULL);
9802 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9803 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9805 bpp = 0;
9806 if (SUCCEEDED(IDirectDraw_SetDisplayMode(ddraw, width, height, 16)))
9807 bpp = 16;
9808 if (SUCCEEDED(IDirectDraw_SetDisplayMode(ddraw, width, height, 24)))
9809 bpp = 24;
9810 if (SUCCEEDED(IDirectDraw_SetDisplayMode(ddraw, width, height, 32)))
9811 bpp = 32;
9812 ok(bpp, "Set display mode failed.\n");
9814 surface_desc.dwSize = sizeof(surface_desc);
9815 hr = IDirectDraw_GetDisplayMode(ddraw, &surface_desc);
9816 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
9817 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
9818 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
9819 ok(U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
9820 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, bpp);
9822 memset(&surface_desc, 0, sizeof(surface_desc));
9823 surface_desc.dwSize = sizeof(surface_desc);
9824 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
9825 surface_desc.dwBackBufferCount = 1;
9826 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE;
9827 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9828 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
9829 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
9830 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9831 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
9832 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
9833 ok(surface_desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
9834 surface_desc.ddpfPixelFormat.dwFlags);
9835 ok(U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
9836 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, bpp);
9837 IDirectDrawSurface_Release(surface);
9839 memset(&surface_desc, 0, sizeof(surface_desc));
9840 surface_desc.dwSize = sizeof(surface_desc);
9841 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
9842 surface_desc.dwWidth = width;
9843 surface_desc.dwHeight = height;
9844 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9845 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9846 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
9847 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
9848 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9849 ok(surface_desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
9850 surface_desc.ddpfPixelFormat.dwFlags);
9851 ok(U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
9852 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, bpp);
9853 IDirectDrawSurface_Release(surface);
9855 refcount = IDirectDraw_Release(ddraw);
9856 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
9857 DestroyWindow(window);
9860 static void test_surface_desc_size(void)
9862 union
9864 DWORD dwSize;
9865 DDSURFACEDESC desc1;
9866 DDSURFACEDESC2 desc2;
9867 BYTE blob[1024];
9868 } desc;
9869 IDirectDrawSurface7 *surface7;
9870 IDirectDrawSurface *surface;
9871 DDSURFACEDESC surface_desc;
9872 HRESULT expected_hr, hr;
9873 IDirectDraw *ddraw;
9874 unsigned int i, j;
9875 ULONG refcount;
9877 static const struct
9879 unsigned int caps;
9880 const char *name;
9882 surface_caps[] =
9884 {DDSCAPS_OFFSCREENPLAIN, "offscreenplain"},
9885 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "systemmemory texture"},
9886 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "videomemory texture"},
9888 static const unsigned int desc_sizes[] =
9890 sizeof(DDSURFACEDESC),
9891 sizeof(DDSURFACEDESC2),
9892 sizeof(DDSURFACEDESC) + 1,
9893 sizeof(DDSURFACEDESC2) + 1,
9894 2 * sizeof(DDSURFACEDESC),
9895 2 * sizeof(DDSURFACEDESC2),
9896 sizeof(DDSURFACEDESC) - 1,
9897 sizeof(DDSURFACEDESC2) - 1,
9898 sizeof(DDSURFACEDESC) / 2,
9899 sizeof(DDSURFACEDESC2) / 2,
9903 sizeof(desc) / 2,
9904 sizeof(desc) - 100,
9907 if (!(ddraw = create_ddraw()))
9909 skip("Failed to create ddraw.\n");
9910 return;
9912 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
9913 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9915 for (i = 0; i < sizeof(surface_caps) / sizeof(*surface_caps); ++i)
9917 memset(&surface_desc, 0, sizeof(surface_desc));
9918 surface_desc.dwSize = sizeof(surface_desc);
9919 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
9920 surface_desc.ddsCaps.dwCaps = surface_caps[i].caps;
9921 surface_desc.dwHeight = 128;
9922 surface_desc.dwWidth = 128;
9923 if (FAILED(IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
9925 skip("Failed to create surface, type %s.\n", surface_caps[i].name);
9926 continue;
9928 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface7, (void **)&surface7);
9929 ok(hr == DD_OK, "Failed to query IDirectDrawSurface7, hr %#x, type %s.\n", hr, surface_caps[i].name);
9931 /* GetSurfaceDesc() */
9932 for (j = 0; j < sizeof(desc_sizes) / sizeof(*desc_sizes); ++j)
9934 memset(&desc, 0, sizeof(desc));
9935 desc.dwSize = desc_sizes[j];
9936 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
9937 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc.desc1);
9938 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
9939 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
9941 memset(&desc, 0, sizeof(desc));
9942 desc.dwSize = desc_sizes[j];
9943 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC2) ? DD_OK : DDERR_INVALIDPARAMS;
9944 hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
9945 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
9946 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
9949 /* Lock() */
9950 for (j = 0; j < sizeof(desc_sizes) / sizeof(*desc_sizes); ++j)
9952 const BOOL valid_size = desc_sizes[j] == sizeof(DDSURFACEDESC)
9953 || desc_sizes[j] == sizeof(DDSURFACEDESC2);
9954 DWORD expected_texture_stage;
9956 memset(&desc, 0, sizeof(desc));
9957 desc.dwSize = desc_sizes[j];
9958 desc.desc2.dwTextureStage = 0xdeadbeef;
9959 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
9960 hr = IDirectDrawSurface_Lock(surface, NULL, &desc.desc1, 0, 0);
9961 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
9962 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
9963 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
9964 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
9965 desc_sizes[j], desc.dwSize, surface_caps[i].name);
9966 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
9967 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
9968 if (SUCCEEDED(hr))
9970 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
9971 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
9972 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
9973 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
9974 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
9975 todo_wine_if(!expected_texture_stage)
9976 ok(desc.desc2.dwTextureStage == expected_texture_stage,
9977 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
9978 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
9979 IDirectDrawSurface_Unlock(surface, NULL);
9982 memset(&desc, 0, sizeof(desc));
9983 desc.dwSize = desc_sizes[j];
9984 desc.desc2.dwTextureStage = 0xdeadbeef;
9985 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
9986 hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
9987 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
9988 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
9989 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
9990 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
9991 desc_sizes[j], desc.dwSize, surface_caps[i].name);
9992 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
9993 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
9994 if (SUCCEEDED(hr))
9996 ok(desc.desc2.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
9997 desc.desc2.dwWidth, desc_sizes[j], surface_caps[i].name);
9998 ok(desc.desc2.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
9999 desc.desc2.dwHeight, desc_sizes[j], surface_caps[i].name);
10000 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
10001 ok(desc.desc2.dwTextureStage == expected_texture_stage,
10002 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
10003 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
10004 IDirectDrawSurface7_Unlock(surface7, NULL);
10008 IDirectDrawSurface7_Release(surface7);
10009 IDirectDrawSurface_Release(surface);
10012 refcount = IDirectDraw7_Release(ddraw);
10013 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
10016 static void test_texture_load(void)
10018 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
10019 static D3DTLVERTEX tquad[] =
10021 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
10022 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
10023 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
10024 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
10026 D3DTEXTUREHANDLE dst_texture_handle, src_texture_handle;
10027 IDirectDrawSurface *dst_surface, *src_surface;
10028 IDirect3DExecuteBuffer *execute_buffer;
10029 D3DEXECUTEBUFFERDESC exec_desc;
10030 IDirect3DMaterial *background;
10031 IDirect3DViewport *viewport;
10032 DDSURFACEDESC surface_desc;
10033 IDirect3DTexture *texture;
10034 IDirect3DDevice *device;
10035 IDirectDrawSurface *rt;
10036 IDirectDraw *ddraw;
10037 UINT inst_length;
10038 D3DCOLOR color;
10039 ULONG refcount;
10040 HWND window;
10041 DDBLTFX fx;
10042 HRESULT hr;
10043 void *ptr;
10045 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10046 0, 0, 640, 480, 0, 0, 0, 0);
10047 ddraw = create_ddraw();
10048 ok(!!ddraw, "Failed to create a ddraw object.\n");
10049 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
10051 skip("Failed to create a 3D device, skipping test.\n");
10052 IDirectDraw_Release(ddraw);
10053 DestroyWindow(window);
10054 return;
10057 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
10058 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10060 background = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
10061 viewport = create_viewport(device, 0, 0, 640, 480);
10062 viewport_set_background(device, viewport, background);
10064 memset(&exec_desc, 0, sizeof(exec_desc));
10065 exec_desc.dwSize = sizeof(exec_desc);
10066 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
10067 exec_desc.dwBufferSize = 1024;
10068 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
10069 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
10070 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
10072 memset(&surface_desc, 0, sizeof(surface_desc));
10073 surface_desc.dwSize = sizeof(surface_desc);
10074 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10075 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10076 surface_desc.dwWidth = 256;
10077 surface_desc.dwHeight = 256;
10078 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
10079 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
10080 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
10081 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10082 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10083 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
10085 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
10086 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10087 hr = IDirectDrawSurface_QueryInterface(src_surface, &IID_IDirect3DTexture, (void **)&texture);
10088 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
10089 hr = IDirect3DTexture_GetHandle(texture, device, &src_texture_handle);
10090 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
10091 IDirect3DTexture_Release(texture);
10093 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
10094 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10095 hr = IDirectDrawSurface_QueryInterface(dst_surface, &IID_IDirect3DTexture, (void **)&texture);
10096 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
10097 hr = IDirect3DTexture_GetHandle(texture, device, &dst_texture_handle);
10098 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
10099 IDirect3DTexture_Release(texture);
10101 memset(&fx, 0, sizeof(fx));
10102 fx.dwSize = sizeof(fx);
10103 U5(fx).dwFillColor = 0x0000ffff;
10104 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10105 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
10107 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
10108 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
10109 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
10110 ptr = (BYTE *)exec_desc.lpData + sizeof(tquad);
10111 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
10112 emit_texture_load(&ptr, dst_texture_handle, src_texture_handle);
10113 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, dst_texture_handle);
10114 emit_tquad(&ptr, 0);
10115 emit_end(&ptr);
10116 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData - sizeof(tquad);
10117 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
10118 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
10120 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
10121 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
10122 color = get_surface_color(rt, 320, 240);
10123 ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
10124 set_execute_data(execute_buffer, 4, sizeof(tquad), inst_length);
10125 hr = IDirect3DDevice_BeginScene(device);
10126 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10127 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
10128 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
10129 hr = IDirect3DDevice_EndScene(device);
10130 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10131 color = get_surface_color(rt, 320, 240);
10132 ok(compare_color(color, 0x0000ffff, 1), "Got unexpected color 0x%08x.\n", color);
10134 memset(&fx, 0, sizeof(fx));
10135 fx.dwSize = sizeof(fx);
10136 U5(fx).dwFillColor = 0x000000ff;
10137 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10138 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
10140 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
10141 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
10142 color = get_surface_color(rt, 320, 240);
10143 ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
10144 set_execute_data(execute_buffer, 4, sizeof(tquad), inst_length);
10145 hr = IDirect3DDevice_BeginScene(device);
10146 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10147 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
10148 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
10149 hr = IDirect3DDevice_EndScene(device);
10150 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10151 color = get_surface_color(rt, 320, 240);
10152 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
10154 IDirectDrawSurface_Release(dst_surface);
10155 IDirectDrawSurface_Release(src_surface);
10156 IDirectDrawSurface_Release(rt);
10157 IDirect3DExecuteBuffer_Release(execute_buffer);
10158 IDirect3DMaterial_Release(background);
10159 destroy_viewport(device, viewport);
10160 IDirect3DDevice_Release(device);
10161 refcount = IDirectDraw_Release(ddraw);
10162 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
10163 DestroyWindow(window);
10166 START_TEST(ddraw1)
10168 IDirectDraw *ddraw;
10169 DEVMODEW current_mode;
10170 HMODULE dwmapi;
10172 if (!(ddraw = create_ddraw()))
10174 skip("Failed to create a ddraw object, skipping tests.\n");
10175 return;
10177 IDirectDraw_Release(ddraw);
10179 memset(&current_mode, 0, sizeof(current_mode));
10180 current_mode.dmSize = sizeof(current_mode);
10181 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
10182 registry_mode.dmSize = sizeof(registry_mode);
10183 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
10184 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
10185 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
10187 skip("Current mode does not match registry mode, skipping test.\n");
10188 return;
10191 if ((dwmapi = LoadLibraryA("dwmapi.dll")))
10192 pDwmIsCompositionEnabled = (void *)GetProcAddress(dwmapi, "DwmIsCompositionEnabled");
10194 test_coop_level_create_device_window();
10195 test_clipper_blt();
10196 test_coop_level_d3d_state();
10197 test_surface_interface_mismatch();
10198 test_coop_level_threaded();
10199 test_viewport();
10200 test_zenable();
10201 test_ck_rgba();
10202 test_ck_default();
10203 test_ck_complex();
10204 test_surface_qi();
10205 test_device_qi();
10206 test_wndproc();
10207 test_window_style();
10208 test_redundant_mode_set();
10209 test_coop_level_mode_set();
10210 test_coop_level_mode_set_multi();
10211 test_initialize();
10212 test_coop_level_surf_create();
10213 test_coop_level_multi_window();
10214 test_clear_rect_count();
10215 test_coop_level_activateapp();
10216 test_unsupported_formats();
10217 test_rt_caps();
10218 test_primary_caps();
10219 test_surface_lock();
10220 test_surface_discard();
10221 test_flip();
10222 test_sysmem_overlay();
10223 test_primary_palette();
10224 test_surface_attachment();
10225 test_pixel_format();
10226 test_create_surface_pitch();
10227 test_mipmap();
10228 test_palette_complex();
10229 test_p8_blit();
10230 test_material();
10231 test_lighting();
10232 test_palette_gdi();
10233 test_palette_alpha();
10234 test_lost_device();
10235 test_surface_desc_lock();
10236 test_texturemapblend();
10237 test_viewport_clear_rect();
10238 test_color_fill();
10239 test_colorkey_precision();
10240 test_range_colorkey();
10241 test_shademode();
10242 test_lockrect_invalid();
10243 test_yv12_overlay();
10244 test_offscreen_overlay();
10245 test_overlay_rect();
10246 test_blt();
10247 test_getdc();
10248 test_transform_vertices();
10249 test_display_mode_surface_pixel_format();
10250 test_surface_desc_size();
10251 test_texture_load();