ddraw/tests: Rewrite SetRenderState() tests.
[wine.git] / dlls / ddraw / tests / ddraw4.c
blob1f0b01bddedbc78aff42e6f0ca927f7cb5e349d0
1 /*
2 * Copyright 2005 Antoine Chavasse (a.chavasse@gmail.com)
3 * Copyright 2008, 2011, 2012-2014 Stefan Dösinger for CodeWeavers
4 * Copyright 2011-2014 Henri Verbeet for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #define COBJMACROS
22 #include "wine/test.h"
23 #include <limits.h>
24 #include <math.h>
25 #include "d3d.h"
27 HRESULT WINAPI GetSurfaceFromDC(HDC dc, struct IDirectDrawSurface **surface, HDC *device_dc);
29 static BOOL is_ddraw64 = sizeof(DWORD) != sizeof(DWORD *);
30 static DEVMODEW registry_mode;
32 static HRESULT (WINAPI *pDwmIsCompositionEnabled)(BOOL *);
34 #ifndef ARRAY_SIZE
35 #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
36 #endif
38 struct vec2
40 float x, y;
43 struct vec3
45 float x, y, z;
48 struct vec4
50 float x, y, z, w;
53 struct create_window_thread_param
55 HWND window;
56 HANDLE window_created;
57 HANDLE destroy_window;
58 HANDLE thread;
61 static BOOL compare_float(float f, float g, unsigned int ulps)
63 int x = *(int *)&f;
64 int y = *(int *)&g;
66 if (x < 0)
67 x = INT_MIN - x;
68 if (y < 0)
69 y = INT_MIN - y;
71 if (abs(x - y) > ulps)
72 return FALSE;
74 return TRUE;
77 static BOOL compare_vec4(const struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
79 return compare_float(vec->x, x, ulps)
80 && compare_float(vec->y, y, ulps)
81 && compare_float(vec->z, z, ulps)
82 && compare_float(vec->w, w, ulps);
85 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
87 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
88 c1 >>= 8; c2 >>= 8;
89 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
90 c1 >>= 8; c2 >>= 8;
91 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
92 c1 >>= 8; c2 >>= 8;
93 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
94 return TRUE;
97 static BOOL ddraw_get_identifier(IDirectDraw4 *ddraw, DDDEVICEIDENTIFIER *identifier)
99 HRESULT hr;
101 hr = IDirectDraw4_GetDeviceIdentifier(ddraw, identifier, 0);
102 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#x.\n", hr);
104 return SUCCEEDED(hr);
107 static BOOL ddraw_is_warp(IDirectDraw4 *ddraw)
109 DDDEVICEIDENTIFIER identifier;
111 return strcmp(winetest_platform, "wine")
112 && ddraw_get_identifier(ddraw, &identifier)
113 && strstr(identifier.szDriver, "warp");
116 static BOOL ddraw_is_vendor(IDirectDraw4 *ddraw, DWORD vendor)
118 DDDEVICEIDENTIFIER identifier;
120 return strcmp(winetest_platform, "wine")
121 && ddraw_get_identifier(ddraw, &identifier)
122 && identifier.dwVendorId == vendor;
125 static BOOL ddraw_is_intel(IDirectDraw4 *ddraw)
127 return ddraw_is_vendor(ddraw, 0x8086);
130 static BOOL ddraw_is_nvidia(IDirectDraw4 *ddraw)
132 return ddraw_is_vendor(ddraw, 0x10de);
135 static BOOL ddraw_is_vmware(IDirectDraw4 *ddraw)
137 return ddraw_is_vendor(ddraw, 0x15ad);
140 static IDirectDrawSurface4 *create_overlay(IDirectDraw4 *ddraw,
141 unsigned int width, unsigned int height, DWORD format)
143 IDirectDrawSurface4 *surface;
144 DDSURFACEDESC2 desc;
146 memset(&desc, 0, sizeof(desc));
147 desc.dwSize = sizeof(desc);
148 desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
149 desc.dwWidth = width;
150 desc.dwHeight = height;
151 desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
152 U4(desc).ddpfPixelFormat.dwSize = sizeof(U4(desc).ddpfPixelFormat);
153 U4(desc).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
154 U4(desc).ddpfPixelFormat.dwFourCC = format;
156 if (FAILED(IDirectDraw4_CreateSurface(ddraw, &desc, &surface, NULL)))
157 return NULL;
158 return surface;
161 static HWND create_window(void)
163 RECT r = {0, 0, 640, 480};
165 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
167 return CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
168 CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
171 static DWORD WINAPI create_window_thread_proc(void *param)
173 struct create_window_thread_param *p = param;
174 DWORD res;
175 BOOL ret;
177 p->window = create_window();
178 ret = SetEvent(p->window_created);
179 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
181 for (;;)
183 MSG msg;
185 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
186 DispatchMessageA(&msg);
187 res = WaitForSingleObject(p->destroy_window, 100);
188 if (res == WAIT_OBJECT_0)
189 break;
190 if (res != WAIT_TIMEOUT)
192 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
193 break;
197 DestroyWindow(p->window);
199 return 0;
202 static void create_window_thread(struct create_window_thread_param *p)
204 DWORD res, tid;
206 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
207 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
208 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
209 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
210 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
211 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
212 res = WaitForSingleObject(p->window_created, INFINITE);
213 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
216 static void destroy_window_thread(struct create_window_thread_param *p)
218 SetEvent(p->destroy_window);
219 WaitForSingleObject(p->thread, INFINITE);
220 CloseHandle(p->destroy_window);
221 CloseHandle(p->window_created);
222 CloseHandle(p->thread);
225 static IDirectDrawSurface4 *get_depth_stencil(IDirect3DDevice3 *device)
227 IDirectDrawSurface4 *rt, *ret;
228 DDSCAPS2 caps = {DDSCAPS_ZBUFFER, 0, 0, {0}};
229 HRESULT hr;
231 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
232 ok(SUCCEEDED(hr), "Failed to get the render target, hr %#x.\n", hr);
233 hr = IDirectDrawSurface4_GetAttachedSurface(rt, &caps, &ret);
234 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
235 IDirectDrawSurface4_Release(rt);
236 return ret;
239 static HRESULT set_display_mode(IDirectDraw4 *ddraw, DWORD width, DWORD height)
241 if (SUCCEEDED(IDirectDraw4_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
242 return DD_OK;
243 return IDirectDraw4_SetDisplayMode(ddraw, width, height, 24, 0, 0);
246 static D3DCOLOR get_surface_color(IDirectDrawSurface4 *surface, UINT x, UINT y)
248 RECT rect = {x, y, x + 1, y + 1};
249 DDSURFACEDESC2 surface_desc;
250 D3DCOLOR color;
251 HRESULT hr;
253 memset(&surface_desc, 0, sizeof(surface_desc));
254 surface_desc.dwSize = sizeof(surface_desc);
256 hr = IDirectDrawSurface4_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
257 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
258 if (FAILED(hr))
259 return 0xdeadbeef;
261 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
263 hr = IDirectDrawSurface4_Unlock(surface, &rect);
264 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
266 return color;
269 static HRESULT CALLBACK enum_z_fmt(DDPIXELFORMAT *format, void *ctx)
271 DDPIXELFORMAT *z_fmt = ctx;
273 if (U1(*format).dwZBufferBitDepth > U1(*z_fmt).dwZBufferBitDepth)
274 *z_fmt = *format;
276 return DDENUMRET_OK;
279 static IDirectDraw4 *create_ddraw(void)
281 IDirectDraw4 *ddraw4;
282 IDirectDraw *ddraw1;
283 HRESULT hr;
285 if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
286 return NULL;
288 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw4, (void **)&ddraw4);
289 IDirectDraw_Release(ddraw1);
290 if (FAILED(hr))
291 return NULL;
293 return ddraw4;
296 static IDirect3DDevice3 *create_device(HWND window, DWORD coop_level)
298 IDirectDrawSurface4 *surface, *ds;
299 IDirect3DDevice3 *device = NULL;
300 DDSURFACEDESC2 surface_desc;
301 IDirectDraw4 *ddraw4;
302 DDPIXELFORMAT z_fmt;
303 IDirect3D3 *d3d3;
304 HRESULT hr;
306 if (!(ddraw4 = create_ddraw()))
307 return NULL;
309 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, coop_level);
310 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
312 memset(&surface_desc, 0, sizeof(surface_desc));
313 surface_desc.dwSize = sizeof(surface_desc);
314 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
315 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
316 surface_desc.dwWidth = 640;
317 surface_desc.dwHeight = 480;
319 hr = IDirectDraw4_CreateSurface(ddraw4, &surface_desc, &surface, NULL);
320 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
322 if (coop_level & DDSCL_NORMAL)
324 IDirectDrawClipper *clipper;
326 hr = IDirectDraw4_CreateClipper(ddraw4, 0, &clipper, NULL);
327 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
328 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
329 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
330 hr = IDirectDrawSurface4_SetClipper(surface, clipper);
331 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
332 IDirectDrawClipper_Release(clipper);
335 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirect3D3, (void **)&d3d3);
336 IDirectDraw4_Release(ddraw4);
337 if (FAILED(hr))
339 IDirectDrawSurface4_Release(surface);
340 return NULL;
343 memset(&z_fmt, 0, sizeof(z_fmt));
344 hr = IDirect3D3_EnumZBufferFormats(d3d3, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
345 if (FAILED(hr) || !z_fmt.dwSize)
347 IDirect3D3_Release(d3d3);
348 IDirectDrawSurface4_Release(surface);
349 return NULL;
352 memset(&surface_desc, 0, sizeof(surface_desc));
353 surface_desc.dwSize = sizeof(surface_desc);
354 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
355 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
356 U4(surface_desc).ddpfPixelFormat = z_fmt;
357 surface_desc.dwWidth = 640;
358 surface_desc.dwHeight = 480;
359 hr = IDirectDraw4_CreateSurface(ddraw4, &surface_desc, &ds, NULL);
360 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
361 if (FAILED(hr))
363 IDirect3D3_Release(d3d3);
364 IDirectDrawSurface4_Release(surface);
365 return NULL;
368 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
369 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
370 IDirectDrawSurface4_Release(ds);
371 if (FAILED(hr))
373 IDirect3D3_Release(d3d3);
374 IDirectDrawSurface4_Release(surface);
375 return NULL;
378 hr = IDirect3D3_CreateDevice(d3d3, &IID_IDirect3DHALDevice, surface, &device, NULL);
379 IDirect3D3_Release(d3d3);
380 IDirectDrawSurface4_Release(surface);
381 if (FAILED(hr))
382 return NULL;
384 return device;
387 static IDirect3DViewport3 *create_viewport(IDirect3DDevice3 *device, UINT x, UINT y, UINT w, UINT h)
389 IDirect3DViewport3 *viewport;
390 D3DVIEWPORT2 vp;
391 IDirect3D3 *d3d;
392 HRESULT hr;
394 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
395 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
396 hr = IDirect3D3_CreateViewport(d3d, &viewport, NULL);
397 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
398 hr = IDirect3DDevice3_AddViewport(device, viewport);
399 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
400 memset(&vp, 0, sizeof(vp));
401 vp.dwSize = sizeof(vp);
402 vp.dwX = x;
403 vp.dwY = y;
404 vp.dwWidth = w;
405 vp.dwHeight = h;
406 vp.dvClipX = -1.0f;
407 vp.dvClipY = 1.0f;
408 vp.dvClipWidth = 2.0f;
409 vp.dvClipHeight = 2.0f;
410 vp.dvMinZ = 0.0f;
411 vp.dvMaxZ = 1.0f;
412 hr = IDirect3DViewport3_SetViewport2(viewport, &vp);
413 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
414 IDirect3D3_Release(d3d);
416 return viewport;
419 static void destroy_viewport(IDirect3DDevice3 *device, IDirect3DViewport3 *viewport)
421 HRESULT hr;
423 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
424 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
425 IDirect3DViewport3_Release(viewport);
428 static IDirect3DMaterial3 *create_material(IDirect3DDevice3 *device, D3DMATERIAL *mat)
430 IDirect3DMaterial3 *material;
431 IDirect3D3 *d3d;
432 HRESULT hr;
434 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
435 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
436 hr = IDirect3D3_CreateMaterial(d3d, &material, NULL);
437 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
438 hr = IDirect3DMaterial3_SetMaterial(material, mat);
439 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
440 IDirect3D3_Release(d3d);
442 return material;
445 static IDirect3DMaterial3 *create_diffuse_material(IDirect3DDevice3 *device, float r, float g, float b, float a)
447 D3DMATERIAL mat;
449 memset(&mat, 0, sizeof(mat));
450 mat.dwSize = sizeof(mat);
451 U1(U(mat).diffuse).r = r;
452 U2(U(mat).diffuse).g = g;
453 U3(U(mat).diffuse).b = b;
454 U4(U(mat).diffuse).a = a;
456 return create_material(device, &mat);
459 static IDirect3DMaterial3 *create_specular_material(IDirect3DDevice3 *device,
460 float r, float g, float b, float a, float power)
462 D3DMATERIAL mat;
464 memset(&mat, 0, sizeof(mat));
465 mat.dwSize = sizeof(mat);
466 U1(U2(mat).specular).r = r;
467 U2(U2(mat).specular).g = g;
468 U3(U2(mat).specular).b = b;
469 U4(U2(mat).specular).a = a;
470 U4(mat).power = power;
472 return create_material(device, &mat);
475 static IDirect3DMaterial3 *create_emissive_material(IDirect3DDevice3 *device, float r, float g, float b, float a)
477 D3DMATERIAL mat;
479 memset(&mat, 0, sizeof(mat));
480 mat.dwSize = sizeof(mat);
481 U1(U3(mat).emissive).r = r;
482 U2(U3(mat).emissive).g = g;
483 U3(U3(mat).emissive).b = b;
484 U4(U3(mat).emissive).a = a;
486 return create_material(device, &mat);
489 static void destroy_material(IDirect3DMaterial3 *material)
491 IDirect3DMaterial3_Release(material);
494 struct message
496 UINT message;
497 BOOL check_wparam;
498 WPARAM expect_wparam;
501 static const struct message *expect_messages;
503 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
505 if (expect_messages && message == expect_messages->message)
507 if (expect_messages->check_wparam)
508 ok (wparam == expect_messages->expect_wparam,
509 "Got unexpected wparam %lx for message %x, expected %lx.\n",
510 wparam, message, expect_messages->expect_wparam);
512 ++expect_messages;
515 return DefWindowProcA(hwnd, message, wparam, lparam);
518 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
519 * interface. This prevents subsequent SetCooperativeLevel() calls on a
520 * different window from failing with DDERR_HWNDALREADYSET. */
521 static void fix_wndproc(HWND window, LONG_PTR proc)
523 IDirectDraw4 *ddraw;
524 HRESULT hr;
526 if (!(ddraw = create_ddraw()))
527 return;
529 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
530 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
531 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
532 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
533 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
535 IDirectDraw4_Release(ddraw);
538 static void test_process_vertices(void)
540 IDirect3DVertexBuffer *src_vb, *dst_vb;
541 IDirect3DViewport3 *viewport;
542 D3DVERTEXBUFFERDESC vb_desc;
543 IDirect3DDevice3 *device;
544 struct vec3 *src_data;
545 struct vec4 *dst_data;
546 IDirect3D3 *d3d3;
547 D3DVIEWPORT2 vp2;
548 D3DVIEWPORT vp1;
549 HWND window;
550 HRESULT hr;
552 static D3DMATRIX identity =
554 1.0f, 0.0f, 0.0f, 0.0f,
555 0.0f, 1.0f, 0.0f, 0.0f,
556 0.0f, 0.0f, 1.0f, 0.0f,
557 0.0f, 0.0f, 0.0f, 1.0f,
559 static D3DMATRIX projection =
561 1.0f, 0.0f, 0.0f, 0.0f,
562 0.0f, 1.0f, 0.0f, 0.0f,
563 0.0f, 0.0f, 1.0f, 0.0f,
564 6.0f, 7.0f, 8.0f, 1.0f,
567 window = create_window();
568 if (!(device = create_device(window, DDSCL_NORMAL)))
570 skip("Failed to create a 3D device, skipping test.\n");
571 DestroyWindow(window);
572 return;
575 hr = IDirect3DDevice3_GetDirect3D(device, &d3d3);
576 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
578 memset(&vb_desc, 0, sizeof(vb_desc));
579 vb_desc.dwSize = sizeof(vb_desc);
580 vb_desc.dwFVF = D3DFVF_XYZ;
581 vb_desc.dwNumVertices = 3;
582 hr = IDirect3D3_CreateVertexBuffer(d3d3, &vb_desc, &src_vb, 0, NULL);
583 ok(SUCCEEDED(hr), "Failed to create source vertex buffer, hr %#x.\n", hr);
585 hr = IDirect3DVertexBuffer_Lock(src_vb, DDLOCK_WRITEONLY, (void **)&src_data, NULL);
586 ok(SUCCEEDED(hr), "Failed to lock source vertex buffer, hr %#x.\n", hr);
587 src_data[0].x = -1.0f;
588 src_data[0].y = -1.0f;
589 src_data[0].z = -1.0f;
590 src_data[1].x = 0.0f;
591 src_data[1].y = 0.0f;
592 src_data[1].z = 0.0f;
593 src_data[2].x = 1.0f;
594 src_data[2].y = 1.0f;
595 src_data[2].z = 1.0f;
596 hr = IDirect3DVertexBuffer_Unlock(src_vb);
597 ok(SUCCEEDED(hr), "Failed to unlock source vertex buffer, hr %#x.\n", hr);
599 memset(&vb_desc, 0, sizeof(vb_desc));
600 vb_desc.dwSize = sizeof(vb_desc);
601 vb_desc.dwFVF = D3DFVF_XYZRHW;
602 vb_desc.dwNumVertices = 3;
603 hr = IDirect3D3_CreateVertexBuffer(d3d3, &vb_desc, &dst_vb, 0, NULL);
604 ok(SUCCEEDED(hr), "Failed to create destination vertex buffer, hr %#x.\n", hr);
606 hr = IDirect3D3_CreateViewport(d3d3, &viewport, NULL);
607 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
608 hr = IDirect3DDevice3_AddViewport(device, viewport);
609 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
610 vp2.dwSize = sizeof(vp2);
611 vp2.dwX = 10;
612 vp2.dwY = 20;
613 vp2.dwWidth = 100;
614 vp2.dwHeight = 200;
615 vp2.dvClipX = 2.0f;
616 vp2.dvClipY = 3.0f;
617 vp2.dvClipWidth = 4.0f;
618 vp2.dvClipHeight = 5.0f;
619 vp2.dvMinZ = -2.0f;
620 vp2.dvMaxZ = 3.0f;
621 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2);
622 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
623 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
624 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
626 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
627 ok(SUCCEEDED(hr), "Failed to set world transformation, hr %#x.\n", hr);
628 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &identity);
629 ok(SUCCEEDED(hr), "Failed to set view transformation, hr %#x.\n", hr);
630 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity);
631 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
633 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
634 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
636 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
637 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
638 ok(compare_vec4(&dst_data[0], -6.500e+1f, +1.800e+2f, +2.000e-1f, +1.000e+0f, 4096),
639 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
640 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
641 ok(compare_vec4(&dst_data[1], -4.000e+1f, +1.400e+2f, +4.000e-1f, +1.000e+0f, 4096),
642 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
643 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
644 ok(compare_vec4(&dst_data[2], -1.500e+1f, +1.000e+2f, +6.000e-1f, +1.000e+0f, 4096),
645 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
646 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
647 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
648 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
650 hr = IDirect3DDevice3_MultiplyTransform(device, D3DTRANSFORMSTATE_PROJECTION, &projection);
651 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
653 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
654 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
656 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
657 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
658 ok(compare_vec4(&dst_data[0], +8.500e+1f, -1.000e+2f, +1.800e+0f, +1.000e+0f, 4096),
659 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
660 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
661 ok(compare_vec4(&dst_data[1], +1.100e+2f, -1.400e+2f, +2.000e+0f, +1.000e+0f, 4096),
662 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
663 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
664 ok(compare_vec4(&dst_data[2], +1.350e+2f, -1.800e+2f, +2.200e+0f, +1.000e+0f, 4096),
665 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
666 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
667 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
668 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
670 vp2.dwSize = sizeof(vp2);
671 vp2.dwX = 30;
672 vp2.dwY = 40;
673 vp2.dwWidth = 90;
674 vp2.dwHeight = 80;
675 vp2.dvClipX = 4.0f;
676 vp2.dvClipY = 6.0f;
677 vp2.dvClipWidth = 2.0f;
678 vp2.dvClipHeight = 4.0f;
679 vp2.dvMinZ = 3.0f;
680 vp2.dvMaxZ = -2.0f;
681 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2);
682 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
684 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
685 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
687 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
688 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
689 ok(compare_vec4(&dst_data[0], +7.500e+1f, +4.000e+1f, -8.000e-1f, +1.000e+0f, 4096),
690 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
691 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
692 ok(compare_vec4(&dst_data[1], +1.200e+2f, +2.000e+1f, -1.000e+0f, +1.000e+0f, 4096),
693 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
694 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
695 ok(compare_vec4(&dst_data[2], +1.650e+2f, +0.000e+0f, -1.200e+0f, +1.000e+0f, 4096),
696 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
697 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
698 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
699 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
701 vp1.dwSize = sizeof(vp1);
702 vp1.dwX = 30;
703 vp1.dwY = 40;
704 vp1.dwWidth = 90;
705 vp1.dwHeight = 80;
706 vp1.dvScaleX = 7.0f;
707 vp1.dvScaleY = 2.0f;
708 vp1.dvMaxX = 6.0f;
709 vp1.dvMaxY = 10.0f;
710 vp1.dvMinZ = -2.0f;
711 vp1.dvMaxZ = 3.0f;
712 hr = IDirect3DViewport3_SetViewport(viewport, &vp1);
713 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
715 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
716 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
718 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
719 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
720 ok(compare_vec4(&dst_data[0], +1.100e+2f, +6.800e+1f, +7.000e+0f, +1.000e+0f, 4096),
721 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
722 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
723 ok(compare_vec4(&dst_data[1], +1.170e+2f, +6.600e+1f, +8.000e+0f, +1.000e+0f, 4096),
724 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
725 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
726 ok(compare_vec4(&dst_data[2], +1.240e+2f, +6.400e+1f, +9.000e+0f, +1.000e+0f, 4096),
727 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
728 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
729 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
730 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
732 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
733 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
735 IDirect3DVertexBuffer_Release(dst_vb);
736 IDirect3DVertexBuffer_Release(src_vb);
737 IDirect3DViewport3_Release(viewport);
738 IDirect3D3_Release(d3d3);
739 IDirect3DDevice3_Release(device);
740 DestroyWindow(window);
743 static void test_coop_level_create_device_window(void)
745 HWND focus_window, device_window;
746 IDirectDraw4 *ddraw;
747 HRESULT hr;
749 focus_window = create_window();
750 ddraw = create_ddraw();
751 ok(!!ddraw, "Failed to create a ddraw object.\n");
753 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
754 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
755 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
756 ok(!device_window, "Unexpected device window found.\n");
757 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
758 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
759 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
760 ok(!device_window, "Unexpected device window found.\n");
761 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
762 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
763 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
764 ok(!device_window, "Unexpected device window found.\n");
765 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
766 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
767 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
768 ok(!device_window, "Unexpected device window found.\n");
769 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
770 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
771 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
772 ok(!device_window, "Unexpected device window found.\n");
774 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
775 if (broken(hr == DDERR_INVALIDPARAMS))
777 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
778 IDirectDraw4_Release(ddraw);
779 DestroyWindow(focus_window);
780 return;
783 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
784 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
785 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
786 ok(!device_window, "Unexpected device window found.\n");
787 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
788 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
789 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
790 ok(!device_window, "Unexpected device window found.\n");
792 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
793 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
794 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
795 ok(!device_window, "Unexpected device window found.\n");
796 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
797 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
798 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
799 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
800 ok(!!device_window, "Device window not found.\n");
802 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
803 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
804 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
805 ok(!device_window, "Unexpected device window found.\n");
806 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
807 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
808 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
809 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
810 ok(!!device_window, "Device window not found.\n");
812 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
813 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
814 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
815 ok(!device_window, "Unexpected device window found.\n");
816 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
817 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
818 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
819 ok(!device_window, "Unexpected device window found.\n");
820 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
821 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
822 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
823 ok(!device_window, "Unexpected device window found.\n");
824 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
825 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
826 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
827 ok(!!device_window, "Device window not found.\n");
829 IDirectDraw4_Release(ddraw);
830 DestroyWindow(focus_window);
833 static void test_clipper_blt(void)
835 IDirectDrawSurface4 *src_surface, *dst_surface;
836 RECT client_rect, src_rect;
837 IDirectDrawClipper *clipper;
838 DDSURFACEDESC2 surface_desc;
839 unsigned int i, j, x, y;
840 IDirectDraw4 *ddraw;
841 RGNDATA *rgn_data;
842 D3DCOLOR color;
843 ULONG refcount;
844 HRGN r1, r2;
845 HWND window;
846 DDBLTFX fx;
847 HRESULT hr;
848 DWORD *ptr;
849 DWORD ret;
851 static const DWORD src_data[] =
853 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
854 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
855 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
857 static const D3DCOLOR expected1[] =
859 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
860 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
861 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
862 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
864 /* Nvidia on Windows seems to have an off-by-one error
865 * when processing source rectangles. Our left = 1 and
866 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
867 * read as well, but only for the edge pixels on the
868 * output image. The bug happens on the y axis as well,
869 * but we only read one row there, and all source rows
870 * contain the same data. This bug is not dependent on
871 * the presence of a clipper. */
872 static const D3DCOLOR expected1_broken[] =
874 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
875 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
876 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
877 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
879 static const D3DCOLOR expected2[] =
881 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
882 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
883 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
884 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
887 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
888 10, 10, 640, 480, 0, 0, 0, 0);
889 ShowWindow(window, SW_SHOW);
890 ddraw = create_ddraw();
891 ok(!!ddraw, "Failed to create a ddraw object.\n");
893 ret = GetClientRect(window, &client_rect);
894 ok(ret, "Failed to get client rect.\n");
895 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
896 ok(ret, "Failed to map client rect.\n");
898 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
899 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
901 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL);
902 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
903 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
904 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
905 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
906 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
907 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
908 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
909 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
910 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
911 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
912 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
913 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
914 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
915 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
916 "Got unexpected bounding rect %s, expected %s.\n",
917 wine_dbgstr_rect(&rgn_data->rdh.rcBound), wine_dbgstr_rect(&client_rect));
918 HeapFree(GetProcessHeap(), 0, rgn_data);
920 r1 = CreateRectRgn(0, 0, 320, 240);
921 ok(!!r1, "Failed to create region.\n");
922 r2 = CreateRectRgn(320, 240, 640, 480);
923 ok(!!r2, "Failed to create region.\n");
924 CombineRgn(r1, r1, r2, RGN_OR);
925 ret = GetRegionData(r1, 0, NULL);
926 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
927 ret = GetRegionData(r1, ret, rgn_data);
928 ok(!!ret, "Failed to get region data.\n");
930 DeleteObject(r2);
931 DeleteObject(r1);
933 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
934 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
935 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
936 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
937 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
938 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
940 HeapFree(GetProcessHeap(), 0, rgn_data);
942 memset(&surface_desc, 0, sizeof(surface_desc));
943 surface_desc.dwSize = sizeof(surface_desc);
944 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
945 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
946 surface_desc.dwWidth = 640;
947 surface_desc.dwHeight = 480;
948 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
949 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
950 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
951 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
952 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
953 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
955 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
956 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
957 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
958 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
960 memset(&fx, 0, sizeof(fx));
961 fx.dwSize = sizeof(fx);
962 hr = IDirectDrawSurface4_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
963 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
964 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
965 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
967 hr = IDirectDrawSurface4_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
968 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
969 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
970 ptr = surface_desc.lpSurface;
971 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
972 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
973 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
974 hr = IDirectDrawSurface4_Unlock(src_surface, NULL);
975 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
977 hr = IDirectDrawSurface4_SetClipper(dst_surface, clipper);
978 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
980 SetRect(&src_rect, 1, 1, 5, 2);
981 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
982 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
983 for (i = 0; i < 4; ++i)
985 for (j = 0; j < 4; ++j)
987 x = 80 * ((2 * j) + 1);
988 y = 60 * ((2 * i) + 1);
989 color = get_surface_color(dst_surface, x, y);
990 ok(compare_color(color, expected1[i * 4 + j], 1)
991 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
992 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
996 U5(fx).dwFillColor = 0xff0000ff;
997 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
998 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
999 for (i = 0; i < 4; ++i)
1001 for (j = 0; j < 4; ++j)
1003 x = 80 * ((2 * j) + 1);
1004 y = 60 * ((2 * i) + 1);
1005 color = get_surface_color(dst_surface, x, y);
1006 ok(compare_color(color, expected2[i * 4 + j], 1),
1007 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
1011 hr = IDirectDrawSurface4_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
1012 ok(hr == DDERR_BLTFASTCANTCLIP, "Got unexpected hr %#x.\n", hr);
1014 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
1015 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
1016 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1017 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
1018 DestroyWindow(window);
1019 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1020 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
1021 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
1022 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
1023 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1024 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
1025 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
1026 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
1027 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1028 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
1029 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1030 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
1032 IDirectDrawSurface4_Release(dst_surface);
1033 IDirectDrawSurface4_Release(src_surface);
1034 refcount = IDirectDrawClipper_Release(clipper);
1035 ok(!refcount, "Clipper has %u references left.\n", refcount);
1036 IDirectDraw4_Release(ddraw);
1039 static void test_coop_level_d3d_state(void)
1041 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1042 IDirectDrawSurface4 *rt, *surface;
1043 IDirect3DViewport3 *viewport;
1044 IDirect3DDevice3 *device;
1045 IDirectDraw4 *ddraw;
1046 IDirect3D3 *d3d;
1047 D3DCOLOR color;
1048 DWORD value;
1049 HWND window;
1050 HRESULT hr;
1052 window = create_window();
1053 if (!(device = create_device(window, DDSCL_NORMAL)))
1055 skip("Failed to create a 3D device, skipping test.\n");
1056 DestroyWindow(window);
1057 return;
1060 viewport = create_viewport(device, 0, 0, 640, 480);
1062 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1063 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1064 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
1065 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1066 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
1067 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1068 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1069 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
1070 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
1071 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
1072 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1073 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1074 color = get_surface_color(rt, 320, 240);
1075 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1077 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1078 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1079 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1080 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1081 IDirect3D3_Release(d3d);
1082 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1083 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1084 hr = IDirectDrawSurface4_IsLost(rt);
1085 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
1086 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
1087 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
1088 IDirectDraw4_Release(ddraw);
1090 hr = IDirect3DDevice3_GetRenderTarget(device, &surface);
1091 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1092 ok(surface == rt, "Got unexpected surface %p.\n", surface);
1093 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
1094 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1095 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
1096 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1097 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1098 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
1099 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
1100 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1101 color = get_surface_color(rt, 320, 240);
1102 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1104 destroy_viewport(device, viewport);
1105 IDirectDrawSurface4_Release(surface);
1106 IDirectDrawSurface4_Release(rt);
1107 IDirect3DDevice3_Release(device);
1108 DestroyWindow(window);
1111 static void test_surface_interface_mismatch(void)
1113 IDirectDraw4 *ddraw = NULL;
1114 IDirect3D3 *d3d = NULL;
1115 IDirectDrawSurface4 *surface = NULL, *ds;
1116 IDirectDrawSurface3 *surface3 = NULL;
1117 IDirect3DDevice3 *device = NULL;
1118 IDirect3DViewport3 *viewport = NULL;
1119 DDSURFACEDESC2 surface_desc;
1120 DDPIXELFORMAT z_fmt;
1121 ULONG refcount;
1122 HRESULT hr;
1123 D3DCOLOR color;
1124 HWND window;
1125 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1127 window = create_window();
1128 ddraw = create_ddraw();
1129 ok(!!ddraw, "Failed to create a ddraw object.\n");
1130 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1131 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1133 memset(&surface_desc, 0, sizeof(surface_desc));
1134 surface_desc.dwSize = sizeof(surface_desc);
1135 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1136 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1137 surface_desc.dwWidth = 640;
1138 surface_desc.dwHeight = 480;
1140 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1141 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1143 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
1144 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface3, hr %#x.\n", hr);
1146 if (FAILED(IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
1148 skip("D3D interface is not available, skipping test.\n");
1149 goto cleanup;
1152 memset(&z_fmt, 0, sizeof(z_fmt));
1153 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
1154 if (FAILED(hr) || !z_fmt.dwSize)
1156 skip("No depth buffer formats available, skipping test.\n");
1157 goto cleanup;
1160 memset(&surface_desc, 0, sizeof(surface_desc));
1161 surface_desc.dwSize = sizeof(surface_desc);
1162 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
1163 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1164 U4(surface_desc).ddpfPixelFormat = z_fmt;
1165 surface_desc.dwWidth = 640;
1166 surface_desc.dwHeight = 480;
1167 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &ds, NULL);
1168 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
1169 if (FAILED(hr))
1170 goto cleanup;
1172 /* Using a different surface interface version still works */
1173 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
1174 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
1175 refcount = IDirectDrawSurface4_Release(ds);
1176 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
1177 if (FAILED(hr))
1178 goto cleanup;
1180 /* Here too */
1181 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface4 *)surface3, &device, NULL);
1182 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
1183 if (FAILED(hr))
1184 goto cleanup;
1186 viewport = create_viewport(device, 0, 0, 640, 480);
1188 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1189 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1190 color = get_surface_color(surface, 320, 240);
1191 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1193 cleanup:
1194 if (viewport)
1195 destroy_viewport(device, viewport);
1196 if (surface3) IDirectDrawSurface3_Release(surface3);
1197 if (surface) IDirectDrawSurface4_Release(surface);
1198 if (device) IDirect3DDevice3_Release(device);
1199 if (d3d) IDirect3D3_Release(d3d);
1200 if (ddraw) IDirectDraw4_Release(ddraw);
1201 DestroyWindow(window);
1204 static void test_coop_level_threaded(void)
1206 struct create_window_thread_param p;
1207 IDirectDraw4 *ddraw;
1208 HRESULT hr;
1210 ddraw = create_ddraw();
1211 ok(!!ddraw, "Failed to create a ddraw object.\n");
1212 create_window_thread(&p);
1214 hr = IDirectDraw4_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1215 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1217 IDirectDraw4_Release(ddraw);
1218 destroy_window_thread(&p);
1221 static void test_depth_blit(void)
1223 static struct
1225 float x, y, z;
1226 DWORD color;
1228 quad1[] =
1230 { -1.0, 1.0, 0.50f, 0xff00ff00},
1231 { 1.0, 1.0, 0.50f, 0xff00ff00},
1232 { -1.0, -1.0, 0.50f, 0xff00ff00},
1233 { 1.0, -1.0, 0.50f, 0xff00ff00},
1235 static const D3DCOLOR expected_colors[4][4] =
1237 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1238 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1239 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1240 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1242 DDSURFACEDESC2 ddsd_new, ddsd_existing;
1244 IDirect3DDevice3 *device;
1245 IDirectDrawSurface4 *ds1, *ds2, *ds3, *rt;
1246 IDirect3DViewport3 *viewport;
1247 RECT src_rect, dst_rect;
1248 unsigned int i, j;
1249 D3DCOLOR color;
1250 HRESULT hr;
1251 IDirect3D3 *d3d;
1252 IDirectDraw4 *ddraw;
1253 DDBLTFX fx;
1254 HWND window;
1255 D3DRECT d3drect;
1257 window = create_window();
1258 if (!(device = create_device(window, DDSCL_NORMAL)))
1260 skip("Failed to create a 3D device, skipping test.\n");
1261 DestroyWindow(window);
1262 return;
1265 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1266 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
1267 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1268 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
1269 IDirect3D3_Release(d3d);
1271 ds1 = get_depth_stencil(device);
1273 memset(&ddsd_new, 0, sizeof(ddsd_new));
1274 ddsd_new.dwSize = sizeof(ddsd_new);
1275 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1276 ddsd_existing.dwSize = sizeof(ddsd_existing);
1277 hr = IDirectDrawSurface4_GetSurfaceDesc(ds1, &ddsd_existing);
1278 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
1279 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1280 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1281 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1282 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1283 U4(ddsd_new).ddpfPixelFormat = U4(ddsd_existing).ddpfPixelFormat;
1284 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1285 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1286 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1287 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1288 IDirectDraw4_Release(ddraw);
1290 viewport = create_viewport(device, 0, 0, ddsd_existing.dwWidth, ddsd_existing.dwHeight);
1291 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1292 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
1294 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1295 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
1296 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1297 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
1299 U1(d3drect).x1 = U2(d3drect).y1 = 0;
1300 U3(d3drect).x2 = ddsd_existing.dwWidth; U4(d3drect).y2 = ddsd_existing.dwHeight;
1301 hr = IDirect3DViewport3_Clear2(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
1302 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
1304 /* Partial blit. */
1305 SetRect(&src_rect, 0, 0, 320, 240);
1306 SetRect(&dst_rect, 0, 0, 320, 240);
1307 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1308 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1309 /* Different locations. */
1310 SetRect(&src_rect, 0, 0, 320, 240);
1311 SetRect(&dst_rect, 320, 240, 640, 480);
1312 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1313 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1314 /* Stretched. */
1315 SetRect(&src_rect, 0, 0, 320, 240);
1316 SetRect(&dst_rect, 0, 0, 640, 480);
1317 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1318 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1319 /* Flipped. */
1320 SetRect(&src_rect, 0, 480, 640, 0);
1321 SetRect(&dst_rect, 0, 0, 640, 480);
1322 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1323 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1324 SetRect(&src_rect, 0, 0, 640, 480);
1325 SetRect(&dst_rect, 0, 480, 640, 0);
1326 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1327 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1328 /* Full, explicit. */
1329 SetRect(&src_rect, 0, 0, 640, 480);
1330 SetRect(&dst_rect, 0, 0, 640, 480);
1331 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1332 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1333 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1335 /* Depth blit inside a BeginScene / EndScene pair */
1336 hr = IDirect3DDevice3_BeginScene(device);
1337 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1338 /* From the current depth stencil */
1339 hr = IDirectDrawSurface4_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1340 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1341 /* To the current depth stencil */
1342 hr = IDirectDrawSurface4_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1343 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1344 /* Between unbound surfaces */
1345 hr = IDirectDrawSurface4_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1346 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1347 hr = IDirect3DDevice3_EndScene(device);
1348 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1350 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1351 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1352 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1353 * a reliable result(z = 0.0) */
1354 memset(&fx, 0, sizeof(fx));
1355 fx.dwSize = sizeof(fx);
1356 hr = IDirectDrawSurface4_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1357 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1359 hr = IDirect3DViewport3_Clear2(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
1360 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1361 SetRect(&dst_rect, 0, 0, 320, 240);
1362 hr = IDirectDrawSurface4_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1363 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1364 IDirectDrawSurface4_Release(ds3);
1365 IDirectDrawSurface4_Release(ds2);
1366 IDirectDrawSurface4_Release(ds1);
1368 hr = IDirect3DDevice3_BeginScene(device);
1369 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1370 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1371 quad1, 4, 0);
1372 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1373 hr = IDirect3DDevice3_EndScene(device);
1374 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1376 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1377 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1378 for (i = 0; i < 4; ++i)
1380 for (j = 0; j < 4; ++j)
1382 unsigned int x = 80 * ((2 * j) + 1);
1383 unsigned int y = 60 * ((2 * i) + 1);
1384 color = get_surface_color(rt, x, y);
1385 ok(compare_color(color, expected_colors[i][j], 1),
1386 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1389 IDirectDrawSurface4_Release(rt);
1391 destroy_viewport(device, viewport);
1392 IDirect3DDevice3_Release(device);
1393 DestroyWindow(window);
1396 static void test_texture_load_ckey(void)
1398 IDirectDraw4 *ddraw;
1399 IDirectDrawSurface4 *src;
1400 IDirectDrawSurface4 *dst;
1401 IDirect3DTexture2 *src_tex;
1402 IDirect3DTexture2 *dst_tex;
1403 DDSURFACEDESC2 ddsd;
1404 HRESULT hr;
1405 DDCOLORKEY ckey;
1407 ddraw = create_ddraw();
1408 ok(!!ddraw, "Failed to create a ddraw object.\n");
1409 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
1410 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1412 memset(&ddsd, 0, sizeof(ddsd));
1413 ddsd.dwSize = sizeof(ddsd);
1414 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1415 ddsd.dwHeight = 128;
1416 ddsd.dwWidth = 128;
1417 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1418 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &src, NULL);
1419 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1420 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1421 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &dst, NULL);
1422 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1424 hr = IDirectDrawSurface4_QueryInterface(src, &IID_IDirect3DTexture2, (void **)&src_tex);
1425 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get Direct3DTexture2 interface, hr %#x.\n", hr);
1426 if (FAILED(hr))
1428 /* 64 bit ddraw does not support d3d */
1429 skip("Could not get Direct3DTexture2 interface, skipping texture::Load color keying tests.\n");
1430 IDirectDrawSurface4_Release(dst);
1431 IDirectDrawSurface4_Release(src);
1432 IDirectDraw4_Release(ddraw);
1433 return;
1435 hr = IDirectDrawSurface4_QueryInterface(dst, &IID_IDirect3DTexture2, (void **)&dst_tex);
1436 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture2 interface, hr %#x.\n", hr);
1438 /* No surface has a color key */
1439 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1440 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1441 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1442 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1443 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1444 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1445 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1447 /* Source surface has a color key */
1448 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1449 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1450 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1451 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1452 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1453 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1454 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1455 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1456 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1458 /* Both surfaces have a color key: Dest ckey is overwritten */
1459 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1460 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1461 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1462 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1463 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1464 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1465 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1466 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1467 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1469 /* Only the destination has a color key: It is not deleted */
1470 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1471 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1472 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1473 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1474 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1475 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1476 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1477 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1478 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1479 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1481 IDirect3DTexture2_Release(dst_tex);
1482 IDirect3DTexture2_Release(src_tex);
1483 IDirectDrawSurface4_Release(dst);
1484 IDirectDrawSurface4_Release(src);
1485 IDirectDraw4_Release(ddraw);
1488 static ULONG get_refcount(IUnknown *test_iface)
1490 IUnknown_AddRef(test_iface);
1491 return IUnknown_Release(test_iface);
1494 static void test_viewport(void)
1496 IDirectDraw4 *ddraw;
1497 IDirect3D3 *d3d;
1498 HRESULT hr, old_d3d_ref;
1499 ULONG ref;
1500 IDirect3DViewport *viewport;
1501 IDirect3DViewport2 *viewport2;
1502 IDirect3DViewport3 *viewport3, *another_vp, *test_vp;
1503 IDirectDrawGammaControl *gamma;
1504 IUnknown *unknown;
1505 HWND window;
1506 IDirect3DDevice3 *device;
1508 window = create_window();
1509 if (!(device = create_device(window, DDSCL_NORMAL)))
1511 skip("Failed to create a 3D device, skipping test.\n");
1512 DestroyWindow(window);
1513 return;
1515 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1516 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
1517 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1518 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
1519 old_d3d_ref = get_refcount((IUnknown *) d3d);
1521 hr = IDirect3D3_CreateViewport(d3d, &viewport3, NULL);
1522 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1523 ref = get_refcount((IUnknown *)viewport3);
1524 ok(ref == 1, "Initial IDirect3DViewport3 refcount is %u\n", ref);
1525 ref = get_refcount((IUnknown *)d3d);
1526 ok(ref == old_d3d_ref, "IDirect3D3 refcount is %u\n", ref);
1528 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1529 hr = IDirect3DViewport2_QueryInterface(viewport3, &IID_IDirectDrawGammaControl, (void **)&gamma);
1530 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
1531 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
1532 if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
1533 /* NULL iid: Segfaults */
1535 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IDirect3DViewport, (void **)&viewport);
1536 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport, hr %#x.\n", hr);
1537 if (viewport)
1539 ref = get_refcount((IUnknown *)viewport);
1540 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1541 ref = get_refcount((IUnknown *)viewport3);
1542 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1543 IDirect3DViewport_Release(viewport);
1544 viewport = NULL;
1547 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IDirect3DViewport3, (void **)&viewport2);
1548 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1549 if (viewport2)
1551 ref = get_refcount((IUnknown *)viewport2);
1552 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1553 ref = get_refcount((IUnknown *)viewport3);
1554 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1555 IDirect3DViewport3_Release(viewport2);
1558 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IUnknown, (void **)&unknown);
1559 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1560 if (unknown)
1562 ref = get_refcount((IUnknown *)viewport3);
1563 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1564 ref = get_refcount(unknown);
1565 ok(ref == 2, "IUnknown refcount is %u\n", ref);
1566 IUnknown_Release(unknown);
1569 /* AddViewport(NULL): Segfault */
1570 hr = IDirect3DDevice3_DeleteViewport(device, NULL);
1571 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1572 hr = IDirect3DDevice3_GetCurrentViewport(device, NULL);
1573 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1575 hr = IDirect3D3_CreateViewport(d3d, &another_vp, NULL);
1576 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1578 /* Setting a viewport not in the viewport list fails */
1579 hr = IDirect3DDevice3_SetCurrentViewport(device, another_vp);
1580 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1582 hr = IDirect3DDevice3_AddViewport(device, viewport3);
1583 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1584 ref = get_refcount((IUnknown *) viewport3);
1585 ok(ref == 2, "viewport3 refcount is %d\n", ref);
1586 hr = IDirect3DDevice3_AddViewport(device, another_vp);
1587 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1588 ref = get_refcount((IUnknown *) another_vp);
1589 ok(ref == 2, "another_vp refcount is %d\n", ref);
1591 test_vp = (IDirect3DViewport3 *) 0xbaadc0de;
1592 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1593 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1594 ok(test_vp == (IDirect3DViewport3 *) 0xbaadc0de, "Got unexpected pointer %p\n", test_vp);
1596 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport3);
1597 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1598 ref = get_refcount((IUnknown *) viewport3);
1599 ok(ref == 3, "viewport3 refcount is %d\n", ref);
1600 ref = get_refcount((IUnknown *) device);
1601 ok(ref == 1, "device refcount is %d\n", ref);
1603 test_vp = NULL;
1604 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1605 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1606 ok(test_vp == viewport3, "Got unexpected viewport %p\n", test_vp);
1607 ref = get_refcount((IUnknown *) viewport3);
1608 ok(ref == 4, "viewport3 refcount is %d\n", ref);
1609 if(test_vp) IDirect3DViewport3_Release(test_vp);
1611 /* GetCurrentViewport with a viewport set and NULL input param: Segfault */
1613 /* Cannot set the viewport to NULL */
1614 hr = IDirect3DDevice3_SetCurrentViewport(device, NULL);
1615 ok(hr == DDERR_INVALIDPARAMS, "Failed to set viewport to NULL, hr %#x.\n", hr);
1616 test_vp = NULL;
1617 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1618 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1619 ok(test_vp == viewport3, "Got unexpected viewport %p\n", test_vp);
1620 if(test_vp) IDirect3DViewport3_Release(test_vp);
1622 /* SetCurrentViewport properly releases the old viewport's reference */
1623 hr = IDirect3DDevice3_SetCurrentViewport(device, another_vp);
1624 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1625 ref = get_refcount((IUnknown *) viewport3);
1626 ok(ref == 2, "viewport3 refcount is %d\n", ref);
1627 ref = get_refcount((IUnknown *) another_vp);
1628 ok(ref == 3, "another_vp refcount is %d\n", ref);
1630 /* Unlike device2::DeleteViewport, device3::DeleteViewport releases the
1631 * reference held by SetCurrentViewport */
1632 hr = IDirect3DDevice3_DeleteViewport(device, another_vp);
1633 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1634 ref = get_refcount((IUnknown *) another_vp);
1635 ok(ref == 1, "another_vp refcount is %d\n", ref);
1637 /* GetCurrentViewport still fails */
1638 test_vp = NULL;
1639 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1640 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1641 ok(test_vp == NULL, "Got unexpected viewport %p\n", test_vp);
1642 if(test_vp) IDirect3DViewport3_Release(test_vp);
1644 /* Setting a different viewport doesn't have any surprises now */
1645 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport3);
1646 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1647 ref = get_refcount((IUnknown *) viewport3);
1648 ok(ref == 3, "viewport3 refcount is %d\n", ref);
1649 ref = get_refcount((IUnknown *) another_vp);
1650 ok(ref == 1, "another_vp refcount is %d\n", ref);
1652 /* Destroying the device removes the viewport and releases the reference */
1653 IDirect3DDevice3_Release(device);
1654 ref = get_refcount((IUnknown *) viewport3);
1655 ok(ref == 1, "viewport3 refcount is %d\n", ref);
1657 ref = IDirect3DViewport3_Release(another_vp);
1658 ok(ref == 0, "Got unexpected ref %d\n", ref);
1659 ref = IDirect3DViewport3_Release(viewport3);
1660 ok(ref == 0, "Got unexpected ref %d\n", ref);
1661 IDirect3D3_Release(d3d);
1662 DestroyWindow(window);
1663 IDirectDraw4_Release(ddraw);
1666 static void test_zenable(void)
1668 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1669 static struct
1671 struct vec4 position;
1672 D3DCOLOR diffuse;
1674 tquad[] =
1676 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xff00ff00},
1677 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xff00ff00},
1678 {{640.0f, 480.0f, 1.5f, 1.0f}, 0xff00ff00},
1679 {{640.0f, 0.0f, 1.5f, 1.0f}, 0xff00ff00},
1681 IDirect3DViewport3 *viewport;
1682 IDirect3DDevice3 *device;
1683 IDirectDrawSurface4 *rt;
1684 D3DCOLOR color;
1685 HWND window;
1686 HRESULT hr;
1687 UINT x, y;
1688 UINT i, j;
1690 window = create_window();
1691 if (!(device = create_device(window, DDSCL_NORMAL)))
1693 skip("Failed to create a 3D device, skipping test.\n");
1694 DestroyWindow(window);
1695 return;
1698 viewport = create_viewport(device, 0, 0, 640, 480);
1699 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1700 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1702 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1703 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1705 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0f, 0);
1706 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1707 hr = IDirect3DDevice3_BeginScene(device);
1708 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1709 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, tquad, 4, 0);
1710 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1711 hr = IDirect3DDevice3_EndScene(device);
1712 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1714 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1715 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1716 for (i = 0; i < 4; ++i)
1718 for (j = 0; j < 4; ++j)
1720 x = 80 * ((2 * j) + 1);
1721 y = 60 * ((2 * i) + 1);
1722 color = get_surface_color(rt, x, y);
1723 ok(compare_color(color, 0x0000ff00, 1),
1724 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1727 IDirectDrawSurface4_Release(rt);
1729 destroy_viewport(device, viewport);
1730 IDirect3DDevice3_Release(device);
1731 DestroyWindow(window);
1734 static void test_ck_rgba(void)
1736 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1737 static struct
1739 struct vec4 position;
1740 struct vec2 texcoord;
1742 tquad[] =
1744 {{ 0.0f, 480.0f, 0.25f, 1.0f}, {0.0f, 0.0f}},
1745 {{ 0.0f, 0.0f, 0.25f, 1.0f}, {0.0f, 1.0f}},
1746 {{640.0f, 480.0f, 0.25f, 1.0f}, {1.0f, 0.0f}},
1747 {{640.0f, 0.0f, 0.25f, 1.0f}, {1.0f, 1.0f}},
1748 {{ 0.0f, 480.0f, 0.75f, 1.0f}, {0.0f, 0.0f}},
1749 {{ 0.0f, 0.0f, 0.75f, 1.0f}, {0.0f, 1.0f}},
1750 {{640.0f, 480.0f, 0.75f, 1.0f}, {1.0f, 0.0f}},
1751 {{640.0f, 0.0f, 0.75f, 1.0f}, {1.0f, 1.0f}},
1753 static const struct
1755 D3DCOLOR fill_color;
1756 BOOL color_key;
1757 BOOL blend;
1758 D3DCOLOR result1, result1_broken;
1759 D3DCOLOR result2, result2_broken;
1761 tests[] =
1763 /* r200 on Windows doesn't check the alpha component when applying the color
1764 * key, so the key matches on every texel. */
1765 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1766 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1767 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1768 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1769 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00ff0000, 0x00807f00, 0x000000ff},
1770 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x00ff0000, 0x0000ff00, 0x000000ff},
1771 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00, 0x00807f00, 0x00807f00},
1772 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1775 IDirectDrawSurface4 *surface;
1776 IDirect3DViewport3 *viewport;
1777 DDSURFACEDESC2 surface_desc;
1778 IDirect3DTexture2 *texture;
1779 IDirect3DDevice3 *device;
1780 IDirectDrawSurface4 *rt;
1781 IDirectDraw4 *ddraw;
1782 IDirect3D3 *d3d;
1783 D3DCOLOR color;
1784 HWND window;
1785 DDBLTFX fx;
1786 HRESULT hr;
1787 UINT i;
1789 window = create_window();
1790 if (!(device = create_device(window, DDSCL_NORMAL)))
1792 skip("Failed to create a 3D device, skipping test.\n");
1793 DestroyWindow(window);
1794 return;
1797 viewport = create_viewport(device, 0, 0, 640, 480);
1798 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1799 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1801 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1802 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1803 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1804 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1805 IDirect3D3_Release(d3d);
1807 memset(&surface_desc, 0, sizeof(surface_desc));
1808 surface_desc.dwSize = sizeof(surface_desc);
1809 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1810 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1811 surface_desc.dwWidth = 256;
1812 surface_desc.dwHeight = 256;
1813 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1814 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1815 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1816 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1817 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1818 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1819 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1820 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1821 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1822 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1823 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1824 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1825 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1827 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
1828 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1829 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1830 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1831 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1832 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1834 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1835 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1837 for (i = 0; i < ARRAY_SIZE(tests); ++i)
1839 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1840 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1841 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1842 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1844 memset(&fx, 0, sizeof(fx));
1845 fx.dwSize = sizeof(fx);
1846 U5(fx).dwFillColor = tests[i].fill_color;
1847 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1848 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1850 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect,
1851 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
1852 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1853 hr = IDirect3DDevice3_BeginScene(device);
1854 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1855 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1856 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1857 hr = IDirect3DDevice3_EndScene(device);
1858 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1860 color = get_surface_color(rt, 320, 240);
1861 ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
1862 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1863 tests[i].result1, i, color);
1865 U5(fx).dwFillColor = 0xff0000ff;
1866 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1867 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1869 hr = IDirect3DDevice3_BeginScene(device);
1870 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1871 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[4], 4, 0);
1872 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1873 hr = IDirect3DDevice3_EndScene(device);
1874 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1876 /* This tests that fragments that are masked out by the color key are
1877 * discarded, instead of just fully transparent. */
1878 color = get_surface_color(rt, 320, 240);
1879 ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
1880 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1881 tests[i].result2, i, color);
1884 IDirectDrawSurface4_Release(rt);
1885 IDirect3DTexture2_Release(texture);
1886 IDirectDrawSurface4_Release(surface);
1887 destroy_viewport(device, viewport);
1888 IDirectDraw4_Release(ddraw);
1889 IDirect3DDevice3_Release(device);
1890 DestroyWindow(window);
1893 static void test_ck_default(void)
1895 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1896 static struct
1898 struct vec4 position;
1899 struct vec2 texcoord;
1901 tquad[] =
1903 {{ 0.0f, 480.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
1904 {{ 0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
1905 {{640.0f, 480.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
1906 {{640.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
1908 IDirectDrawSurface4 *surface, *rt;
1909 IDirect3DViewport3 *viewport;
1910 DDSURFACEDESC2 surface_desc;
1911 IDirect3DTexture2 *texture;
1912 IDirect3DDevice3 *device;
1913 IDirectDraw4 *ddraw;
1914 IDirect3D3 *d3d;
1915 D3DCOLOR color;
1916 DWORD value;
1917 HWND window;
1918 DDBLTFX fx;
1919 HRESULT hr;
1921 window = create_window();
1922 if (!(device = create_device(window, DDSCL_NORMAL)))
1924 skip("Failed to create a 3D device, skipping test.\n");
1925 DestroyWindow(window);
1926 return;
1929 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1930 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1931 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1932 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1933 IDirect3D3_Release(d3d);
1935 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1936 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1938 viewport = create_viewport(device, 0, 0, 640, 480);
1939 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1940 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1942 memset(&surface_desc, 0, sizeof(surface_desc));
1943 surface_desc.dwSize = sizeof(surface_desc);
1944 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1945 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1946 surface_desc.dwWidth = 256;
1947 surface_desc.dwHeight = 256;
1948 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1949 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
1950 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1951 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1952 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1953 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1954 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1955 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1956 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1957 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1958 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1959 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1960 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
1961 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1963 memset(&fx, 0, sizeof(fx));
1964 fx.dwSize = sizeof(fx);
1965 U5(fx).dwFillColor = 0x000000ff;
1966 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1967 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1969 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1970 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1971 hr = IDirect3DDevice3_BeginScene(device);
1972 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1973 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1974 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1975 ok(!value, "Got unexpected color keying state %#x.\n", value);
1976 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1977 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1978 hr = IDirect3DDevice3_EndScene(device);
1979 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1980 color = get_surface_color(rt, 320, 240);
1981 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1983 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1984 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1985 hr = IDirect3DDevice3_BeginScene(device);
1986 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1987 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1988 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1989 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1990 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1991 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1992 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1993 ok(!!value, "Got unexpected color keying state %#x.\n", value);
1994 hr = IDirect3DDevice3_EndScene(device);
1995 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1996 color = get_surface_color(rt, 320, 240);
1997 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1999 IDirect3DTexture_Release(texture);
2000 IDirectDrawSurface4_Release(surface);
2001 destroy_viewport(device, viewport);
2002 IDirectDrawSurface4_Release(rt);
2003 IDirect3DDevice3_Release(device);
2004 IDirectDraw4_Release(ddraw);
2005 DestroyWindow(window);
2008 static void test_ck_complex(void)
2010 IDirectDrawSurface4 *surface, *mipmap, *tmp;
2011 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
2012 DDSURFACEDESC2 surface_desc;
2013 IDirect3DDevice3 *device;
2014 DDCOLORKEY color_key;
2015 IDirectDraw4 *ddraw;
2016 IDirect3D3 *d3d;
2017 unsigned int i;
2018 ULONG refcount;
2019 HWND window;
2020 HRESULT hr;
2022 window = create_window();
2023 if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
2025 skip("Failed to create a 3D device, skipping test.\n");
2026 DestroyWindow(window);
2027 return;
2029 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
2030 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
2031 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
2032 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
2033 IDirect3D3_Release(d3d);
2035 memset(&surface_desc, 0, sizeof(surface_desc));
2036 surface_desc.dwSize = sizeof(surface_desc);
2037 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2038 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2039 surface_desc.dwWidth = 128;
2040 surface_desc.dwHeight = 128;
2041 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2042 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2044 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2045 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
2046 color_key.dwColorSpaceLowValue = 0x0000ff00;
2047 color_key.dwColorSpaceHighValue = 0x0000ff00;
2048 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2049 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2050 memset(&color_key, 0, sizeof(color_key));
2051 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2052 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2053 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2054 color_key.dwColorSpaceLowValue);
2055 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2056 color_key.dwColorSpaceHighValue);
2058 mipmap = surface;
2059 IDirectDrawSurface_AddRef(mipmap);
2060 for (i = 0; i < 7; ++i)
2062 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
2063 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
2065 hr = IDirectDrawSurface4_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2066 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
2067 color_key.dwColorSpaceLowValue = 0x000000ff;
2068 color_key.dwColorSpaceHighValue = 0x000000ff;
2069 hr = IDirectDrawSurface4_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2070 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x, i %u.\n", hr, i);
2071 memset(&color_key, 0, sizeof(color_key));
2072 hr = IDirectDrawSurface4_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2073 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x, i %u.\n", hr, i);
2074 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
2075 color_key.dwColorSpaceLowValue, i);
2076 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
2077 color_key.dwColorSpaceHighValue, i);
2079 IDirectDrawSurface_Release(mipmap);
2080 mipmap = tmp;
2083 memset(&color_key, 0, sizeof(color_key));
2084 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2085 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2086 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2087 color_key.dwColorSpaceLowValue);
2088 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2089 color_key.dwColorSpaceHighValue);
2091 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
2092 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
2093 IDirectDrawSurface_Release(mipmap);
2094 refcount = IDirectDrawSurface4_Release(surface);
2095 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2097 memset(&surface_desc, 0, sizeof(surface_desc));
2098 surface_desc.dwSize = sizeof(surface_desc);
2099 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
2100 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
2101 U5(surface_desc).dwBackBufferCount = 1;
2102 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2103 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2105 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2106 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
2107 color_key.dwColorSpaceLowValue = 0x0000ff00;
2108 color_key.dwColorSpaceHighValue = 0x0000ff00;
2109 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2110 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2111 memset(&color_key, 0, sizeof(color_key));
2112 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2113 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2114 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2115 color_key.dwColorSpaceLowValue);
2116 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2117 color_key.dwColorSpaceHighValue);
2119 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &tmp);
2120 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
2122 hr = IDirectDrawSurface4_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2123 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
2124 color_key.dwColorSpaceLowValue = 0x0000ff00;
2125 color_key.dwColorSpaceHighValue = 0x0000ff00;
2126 hr = IDirectDrawSurface4_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2127 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2128 memset(&color_key, 0, sizeof(color_key));
2129 hr = IDirectDrawSurface4_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2130 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2131 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2132 color_key.dwColorSpaceLowValue);
2133 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2134 color_key.dwColorSpaceHighValue);
2136 IDirectDrawSurface_Release(tmp);
2138 refcount = IDirectDrawSurface4_Release(surface);
2139 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2140 IDirectDraw4_Release(ddraw);
2141 refcount = IDirect3DDevice3_Release(device);
2142 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2143 DestroyWindow(window);
2146 struct qi_test
2148 REFIID iid;
2149 REFIID refcount_iid;
2150 HRESULT hr;
2153 static void test_qi(const char *test_name, IUnknown *base_iface,
2154 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
2156 ULONG refcount, expected_refcount;
2157 IUnknown *iface1, *iface2;
2158 HRESULT hr;
2159 UINT i, j;
2161 for (i = 0; i < entry_count; ++i)
2163 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
2164 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
2165 if (SUCCEEDED(hr))
2167 for (j = 0; j < entry_count; ++j)
2169 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
2170 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
2171 if (SUCCEEDED(hr))
2173 expected_refcount = 0;
2174 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
2175 ++expected_refcount;
2176 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
2177 ++expected_refcount;
2178 refcount = IUnknown_Release(iface2);
2179 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
2180 refcount, test_name, i, j, expected_refcount);
2184 expected_refcount = 0;
2185 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
2186 ++expected_refcount;
2187 refcount = IUnknown_Release(iface1);
2188 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
2189 refcount, test_name, i, expected_refcount);
2194 static void test_surface_qi(void)
2196 static const struct qi_test tests[] =
2198 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface4, S_OK },
2199 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface4, S_OK },
2200 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
2201 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2202 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
2203 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
2204 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
2205 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
2206 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
2207 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
2208 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
2209 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
2210 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
2211 {&IID_IDirect3D7, NULL, E_INVALIDARG },
2212 {&IID_IDirect3D3, NULL, E_INVALIDARG },
2213 {&IID_IDirect3D2, NULL, E_INVALIDARG },
2214 {&IID_IDirect3D, NULL, E_INVALIDARG },
2215 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
2216 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
2217 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
2218 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
2219 {&IID_IDirectDraw, NULL, E_INVALIDARG },
2220 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
2221 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
2222 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
2223 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
2224 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
2225 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
2226 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
2227 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
2228 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
2229 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
2230 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
2231 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
2232 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
2233 {NULL, NULL, E_INVALIDARG },
2236 IDirectDrawSurface4 *surface;
2237 DDSURFACEDESC2 surface_desc;
2238 IDirect3DDevice3 *device;
2239 IDirectDraw4 *ddraw;
2240 HWND window;
2241 HRESULT hr;
2243 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
2245 win_skip("DirectDrawCreateEx not available, skipping test.\n");
2246 return;
2249 window = create_window();
2250 /* Try to create a D3D device to see if the ddraw implementation supports
2251 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
2252 * doesn't support e.g. the IDirect3DTexture interfaces. */
2253 if (!(device = create_device(window, DDSCL_NORMAL)))
2255 skip("Failed to create a 3D device, skipping test.\n");
2256 DestroyWindow(window);
2257 return;
2259 IDirect3DDevice_Release(device);
2260 ddraw = create_ddraw();
2261 ok(!!ddraw, "Failed to create a ddraw object.\n");
2262 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2263 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2265 memset(&surface_desc, 0, sizeof(surface_desc));
2266 surface_desc.dwSize = sizeof(surface_desc);
2267 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2268 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2269 surface_desc.dwWidth = 512;
2270 surface_desc.dwHeight = 512;
2271 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, (IDirectDrawSurface4 **)0xdeadbeef, NULL);
2272 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
2273 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2274 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2276 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface4, tests, ARRAY_SIZE(tests));
2278 IDirectDrawSurface4_Release(surface);
2279 IDirectDraw4_Release(ddraw);
2280 DestroyWindow(window);
2283 static void test_device_qi(void)
2285 static const struct qi_test tests[] =
2287 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
2288 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
2289 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
2290 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2291 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
2292 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
2293 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
2294 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
2295 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
2296 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
2297 {&IID_IDirect3DDevice3, &IID_IDirect3DDevice3, S_OK },
2298 {&IID_IDirect3DDevice2, &IID_IDirect3DDevice3, S_OK },
2299 {&IID_IDirect3DDevice, &IID_IDirect3DDevice3, S_OK },
2300 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2301 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2302 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2303 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2304 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2305 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2306 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2307 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2308 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2309 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2310 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2311 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2312 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2313 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2314 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2315 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2316 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2317 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2318 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2319 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2320 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2321 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2322 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2323 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2324 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2325 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2326 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2327 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2328 {&IID_IUnknown, &IID_IDirect3DDevice3, S_OK },
2331 IDirect3DDevice3 *device;
2332 HWND window;
2334 window = create_window();
2335 if (!(device = create_device(window, DDSCL_NORMAL)))
2337 skip("Failed to create a 3D device, skipping test.\n");
2338 DestroyWindow(window);
2339 return;
2342 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice3, tests, ARRAY_SIZE(tests));
2344 IDirect3DDevice3_Release(device);
2345 DestroyWindow(window);
2348 static void test_wndproc(void)
2350 LONG_PTR proc, ddraw_proc;
2351 IDirectDraw4 *ddraw;
2352 WNDCLASSA wc = {0};
2353 HWND window;
2354 HRESULT hr;
2355 ULONG ref;
2357 static struct message messages[] =
2359 {WM_WINDOWPOSCHANGING, FALSE, 0},
2360 {WM_MOVE, FALSE, 0},
2361 {WM_SIZE, FALSE, 0},
2362 {WM_WINDOWPOSCHANGING, FALSE, 0},
2363 {WM_ACTIVATE, FALSE, 0},
2364 {WM_SETFOCUS, FALSE, 0},
2365 {0, FALSE, 0},
2368 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2369 ddraw = create_ddraw();
2370 ok(!!ddraw, "Failed to create a ddraw object.\n");
2372 wc.lpfnWndProc = test_proc;
2373 wc.lpszClassName = "ddraw_test_wndproc_wc";
2374 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2376 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2377 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2379 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2380 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2381 (LONG_PTR)test_proc, proc);
2382 expect_messages = messages;
2383 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2384 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2385 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2386 expect_messages = NULL;
2387 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2388 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2389 (LONG_PTR)test_proc, proc);
2390 ref = IDirectDraw4_Release(ddraw);
2391 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2392 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2393 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2394 (LONG_PTR)test_proc, proc);
2396 /* DDSCL_NORMAL doesn't. */
2397 ddraw = create_ddraw();
2398 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2399 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2400 (LONG_PTR)test_proc, proc);
2401 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2402 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2403 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2404 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2405 (LONG_PTR)test_proc, proc);
2406 ref = IDirectDraw4_Release(ddraw);
2407 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2408 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2409 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2410 (LONG_PTR)test_proc, proc);
2412 /* The original window proc is only restored by ddraw if the current
2413 * window proc matches the one ddraw set. This also affects switching
2414 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2415 ddraw = create_ddraw();
2416 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2417 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2418 (LONG_PTR)test_proc, proc);
2419 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2420 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2421 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2422 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2423 (LONG_PTR)test_proc, proc);
2424 ddraw_proc = proc;
2425 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2426 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2427 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2428 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2429 (LONG_PTR)test_proc, proc);
2430 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2431 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2432 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2433 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2434 (LONG_PTR)test_proc, proc);
2435 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2436 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2437 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2438 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2439 (LONG_PTR)DefWindowProcA, proc);
2440 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2441 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2442 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
2443 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2444 (LONG_PTR)DefWindowProcA, proc);
2445 ref = IDirectDraw4_Release(ddraw);
2446 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2447 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2448 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2449 (LONG_PTR)test_proc, proc);
2451 ddraw = create_ddraw();
2452 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2453 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2454 (LONG_PTR)test_proc, proc);
2455 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2456 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2457 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2458 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2459 (LONG_PTR)test_proc, proc);
2460 ref = IDirectDraw4_Release(ddraw);
2461 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2462 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2463 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2464 (LONG_PTR)DefWindowProcA, proc);
2466 fix_wndproc(window, (LONG_PTR)test_proc);
2467 expect_messages = NULL;
2468 DestroyWindow(window);
2469 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2472 static void test_window_style(void)
2474 LONG style, exstyle, tmp, expected_style;
2475 RECT fullscreen_rect, r;
2476 IDirectDraw4 *ddraw;
2477 HWND window;
2478 HRESULT hr;
2479 ULONG ref;
2480 BOOL ret;
2482 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2483 0, 0, 100, 100, 0, 0, 0, 0);
2484 ddraw = create_ddraw();
2485 ok(!!ddraw, "Failed to create a ddraw object.\n");
2487 style = GetWindowLongA(window, GWL_STYLE);
2488 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2489 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2491 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2492 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2494 tmp = GetWindowLongA(window, GWL_STYLE);
2495 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2496 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2497 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2499 GetWindowRect(window, &r);
2500 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2501 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2502 GetClientRect(window, &r);
2503 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2505 ret = SetForegroundWindow(GetDesktopWindow());
2506 ok(ret, "Failed to set foreground window.\n");
2508 tmp = GetWindowLongA(window, GWL_STYLE);
2509 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2510 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2511 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2513 ret = SetForegroundWindow(window);
2514 ok(ret, "Failed to set foreground window.\n");
2515 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2516 * the next tests expect this. */
2517 ShowWindow(window, SW_HIDE);
2519 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2520 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2522 tmp = GetWindowLongA(window, GWL_STYLE);
2523 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2524 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2525 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2527 ShowWindow(window, SW_SHOW);
2528 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2529 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2531 tmp = GetWindowLongA(window, GWL_STYLE);
2532 expected_style = style | WS_VISIBLE;
2533 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2534 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2535 expected_style = exstyle | WS_EX_TOPMOST;
2536 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2538 ret = SetForegroundWindow(GetDesktopWindow());
2539 ok(ret, "Failed to set foreground window.\n");
2540 tmp = GetWindowLongA(window, GWL_STYLE);
2541 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
2542 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2543 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2544 expected_style = exstyle | WS_EX_TOPMOST;
2545 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2547 ref = IDirectDraw4_Release(ddraw);
2548 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2550 DestroyWindow(window);
2553 static void test_redundant_mode_set(void)
2555 DDSURFACEDESC2 surface_desc = {0};
2556 IDirectDraw4 *ddraw;
2557 RECT q, r, s;
2558 HWND window;
2559 HRESULT hr;
2560 ULONG ref;
2562 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2563 0, 0, 100, 100, 0, 0, 0, 0);
2564 ddraw = create_ddraw();
2565 ok(!!ddraw, "Failed to create a ddraw object.\n");
2567 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2568 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2570 surface_desc.dwSize = sizeof(surface_desc);
2571 hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc);
2572 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
2574 hr = IDirectDraw4_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2575 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2576 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2578 GetWindowRect(window, &q);
2579 r = q;
2580 r.right /= 2;
2581 r.bottom /= 2;
2582 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2583 GetWindowRect(window, &s);
2584 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2586 hr = IDirectDraw4_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2587 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2588 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2590 GetWindowRect(window, &s);
2591 ok(EqualRect(&r, &s) || broken(EqualRect(&q, &s) /* Windows 10 */),
2592 "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2594 ref = IDirectDraw4_Release(ddraw);
2595 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2597 DestroyWindow(window);
2600 static SIZE screen_size, screen_size2;
2602 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2604 if (message == WM_SIZE)
2606 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2607 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2610 return test_proc(hwnd, message, wparam, lparam);
2613 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2615 if (message == WM_SIZE)
2617 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
2618 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
2621 return test_proc(hwnd, message, wparam, lparam);
2624 struct test_coop_level_mode_set_enum_param
2626 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
2629 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC2 *surface_desc, void *context)
2631 struct test_coop_level_mode_set_enum_param *param = context;
2633 if (U1(U4(*surface_desc).ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
2634 return DDENUMRET_OK;
2635 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
2636 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
2637 return DDENUMRET_OK;
2639 if (!param->ddraw_width)
2641 param->ddraw_width = surface_desc->dwWidth;
2642 param->ddraw_height = surface_desc->dwHeight;
2643 return DDENUMRET_OK;
2645 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
2646 return DDENUMRET_OK;
2648 param->user32_width = surface_desc->dwWidth;
2649 param->user32_height = surface_desc->dwHeight;
2650 return DDENUMRET_CANCEL;
2653 static void test_coop_level_mode_set(void)
2655 IDirectDrawSurface4 *primary;
2656 RECT registry_rect, ddraw_rect, user32_rect, r;
2657 IDirectDraw4 *ddraw;
2658 DDSURFACEDESC2 ddsd;
2659 WNDCLASSA wc = {0};
2660 HWND window, window2;
2661 HRESULT hr;
2662 ULONG ref;
2663 MSG msg;
2664 struct test_coop_level_mode_set_enum_param param;
2665 DEVMODEW devmode;
2666 BOOL ret;
2667 LONG change_ret;
2669 static const struct message exclusive_messages[] =
2671 {WM_WINDOWPOSCHANGING, FALSE, 0},
2672 {WM_WINDOWPOSCHANGED, FALSE, 0},
2673 {WM_SIZE, FALSE, 0},
2674 {WM_DISPLAYCHANGE, FALSE, 0},
2675 {0, FALSE, 0},
2677 static const struct message exclusive_focus_loss_messages[] =
2679 {WM_ACTIVATE, TRUE, WA_INACTIVE},
2680 {WM_DISPLAYCHANGE, FALSE, 0},
2681 {WM_WINDOWPOSCHANGING, FALSE, 0},
2682 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
2683 * SW_MINIMIZED, causing a recursive window activation that does not
2684 * produce the same result in Wine yet. Ignore the difference for now.
2685 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
2686 {WM_WINDOWPOSCHANGED, FALSE, 0},
2687 {WM_MOVE, FALSE, 0},
2688 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2689 {WM_ACTIVATEAPP, TRUE, FALSE},
2690 {0, FALSE, 0},
2692 static const struct message exclusive_focus_restore_messages[] =
2694 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
2695 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
2696 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
2697 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
2698 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
2699 /* Native redundantly sets the window size here. */
2700 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
2701 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
2702 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
2703 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
2704 {0, FALSE, 0},
2706 static const struct message sc_restore_messages[] =
2708 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
2709 {WM_WINDOWPOSCHANGING, FALSE, 0},
2710 {WM_WINDOWPOSCHANGED, FALSE, 0},
2711 {WM_SIZE, TRUE, SIZE_RESTORED},
2712 {0, FALSE, 0},
2714 static const struct message sc_minimize_messages[] =
2716 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
2717 {WM_WINDOWPOSCHANGING, FALSE, 0},
2718 {WM_WINDOWPOSCHANGED, FALSE, 0},
2719 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2720 {0, FALSE, 0},
2722 static const struct message sc_maximize_messages[] =
2724 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
2725 {WM_WINDOWPOSCHANGING, FALSE, 0},
2726 {WM_WINDOWPOSCHANGED, FALSE, 0},
2727 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
2728 {0, FALSE, 0},
2731 static const struct message normal_messages[] =
2733 {WM_DISPLAYCHANGE, FALSE, 0},
2734 {0, FALSE, 0},
2737 ddraw = create_ddraw();
2738 ok(!!ddraw, "Failed to create a ddraw object.\n");
2740 memset(&param, 0, sizeof(param));
2741 hr = IDirectDraw4_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
2742 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2743 ref = IDirectDraw4_Release(ddraw);
2744 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2746 if (!param.user32_height)
2748 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
2749 return;
2752 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2753 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
2754 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
2756 memset(&devmode, 0, sizeof(devmode));
2757 devmode.dmSize = sizeof(devmode);
2758 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2759 devmode.dmPelsWidth = param.user32_width;
2760 devmode.dmPelsHeight = param.user32_height;
2761 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2762 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2764 ddraw = create_ddraw();
2765 ok(!!ddraw, "Failed to create a ddraw object.\n");
2767 wc.lpfnWndProc = mode_set_proc;
2768 wc.lpszClassName = "ddraw_test_wndproc_wc";
2769 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2770 wc.lpfnWndProc = mode_set_proc2;
2771 wc.lpszClassName = "ddraw_test_wndproc_wc2";
2772 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2774 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2775 0, 0, 100, 100, 0, 0, 0, 0);
2776 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
2777 0, 0, 100, 100, 0, 0, 0, 0);
2779 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2780 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2782 GetWindowRect(window, &r);
2783 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2784 wine_dbgstr_rect(&r));
2786 memset(&ddsd, 0, sizeof(ddsd));
2787 ddsd.dwSize = sizeof(ddsd);
2788 ddsd.dwFlags = DDSD_CAPS;
2789 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2791 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2792 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2793 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2794 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2795 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2796 param.user32_width, ddsd.dwWidth);
2797 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2798 param.user32_height, ddsd.dwHeight);
2800 GetWindowRect(window, &r);
2801 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2802 wine_dbgstr_rect(&r));
2804 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2805 expect_messages = exclusive_messages;
2806 screen_size.cx = 0;
2807 screen_size.cy = 0;
2809 hr = IDirectDrawSurface4_IsLost(primary);
2810 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2811 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2812 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2813 hr = IDirectDrawSurface4_IsLost(primary);
2814 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2816 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2817 expect_messages = NULL;
2818 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
2819 "Expected screen size %ux%u, got %ux%u.\n",
2820 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
2822 GetWindowRect(window, &r);
2823 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2824 wine_dbgstr_rect(&r));
2826 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2827 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2828 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2829 param.user32_width, ddsd.dwWidth);
2830 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2831 param.user32_height, ddsd.dwHeight);
2832 IDirectDrawSurface4_Release(primary);
2834 memset(&ddsd, 0, sizeof(ddsd));
2835 ddsd.dwSize = sizeof(ddsd);
2836 ddsd.dwFlags = DDSD_CAPS;
2837 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2839 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2840 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2841 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2842 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2843 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2844 param.ddraw_width, ddsd.dwWidth);
2845 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2846 param.ddraw_height, ddsd.dwHeight);
2848 GetWindowRect(window, &r);
2849 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2850 wine_dbgstr_rect(&r));
2852 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2853 expect_messages = exclusive_messages;
2854 screen_size.cx = 0;
2855 screen_size.cy = 0;
2857 hr = IDirectDrawSurface4_IsLost(primary);
2858 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2859 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2860 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2861 hr = IDirectDrawSurface4_IsLost(primary);
2862 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2864 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2865 expect_messages = NULL;
2866 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
2867 "Expected screen size %ux%u, got %ux%u.\n",
2868 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
2870 GetWindowRect(window, &r);
2871 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2872 wine_dbgstr_rect(&r));
2874 expect_messages = exclusive_focus_loss_messages;
2875 ret = SetForegroundWindow(GetDesktopWindow());
2876 ok(ret, "Failed to set foreground window.\n");
2877 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2878 memset(&devmode, 0, sizeof(devmode));
2879 devmode.dmSize = sizeof(devmode);
2880 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2881 ok(ret, "Failed to get display mode.\n");
2882 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2883 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
2884 devmode.dmPelsWidth, devmode.dmPelsHeight);
2886 expect_messages = exclusive_focus_restore_messages;
2887 ShowWindow(window, SW_RESTORE);
2888 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2890 GetWindowRect(window, &r);
2891 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2892 wine_dbgstr_rect(&r));
2893 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2894 ok(ret, "Failed to get display mode.\n");
2895 ok(devmode.dmPelsWidth == param.ddraw_width
2896 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpect screen size %ux%u.\n",
2897 devmode.dmPelsWidth, devmode.dmPelsHeight);
2899 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2900 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2901 /* Normally the primary should be restored here. Unfortunately this causes the
2902 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
2903 * testbot. Another Restore call would presumably avoid the crash, but it also moots
2904 * the point of the GetSurfaceDesc call. */
2906 expect_messages = sc_minimize_messages;
2907 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
2908 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2909 expect_messages = NULL;
2911 expect_messages = sc_restore_messages;
2912 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
2913 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2914 expect_messages = NULL;
2916 expect_messages = sc_maximize_messages;
2917 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
2918 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2919 expect_messages = NULL;
2921 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2922 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2924 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2925 expect_messages = exclusive_messages;
2926 screen_size.cx = 0;
2927 screen_size.cy = 0;
2929 hr = IDirectDrawSurface4_IsLost(primary);
2930 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2931 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
2932 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2933 hr = IDirectDrawSurface4_IsLost(primary);
2934 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2936 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2937 expect_messages = NULL;
2938 ok(screen_size.cx == registry_mode.dmPelsWidth
2939 && screen_size.cy == registry_mode.dmPelsHeight,
2940 "Expected screen size %ux%u, got %ux%u.\n",
2941 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
2943 GetWindowRect(window, &r);
2944 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2945 wine_dbgstr_rect(&r));
2947 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2948 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2949 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2950 param.ddraw_width, ddsd.dwWidth);
2951 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2952 param.ddraw_height, ddsd.dwHeight);
2953 IDirectDrawSurface4_Release(primary);
2955 /* For Wine. */
2956 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2957 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2959 memset(&ddsd, 0, sizeof(ddsd));
2960 ddsd.dwSize = sizeof(ddsd);
2961 ddsd.dwFlags = DDSD_CAPS;
2962 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2964 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2965 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2966 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2967 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2968 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2969 registry_mode.dmPelsWidth, ddsd.dwWidth);
2970 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2971 registry_mode.dmPelsHeight, ddsd.dwHeight);
2973 GetWindowRect(window, &r);
2974 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2975 wine_dbgstr_rect(&r));
2977 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2978 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2980 GetWindowRect(window, &r);
2981 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2982 wine_dbgstr_rect(&r));
2984 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2985 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2986 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2987 registry_mode.dmPelsWidth, ddsd.dwWidth);
2988 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2989 registry_mode.dmPelsHeight, ddsd.dwHeight);
2990 IDirectDrawSurface4_Release(primary);
2992 memset(&ddsd, 0, sizeof(ddsd));
2993 ddsd.dwSize = sizeof(ddsd);
2994 ddsd.dwFlags = DDSD_CAPS;
2995 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2997 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2998 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2999 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3000 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3001 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3002 registry_mode.dmPelsWidth, ddsd.dwWidth);
3003 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3004 registry_mode.dmPelsHeight, ddsd.dwHeight);
3006 GetWindowRect(window, &r);
3007 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3008 wine_dbgstr_rect(&r));
3010 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3011 expect_messages = normal_messages;
3012 screen_size.cx = 0;
3013 screen_size.cy = 0;
3015 hr = IDirectDrawSurface4_IsLost(primary);
3016 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3017 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3018 devmode.dmPelsWidth = param.user32_width;
3019 devmode.dmPelsHeight = param.user32_height;
3020 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3021 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3022 hr = IDirectDrawSurface4_IsLost(primary);
3023 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3025 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3026 expect_messages = NULL;
3027 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3029 GetWindowRect(window, &r);
3030 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3031 wine_dbgstr_rect(&r));
3033 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3034 expect_messages = normal_messages;
3035 screen_size.cx = 0;
3036 screen_size.cy = 0;
3038 hr = IDirectDrawSurface4_Restore(primary);
3039 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3040 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3041 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3042 hr = IDirectDrawSurface4_Restore(primary);
3043 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3044 hr = IDirectDrawSurface4_IsLost(primary);
3045 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3047 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3048 expect_messages = NULL;
3049 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3051 GetWindowRect(window, &r);
3052 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3053 wine_dbgstr_rect(&r));
3055 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3056 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3057 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3058 registry_mode.dmPelsWidth, ddsd.dwWidth);
3059 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3060 registry_mode.dmPelsHeight, ddsd.dwHeight);
3061 IDirectDrawSurface4_Release(primary);
3063 memset(&ddsd, 0, sizeof(ddsd));
3064 ddsd.dwSize = sizeof(ddsd);
3065 ddsd.dwFlags = DDSD_CAPS;
3066 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3068 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3069 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3070 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3071 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3072 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3073 param.ddraw_width, ddsd.dwWidth);
3074 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3075 param.ddraw_height, ddsd.dwHeight);
3077 GetWindowRect(window, &r);
3078 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3079 wine_dbgstr_rect(&r));
3081 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3082 expect_messages = normal_messages;
3083 screen_size.cx = 0;
3084 screen_size.cy = 0;
3086 hr = IDirectDrawSurface4_IsLost(primary);
3087 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3088 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
3089 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3090 hr = IDirectDrawSurface4_IsLost(primary);
3091 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3093 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3094 expect_messages = NULL;
3095 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3097 GetWindowRect(window, &r);
3098 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3099 wine_dbgstr_rect(&r));
3101 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3102 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3103 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3104 param.ddraw_width, ddsd.dwWidth);
3105 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3106 param.ddraw_height, ddsd.dwHeight);
3107 IDirectDrawSurface4_Release(primary);
3109 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3110 ok(ret, "Failed to get display mode.\n");
3111 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3112 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3113 "Expected resolution %ux%u, got %ux%u.\n",
3114 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3115 devmode.dmPelsWidth, devmode.dmPelsHeight);
3116 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3117 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3119 memset(&ddsd, 0, sizeof(ddsd));
3120 ddsd.dwSize = sizeof(ddsd);
3121 ddsd.dwFlags = DDSD_CAPS;
3122 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3124 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3125 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3126 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3127 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3128 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3129 registry_mode.dmPelsWidth, ddsd.dwWidth);
3130 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3131 registry_mode.dmPelsHeight, ddsd.dwHeight);
3133 GetWindowRect(window, &r);
3134 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3135 wine_dbgstr_rect(&r));
3137 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
3138 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
3139 * not DDSCL_FULLSCREEN. */
3140 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3141 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3143 GetWindowRect(window, &r);
3144 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3145 wine_dbgstr_rect(&r));
3147 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3148 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3149 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3150 registry_mode.dmPelsWidth, ddsd.dwWidth);
3151 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3152 registry_mode.dmPelsHeight, ddsd.dwHeight);
3153 IDirectDrawSurface4_Release(primary);
3155 memset(&ddsd, 0, sizeof(ddsd));
3156 ddsd.dwSize = sizeof(ddsd);
3157 ddsd.dwFlags = DDSD_CAPS;
3158 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3160 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3161 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3162 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3163 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3164 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3165 registry_mode.dmPelsWidth, ddsd.dwWidth);
3166 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3167 registry_mode.dmPelsHeight, ddsd.dwHeight);
3169 GetWindowRect(window, &r);
3170 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3171 wine_dbgstr_rect(&r));
3173 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3174 expect_messages = normal_messages;
3175 screen_size.cx = 0;
3176 screen_size.cy = 0;
3178 hr = IDirectDrawSurface4_IsLost(primary);
3179 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3180 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3181 devmode.dmPelsWidth = param.user32_width;
3182 devmode.dmPelsHeight = param.user32_height;
3183 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3184 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3185 hr = IDirectDrawSurface4_IsLost(primary);
3186 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3188 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3189 expect_messages = NULL;
3190 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3192 GetWindowRect(window, &r);
3193 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3194 wine_dbgstr_rect(&r));
3196 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3197 expect_messages = normal_messages;
3198 screen_size.cx = 0;
3199 screen_size.cy = 0;
3201 hr = IDirectDrawSurface4_Restore(primary);
3202 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3203 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3204 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3205 hr = IDirectDrawSurface4_Restore(primary);
3206 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3207 hr = IDirectDrawSurface4_IsLost(primary);
3208 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3210 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3211 expect_messages = NULL;
3212 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3214 GetWindowRect(window, &r);
3215 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3216 wine_dbgstr_rect(&r));
3218 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3219 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3220 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3221 registry_mode.dmPelsWidth, ddsd.dwWidth);
3222 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3223 registry_mode.dmPelsHeight, ddsd.dwHeight);
3224 IDirectDrawSurface4_Release(primary);
3226 memset(&ddsd, 0, sizeof(ddsd));
3227 ddsd.dwSize = sizeof(ddsd);
3228 ddsd.dwFlags = DDSD_CAPS;
3229 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3231 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3232 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3233 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3234 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3235 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3236 param.ddraw_width, ddsd.dwWidth);
3237 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3238 param.ddraw_height, ddsd.dwHeight);
3240 GetWindowRect(window, &r);
3241 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3242 wine_dbgstr_rect(&r));
3244 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3245 expect_messages = normal_messages;
3246 screen_size.cx = 0;
3247 screen_size.cy = 0;
3249 hr = IDirectDrawSurface4_IsLost(primary);
3250 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3251 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
3252 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3253 hr = IDirectDrawSurface4_IsLost(primary);
3254 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3256 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3257 expect_messages = NULL;
3258 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3260 GetWindowRect(window, &r);
3261 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3262 wine_dbgstr_rect(&r));
3264 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3265 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3266 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3267 param.ddraw_width, ddsd.dwWidth);
3268 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3269 param.ddraw_height, ddsd.dwHeight);
3270 IDirectDrawSurface4_Release(primary);
3272 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3273 ok(ret, "Failed to get display mode.\n");
3274 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3275 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3276 "Expected resolution %ux%u, got %ux%u.\n",
3277 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3278 devmode.dmPelsWidth, devmode.dmPelsHeight);
3279 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3280 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3282 memset(&ddsd, 0, sizeof(ddsd));
3283 ddsd.dwSize = sizeof(ddsd);
3284 ddsd.dwFlags = DDSD_CAPS;
3285 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3287 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3288 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3289 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3290 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3291 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3292 registry_mode.dmPelsWidth, ddsd.dwWidth);
3293 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3294 registry_mode.dmPelsHeight, ddsd.dwHeight);
3295 IDirectDrawSurface4_Release(primary);
3297 GetWindowRect(window, &r);
3298 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3299 wine_dbgstr_rect(&r));
3301 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
3302 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3303 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3304 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3305 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3307 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3308 expect_messages = exclusive_messages;
3309 screen_size.cx = 0;
3310 screen_size.cy = 0;
3312 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3313 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3315 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3316 expect_messages = NULL;
3317 ok(screen_size.cx == registry_mode.dmPelsWidth
3318 && screen_size.cy == registry_mode.dmPelsHeight,
3319 "Expected screen size %ux%u, got %ux%u.\n",
3320 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3321 screen_size.cx, screen_size.cy);
3323 GetWindowRect(window, &r);
3324 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3325 wine_dbgstr_rect(&r));
3327 memset(&ddsd, 0, sizeof(ddsd));
3328 ddsd.dwSize = sizeof(ddsd);
3329 ddsd.dwFlags = DDSD_CAPS;
3330 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3332 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3333 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3334 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3335 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3336 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3337 registry_mode.dmPelsWidth, ddsd.dwWidth);
3338 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3339 registry_mode.dmPelsHeight, ddsd.dwHeight);
3340 IDirectDrawSurface4_Release(primary);
3342 /* The screen restore is a property of DDSCL_EXCLUSIVE */
3343 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3344 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3345 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3346 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3348 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3349 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3351 memset(&ddsd, 0, sizeof(ddsd));
3352 ddsd.dwSize = sizeof(ddsd);
3353 ddsd.dwFlags = DDSD_CAPS;
3354 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3356 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3357 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3358 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3359 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3360 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3361 param.ddraw_width, ddsd.dwWidth);
3362 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3363 param.ddraw_height, ddsd.dwHeight);
3364 IDirectDrawSurface4_Release(primary);
3366 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
3367 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3369 /* If the window is changed at the same time, messages are sent to the new window. */
3370 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3371 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3372 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3373 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3375 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3376 expect_messages = exclusive_messages;
3377 screen_size.cx = 0;
3378 screen_size.cy = 0;
3379 screen_size2.cx = 0;
3380 screen_size2.cy = 0;
3382 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3383 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3385 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3386 expect_messages = NULL;
3387 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n",
3388 screen_size.cx, screen_size.cy);
3389 ok(screen_size2.cx == registry_mode.dmPelsWidth && screen_size2.cy == registry_mode.dmPelsHeight,
3390 "Expected screen size 2 %ux%u, got %ux%u.\n",
3391 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size2.cx, screen_size2.cy);
3393 GetWindowRect(window, &r);
3394 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3395 wine_dbgstr_rect(&r));
3396 GetWindowRect(window2, &r);
3397 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3398 wine_dbgstr_rect(&r));
3400 memset(&ddsd, 0, sizeof(ddsd));
3401 ddsd.dwSize = sizeof(ddsd);
3402 ddsd.dwFlags = DDSD_CAPS;
3403 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3405 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3406 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3407 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3408 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3409 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3410 registry_mode.dmPelsWidth, ddsd.dwWidth);
3411 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3412 registry_mode.dmPelsHeight, ddsd.dwHeight);
3413 IDirectDrawSurface4_Release(primary);
3415 ref = IDirectDraw4_Release(ddraw);
3416 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3418 GetWindowRect(window, &r);
3419 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3420 wine_dbgstr_rect(&r));
3422 expect_messages = NULL;
3423 DestroyWindow(window);
3424 DestroyWindow(window2);
3425 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3426 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
3429 static void test_coop_level_mode_set_multi(void)
3431 IDirectDraw4 *ddraw1, *ddraw2;
3432 UINT w, h;
3433 HWND window;
3434 HRESULT hr;
3435 ULONG ref;
3437 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3438 0, 0, 100, 100, 0, 0, 0, 0);
3439 ddraw1 = create_ddraw();
3440 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3442 /* With just a single ddraw object, the display mode is restored on
3443 * release. */
3444 hr = set_display_mode(ddraw1, 800, 600);
3445 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3446 w = GetSystemMetrics(SM_CXSCREEN);
3447 ok(w == 800, "Got unexpected screen width %u.\n", w);
3448 h = GetSystemMetrics(SM_CYSCREEN);
3449 ok(h == 600, "Got unexpected screen height %u.\n", h);
3451 ref = IDirectDraw4_Release(ddraw1);
3452 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3453 w = GetSystemMetrics(SM_CXSCREEN);
3454 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3455 h = GetSystemMetrics(SM_CYSCREEN);
3456 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3458 /* When there are multiple ddraw objects, the display mode is restored to
3459 * the initial mode, before the first SetDisplayMode() call. */
3460 ddraw1 = create_ddraw();
3461 hr = set_display_mode(ddraw1, 800, 600);
3462 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3463 w = GetSystemMetrics(SM_CXSCREEN);
3464 ok(w == 800, "Got unexpected screen width %u.\n", w);
3465 h = GetSystemMetrics(SM_CYSCREEN);
3466 ok(h == 600, "Got unexpected screen height %u.\n", h);
3468 ddraw2 = create_ddraw();
3469 hr = set_display_mode(ddraw2, 640, 480);
3470 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3471 w = GetSystemMetrics(SM_CXSCREEN);
3472 ok(w == 640, "Got unexpected screen width %u.\n", w);
3473 h = GetSystemMetrics(SM_CYSCREEN);
3474 ok(h == 480, "Got unexpected screen height %u.\n", h);
3476 ref = IDirectDraw4_Release(ddraw2);
3477 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3478 w = GetSystemMetrics(SM_CXSCREEN);
3479 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3480 h = GetSystemMetrics(SM_CYSCREEN);
3481 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3483 ref = IDirectDraw4_Release(ddraw1);
3484 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3485 w = GetSystemMetrics(SM_CXSCREEN);
3486 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3487 h = GetSystemMetrics(SM_CYSCREEN);
3488 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3490 /* Regardless of release ordering. */
3491 ddraw1 = create_ddraw();
3492 hr = set_display_mode(ddraw1, 800, 600);
3493 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3494 w = GetSystemMetrics(SM_CXSCREEN);
3495 ok(w == 800, "Got unexpected screen width %u.\n", w);
3496 h = GetSystemMetrics(SM_CYSCREEN);
3497 ok(h == 600, "Got unexpected screen height %u.\n", h);
3499 ddraw2 = create_ddraw();
3500 hr = set_display_mode(ddraw2, 640, 480);
3501 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3502 w = GetSystemMetrics(SM_CXSCREEN);
3503 ok(w == 640, "Got unexpected screen width %u.\n", w);
3504 h = GetSystemMetrics(SM_CYSCREEN);
3505 ok(h == 480, "Got unexpected screen height %u.\n", h);
3507 ref = IDirectDraw4_Release(ddraw1);
3508 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3509 w = GetSystemMetrics(SM_CXSCREEN);
3510 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3511 h = GetSystemMetrics(SM_CYSCREEN);
3512 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3514 ref = IDirectDraw4_Release(ddraw2);
3515 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3516 w = GetSystemMetrics(SM_CXSCREEN);
3517 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3518 h = GetSystemMetrics(SM_CYSCREEN);
3519 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3521 /* But only for ddraw objects that called SetDisplayMode(). */
3522 ddraw1 = create_ddraw();
3523 ddraw2 = create_ddraw();
3524 hr = set_display_mode(ddraw2, 640, 480);
3525 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3526 w = GetSystemMetrics(SM_CXSCREEN);
3527 ok(w == 640, "Got unexpected screen width %u.\n", w);
3528 h = GetSystemMetrics(SM_CYSCREEN);
3529 ok(h == 480, "Got unexpected screen height %u.\n", h);
3531 ref = IDirectDraw4_Release(ddraw1);
3532 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3533 w = GetSystemMetrics(SM_CXSCREEN);
3534 ok(w == 640, "Got unexpected screen width %u.\n", w);
3535 h = GetSystemMetrics(SM_CYSCREEN);
3536 ok(h == 480, "Got unexpected screen height %u.\n", h);
3538 ref = IDirectDraw4_Release(ddraw2);
3539 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3540 w = GetSystemMetrics(SM_CXSCREEN);
3541 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3542 h = GetSystemMetrics(SM_CYSCREEN);
3543 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3545 /* If there's a ddraw object that's currently in exclusive mode, it blocks
3546 * restoring the display mode. */
3547 ddraw1 = create_ddraw();
3548 hr = set_display_mode(ddraw1, 800, 600);
3549 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3550 w = GetSystemMetrics(SM_CXSCREEN);
3551 ok(w == 800, "Got unexpected screen width %u.\n", w);
3552 h = GetSystemMetrics(SM_CYSCREEN);
3553 ok(h == 600, "Got unexpected screen height %u.\n", h);
3555 ddraw2 = create_ddraw();
3556 hr = set_display_mode(ddraw2, 640, 480);
3557 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3558 w = GetSystemMetrics(SM_CXSCREEN);
3559 ok(w == 640, "Got unexpected screen width %u.\n", w);
3560 h = GetSystemMetrics(SM_CYSCREEN);
3561 ok(h == 480, "Got unexpected screen height %u.\n", h);
3563 hr = IDirectDraw4_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3564 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3566 ref = IDirectDraw4_Release(ddraw1);
3567 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3568 w = GetSystemMetrics(SM_CXSCREEN);
3569 ok(w == 640, "Got unexpected screen width %u.\n", w);
3570 h = GetSystemMetrics(SM_CYSCREEN);
3571 ok(h == 480, "Got unexpected screen height %u.\n", h);
3573 ref = IDirectDraw4_Release(ddraw2);
3574 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3575 w = GetSystemMetrics(SM_CXSCREEN);
3576 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3577 h = GetSystemMetrics(SM_CYSCREEN);
3578 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3580 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3581 ddraw1 = create_ddraw();
3582 hr = set_display_mode(ddraw1, 800, 600);
3583 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3584 w = GetSystemMetrics(SM_CXSCREEN);
3585 ok(w == 800, "Got unexpected screen width %u.\n", w);
3586 h = GetSystemMetrics(SM_CYSCREEN);
3587 ok(h == 600, "Got unexpected screen height %u.\n", h);
3589 hr = IDirectDraw4_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3590 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3592 ddraw2 = create_ddraw();
3593 hr = set_display_mode(ddraw2, 640, 480);
3594 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3596 ref = IDirectDraw4_Release(ddraw1);
3597 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3598 w = GetSystemMetrics(SM_CXSCREEN);
3599 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3600 h = GetSystemMetrics(SM_CYSCREEN);
3601 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3603 ref = IDirectDraw4_Release(ddraw2);
3604 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3605 w = GetSystemMetrics(SM_CXSCREEN);
3606 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3607 h = GetSystemMetrics(SM_CYSCREEN);
3608 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3610 DestroyWindow(window);
3613 static void test_initialize(void)
3615 IDirectDraw4 *ddraw;
3616 HRESULT hr;
3618 ddraw = create_ddraw();
3619 ok(!!ddraw, "Failed to create a ddraw object.\n");
3621 hr = IDirectDraw4_Initialize(ddraw, NULL);
3622 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
3623 IDirectDraw4_Release(ddraw);
3625 CoInitialize(NULL);
3626 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw4, (void **)&ddraw);
3627 ok(SUCCEEDED(hr), "Failed to create IDirectDraw4 instance, hr %#x.\n", hr);
3628 hr = IDirectDraw4_Initialize(ddraw, NULL);
3629 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
3630 hr = IDirectDraw4_Initialize(ddraw, NULL);
3631 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
3632 IDirectDraw4_Release(ddraw);
3633 CoUninitialize();
3636 static void test_coop_level_surf_create(void)
3638 IDirectDrawSurface4 *surface;
3639 IDirectDraw4 *ddraw;
3640 DDSURFACEDESC2 ddsd;
3641 HRESULT hr;
3643 ddraw = create_ddraw();
3644 ok(!!ddraw, "Failed to create a ddraw object.\n");
3646 memset(&ddsd, 0, sizeof(ddsd));
3647 ddsd.dwSize = sizeof(ddsd);
3648 ddsd.dwFlags = DDSD_CAPS;
3649 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3650 surface = (void *)0xdeadbeef;
3651 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
3652 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3653 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3655 surface = (void *)0xdeadbeef;
3656 hr = IDirectDraw4_CreateSurface(ddraw, NULL, &surface, NULL);
3657 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3658 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3660 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3661 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3663 surface = (void *)0xdeadbeef;
3664 hr = IDirectDraw4_CreateSurface(ddraw, NULL, &surface, NULL);
3665 ok(hr == DDERR_INVALIDPARAMS, "Unexpected hr %#x.\n", hr);
3666 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3668 IDirectDraw4_Release(ddraw);
3671 static void test_vb_discard(void)
3673 static const struct vec4 quad[] =
3675 { 0.0f, 480.0f, 0.0f, 1.0f},
3676 { 0.0f, 0.0f, 0.0f, 1.0f},
3677 {640.0f, 480.0f, 0.0f, 1.0f},
3678 {640.0f, 0.0f, 0.0f, 1.0f},
3681 IDirect3DDevice3 *device;
3682 IDirect3D3 *d3d;
3683 IDirect3DVertexBuffer *buffer;
3684 HWND window;
3685 HRESULT hr;
3686 D3DVERTEXBUFFERDESC desc;
3687 BYTE *data;
3688 static const unsigned int vbsize = 16;
3689 unsigned int i;
3691 window = create_window();
3692 if (!(device = create_device(window, DDSCL_NORMAL)))
3694 skip("Failed to create a 3D device, skipping test.\n");
3695 DestroyWindow(window);
3696 return;
3699 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
3700 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
3702 memset(&desc, 0, sizeof(desc));
3703 desc.dwSize = sizeof(desc);
3704 desc.dwCaps = D3DVBCAPS_WRITEONLY;
3705 desc.dwFVF = D3DFVF_XYZRHW;
3706 desc.dwNumVertices = vbsize;
3707 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &buffer, 0, NULL);
3708 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3710 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3711 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3712 memcpy(data, quad, sizeof(quad));
3713 hr = IDirect3DVertexBuffer_Unlock(buffer);
3714 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3716 hr = IDirect3DDevice3_BeginScene(device);
3717 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3718 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
3719 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3720 hr = IDirect3DDevice3_EndScene(device);
3721 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3723 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3724 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3725 memset(data, 0xaa, sizeof(struct vec4) * vbsize);
3726 hr = IDirect3DVertexBuffer_Unlock(buffer);
3727 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3729 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3730 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3731 for (i = 0; i < sizeof(struct vec4) * vbsize; i++)
3733 if (data[i] != 0xaa)
3735 ok(FALSE, "Vertex buffer data byte %u is 0x%02x, expected 0xaa\n", i, data[i]);
3736 break;
3739 hr = IDirect3DVertexBuffer_Unlock(buffer);
3740 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3742 IDirect3DVertexBuffer_Release(buffer);
3743 IDirect3D3_Release(d3d);
3744 IDirect3DDevice3_Release(device);
3745 DestroyWindow(window);
3748 static void test_coop_level_multi_window(void)
3750 HWND window1, window2;
3751 IDirectDraw4 *ddraw;
3752 HRESULT hr;
3754 window1 = create_window();
3755 window2 = create_window();
3756 ddraw = create_ddraw();
3757 ok(!!ddraw, "Failed to create a ddraw object.\n");
3759 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
3760 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3761 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3762 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3763 ok(IsWindow(window1), "Window 1 was destroyed.\n");
3764 ok(IsWindow(window2), "Window 2 was destroyed.\n");
3766 IDirectDraw4_Release(ddraw);
3767 DestroyWindow(window2);
3768 DestroyWindow(window1);
3771 static void test_draw_strided(void)
3773 static struct vec3 position[] =
3775 {-1.0, -1.0, 0.0},
3776 {-1.0, 1.0, 0.0},
3777 { 1.0, 1.0, 0.0},
3778 { 1.0, -1.0, 0.0},
3780 static DWORD diffuse[] =
3782 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
3784 static WORD indices[] =
3786 0, 1, 2, 2, 3, 0
3789 IDirectDrawSurface4 *rt;
3790 IDirect3DDevice3 *device;
3791 D3DCOLOR color;
3792 HWND window;
3793 HRESULT hr;
3794 D3DDRAWPRIMITIVESTRIDEDDATA strided;
3795 IDirect3DViewport3 *viewport;
3796 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3798 window = create_window();
3799 if (!(device = create_device(window, DDSCL_NORMAL)))
3801 skip("Failed to create a 3D device, skipping test.\n");
3802 DestroyWindow(window);
3803 return;
3806 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
3807 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3808 viewport = create_viewport(device, 0, 0, 640, 480);
3809 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
3810 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
3811 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
3812 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
3814 hr = IDirect3DDevice3_BeginScene(device);
3815 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3817 memset(&strided, 0x55, sizeof(strided));
3818 strided.position.lpvData = position;
3819 strided.position.dwStride = sizeof(*position);
3820 strided.diffuse.lpvData = diffuse;
3821 strided.diffuse.dwStride = sizeof(*diffuse);
3822 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE,
3823 &strided, 4, indices, 6, 0);
3824 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3826 hr = IDirect3DDevice3_EndScene(device);
3827 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3829 color = get_surface_color(rt, 320, 240);
3830 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3832 IDirect3DViewport3_Release(viewport);
3833 IDirectDrawSurface4_Release(rt);
3834 IDirect3DDevice3_Release(device);
3835 DestroyWindow(window);
3838 static void test_lighting(void)
3840 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3841 static D3DMATRIX mat =
3843 1.0f, 0.0f, 0.0f, 0.0f,
3844 0.0f, 1.0f, 0.0f, 0.0f,
3845 0.0f, 0.0f, 1.0f, 0.0f,
3846 0.0f, 0.0f, 0.0f, 1.0f,
3848 mat_singular =
3850 1.0f, 0.0f, 1.0f, 0.0f,
3851 0.0f, 1.0f, 0.0f, 0.0f,
3852 1.0f, 0.0f, 1.0f, 0.0f,
3853 0.0f, 0.0f, 0.5f, 1.0f,
3855 mat_transf =
3857 0.0f, 0.0f, 1.0f, 0.0f,
3858 0.0f, 1.0f, 0.0f, 0.0f,
3859 -1.0f, 0.0f, 0.0f, 0.0f,
3860 10.f, 10.0f, 10.0f, 1.0f,
3862 mat_nonaffine =
3864 1.0f, 0.0f, 0.0f, 0.0f,
3865 0.0f, 1.0f, 0.0f, 0.0f,
3866 0.0f, 0.0f, 1.0f, -1.0f,
3867 10.f, 10.0f, 10.0f, 0.0f,
3869 static struct
3871 struct vec3 position;
3872 DWORD diffuse;
3874 unlitquad[] =
3876 {{-1.0f, -1.0f, 0.1f}, 0xffff0000},
3877 {{-1.0f, 0.0f, 0.1f}, 0xffff0000},
3878 {{ 0.0f, 0.0f, 0.1f}, 0xffff0000},
3879 {{ 0.0f, -1.0f, 0.1f}, 0xffff0000},
3881 litquad[] =
3883 {{-1.0f, 0.0f, 0.1f}, 0xff00ff00},
3884 {{-1.0f, 1.0f, 0.1f}, 0xff00ff00},
3885 {{ 0.0f, 1.0f, 0.1f}, 0xff00ff00},
3886 {{ 0.0f, 0.0f, 0.1f}, 0xff00ff00},
3888 static struct
3890 struct vec3 position;
3891 struct vec3 normal;
3892 DWORD diffuse;
3894 unlitnquad[] =
3896 {{0.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3897 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3898 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3899 {{1.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3901 litnquad[] =
3903 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3904 {{0.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3905 {{1.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3906 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3908 nquad[] =
3910 {{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3911 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3912 {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3913 {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3915 rotatedquad[] =
3917 {{-10.0f, -11.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3918 {{-10.0f, -9.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3919 {{-10.0f, -9.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3920 {{-10.0f, -11.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3922 translatedquad[] =
3924 {{-11.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3925 {{-11.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3926 {{ -9.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3927 {{ -9.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3929 static WORD indices[] = {0, 1, 2, 2, 3, 0};
3930 static const struct
3932 D3DMATRIX *world_matrix;
3933 void *quad;
3934 DWORD expected;
3935 const char *message;
3937 tests[] =
3939 {&mat, nquad, 0x000000ff, "Lit quad with light"},
3940 {&mat_singular, nquad, 0x000000b4, "Lit quad with singular world matrix"},
3941 {&mat_transf, rotatedquad, 0x000000ff, "Lit quad with transformation matrix"},
3942 {&mat_nonaffine, translatedquad, 0x000000ff, "Lit quad with non-affine matrix"},
3945 HWND window;
3946 IDirect3D3 *d3d;
3947 IDirect3DDevice3 *device;
3948 IDirectDrawSurface4 *rt;
3949 IDirect3DViewport3 *viewport;
3950 IDirect3DMaterial3 *material;
3951 IDirect3DLight *light;
3952 D3DMATERIALHANDLE mat_handle;
3953 D3DLIGHT2 light_desc;
3954 HRESULT hr;
3955 DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
3956 DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
3957 D3DCOLOR color;
3958 ULONG refcount;
3959 unsigned int i;
3961 window = create_window();
3962 if (!(device = create_device(window, DDSCL_NORMAL)))
3964 skip("Failed to create a 3D device, skipping test.\n");
3965 DestroyWindow(window);
3966 return;
3969 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
3970 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
3972 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
3973 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3975 viewport = create_viewport(device, 0, 0, 640, 480);
3976 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
3977 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
3979 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
3980 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3982 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
3983 ok(SUCCEEDED(hr), "Failed to set world transformation, hr %#x.\n", hr);
3984 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
3985 ok(SUCCEEDED(hr), "Failed to set view transformation, hr %#x.\n", hr);
3986 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
3987 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
3988 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
3989 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
3990 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
3991 ok(SUCCEEDED(hr), "Failed to disable zbuffer, hr %#x.\n", hr);
3992 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
3993 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
3994 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
3995 ok(SUCCEEDED(hr), "Failed to disable stencil buffer, hr %#x.\n", hr);
3996 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
3997 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
3999 hr = IDirect3DDevice3_BeginScene(device);
4000 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4002 /* There is no D3DRENDERSTATE_LIGHTING on ddraw < 7. */
4003 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
4004 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
4005 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, unlitquad, 4,
4006 indices, 6, 0);
4007 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4009 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
4010 ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
4011 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, litquad, 4,
4012 indices, 6, 0);
4013 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4015 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
4016 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
4017 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, unlitnquad, 4,
4018 indices, 6, 0);
4019 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4021 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
4022 ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
4023 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, litnquad, 4,
4024 indices, 6, 0);
4025 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4027 hr = IDirect3DDevice3_EndScene(device);
4028 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4030 color = get_surface_color(rt, 160, 360);
4031 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x.\n", color);
4032 color = get_surface_color(rt, 160, 120);
4033 ok(color == 0x0000ff00, "Lit quad without normals has color 0x%08x.\n", color);
4034 color = get_surface_color(rt, 480, 360);
4035 ok(color == 0x000000ff, "Unlit quad with normals has color 0x%08x.\n", color);
4036 color = get_surface_color(rt, 480, 120);
4037 ok(color == 0x00ffff00, "Lit quad with normals has color 0x%08x.\n", color);
4039 material = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
4040 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
4041 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
4042 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
4043 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
4045 hr = IDirect3D3_CreateLight(d3d, &light, NULL);
4046 ok(SUCCEEDED(hr), "Failed to create a light object, hr %#x.\n", hr);
4047 memset(&light_desc, 0, sizeof(light_desc));
4048 light_desc.dwSize = sizeof(light_desc);
4049 light_desc.dltType = D3DLIGHT_DIRECTIONAL;
4050 U1(light_desc.dcvColor).r = 1.0f;
4051 U2(light_desc.dcvColor).g = 1.0f;
4052 U3(light_desc.dcvColor).b = 1.0f;
4053 U4(light_desc.dcvColor).a = 1.0f;
4054 U3(light_desc.dvDirection).z = 1.0f;
4055 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
4056 ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
4057 hr = IDirect3DViewport3_AddLight(viewport, light);
4058 ok(SUCCEEDED(hr), "Failed to add a light to the viewport, hr %#x.\n", hr);
4060 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
4061 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4063 hr = IDirect3DDevice3_BeginScene(device);
4064 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4066 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, nquad,
4067 4, indices, 6, 0);
4068 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4070 hr = IDirect3DDevice3_EndScene(device);
4071 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4073 color = get_surface_color(rt, 320, 240);
4074 ok(color == 0x00000000, "Lit quad with no light has color 0x%08x.\n", color);
4076 light_desc.dwFlags = D3DLIGHT_ACTIVE;
4077 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
4078 ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
4080 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4082 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
4083 ok(SUCCEEDED(hr), "Failed to set world transformation, hr %#x.\n", hr);
4085 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
4086 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4088 hr = IDirect3DDevice3_BeginScene(device);
4089 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4091 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, tests[i].quad,
4092 4, indices, 6, 0);
4093 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4095 hr = IDirect3DDevice3_EndScene(device);
4096 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4098 color = get_surface_color(rt, 320, 240);
4099 ok(color == tests[i].expected, "%s has color 0x%08x.\n", tests[i].message, color);
4102 hr = IDirect3DViewport3_DeleteLight(viewport, light);
4103 ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#x.\n", hr);
4104 IDirect3DLight_Release(light);
4105 destroy_material(material);
4106 IDirect3DViewport3_Release(viewport);
4107 IDirectDrawSurface4_Release(rt);
4108 refcount = IDirect3DDevice3_Release(device);
4109 ok(!refcount, "Device has %u references left.\n", refcount);
4110 IDirect3D3_Release(d3d);
4111 DestroyWindow(window);
4114 static void test_specular_lighting(void)
4116 static const unsigned int vertices_side = 5;
4117 const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
4118 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
4119 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
4120 static D3DMATRIX mat =
4122 1.0f, 0.0f, 0.0f, 0.0f,
4123 0.0f, 1.0f, 0.0f, 0.0f,
4124 0.0f, 0.0f, 1.0f, 0.0f,
4125 0.0f, 0.0f, 0.0f, 1.0f,
4127 static D3DLIGHT2 directional =
4129 sizeof(D3DLIGHT2),
4130 D3DLIGHT_DIRECTIONAL,
4131 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4132 {{0.0f}, {0.0f}, {0.0f}},
4133 {{0.0f}, {0.0f}, {1.0f}},
4135 point =
4137 sizeof(D3DLIGHT2),
4138 D3DLIGHT_POINT,
4139 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4140 {{0.0f}, {0.0f}, {0.0f}},
4141 {{0.0f}, {0.0f}, {0.0f}},
4142 100.0f,
4143 0.0f,
4144 0.0f, 0.0f, 1.0f,
4146 spot =
4148 sizeof(D3DLIGHT2),
4149 D3DLIGHT_SPOT,
4150 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4151 {{0.0f}, {0.0f}, {0.0f}},
4152 {{0.0f}, {0.0f}, {1.0f}},
4153 100.0f,
4154 1.0f,
4155 0.0f, 0.0f, 1.0f,
4156 M_PI / 12.0f, M_PI / 3.0f
4158 parallelpoint =
4160 sizeof(D3DLIGHT2),
4161 D3DLIGHT_PARALLELPOINT,
4162 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4163 {{0.5f}, {0.0f}, {-1.0f}},
4164 {{0.0f}, {0.0f}, {0.0f}},
4166 point_side =
4168 sizeof(D3DLIGHT2),
4169 D3DLIGHT_POINT,
4170 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4171 {{-1.1f}, {0.0f}, {1.1f}},
4172 {{0.0f}, {0.0f}, {0.0f}},
4173 100.0f,
4174 0.0f,
4175 1.0f, 0.0f, 0.0f,
4177 point_far =
4179 sizeof(D3DLIGHT2),
4180 D3DLIGHT_POINT,
4181 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4182 {{0.0f}, {0.0f}, {0.1f}},
4183 {{0.0f}, {0.0f}, {0.0f}},
4184 1.0f,
4185 0.0f,
4186 1.0f, 0.0f, 0.0f,
4188 static const struct expected_color
4190 unsigned int x, y;
4191 D3DCOLOR color;
4193 expected_directional[] =
4195 {160, 120, 0x003c3c3c},
4196 {320, 120, 0x00717171},
4197 {480, 120, 0x003c3c3c},
4198 {160, 240, 0x00717171},
4199 {320, 240, 0x00ffffff},
4200 {480, 240, 0x00717171},
4201 {160, 360, 0x003c3c3c},
4202 {320, 360, 0x00717171},
4203 {480, 360, 0x003c3c3c},
4205 expected_point[] =
4207 {160, 120, 0x00000000},
4208 {320, 120, 0x00090909},
4209 {480, 120, 0x00000000},
4210 {160, 240, 0x00090909},
4211 {320, 240, 0x00fafafa},
4212 {480, 240, 0x00090909},
4213 {160, 360, 0x00000000},
4214 {320, 360, 0x00090909},
4215 {480, 360, 0x00000000},
4217 expected_spot[] =
4219 {160, 120, 0x00000000},
4220 {320, 120, 0x00020202},
4221 {480, 120, 0x00000000},
4222 {160, 240, 0x00020202},
4223 {320, 240, 0x00fafafa},
4224 {480, 240, 0x00020202},
4225 {160, 360, 0x00000000},
4226 {320, 360, 0x00020202},
4227 {480, 360, 0x00000000},
4229 expected_parallelpoint[] =
4231 {160, 120, 0x00050505},
4232 {320, 120, 0x002c2c2c},
4233 {480, 120, 0x006e6e6e},
4234 {160, 240, 0x00090909},
4235 {320, 240, 0x00717171},
4236 {480, 240, 0x00ffffff},
4237 {160, 360, 0x00050505},
4238 {320, 360, 0x002c2c2c},
4239 {480, 360, 0x006e6e6e},
4241 expected_point_side[] =
4243 {160, 120, 0x00000000},
4244 {320, 120, 0x00000000},
4245 {480, 120, 0x00000000},
4246 {160, 240, 0x00000000},
4247 {320, 240, 0x00000000},
4248 {480, 240, 0x00000000},
4249 {160, 360, 0x00000000},
4250 {320, 360, 0x00000000},
4251 {480, 360, 0x00000000},
4253 expected_point_far[] =
4255 {160, 120, 0x00000000},
4256 {320, 120, 0x00000000},
4257 {480, 120, 0x00000000},
4258 {160, 240, 0x00000000},
4259 {320, 240, 0x00ffffff},
4260 {480, 240, 0x00000000},
4261 {160, 360, 0x00000000},
4262 {320, 360, 0x00000000},
4263 {480, 360, 0x00000000},
4265 static const struct
4267 D3DLIGHT2 *light;
4268 BOOL local_viewer;
4269 float specular_power;
4270 const struct expected_color *expected;
4271 unsigned int expected_count;
4273 tests[] =
4275 /* D3DRENDERSTATE_LOCALVIEWER does not exist in D3D < 7 (the behavior is
4276 * the one you get on newer D3D versions with it set as TRUE). */
4277 {&directional, FALSE, 30.0f, expected_directional, ARRAY_SIZE(expected_directional)},
4278 {&directional, TRUE, 30.0f, expected_directional, ARRAY_SIZE(expected_directional)},
4279 {&point, TRUE, 30.0f, expected_point, ARRAY_SIZE(expected_point)},
4280 {&spot, TRUE, 30.0f, expected_spot, ARRAY_SIZE(expected_spot)},
4281 {&parallelpoint, TRUE, 30.0f, expected_parallelpoint, ARRAY_SIZE(expected_parallelpoint)},
4282 {&point_side, TRUE, 0.0f, expected_point_side, ARRAY_SIZE(expected_point_side)},
4283 {&point_far, TRUE, 1.0f, expected_point_far, ARRAY_SIZE(expected_point_far)},
4285 IDirect3D3 *d3d;
4286 IDirect3DDevice3 *device;
4287 IDirectDrawSurface4 *rt;
4288 IDirect3DViewport3 *viewport;
4289 IDirect3DMaterial3 *material;
4290 IDirect3DLight *light;
4291 D3DMATERIALHANDLE mat_handle;
4292 D3DCOLOR color;
4293 ULONG refcount;
4294 HWND window;
4295 HRESULT hr;
4296 unsigned int i, j, x, y;
4297 struct
4299 struct vec3 position;
4300 struct vec3 normal;
4301 } *quad;
4302 WORD *indices;
4304 window = create_window();
4305 if (!(device = create_device(window, DDSCL_NORMAL)))
4307 skip("Failed to create a 3D device, skipping test.\n");
4308 DestroyWindow(window);
4309 return;
4312 quad = HeapAlloc(GetProcessHeap(), 0, vertices_side * vertices_side * sizeof(*quad));
4313 indices = HeapAlloc(GetProcessHeap(), 0, indices_count * sizeof(*indices));
4314 for (i = 0, y = 0; y < vertices_side; ++y)
4316 for (x = 0; x < vertices_side; ++x)
4318 quad[i].position.x = x * 2.0f / (vertices_side - 1) - 1.0f;
4319 quad[i].position.y = y * 2.0f / (vertices_side - 1) - 1.0f;
4320 quad[i].position.z = 1.0f;
4321 quad[i].normal.x = 0.0f;
4322 quad[i].normal.y = 0.0f;
4323 quad[i++].normal.z = -1.0f;
4326 for (i = 0, y = 0; y < (vertices_side - 1); ++y)
4328 for (x = 0; x < (vertices_side - 1); ++x)
4330 indices[i++] = y * vertices_side + x + 1;
4331 indices[i++] = y * vertices_side + x;
4332 indices[i++] = (y + 1) * vertices_side + x;
4333 indices[i++] = y * vertices_side + x + 1;
4334 indices[i++] = (y + 1) * vertices_side + x;
4335 indices[i++] = (y + 1) * vertices_side + x + 1;
4339 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
4340 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
4342 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
4343 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4345 viewport = create_viewport(device, 0, 0, 640, 480);
4346 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
4347 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
4349 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
4350 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
4351 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
4352 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
4353 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
4354 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
4355 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
4356 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
4357 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
4358 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
4359 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4360 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
4362 hr = IDirect3D3_CreateLight(d3d, &light, NULL);
4363 ok(SUCCEEDED(hr), "Failed to create a light object, hr %#x.\n", hr);
4364 hr = IDirect3DViewport3_AddLight(viewport, light);
4365 ok(SUCCEEDED(hr), "Failed to add a light to the viewport, hr %#x.\n", hr);
4367 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
4368 ok(SUCCEEDED(hr), "Failed to enable specular lighting, hr %#x.\n", hr);
4370 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4372 tests[i].light->dwFlags = D3DLIGHT_ACTIVE;
4373 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)tests[i].light);
4374 ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
4376 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LOCALVIEWER, tests[i].local_viewer);
4377 ok(SUCCEEDED(hr), "Failed to set local viewer state, hr %#x.\n", hr);
4379 material = create_specular_material(device, 1.0f, 1.0f, 1.0f, 1.0f, tests[i].specular_power);
4380 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
4381 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
4382 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
4383 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
4385 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
4386 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4388 hr = IDirect3DDevice3_BeginScene(device);
4389 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4391 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, quad,
4392 vertices_side * vertices_side, indices, indices_count, 0);
4393 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4395 hr = IDirect3DDevice3_EndScene(device);
4396 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4398 for (j = 0; j < tests[i].expected_count; ++j)
4400 color = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
4401 ok(compare_color(color, tests[i].expected[j].color, 1),
4402 "Expected color 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
4403 tests[i].expected[j].color, tests[i].expected[j].x,
4404 tests[i].expected[j].y, color, i);
4407 destroy_material(material);
4410 hr = IDirect3DViewport3_DeleteLight(viewport, light);
4411 ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#x.\n", hr);
4412 IDirect3DLight_Release(light);
4413 IDirect3DViewport3_Release(viewport);
4414 IDirectDrawSurface4_Release(rt);
4415 refcount = IDirect3DDevice3_Release(device);
4416 ok(!refcount, "Device has %u references left.\n", refcount);
4417 IDirect3D3_Release(d3d);
4418 DestroyWindow(window);
4419 HeapFree(GetProcessHeap(), 0, indices);
4420 HeapFree(GetProcessHeap(), 0, quad);
4423 static void test_clear_rect_count(void)
4425 IDirectDrawSurface4 *rt;
4426 IDirect3DDevice3 *device;
4427 D3DCOLOR color;
4428 HWND window;
4429 HRESULT hr;
4430 IDirect3DViewport3 *viewport;
4431 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
4433 window = create_window();
4434 if (!(device = create_device(window, DDSCL_NORMAL)))
4436 skip("Failed to create a 3D device, skipping test.\n");
4437 DestroyWindow(window);
4438 return;
4441 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
4442 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4444 viewport = create_viewport(device, 0, 0, 640, 480);
4445 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
4446 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
4447 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00ffffff, 0.0f, 0);
4448 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
4449 hr = IDirect3DViewport3_Clear2(viewport, 0, &clear_rect, D3DCLEAR_TARGET, 0x00ff0000, 0.0f, 0);
4450 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
4451 hr = IDirect3DViewport3_Clear2(viewport, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 0.0f, 0);
4452 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
4453 hr = IDirect3DViewport3_Clear2(viewport, 1, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
4454 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
4456 color = get_surface_color(rt, 320, 240);
4457 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x000000ff, 1)),
4458 "Got unexpected color 0x%08x.\n", color);
4460 IDirect3DViewport3_Release(viewport);
4461 IDirectDrawSurface4_Release(rt);
4462 IDirect3DDevice3_Release(device);
4463 DestroyWindow(window);
4466 static BOOL test_mode_restored(IDirectDraw4 *ddraw, HWND window)
4468 DDSURFACEDESC2 ddsd1, ddsd2;
4469 HRESULT hr;
4471 memset(&ddsd1, 0, sizeof(ddsd1));
4472 ddsd1.dwSize = sizeof(ddsd1);
4473 hr = IDirectDraw4_GetDisplayMode(ddraw, &ddsd1);
4474 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4476 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4477 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4478 hr = set_display_mode(ddraw, 640, 480);
4479 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
4480 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4481 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4483 memset(&ddsd2, 0, sizeof(ddsd2));
4484 ddsd2.dwSize = sizeof(ddsd2);
4485 hr = IDirectDraw4_GetDisplayMode(ddraw, &ddsd2);
4486 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4487 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
4488 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4490 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
4493 static void test_coop_level_versions(void)
4495 HWND window;
4496 IDirectDraw *ddraw;
4497 HRESULT hr;
4498 BOOL restored;
4499 IDirectDrawSurface *surface;
4500 IDirectDraw4 *ddraw4;
4501 DDSURFACEDESC ddsd;
4503 window = create_window();
4504 ddraw4 = create_ddraw();
4505 ok(!!ddraw4, "Failed to create a ddraw object.\n");
4506 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
4507 restored = test_mode_restored(ddraw4, window);
4508 ok(restored, "Display mode not restored in new ddraw object\n");
4510 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
4511 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
4512 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4514 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4515 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4516 restored = test_mode_restored(ddraw4, window);
4517 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
4519 /* A successful one does */
4520 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4521 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4522 restored = test_mode_restored(ddraw4, window);
4523 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
4525 IDirectDraw_Release(ddraw);
4526 IDirectDraw4_Release(ddraw4);
4528 ddraw4 = create_ddraw();
4529 ok(!!ddraw4, "Failed to create a ddraw object.\n");
4530 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
4531 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4533 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
4534 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4535 restored = test_mode_restored(ddraw4, window);
4536 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
4538 IDirectDraw_Release(ddraw);
4539 IDirectDraw4_Release(ddraw4);
4541 /* A failing call does not restore the ddraw2+ behavior */
4542 ddraw4 = create_ddraw();
4543 ok(!!ddraw4, "Failed to create a ddraw object.\n");
4544 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
4545 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4547 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4548 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4549 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4550 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4551 restored = test_mode_restored(ddraw4, window);
4552 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
4554 IDirectDraw_Release(ddraw);
4555 IDirectDraw4_Release(ddraw4);
4557 /* Neither does a sequence of successful calls with the new interface */
4558 ddraw4 = create_ddraw();
4559 ok(!!ddraw4, "Failed to create a ddraw object.\n");
4560 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
4561 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4563 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4564 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4565 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4566 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4567 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_NORMAL);
4568 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4570 restored = test_mode_restored(ddraw4, window);
4571 ok(!restored, "Display mode restored after ddraw1-ddraw4 SetCooperativeLevel() call sequence\n");
4572 IDirectDraw_Release(ddraw);
4573 IDirectDraw4_Release(ddraw4);
4575 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
4576 ddraw4 = create_ddraw();
4577 ok(!!ddraw4, "Failed to create a ddraw object.\n");
4578 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
4579 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4581 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_NORMAL);
4582 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4584 memset(&ddsd, 0, sizeof(ddsd));
4585 ddsd.dwSize = sizeof(ddsd);
4586 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4587 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4588 ddsd.dwWidth = ddsd.dwHeight = 8;
4589 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4590 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
4591 IDirectDrawSurface_Release(surface);
4592 restored = test_mode_restored(ddraw4, window);
4593 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
4595 IDirectDraw_Release(ddraw);
4596 IDirectDraw4_Release(ddraw4);
4597 DestroyWindow(window);
4600 static void test_lighting_interface_versions(void)
4602 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
4603 IDirect3DMaterial3 *emissive;
4604 IDirect3DViewport3 *viewport;
4605 IDirect3DDevice3 *device;
4606 IDirectDrawSurface4 *rt;
4607 D3DCOLOR color;
4608 HWND window;
4609 HRESULT hr;
4610 D3DMATERIALHANDLE mat_handle;
4611 DWORD rs;
4612 unsigned int i;
4613 ULONG ref;
4614 static D3DVERTEX quad[] =
4616 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4617 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4618 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4619 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4622 #define FVF_COLORVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_SPECULAR)
4623 static struct
4625 struct vec3 position;
4626 struct vec3 normal;
4627 DWORD diffuse, specular;
4629 quad2[] =
4631 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4632 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4633 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4634 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4637 static D3DLVERTEX lquad[] =
4639 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4640 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4641 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4642 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4645 #define FVF_LVERTEX2 (D3DFVF_LVERTEX & ~D3DFVF_RESERVED1)
4646 static struct
4648 struct vec3 position;
4649 DWORD diffuse, specular;
4650 struct vec2 texcoord;
4652 lquad2[] =
4654 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4655 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4656 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4657 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4660 static D3DTLVERTEX tlquad[] =
4662 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4663 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4664 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4665 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4668 static const struct
4670 DWORD vertextype;
4671 void *data;
4672 DWORD d3drs_lighting, d3drs_specular;
4673 DWORD draw_flags;
4674 D3DCOLOR color;
4676 tests[] =
4678 /* Lighting is enabled when all of these conditions are met:
4679 * 1) No pretransformed position(D3DFVF_XYZRHW)
4680 * 2) Normals are available (D3DFVF_NORMAL)
4681 * 3) D3DDP_DONOTLIGHT is not set.
4683 * D3DRENDERSTATE_LIGHTING is ignored, it is not defined
4684 * in this d3d version */
4686 /* 0 */
4687 { D3DFVF_VERTEX, quad, FALSE, FALSE, 0, 0x0000ff00},
4688 { D3DFVF_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
4689 { D3DFVF_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
4690 { D3DFVF_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
4691 { D3DFVF_VERTEX, quad, FALSE, TRUE, 0, 0x0000ff00},
4692 { D3DFVF_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
4693 { D3DFVF_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
4694 { D3DFVF_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
4696 /* 8 */
4697 { FVF_COLORVERTEX, quad2, FALSE, FALSE, 0, 0x0000ff00},
4698 { FVF_COLORVERTEX, quad2, TRUE, FALSE, 0, 0x0000ff00},
4699 { FVF_COLORVERTEX, quad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4700 { FVF_COLORVERTEX, quad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4701 /* The specular color in the vertex is ignored because
4702 * D3DRENDERSTATE_COLORVERTEX is not enabled */
4703 { FVF_COLORVERTEX, quad2, FALSE, TRUE, 0, 0x0000ff00},
4704 { FVF_COLORVERTEX, quad2, TRUE, TRUE, 0, 0x0000ff00},
4705 { FVF_COLORVERTEX, quad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4706 { FVF_COLORVERTEX, quad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4708 /* 16 */
4709 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
4710 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, 0, 0x00ff0000},
4711 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4712 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4713 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
4714 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, 0, 0x00ff8080},
4715 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4716 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4718 /* 24 */
4719 { FVF_LVERTEX2, lquad2, FALSE, FALSE, 0, 0x00ff0000},
4720 { FVF_LVERTEX2, lquad2, TRUE, FALSE, 0, 0x00ff0000},
4721 { FVF_LVERTEX2, lquad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4722 { FVF_LVERTEX2, lquad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4723 { FVF_LVERTEX2, lquad2, FALSE, TRUE, 0, 0x00ff8080},
4724 { FVF_LVERTEX2, lquad2, TRUE, TRUE, 0, 0x00ff8080},
4725 { FVF_LVERTEX2, lquad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4726 { FVF_LVERTEX2, lquad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4728 /* 32 */
4729 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
4730 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
4731 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4732 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4733 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
4734 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
4735 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4736 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4739 window = create_window();
4740 if (!(device = create_device(window, DDSCL_NORMAL)))
4742 skip("Failed to create a 3D device, skipping test.\n");
4743 DestroyWindow(window);
4744 return;
4747 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
4748 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4750 viewport = create_viewport(device, 0, 0, 640, 480);
4751 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
4752 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
4754 emissive = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
4755 hr = IDirect3DMaterial3_GetHandle(emissive, device, &mat_handle);
4756 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
4757 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
4758 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
4759 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
4760 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr);
4762 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
4763 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#x.\n", hr);
4764 ok(rs == FALSE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#x, expected FALSE.\n", rs);
4766 for (i = 0; i < ARRAY_SIZE(tests); i++)
4768 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff202020, 0.0f, 0);
4769 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4771 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
4772 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#x.\n", hr);
4773 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
4774 tests[i].d3drs_specular);
4775 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#x.\n", hr);
4777 hr = IDirect3DDevice3_BeginScene(device);
4778 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4779 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
4780 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
4781 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4782 hr = IDirect3DDevice3_EndScene(device);
4783 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4785 color = get_surface_color(rt, 320, 240);
4786 ok(compare_color(color, tests[i].color, 1),
4787 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
4788 color, tests[i].color, i);
4791 destroy_material(emissive);
4792 IDirectDrawSurface4_Release(rt);
4793 ref = IDirect3DDevice3_Release(device);
4794 ok(ref == 0, "Device not properly released, refcount %u.\n", ref);
4795 DestroyWindow(window);
4798 static struct
4800 BOOL received;
4801 IDirectDraw4 *ddraw;
4802 HWND window;
4803 DWORD coop_level;
4804 } activateapp_testdata;
4806 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
4808 if (message == WM_ACTIVATEAPP)
4810 if (activateapp_testdata.ddraw)
4812 HRESULT hr;
4813 activateapp_testdata.received = FALSE;
4814 hr = IDirectDraw4_SetCooperativeLevel(activateapp_testdata.ddraw,
4815 activateapp_testdata.window, activateapp_testdata.coop_level);
4816 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
4817 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
4819 activateapp_testdata.received = TRUE;
4822 return DefWindowProcA(hwnd, message, wparam, lparam);
4825 static void test_coop_level_activateapp(void)
4827 IDirectDraw4 *ddraw;
4828 HRESULT hr;
4829 HWND window;
4830 WNDCLASSA wc = {0};
4831 DDSURFACEDESC2 ddsd;
4832 IDirectDrawSurface4 *surface;
4834 ddraw = create_ddraw();
4835 ok(!!ddraw, "Failed to create a ddraw object.\n");
4837 wc.lpfnWndProc = activateapp_test_proc;
4838 wc.lpszClassName = "ddraw_test_wndproc_wc";
4839 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4841 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
4842 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
4844 /* Exclusive with window already active. */
4845 SetForegroundWindow(window);
4846 activateapp_testdata.received = FALSE;
4847 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4848 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4849 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
4850 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4851 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4853 /* Exclusive with window not active. */
4854 SetForegroundWindow(GetDesktopWindow());
4855 activateapp_testdata.received = FALSE;
4856 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4857 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4858 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4859 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4860 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4862 /* Normal with window not active, then exclusive with the same window. */
4863 SetForegroundWindow(GetDesktopWindow());
4864 activateapp_testdata.received = FALSE;
4865 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4866 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4867 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
4868 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4869 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4870 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4871 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4872 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4874 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
4875 SetForegroundWindow(GetDesktopWindow());
4876 activateapp_testdata.received = FALSE;
4877 activateapp_testdata.ddraw = ddraw;
4878 activateapp_testdata.window = window;
4879 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
4880 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4881 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4882 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4883 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4884 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4886 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
4887 * succeeding. Another switch to exclusive and back to normal is needed to release the
4888 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
4889 * WM_ACTIVATEAPP messages. */
4890 activateapp_testdata.ddraw = NULL;
4891 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4892 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4893 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4894 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4896 /* Setting DDSCL_NORMAL with recursive invocation. */
4897 SetForegroundWindow(GetDesktopWindow());
4898 activateapp_testdata.received = FALSE;
4899 activateapp_testdata.ddraw = ddraw;
4900 activateapp_testdata.window = window;
4901 activateapp_testdata.coop_level = DDSCL_NORMAL;
4902 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4903 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4904 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4906 /* DDraw is in exclusive mode now. */
4907 memset(&ddsd, 0, sizeof(ddsd));
4908 ddsd.dwSize = sizeof(ddsd);
4909 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
4910 U5(ddsd).dwBackBufferCount = 1;
4911 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
4912 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
4913 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4914 IDirectDrawSurface4_Release(surface);
4916 /* Recover again, just to be sure. */
4917 activateapp_testdata.ddraw = NULL;
4918 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4919 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4920 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4921 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4923 DestroyWindow(window);
4924 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
4925 IDirectDraw4_Release(ddraw);
4928 static void test_texturemanage(void)
4930 IDirectDraw4 *ddraw;
4931 HRESULT hr;
4932 DDSURFACEDESC2 ddsd;
4933 IDirectDrawSurface4 *surface;
4934 unsigned int i;
4935 DDCAPS hal_caps, hel_caps;
4936 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
4937 static const struct
4939 DWORD caps_in, caps2_in;
4940 HRESULT hr;
4941 DWORD caps_out, caps2_out;
4943 tests[] =
4945 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4946 ~0U, ~0U},
4947 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4948 ~0U, ~0U},
4949 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4950 ~0U, ~0U},
4951 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4952 ~0U, ~0U},
4953 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DD_OK,
4954 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE},
4955 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DD_OK,
4956 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE},
4957 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
4958 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_LOCALVIDMEM, 0},
4959 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
4960 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0},
4962 {0, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4963 ~0U, ~0U},
4964 {0, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4965 ~0U, ~0U},
4966 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4967 ~0U, ~0U},
4968 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4969 ~0U, ~0U},
4970 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4971 ~0U, ~0U},
4972 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4973 ~0U, ~0U},
4974 {DDSCAPS_VIDEOMEMORY, 0, DD_OK,
4975 DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY, 0},
4976 {DDSCAPS_SYSTEMMEMORY, 0, DD_OK,
4977 DDSCAPS_SYSTEMMEMORY, 0},
4980 ddraw = create_ddraw();
4981 ok(!!ddraw, "Failed to create a ddraw object.\n");
4982 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4983 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4985 memset(&hal_caps, 0, sizeof(hal_caps));
4986 hal_caps.dwSize = sizeof(hal_caps);
4987 memset(&hel_caps, 0, sizeof(hel_caps));
4988 hel_caps.dwSize = sizeof(hel_caps);
4989 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, &hel_caps);
4990 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
4991 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
4993 skip("Managed textures not supported, skipping managed texture test.\n");
4994 IDirectDraw4_Release(ddraw);
4995 return;
4998 for (i = 0; i < ARRAY_SIZE(tests); i++)
5000 memset(&ddsd, 0, sizeof(ddsd));
5001 ddsd.dwSize = sizeof(ddsd);
5002 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5003 ddsd.ddsCaps.dwCaps = tests[i].caps_in;
5004 ddsd.ddsCaps.dwCaps2 = tests[i].caps2_in;
5005 ddsd.dwWidth = 4;
5006 ddsd.dwHeight = 4;
5008 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5009 ok(hr == tests[i].hr, "Got unexpected, hr %#x, case %u.\n", hr, i);
5010 if (FAILED(hr))
5011 continue;
5013 memset(&ddsd, 0, sizeof(ddsd));
5014 ddsd.dwSize = sizeof(ddsd);
5015 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5016 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5018 ok(ddsd.ddsCaps.dwCaps == tests[i].caps_out,
5019 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
5020 tests[i].caps_in, tests[i].caps2_in, tests[i].caps_out, ddsd.ddsCaps.dwCaps, i);
5021 ok(ddsd.ddsCaps.dwCaps2 == tests[i].caps2_out,
5022 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
5023 tests[i].caps_in, tests[i].caps2_in, tests[i].caps2_out, ddsd.ddsCaps.dwCaps2, i);
5025 IDirectDrawSurface4_Release(surface);
5028 IDirectDraw4_Release(ddraw);
5031 #define SUPPORT_DXT1 0x01
5032 #define SUPPORT_DXT2 0x02
5033 #define SUPPORT_DXT3 0x04
5034 #define SUPPORT_DXT4 0x08
5035 #define SUPPORT_DXT5 0x10
5036 #define SUPPORT_YUY2 0x20
5037 #define SUPPORT_UYVY 0x40
5039 static HRESULT WINAPI test_block_formats_creation_cb(DDPIXELFORMAT *fmt, void *ctx)
5041 DWORD *supported_fmts = ctx;
5043 if (!(fmt->dwFlags & DDPF_FOURCC))
5044 return DDENUMRET_OK;
5046 switch (fmt->dwFourCC)
5048 case MAKEFOURCC('D','X','T','1'):
5049 *supported_fmts |= SUPPORT_DXT1;
5050 break;
5051 case MAKEFOURCC('D','X','T','2'):
5052 *supported_fmts |= SUPPORT_DXT2;
5053 break;
5054 case MAKEFOURCC('D','X','T','3'):
5055 *supported_fmts |= SUPPORT_DXT3;
5056 break;
5057 case MAKEFOURCC('D','X','T','4'):
5058 *supported_fmts |= SUPPORT_DXT4;
5059 break;
5060 case MAKEFOURCC('D','X','T','5'):
5061 *supported_fmts |= SUPPORT_DXT5;
5062 break;
5063 case MAKEFOURCC('Y','U','Y','2'):
5064 *supported_fmts |= SUPPORT_YUY2;
5065 break;
5066 case MAKEFOURCC('U','Y','V','Y'):
5067 *supported_fmts |= SUPPORT_UYVY;
5068 break;
5069 default:
5070 break;
5073 return DDENUMRET_OK;
5076 static void test_block_formats_creation(void)
5078 HRESULT hr, expect_hr;
5079 unsigned int i, j, w, h;
5080 HWND window;
5081 IDirectDraw4 *ddraw;
5082 IDirect3D3 *d3d;
5083 IDirect3DDevice3 *device;
5084 IDirectDrawSurface4 *surface;
5085 DWORD supported_fmts = 0, supported_overlay_fmts = 0;
5086 DWORD num_fourcc_codes = 0, *fourcc_codes;
5087 DDSURFACEDESC2 ddsd;
5088 DDCAPS hal_caps;
5089 void *mem;
5091 static const struct
5093 DWORD fourcc;
5094 const char *name;
5095 DWORD support_flag;
5096 unsigned int block_width;
5097 unsigned int block_height;
5098 unsigned int block_size;
5099 BOOL create_size_checked, overlay;
5101 formats[] =
5103 {MAKEFOURCC('D','X','T','1'), "D3DFMT_DXT1", SUPPORT_DXT1, 4, 4, 8, TRUE, FALSE},
5104 {MAKEFOURCC('D','X','T','2'), "D3DFMT_DXT2", SUPPORT_DXT2, 4, 4, 16, TRUE, FALSE},
5105 {MAKEFOURCC('D','X','T','3'), "D3DFMT_DXT3", SUPPORT_DXT3, 4, 4, 16, TRUE, FALSE},
5106 {MAKEFOURCC('D','X','T','4'), "D3DFMT_DXT4", SUPPORT_DXT4, 4, 4, 16, TRUE, FALSE},
5107 {MAKEFOURCC('D','X','T','5'), "D3DFMT_DXT5", SUPPORT_DXT5, 4, 4, 16, TRUE, FALSE},
5108 {MAKEFOURCC('Y','U','Y','2'), "D3DFMT_YUY2", SUPPORT_YUY2, 2, 1, 4, FALSE, TRUE },
5109 {MAKEFOURCC('U','Y','V','Y'), "D3DFMT_UYVY", SUPPORT_UYVY, 2, 1, 4, FALSE, TRUE },
5111 static const struct
5113 DWORD caps, caps2;
5114 const char *name;
5115 BOOL overlay;
5117 types[] =
5119 /* DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY fails to create any fourcc
5120 * surface with DDERR_INVALIDPIXELFORMAT. Don't care about it for now.
5122 * Nvidia returns E_FAIL on DXTN DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY.
5123 * Other hw / drivers successfully create those surfaces. Ignore them, this
5124 * suggests that no game uses this, otherwise Nvidia would support it. */
5126 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0,
5127 "videomemory texture", FALSE
5130 DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY, 0,
5131 "videomemory overlay", TRUE
5134 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0,
5135 "systemmemory texture", FALSE
5138 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
5139 "managed texture", FALSE
5142 enum size_type
5144 SIZE_TYPE_ZERO,
5145 SIZE_TYPE_PITCH,
5146 SIZE_TYPE_SIZE,
5148 static const struct
5150 DWORD flags;
5151 enum size_type size_type;
5152 int rel_size;
5153 HRESULT hr;
5155 user_mem_tests[] =
5157 {DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DD_OK},
5158 {DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
5159 {DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
5160 {DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
5161 {DDSD_LPSURFACE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
5162 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
5163 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
5164 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
5165 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 1, DD_OK},
5166 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, -1, DDERR_INVALIDPARAMS},
5167 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
5168 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
5169 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_SIZE, 0, DD_OK},
5170 {DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
5173 window = create_window();
5174 if (!(device = create_device(window, DDSCL_NORMAL)))
5176 skip("Failed to create a 3D device, skipping test.\n");
5177 DestroyWindow(window);
5178 return;
5181 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
5182 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5183 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **) &ddraw);
5184 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5185 IDirect3D3_Release(d3d);
5187 hr = IDirect3DDevice3_EnumTextureFormats(device, test_block_formats_creation_cb,
5188 &supported_fmts);
5189 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
5191 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
5192 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
5193 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5194 num_fourcc_codes * sizeof(*fourcc_codes));
5195 if (!fourcc_codes)
5196 goto cleanup;
5197 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
5198 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
5199 for (i = 0; i < num_fourcc_codes; i++)
5201 for (j = 0; j < ARRAY_SIZE(formats); j++)
5203 if (fourcc_codes[i] == formats[j].fourcc)
5204 supported_overlay_fmts |= formats[j].support_flag;
5207 HeapFree(GetProcessHeap(), 0, fourcc_codes);
5209 memset(&hal_caps, 0, sizeof(hal_caps));
5210 hal_caps.dwSize = sizeof(hal_caps);
5211 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
5212 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5214 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * 2 * 16 + 1);
5216 for (i = 0; i < ARRAY_SIZE(formats); i++)
5218 for (j = 0; j < ARRAY_SIZE(types); j++)
5220 BOOL support;
5222 if (formats[i].overlay != types[j].overlay
5223 || (types[j].overlay && !(hal_caps.dwCaps & DDCAPS_OVERLAY)))
5224 continue;
5226 if (formats[i].overlay)
5227 support = supported_overlay_fmts & formats[i].support_flag;
5228 else
5229 support = supported_fmts & formats[i].support_flag;
5231 for (w = 1; w <= 8; w++)
5233 for (h = 1; h <= 8; h++)
5235 BOOL block_aligned = TRUE;
5236 BOOL todo = FALSE;
5238 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
5239 block_aligned = FALSE;
5241 memset(&ddsd, 0, sizeof(ddsd));
5242 ddsd.dwSize = sizeof(ddsd);
5243 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5244 ddsd.ddsCaps.dwCaps = types[j].caps;
5245 ddsd.ddsCaps.dwCaps2 = types[j].caps2;
5246 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5247 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
5248 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
5249 ddsd.dwWidth = w;
5250 ddsd.dwHeight = h;
5252 /* TODO: Handle power of two limitations. I cannot test the pow2
5253 * behavior on windows because I have no hardware that doesn't at
5254 * least support np2_conditional. There's probably no HW that
5255 * supports DXTN textures but no conditional np2 textures. */
5256 if (!support && !(types[j].caps & DDSCAPS_SYSTEMMEMORY))
5257 expect_hr = DDERR_INVALIDPARAMS;
5258 else if (formats[i].create_size_checked && !block_aligned)
5260 expect_hr = DDERR_INVALIDPARAMS;
5261 if (!(types[j].caps & DDSCAPS_TEXTURE))
5262 todo = TRUE;
5264 else
5265 expect_hr = D3D_OK;
5267 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5268 todo_wine_if (todo)
5269 ok(hr == expect_hr,
5270 "Got unexpected hr %#x for format %s, resource type %s, size %ux%u, expected %#x.\n",
5271 hr, formats[i].name, types[j].name, w, h, expect_hr);
5273 if (SUCCEEDED(hr))
5274 IDirectDrawSurface4_Release(surface);
5279 if (formats[i].overlay)
5280 continue;
5282 for (j = 0; j < ARRAY_SIZE(user_mem_tests); ++j)
5284 memset(&ddsd, 0, sizeof(ddsd));
5285 ddsd.dwSize = sizeof(ddsd);
5286 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | user_mem_tests[j].flags;
5287 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE;
5289 switch (user_mem_tests[j].size_type)
5291 case SIZE_TYPE_ZERO:
5292 U1(ddsd).dwLinearSize = 0;
5293 break;
5295 case SIZE_TYPE_PITCH:
5296 U1(ddsd).dwLinearSize = 2 * formats[i].block_size;
5297 break;
5299 case SIZE_TYPE_SIZE:
5300 U1(ddsd).dwLinearSize = 2 * 2 * formats[i].block_size;
5301 break;
5303 U1(ddsd).dwLinearSize += user_mem_tests[j].rel_size;
5305 ddsd.lpSurface = mem;
5306 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5307 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
5308 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
5309 ddsd.dwWidth = 8;
5310 ddsd.dwHeight = 8;
5312 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5313 ok(hr == user_mem_tests[j].hr, "Test %u: Got unexpected hr %#x, format %s.\n", j, hr, formats[i].name);
5315 if (FAILED(hr))
5316 continue;
5318 memset(&ddsd, 0, sizeof(ddsd));
5319 ddsd.dwSize = sizeof(ddsd);
5320 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5321 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", j, hr);
5322 ok(ddsd.dwFlags == (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_LINEARSIZE),
5323 "Test %u: Got unexpected flags %#x.\n", j, ddsd.dwFlags);
5324 if (user_mem_tests[j].flags & DDSD_LPSURFACE)
5325 ok(U1(ddsd).dwLinearSize == ~0u, "Test %u: Got unexpected linear size %#x.\n",
5326 j, U1(ddsd).dwLinearSize);
5327 else
5328 ok(U1(ddsd).dwLinearSize == 2 * 2 * formats[i].block_size,
5329 "Test %u: Got unexpected linear size %#x, expected %#x.\n",
5330 j, U1(ddsd).dwLinearSize, 2 * 2 * formats[i].block_size);
5331 IDirectDrawSurface4_Release(surface);
5335 HeapFree(GetProcessHeap(), 0, mem);
5336 cleanup:
5337 IDirectDraw4_Release(ddraw);
5338 IDirect3DDevice3_Release(device);
5339 DestroyWindow(window);
5342 struct format_support_check
5344 const DDPIXELFORMAT *format;
5345 BOOL supported;
5348 static HRESULT WINAPI test_unsupported_formats_cb(DDPIXELFORMAT *fmt, void *ctx)
5350 struct format_support_check *format = ctx;
5352 if (!memcmp(format->format, fmt, sizeof(*fmt)))
5354 format->supported = TRUE;
5355 return DDENUMRET_CANCEL;
5358 return DDENUMRET_OK;
5361 static void test_unsupported_formats(void)
5363 HRESULT hr;
5364 BOOL expect_success;
5365 HWND window;
5366 IDirectDraw4 *ddraw;
5367 IDirect3D3 *d3d;
5368 IDirect3DDevice3 *device;
5369 IDirectDrawSurface4 *surface;
5370 DDSURFACEDESC2 ddsd;
5371 unsigned int i, j;
5372 DWORD expected_caps;
5373 static const struct
5375 const char *name;
5376 DDPIXELFORMAT fmt;
5378 formats[] =
5381 "D3DFMT_A8R8G8B8",
5383 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
5384 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
5388 "D3DFMT_P8",
5390 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5391 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
5395 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
5397 window = create_window();
5398 if (!(device = create_device(window, DDSCL_NORMAL)))
5400 skip("Failed to create a 3D device, skipping test.\n");
5401 DestroyWindow(window);
5402 return;
5405 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
5406 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5407 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **) &ddraw);
5408 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5409 IDirect3D3_Release(d3d);
5411 for (i = 0; i < ARRAY_SIZE(formats); i++)
5413 struct format_support_check check = {&formats[i].fmt, FALSE};
5414 hr = IDirect3DDevice3_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
5415 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
5417 for (j = 0; j < ARRAY_SIZE(caps); j++)
5419 memset(&ddsd, 0, sizeof(ddsd));
5420 ddsd.dwSize = sizeof(ddsd);
5421 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5422 U4(ddsd).ddpfPixelFormat = formats[i].fmt;
5423 ddsd.dwWidth = 4;
5424 ddsd.dwHeight = 4;
5425 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
5427 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
5428 expect_success = FALSE;
5429 else
5430 expect_success = TRUE;
5432 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5433 ok(SUCCEEDED(hr) == expect_success,
5434 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
5435 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
5436 if (FAILED(hr))
5437 continue;
5439 memset(&ddsd, 0, sizeof(ddsd));
5440 ddsd.dwSize = sizeof(ddsd);
5441 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5442 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5444 if (caps[j] & DDSCAPS_VIDEOMEMORY)
5445 expected_caps = DDSCAPS_VIDEOMEMORY;
5446 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
5447 expected_caps = DDSCAPS_SYSTEMMEMORY;
5448 else if (check.supported)
5449 expected_caps = DDSCAPS_VIDEOMEMORY;
5450 else
5451 expected_caps = DDSCAPS_SYSTEMMEMORY;
5453 ok(ddsd.ddsCaps.dwCaps & expected_caps,
5454 "Expected capability %#x, format %s, input cap %#x.\n",
5455 expected_caps, formats[i].name, caps[j]);
5457 IDirectDrawSurface4_Release(surface);
5461 IDirectDraw4_Release(ddraw);
5462 IDirect3DDevice3_Release(device);
5463 DestroyWindow(window);
5466 static void test_rt_caps(void)
5468 PALETTEENTRY palette_entries[256];
5469 IDirectDrawPalette *palette;
5470 IDirectDraw4 *ddraw;
5471 DDPIXELFORMAT z_fmt;
5472 IDirect3D3 *d3d;
5473 unsigned int i;
5474 ULONG refcount;
5475 HWND window;
5476 HRESULT hr;
5478 static const DDPIXELFORMAT p8_fmt =
5480 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5481 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
5484 const struct
5486 const DDPIXELFORMAT *pf;
5487 DWORD caps_in;
5488 DWORD caps_out;
5489 HRESULT create_device_hr;
5490 HRESULT set_rt_hr, alternative_set_rt_hr;
5492 test_data[] =
5495 NULL,
5496 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5497 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5498 D3D_OK,
5499 D3D_OK,
5500 D3D_OK,
5503 NULL,
5504 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5505 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5506 D3D_OK,
5507 D3D_OK,
5508 D3D_OK,
5511 NULL,
5512 DDSCAPS_OFFSCREENPLAIN,
5513 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5514 DDERR_INVALIDCAPS,
5515 DDERR_INVALIDCAPS,
5516 DDERR_INVALIDCAPS,
5519 NULL,
5520 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5521 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5522 D3DERR_SURFACENOTINVIDMEM,
5523 D3D_OK,
5524 D3D_OK,
5527 NULL,
5528 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5529 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5530 DDERR_INVALIDCAPS,
5531 DDERR_INVALIDCAPS,
5532 DDERR_INVALIDCAPS,
5535 NULL,
5536 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5537 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5538 D3D_OK,
5539 D3D_OK,
5540 D3D_OK,
5543 NULL,
5544 DDSCAPS_3DDEVICE,
5545 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5546 D3D_OK,
5547 D3D_OK,
5548 D3D_OK,
5551 NULL,
5553 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5554 DDERR_INVALIDCAPS,
5555 DDERR_INVALIDCAPS,
5556 DDERR_INVALIDCAPS,
5559 NULL,
5560 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5561 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5562 D3DERR_SURFACENOTINVIDMEM,
5563 D3D_OK,
5564 D3D_OK,
5567 NULL,
5568 DDSCAPS_SYSTEMMEMORY,
5569 DDSCAPS_SYSTEMMEMORY,
5570 DDERR_INVALIDCAPS,
5571 DDERR_INVALIDCAPS,
5572 DDERR_INVALIDCAPS,
5575 &p8_fmt,
5577 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5578 DDERR_INVALIDCAPS,
5579 DDERR_INVALIDCAPS,
5580 DDERR_INVALIDCAPS,
5583 &p8_fmt,
5584 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5585 ~0U /* AMD r200 */,
5586 DDERR_NOPALETTEATTACHED,
5587 DDERR_INVALIDCAPS,
5588 DDERR_INVALIDCAPS,
5591 &p8_fmt,
5592 DDSCAPS_OFFSCREENPLAIN,
5593 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5594 DDERR_INVALIDCAPS,
5595 DDERR_INVALIDCAPS,
5596 DDERR_INVALIDCAPS,
5599 &p8_fmt,
5600 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5601 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5602 DDERR_NOPALETTEATTACHED,
5603 DDERR_INVALIDCAPS,
5604 DDERR_INVALIDCAPS,
5607 &p8_fmt,
5608 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5609 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5610 DDERR_INVALIDCAPS,
5611 DDERR_INVALIDCAPS,
5612 DDERR_INVALIDCAPS,
5615 &z_fmt,
5616 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
5617 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5618 DDERR_INVALIDCAPS,
5619 DDERR_INVALIDPIXELFORMAT,
5620 D3D_OK /* r200 */,
5623 &z_fmt,
5624 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5625 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5626 DDERR_INVALIDCAPS,
5627 DDERR_INVALIDPIXELFORMAT,
5628 D3D_OK /* r200 */,
5631 &z_fmt,
5632 DDSCAPS_ZBUFFER,
5633 DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5634 DDERR_INVALIDCAPS,
5635 DDERR_INVALIDCAPS,
5636 DDERR_INVALIDCAPS,
5639 &z_fmt,
5640 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5641 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5642 DDERR_INVALIDCAPS,
5643 DDERR_INVALIDPIXELFORMAT,
5644 D3D_OK /* r200 */,
5647 &z_fmt,
5648 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5649 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5650 DDERR_INVALIDCAPS,
5651 DDERR_INVALIDCAPS,
5652 DDERR_INVALIDCAPS,
5656 window = create_window();
5657 ddraw = create_ddraw();
5658 ok(!!ddraw, "Failed to create a ddraw object.\n");
5659 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5660 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5662 if (FAILED(IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
5664 skip("D3D interface is not available, skipping test.\n");
5665 goto done;
5668 memset(&z_fmt, 0, sizeof(z_fmt));
5669 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
5670 if (FAILED(hr) || !z_fmt.dwSize)
5672 skip("No depth buffer formats available, skipping test.\n");
5673 IDirect3D3_Release(d3d);
5674 goto done;
5677 memset(palette_entries, 0, sizeof(palette_entries));
5678 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
5679 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5681 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5683 IDirectDrawSurface4 *surface, *rt, *expected_rt, *tmp;
5684 DDSURFACEDESC2 surface_desc;
5685 IDirect3DDevice3 *device;
5687 memset(&surface_desc, 0, sizeof(surface_desc));
5688 surface_desc.dwSize = sizeof(surface_desc);
5689 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5690 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5691 if (test_data[i].pf)
5693 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5694 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5696 surface_desc.dwWidth = 640;
5697 surface_desc.dwHeight = 480;
5698 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5699 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
5700 i, test_data[i].caps_in, hr);
5702 memset(&surface_desc, 0, sizeof(surface_desc));
5703 surface_desc.dwSize = sizeof(surface_desc);
5704 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
5705 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5706 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
5707 "Test %u: Got unexpected caps %#x, expected %#x.\n",
5708 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5710 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
5711 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
5712 i, hr, test_data[i].create_device_hr);
5713 if (FAILED(hr))
5715 if (hr == DDERR_NOPALETTEATTACHED)
5717 hr = IDirectDrawSurface4_SetPalette(surface, palette);
5718 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
5719 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
5720 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
5721 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
5722 else
5723 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
5725 IDirectDrawSurface4_Release(surface);
5727 memset(&surface_desc, 0, sizeof(surface_desc));
5728 surface_desc.dwSize = sizeof(surface_desc);
5729 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5730 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5731 surface_desc.dwWidth = 640;
5732 surface_desc.dwHeight = 480;
5733 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5734 ok(SUCCEEDED(hr), "Test %u: Failed to create surface, hr %#x.\n", i, hr);
5736 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
5737 ok(SUCCEEDED(hr), "Test %u: Failed to create device, hr %#x.\n", i, hr);
5740 memset(&surface_desc, 0, sizeof(surface_desc));
5741 surface_desc.dwSize = sizeof(surface_desc);
5742 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5743 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5744 if (test_data[i].pf)
5746 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5747 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5749 surface_desc.dwWidth = 640;
5750 surface_desc.dwHeight = 480;
5751 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &rt, NULL);
5752 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
5753 i, test_data[i].caps_in, hr);
5755 hr = IDirect3DDevice3_SetRenderTarget(device, rt, 0);
5756 ok(hr == test_data[i].set_rt_hr || broken(hr == test_data[i].alternative_set_rt_hr),
5757 "Test %u: Got unexpected hr %#x, expected %#x.\n",
5758 i, hr, test_data[i].set_rt_hr);
5759 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
5760 expected_rt = rt;
5761 else
5762 expected_rt = surface;
5764 hr = IDirect3DDevice3_GetRenderTarget(device, &tmp);
5765 ok(SUCCEEDED(hr), "Test %u: Failed to get render target, hr %#x.\n", i, hr);
5766 ok(tmp == expected_rt, "Test %u: Got unexpected rt %p.\n", i, tmp);
5768 IDirectDrawSurface4_Release(tmp);
5769 IDirectDrawSurface4_Release(rt);
5770 refcount = IDirect3DDevice3_Release(device);
5771 ok(refcount == 0, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
5772 refcount = IDirectDrawSurface4_Release(surface);
5773 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
5776 IDirectDrawPalette_Release(palette);
5777 IDirect3D3_Release(d3d);
5779 done:
5780 refcount = IDirectDraw4_Release(ddraw);
5781 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5782 DestroyWindow(window);
5785 static void test_primary_caps(void)
5787 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
5788 IDirectDrawSurface4 *surface;
5789 DDSURFACEDESC2 surface_desc;
5790 IDirectDraw4 *ddraw;
5791 unsigned int i;
5792 ULONG refcount;
5793 HWND window;
5794 HRESULT hr;
5796 static const struct
5798 DWORD coop_level;
5799 DWORD caps_in;
5800 DWORD back_buffer_count;
5801 HRESULT hr;
5802 DWORD caps_out;
5804 test_data[] =
5807 DDSCL_NORMAL,
5808 DDSCAPS_PRIMARYSURFACE,
5809 ~0u,
5810 DD_OK,
5811 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
5814 DDSCL_NORMAL,
5815 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
5816 ~0u,
5817 DDERR_INVALIDCAPS,
5818 ~0u,
5821 DDSCL_NORMAL,
5822 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
5823 ~0u,
5824 DDERR_INVALIDCAPS,
5825 ~0u,
5828 DDSCL_NORMAL,
5829 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
5830 ~0u,
5831 DDERR_INVALIDCAPS,
5832 ~0u,
5835 DDSCL_NORMAL,
5836 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
5837 ~0u,
5838 DDERR_INVALIDCAPS,
5839 ~0u,
5842 DDSCL_NORMAL,
5843 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
5844 ~0u,
5845 DDERR_INVALIDCAPS,
5846 ~0u,
5849 DDSCL_NORMAL,
5850 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5851 ~0u,
5852 DDERR_INVALIDCAPS,
5853 ~0u,
5856 DDSCL_NORMAL,
5857 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5859 DDERR_INVALIDCAPS,
5860 ~0u,
5863 DDSCL_NORMAL,
5864 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5866 DDERR_NOEXCLUSIVEMODE,
5867 ~0u,
5870 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5871 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5873 DDERR_INVALIDCAPS,
5874 ~0u,
5877 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5878 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5880 DD_OK,
5881 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
5884 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5885 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
5887 DDERR_INVALIDCAPS,
5888 ~0u,
5891 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5892 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
5894 DDERR_INVALIDCAPS,
5895 ~0u,
5899 window = create_window();
5900 ddraw = create_ddraw();
5901 ok(!!ddraw, "Failed to create a ddraw object.\n");
5903 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5905 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
5906 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5908 memset(&surface_desc, 0, sizeof(surface_desc));
5909 surface_desc.dwSize = sizeof(surface_desc);
5910 surface_desc.dwFlags = DDSD_CAPS;
5911 if (test_data[i].back_buffer_count != ~0u)
5912 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
5913 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5914 U5(surface_desc).dwBackBufferCount = test_data[i].back_buffer_count;
5915 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5916 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
5917 if (FAILED(hr))
5918 continue;
5920 memset(&surface_desc, 0, sizeof(surface_desc));
5921 surface_desc.dwSize = sizeof(surface_desc);
5922 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
5923 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5924 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
5925 "Test %u: Got unexpected caps %#x, expected %#x.\n",
5926 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5928 IDirectDrawSurface4_Release(surface);
5931 refcount = IDirectDraw4_Release(ddraw);
5932 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5933 DestroyWindow(window);
5936 static void test_surface_lock(void)
5938 IDirectDraw4 *ddraw;
5939 IDirect3D3 *d3d = NULL;
5940 IDirectDrawSurface4 *surface;
5941 HRESULT hr;
5942 HWND window;
5943 unsigned int i;
5944 DDSURFACEDESC2 ddsd;
5945 ULONG refcount;
5946 DDPIXELFORMAT z_fmt;
5947 static const struct
5949 DWORD caps;
5950 DWORD caps2;
5951 const char *name;
5953 tests[] =
5956 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
5958 "videomemory offscreenplain"
5961 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5963 "systemmemory offscreenplain"
5966 DDSCAPS_PRIMARYSURFACE,
5968 "primary"
5971 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
5973 "videomemory texture"
5976 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
5977 DDSCAPS2_OPAQUE,
5978 "opaque videomemory texture"
5981 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
5983 "systemmemory texture"
5986 DDSCAPS_TEXTURE,
5987 DDSCAPS2_TEXTUREMANAGE,
5988 "managed texture"
5991 DDSCAPS_TEXTURE,
5992 DDSCAPS2_D3DTEXTUREMANAGE,
5993 "managed texture"
5996 DDSCAPS_TEXTURE,
5997 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_OPAQUE,
5998 "opaque managed texture"
6001 DDSCAPS_TEXTURE,
6002 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_OPAQUE,
6003 "opaque managed texture"
6006 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
6008 "render target"
6011 DDSCAPS_ZBUFFER,
6013 "Z buffer"
6017 window = create_window();
6018 ddraw = create_ddraw();
6019 ok(!!ddraw, "Failed to create a ddraw object.\n");
6020 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6021 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6023 if (FAILED(IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
6025 skip("D3D interface is not available, skipping test.\n");
6026 goto done;
6029 memset(&z_fmt, 0, sizeof(z_fmt));
6030 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
6031 if (FAILED(hr) || !z_fmt.dwSize)
6033 skip("No depth buffer formats available, skipping test.\n");
6034 goto done;
6037 for (i = 0; i < ARRAY_SIZE(tests); i++)
6039 memset(&ddsd, 0, sizeof(ddsd));
6040 ddsd.dwSize = sizeof(ddsd);
6041 ddsd.dwFlags = DDSD_CAPS;
6042 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
6044 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6045 ddsd.dwWidth = 64;
6046 ddsd.dwHeight = 64;
6048 if (tests[i].caps & DDSCAPS_ZBUFFER)
6050 ddsd.dwFlags |= DDSD_PIXELFORMAT;
6051 U4(ddsd).ddpfPixelFormat = z_fmt;
6053 ddsd.ddsCaps.dwCaps = tests[i].caps;
6054 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
6056 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6057 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
6059 memset(&ddsd, 0, sizeof(ddsd));
6060 ddsd.dwSize = sizeof(ddsd);
6061 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
6062 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
6063 if (SUCCEEDED(hr))
6065 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6066 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
6069 memset(&ddsd, 0, sizeof(ddsd));
6070 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
6071 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, tests[i].name);
6073 IDirectDrawSurface4_Release(surface);
6076 done:
6077 if (d3d)
6078 IDirect3D3_Release(d3d);
6079 refcount = IDirectDraw4_Release(ddraw);
6080 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6081 DestroyWindow(window);
6084 static void test_surface_discard(void)
6086 IDirect3DDevice3 *device;
6087 IDirect3D3 *d3d;
6088 IDirectDraw4 *ddraw;
6089 HRESULT hr;
6090 HWND window;
6091 DDSURFACEDESC2 ddsd;
6092 IDirectDrawSurface4 *surface, *target;
6093 void *addr;
6094 static const struct
6096 DWORD caps, caps2;
6097 BOOL discard;
6099 tests[] =
6101 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, TRUE},
6102 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
6103 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, TRUE},
6104 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
6105 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE},
6106 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
6107 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE},
6108 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
6110 unsigned int i;
6112 window = create_window();
6113 if (!(device = create_device(window, DDSCL_NORMAL)))
6115 skip("Failed to create a 3D device, skipping test.\n");
6116 DestroyWindow(window);
6117 return;
6119 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
6120 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
6121 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
6122 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
6123 hr = IDirect3DDevice3_GetRenderTarget(device, &target);
6124 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
6126 for (i = 0; i < ARRAY_SIZE(tests); i++)
6128 BOOL discarded;
6130 memset(&ddsd, 0, sizeof(ddsd));
6131 ddsd.dwSize = sizeof(ddsd);
6132 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6133 ddsd.ddsCaps.dwCaps = tests[i].caps;
6134 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
6135 ddsd.dwWidth = 64;
6136 ddsd.dwHeight = 64;
6137 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6138 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x, case %u.\n", hr, i);
6140 memset(&ddsd, 0, sizeof(ddsd));
6141 ddsd.dwSize = sizeof(ddsd);
6142 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, 0, NULL);
6143 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6144 addr = ddsd.lpSurface;
6145 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6146 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6148 memset(&ddsd, 0, sizeof(ddsd));
6149 ddsd.dwSize = sizeof(ddsd);
6150 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
6151 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6152 discarded = ddsd.lpSurface != addr;
6153 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6154 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6156 hr = IDirectDrawSurface4_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
6157 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
6159 memset(&ddsd, 0, sizeof(ddsd));
6160 ddsd.dwSize = sizeof(ddsd);
6161 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
6162 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6163 discarded |= ddsd.lpSurface != addr;
6164 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6165 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6167 IDirectDrawSurface4_Release(surface);
6169 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
6170 * AMD r500, evergreen). Windows XP, at least on AMD r200, does not. */
6171 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
6174 IDirectDrawSurface4_Release(target);
6175 IDirectDraw4_Release(ddraw);
6176 IDirect3D3_Release(d3d);
6177 IDirect3DDevice3_Release(device);
6178 DestroyWindow(window);
6181 static void fill_surface(IDirectDrawSurface4 *surface, D3DCOLOR color)
6183 DDSURFACEDESC2 surface_desc = {sizeof(surface_desc)};
6184 HRESULT hr;
6185 unsigned int x, y;
6186 DWORD *ptr;
6188 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
6189 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6191 for (y = 0; y < surface_desc.dwHeight; ++y)
6193 ptr = (DWORD *)((BYTE *)surface_desc.lpSurface + y * surface_desc.lPitch);
6194 for (x = 0; x < surface_desc.dwWidth; ++x)
6196 ptr[x] = color;
6200 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6201 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6204 static void test_flip(void)
6206 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
6207 IDirectDrawSurface4 *frontbuffer, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
6208 DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}};
6209 DDSURFACEDESC2 surface_desc;
6210 BOOL sysmem_primary;
6211 IDirectDraw4 *ddraw;
6212 DWORD expected_caps;
6213 unsigned int i;
6214 D3DCOLOR color;
6215 ULONG refcount;
6216 HWND window;
6217 HRESULT hr;
6219 static const struct
6221 const char *name;
6222 DWORD caps;
6224 test_data[] =
6226 {"PRIMARYSURFACE", DDSCAPS_PRIMARYSURFACE},
6227 {"OFFSCREENPLAIN", DDSCAPS_OFFSCREENPLAIN},
6228 {"TEXTURE", DDSCAPS_TEXTURE},
6231 window = create_window();
6232 ddraw = create_ddraw();
6233 ok(!!ddraw, "Failed to create a ddraw object.\n");
6235 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6236 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6238 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6240 /* Creating a flippable texture induces a BSoD on some versions of the
6241 * Intel graphics driver. At least Intel GMA 950 with driver version
6242 * 6.14.10.4926 on Windows XP SP3 is affected. */
6243 if ((test_data[i].caps & DDSCAPS_TEXTURE) && ddraw_is_intel(ddraw))
6245 win_skip("Skipping flippable texture test.\n");
6246 continue;
6249 memset(&surface_desc, 0, sizeof(surface_desc));
6250 surface_desc.dwSize = sizeof(surface_desc);
6251 surface_desc.dwFlags = DDSD_CAPS;
6252 if (!(test_data[i].caps & DDSCAPS_PRIMARYSURFACE))
6253 surface_desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6254 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
6255 surface_desc.dwWidth = 512;
6256 surface_desc.dwHeight = 512;
6257 U5(surface_desc).dwBackBufferCount = 3;
6258 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6259 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6261 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
6262 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
6263 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6264 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6266 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
6267 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
6268 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6269 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6271 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
6272 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6273 todo_wine_if(test_data[i].caps & DDSCAPS_TEXTURE)
6274 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
6275 if (FAILED(hr))
6276 continue;
6278 memset(&surface_desc, 0, sizeof(surface_desc));
6279 surface_desc.dwSize = sizeof(surface_desc);
6280 hr = IDirectDrawSurface4_GetSurfaceDesc(frontbuffer, &surface_desc);
6281 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6282 expected_caps = DDSCAPS_FRONTBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
6283 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
6284 expected_caps |= DDSCAPS_VISIBLE;
6285 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6286 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6287 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
6289 hr = IDirectDrawSurface4_GetAttachedSurface(frontbuffer, &caps, &backbuffer1);
6290 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6291 memset(&surface_desc, 0, sizeof(surface_desc));
6292 surface_desc.dwSize = sizeof(surface_desc);
6293 hr = IDirectDrawSurface4_GetSurfaceDesc(backbuffer1, &surface_desc);
6294 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6295 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6296 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6297 expected_caps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER);
6298 expected_caps |= DDSCAPS_BACKBUFFER;
6299 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6300 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6302 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
6303 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6304 memset(&surface_desc, 0, sizeof(surface_desc));
6305 surface_desc.dwSize = sizeof(surface_desc);
6306 hr = IDirectDrawSurface4_GetSurfaceDesc(backbuffer2, &surface_desc);
6307 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6308 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6309 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6310 expected_caps &= ~DDSCAPS_BACKBUFFER;
6311 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6312 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6314 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
6315 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6316 memset(&surface_desc, 0, sizeof(surface_desc));
6317 surface_desc.dwSize = sizeof(surface_desc);
6318 hr = IDirectDrawSurface4_GetSurfaceDesc(backbuffer3, &surface_desc);
6319 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6320 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6321 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6322 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6323 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6325 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer3, &caps, &surface);
6326 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6327 ok(surface == frontbuffer, "%s: Got unexpected surface %p, expected %p.\n",
6328 test_data[i].name, surface, frontbuffer);
6329 IDirectDrawSurface4_Release(surface);
6331 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
6332 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
6333 hr = IDirectDrawSurface4_IsLost(frontbuffer);
6334 ok(hr == DD_OK, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6335 hr = IDirectDrawSurface4_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6336 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
6337 ok(hr == DDERR_NOEXCLUSIVEMODE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6338 else
6339 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6340 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6341 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
6342 hr = IDirectDrawSurface4_IsLost(frontbuffer);
6343 todo_wine ok(hr == DDERR_SURFACELOST, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6344 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
6345 ok(SUCCEEDED(hr), "%s: Failed to restore surfaces, hr %#x.\n", test_data[i].name, hr);
6347 memset(&surface_desc, 0, sizeof(surface_desc));
6348 surface_desc.dwSize = sizeof(surface_desc);
6349 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6350 surface_desc.ddsCaps.dwCaps = 0;
6351 surface_desc.dwWidth = 640;
6352 surface_desc.dwHeight = 480;
6353 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6354 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
6355 hr = IDirectDrawSurface4_Flip(frontbuffer, surface, DDFLIP_WAIT);
6356 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6357 IDirectDrawSurface4_Release(surface);
6359 hr = IDirectDrawSurface4_Flip(frontbuffer, frontbuffer, DDFLIP_WAIT);
6360 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6361 hr = IDirectDrawSurface4_Flip(backbuffer1, NULL, DDFLIP_WAIT);
6362 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6363 hr = IDirectDrawSurface4_Flip(backbuffer2, NULL, DDFLIP_WAIT);
6364 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6365 hr = IDirectDrawSurface4_Flip(backbuffer3, NULL, DDFLIP_WAIT);
6366 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6368 /* The Nvidia Geforce 7 driver cannot do a color fill on a texture backbuffer after
6369 * the backbuffer has been locked. Do it ourselves as a workaround. Unlike ddraw1
6370 * and 2 GetSurfaceDesc does not cause issues in ddraw4 and ddraw7. */
6371 fill_surface(backbuffer1, 0xffff0000);
6372 fill_surface(backbuffer2, 0xff00ff00);
6373 fill_surface(backbuffer3, 0xff0000ff);
6375 hr = IDirectDrawSurface4_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6376 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6377 color = get_surface_color(backbuffer1, 320, 240);
6378 /* The testbot seems to just copy the contents of one surface to all the
6379 * others, instead of properly flipping. */
6380 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6381 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6382 color = get_surface_color(backbuffer2, 320, 240);
6383 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6384 fill_surface(backbuffer3, 0xffff0000);
6386 hr = IDirectDrawSurface4_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6387 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6388 color = get_surface_color(backbuffer1, 320, 240);
6389 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6390 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6391 color = get_surface_color(backbuffer2, 320, 240);
6392 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6393 fill_surface(backbuffer3, 0xff00ff00);
6395 hr = IDirectDrawSurface4_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6396 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6397 color = get_surface_color(backbuffer1, 320, 240);
6398 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6399 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6400 color = get_surface_color(backbuffer2, 320, 240);
6401 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6402 fill_surface(backbuffer3, 0xff0000ff);
6404 hr = IDirectDrawSurface4_Flip(frontbuffer, backbuffer1, DDFLIP_WAIT);
6405 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6406 color = get_surface_color(backbuffer2, 320, 240);
6407 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6408 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6409 color = get_surface_color(backbuffer3, 320, 240);
6410 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6411 fill_surface(backbuffer1, 0xffff0000);
6413 hr = IDirectDrawSurface4_Flip(frontbuffer, backbuffer2, DDFLIP_WAIT);
6414 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6415 color = get_surface_color(backbuffer1, 320, 240);
6416 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6417 color = get_surface_color(backbuffer3, 320, 240);
6418 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6419 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6420 fill_surface(backbuffer2, 0xff00ff00);
6422 hr = IDirectDrawSurface4_Flip(frontbuffer, backbuffer3, DDFLIP_WAIT);
6423 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6424 color = get_surface_color(backbuffer1, 320, 240);
6425 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6426 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6427 color = get_surface_color(backbuffer2, 320, 240);
6428 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6430 IDirectDrawSurface4_Release(backbuffer3);
6431 IDirectDrawSurface4_Release(backbuffer2);
6432 IDirectDrawSurface4_Release(backbuffer1);
6433 IDirectDrawSurface4_Release(frontbuffer);
6436 refcount = IDirectDraw4_Release(ddraw);
6437 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6438 DestroyWindow(window);
6441 static void reset_ddsd(DDSURFACEDESC2 *ddsd)
6443 memset(ddsd, 0, sizeof(*ddsd));
6444 ddsd->dwSize = sizeof(*ddsd);
6447 static void test_set_surface_desc(void)
6449 IDirectDraw4 *ddraw;
6450 HWND window;
6451 HRESULT hr;
6452 DDSURFACEDESC2 ddsd;
6453 IDirectDrawSurface4 *surface;
6454 BYTE data[16*16*4];
6455 ULONG ref;
6456 unsigned int i;
6457 static const struct
6459 DWORD caps, caps2;
6460 BOOL supported;
6461 const char *name;
6463 invalid_caps_tests[] =
6465 {DDSCAPS_VIDEOMEMORY, 0, FALSE, "videomemory plain"},
6466 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, TRUE, "systemmemory texture"},
6467 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE, "managed texture"},
6468 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE, "managed texture"},
6469 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, 0, FALSE, "systemmemory primary"},
6472 window = create_window();
6473 ddraw = create_ddraw();
6474 ok(!!ddraw, "Failed to create a ddraw object.\n");
6475 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6476 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6478 reset_ddsd(&ddsd);
6479 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6480 ddsd.dwWidth = 8;
6481 ddsd.dwHeight = 8;
6482 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6483 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6484 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6485 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6486 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6487 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6488 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6490 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6491 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6493 reset_ddsd(&ddsd);
6494 ddsd.dwFlags = DDSD_LPSURFACE;
6495 ddsd.lpSurface = data;
6496 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6497 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6499 /* Redundantly setting the same lpSurface is not an error. */
6500 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6501 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6502 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6503 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6504 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6505 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
6507 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, 0, NULL);
6508 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6509 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6510 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
6511 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6512 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6514 reset_ddsd(&ddsd);
6515 ddsd.dwFlags = DDSD_LPSURFACE;
6516 ddsd.lpSurface = data;
6517 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 1);
6518 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
6520 ddsd.lpSurface = NULL;
6521 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6522 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
6524 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, NULL, 0);
6525 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
6527 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6528 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6529 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6530 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6531 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6533 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
6534 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6535 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
6537 ddsd.dwFlags = DDSD_CAPS;
6538 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6539 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
6541 /* dwCaps = 0 is allowed, but ignored. Caps2 can be anything and is ignored too. */
6542 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
6543 ddsd.lpSurface = data;
6544 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6545 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6546 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6547 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6548 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6549 ddsd.ddsCaps.dwCaps = 0;
6550 ddsd.ddsCaps.dwCaps2 = 0xdeadbeef;
6551 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6552 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6554 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6555 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6556 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6557 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6558 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6560 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
6561 reset_ddsd(&ddsd);
6562 ddsd.dwFlags = DDSD_HEIGHT;
6563 ddsd.dwHeight = 16;
6564 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6565 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
6567 ddsd.lpSurface = data;
6568 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
6569 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6570 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6572 ddsd.dwHeight = 0;
6573 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6574 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
6576 reset_ddsd(&ddsd);
6577 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6578 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
6579 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6580 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6582 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0 */
6583 reset_ddsd(&ddsd);
6584 ddsd.dwFlags = DDSD_PITCH;
6585 U1(ddsd).lPitch = 8 * 4;
6586 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6587 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
6589 ddsd.dwFlags = DDSD_WIDTH;
6590 ddsd.dwWidth = 16;
6591 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6592 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
6594 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
6595 ddsd.lpSurface = data;
6596 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6597 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
6599 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
6600 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6601 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
6603 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6604 U1(ddsd).lPitch = 16 * 4;
6605 ddsd.dwWidth = 16;
6606 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6607 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6609 reset_ddsd(&ddsd);
6610 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6611 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6612 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6613 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6614 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
6616 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
6618 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
6619 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6620 U1(ddsd).lPitch = 4 * 4;
6621 ddsd.lpSurface = data;
6622 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6623 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
6625 U1(ddsd).lPitch = 4;
6626 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6627 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
6629 U1(ddsd).lPitch = 16 * 4 + 1;
6630 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6631 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
6633 U1(ddsd).lPitch = 16 * 4 + 3;
6634 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6635 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
6637 U1(ddsd).lPitch = -4;
6638 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6639 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
6641 U1(ddsd).lPitch = 16 * 4;
6642 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6643 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6645 reset_ddsd(&ddsd);
6646 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6647 U1(ddsd).lPitch = 0;
6648 ddsd.dwWidth = 16;
6649 ddsd.lpSurface = data;
6650 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6651 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
6653 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6654 U1(ddsd).lPitch = 16 * 4;
6655 ddsd.dwWidth = 0;
6656 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6657 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
6659 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
6660 ddsd.dwFlags = DDSD_PIXELFORMAT;
6661 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6662 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6663 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6664 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6665 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6666 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6667 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6668 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
6670 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
6671 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6672 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6674 /* Can't set color keys. */
6675 reset_ddsd(&ddsd);
6676 ddsd.dwFlags = DDSD_CKSRCBLT;
6677 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
6678 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
6679 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6680 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
6682 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
6683 ddsd.lpSurface = data;
6684 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6685 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
6687 IDirectDrawSurface4_Release(surface);
6689 /* SetSurfaceDesc needs systemmemory surfaces.
6691 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing DDSD_LINEARSIZE is moot. */
6692 for (i = 0; i < ARRAY_SIZE(invalid_caps_tests); i++)
6694 reset_ddsd(&ddsd);
6695 ddsd.dwFlags = DDSD_CAPS;
6696 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
6697 ddsd.ddsCaps.dwCaps2 = invalid_caps_tests[i].caps2;
6698 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
6700 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6701 ddsd.dwWidth = 8;
6702 ddsd.dwHeight = 8;
6703 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6704 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6705 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6706 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6707 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6708 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6711 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6712 ok(SUCCEEDED(hr) || hr == DDERR_NODIRECTDRAWHW, "Failed to create surface, hr %#x.\n", hr);
6713 if (FAILED(hr))
6715 skip("Cannot create a %s surface, skipping vidmem SetSurfaceDesc test.\n",
6716 invalid_caps_tests[i].name);
6717 goto done;
6720 reset_ddsd(&ddsd);
6721 ddsd.dwFlags = DDSD_LPSURFACE;
6722 ddsd.lpSurface = data;
6723 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6724 if (invalid_caps_tests[i].supported)
6726 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6728 else
6730 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
6731 invalid_caps_tests[i].name, hr);
6733 /* Check priority of error conditions. */
6734 ddsd.dwFlags = DDSD_WIDTH;
6735 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6736 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
6737 invalid_caps_tests[i].name, hr);
6740 IDirectDrawSurface4_Release(surface);
6743 done:
6744 ref = IDirectDraw4_Release(ddraw);
6745 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6746 DestroyWindow(window);
6749 static void test_user_memory_getdc(void)
6751 IDirectDraw4 *ddraw;
6752 HWND window;
6753 HRESULT hr;
6754 DDSURFACEDESC2 ddsd;
6755 IDirectDrawSurface4 *surface;
6756 DWORD data[16][16];
6757 HBITMAP bitmap;
6758 DIBSECTION dib;
6759 ULONG ref;
6760 int size;
6761 HDC dc;
6762 unsigned int x, y;
6764 window = create_window();
6765 ddraw = create_ddraw();
6766 ok(!!ddraw, "Failed to create a ddraw object.\n");
6768 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6769 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6771 reset_ddsd(&ddsd);
6772 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6773 ddsd.dwWidth = 16;
6774 ddsd.dwHeight = 16;
6775 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6776 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6777 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6778 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6779 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6780 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6781 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6782 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6783 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6785 memset(data, 0xaa, sizeof(data));
6786 reset_ddsd(&ddsd);
6787 ddsd.dwFlags = DDSD_LPSURFACE;
6788 ddsd.lpSurface = data;
6789 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6790 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6792 hr = IDirectDrawSurface4_GetDC(surface, &dc);
6793 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6794 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
6795 ok(!!bitmap, "Failed to get bitmap.\n");
6796 size = GetObjectA(bitmap, sizeof(dib), &dib);
6797 ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
6798 ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
6799 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
6800 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
6801 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
6802 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6804 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
6805 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
6807 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
6808 ddsd.lpSurface = data;
6809 ddsd.dwWidth = 4;
6810 ddsd.dwHeight = 8;
6811 U1(ddsd).lPitch = sizeof(*data);
6812 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6813 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6815 memset(data, 0xaa, sizeof(data));
6816 hr = IDirectDrawSurface4_GetDC(surface, &dc);
6817 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6818 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
6819 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
6820 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
6821 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6823 for (y = 0; y < 4; y++)
6825 for (x = 0; x < 4; x++)
6827 if ((x == 1 || x == 2) && (y == 1 || y == 2))
6828 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
6829 x, y, data[y][x]);
6830 else
6831 ok(data[y][x] == 0x00000000, "Expected color 0x00000000 on position %ux%u, got %#x.\n",
6832 x, y, data[y][x]);
6835 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
6836 data[0][5]);
6837 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
6838 data[7][3]);
6839 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
6840 data[7][4]);
6841 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
6842 data[8][0]);
6844 IDirectDrawSurface4_Release(surface);
6845 ref = IDirectDraw4_Release(ddraw);
6846 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6847 DestroyWindow(window);
6850 static void test_sysmem_overlay(void)
6852 IDirectDraw4 *ddraw;
6853 HWND window;
6854 HRESULT hr;
6855 DDSURFACEDESC2 ddsd;
6856 IDirectDrawSurface4 *surface;
6857 ULONG ref;
6859 window = create_window();
6860 ddraw = create_ddraw();
6861 ok(!!ddraw, "Failed to create a ddraw object.\n");
6863 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6864 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6866 reset_ddsd(&ddsd);
6867 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
6868 ddsd.dwWidth = 16;
6869 ddsd.dwHeight = 16;
6870 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
6871 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6872 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6873 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6874 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6875 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6876 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6877 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6878 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
6880 ref = IDirectDraw4_Release(ddraw);
6881 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6882 DestroyWindow(window);
6885 static void test_primary_palette(void)
6887 DDSCAPS2 surface_caps = {DDSCAPS_FLIP, 0, 0, {0}};
6888 IDirectDrawSurface4 *primary, *backbuffer;
6889 PALETTEENTRY palette_entries[256];
6890 IDirectDrawPalette *palette, *tmp;
6891 DDSURFACEDESC2 surface_desc;
6892 IDirectDraw4 *ddraw;
6893 DWORD palette_caps;
6894 ULONG refcount;
6895 HWND window;
6896 HRESULT hr;
6898 window = create_window();
6899 ddraw = create_ddraw();
6900 ok(!!ddraw, "Failed to create a ddraw object.\n");
6901 if (FAILED(IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
6903 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
6904 IDirectDraw4_Release(ddraw);
6905 DestroyWindow(window);
6906 return;
6908 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6909 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6911 memset(&surface_desc, 0, sizeof(surface_desc));
6912 surface_desc.dwSize = sizeof(surface_desc);
6913 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
6914 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
6915 U5(surface_desc).dwBackBufferCount = 1;
6916 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
6917 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6918 hr = IDirectDrawSurface4_GetAttachedSurface(primary, &surface_caps, &backbuffer);
6919 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
6921 memset(palette_entries, 0, sizeof(palette_entries));
6922 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
6923 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6924 refcount = get_refcount((IUnknown *)palette);
6925 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6927 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6928 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6929 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
6931 hr = IDirectDrawSurface4_SetPalette(primary, palette);
6932 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6934 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
6935 * and is generally somewhat broken with respect to 8 bpp / palette
6936 * handling. */
6937 if (SUCCEEDED(IDirectDrawSurface4_GetPalette(backbuffer, &tmp)))
6939 win_skip("Broken palette handling detected, skipping tests.\n");
6940 IDirectDrawPalette_Release(tmp);
6941 IDirectDrawPalette_Release(palette);
6942 /* The Windows 8 testbot keeps extra references to the primary and
6943 * backbuffer while in 8 bpp mode. */
6944 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
6945 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
6946 goto done;
6949 refcount = get_refcount((IUnknown *)palette);
6950 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6952 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6953 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6954 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
6955 "Got unexpected palette caps %#x.\n", palette_caps);
6957 hr = IDirectDrawSurface4_SetPalette(primary, NULL);
6958 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6959 refcount = get_refcount((IUnknown *)palette);
6960 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6962 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6963 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6964 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
6966 hr = IDirectDrawSurface4_SetPalette(primary, palette);
6967 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6968 refcount = get_refcount((IUnknown *)palette);
6969 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6971 hr = IDirectDrawSurface4_GetPalette(primary, &tmp);
6972 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
6973 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
6974 IDirectDrawPalette_Release(tmp);
6975 hr = IDirectDrawSurface4_GetPalette(backbuffer, &tmp);
6976 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6978 refcount = IDirectDrawPalette_Release(palette);
6979 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6980 refcount = IDirectDrawPalette_Release(palette);
6981 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6983 /* Note that this only seems to work when the palette is attached to the
6984 * primary surface. When attached to a regular surface, attempting to get
6985 * the palette here will cause an access violation. */
6986 hr = IDirectDrawSurface4_GetPalette(primary, &tmp);
6987 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6989 hr = IDirectDrawSurface4_IsLost(primary);
6990 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6992 memset(&surface_desc, 0, sizeof(surface_desc));
6993 surface_desc.dwSize = sizeof(surface_desc);
6994 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &surface_desc);
6995 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6996 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
6997 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
6998 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 8, "Got unexpected bit count %u.\n",
6999 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
7001 hr = set_display_mode(ddraw, 640, 480);
7002 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
7004 memset(&surface_desc, 0, sizeof(surface_desc));
7005 surface_desc.dwSize = sizeof(surface_desc);
7006 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &surface_desc);
7007 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7008 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
7009 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
7010 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
7011 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
7012 "Got unexpected bit count %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
7014 hr = IDirectDrawSurface4_IsLost(primary);
7015 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7016 hr = IDirectDrawSurface4_Restore(primary);
7017 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
7018 hr = IDirectDrawSurface4_IsLost(primary);
7019 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7021 memset(&surface_desc, 0, sizeof(surface_desc));
7022 surface_desc.dwSize = sizeof(surface_desc);
7023 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &surface_desc);
7024 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7025 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
7026 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
7027 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
7028 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
7029 "Got unexpected bit count %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
7031 done:
7032 refcount = IDirectDrawSurface4_Release(backbuffer);
7033 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7034 refcount = IDirectDrawSurface4_Release(primary);
7035 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7036 refcount = IDirectDraw4_Release(ddraw);
7037 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7038 DestroyWindow(window);
7041 static HRESULT WINAPI surface_counter(IDirectDrawSurface4 *surface, DDSURFACEDESC2 *desc, void *context)
7043 UINT *surface_count = context;
7045 ++(*surface_count);
7046 IDirectDrawSurface_Release(surface);
7048 return DDENUMRET_OK;
7051 static void test_surface_attachment(void)
7053 IDirectDrawSurface4 *surface1, *surface2, *surface3, *surface4;
7054 IDirectDrawSurface *surface1v1, *surface2v1;
7055 DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, {0}};
7056 DDSURFACEDESC2 surface_desc;
7057 IDirectDraw4 *ddraw;
7058 UINT surface_count;
7059 ULONG refcount;
7060 HWND window;
7061 HRESULT hr;
7063 window = create_window();
7064 ddraw = create_ddraw();
7065 ok(!!ddraw, "Failed to create a ddraw object.\n");
7066 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7067 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7069 memset(&surface_desc, 0, sizeof(surface_desc));
7070 surface_desc.dwSize = sizeof(surface_desc);
7071 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
7072 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7073 U2(surface_desc).dwMipMapCount = 3;
7074 surface_desc.dwWidth = 128;
7075 surface_desc.dwHeight = 128;
7076 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7077 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7079 hr = IDirectDrawSurface4_GetAttachedSurface(surface1, &caps, &surface2);
7080 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
7081 hr = IDirectDrawSurface4_GetAttachedSurface(surface2, &caps, &surface3);
7082 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
7083 hr = IDirectDrawSurface4_GetAttachedSurface(surface3, &caps, &surface4);
7084 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7086 surface_count = 0;
7087 IDirectDrawSurface4_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
7088 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
7089 surface_count = 0;
7090 IDirectDrawSurface4_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
7091 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
7092 surface_count = 0;
7093 IDirectDrawSurface4_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
7094 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
7096 memset(&surface_desc, 0, sizeof(surface_desc));
7097 surface_desc.dwSize = sizeof(surface_desc);
7098 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7099 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
7100 surface_desc.dwWidth = 16;
7101 surface_desc.dwHeight = 16;
7102 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7103 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7105 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface4);
7106 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7107 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface1);
7108 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7109 hr = IDirectDrawSurface4_AddAttachedSurface(surface3, surface4);
7110 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7111 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface3);
7112 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7113 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface4);
7114 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7115 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface2);
7116 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7118 IDirectDrawSurface4_Release(surface4);
7120 memset(&surface_desc, 0, sizeof(surface_desc));
7121 surface_desc.dwSize = sizeof(surface_desc);
7122 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7123 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7124 surface_desc.dwWidth = 16;
7125 surface_desc.dwHeight = 16;
7126 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7127 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7129 if (SUCCEEDED(hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface4)))
7131 skip("Running on refrast, skipping some tests.\n");
7132 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface4);
7133 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7135 else
7137 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7138 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface1);
7139 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7140 hr = IDirectDrawSurface4_AddAttachedSurface(surface3, surface4);
7141 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7142 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface3);
7143 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7144 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface4);
7145 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7146 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface2);
7147 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7150 IDirectDrawSurface4_Release(surface4);
7151 IDirectDrawSurface4_Release(surface3);
7152 IDirectDrawSurface4_Release(surface2);
7153 IDirectDrawSurface4_Release(surface1);
7155 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7156 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7158 /* Try a single primary and two offscreen plain surfaces. */
7159 memset(&surface_desc, 0, sizeof(surface_desc));
7160 surface_desc.dwSize = sizeof(surface_desc);
7161 surface_desc.dwFlags = DDSD_CAPS;
7162 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7163 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7164 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7166 memset(&surface_desc, 0, sizeof(surface_desc));
7167 surface_desc.dwSize = sizeof(surface_desc);
7168 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7169 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7170 surface_desc.dwWidth = registry_mode.dmPelsWidth;
7171 surface_desc.dwHeight = registry_mode.dmPelsHeight;
7172 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7173 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7175 memset(&surface_desc, 0, sizeof(surface_desc));
7176 surface_desc.dwSize = sizeof(surface_desc);
7177 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7178 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7179 surface_desc.dwWidth = registry_mode.dmPelsWidth;
7180 surface_desc.dwHeight = registry_mode.dmPelsHeight;
7181 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7182 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7184 /* This one has a different size. */
7185 memset(&surface_desc, 0, sizeof(surface_desc));
7186 surface_desc.dwSize = sizeof(surface_desc);
7187 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7188 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7189 surface_desc.dwWidth = 128;
7190 surface_desc.dwHeight = 128;
7191 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7192 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7194 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface2);
7195 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7196 /* Try the reverse without detaching first. */
7197 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface1);
7198 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
7199 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
7200 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7202 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface1);
7203 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7204 /* Try to detach reversed. */
7205 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
7206 ok(hr == DDERR_CANNOTDETACHSURFACE, "Got unexpected hr %#x.\n", hr);
7207 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface2, 0, surface1);
7208 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7210 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface3);
7211 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7212 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface2, 0, surface3);
7213 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7215 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface4);
7216 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7217 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface1);
7218 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7220 IDirectDrawSurface4_Release(surface4);
7221 IDirectDrawSurface4_Release(surface3);
7222 IDirectDrawSurface4_Release(surface2);
7223 IDirectDrawSurface4_Release(surface1);
7225 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
7226 memset(&surface_desc, 0, sizeof(surface_desc));
7227 surface_desc.dwSize = sizeof(surface_desc);
7228 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7229 surface_desc.dwWidth = 64;
7230 surface_desc.dwHeight = 64;
7231 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
7232 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7233 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
7234 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
7235 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
7236 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
7237 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
7238 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7239 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7240 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7241 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7243 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
7244 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
7245 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
7246 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
7247 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7248 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7250 hr = IDirectDrawSurface4_QueryInterface(surface1, &IID_IDirectDrawSurface, (void **)&surface1v1);
7251 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
7252 hr = IDirectDrawSurface4_QueryInterface(surface2, &IID_IDirectDrawSurface, (void **)&surface2v1);
7253 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
7255 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface2);
7256 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7257 refcount = get_refcount((IUnknown *)surface2);
7258 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7259 refcount = get_refcount((IUnknown *)surface2v1);
7260 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7261 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface2);
7262 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
7263 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7264 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7265 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
7266 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
7268 /* Attaching while already attached to other surface. */
7269 hr = IDirectDrawSurface4_AddAttachedSurface(surface3, surface2);
7270 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7271 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface3, 0, surface2);
7272 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7273 IDirectDrawSurface4_Release(surface3);
7275 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
7276 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7277 refcount = get_refcount((IUnknown *)surface2);
7278 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7279 refcount = get_refcount((IUnknown *)surface2v1);
7280 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7282 /* DeleteAttachedSurface() when attaching via IDirectDrawSurface. */
7283 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7284 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7285 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
7286 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
7287 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
7288 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7289 refcount = IDirectDrawSurface4_Release(surface2);
7290 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7291 refcount = IDirectDrawSurface4_Release(surface1);
7292 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7294 /* Automatic detachment on release. */
7295 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7296 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7297 refcount = get_refcount((IUnknown *)surface2v1);
7298 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7299 refcount = IDirectDrawSurface_Release(surface1v1);
7300 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7301 refcount = IDirectDrawSurface_Release(surface2v1);
7302 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7303 refcount = IDirectDraw4_Release(ddraw);
7304 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7305 DestroyWindow(window);
7308 static void test_private_data(void)
7310 IDirectDraw4 *ddraw;
7311 IDirectDrawSurface4 *surface, *surface2;
7312 DDSURFACEDESC2 surface_desc;
7313 ULONG refcount, refcount2, refcount3;
7314 IUnknown *ptr;
7315 DWORD size = sizeof(ptr);
7316 HRESULT hr;
7317 HWND window;
7318 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7319 DWORD data[] = {1, 2, 3, 4};
7320 DDCAPS hal_caps;
7321 static const GUID ddraw_private_data_test_guid =
7323 0xfdb37466,
7324 0x428f,
7325 0x4edf,
7326 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
7328 static const GUID ddraw_private_data_test_guid2 =
7330 0x2e5afac2,
7331 0x87b5,
7332 0x4c10,
7333 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
7336 window = create_window();
7337 ddraw = create_ddraw();
7338 ok(!!ddraw, "Failed to create a ddraw object.\n");
7339 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7340 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7342 reset_ddsd(&surface_desc);
7343 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
7344 surface_desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
7345 surface_desc.dwHeight = 4;
7346 surface_desc.dwWidth = 4;
7347 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7348 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7350 /* NULL pointers are not valid, but don't cause a crash. */
7351 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL,
7352 sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
7353 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7354 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 0, 0);
7355 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7356 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 1, 0);
7357 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7359 /* DDSPD_IUNKNOWNPOINTER needs sizeof(IUnknown *) bytes of data. */
7360 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7361 0, DDSPD_IUNKNOWNPOINTER);
7362 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7363 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7364 5, DDSPD_IUNKNOWNPOINTER);
7365 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7366 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7367 sizeof(ddraw) * 2, DDSPD_IUNKNOWNPOINTER);
7368 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7370 /* Note that with a size != 0 and size != sizeof(IUnknown *) and
7371 * DDSPD_IUNKNOWNPOINTER set SetPrivateData in ddraw4 and ddraw7
7372 * erases the old content and returns an error. This behavior has
7373 * been fixed in d3d8 and d3d9. Unless an application is found
7374 * that depends on this we don't care about this behavior. */
7375 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7376 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7377 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7378 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7379 0, DDSPD_IUNKNOWNPOINTER);
7380 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7381 size = sizeof(ptr);
7382 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7383 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7384 hr = IDirectDrawSurface4_FreePrivateData(surface, &ddraw_private_data_test_guid);
7385 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7387 refcount = get_refcount((IUnknown *)ddraw);
7388 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7389 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7390 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7391 refcount2 = get_refcount((IUnknown *)ddraw);
7392 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
7394 hr = IDirectDrawSurface4_FreePrivateData(surface, &ddraw_private_data_test_guid);
7395 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7396 refcount2 = get_refcount((IUnknown *)ddraw);
7397 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
7399 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7400 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7401 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7402 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, surface,
7403 sizeof(surface), DDSPD_IUNKNOWNPOINTER);
7404 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7405 refcount2 = get_refcount((IUnknown *)ddraw);
7406 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
7408 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7409 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7410 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7411 size = 2 * sizeof(ptr);
7412 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7413 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7414 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7415 refcount2 = get_refcount(ptr);
7416 /* Object is NOT addref'ed by the getter. */
7417 ok(ptr == (IUnknown *)ddraw, "Returned interface pointer is %p, expected %p.\n", ptr, ddraw);
7418 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
7420 ptr = (IUnknown *)0xdeadbeef;
7421 size = 1;
7422 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
7423 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7424 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7425 size = 2 * sizeof(ptr);
7426 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
7427 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7428 ok(size == 2 * sizeof(ptr), "Got unexpected size %u.\n", size);
7429 size = 1;
7430 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7431 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7432 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7433 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7434 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid2, NULL, NULL);
7435 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7436 size = 0xdeadbabe;
7437 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid2, &ptr, &size);
7438 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7439 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7440 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
7441 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, NULL);
7442 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7444 refcount3 = IDirectDrawSurface4_Release(surface);
7445 ok(!refcount3, "Got unexpected refcount %u.\n", refcount3);
7447 /* Destroying the surface frees the reference held on the private data. It also frees
7448 * the reference the surface is holding on its creating object. */
7449 refcount2 = get_refcount((IUnknown *)ddraw);
7450 ok(refcount2 == refcount - 1, "Got unexpected refcount %u.\n", refcount2);
7452 memset(&hal_caps, 0, sizeof(hal_caps));
7453 hal_caps.dwSize = sizeof(hal_caps);
7454 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
7455 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7456 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) == (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
7458 reset_ddsd(&surface_desc);
7459 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT;
7460 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7461 surface_desc.dwHeight = 4;
7462 surface_desc.dwWidth = 4;
7463 U2(surface_desc).dwMipMapCount = 2;
7464 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7465 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7466 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &surface2);
7467 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7469 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, data, sizeof(data), 0);
7470 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7471 hr = IDirectDrawSurface4_GetPrivateData(surface2, &ddraw_private_data_test_guid, NULL, NULL);
7472 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7474 IDirectDrawSurface4_Release(surface2);
7475 IDirectDrawSurface4_Release(surface);
7477 else
7478 skip("Mipmapped textures not supported, skipping mipmap private data test.\n");
7480 refcount = IDirectDraw4_Release(ddraw);
7481 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7482 DestroyWindow(window);
7485 static void test_pixel_format(void)
7487 HWND window, window2 = NULL;
7488 HDC hdc, hdc2 = NULL;
7489 HMODULE gl = NULL;
7490 int format, test_format;
7491 PIXELFORMATDESCRIPTOR pfd;
7492 IDirectDraw4 *ddraw = NULL;
7493 IDirectDrawClipper *clipper = NULL;
7494 DDSURFACEDESC2 ddsd;
7495 IDirectDrawSurface4 *primary = NULL;
7496 DDBLTFX fx;
7497 HRESULT hr;
7499 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7500 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7501 if (!window)
7503 skip("Failed to create window\n");
7504 return;
7507 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7508 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7510 hdc = GetDC(window);
7511 if (!hdc)
7513 skip("Failed to get DC\n");
7514 goto cleanup;
7517 if (window2)
7518 hdc2 = GetDC(window2);
7520 gl = LoadLibraryA("opengl32.dll");
7521 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
7523 format = GetPixelFormat(hdc);
7524 ok(format == 0, "new window has pixel format %d\n", format);
7526 ZeroMemory(&pfd, sizeof(pfd));
7527 pfd.nSize = sizeof(pfd);
7528 pfd.nVersion = 1;
7529 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
7530 pfd.iPixelType = PFD_TYPE_RGBA;
7531 pfd.iLayerType = PFD_MAIN_PLANE;
7532 format = ChoosePixelFormat(hdc, &pfd);
7533 if (format <= 0)
7535 skip("no pixel format available\n");
7536 goto cleanup;
7539 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
7541 skip("failed to set pixel format\n");
7542 goto cleanup;
7545 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
7547 skip("failed to set pixel format on second window\n");
7548 if (hdc2)
7550 ReleaseDC(window2, hdc2);
7551 hdc2 = NULL;
7555 ddraw = create_ddraw();
7556 ok(!!ddraw, "Failed to create a ddraw object.\n");
7558 test_format = GetPixelFormat(hdc);
7559 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7561 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7562 if (FAILED(hr))
7564 skip("Failed to set cooperative level, hr %#x.\n", hr);
7565 goto cleanup;
7568 test_format = GetPixelFormat(hdc);
7569 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7571 if (hdc2)
7573 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL);
7574 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
7575 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
7576 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
7578 test_format = GetPixelFormat(hdc);
7579 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7581 test_format = GetPixelFormat(hdc2);
7582 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7585 memset(&ddsd, 0, sizeof(ddsd));
7586 ddsd.dwSize = sizeof(ddsd);
7587 ddsd.dwFlags = DDSD_CAPS;
7588 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7590 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
7591 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
7593 test_format = GetPixelFormat(hdc);
7594 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7596 if (hdc2)
7598 test_format = GetPixelFormat(hdc2);
7599 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7602 if (clipper)
7604 hr = IDirectDrawSurface4_SetClipper(primary, clipper);
7605 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
7607 test_format = GetPixelFormat(hdc);
7608 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7610 test_format = GetPixelFormat(hdc2);
7611 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7614 memset(&fx, 0, sizeof(fx));
7615 fx.dwSize = sizeof(fx);
7616 hr = IDirectDrawSurface4_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7617 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
7619 test_format = GetPixelFormat(hdc);
7620 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7622 if (hdc2)
7624 test_format = GetPixelFormat(hdc2);
7625 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7628 cleanup:
7629 if (primary) IDirectDrawSurface4_Release(primary);
7630 if (clipper) IDirectDrawClipper_Release(clipper);
7631 if (ddraw) IDirectDraw4_Release(ddraw);
7632 if (gl) FreeLibrary(gl);
7633 if (hdc) ReleaseDC(window, hdc);
7634 if (hdc2) ReleaseDC(window2, hdc2);
7635 if (window) DestroyWindow(window);
7636 if (window2) DestroyWindow(window2);
7639 static void test_create_surface_pitch(void)
7641 IDirectDrawSurface4 *surface;
7642 DDSURFACEDESC2 surface_desc;
7643 IDirectDraw4 *ddraw;
7644 unsigned int i;
7645 ULONG refcount;
7646 HWND window;
7647 HRESULT hr;
7648 void *mem;
7650 static const struct
7652 DWORD caps;
7653 DWORD flags_in;
7654 DWORD pitch_in;
7655 HRESULT hr;
7656 DWORD flags_out;
7657 DWORD pitch_out32;
7658 DWORD pitch_out64;
7660 test_data[] =
7662 /* 0 */
7663 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7664 0, 0, DD_OK,
7665 DDSD_PITCH, 0x100, 0x100},
7666 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7667 DDSD_PITCH, 0x104, DD_OK,
7668 DDSD_PITCH, 0x100, 0x100},
7669 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7670 DDSD_PITCH, 0x0f8, DD_OK,
7671 DDSD_PITCH, 0x100, 0x100},
7672 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7673 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
7674 0, 0, 0 },
7675 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7676 0, 0, DD_OK,
7677 DDSD_PITCH, 0x100, 0x0fc},
7678 /* 5 */
7679 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7680 DDSD_PITCH, 0x104, DD_OK,
7681 DDSD_PITCH, 0x100, 0x0fc},
7682 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7683 DDSD_PITCH, 0x0f8, DD_OK,
7684 DDSD_PITCH, 0x100, 0x0fc},
7685 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7686 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
7687 DDSD_PITCH, 0x100, 0x0fc},
7688 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7689 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
7690 0, 0, 0 },
7691 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7692 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
7693 DDSD_PITCH, 0x100, 0x100},
7694 /* 10 */
7695 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7696 DDSD_LPSURFACE | DDSD_PITCH, 0x0fe, DDERR_INVALIDPARAMS,
7697 0, 0, 0 },
7698 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7699 DDSD_LPSURFACE | DDSD_PITCH, 0x0fc, DD_OK,
7700 DDSD_PITCH, 0x0fc, 0x0fc},
7701 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7702 DDSD_LPSURFACE | DDSD_PITCH, 0x0f8, DDERR_INVALIDPARAMS,
7703 0, 0, 0 },
7704 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7705 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x100, DDERR_INVALIDPARAMS,
7706 0, 0, 0 },
7707 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7708 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x3f00, DDERR_INVALIDPARAMS,
7709 0, 0, 0 },
7710 /* 15 */
7711 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7712 DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, 0x100, DD_OK,
7713 DDSD_PITCH, 0x100, 0x100},
7714 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
7715 0, 0, DDERR_INVALIDCAPS,
7716 0, 0, 0 },
7717 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7718 0, 0, DD_OK,
7719 DDSD_PITCH, 0x100, 0 },
7720 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7721 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
7722 0, 0, 0 },
7723 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
7724 0, 0, DDERR_INVALIDCAPS,
7725 0, 0, 0 },
7726 /* 20 */
7727 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7728 0, 0, DD_OK,
7729 DDSD_PITCH, 0x100, 0 },
7730 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7731 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
7732 DDSD_PITCH, 0x100, 0 },
7734 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
7736 window = create_window();
7737 ddraw = create_ddraw();
7738 ok(!!ddraw, "Failed to create a ddraw object.\n");
7739 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7740 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7742 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
7744 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
7746 memset(&surface_desc, 0, sizeof(surface_desc));
7747 surface_desc.dwSize = sizeof(surface_desc);
7748 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
7749 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
7750 surface_desc.dwWidth = 63;
7751 surface_desc.dwHeight = 63;
7752 U1(surface_desc).lPitch = test_data[i].pitch_in;
7753 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7754 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
7755 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
7756 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7757 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7758 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7759 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7760 if (test_data[i].flags_in & DDSD_LPSURFACE)
7762 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
7763 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, expected_hr);
7764 surface_desc.lpSurface = mem;
7765 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7767 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
7768 continue;
7769 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
7770 if (FAILED(hr))
7771 continue;
7773 memset(&surface_desc, 0, sizeof(surface_desc));
7774 surface_desc.dwSize = sizeof(surface_desc);
7775 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
7776 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
7777 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
7778 "Test %u: Got unexpected flags %#x, expected %#x.\n",
7779 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
7780 /* The pitch for textures seems to be implementation specific. */
7781 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
7783 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
7784 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
7785 "Test %u: Got unexpected pitch %u, expected %u.\n",
7786 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
7787 else
7788 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
7789 "Test %u: Got unexpected pitch %u, expected %u.\n",
7790 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
7792 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
7794 IDirectDrawSurface4_Release(surface);
7797 HeapFree(GetProcessHeap(), 0, mem);
7798 refcount = IDirectDraw4_Release(ddraw);
7799 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7800 DestroyWindow(window);
7803 static void test_mipmap(void)
7805 IDirectDrawSurface4 *surface, *surface2;
7806 DDSURFACEDESC2 surface_desc;
7807 IDirectDraw4 *ddraw;
7808 unsigned int i;
7809 ULONG refcount;
7810 HWND window;
7811 HRESULT hr;
7812 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7813 DDCAPS hal_caps;
7815 static const struct
7817 DWORD flags;
7818 DWORD caps;
7819 DWORD width;
7820 DWORD height;
7821 DWORD mipmap_count_in;
7822 HRESULT hr;
7823 DWORD mipmap_count_out;
7825 tests[] =
7827 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
7828 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS, 0},
7829 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
7830 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS, 0},
7831 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 6},
7832 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 6},
7835 window = create_window();
7836 ddraw = create_ddraw();
7837 ok(!!ddraw, "Failed to create a ddraw object.\n");
7838 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7839 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7841 memset(&hal_caps, 0, sizeof(hal_caps));
7842 hal_caps.dwSize = sizeof(hal_caps);
7843 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
7844 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7845 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
7847 skip("Mipmapped textures not supported, skipping tests.\n");
7848 IDirectDraw4_Release(ddraw);
7849 DestroyWindow(window);
7850 return;
7853 for (i = 0; i < ARRAY_SIZE(tests); ++i)
7855 memset(&surface_desc, 0, sizeof(surface_desc));
7856 surface_desc.dwSize = sizeof(surface_desc);
7857 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
7858 surface_desc.ddsCaps.dwCaps = tests[i].caps;
7859 surface_desc.dwWidth = tests[i].width;
7860 surface_desc.dwHeight = tests[i].height;
7861 if (tests[i].flags & DDSD_MIPMAPCOUNT)
7862 U2(surface_desc).dwMipMapCount = tests[i].mipmap_count_in;
7863 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7864 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
7865 if (FAILED(hr))
7866 continue;
7868 memset(&surface_desc, 0, sizeof(surface_desc));
7869 surface_desc.dwSize = sizeof(surface_desc);
7870 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
7871 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
7872 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
7873 "Test %u: Got unexpected flags %#x.\n", i, surface_desc.dwFlags);
7874 ok(U2(surface_desc).dwMipMapCount == tests[i].mipmap_count_out,
7875 "Test %u: Got unexpected mipmap count %u.\n", i, U2(surface_desc).dwMipMapCount);
7877 if (U2(surface_desc).dwMipMapCount > 1)
7879 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &surface2);
7880 ok(SUCCEEDED(hr), "Test %u: Failed to get attached surface, hr %#x.\n", i, hr);
7882 memset(&surface_desc, 0, sizeof(surface_desc));
7883 surface_desc.dwSize = sizeof(surface_desc);
7884 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, 0, NULL);
7885 ok(SUCCEEDED(hr), "Test %u: Failed to lock surface, hr %#x.\n", i, hr);
7886 memset(&surface_desc, 0, sizeof(surface_desc));
7887 surface_desc.dwSize = sizeof(surface_desc);
7888 hr = IDirectDrawSurface4_Lock(surface2, NULL, &surface_desc, 0, NULL);
7889 ok(SUCCEEDED(hr), "Test %u: Failed to lock surface, hr %#x.\n", i, hr);
7890 IDirectDrawSurface4_Unlock(surface2, NULL);
7891 IDirectDrawSurface4_Unlock(surface, NULL);
7893 IDirectDrawSurface4_Release(surface2);
7896 IDirectDrawSurface4_Release(surface);
7899 refcount = IDirectDraw4_Release(ddraw);
7900 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7901 DestroyWindow(window);
7904 static void test_palette_complex(void)
7906 IDirectDrawSurface4 *surface, *mipmap, *tmp;
7907 DDSURFACEDESC2 surface_desc;
7908 IDirectDraw4 *ddraw;
7909 IDirectDrawPalette *palette, *palette2, *palette_mipmap;
7910 ULONG refcount;
7911 HWND window;
7912 HRESULT hr;
7913 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7914 DDCAPS hal_caps;
7915 PALETTEENTRY palette_entries[256];
7916 unsigned int i;
7917 HDC dc;
7918 RGBQUAD rgbquad;
7919 UINT count;
7921 window = create_window();
7922 ddraw = create_ddraw();
7923 ok(!!ddraw, "Failed to create a ddraw object.\n");
7924 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7925 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7927 memset(&hal_caps, 0, sizeof(hal_caps));
7928 hal_caps.dwSize = sizeof(hal_caps);
7929 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
7930 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7931 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
7933 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
7934 IDirectDraw4_Release(ddraw);
7935 DestroyWindow(window);
7936 return;
7939 memset(&surface_desc, 0, sizeof(surface_desc));
7940 surface_desc.dwSize = sizeof(surface_desc);
7941 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7942 surface_desc.dwWidth = 128;
7943 surface_desc.dwHeight = 128;
7944 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7945 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7946 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7947 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
7948 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7949 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7951 memset(palette_entries, 0, sizeof(palette_entries));
7952 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7953 palette_entries, &palette, NULL);
7954 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7956 memset(palette_entries, 0, sizeof(palette_entries));
7957 palette_entries[1].peRed = 0xff;
7958 palette_entries[1].peGreen = 0x80;
7959 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7960 palette_entries, &palette_mipmap, NULL);
7961 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7963 palette2 = (void *)0xdeadbeef;
7964 hr = IDirectDrawSurface4_GetPalette(surface, &palette2);
7965 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
7966 ok(!palette2, "Got unexpected palette %p.\n", palette2);
7967 hr = IDirectDrawSurface4_SetPalette(surface, palette);
7968 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7969 hr = IDirectDrawSurface4_GetPalette(surface, &palette2);
7970 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
7971 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
7972 IDirectDrawPalette_Release(palette2);
7974 mipmap = surface;
7975 IDirectDrawSurface4_AddRef(mipmap);
7976 for (i = 0; i < 7; ++i)
7978 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
7979 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
7980 palette2 = (void *)0xdeadbeef;
7981 hr = IDirectDrawSurface4_GetPalette(tmp, &palette2);
7982 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
7983 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
7985 hr = IDirectDrawSurface4_SetPalette(tmp, palette_mipmap);
7986 ok(SUCCEEDED(hr), "Failed to set palette, i %u, hr %#x.\n", i, hr);
7988 hr = IDirectDrawSurface4_GetPalette(tmp, &palette2);
7989 ok(SUCCEEDED(hr), "Failed to get palette, i %u, hr %#x.\n", i, hr);
7990 ok(palette_mipmap == palette2, "Got unexpected palette %p.\n", palette2);
7991 IDirectDrawPalette_Release(palette2);
7993 hr = IDirectDrawSurface4_GetDC(tmp, &dc);
7994 ok(SUCCEEDED(hr), "Failed to get DC, i %u, hr %#x.\n", i, hr);
7995 count = GetDIBColorTable(dc, 1, 1, &rgbquad);
7996 ok(count == 1, "Expected count 1, got %u.\n", count);
7997 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x.\n", rgbquad.rgbRed);
7998 ok(rgbquad.rgbGreen == 0x80, "Expected rgbGreen = 0x80, got %#x.\n", rgbquad.rgbGreen);
7999 ok(rgbquad.rgbBlue == 0x0, "Expected rgbBlue = 0x0, got %#x.\n", rgbquad.rgbBlue);
8000 hr = IDirectDrawSurface4_ReleaseDC(tmp, dc);
8001 ok(SUCCEEDED(hr), "Failed to release DC, i %u, hr %#x.\n", i, hr);
8003 IDirectDrawSurface4_Release(mipmap);
8004 mipmap = tmp;
8007 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
8008 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8009 IDirectDrawSurface4_Release(mipmap);
8010 refcount = IDirectDrawSurface4_Release(surface);
8011 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8012 refcount = IDirectDrawPalette_Release(palette_mipmap);
8013 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8014 refcount = IDirectDrawPalette_Release(palette);
8015 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8017 refcount = IDirectDraw4_Release(ddraw);
8018 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8019 DestroyWindow(window);
8022 static void test_p8_blit(void)
8024 IDirectDrawSurface4 *src, *dst, *dst_p8;
8025 DDSURFACEDESC2 surface_desc;
8026 IDirectDraw4 *ddraw;
8027 IDirectDrawPalette *palette, *palette2;
8028 ULONG refcount;
8029 HWND window;
8030 HRESULT hr;
8031 PALETTEENTRY palette_entries[256];
8032 unsigned int x;
8033 DDBLTFX fx;
8034 BOOL is_warp;
8035 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
8036 static const BYTE src_data2[] = {0x10, 0x5, 0x4, 0x3, 0x2, 0x1, 0xff, 0x80};
8037 static const BYTE expected_p8[] = {0x10, 0x1, 0x4, 0x3, 0x4, 0x5, 0xff, 0x80};
8038 static const D3DCOLOR expected[] =
8040 0x00101010, 0x00010101, 0x00020202, 0x00030303,
8041 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
8043 D3DCOLOR color;
8045 window = create_window();
8046 ddraw = create_ddraw();
8047 ok(!!ddraw, "Failed to create a ddraw object.\n");
8048 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8049 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8050 is_warp = ddraw_is_warp(ddraw);
8052 memset(palette_entries, 0, sizeof(palette_entries));
8053 palette_entries[1].peGreen = 0xff;
8054 palette_entries[2].peBlue = 0xff;
8055 palette_entries[3].peFlags = 0xff;
8056 palette_entries[4].peRed = 0xff;
8057 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8058 palette_entries, &palette, NULL);
8059 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8060 palette_entries[1].peBlue = 0xff;
8061 palette_entries[2].peGreen = 0xff;
8062 palette_entries[3].peRed = 0xff;
8063 palette_entries[4].peFlags = 0x0;
8064 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8065 palette_entries, &palette2, NULL);
8066 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8068 memset(&surface_desc, 0, sizeof(surface_desc));
8069 surface_desc.dwSize = sizeof(surface_desc);
8070 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8071 surface_desc.dwWidth = 8;
8072 surface_desc.dwHeight = 1;
8073 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8074 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8075 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8076 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
8077 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL);
8078 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8079 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_p8, NULL);
8080 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8081 hr = IDirectDrawSurface4_SetPalette(dst_p8, palette2);
8082 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8084 memset(&surface_desc, 0, sizeof(surface_desc));
8085 surface_desc.dwSize = sizeof(surface_desc);
8086 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8087 surface_desc.dwWidth = 8;
8088 surface_desc.dwHeight = 1;
8089 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8090 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8091 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
8092 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8093 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8094 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8095 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8096 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
8097 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL);
8098 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8100 memset(&surface_desc, 0, sizeof(surface_desc));
8101 surface_desc.dwSize = sizeof(surface_desc);
8102 hr = IDirectDrawSurface4_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
8103 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
8104 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
8105 hr = IDirectDrawSurface4_Unlock(src, NULL);
8106 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
8108 hr = IDirectDrawSurface4_Lock(dst_p8, NULL, &surface_desc, DDLOCK_WAIT, NULL);
8109 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
8110 memcpy(surface_desc.lpSurface, src_data2, sizeof(src_data2));
8111 hr = IDirectDrawSurface4_Unlock(dst_p8, NULL);
8112 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
8114 hr = IDirectDrawSurface4_SetPalette(src, palette);
8115 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8116 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
8117 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
8118 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
8119 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
8120 "Failed to blit, hr %#x.\n", hr);
8122 if (SUCCEEDED(hr))
8124 for (x = 0; x < ARRAY_SIZE(expected); x++)
8126 color = get_surface_color(dst, x, 0);
8127 todo_wine ok(compare_color(color, expected[x], 0),
8128 "Pixel %u: Got color %#x, expected %#x.\n",
8129 x, color, expected[x]);
8133 memset(&fx, 0, sizeof(fx));
8134 fx.dwSize = sizeof(fx);
8135 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x2;
8136 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x2;
8137 hr = IDirectDrawSurface4_Blt(dst_p8, NULL, src, NULL, DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &fx);
8138 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
8140 hr = IDirectDrawSurface4_Lock(dst_p8, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
8141 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
8142 /* A color keyed P8 blit doesn't do anything on WARP - it just leaves the data in the destination
8143 * surface untouched. P8 blits without color keys work. Error checking (DDBLT_KEYSRC without a key
8144 * for example) also works as expected.
8146 * Using DDBLT_KEYSRC instead of DDBLT_KEYSRCOVERRIDE doesn't change this. Doing this blit with
8147 * the display mode set to P8 doesn't help either. */
8148 ok(!memcmp(surface_desc.lpSurface, expected_p8, sizeof(expected_p8))
8149 || broken(is_warp && !memcmp(surface_desc.lpSurface, src_data2, sizeof(src_data2))),
8150 "Got unexpected P8 color key blit result.\n");
8151 hr = IDirectDrawSurface4_Unlock(dst_p8, NULL);
8152 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
8154 IDirectDrawSurface4_Release(src);
8155 IDirectDrawSurface4_Release(dst);
8156 IDirectDrawSurface4_Release(dst_p8);
8157 IDirectDrawPalette_Release(palette);
8158 IDirectDrawPalette_Release(palette2);
8160 refcount = IDirectDraw4_Release(ddraw);
8161 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8162 DestroyWindow(window);
8165 static void test_material(void)
8167 D3DMATERIALHANDLE mat_handle, tmp;
8168 IDirect3DMaterial3 *material;
8169 IDirect3DViewport3 *viewport;
8170 IDirect3DDevice3 *device;
8171 IDirectDrawSurface4 *rt;
8172 D3DCOLOR color;
8173 ULONG refcount;
8174 unsigned int i;
8175 HWND window;
8176 HRESULT hr;
8177 BOOL valid;
8179 static struct
8181 struct vec3 position;
8182 struct vec3 normal;
8183 D3DCOLOR diffuse;
8185 quad1[] =
8187 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
8188 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
8189 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
8190 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
8192 quad2[] =
8194 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
8195 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
8196 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
8197 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
8199 static const struct
8201 void *data;
8202 BOOL material;
8203 D3DCOLOR expected_color;
8205 test_data[] =
8207 {quad1, TRUE, 0x0000ff00},
8208 {quad2, TRUE, 0x0000ff00},
8209 {quad1, FALSE, 0x00ffffff},
8210 {quad2, FALSE, 0x00ff0000},
8212 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
8214 window = create_window();
8215 if (!(device = create_device(window, DDSCL_NORMAL)))
8217 skip("Failed to create a 3D device, skipping test.\n");
8218 DestroyWindow(window);
8219 return;
8222 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
8223 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8225 viewport = create_viewport(device, 0, 0, 640, 480);
8226 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
8227 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
8229 material = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
8230 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
8231 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
8233 hr = IDirect3DDevice3_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
8234 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
8235 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
8236 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
8237 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
8238 hr = IDirect3DDevice3_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
8239 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
8240 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
8241 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, 0);
8242 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
8243 hr = IDirect3DDevice3_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
8244 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
8245 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
8247 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
8249 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect,
8250 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
8251 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8253 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, test_data[i].material ? mat_handle : 0);
8254 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
8256 hr = IDirect3DDevice3_BeginScene(device);
8257 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8258 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
8259 D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE, test_data[i].data, 4, 0);
8260 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8261 hr = IDirect3DDevice3_EndScene(device);
8262 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8263 color = get_surface_color(rt, 320, 240);
8264 ok(compare_color(color, test_data[i].expected_color, 1),
8265 "Got unexpected color 0x%08x, test %u.\n", color, i);
8268 destroy_material(material);
8269 material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
8270 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
8271 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
8273 hr = IDirect3DViewport3_SetBackground(viewport, mat_handle);
8274 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
8275 hr = IDirect3DViewport3_GetBackground(viewport, &tmp, &valid);
8276 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
8277 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
8278 ok(valid, "Got unexpected valid %#x.\n", valid);
8279 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8280 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8281 color = get_surface_color(rt, 320, 240);
8282 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
8284 hr = IDirect3DViewport3_SetBackground(viewport, 0);
8285 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8286 hr = IDirect3DViewport3_GetBackground(viewport, &tmp, &valid);
8287 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
8288 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
8289 ok(valid, "Got unexpected valid %#x.\n", valid);
8290 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8291 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8292 color = get_surface_color(rt, 320, 240);
8293 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
8295 destroy_viewport(device, viewport);
8296 viewport = create_viewport(device, 0, 0, 640, 480);
8298 hr = IDirect3DViewport3_GetBackground(viewport, &tmp, &valid);
8299 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
8300 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
8301 ok(!valid, "Got unexpected valid %#x.\n", valid);
8302 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8303 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8304 color = get_surface_color(rt, 320, 240);
8305 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x.\n", color);
8307 destroy_viewport(device, viewport);
8308 destroy_material(material);
8309 IDirectDrawSurface4_Release(rt);
8310 refcount = IDirect3DDevice3_Release(device);
8311 ok(!refcount, "Device has %u references left.\n", refcount);
8312 DestroyWindow(window);
8315 static void test_palette_gdi(void)
8317 IDirectDrawSurface4 *surface, *primary;
8318 DDSURFACEDESC2 surface_desc;
8319 IDirectDraw4 *ddraw;
8320 IDirectDrawPalette *palette, *palette2;
8321 ULONG refcount;
8322 HWND window;
8323 HRESULT hr;
8324 PALETTEENTRY palette_entries[256];
8325 UINT i;
8326 HDC dc;
8327 DDBLTFX fx;
8328 RECT r;
8329 COLORREF color;
8330 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
8331 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
8332 * not the point of this test. */
8333 static const RGBQUAD expected1[] =
8335 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8336 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
8338 static const RGBQUAD expected2[] =
8340 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8341 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
8343 static const RGBQUAD expected3[] =
8345 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
8346 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
8348 HPALETTE ddraw_palette_handle;
8349 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
8350 RGBQUAD rgbquad[255];
8351 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
8353 window = create_window();
8354 ddraw = create_ddraw();
8355 ok(!!ddraw, "Failed to create a ddraw object.\n");
8356 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8357 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8359 memset(&surface_desc, 0, sizeof(surface_desc));
8360 surface_desc.dwSize = sizeof(surface_desc);
8361 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8362 surface_desc.dwWidth = 16;
8363 surface_desc.dwHeight = 16;
8364 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8365 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8366 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8367 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
8368 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8369 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8371 /* Avoid colors from the Windows default palette. */
8372 memset(palette_entries, 0, sizeof(palette_entries));
8373 palette_entries[1].peRed = 0x01;
8374 palette_entries[2].peGreen = 0x02;
8375 palette_entries[3].peBlue = 0x03;
8376 palette_entries[4].peRed = 0x13;
8377 palette_entries[4].peGreen = 0x14;
8378 palette_entries[4].peBlue = 0x15;
8379 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8380 palette_entries, &palette, NULL);
8381 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8383 /* If there is no palette assigned and the display mode is not 8 bpp, some
8384 * drivers refuse to create a DC while others allow it. If a DC is created,
8385 * the DIB color table is uninitialized and contains random colors. No error
8386 * is generated when trying to read pixels and random garbage is returned.
8388 * The most likely explanation is that if the driver creates a DC, it (or
8389 * the higher-level runtime) uses GetSystemPaletteEntries to find the
8390 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
8391 * contains uninitialized garbage. See comments below for the P8 case. */
8393 hr = IDirectDrawSurface4_SetPalette(surface, palette);
8394 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8395 hr = IDirectDrawSurface4_GetDC(surface, &dc);
8396 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8397 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8398 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8399 "Got unexpected palette %p, expected %p.\n",
8400 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8402 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8403 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8404 for (i = 0; i < ARRAY_SIZE(expected1); i++)
8406 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
8407 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8408 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8409 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
8411 for (; i < ARRAY_SIZE(rgbquad); i++)
8413 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8414 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8415 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8418 /* Update the palette while the DC is in use. This does not modify the DC. */
8419 palette_entries[4].peRed = 0x23;
8420 palette_entries[4].peGreen = 0x24;
8421 palette_entries[4].peBlue = 0x25;
8422 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
8423 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8425 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8426 ok(i == 1, "Expected count 1, got %u.\n", i);
8427 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8428 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8429 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8430 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8432 /* Neither does re-setting the palette. */
8433 hr = IDirectDrawSurface4_SetPalette(surface, NULL);
8434 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8435 hr = IDirectDrawSurface4_SetPalette(surface, palette);
8436 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8438 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8439 ok(i == 1, "Expected count 1, got %u.\n", i);
8440 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8441 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8442 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8443 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8445 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
8446 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8448 /* Refresh the DC. This updates the palette. */
8449 hr = IDirectDrawSurface4_GetDC(surface, &dc);
8450 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8451 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8452 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8453 for (i = 0; i < ARRAY_SIZE(expected2); i++)
8455 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8456 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8457 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8458 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8460 for (; i < ARRAY_SIZE(rgbquad); i++)
8462 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8463 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8464 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8466 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
8467 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8469 refcount = IDirectDrawSurface4_Release(surface);
8470 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8472 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
8473 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8474 if (FAILED(IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8476 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8477 IDirectDrawPalette_Release(palette);
8478 IDirectDraw4_Release(ddraw);
8479 DestroyWindow(window);
8480 return;
8482 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
8484 memset(&surface_desc, 0, sizeof(surface_desc));
8485 surface_desc.dwSize = sizeof(surface_desc);
8486 surface_desc.dwFlags = DDSD_CAPS;
8487 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8488 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
8489 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8491 memset(&fx, 0, sizeof(fx));
8492 fx.dwSize = sizeof(fx);
8493 U5(fx).dwFillColor = 3;
8494 SetRect(&r, 0, 0, 319, 479);
8495 hr = IDirectDrawSurface4_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8496 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
8497 SetRect(&r, 320, 0, 639, 479);
8498 U5(fx).dwFillColor = 4;
8499 hr = IDirectDrawSurface4_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8500 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
8502 hr = IDirectDrawSurface4_SetPalette(primary, palette);
8503 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8504 hr = IDirectDrawSurface4_GetDC(primary, &dc);
8505 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8507 color = GetPixel(dc, 160, 240);
8508 ok(color == 0x00030000, "Clear index 3: Got unexpected color 0x%08x.\n", color);
8509 color = GetPixel(dc, 480, 240);
8510 ok(color == 0x00252423, "Clear index 4: Got unexpected color 0x%08x.\n", color);
8512 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8513 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8514 "Got unexpected palette %p, expected %p.\n",
8515 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8516 SelectPalette(dc, ddraw_palette_handle, FALSE);
8518 /* The primary uses the system palette. In exclusive mode, the system palette matches
8519 * the ddraw palette attached to the primary, so the result is what you would expect
8520 * from a regular surface. Tests for the interaction between the ddraw palette and
8521 * the system palette are not included pending an application that depends on this.
8522 * The relation between those causes problems on Windows Vista and newer for games
8523 * like Age of Empires or StarCraft. Don't emulate it without a real need. */
8524 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8525 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8526 for (i = 0; i < ARRAY_SIZE(expected2); i++)
8528 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8529 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8530 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8531 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8533 for (; i < ARRAY_SIZE(rgbquad); i++)
8535 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8536 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8537 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8539 hr = IDirectDrawSurface4_ReleaseDC(primary, dc);
8540 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8542 memset(&surface_desc, 0, sizeof(surface_desc));
8543 surface_desc.dwSize = sizeof(surface_desc);
8544 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8545 surface_desc.dwWidth = 16;
8546 surface_desc.dwHeight = 16;
8547 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8548 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8549 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8551 /* Here the offscreen surface appears to use the primary's palette,
8552 * but in all likelihood it is actually the system palette. */
8553 hr = IDirectDrawSurface4_GetDC(surface, &dc);
8554 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8555 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8556 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8557 for (i = 0; i < ARRAY_SIZE(expected2); i++)
8559 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8560 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8561 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8562 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8564 for (; i < ARRAY_SIZE(rgbquad); i++)
8566 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8567 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8568 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8570 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
8571 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8573 /* On real hardware a change to the primary surface's palette applies immediately,
8574 * even on device contexts from offscreen surfaces that do not have their own
8575 * palette. On the testbot VMs this is not the case. Don't test this until we
8576 * know of an application that depends on this. */
8578 memset(palette_entries, 0, sizeof(palette_entries));
8579 palette_entries[1].peBlue = 0x40;
8580 palette_entries[2].peRed = 0x40;
8581 palette_entries[3].peGreen = 0x40;
8582 palette_entries[4].peRed = 0x12;
8583 palette_entries[4].peGreen = 0x34;
8584 palette_entries[4].peBlue = 0x56;
8585 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8586 palette_entries, &palette2, NULL);
8587 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8588 hr = IDirectDrawSurface4_SetPalette(surface, palette2);
8589 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8591 /* A palette assigned to the offscreen surface overrides the primary / system
8592 * palette. */
8593 hr = IDirectDrawSurface4_GetDC(surface, &dc);
8594 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8595 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8596 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8597 for (i = 0; i < ARRAY_SIZE(expected3); i++)
8599 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
8600 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8601 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8602 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
8604 for (; i < ARRAY_SIZE(rgbquad); i++)
8606 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8607 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8608 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8610 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
8611 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8613 refcount = IDirectDrawSurface4_Release(surface);
8614 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8616 /* The Windows 8 testbot keeps extra references to the primary and
8617 * backbuffer while in 8 bpp mode. */
8618 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
8619 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
8621 refcount = IDirectDrawSurface4_Release(primary);
8622 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8623 refcount = IDirectDrawPalette_Release(palette2);
8624 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8625 refcount = IDirectDrawPalette_Release(palette);
8626 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8627 refcount = IDirectDraw4_Release(ddraw);
8628 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8629 DestroyWindow(window);
8632 static void test_palette_alpha(void)
8634 IDirectDrawSurface4 *surface;
8635 DDSURFACEDESC2 surface_desc;
8636 IDirectDraw4 *ddraw;
8637 IDirectDrawPalette *palette;
8638 ULONG refcount;
8639 HWND window;
8640 HRESULT hr;
8641 PALETTEENTRY palette_entries[256];
8642 unsigned int i;
8643 static const struct
8645 DWORD caps, flags;
8646 BOOL attach_allowed;
8647 const char *name;
8649 test_data[] =
8651 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
8652 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
8653 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
8656 window = create_window();
8657 ddraw = create_ddraw();
8658 ok(!!ddraw, "Failed to create a ddraw object.\n");
8659 if (FAILED(IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8661 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8662 IDirectDraw4_Release(ddraw);
8663 DestroyWindow(window);
8664 return;
8666 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8667 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8669 memset(palette_entries, 0, sizeof(palette_entries));
8670 palette_entries[1].peFlags = 0x42;
8671 palette_entries[2].peFlags = 0xff;
8672 palette_entries[3].peFlags = 0x80;
8673 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
8674 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8676 memset(palette_entries, 0x66, sizeof(palette_entries));
8677 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
8678 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
8679 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8680 palette_entries[0].peFlags);
8681 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8682 palette_entries[1].peFlags);
8683 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
8684 palette_entries[2].peFlags);
8685 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
8686 palette_entries[3].peFlags);
8688 IDirectDrawPalette_Release(palette);
8690 memset(palette_entries, 0, sizeof(palette_entries));
8691 palette_entries[1].peFlags = 0x42;
8692 palette_entries[1].peRed = 0xff;
8693 palette_entries[2].peFlags = 0xff;
8694 palette_entries[3].peFlags = 0x80;
8695 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
8696 palette_entries, &palette, NULL);
8697 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8699 memset(palette_entries, 0x66, sizeof(palette_entries));
8700 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
8701 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
8702 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8703 palette_entries[0].peFlags);
8704 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8705 palette_entries[1].peFlags);
8706 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
8707 palette_entries[2].peFlags);
8708 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
8709 palette_entries[3].peFlags);
8711 for (i = 0; i < ARRAY_SIZE(test_data); i++)
8713 memset(&surface_desc, 0, sizeof(surface_desc));
8714 surface_desc.dwSize = sizeof(surface_desc);
8715 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
8716 surface_desc.dwWidth = 128;
8717 surface_desc.dwHeight = 128;
8718 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
8719 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8720 ok(SUCCEEDED(hr), "Failed to create %s surface, hr %#x.\n", test_data[i].name, hr);
8722 hr = IDirectDrawSurface4_SetPalette(surface, palette);
8723 if (test_data[i].attach_allowed)
8724 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#x.\n", test_data[i].name, hr);
8725 else
8726 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x, %s surface.\n", hr, test_data[i].name);
8728 if (SUCCEEDED(hr))
8730 HDC dc;
8731 RGBQUAD rgbquad;
8732 UINT retval;
8734 hr = IDirectDrawSurface4_GetDC(surface, &dc);
8735 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
8736 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
8737 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
8738 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
8739 rgbquad.rgbRed, test_data[i].name);
8740 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
8741 rgbquad.rgbGreen, test_data[i].name);
8742 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
8743 rgbquad.rgbBlue, test_data[i].name);
8744 ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
8745 rgbquad.rgbReserved, test_data[i].name);
8746 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
8747 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8749 IDirectDrawSurface4_Release(surface);
8752 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
8753 memset(&surface_desc, 0, sizeof(surface_desc));
8754 surface_desc.dwSize = sizeof(surface_desc);
8755 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8756 surface_desc.dwWidth = 128;
8757 surface_desc.dwHeight = 128;
8758 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8759 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8760 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
8761 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8762 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8763 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8764 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8765 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8766 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8767 hr = IDirectDrawSurface4_SetPalette(surface, palette);
8768 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
8769 IDirectDrawSurface4_Release(surface);
8771 /* The Windows 8 testbot keeps extra references to the primary
8772 * while in 8 bpp mode. */
8773 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
8774 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
8776 refcount = IDirectDrawPalette_Release(palette);
8777 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8778 refcount = IDirectDraw4_Release(ddraw);
8779 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8780 DestroyWindow(window);
8783 static void test_vb_writeonly(void)
8785 IDirect3DDevice3 *device;
8786 IDirect3D3 *d3d;
8787 IDirect3DVertexBuffer *buffer;
8788 HWND window;
8789 HRESULT hr;
8790 D3DVERTEXBUFFERDESC desc;
8791 void *ptr;
8792 static const struct vec4 quad[] =
8794 { 0.0f, 480.0f, 0.0f, 1.0f},
8795 { 0.0f, 0.0f, 0.0f, 1.0f},
8796 {640.0f, 480.0f, 0.0f, 1.0f},
8797 {640.0f, 0.0f, 0.0f, 1.0f},
8800 window = create_window();
8801 if (!(device = create_device(window, DDSCL_NORMAL)))
8803 skip("Failed to create a 3D device, skipping test.\n");
8804 DestroyWindow(window);
8805 return;
8808 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
8809 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
8811 memset(&desc, 0, sizeof(desc));
8812 desc.dwSize = sizeof(desc);
8813 desc.dwCaps = D3DVBCAPS_WRITEONLY;
8814 desc.dwFVF = D3DFVF_XYZRHW;
8815 desc.dwNumVertices = ARRAY_SIZE(quad);
8816 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &buffer, 0, NULL);
8817 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
8819 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, &ptr, NULL);
8820 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8821 memcpy(ptr, quad, sizeof(quad));
8822 hr = IDirect3DVertexBuffer_Unlock(buffer);
8823 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8825 hr = IDirect3DDevice3_BeginScene(device);
8826 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8827 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
8828 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8829 hr = IDirect3DDevice3_EndScene(device);
8830 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8832 hr = IDirect3DVertexBuffer_Lock(buffer, 0, &ptr, NULL);
8833 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8834 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
8835 hr = IDirect3DVertexBuffer_Unlock(buffer);
8836 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8838 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_READONLY, &ptr, NULL);
8839 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8840 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
8841 hr = IDirect3DVertexBuffer_Unlock(buffer);
8842 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8844 IDirect3DVertexBuffer_Release(buffer);
8845 IDirect3D3_Release(d3d);
8846 IDirect3DDevice3_Release(device);
8847 DestroyWindow(window);
8850 static void test_lost_device(void)
8852 IDirectDrawSurface4 *surface;
8853 DDSURFACEDESC2 surface_desc;
8854 HWND window1, window2;
8855 IDirectDraw4 *ddraw;
8856 ULONG refcount;
8857 HRESULT hr;
8858 BOOL ret;
8860 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8861 0, 0, 640, 480, 0, 0, 0, 0);
8862 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8863 0, 0, 640, 480, 0, 0, 0, 0);
8864 ddraw = create_ddraw();
8865 ok(!!ddraw, "Failed to create a ddraw object.\n");
8866 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8867 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8869 memset(&surface_desc, 0, sizeof(surface_desc));
8870 surface_desc.dwSize = sizeof(surface_desc);
8871 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8872 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8873 U5(surface_desc).dwBackBufferCount = 1;
8874 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8875 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8877 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8878 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8879 hr = IDirectDrawSurface4_IsLost(surface);
8880 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8881 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8882 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8884 ret = SetForegroundWindow(GetDesktopWindow());
8885 ok(ret, "Failed to set foreground window.\n");
8886 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8887 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8888 hr = IDirectDrawSurface4_IsLost(surface);
8889 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8890 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8891 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8893 ret = SetForegroundWindow(window1);
8894 ok(ret, "Failed to set foreground window.\n");
8895 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8896 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8897 hr = IDirectDrawSurface4_IsLost(surface);
8898 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8899 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8900 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8902 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
8903 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8904 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8905 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8906 hr = IDirectDrawSurface4_IsLost(surface);
8907 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8908 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8909 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8911 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
8912 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8913 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8914 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8915 hr = IDirectDrawSurface4_IsLost(surface);
8916 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8917 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8918 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8920 /* Trying to restore the primary will crash, probably because flippable
8921 * surfaces can't exist in DDSCL_NORMAL. */
8922 IDirectDrawSurface4_Release(surface);
8923 memset(&surface_desc, 0, sizeof(surface_desc));
8924 surface_desc.dwSize = sizeof(surface_desc);
8925 surface_desc.dwFlags = DDSD_CAPS;
8926 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8927 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8928 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8930 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8931 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8932 hr = IDirectDrawSurface4_IsLost(surface);
8933 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8935 ret = SetForegroundWindow(GetDesktopWindow());
8936 ok(ret, "Failed to set foreground window.\n");
8937 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8938 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8939 hr = IDirectDrawSurface4_IsLost(surface);
8940 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8942 ret = SetForegroundWindow(window1);
8943 ok(ret, "Failed to set foreground window.\n");
8944 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8945 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8946 hr = IDirectDrawSurface4_IsLost(surface);
8947 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8949 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8950 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8951 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8952 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8953 hr = IDirectDrawSurface4_IsLost(surface);
8954 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8956 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
8957 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8958 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8959 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8960 hr = IDirectDrawSurface4_IsLost(surface);
8961 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8963 IDirectDrawSurface4_Release(surface);
8964 memset(&surface_desc, 0, sizeof(surface_desc));
8965 surface_desc.dwSize = sizeof(surface_desc);
8966 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8967 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8968 U5(surface_desc).dwBackBufferCount = 1;
8969 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8970 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8972 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8973 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8974 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8975 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8976 hr = IDirectDrawSurface4_IsLost(surface);
8977 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8978 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8979 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8981 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
8982 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8983 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8984 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8985 hr = IDirectDrawSurface4_IsLost(surface);
8986 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8987 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8988 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8990 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
8991 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8992 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8993 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8994 hr = IDirectDrawSurface4_IsLost(surface);
8995 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8996 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8997 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8999 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
9000 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9001 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
9002 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9003 hr = IDirectDrawSurface4_IsLost(surface);
9004 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9005 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
9006 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9008 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
9009 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9010 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
9011 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9012 hr = IDirectDrawSurface4_IsLost(surface);
9013 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9014 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
9015 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9017 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9018 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9019 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
9020 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9021 hr = IDirectDrawSurface4_IsLost(surface);
9022 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9023 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
9024 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9026 IDirectDrawSurface4_Release(surface);
9027 refcount = IDirectDraw4_Release(ddraw);
9028 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9029 DestroyWindow(window2);
9030 DestroyWindow(window1);
9033 static void test_surface_desc_lock(void)
9035 IDirectDrawSurface4 *surface;
9036 DDSURFACEDESC2 surface_desc;
9037 IDirectDraw4 *ddraw;
9038 ULONG refcount;
9039 HWND window;
9040 HRESULT hr;
9042 window = create_window();
9043 ddraw = create_ddraw();
9044 ok(!!ddraw, "Failed to create a ddraw object.\n");
9045 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9046 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9048 memset(&surface_desc, 0, sizeof(surface_desc));
9049 surface_desc.dwSize = sizeof(surface_desc);
9050 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
9051 surface_desc.dwWidth = 16;
9052 surface_desc.dwHeight = 16;
9053 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9054 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9055 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9057 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9058 surface_desc.dwSize = sizeof(surface_desc);
9059 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
9060 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9061 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9063 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9064 surface_desc.dwSize = sizeof(surface_desc);
9065 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, 0, NULL);
9066 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9067 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9068 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9069 surface_desc.dwSize = sizeof(surface_desc);
9070 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
9071 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9072 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9073 hr = IDirectDrawSurface4_Unlock(surface, NULL);
9074 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9076 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9077 surface_desc.dwSize = sizeof(surface_desc);
9078 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
9079 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9080 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9082 IDirectDrawSurface4_Release(surface);
9083 refcount = IDirectDraw4_Release(ddraw);
9084 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9085 DestroyWindow(window);
9088 static void test_texturemapblend(void)
9090 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
9091 static RECT rect = {0, 0, 64, 128};
9092 IDirectDrawSurface4 *surface, *rt;
9093 IDirect3DViewport3 *viewport;
9094 DDSURFACEDESC2 surface_desc;
9095 IDirect3DTexture2 *texture;
9096 IDirect3DDevice3 *device;
9097 IDirectDraw4 *ddraw;
9098 IDirect3D3 *d3d;
9099 DDCOLORKEY ckey;
9100 D3DCOLOR color;
9101 ULONG refcount;
9102 HWND window;
9103 DDBLTFX fx;
9104 HRESULT hr;
9106 static struct
9108 struct vec4 position;
9109 D3DCOLOR diffuse;
9110 struct vec2 texcoord;
9112 test1_quads[] =
9114 {{ 0.0f, 0.0f, 0.0f, 1.0f}, 0xffffffff, {0.0f, 0.0f}},
9115 {{ 0.0f, 240.0f, 0.0f, 1.0f}, 0xffffffff, {0.0f, 1.0f}},
9116 {{640.0f, 0.0f, 0.0f, 1.0f}, 0xffffffff, {1.0f, 0.0f}},
9117 {{640.0f, 240.0f, 0.0f, 1.0f}, 0xffffffff, {1.0f, 1.0f}},
9118 {{ 0.0f, 240.0f, 0.0f, 1.0f}, 0x80ffffff, {0.0f, 0.0f}},
9119 {{ 0.0f, 480.0f, 0.0f, 1.0f}, 0x80ffffff, {0.0f, 1.0f}},
9120 {{640.0f, 240.0f, 0.0f, 1.0f}, 0x80ffffff, {1.0f, 0.0f}},
9121 {{640.0f, 480.0f, 0.0f, 1.0f}, 0x80ffffff, {1.0f, 1.0f}},
9123 test2_quads[] =
9125 {{ 0.0f, 0.0f, 0.0f, 1.0f}, 0x00ff0080, {0.0f, 0.0f}},
9126 {{ 0.0f, 240.0f, 0.0f, 1.0f}, 0x00ff0080, {0.0f, 1.0f}},
9127 {{640.0f, 0.0f, 0.0f, 1.0f}, 0x00ff0080, {1.0f, 0.0f}},
9128 {{640.0f, 240.0f, 0.0f, 1.0f}, 0x00ff0080, {1.0f, 1.0f}},
9129 {{ 0.0f, 240.0f, 0.0f, 1.0f}, 0x008000ff, {0.0f, 0.0f}},
9130 {{ 0.0f, 480.0f, 0.0f, 1.0f}, 0x008000ff, {0.0f, 1.0f}},
9131 {{640.0f, 240.0f, 0.0f, 1.0f}, 0x008000ff, {1.0f, 0.0f}},
9132 {{640.0f, 480.0f, 0.0f, 1.0f}, 0x008000ff, {1.0f, 1.0f}},
9135 window = create_window();
9136 if (!(device = create_device(window, DDSCL_NORMAL)))
9138 skip("Failed to create a 3D device, skipping test.\n");
9139 DestroyWindow(window);
9140 return;
9143 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
9144 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9145 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
9146 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
9147 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
9148 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9150 viewport = create_viewport(device, 0, 0, 640, 480);
9151 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
9152 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
9154 /* Test alpha with DDPF_ALPHAPIXELS texture - should be taken from texture
9155 * alpha channel.
9157 * The vertex alpha is completely ignored in this case, so case 1 and 2
9158 * combined are not a D3DTOP_MODULATE with texture alpha = 0xff in case 2
9159 * (no alpha in texture). */
9160 memset(&surface_desc, 0, sizeof(surface_desc));
9161 surface_desc.dwSize = sizeof(surface_desc);
9162 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9163 surface_desc.dwHeight = 128;
9164 surface_desc.dwWidth = 128;
9165 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9166 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9167 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
9168 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9169 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9170 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9171 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9172 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
9173 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9174 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9176 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9177 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
9178 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
9179 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9181 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9182 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
9184 memset(&fx, 0, sizeof(fx));
9185 fx.dwSize = sizeof(fx);
9186 U5(fx).dwFillColor = 0xff0000ff;
9187 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9188 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9189 U5(fx).dwFillColor = 0x800000ff;
9190 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9191 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9193 /* Note that the ddraw1 version of this test runs tests 1-3 with
9194 * D3DRENDERSTATE_COLORKEYENABLE enabled, whereas this version only runs
9195 * test 4 with color keying on. Because no color key is set on the texture
9196 * this should not result in different behavior. */
9197 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
9198 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9199 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
9200 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9201 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
9202 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9203 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
9204 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9205 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
9206 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9207 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
9208 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9210 hr = IDirect3DDevice3_BeginScene(device);
9211 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9212 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9213 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[0], 4, 0);
9214 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9215 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9216 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[4], 4, 0);
9217 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9218 hr = IDirect3DDevice3_EndScene(device);
9219 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9221 color = get_surface_color(rt, 5, 5);
9222 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9223 color = get_surface_color(rt, 400, 5);
9224 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9225 color = get_surface_color(rt, 5, 245);
9226 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9227 color = get_surface_color(rt, 400, 245);
9228 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9230 hr = IDirect3DDevice3_SetTexture(device, 0, NULL);
9231 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9232 IDirect3DTexture2_Release(texture);
9233 refcount = IDirectDrawSurface4_Release(surface);
9234 ok(!refcount, "Surface not properly released, refcount %u.\n", refcount);
9236 /* Test alpha with texture that has no alpha channel - alpha should be
9237 * taken from diffuse vertex color. */
9238 memset(&surface_desc, 0, sizeof(surface_desc));
9239 surface_desc.dwSize = sizeof(surface_desc);
9240 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9241 surface_desc.dwHeight = 128;
9242 surface_desc.dwWidth = 128;
9243 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9244 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9245 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
9246 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9247 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9248 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9249 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9251 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9252 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9254 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9255 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
9256 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
9257 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9259 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9260 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
9262 U5(fx).dwFillColor = 0xff0000ff;
9263 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9264 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9265 U5(fx).dwFillColor = 0x800000ff;
9266 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9267 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9269 hr = IDirect3DDevice3_BeginScene(device);
9270 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9271 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9272 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[0], 4, 0);
9273 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9274 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9275 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[4], 4, 0);
9276 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9277 hr = IDirect3DDevice3_EndScene(device);
9278 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9280 color = get_surface_color(rt, 5, 5);
9281 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9282 color = get_surface_color(rt, 400, 5);
9283 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9284 color = get_surface_color(rt, 5, 245);
9285 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9286 color = get_surface_color(rt, 400, 245);
9287 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9289 hr = IDirect3DDevice3_SetTexture(device, 0, NULL);
9290 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9291 IDirect3DTexture2_Release(texture);
9292 refcount = IDirectDrawSurface4_Release(surface);
9293 ok(!refcount, "Surface not properly released, refcount %u.\n", refcount);
9295 /* Test RGB - should multiply color components from diffuse vertex color
9296 * and texture. */
9297 memset(&surface_desc, 0, sizeof(surface_desc));
9298 surface_desc.dwSize = sizeof(surface_desc);
9299 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9300 surface_desc.dwHeight = 128;
9301 surface_desc.dwWidth = 128;
9302 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9303 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9304 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
9305 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9306 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9307 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9308 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9309 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
9310 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9311 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9313 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9314 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
9315 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
9316 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9318 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9319 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
9321 U5(fx).dwFillColor = 0x00ffffff;
9322 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9323 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9324 U5(fx).dwFillColor = 0x00ffff80;
9325 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9326 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9328 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
9329 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9331 hr = IDirect3DDevice3_BeginScene(device);
9332 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9333 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9334 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test2_quads[0], 4, 0);
9335 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9336 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9337 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test2_quads[4], 4, 0);
9338 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9339 hr = IDirect3DDevice3_EndScene(device);
9340 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9342 color = get_surface_color(rt, 5, 5);
9343 ok(compare_color(color, 0x00ff0040, 2), "Got unexpected color 0x%08x.\n", color);
9344 color = get_surface_color(rt, 400, 5);
9345 ok(compare_color(color, 0x00ff0080, 2), "Got unexpected color 0x%08x.\n", color);
9346 color = get_surface_color(rt, 5, 245);
9347 ok(compare_color(color, 0x00800080, 2), "Got unexpected color 0x%08x.\n", color);
9348 color = get_surface_color(rt, 400, 245);
9349 ok(compare_color(color, 0x008000ff, 2), "Got unexpected color 0x%08x.\n", color);
9351 hr = IDirect3DDevice3_SetTexture(device, 0, NULL);
9352 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9353 IDirect3DTexture2_Release(texture);
9354 refcount = IDirectDrawSurface4_Release(surface);
9355 ok(!refcount, "Surface not properly released, refcount %u.\n", refcount);
9357 /* Test alpha again, now with color keyed texture (colorkey emulation in
9358 * wine can interfere). */
9359 memset(&surface_desc, 0, sizeof(surface_desc));
9360 surface_desc.dwSize = sizeof(surface_desc);
9361 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9362 surface_desc.dwHeight = 128;
9363 surface_desc.dwWidth = 128;
9364 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9365 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9366 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
9367 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
9368 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
9369 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
9370 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
9372 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9373 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9375 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9376 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
9377 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
9378 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9380 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9381 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
9383 U5(fx).dwFillColor = 0xf800;
9384 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9385 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9386 U5(fx).dwFillColor = 0x001f;
9387 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9388 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9390 ckey.dwColorSpaceLowValue = 0x001f;
9391 ckey.dwColorSpaceHighValue = 0x001f;
9392 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9393 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
9395 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
9396 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9397 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
9398 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9400 hr = IDirect3DDevice3_BeginScene(device);
9401 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9402 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9403 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[0], 4, 0);
9404 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9405 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9406 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[4], 4, 0);
9407 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9408 hr = IDirect3DDevice3_EndScene(device);
9409 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9411 color = get_surface_color(rt, 5, 5);
9412 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
9413 color = get_surface_color(rt, 400, 5);
9414 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
9415 color = get_surface_color(rt, 5, 245);
9416 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
9417 color = get_surface_color(rt, 400, 245);
9418 ok(compare_color(color, 0x00800000, 2), "Got unexpected color 0x%08x.\n", color);
9420 hr = IDirect3DDevice3_SetTexture(device, 0, NULL);
9421 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9422 IDirect3DTexture2_Release(texture);
9423 refcount = IDirectDrawSurface4_Release(surface);
9424 ok(!refcount, "Surface not properly released, refcount %u.\n", refcount);
9426 destroy_viewport(device, viewport);
9427 IDirectDrawSurface4_Release(rt);
9428 IDirect3DDevice3_Release(device);
9429 IDirect3D3_Release(d3d);
9430 refcount = IDirectDraw4_Release(ddraw);
9431 ok(!refcount, "Ddraw object not properly released, refcount %u.\n", refcount);
9432 DestroyWindow(window);
9435 static void test_signed_formats(void)
9437 HRESULT hr;
9438 IDirect3DDevice3 *device;
9439 IDirect3D3 *d3d;
9440 IDirectDraw4 *ddraw;
9441 IDirectDrawSurface4 *surface, *rt;
9442 IDirect3DTexture2 *texture;
9443 IDirect3DViewport3 *viewport;
9444 DDSURFACEDESC2 surface_desc;
9445 ULONG refcount;
9446 HWND window;
9447 D3DCOLOR color, expected_color;
9448 D3DRECT clear_rect;
9449 static struct
9451 struct vec3 position;
9452 struct vec2 texcoord;
9454 quad[] =
9456 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
9457 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
9458 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
9459 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
9461 /* See test_signed_formats() in dlls/d3d9/tests/visual.c for an explanation
9462 * of these values. */
9463 static const USHORT content_v8u8[4][4] =
9465 {0x0000, 0x7f7f, 0x8880, 0x0000},
9466 {0x0080, 0x8000, 0x7f00, 0x007f},
9467 {0x193b, 0xe8c8, 0x0808, 0xf8f8},
9468 {0x4444, 0xc0c0, 0xa066, 0x22e0},
9470 static const DWORD content_x8l8v8u8[4][4] =
9472 {0x00000000, 0x00ff7f7f, 0x00008880, 0x00ff0000},
9473 {0x00000080, 0x00008000, 0x00007f00, 0x0000007f},
9474 {0x0041193b, 0x0051e8c8, 0x00040808, 0x00fff8f8},
9475 {0x00824444, 0x0000c0c0, 0x00c2a066, 0x009222e0},
9477 static const USHORT content_l6v5u5[4][4] =
9479 {0x0000, 0xfdef, 0x0230, 0xfc00},
9480 {0x0010, 0x0200, 0x01e0, 0x000f},
9481 {0x4067, 0x53b9, 0x0421, 0xffff},
9482 {0x8108, 0x0318, 0xc28c, 0x909c},
9484 static const struct
9486 const char *name;
9487 const void *content;
9488 SIZE_T pixel_size;
9489 BOOL blue;
9490 unsigned int slop, slop_broken;
9491 DDPIXELFORMAT format;
9493 formats[] =
9496 "D3DFMT_V8U8", content_v8u8, sizeof(WORD), FALSE, 1, 0,
9498 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV, 0,
9499 {16}, {0x000000ff}, {0x0000ff00}, {0x00000000}, {0x00000000}
9503 "D3DFMT_X8L8V8U8", content_x8l8v8u8, sizeof(DWORD), TRUE, 1, 0,
9505 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
9506 {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}
9510 "D3DFMT_L6V5U5", content_l6v5u5, sizeof(WORD), TRUE, 4, 7,
9512 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
9513 {16}, {0x0000001f}, {0x000003e0}, {0x0000fc00}, {0x00000000}
9517 /* No V16U16 or Q8W8V8U8 support in ddraw. */
9519 static const D3DCOLOR expected_colors[4][4] =
9521 {0x00808080, 0x00fefeff, 0x00010780, 0x008080ff},
9522 {0x00018080, 0x00800180, 0x0080fe80, 0x00fe8080},
9523 {0x00ba98a0, 0x004767a8, 0x00888881, 0x007878ff},
9524 {0x00c3c3c0, 0x003f3f80, 0x00e51fe1, 0x005fa2c8},
9526 unsigned int i, width, x, y;
9527 D3DDEVICEDESC device_desc, hel_desc;
9529 window = create_window();
9530 if (!(device = create_device(window, DDSCL_NORMAL)))
9532 skip("Failed to create a 3D device, skipping test.\n");
9533 DestroyWindow(window);
9534 return;
9537 memset(&device_desc, 0, sizeof(device_desc));
9538 device_desc.dwSize = sizeof(device_desc);
9539 memset(&hel_desc, 0, sizeof(hel_desc));
9540 hel_desc.dwSize = sizeof(hel_desc);
9541 hr = IDirect3DDevice3_GetCaps(device, &device_desc, &hel_desc);
9542 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9543 if (!(device_desc.dwTextureOpCaps & D3DTEXOPCAPS_BLENDFACTORALPHA))
9545 skip("D3DTOP_BLENDFACTORALPHA not supported, skipping bumpmap format tests.\n");
9546 goto done;
9549 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
9550 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9551 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
9552 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
9553 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
9554 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9556 memset(&surface_desc, 0, sizeof(surface_desc));
9557 surface_desc.dwSize = sizeof(surface_desc);
9558 hr = IDirectDrawSurface4_GetSurfaceDesc(rt, &surface_desc);
9559 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9560 viewport = create_viewport(device, 0, 0, surface_desc.dwWidth, surface_desc.dwHeight);
9561 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
9562 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
9563 U1(clear_rect).x1 = 0;
9564 U2(clear_rect).y1 = 0;
9565 U3(clear_rect).x2 = surface_desc.dwWidth;
9566 U4(clear_rect).y2 = surface_desc.dwHeight;
9568 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
9569 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9571 /* dst = tex * 0.5 + 1.0 * (1.0 - 0.5) = tex * 0.5 + 0.5 */
9572 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x80ffffff);
9573 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9574 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BLENDFACTORALPHA);
9575 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9576 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9577 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9578 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
9579 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9581 for (i = 0; i < ARRAY_SIZE(formats); i++)
9583 for (width = 1; width < 5; width += 3)
9585 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
9586 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
9588 memset(&surface_desc, 0, sizeof(surface_desc));
9589 surface_desc.dwSize = sizeof(surface_desc);
9590 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
9591 surface_desc.dwWidth = width;
9592 surface_desc.dwHeight = 4;
9593 U4(surface_desc).ddpfPixelFormat = formats[i].format;
9594 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
9595 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9596 if (FAILED(hr))
9598 skip("%s textures not supported, skipping.\n", formats[i].name);
9599 continue;
9601 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, format %s.\n", hr, formats[i].name);
9603 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9604 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture2 interface, hr %#x, format %s.\n",
9605 hr, formats[i].name);
9606 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
9607 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x, format %s.\n", hr, formats[i].name);
9608 IDirect3DTexture2_Release(texture);
9610 memset(&surface_desc, 0, sizeof(surface_desc));
9611 surface_desc.dwSize = sizeof(surface_desc);
9612 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, 0, NULL);
9613 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, format %s.\n", hr, formats[i].name);
9614 for (y = 0; y < 4; y++)
9616 memcpy((char *)surface_desc.lpSurface + y * U1(surface_desc).lPitch,
9617 (char *)formats[i].content + y * 4 * formats[i].pixel_size,
9618 width * formats[i].pixel_size);
9620 hr = IDirectDrawSurface4_Unlock(surface, NULL);
9621 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, format %s.\n", hr, formats[i].name);
9623 hr = IDirect3DDevice3_BeginScene(device);
9624 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9625 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9626 D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
9627 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9628 hr = IDirect3DDevice3_EndScene(device);
9629 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9631 for (y = 0; y < 4; y++)
9633 for (x = 0; x < width; x++)
9635 expected_color = expected_colors[y][x];
9636 if (!formats[i].blue)
9637 expected_color |= 0x000000ff;
9639 color = get_surface_color(rt, 80 + 160 * x, 60 + 120 * y);
9640 ok(compare_color(color, expected_color, formats[i].slop)
9641 || broken(compare_color(color, expected_color, formats[i].slop_broken)),
9642 "Expected color 0x%08x, got 0x%08x, format %s, location %ux%u.\n",
9643 expected_color, color, formats[i].name, x, y);
9647 IDirectDrawSurface4_Release(surface);
9651 destroy_viewport(device, viewport);
9652 IDirectDrawSurface4_Release(rt);
9653 IDirectDraw4_Release(ddraw);
9654 IDirect3D3_Release(d3d);
9656 done:
9657 refcount = IDirect3DDevice3_Release(device);
9658 ok(!refcount, "Device has %u references left.\n", refcount);
9659 DestroyWindow(window);
9662 static void test_color_fill(void)
9664 HRESULT hr;
9665 IDirect3DDevice3 *device;
9666 IDirect3D3 *d3d;
9667 IDirectDraw4 *ddraw;
9668 IDirectDrawSurface4 *surface, *surface2;
9669 DDSURFACEDESC2 surface_desc;
9670 DDPIXELFORMAT z_fmt;
9671 ULONG refcount;
9672 HWND window;
9673 unsigned int i;
9674 DDBLTFX fx;
9675 RECT rect = {5, 5, 7, 7};
9676 DWORD *color;
9677 DWORD supported_fmts = 0, num_fourcc_codes, *fourcc_codes;
9678 DDCAPS hal_caps;
9679 static const struct
9681 DWORD caps, caps2;
9682 HRESULT colorfill_hr, depthfill_hr;
9683 BOOL rop_success;
9684 const char *name;
9685 DWORD result;
9686 BOOL check_result;
9687 DDPIXELFORMAT format;
9689 tests[] =
9692 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9693 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
9695 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9696 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9700 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
9701 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
9703 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9704 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9708 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
9709 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
9711 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9712 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9716 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
9717 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
9719 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9720 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9724 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
9725 DD_OK, DDERR_INVALIDPARAMS, TRUE, "managed texture RGB", 0xdeadbeef, TRUE,
9727 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9728 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9732 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY, 0,
9733 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0xdeadbeef, TRUE,
9734 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
9737 DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY, 0,
9738 DDERR_INVALIDPARAMS, DD_OK, TRUE, "sysmem zbuffer", 0xdeadbeef, TRUE,
9739 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
9742 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
9743 * different afterwards. DX9+ GPUs set one of the two luminance values
9744 * in each block, but AMD and Nvidia GPUs disagree on which luminance
9745 * value they set. r200 (dx8) just sets the entire block to the clear
9746 * value. */
9747 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9748 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
9750 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
9751 {0}, {0}, {0}, {0}, {0}
9755 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9756 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
9758 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
9759 {0}, {0}, {0}, {0}, {0}
9763 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
9764 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
9766 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
9767 {0}, {0}, {0}, {0}, {0}
9771 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
9772 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
9774 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
9775 {0}, {0}, {0}, {0}, {0}
9779 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
9780 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
9782 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
9783 {0}, {0}, {0}, {0}, {0}
9787 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
9788 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
9790 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
9791 {0}, {0}, {0}, {0}, {0}
9795 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
9796 * surface works, presumably because it is handled by the runtime instead of
9797 * the driver. */
9798 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9799 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
9801 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
9802 {8}, {0}, {0}, {0}, {0}
9806 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
9807 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
9809 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
9810 {8}, {0}, {0}, {0}, {0}
9814 static const struct
9816 DWORD rop;
9817 const char *name;
9818 HRESULT hr;
9820 rops[] =
9822 {SRCCOPY, "SRCCOPY", DD_OK},
9823 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
9824 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
9825 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
9826 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
9827 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
9828 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
9829 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
9830 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
9831 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
9832 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
9833 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
9834 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
9835 {BLACKNESS, "BLACKNESS", DD_OK},
9836 {WHITENESS, "WHITENESS", DD_OK},
9837 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
9840 window = create_window();
9841 if (!(device = create_device(window, DDSCL_NORMAL)))
9843 skip("Failed to create a 3D device, skipping test.\n");
9844 DestroyWindow(window);
9845 return;
9848 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
9849 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9850 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
9851 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
9853 memset(&z_fmt, 0, sizeof(z_fmt));
9854 IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
9855 if (!z_fmt.dwSize)
9856 skip("No Z buffer formats supported, skipping Z buffer colorfill test.\n");
9858 IDirect3DDevice3_EnumTextureFormats(device, test_block_formats_creation_cb, &supported_fmts);
9859 if (!(supported_fmts & SUPPORT_DXT1))
9860 skip("DXT1 textures not supported, skipping DXT1 colorfill test.\n");
9862 IDirect3D3_Release(d3d);
9864 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
9865 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
9866 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
9867 num_fourcc_codes * sizeof(*fourcc_codes));
9868 if (!fourcc_codes)
9869 goto done;
9870 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
9871 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
9872 for (i = 0; i < num_fourcc_codes; i++)
9874 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
9875 supported_fmts |= SUPPORT_YUY2;
9876 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
9877 supported_fmts |= SUPPORT_UYVY;
9879 HeapFree(GetProcessHeap(), 0, fourcc_codes);
9881 memset(&hal_caps, 0, sizeof(hal_caps));
9882 hal_caps.dwSize = sizeof(hal_caps);
9883 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
9884 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9886 if (!(supported_fmts & (SUPPORT_YUY2 | SUPPORT_UYVY)) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
9887 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
9889 for (i = 0; i < ARRAY_SIZE(tests); i++)
9891 DWORD expected_broken = tests[i].result;
9893 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
9894 memset(&fx, 0, sizeof(fx));
9895 fx.dwSize = sizeof(fx);
9896 U5(fx).dwFillColor = 0xdeadbeef;
9898 memset(&surface_desc, 0, sizeof(surface_desc));
9899 surface_desc.dwSize = sizeof(surface_desc);
9900 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9901 surface_desc.dwWidth = 64;
9902 surface_desc.dwHeight = 64;
9903 U4(surface_desc).ddpfPixelFormat = tests[i].format;
9904 surface_desc.ddsCaps.dwCaps = tests[i].caps;
9905 surface_desc.ddsCaps.dwCaps2 = tests[i].caps2;
9907 if (tests[i].format.dwFourCC == MAKEFOURCC('D','X','T','1') && !(supported_fmts & SUPPORT_DXT1))
9908 continue;
9909 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !(supported_fmts & SUPPORT_YUY2))
9910 continue;
9911 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !(supported_fmts & SUPPORT_UYVY))
9912 continue;
9913 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
9914 continue;
9916 if (tests[i].caps & DDSCAPS_ZBUFFER)
9918 if (!z_fmt.dwSize)
9919 continue;
9921 U4(surface_desc).ddpfPixelFormat = z_fmt;
9922 /* Some drivers seem to convert depth values incorrectly or not at
9923 * all. Affects at least AMD PALM, 8.17.10.1247. */
9924 if (tests[i].caps & DDSCAPS_VIDEOMEMORY)
9926 DWORD expected;
9927 float f, g;
9929 expected = tests[i].result & U3(z_fmt).dwZBitMask;
9930 f = ceilf(log2f(expected + 1.0f));
9931 g = (f + 1.0f) / 2.0f;
9932 g -= (int)g;
9933 expected_broken = (expected / exp2f(f) - g) * 256;
9934 expected_broken *= 0x01010101;
9938 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9939 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, surface %s.\n", hr, tests[i].name);
9941 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9942 todo_wine_if (tests[i].format.dwFourCC)
9943 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9944 hr, tests[i].colorfill_hr, tests[i].name);
9946 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9947 todo_wine_if (tests[i].format.dwFourCC)
9948 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9949 hr, tests[i].colorfill_hr, tests[i].name);
9951 if (SUCCEEDED(hr) && tests[i].check_result)
9953 memset(&surface_desc, 0, sizeof(surface_desc));
9954 surface_desc.dwSize = sizeof(surface_desc);
9955 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9956 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9957 color = surface_desc.lpSurface;
9958 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
9959 *color, tests[i].result, tests[i].name);
9960 hr = IDirectDrawSurface4_Unlock(surface, NULL);
9961 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9964 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9965 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9966 hr, tests[i].depthfill_hr, tests[i].name);
9967 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9968 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9969 hr, tests[i].depthfill_hr, tests[i].name);
9971 if (SUCCEEDED(hr) && tests[i].check_result)
9973 memset(&surface_desc, 0, sizeof(surface_desc));
9974 surface_desc.dwSize = sizeof(surface_desc);
9975 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9976 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9977 color = surface_desc.lpSurface;
9978 ok((*color & U3(z_fmt).dwZBitMask) == (tests[i].result & U3(z_fmt).dwZBitMask)
9979 || broken((*color & U3(z_fmt).dwZBitMask) == (expected_broken & U3(z_fmt).dwZBitMask)),
9980 "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
9981 *color & U3(z_fmt).dwZBitMask, tests[i].result & U3(z_fmt).dwZBitMask, tests[i].name);
9982 hr = IDirectDrawSurface4_Unlock(surface, NULL);
9983 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9986 U5(fx).dwFillColor = 0xdeadbeef;
9987 fx.dwROP = BLACKNESS;
9988 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9989 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
9990 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
9991 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
9992 U5(fx).dwFillColor, tests[i].name);
9994 if (SUCCEEDED(hr) && tests[i].check_result)
9996 memset(&surface_desc, 0, sizeof(surface_desc));
9997 surface_desc.dwSize = sizeof(surface_desc);
9998 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9999 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10000 color = surface_desc.lpSurface;
10001 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
10002 *color, tests[i].name);
10003 hr = IDirectDrawSurface4_Unlock(surface, NULL);
10004 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10007 fx.dwROP = WHITENESS;
10008 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10009 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
10010 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
10011 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
10012 U5(fx).dwFillColor, tests[i].name);
10014 if (SUCCEEDED(hr) && tests[i].check_result)
10016 memset(&surface_desc, 0, sizeof(surface_desc));
10017 surface_desc.dwSize = sizeof(surface_desc);
10018 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10019 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10020 color = surface_desc.lpSurface;
10021 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
10022 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
10023 *color, tests[i].name);
10024 hr = IDirectDrawSurface4_Unlock(surface, NULL);
10025 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10028 IDirectDrawSurface4_Release(surface);
10031 memset(&fx, 0, sizeof(fx));
10032 fx.dwSize = sizeof(fx);
10033 U5(fx).dwFillColor = 0xdeadbeef;
10034 fx.dwROP = WHITENESS;
10036 memset(&surface_desc, 0, sizeof(surface_desc));
10037 surface_desc.dwSize = sizeof(surface_desc);
10038 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10039 surface_desc.dwWidth = 64;
10040 surface_desc.dwHeight = 64;
10041 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10042 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10043 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10044 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10045 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10046 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10047 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
10048 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10049 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10050 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
10051 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10053 /* No DDBLTFX. */
10054 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
10055 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10056 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
10057 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10059 /* Unused source rectangle. */
10060 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10061 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10062 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10063 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10065 /* Unused source surface. */
10066 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10067 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10068 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10069 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10070 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10071 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10072 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10073 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10075 /* Inverted destination or source rectangle. */
10076 SetRect(&rect, 5, 7, 7, 5);
10077 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10078 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10079 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10080 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10081 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10082 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10083 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10084 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10085 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10086 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10088 /* Negative rectangle. */
10089 SetRect(&rect, -1, -1, 5, 5);
10090 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10091 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10092 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10093 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10094 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10095 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10096 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10097 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10098 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10099 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10101 /* Out of bounds rectangle. */
10102 SetRect(&rect, 0, 0, 65, 65);
10103 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10104 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10105 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10106 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10108 /* Combine multiple flags. */
10109 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10110 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10111 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
10112 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10113 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
10114 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10116 for (i = 0; i < ARRAY_SIZE(rops); i++)
10118 fx.dwROP = rops[i].rop;
10119 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10120 ok(hr == rops[i].hr, "Got unexpected hr %#x for rop %s.\n", hr, rops[i].name);
10123 IDirectDrawSurface4_Release(surface2);
10124 IDirectDrawSurface4_Release(surface);
10126 if (!z_fmt.dwSize)
10127 goto done;
10129 memset(&surface_desc, 0, sizeof(surface_desc));
10130 surface_desc.dwSize = sizeof(surface_desc);
10131 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10132 surface_desc.dwWidth = 64;
10133 surface_desc.dwHeight = 64;
10134 U4(surface_desc).ddpfPixelFormat = z_fmt;
10135 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
10136 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10137 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10138 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
10139 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10141 /* No DDBLTFX. */
10142 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
10143 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10145 /* Unused source rectangle. */
10146 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10147 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10149 /* Unused source surface. */
10150 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10151 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10152 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10153 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10155 /* Inverted destination or source rectangle. */
10156 SetRect(&rect, 5, 7, 7, 5);
10157 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10158 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10159 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10160 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10161 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10162 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10163 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10164 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10166 /* Negative rectangle. */
10167 SetRect(&rect, -1, -1, 5, 5);
10168 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10169 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10170 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10171 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10172 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10173 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10174 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10175 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10177 /* Out of bounds rectangle. */
10178 SetRect(&rect, 0, 0, 65, 65);
10179 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10180 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10182 /* Combine multiple flags. */
10183 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10184 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10186 IDirectDrawSurface4_Release(surface2);
10187 IDirectDrawSurface4_Release(surface);
10189 done:
10190 IDirectDraw4_Release(ddraw);
10191 refcount = IDirect3DDevice3_Release(device);
10192 ok(!refcount, "Device has %u references left.\n", refcount);
10193 DestroyWindow(window);
10196 static void test_texcoordindex(void)
10198 static struct
10200 struct vec3 pos;
10201 struct vec2 texcoord1;
10202 struct vec2 texcoord2;
10203 struct vec2 texcoord3;
10205 quad[] =
10207 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f}},
10208 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f}},
10209 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}},
10210 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}},
10212 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_TEX3;
10213 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
10214 IDirect3DDevice3 *device;
10215 IDirect3D3 *d3d;
10216 IDirectDraw4 *ddraw;
10217 IDirectDrawSurface4 *rt;
10218 IDirect3DViewport3 *viewport;
10219 HWND window;
10220 HRESULT hr;
10221 IDirectDrawSurface4 *surface1, *surface2;
10222 IDirect3DTexture2 *texture1, *texture2;
10223 DDSURFACEDESC2 surface_desc;
10224 ULONG refcount;
10225 D3DCOLOR color;
10226 DWORD *ptr;
10228 window = create_window();
10229 if (!(device = create_device(window, DDSCL_NORMAL)))
10231 skip("Failed to create a 3D device, skipping test.\n");
10232 DestroyWindow(window);
10233 return;
10236 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
10237 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
10238 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
10239 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
10240 IDirect3D3_Release(d3d);
10242 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
10243 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10245 memset(&surface_desc, 0, sizeof(surface_desc));
10246 surface_desc.dwSize = sizeof(surface_desc);
10247 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10248 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10249 surface_desc.dwWidth = 2;
10250 surface_desc.dwHeight = 2;
10251 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10252 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
10253 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10254 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10255 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10256 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10257 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
10258 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
10259 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10260 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
10261 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10263 memset(&surface_desc, 0, sizeof(surface_desc));
10264 surface_desc.dwSize = sizeof(surface_desc);
10265 hr = IDirectDrawSurface4_Lock(surface1, 0, &surface_desc, 0, NULL);
10266 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10267 ptr = surface_desc.lpSurface;
10268 ptr[0] = 0xff000000;
10269 ptr[1] = 0xff00ff00;
10270 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
10271 ptr[0] = 0xff0000ff;
10272 ptr[1] = 0xff00ffff;
10273 hr = IDirectDrawSurface4_Unlock(surface1, NULL);
10274 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10276 memset(&surface_desc, 0, sizeof(surface_desc));
10277 surface_desc.dwSize = sizeof(surface_desc);
10278 hr = IDirectDrawSurface4_Lock(surface2, 0, &surface_desc, 0, NULL);
10279 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10280 ptr = surface_desc.lpSurface;
10281 ptr[0] = 0xff000000;
10282 ptr[1] = 0xff0000ff;
10283 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
10284 ptr[0] = 0xffff0000;
10285 ptr[1] = 0xffff00ff;
10286 hr = IDirectDrawSurface4_Unlock(surface2, 0);
10287 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10289 viewport = create_viewport(device, 0, 0, 640, 480);
10290 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
10291 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
10293 hr = IDirectDrawSurface4_QueryInterface(surface1, &IID_IDirect3DTexture2, (void **)&texture1);
10294 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
10295 hr = IDirectDrawSurface4_QueryInterface(surface2, &IID_IDirect3DTexture2, (void **)&texture2);
10296 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
10297 hr = IDirect3DDevice3_SetTexture(device, 0, texture1);
10298 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
10299 hr = IDirect3DDevice3_SetTexture(device, 1, texture2);
10300 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
10301 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10302 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10303 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
10304 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10305 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10306 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10307 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD);
10308 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10309 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10310 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10311 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
10312 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10313 hr = IDirect3DDevice3_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
10314 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10316 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_TEXCOORDINDEX, 1);
10317 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10318 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 0);
10319 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10321 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
10322 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
10324 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
10325 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10327 hr = IDirect3DDevice3_BeginScene(device);
10328 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10329 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
10330 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10331 hr = IDirect3DDevice3_EndScene(device);
10332 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10334 color = get_surface_color(rt, 160, 120);
10335 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10336 color = get_surface_color(rt, 480, 120);
10337 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10338 color = get_surface_color(rt, 160, 360);
10339 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
10340 color = get_surface_color(rt, 480, 360);
10341 ok(compare_color(color, 0x00ffffff, 2), "Got unexpected color 0x%08x.\n", color);
10343 /* D3DTSS_TEXTURETRANSFORMFLAGS was introduced in D3D7, can't test it here. */
10345 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 2);
10346 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10348 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
10349 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10351 hr = IDirect3DDevice3_BeginScene(device);
10352 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10353 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
10354 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10355 hr = IDirect3DDevice3_EndScene(device);
10356 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10358 color = get_surface_color(rt, 160, 120);
10359 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10360 color = get_surface_color(rt, 480, 120);
10361 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10362 color = get_surface_color(rt, 160, 360);
10363 ok(compare_color(color, 0x00ff00ff, 2), "Got unexpected color 0x%08x.\n", color);
10364 color = get_surface_color(rt, 480, 360);
10365 ok(compare_color(color, 0x00ffff00, 2), "Got unexpected color 0x%08x.\n", color);
10367 IDirect3DTexture2_Release(texture2);
10368 IDirect3DTexture2_Release(texture1);
10369 IDirectDrawSurface4_Release(surface2);
10370 IDirectDrawSurface4_Release(surface1);
10372 destroy_viewport(device, viewport);
10374 IDirectDrawSurface4_Release(rt);
10375 IDirectDraw_Release(ddraw);
10376 refcount = IDirect3DDevice3_Release(device);
10377 ok(!refcount, "Device has %u references left.\n", refcount);
10378 DestroyWindow(window);
10381 static void test_colorkey_precision(void)
10383 static struct
10385 struct vec3 pos;
10386 struct vec2 texcoord;
10388 quad[] =
10390 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
10391 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
10392 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
10393 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
10395 IDirect3DDevice3 *device;
10396 IDirect3D3 *d3d;
10397 IDirectDraw4 *ddraw;
10398 IDirectDrawSurface4 *rt;
10399 IDirect3DViewport3 *viewport;
10400 HWND window;
10401 HRESULT hr;
10402 IDirectDrawSurface4 *src, *dst, *texture;
10403 IDirect3DTexture2 *d3d_texture;
10404 DDSURFACEDESC2 surface_desc, lock_desc;
10405 ULONG refcount;
10406 D3DCOLOR color;
10407 unsigned int t, c;
10408 DDCOLORKEY ckey;
10409 DDBLTFX fx;
10410 DWORD data[4] = {0}, color_mask;
10411 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
10412 BOOL is_nvidia, is_warp;
10413 static const struct
10415 unsigned int max, shift, bpp, clear;
10416 const char *name;
10417 BOOL skip_nv;
10418 DDPIXELFORMAT fmt;
10420 tests[] =
10423 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8", FALSE,
10425 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10426 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
10431 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel", FALSE,
10433 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10434 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
10439 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel", FALSE,
10441 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10442 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
10447 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4", TRUE,
10449 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10450 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
10455 window = create_window();
10456 if (!(device = create_device(window, DDSCL_NORMAL)))
10458 skip("Failed to create a 3D device, skipping test.\n");
10459 DestroyWindow(window);
10460 return;
10463 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
10464 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
10465 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
10466 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
10467 IDirect3D3_Release(d3d);
10468 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
10469 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10471 is_nvidia = ddraw_is_nvidia(ddraw);
10472 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
10473 * (color key doesn't match although the values are equal), and a false
10474 * positive when the color key is 0 and the texture contains the value 1.
10475 * I don't want to mark this broken unconditionally since this would
10476 * essentially disable the test on Windows. Also on random occasions
10477 * 254 == 255 and 255 != 255.*/
10478 is_warp = ddraw_is_warp(ddraw);
10480 viewport = create_viewport(device, 0, 0, 640, 480);
10481 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
10482 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
10484 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10485 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
10486 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
10487 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
10488 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
10489 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
10490 /* Multiply the texture read result with 0, that way the result color if the key doesn't
10491 * match is constant. In theory color keying works without reading the texture result
10492 * (meaning we could just op=arg1, arg1=tfactor), but the Geforce7 Windows driver begs
10493 * to differ. */
10494 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
10495 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10496 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10497 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10498 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
10499 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10500 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x00000000);
10501 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10503 memset(&fx, 0, sizeof(fx));
10504 fx.dwSize = sizeof(fx);
10505 memset(&lock_desc, 0, sizeof(lock_desc));
10506 lock_desc.dwSize = sizeof(lock_desc);
10508 for (t = 0; t < ARRAY_SIZE(tests); ++t)
10510 if (is_nvidia && tests[t].skip_nv)
10512 win_skip("Skipping test %s on Nvidia Windows drivers.\n", tests[t].name);
10513 continue;
10516 memset(&surface_desc, 0, sizeof(surface_desc));
10517 surface_desc.dwSize = sizeof(surface_desc);
10518 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10519 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10520 surface_desc.dwWidth = 4;
10521 surface_desc.dwHeight = 1;
10522 U4(surface_desc).ddpfPixelFormat = tests[t].fmt;
10523 /* Windows XP (at least with the r200 driver, other drivers untested) produces
10524 * garbage when doing color keyed texture->texture blits. */
10525 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL);
10526 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10527 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL);
10528 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10530 U5(fx).dwFillColor = tests[t].clear;
10531 /* On the w8 testbot (WARP driver) the blit result has different values in the
10532 * X channel. */
10533 color_mask = U2(tests[t].fmt).dwRBitMask
10534 | U3(tests[t].fmt).dwGBitMask
10535 | U4(tests[t].fmt).dwBBitMask;
10537 for (c = 0; c <= tests[t].max; ++c)
10539 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
10540 * texture after it has been set once... */
10541 surface_desc.dwFlags |= DDSD_CKSRCBLT;
10542 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10543 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
10544 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
10545 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &texture, NULL);
10546 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10547 hr = IDirectDrawSurface4_QueryInterface(texture, &IID_IDirect3DTexture2, (void **)&d3d_texture);
10548 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
10549 hr = IDirect3DDevice3_SetTexture(device, 0, d3d_texture);
10550 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
10552 hr = IDirectDrawSurface4_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10553 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
10555 hr = IDirectDrawSurface4_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
10556 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10557 switch (tests[t].bpp)
10559 case 4:
10560 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
10561 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
10562 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
10563 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
10564 break;
10566 case 2:
10567 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
10568 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
10569 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
10570 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
10571 break;
10573 hr = IDirectDrawSurface4_Unlock(src, 0);
10574 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10575 hr = IDirectDrawSurface4_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
10576 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
10578 ckey.dwColorSpaceLowValue = c << tests[t].shift;
10579 ckey.dwColorSpaceHighValue = c << tests[t].shift;
10580 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
10581 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10583 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
10584 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
10586 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
10587 hr = IDirectDrawSurface4_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
10588 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10589 switch (tests[t].bpp)
10591 case 4:
10592 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
10593 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
10594 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
10595 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
10596 break;
10598 case 2:
10599 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
10600 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
10601 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
10602 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
10603 break;
10605 hr = IDirectDrawSurface4_Unlock(dst, 0);
10606 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10608 if (!c)
10610 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10611 tests[t].clear, data[0], tests[t].name, c);
10613 if (data[3] == tests[t].clear)
10615 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
10616 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
10617 * even when a different surface is used. The blit itself doesn't draw anything,
10618 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
10619 * never be masked out by the key.
10621 * On Windows 10 the problem is worse, Blt just hangs. For this reason the ARGB4444
10622 * test is disabled entirely.
10624 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
10625 * terrible on WARP. */
10626 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
10627 IDirect3DTexture2_Release(d3d_texture);
10628 IDirectDrawSurface4_Release(texture);
10629 IDirectDrawSurface4_Release(src);
10630 IDirectDrawSurface4_Release(dst);
10631 goto done;
10634 else
10635 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10636 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
10638 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10639 tests[t].clear, data[1], tests[t].name, c);
10641 if (c == tests[t].max)
10642 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10643 tests[t].clear, data[2], tests[t].name, c);
10644 else
10645 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10646 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
10648 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
10649 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10651 hr = IDirect3DDevice3_BeginScene(device);
10652 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10653 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
10654 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10655 hr = IDirect3DDevice3_EndScene(device);
10656 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10658 color = get_surface_color(rt, 80, 240);
10659 if (!c)
10660 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10661 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10662 color, tests[t].name, c);
10663 else
10664 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
10665 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10666 color, tests[t].name, c);
10668 color = get_surface_color(rt, 240, 240);
10669 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10670 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10671 color, tests[t].name, c);
10673 color = get_surface_color(rt, 400, 240);
10674 if (c == tests[t].max)
10675 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10676 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10677 color, tests[t].name, c);
10678 else
10679 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
10680 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10681 color, tests[t].name, c);
10683 IDirect3DTexture2_Release(d3d_texture);
10684 IDirectDrawSurface4_Release(texture);
10686 IDirectDrawSurface4_Release(src);
10687 IDirectDrawSurface4_Release(dst);
10689 done:
10691 destroy_viewport(device, viewport);
10692 IDirectDrawSurface4_Release(rt);
10693 IDirectDraw4_Release(ddraw);
10694 refcount = IDirect3DDevice3_Release(device);
10695 ok(!refcount, "Device has %u references left.\n", refcount);
10696 DestroyWindow(window);
10699 static void test_range_colorkey(void)
10701 IDirectDraw4 *ddraw;
10702 HWND window;
10703 HRESULT hr;
10704 IDirectDrawSurface4 *surface;
10705 DDSURFACEDESC2 surface_desc;
10706 ULONG refcount;
10707 DDCOLORKEY ckey;
10709 window = create_window();
10710 ddraw = create_ddraw();
10711 ok(!!ddraw, "Failed to create a ddraw object.\n");
10712 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10713 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10715 memset(&surface_desc, 0, sizeof(surface_desc));
10716 surface_desc.dwSize = sizeof(surface_desc);
10717 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
10718 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10719 surface_desc.dwWidth = 1;
10720 surface_desc.dwHeight = 1;
10721 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10722 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10723 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10724 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10725 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10726 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
10728 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
10729 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10730 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
10731 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10732 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10734 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
10735 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10736 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10737 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10739 /* Same for DDSCAPS_OFFSCREENPLAIN. */
10740 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10741 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10742 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
10743 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10744 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10746 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
10747 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10748 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10749 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10751 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10752 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10753 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10754 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10756 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
10757 ckey.dwColorSpaceLowValue = 0x00000000;
10758 ckey.dwColorSpaceHighValue = 0x00000001;
10759 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10760 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10762 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10763 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10764 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10765 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10767 ckey.dwColorSpaceLowValue = 0x00000001;
10768 ckey.dwColorSpaceHighValue = 0x00000000;
10769 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10770 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10772 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10773 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10774 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10775 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10777 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
10778 ckey.dwColorSpaceLowValue = 0x00000000;
10779 ckey.dwColorSpaceHighValue = 0x00000000;
10780 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10781 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10783 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
10784 ckey.dwColorSpaceLowValue = 0x00000001;
10785 ckey.dwColorSpaceHighValue = 0x00000000;
10786 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10787 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10788 ckey.dwColorSpaceLowValue = 0x00000000;
10789 ckey.dwColorSpaceHighValue = 0x00000001;
10790 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10791 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10792 /* Range destination keys don't work either. */
10793 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
10794 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10796 /* Just to show it's not because of A, R, and G having equal values. */
10797 ckey.dwColorSpaceLowValue = 0x00000000;
10798 ckey.dwColorSpaceHighValue = 0x01010101;
10799 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10800 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10802 /* None of these operations modified the key. */
10803 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10804 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10805 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10806 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10808 IDirectDrawSurface4_Release(surface),
10809 refcount = IDirectDraw4_Release(ddraw);
10810 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
10811 DestroyWindow(window);
10814 static void test_shademode(void)
10816 IDirect3DVertexBuffer *vb_strip, *vb_list, *buffer;
10817 IDirect3DViewport3 *viewport;
10818 IDirect3DDevice3 *device;
10819 D3DVERTEXBUFFERDESC desc;
10820 IDirectDrawSurface4 *rt;
10821 DWORD color0, color1;
10822 void *data = NULL;
10823 IDirect3D3 *d3d;
10824 ULONG refcount;
10825 UINT i, count;
10826 HWND window;
10827 HRESULT hr;
10828 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
10829 static const struct
10831 struct vec3 position;
10832 DWORD diffuse;
10834 quad_strip[] =
10836 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
10837 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
10838 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
10839 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
10841 quad_list[] =
10843 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
10844 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
10845 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
10847 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
10848 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
10849 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
10851 static const struct
10853 DWORD primtype;
10854 DWORD shademode;
10855 DWORD color0, color1;
10857 tests[] =
10859 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x0000ff00},
10860 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
10861 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
10862 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
10863 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
10864 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
10867 window = create_window();
10868 if (!(device = create_device(window, DDSCL_NORMAL)))
10870 skip("Failed to create a 3D device, skipping test.\n");
10871 DestroyWindow(window);
10872 return;
10875 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
10876 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
10877 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
10878 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10880 viewport = create_viewport(device, 0, 0, 640, 480);
10881 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
10882 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
10884 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
10885 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
10887 memset(&desc, 0, sizeof(desc));
10888 desc.dwSize = sizeof(desc);
10889 desc.dwCaps = D3DVBCAPS_WRITEONLY;
10890 desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
10891 desc.dwNumVertices = ARRAY_SIZE(quad_strip);
10892 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &vb_strip, 0, NULL);
10893 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
10894 hr = IDirect3DVertexBuffer_Lock(vb_strip, 0, &data, NULL);
10895 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
10896 memcpy(data, quad_strip, sizeof(quad_strip));
10897 hr = IDirect3DVertexBuffer_Unlock(vb_strip);
10898 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
10900 desc.dwNumVertices = ARRAY_SIZE(quad_list);
10901 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &vb_list, 0, NULL);
10902 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
10903 hr = IDirect3DVertexBuffer_Lock(vb_list, 0, &data, NULL);
10904 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
10905 memcpy(data, quad_list, sizeof(quad_list));
10906 hr = IDirect3DVertexBuffer_Unlock(vb_list);
10907 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
10909 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
10910 * the color fixups we have to do for FLAT shading will be dependent on that. */
10912 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10914 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
10915 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
10917 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
10918 ok(hr == D3D_OK, "Failed to set shade mode, hr %#x.\n", hr);
10920 hr = IDirect3DDevice3_BeginScene(device);
10921 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10922 buffer = tests[i].primtype == D3DPT_TRIANGLESTRIP ? vb_strip : vb_list;
10923 count = tests[i].primtype == D3DPT_TRIANGLESTRIP ? 4 : 6;
10924 hr = IDirect3DDevice3_DrawPrimitiveVB(device, tests[i].primtype, buffer, 0, count, 0);
10925 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10926 hr = IDirect3DDevice3_EndScene(device);
10927 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10929 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
10930 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
10932 /* For D3DSHADE_FLAT it should take the color of the first vertex of
10933 * each triangle. This requires EXT_provoking_vertex or similar
10934 * functionality being available. */
10935 /* PHONG should be the same as GOURAUD, since no hardware implements
10936 * this. */
10937 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
10938 i, color0, tests[i].color0);
10939 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
10940 i, color1, tests[i].color1);
10943 IDirect3DVertexBuffer_Release(vb_strip);
10944 IDirect3DVertexBuffer_Release(vb_list);
10945 destroy_viewport(device, viewport);
10946 IDirectDrawSurface4_Release(rt);
10947 IDirect3D3_Release(d3d);
10948 refcount = IDirect3DDevice3_Release(device);
10949 ok(!refcount, "Device has %u references left.\n", refcount);
10950 DestroyWindow(window);
10953 static void test_lockrect_invalid(void)
10955 unsigned int i, r;
10956 IDirectDraw4 *ddraw;
10957 IDirectDrawSurface4 *surface;
10958 HWND window;
10959 HRESULT hr;
10960 DDSURFACEDESC2 surface_desc;
10961 DDCAPS hal_caps;
10962 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
10963 static RECT valid[] =
10965 {60, 60, 68, 68},
10966 {60, 60, 60, 68},
10967 {60, 60, 68, 60},
10968 {120, 60, 128, 68},
10969 {60, 120, 68, 128},
10971 static RECT invalid[] =
10973 {68, 60, 60, 68}, /* left > right */
10974 {60, 68, 68, 60}, /* top > bottom */
10975 {-8, 60, 0, 68}, /* left < surface */
10976 {60, -8, 68, 0}, /* top < surface */
10977 {-16, 60, -8, 68}, /* right < surface */
10978 {60, -16, 68, -8}, /* bottom < surface */
10979 {60, 60, 136, 68}, /* right > surface */
10980 {60, 60, 68, 136}, /* bottom > surface */
10981 {136, 60, 144, 68}, /* left > surface */
10982 {60, 136, 68, 144}, /* top > surface */
10984 static const struct
10986 DWORD caps, caps2;
10987 const char *name;
10988 HRESULT hr;
10990 resources[] =
10992 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", DDERR_INVALIDPARAMS},
10993 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", DDERR_INVALIDPARAMS},
10994 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", DDERR_INVALIDPARAMS},
10995 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", DDERR_INVALIDPARAMS},
10996 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", DDERR_INVALIDPARAMS},
10999 window = create_window();
11000 ddraw = create_ddraw();
11001 ok(!!ddraw, "Failed to create a ddraw object.\n");
11002 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11003 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11005 memset(&hal_caps, 0, sizeof(hal_caps));
11006 hal_caps.dwSize = sizeof(hal_caps);
11007 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
11008 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
11009 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
11010 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
11012 skip("Required surface types not supported, skipping test.\n");
11013 goto done;
11016 for (r = 0; r < ARRAY_SIZE(resources); ++r)
11018 memset(&surface_desc, 0, sizeof(surface_desc));
11019 surface_desc.dwSize = sizeof(surface_desc);
11020 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11021 surface_desc.ddsCaps.dwCaps = resources[r].caps;
11022 surface_desc.ddsCaps.dwCaps2 = resources[r].caps2;
11023 surface_desc.dwWidth = 128;
11024 surface_desc.dwHeight = 128;
11025 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11026 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11027 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
11028 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xff0000;
11029 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x00ff00;
11030 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000ff;
11032 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11033 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, resources[r].name);
11035 hr = IDirectDrawSurface4_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
11036 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
11038 for (i = 0; i < ARRAY_SIZE(valid); ++i)
11040 RECT *rect = &valid[i];
11042 memset(&surface_desc, 0, sizeof(surface_desc));
11043 surface_desc.dwSize = sizeof(surface_desc);
11045 hr = IDirectDrawSurface4_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
11046 ok(SUCCEEDED(hr), "Lock failed (%#x) for rect %s, type %s.\n",
11047 hr, wine_dbgstr_rect(rect), resources[r].name);
11049 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11050 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11053 for (i = 0; i < ARRAY_SIZE(invalid); ++i)
11055 RECT *rect = &invalid[i];
11057 memset(&surface_desc, 1, sizeof(surface_desc));
11058 surface_desc.dwSize = sizeof(surface_desc);
11060 hr = IDirectDrawSurface4_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
11061 ok(hr == resources[r].hr, "Lock returned %#x for rect %s, type %s.\n",
11062 hr, wine_dbgstr_rect(rect), resources[r].name);
11063 if (SUCCEEDED(hr))
11065 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11066 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11068 else
11069 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
11072 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
11073 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#x, type %s.\n",
11074 hr, resources[r].name);
11075 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
11076 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#x, type %s.\n",
11077 hr, resources[r].name);
11078 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11079 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11081 hr = IDirectDrawSurface4_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
11082 ok(SUCCEEDED(hr), "Lock(rect = %s) failed (%#x).\n", wine_dbgstr_rect(&valid[0]), hr);
11083 hr = IDirectDrawSurface4_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
11084 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = %s) failed (%#x).\n",
11085 wine_dbgstr_rect(&valid[0]), hr);
11087 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
11088 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
11090 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11091 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11093 IDirectDrawSurface4_Release(surface);
11096 done:
11097 IDirectDraw4_Release(ddraw);
11098 DestroyWindow(window);
11101 static void test_yv12_overlay(void)
11103 IDirectDrawSurface4 *src_surface, *dst_surface;
11104 RECT rect = {13, 17, 14, 18};
11105 unsigned int offset, y;
11106 DDSURFACEDESC2 desc;
11107 unsigned char *base;
11108 IDirectDraw4 *ddraw;
11109 HWND window;
11110 HRESULT hr;
11112 window = create_window();
11113 ddraw = create_ddraw();
11114 ok(!!ddraw, "Failed to create a ddraw object.\n");
11115 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11116 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11118 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
11120 skip("Failed to create a YV12 overlay, skipping test.\n");
11121 goto done;
11124 memset(&desc, 0, sizeof(desc));
11125 desc.dwSize = sizeof(desc);
11126 hr = IDirectDrawSurface4_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
11127 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11129 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
11130 "Got unexpected flags %#x.\n", desc.dwFlags);
11131 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
11132 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
11133 "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps);
11134 ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth);
11135 ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight);
11136 /* The overlay pitch seems to have 256 byte alignment. */
11137 ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch);
11139 /* Fill the surface with some data for the blit test. */
11140 base = desc.lpSurface;
11141 /* Luminance */
11142 for (y = 0; y < desc.dwHeight; ++y)
11144 memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth);
11146 /* V */
11147 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
11149 memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth);
11151 /* U */
11152 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
11154 memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth);
11157 hr = IDirectDrawSurface4_Unlock(src_surface, NULL);
11158 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11160 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
11161 * other block-based formats like DXT the entire Y channel is stored in
11162 * one big chunk of memory, followed by the chroma channels. So partial
11163 * locks do not really make sense. Show that they are allowed nevertheless
11164 * and the offset points into the luminance data. */
11165 hr = IDirectDrawSurface4_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
11166 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11167 offset = ((const unsigned char *)desc.lpSurface - base);
11168 ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n",
11169 offset, rect.top * U1(desc).lPitch + rect.left);
11170 hr = IDirectDrawSurface4_Unlock(src_surface, NULL);
11171 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11173 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
11175 /* Windows XP with a Radeon X1600 GPU refuses to create a second
11176 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
11177 skip("Failed to create a second YV12 surface, skipping blit test.\n");
11178 IDirectDrawSurface4_Release(src_surface);
11179 goto done;
11182 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
11183 /* VMware rejects YV12 blits. This behavior has not been seen on real
11184 * hardware yet, so mark it broken. */
11185 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr);
11187 if (SUCCEEDED(hr))
11189 memset(&desc, 0, sizeof(desc));
11190 desc.dwSize = sizeof(desc);
11191 hr = IDirectDrawSurface4_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
11192 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11194 base = desc.lpSurface;
11195 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
11196 base += desc.dwHeight * U1(desc).lPitch;
11197 todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
11198 base += desc.dwHeight / 4 * U1(desc).lPitch;
11199 todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
11201 hr = IDirectDrawSurface4_Unlock(dst_surface, NULL);
11202 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11205 IDirectDrawSurface4_Release(dst_surface);
11206 IDirectDrawSurface4_Release(src_surface);
11207 done:
11208 IDirectDraw4_Release(ddraw);
11209 DestroyWindow(window);
11212 static BOOL dwm_enabled(void)
11214 BOOL ret = FALSE;
11216 if (!strcmp(winetest_platform, "wine"))
11217 return FALSE;
11218 if (!pDwmIsCompositionEnabled)
11219 return FALSE;
11220 if (FAILED(pDwmIsCompositionEnabled(&ret)))
11221 return FALSE;
11222 return ret;
11225 static void test_offscreen_overlay(void)
11227 IDirectDrawSurface4 *overlay, *offscreen, *primary;
11228 DDSURFACEDESC2 surface_desc;
11229 IDirectDraw4 *ddraw;
11230 HWND window;
11231 HRESULT hr;
11232 HDC dc;
11234 window = create_window();
11235 ddraw = create_ddraw();
11236 ok(!!ddraw, "Failed to create a ddraw object.\n");
11237 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11238 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11240 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
11242 skip("Failed to create a UYVY overlay, skipping test.\n");
11243 goto done;
11246 memset(&surface_desc, 0, sizeof(surface_desc));
11247 surface_desc.dwSize = sizeof(surface_desc);
11248 surface_desc.dwFlags = DDSD_CAPS;
11249 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
11250 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
11251 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
11253 /* On Windows 7, and probably Vista, UpdateOverlay() will return
11254 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
11255 * surface prevents this by disabling the dwm. */
11256 hr = IDirectDrawSurface4_GetDC(primary, &dc);
11257 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
11258 hr = IDirectDrawSurface4_ReleaseDC(primary, dc);
11259 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
11261 /* Try to overlay a NULL surface. */
11262 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
11263 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11264 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
11265 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11267 /* Try to overlay an offscreen surface. */
11268 memset(&surface_desc, 0, sizeof(surface_desc));
11269 surface_desc.dwSize = sizeof(surface_desc);
11270 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
11271 surface_desc.dwWidth = 64;
11272 surface_desc.dwHeight = 64;
11273 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11274 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11275 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11276 U4(surface_desc).ddpfPixelFormat.dwFourCC = 0;
11277 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
11278 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
11279 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
11280 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
11281 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
11282 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
11284 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
11285 ok(SUCCEEDED(hr) || broken(hr == DDERR_OUTOFCAPS && dwm_enabled())
11286 || broken(hr == E_NOTIMPL && ddraw_is_vmware(ddraw)),
11287 "Failed to update overlay, hr %#x.\n", hr);
11289 /* Try to overlay the primary with a non-overlay surface. */
11290 hr = IDirectDrawSurface4_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
11291 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
11292 hr = IDirectDrawSurface4_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_HIDE, NULL);
11293 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
11295 IDirectDrawSurface4_Release(offscreen);
11296 IDirectDrawSurface4_Release(primary);
11297 IDirectDrawSurface4_Release(overlay);
11298 done:
11299 IDirectDraw4_Release(ddraw);
11300 DestroyWindow(window);
11303 static void test_overlay_rect(void)
11305 IDirectDrawSurface4 *overlay, *primary = NULL;
11306 DDSURFACEDESC2 surface_desc;
11307 RECT rect = {0, 0, 64, 64};
11308 IDirectDraw4 *ddraw;
11309 LONG pos_x, pos_y;
11310 HRESULT hr, hr2;
11311 HWND window;
11312 HDC dc;
11314 window = create_window();
11315 ddraw = create_ddraw();
11316 ok(!!ddraw, "Failed to create a ddraw object.\n");
11317 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11318 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11320 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
11322 skip("Failed to create a UYVY overlay, skipping test.\n");
11323 goto done;
11326 memset(&surface_desc, 0, sizeof(surface_desc));
11327 surface_desc.dwSize = sizeof(surface_desc);
11328 surface_desc.dwFlags = DDSD_CAPS;
11329 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
11330 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
11331 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
11333 /* On Windows 7, and probably Vista, UpdateOverlay() will return
11334 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
11335 * surface prevents this by disabling the dwm. */
11336 hr = IDirectDrawSurface4_GetDC(primary, &dc);
11337 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
11338 hr = IDirectDrawSurface4_ReleaseDC(primary, dc);
11339 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
11341 /* On Windows 8 and newer DWM can't be turned off, making overlays unusable. */
11342 if (dwm_enabled())
11344 win_skip("Cannot disable DWM, skipping overlay test.\n");
11345 goto done;
11348 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is
11349 * used. This is not true in Windows Vista and earlier, but changed in
11350 * Windows 7. */
11351 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
11352 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11353 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
11354 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11355 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
11356 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11358 /* Show that the overlay position is the (top, left) coordinate of the
11359 * destination rectangle. */
11360 OffsetRect(&rect, 32, 16);
11361 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
11362 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11363 pos_x = -1; pos_y = -1;
11364 hr = IDirectDrawSurface4_GetOverlayPosition(overlay, &pos_x, &pos_y);
11365 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
11366 ok(pos_x == rect.left, "Got unexpected pos_x %d, expected %d.\n", pos_x, rect.left);
11367 ok(pos_y == rect.top, "Got unexpected pos_y %d, expected %d.\n", pos_y, rect.top);
11369 /* Passing a NULL dest rect sets the position to 0/0. Visually it can be
11370 * seen that the overlay overlays the whole primary(==screen). */
11371 hr2 = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
11372 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS || hr2 == DDERR_OUTOFCAPS, "Got unexpected hr %#x.\n", hr2);
11373 hr = IDirectDrawSurface4_GetOverlayPosition(overlay, &pos_x, &pos_y);
11374 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
11375 if (SUCCEEDED(hr2))
11377 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
11378 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
11380 else
11382 ok(pos_x == 32, "Got unexpected pos_x %d.\n", pos_x);
11383 ok(pos_y == 16, "Got unexpected pos_y %d.\n", pos_y);
11386 /* The position cannot be retrieved when the overlay is not shown. */
11387 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
11388 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11389 pos_x = -1; pos_y = -1;
11390 hr = IDirectDrawSurface4_GetOverlayPosition(overlay, &pos_x, &pos_y);
11391 ok(hr == DDERR_OVERLAYNOTVISIBLE, "Got unexpected hr %#x.\n", hr);
11392 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
11393 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
11395 IDirectDrawSurface4_Release(overlay);
11396 done:
11397 if (primary)
11398 IDirectDrawSurface4_Release(primary);
11399 IDirectDraw4_Release(ddraw);
11400 DestroyWindow(window);
11403 static void test_blt(void)
11405 IDirectDrawSurface4 *surface, *rt;
11406 DDSURFACEDESC2 surface_desc;
11407 IDirect3DDevice3 *device;
11408 IDirectDraw4 *ddraw;
11409 IDirect3D3 *d3d;
11410 unsigned int i;
11411 ULONG refcount;
11412 HWND window;
11413 HRESULT hr;
11415 static struct
11417 RECT src_rect;
11418 RECT dst_rect;
11419 HRESULT hr;
11421 test_data[] =
11423 {{160, 0, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit. */
11424 {{160, 480, 640, 0}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, flipped source. */
11425 {{640, 0, 160, 480}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, mirrored source. */
11426 {{160, 0, 480, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched x. */
11427 {{160, 160, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched y. */
11428 {{ 0, 0, 640, 480}, { 0, 0, 640, 480}, DD_OK}, /* Full surface blit. */
11429 {{ 0, 0, 640, 480}, { 0, 480, 640, 0}, DDERR_INVALIDRECT}, /* Full surface, flipped destination. */
11430 {{ 0, 0, 640, 480}, {640, 0, 0, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored destination. */
11431 {{ 0, 480, 640, 0}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, flipped source. */
11432 {{640, 0, 0, 480}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored source. */
11435 window = create_window();
11436 if (!(device = create_device(window, DDSCL_NORMAL)))
11438 skip("Failed to create a 3D device, skipping test.\n");
11439 DestroyWindow(window);
11440 return;
11443 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
11444 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
11445 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
11446 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
11447 IDirect3D3_Release(d3d);
11448 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
11449 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11451 memset(&surface_desc, 0, sizeof(surface_desc));
11452 surface_desc.dwSize = sizeof(surface_desc);
11453 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
11454 surface_desc.dwWidth = 640;
11455 surface_desc.dwHeight = 480;
11456 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11457 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11458 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11460 hr = IDirectDrawSurface4_Blt(surface, NULL, surface, NULL, 0, NULL);
11461 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
11463 hr = IDirectDrawSurface4_Blt(surface, NULL, rt, NULL, 0, NULL);
11464 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
11466 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
11468 hr = IDirectDrawSurface4_Blt(surface, &test_data[i].dst_rect,
11469 surface, &test_data[i].src_rect, DDBLT_WAIT, NULL);
11470 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
11472 hr = IDirectDrawSurface4_Blt(surface, &test_data[i].dst_rect,
11473 rt, &test_data[i].src_rect, DDBLT_WAIT, NULL);
11474 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
11476 hr = IDirectDrawSurface4_Blt(surface, &test_data[i].dst_rect,
11477 NULL, &test_data[i].src_rect, DDBLT_WAIT, NULL);
11478 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
11480 hr = IDirectDrawSurface4_Blt(surface, &test_data[i].dst_rect, NULL, NULL, DDBLT_WAIT, NULL);
11481 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
11484 IDirectDrawSurface4_Release(surface);
11485 IDirectDrawSurface4_Release(rt);
11486 IDirectDraw4_Release(ddraw);
11487 refcount = IDirect3DDevice3_Release(device);
11488 ok(!refcount, "Device has %u references left.\n", refcount);
11489 DestroyWindow(window);
11492 static void test_blt_z_alpha(void)
11494 DWORD blt_flags[] =
11496 /* 0 */
11497 DDBLT_ALPHADEST,
11498 DDBLT_ALPHADESTCONSTOVERRIDE,
11499 DDBLT_ALPHADESTNEG,
11500 DDBLT_ALPHADESTSURFACEOVERRIDE,
11501 DDBLT_ALPHAEDGEBLEND,
11502 /* 5 */
11503 DDBLT_ALPHASRC,
11504 DDBLT_ALPHASRCCONSTOVERRIDE,
11505 DDBLT_ALPHASRCNEG,
11506 DDBLT_ALPHASRCSURFACEOVERRIDE,
11507 DDBLT_ZBUFFER,
11508 /* 10 */
11509 DDBLT_ZBUFFERDESTCONSTOVERRIDE,
11510 DDBLT_ZBUFFERDESTOVERRIDE,
11511 DDBLT_ZBUFFERSRCCONSTOVERRIDE,
11512 DDBLT_ZBUFFERSRCOVERRIDE,
11514 IDirectDrawSurface4 *src_surface, *dst_surface;
11515 DDSURFACEDESC2 surface_desc;
11516 IDirectDraw4 *ddraw;
11517 DDPIXELFORMAT pf;
11518 ULONG refcount;
11519 unsigned int i;
11520 D3DCOLOR color;
11521 HWND window;
11522 HRESULT hr;
11523 DDBLTFX fx;
11525 window = create_window();
11526 ddraw = create_ddraw();
11527 ok(!!ddraw, "Failed to create a ddraw object.\n");
11528 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11529 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11531 memset(&pf, 0, sizeof(pf));
11532 pf.dwSize = sizeof(pf);
11533 pf.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
11534 U1(pf).dwRGBBitCount = 32;
11535 U2(pf).dwRBitMask = 0x00ff0000;
11536 U3(pf).dwGBitMask = 0x0000ff00;
11537 U4(pf).dwBBitMask = 0x000000ff;
11538 U5(pf).dwRGBAlphaBitMask = 0xff000000;
11540 memset(&surface_desc, 0, sizeof(surface_desc));
11541 surface_desc.dwSize = sizeof(surface_desc);
11542 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
11543 surface_desc.dwWidth = 64;
11544 surface_desc.dwHeight = 64;
11545 U4(surface_desc).ddpfPixelFormat = pf;
11546 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11548 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
11549 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
11550 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
11551 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
11553 memset(&fx, 0, sizeof(fx));
11554 fx.dwSize = sizeof(fx);
11555 fx.dwZBufferOpCode = D3DCMP_NEVER;
11556 fx.dwZDestConstBitDepth = 32;
11557 U1(fx).dwZDestConst = 0x11111111;
11558 fx.dwZSrcConstBitDepth = 32;
11559 U2(fx).dwZSrcConst = 0xeeeeeeee;
11560 fx.dwAlphaEdgeBlendBitDepth = 8;
11561 fx.dwAlphaEdgeBlend = 0x7f;
11562 fx.dwAlphaDestConstBitDepth = 8;
11563 U3(fx).dwAlphaDestConst = 0xdd;
11564 fx.dwAlphaSrcConstBitDepth = 8;
11565 U4(fx).dwAlphaSrcConst = 0x22;
11567 for (i = 0; i < ARRAY_SIZE(blt_flags); ++i)
11569 fx.dwFillColor = 0x3300ff00;
11570 hr = IDirectDrawSurface4_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11571 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
11573 fx.dwFillColor = 0xccff0000;
11574 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11575 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
11577 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, src_surface, NULL, blt_flags[i] | DDBLT_WAIT, &fx);
11578 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
11580 color = get_surface_color(dst_surface, 32, 32);
11581 ok(compare_color(color, 0x0000ff00, 0), "Test %u: Got unexpected color 0x%08x.\n", i, color);
11584 IDirectDrawSurface4_Release(dst_surface);
11585 IDirectDrawSurface4_Release(src_surface);
11586 refcount = IDirectDraw4_Release(ddraw);
11587 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
11588 DestroyWindow(window);
11591 static void test_color_clamping(void)
11593 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
11594 static D3DMATRIX mat =
11596 1.0f, 0.0f, 0.0f, 0.0f,
11597 0.0f, 1.0f, 0.0f, 0.0f,
11598 0.0f, 0.0f, 1.0f, 0.0f,
11599 0.0f, 0.0f, 0.0f, 1.0f,
11601 static struct vec3 quad[] =
11603 {-1.0f, -1.0f, 0.1f},
11604 {-1.0f, 1.0f, 0.1f},
11605 { 1.0f, -1.0f, 0.1f},
11606 { 1.0f, 1.0f, 0.1f},
11608 IDirect3DViewport3 *viewport;
11609 IDirect3DDevice3 *device;
11610 IDirectDrawSurface4 *rt;
11611 ULONG refcount;
11612 D3DCOLOR color;
11613 HWND window;
11614 HRESULT hr;
11616 window = create_window();
11617 if (!(device = create_device(window, DDSCL_NORMAL)))
11619 skip("Failed to create a 3D device, skipping test.\n");
11620 DestroyWindow(window);
11621 return;
11624 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
11625 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11627 viewport = create_viewport(device, 0, 0, 640, 480);
11628 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
11629 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
11631 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
11632 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
11633 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
11634 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
11635 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
11636 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
11637 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
11638 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
11639 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
11640 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
11641 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
11642 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
11643 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
11644 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
11645 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
11646 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
11647 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
11648 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
11650 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0xff404040);
11651 ok(SUCCEEDED(hr), "Failed to set texture factor, hr %#x.\n", hr);
11652 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_ADD);
11653 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11654 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
11655 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11656 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_SPECULAR);
11657 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11658 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_MODULATE);
11659 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11660 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TFACTOR);
11661 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11662 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
11663 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11665 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
11666 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
11668 hr = IDirect3DDevice3_BeginScene(device);
11669 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11671 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
11672 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11674 hr = IDirect3DDevice3_EndScene(device);
11675 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11677 color = get_surface_color(rt, 320, 240);
11678 ok(compare_color(color, 0x00404040, 1), "Got unexpected color 0x%08x.\n", color);
11680 destroy_viewport(device, viewport);
11681 IDirectDrawSurface4_Release(rt);
11682 refcount = IDirect3DDevice3_Release(device);
11683 ok(!refcount, "Device has %u references left.\n", refcount);
11684 DestroyWindow(window);
11687 static void test_getdc(void)
11689 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
11690 IDirectDrawSurface4 *surface, *surface2, *tmp;
11691 DDSURFACEDESC2 surface_desc, map_desc;
11692 IDirectDraw4 *ddraw;
11693 unsigned int i;
11694 HWND window;
11695 HDC dc, dc2;
11696 HRESULT hr;
11698 static const struct
11700 const char *name;
11701 DDPIXELFORMAT format;
11702 BOOL getdc_supported;
11703 HRESULT alt_result;
11705 test_data[] =
11707 {"D3DFMT_A8R8G8B8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11708 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}}, TRUE},
11709 {"D3DFMT_X8R8G8B8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
11710 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}}, TRUE},
11711 {"D3DFMT_R5G6B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11712 {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}}, TRUE},
11713 {"D3DFMT_X1R5G5B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11714 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}}, TRUE},
11715 {"D3DFMT_A1R5G5B5", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
11716 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}}, TRUE},
11717 {"D3DFMT_A4R4G4B4", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
11718 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11719 {"D3DFMT_X4R4G4B4", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11720 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11721 {"D3DFMT_A2R10G10B10", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11722 {0xc0000000}, {0x3ff00000}, {0x000ffc00}, {0x000003ff}}, TRUE},
11723 {"D3DFMT_A8B8G8R8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11724 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11725 {"D3DFMT_X8B8G8R8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
11726 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11727 {"D3DFMT_R3G3B2", {sizeof(test_data->format), DDPF_RGB, 0, {8},
11728 {0x000000e0}, {0x0000001c}, {0x00000003}, {0x00000000}}, FALSE},
11729 /* GetDC() on a P8 surface fails unless the display mode is 8 bpp.
11730 * This is not implemented in wine yet, so disable the test for now.
11731 * Succeeding P8 GetDC() calls are tested in the ddraw:visual test.
11732 {"D3DFMT_P8", {sizeof(test_data->format), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0, {8 },
11733 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11735 {"D3DFMT_L8", {sizeof(test_data->format), DDPF_LUMINANCE, 0, {8},
11736 {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11737 {"D3DFMT_A8L8", {sizeof(test_data->format), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0, {16},
11738 {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}}, FALSE},
11739 {"D3DFMT_DXT1", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'), {0},
11740 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11741 {"D3DFMT_DXT2", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'), {0},
11742 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11743 {"D3DFMT_DXT3", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'), {0},
11744 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11745 {"D3DFMT_DXT4", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'), {0},
11746 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11747 {"D3DFMT_DXT5", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'), {0},
11748 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11751 window = create_window();
11752 ddraw = create_ddraw();
11753 ok(!!ddraw, "Failed to create a ddraw object.\n");
11754 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11755 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11757 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
11759 memset(&surface_desc, 0, sizeof(surface_desc));
11760 surface_desc.dwSize = sizeof(surface_desc);
11761 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11762 surface_desc.dwWidth = 64;
11763 surface_desc.dwHeight = 64;
11764 U4(surface_desc).ddpfPixelFormat = test_data[i].format;
11765 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11767 if (FAILED(IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11769 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11770 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
11771 if (FAILED(hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11773 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
11774 continue;
11778 dc = (void *)0x1234;
11779 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11780 if (test_data[i].getdc_supported)
11781 ok(SUCCEEDED(hr) || broken(hr == test_data[i].alt_result),
11782 "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11783 else
11784 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11786 if (SUCCEEDED(hr))
11788 unsigned int width_bytes;
11789 DIBSECTION dib;
11790 HBITMAP bitmap;
11791 DWORD type;
11792 int size;
11794 type = GetObjectType(dc);
11795 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
11796 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
11797 type = GetObjectType(bitmap);
11798 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
11800 size = GetObjectA(bitmap, sizeof(dib), &dib);
11801 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, test_data[i].name);
11802 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
11803 dib.dsBm.bmType, test_data[i].name);
11804 ok(dib.dsBm.bmWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
11805 dib.dsBm.bmWidth, test_data[i].name);
11806 ok(dib.dsBm.bmHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
11807 dib.dsBm.bmHeight, test_data[i].name);
11808 width_bytes = ((dib.dsBm.bmWidth * U1(test_data[i].format).dwRGBBitCount + 31) >> 3) & ~3;
11809 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
11810 dib.dsBm.bmWidthBytes, test_data[i].name);
11811 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
11812 dib.dsBm.bmPlanes, test_data[i].name);
11813 ok(dib.dsBm.bmBitsPixel == U1(test_data[i].format).dwRGBBitCount,
11814 "Got unexpected bit count %d for format %s.\n",
11815 dib.dsBm.bmBitsPixel, test_data[i].name);
11816 ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n",
11817 dib.dsBm.bmBits, test_data[i].name);
11819 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
11820 dib.dsBmih.biSize, test_data[i].name);
11821 ok(dib.dsBmih.biWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
11822 dib.dsBmih.biHeight, test_data[i].name);
11823 ok(dib.dsBmih.biHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
11824 dib.dsBmih.biHeight, test_data[i].name);
11825 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
11826 dib.dsBmih.biPlanes, test_data[i].name);
11827 ok(dib.dsBmih.biBitCount == U1(test_data[i].format).dwRGBBitCount,
11828 "Got unexpected bit count %u for format %s.\n",
11829 dib.dsBmih.biBitCount, test_data[i].name);
11830 ok(dib.dsBmih.biCompression == (U1(test_data[i].format).dwRGBBitCount == 16 ? BI_BITFIELDS : BI_RGB)
11831 || broken(U1(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
11832 "Got unexpected compression %#x for format %s.\n",
11833 dib.dsBmih.biCompression, test_data[i].name);
11834 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
11835 dib.dsBmih.biSizeImage, test_data[i].name);
11836 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
11837 dib.dsBmih.biXPelsPerMeter, test_data[i].name);
11838 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
11839 dib.dsBmih.biYPelsPerMeter, test_data[i].name);
11840 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
11841 dib.dsBmih.biClrUsed, test_data[i].name);
11842 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
11843 dib.dsBmih.biClrImportant, test_data[i].name);
11845 if (dib.dsBmih.biCompression == BI_BITFIELDS)
11847 ok((dib.dsBitfields[0] == U2(test_data[i].format).dwRBitMask
11848 && dib.dsBitfields[1] == U3(test_data[i].format).dwGBitMask
11849 && dib.dsBitfields[2] == U4(test_data[i].format).dwBBitMask)
11850 || broken(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2]),
11851 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
11852 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
11854 else
11856 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
11857 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
11858 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
11860 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, test_data[i].name);
11861 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, test_data[i].name);
11863 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11864 ok(hr == DD_OK, "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11866 else
11868 ok(!dc, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
11871 IDirectDrawSurface4_Release(surface);
11873 if (FAILED(hr))
11874 continue;
11876 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
11877 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
11878 if (FAILED(hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11880 skip("Failed to create mip-mapped texture for format %s (hr %#x), skipping tests.\n",
11881 test_data[i].name, hr);
11882 continue;
11885 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &tmp);
11886 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
11887 hr = IDirectDrawSurface4_GetAttachedSurface(tmp, &caps, &surface2);
11888 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
11889 IDirectDrawSurface4_Release(tmp);
11891 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11892 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11893 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11894 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11895 hr = IDirectDrawSurface4_GetDC(surface2, &dc);
11896 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11897 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc);
11898 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11900 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11901 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11902 dc2 = (void *)0x1234;
11903 hr = IDirectDrawSurface4_GetDC(surface, &dc2);
11904 ok(hr == DDERR_DCALREADYCREATED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11905 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
11906 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11907 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11908 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11909 ok(hr == DDERR_NODC, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11911 map_desc.dwSize = sizeof(map_desc);
11912 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11913 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11914 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11915 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11916 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11917 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11918 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11919 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11921 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11922 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11923 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11924 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11925 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11926 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11928 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11929 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11930 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11931 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11932 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11933 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11934 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11935 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11937 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11938 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11939 hr = IDirectDrawSurface4_GetDC(surface2, &dc2);
11940 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11941 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc2);
11942 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11943 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11944 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11946 hr = IDirectDrawSurface4_GetDC(surface2, &dc);
11947 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11948 hr = IDirectDrawSurface4_GetDC(surface, &dc2);
11949 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11950 hr = IDirectDrawSurface4_ReleaseDC(surface, dc2);
11951 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11952 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc);
11953 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11955 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11956 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11957 hr = IDirectDrawSurface4_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11958 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11959 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
11960 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11961 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11962 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11964 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11965 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11966 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11967 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11968 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11969 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11970 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11971 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11973 hr = IDirectDrawSurface4_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11974 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11975 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11976 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11977 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11978 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11979 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
11980 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11982 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11983 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11984 hr = IDirectDrawSurface4_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11985 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11986 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
11987 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11988 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11989 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11991 hr = IDirectDrawSurface4_GetDC(surface2, &dc);
11992 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11993 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11994 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11995 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11996 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11997 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc);
11998 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12000 hr = IDirectDrawSurface4_Unlock(surface, NULL);
12001 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12002 hr = IDirectDrawSurface4_GetDC(surface2, &dc);
12003 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12004 hr = IDirectDrawSurface4_Unlock(surface, NULL);
12005 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12006 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc);
12007 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12008 hr = IDirectDrawSurface4_Unlock(surface, NULL);
12009 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12011 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
12012 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12013 hr = IDirectDrawSurface4_GetDC(surface, &dc);
12014 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12015 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
12016 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12017 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
12018 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12019 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
12020 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12022 IDirectDrawSurface4_Release(surface2);
12023 IDirectDrawSurface4_Release(surface);
12026 IDirectDraw4_Release(ddraw);
12027 DestroyWindow(window);
12030 static void test_draw_primitive(void)
12032 static WORD indices[] = {0, 1, 2, 3};
12033 static struct vec3 quad[] =
12035 {-1.0f, -1.0f, 0.0f},
12036 {-1.0f, 1.0f, 0.0f},
12037 { 1.0f, -1.0f, 0.0f},
12038 { 1.0f, 1.0f, 0.0f},
12040 D3DDRAWPRIMITIVESTRIDEDDATA strided;
12041 IDirect3DViewport3 *viewport;
12042 D3DVERTEXBUFFERDESC vb_desc;
12043 IDirect3DVertexBuffer *vb;
12044 IDirect3DDevice3 *device;
12045 IDirect3D3 *d3d;
12046 ULONG refcount;
12047 HWND window;
12048 HRESULT hr;
12049 void *data;
12051 window = create_window();
12052 if (!(device = create_device(window, DDSCL_NORMAL)))
12054 skip("Failed to create a 3D device, skipping test.\n");
12055 DestroyWindow(window);
12056 return;
12059 viewport = create_viewport(device, 0, 0, 640, 480);
12060 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
12061 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
12063 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
12064 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
12066 memset(&vb_desc, 0, sizeof(vb_desc));
12067 vb_desc.dwSize = sizeof(vb_desc);
12068 vb_desc.dwFVF = D3DFVF_XYZ;
12069 vb_desc.dwNumVertices = 4;
12070 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &vb, 0, NULL);
12071 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
12073 IDirect3D3_Release(d3d);
12075 memset(&strided, 0, sizeof(strided));
12077 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, NULL, 0, 0);
12078 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12079 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device,
12080 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, NULL, 0, 0);
12081 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12082 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, NULL, 0, 0);
12083 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12084 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, 0);
12085 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12086 hr = IDirect3DDevice3_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, 0);
12087 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12088 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, 0);
12089 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12091 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, indices, 4, 0);
12092 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12093 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device,
12094 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, indices, 4, 0);
12095 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12096 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, indices, 4, 0);
12097 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12099 strided.position.lpvData = quad;
12100 strided.position.dwStride = sizeof(*quad);
12101 hr = IDirect3DVertexBuffer_Lock(vb, 0, &data, NULL);
12102 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
12103 memcpy(data, quad, sizeof(quad));
12104 hr = IDirect3DVertexBuffer_Unlock(vb);
12105 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
12107 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, NULL, 0, 0);
12108 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12109 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device,
12110 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, NULL, 0, 0);
12111 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12112 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, NULL, 0, 0);
12113 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12114 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
12115 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12116 hr = IDirect3DDevice3_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, 0);
12117 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12118 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
12119 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12120 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, indices, 4, 0);
12121 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12122 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device,
12123 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, indices, 4, 0);
12124 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12125 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, indices, 4, 0);
12126 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12128 IDirect3DVertexBuffer_Release(vb);
12129 destroy_viewport(device, viewport);
12130 refcount = IDirect3DDevice3_Release(device);
12131 ok(!refcount, "Device has %u references left.\n", refcount);
12132 DestroyWindow(window);
12135 static void test_edge_antialiasing_blending(void)
12137 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
12138 IDirectDrawSurface4 *offscreen, *ds;
12139 D3DDEVICEDESC hal_desc, hel_desc;
12140 IDirect3DViewport3 *viewport;
12141 DDSURFACEDESC2 surface_desc;
12142 IDirect3DDevice3 *device;
12143 IDirectDraw4 *ddraw;
12144 IDirect3D3 *d3d;
12145 ULONG refcount;
12146 D3DCOLOR color;
12147 HWND window;
12148 HRESULT hr;
12150 static D3DMATRIX mat =
12152 1.0f, 0.0f, 0.0f, 0.0f,
12153 0.0f, 1.0f, 0.0f, 0.0f,
12154 0.0f, 0.0f, 1.0f, 0.0f,
12155 0.0f, 0.0f, 0.0f, 1.0f,
12157 static struct
12159 struct vec3 position;
12160 DWORD diffuse;
12162 green_quad[] =
12164 {{-1.0f, -1.0f, 0.1f}, 0x7f00ff00},
12165 {{-1.0f, 1.0f, 0.1f}, 0x7f00ff00},
12166 {{ 1.0f, -1.0f, 0.1f}, 0x7f00ff00},
12167 {{ 1.0f, 1.0f, 0.1f}, 0x7f00ff00},
12169 static struct
12171 struct vec3 position;
12172 DWORD diffuse;
12174 red_quad[] =
12176 {{-1.0f, -1.0f, 0.1f}, 0xccff0000},
12177 {{-1.0f, 1.0f, 0.1f}, 0xccff0000},
12178 {{ 1.0f, -1.0f, 0.1f}, 0xccff0000},
12179 {{ 1.0f, 1.0f, 0.1f}, 0xccff0000},
12182 window = create_window();
12183 if (!(device = create_device(window, DDSCL_NORMAL)))
12185 skip("Failed to create a 3D device.\n");
12186 DestroyWindow(window);
12187 return;
12190 memset(&hal_desc, 0, sizeof(hal_desc));
12191 hal_desc.dwSize = sizeof(hal_desc);
12192 memset(&hel_desc, 0, sizeof(hel_desc));
12193 hel_desc.dwSize = sizeof(hel_desc);
12194 hr = IDirect3DDevice3_GetCaps(device, &hal_desc, &hel_desc);
12195 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
12196 trace("HAL line edge antialiasing support: %#x.\n",
12197 hal_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12198 trace("HAL triangle edge antialiasing support: %#x.\n",
12199 hal_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12200 trace("HEL line edge antialiasing support: %#x.\n",
12201 hel_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12202 trace("HEL triangle edge antialiasing support: %#x.\n",
12203 hel_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12205 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
12206 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
12207 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
12208 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
12209 IDirect3D3_Release(d3d);
12211 memset(&surface_desc, 0, sizeof(surface_desc));
12212 surface_desc.dwSize = sizeof(surface_desc);
12213 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
12214 surface_desc.dwWidth = 640;
12215 surface_desc.dwHeight = 480;
12216 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
12217 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
12218 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
12219 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
12220 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
12221 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
12222 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
12223 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
12224 ok(hr == D3D_OK, "Creating the offscreen render target failed, hr %#x.\n", hr);
12226 ds = get_depth_stencil(device);
12227 hr = IDirectDrawSurface_AddAttachedSurface(offscreen, ds);
12228 todo_wine ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
12229 IDirectDrawSurface_Release(ds);
12231 hr = IDirect3DDevice3_SetRenderTarget(device, offscreen, 0);
12232 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
12234 viewport = create_viewport(device, 0, 0, 640, 480);
12235 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
12236 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
12238 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
12239 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12240 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
12241 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
12242 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
12243 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
12244 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
12245 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
12246 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
12247 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
12248 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
12249 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
12250 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
12251 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
12252 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
12253 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
12254 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
12255 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
12257 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
12258 ok(SUCCEEDED(hr), "Failed to enable blending, hr %#x.\n", hr);
12259 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
12260 ok(SUCCEEDED(hr), "Failed to set src blend, hr %#x.\n", hr);
12261 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
12262 ok(SUCCEEDED(hr), "Failed to set dest blend, hr %#x.\n", hr);
12264 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
12265 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
12266 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
12267 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12268 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
12269 ok(SUCCEEDED(hr), "Failed to set alpha op, hr %#x.\n", hr);
12270 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
12271 ok(SUCCEEDED(hr), "Failed to set alpha arg, hr %#x.\n", hr);
12273 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
12274 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12275 hr = IDirect3DDevice3_BeginScene(device);
12276 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12277 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12278 green_quad, 4, 0);
12279 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12280 hr = IDirect3DDevice3_EndScene(device);
12281 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12282 color = get_surface_color(offscreen, 320, 240);
12283 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
12285 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
12286 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12287 hr = IDirect3DDevice3_BeginScene(device);
12288 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12289 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12290 red_quad, 4, 0);
12291 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12292 hr = IDirect3DDevice3_EndScene(device);
12293 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12294 color = get_surface_color(offscreen, 320, 240);
12295 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
12297 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
12298 ok(SUCCEEDED(hr), "Failed to disable blending, hr %#x.\n", hr);
12300 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
12301 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12302 hr = IDirect3DDevice3_BeginScene(device);
12303 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12304 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12305 green_quad, 4, 0);
12306 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12307 hr = IDirect3DDevice3_EndScene(device);
12308 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12309 color = get_surface_color(offscreen, 320, 240);
12310 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12312 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
12313 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12314 hr = IDirect3DDevice3_BeginScene(device);
12315 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12316 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12317 red_quad, 4, 0);
12318 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12319 hr = IDirect3DDevice3_EndScene(device);
12320 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12321 color = get_surface_color(offscreen, 320, 240);
12322 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12324 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_EDGEANTIALIAS, TRUE);
12325 ok(SUCCEEDED(hr), "Failed to enable edge antialiasing, hr %#x.\n", hr);
12327 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
12328 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12329 hr = IDirect3DDevice3_BeginScene(device);
12330 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12331 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12332 green_quad, 4, 0);
12333 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12334 hr = IDirect3DDevice3_EndScene(device);
12335 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12336 color = get_surface_color(offscreen, 320, 240);
12337 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12339 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
12340 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12341 hr = IDirect3DDevice3_BeginScene(device);
12342 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12343 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12344 red_quad, 4, 0);
12345 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12346 hr = IDirect3DDevice3_EndScene(device);
12347 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12348 color = get_surface_color(offscreen, 320, 240);
12349 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12351 IDirectDrawSurface4_Release(offscreen);
12352 IDirectDraw3_Release(ddraw);
12353 destroy_viewport(device, viewport);
12354 refcount = IDirect3DDevice3_Release(device);
12355 ok(!refcount, "Device has %u references left.\n", refcount);
12356 DestroyWindow(window);
12359 /* TransformVertices always writes 32 bytes regardless of the input / output stride.
12360 * The stride is honored for navigating to the next vertex. 3 floats input position
12361 * are read, and 16 bytes extra vertex data are copied around. */
12362 struct transform_input
12364 float x, y, z, unused1; /* Position data, transformed. */
12365 DWORD v1, v2, v3, v4; /* Extra data, e.g. color and texture coords, copied. */
12366 DWORD unused2;
12369 struct transform_output
12371 float x, y, z, w;
12372 DWORD v1, v2, v3, v4;
12373 DWORD unused3, unused4;
12376 static void test_transform_vertices(void)
12378 IDirect3DDevice3 *device;
12379 IDirectDrawSurface4 *rt;
12380 ULONG refcount;
12381 HWND window;
12382 HRESULT hr;
12383 D3DCOLOR color;
12384 IDirect3DViewport3 *viewport;
12385 static struct transform_input position_tests[] =
12387 { 0.0f, 0.0f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
12388 { 1.0f, 1.0f, 1.0f, 8.0f, 6, 7, 8, 9, 10},
12389 {-1.0f, -1.0f, -1.0f, 4.0f, 11, 12, 13, 14, 15},
12390 { 0.5f, 0.5f, 0.5f, 2.0f, 16, 17, 18, 19, 20},
12391 {-0.5f, -0.5f, -0.5f, 1.0f, ~1U, ~2U, ~3U, ~4U, ~5U},
12392 {-0.5f, -0.5f, 0.0f, 0.0f, ~6U, ~7U, ~8U, ~9U, ~0U},
12394 static struct transform_input cliptest[] =
12396 { 25.59f, 25.59f, 1.0f, 0.0f, 1, 2, 3, 4, 5},
12397 { 25.61f, 25.61f, 1.01f, 0.0f, 1, 2, 3, 4, 5},
12398 {-25.59f, -25.59f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
12399 {-25.61f, -25.61f, -0.01f, 0.0f, 1, 2, 3, 4, 5},
12401 static struct transform_input offscreentest[] =
12403 {128.1f, 0.0f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
12405 struct transform_output out[ARRAY_SIZE(position_tests)];
12406 D3DHVERTEX out_h[ARRAY_SIZE(position_tests)];
12407 D3DTRANSFORMDATA transformdata;
12408 static const D3DVIEWPORT vp_template =
12410 sizeof(vp_template), 0, 0, 256, 256, 5.0f, 5.0f, 256.0f, 256.0f, -25.0f, 60.0f
12412 D3DVIEWPORT vp_data =
12414 sizeof(vp_data), 0, 0, 256, 256, 1.0f, 1.0f, 256.0f, 256.0f, 0.0f, 1.0f
12416 D3DVIEWPORT2 vp2_data;
12417 unsigned int i;
12418 DWORD offscreen;
12419 static D3DMATRIX mat_scale =
12421 2.0f, 0.0f, 0.0f, 0.0f,
12422 0.0f, 2.0f, 0.0f, 0.0f,
12423 0.0f, 0.0f, 2.0f, 0.0f,
12424 0.0f, 0.0f, 0.0f, 1.0f,
12426 mat_translate1 =
12428 1.0f, 0.0f, 0.0f, 0.0f,
12429 0.0f, 1.0f, 0.0f, 0.0f,
12430 0.0f, 0.0f, 1.0f, 0.0f,
12431 1.0f, 0.0f, 0.0f, 1.0f,
12433 mat_translate2 =
12435 1.0f, 0.0f, 0.0f, 0.0f,
12436 0.0f, 1.0f, 0.0f, 0.0f,
12437 0.0f, 0.0f, 1.0f, 0.0f,
12438 0.0f, 1.0f, 0.0f, 1.0f,
12440 mat_transform3 =
12442 1.0f, 0.0f, 0.0f, 0.0f,
12443 0.0f, 1.0f, 0.0f, 0.0f,
12444 0.0f, 0.0f, 1.0f, 0.0f,
12445 0.0f, 19.2f, 0.0f, 2.0f,
12447 mat_identity =
12449 1.0f, 0.0f, 0.0f, 0.0f,
12450 0.0f, 1.0f, 0.0f, 0.0f,
12451 0.0f, 0.0f, 1.0f, 0.0f,
12452 0.0f, 0.0f, 0.0f, 1.0f,
12454 static struct
12456 struct vec3 position;
12457 DWORD color;
12459 quad[] =
12461 {{-0.75f, -0.5f , 0.0f}, 0xffff0000},
12462 {{-0.75f, 0.25f, 0.0f}, 0xffff0000},
12463 {{ 0.5f, -0.5f , 0.0f}, 0xffff0000},
12464 {{ 0.5f, 0.25f, 0.0f}, 0xffff0000},
12466 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
12468 for (i = 0; i < ARRAY_SIZE(out); ++i)
12470 out[i].unused3 = 0xdeadbeef;
12471 out[i].unused4 = 0xcafecafe;
12474 window = create_window();
12475 if (!(device = create_device(window, DDSCL_NORMAL)))
12477 skip("Failed to create a 3D device.\n");
12478 DestroyWindow(window);
12479 return;
12481 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
12482 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
12484 viewport = create_viewport(device, 0, 0, 256, 256);
12485 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12486 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12488 memset(&transformdata, 0, sizeof(transformdata));
12489 transformdata.dwSize = sizeof(transformdata);
12490 transformdata.lpIn = position_tests;
12491 transformdata.dwInSize = sizeof(position_tests[0]);
12492 transformdata.lpOut = out;
12493 transformdata.dwOutSize = sizeof(out[0]);
12494 transformdata.lpHOut = NULL;
12496 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12497 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12498 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12499 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12501 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12503 static const struct vec4 cmp[] =
12505 {128.0f, 128.0f, 0.0f, 1.0f}, {129.0f, 127.0f, 1.0f, 1.0f}, {127.0f, 129.0f, -1.0f, 1.0f},
12506 {128.5f, 127.5f, 0.5f, 1.0f}, {127.5f, 128.5f, -0.5f, 1.0f}, {127.5f, 128.5f, 0.0f, 1.0f}
12509 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12510 "Vertex %u differs. Got %f %f %f %f.\n", i,
12511 out[i].x, out[i].y, out[i].z, out[i].w);
12512 ok(out[i].v1 == position_tests[i].v1 && out[i].v2 == position_tests[i].v2
12513 && out[i].v3 == position_tests[i].v3 && out[i].v4 == position_tests[i].v4,
12514 "Vertex %u payload is %u %u %u %u.\n", i, out[i].v1, out[i].v2, out[i].v3, out[i].v4);
12515 ok(out[i].unused3 == 0xdeadbeef && out[i].unused4 == 0xcafecafe,
12516 "Vertex %u unused data is %#x, %#x.\n", i, out[i].unused3, out[i].unused4);
12519 vp_data = vp_template;
12520 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12521 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12522 offscreen = 0xdeadbeef;
12523 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12524 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12525 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12526 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12528 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12530 static const struct vec4 cmp[] =
12532 {128.0f, 128.0f, 0.0f, 1.0f}, {133.0f, 123.0f, 1.0f, 1.0f}, {123.0f, 133.0f, -1.0f, 1.0f},
12533 {130.5f, 125.5f, 0.5f, 1.0f}, {125.5f, 130.5f, -0.5f, 1.0f}, {125.5f, 130.5f, 0.0f, 1.0f}
12535 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12536 "Vertex %u differs. Got %f %f %f %f.\n", i,
12537 out[i].x, out[i].y, out[i].z, out[i].w);
12540 vp_data.dwX = 10;
12541 vp_data.dwY = 20;
12542 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12543 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12544 offscreen = 0xdeadbeef;
12545 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12546 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12547 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12548 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12549 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12551 static const struct vec4 cmp[] =
12553 {138.0f, 148.0f, 0.0f, 1.0f}, {143.0f, 143.0f, 1.0f, 1.0f}, {133.0f, 153.0f, -1.0f, 1.0f},
12554 {140.5f, 145.5f, 0.5f, 1.0f}, {135.5f, 150.5f, -0.5f, 1.0f}, {135.5f, 150.5f, 0.0f, 1.0f}
12556 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12557 "Vertex %u differs. Got %f %f %f %f.\n", i,
12558 out[i].x, out[i].y, out[i].z, out[i].w);
12561 transformdata.lpHOut = out_h;
12562 offscreen = 0xdeadbeef;
12563 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12564 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12565 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12566 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12567 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12569 static const D3DHVERTEX cmp_h[] =
12571 {0, { 0.0f}, { 0.0f}, { 0.0f}}, {0, { 1.0f}, { 1.0f}, {1.0f}},
12572 {D3DCLIP_FRONT, {-1.0f}, {-1.0f}, {-1.0f}}, {0, { 0.5f}, { 0.5f}, {0.5f}},
12573 {D3DCLIP_FRONT, {-0.5f}, {-0.5f}, {-0.5f}}, {0, {-0.5f}, {-0.5f}, {0.0f}}
12575 ok(compare_float(U1(cmp_h[i]).hx, U1(out_h[i]).hx, 4096)
12576 && compare_float(U2(cmp_h[i]).hy, U2(out_h[i]).hy, 4096)
12577 && compare_float(U3(cmp_h[i]).hz, U3(out_h[i]).hz, 4096)
12578 && cmp_h[i].dwFlags == out_h[i].dwFlags,
12579 "HVertex %u differs. Got %#x %f %f %f.\n", i,
12580 out_h[i].dwFlags, U1(out_h[i]).hx, U2(out_h[i]).hy, U3(out_h[i]).hz);
12582 /* No scheme has been found behind those return values. It seems to be
12583 * whatever data windows has when throwing the vertex away. Modify the
12584 * input test vertices to test this more. Depending on the input data
12585 * it can happen that the z coord gets written into y, or similar things. */
12586 if (0)
12588 static const struct vec4 cmp[] =
12590 {138.0f, 148.0f, 0.0f, 1.0f}, {143.0f, 143.0f, 1.0f, 1.0f}, { -1.0f, -1.0f, 0.5f, 1.0f},
12591 {140.5f, 145.5f, 0.5f, 1.0f}, { -0.5f, -0.5f, -0.5f, 1.0f}, {135.5f, 150.5f, 0.0f, 1.0f}
12593 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12594 "Vertex %u differs. Got %f %f %f %f.\n", i,
12595 out[i].x, out[i].y, out[i].z, out[i].w);
12599 transformdata.lpIn = cliptest;
12600 transformdata.dwInSize = sizeof(cliptest[0]);
12601 offscreen = 0xdeadbeef;
12602 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
12603 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12604 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12605 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12606 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
12608 static const DWORD flags[] =
12611 D3DCLIP_RIGHT | D3DCLIP_BACK | D3DCLIP_TOP,
12613 D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
12615 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
12618 vp_data = vp_template;
12619 vp_data.dwWidth = 10;
12620 vp_data.dwHeight = 480;
12621 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12622 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12623 offscreen = 0xdeadbeef;
12624 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
12625 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12626 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12627 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12628 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
12630 static const DWORD flags[] =
12632 D3DCLIP_RIGHT,
12633 D3DCLIP_RIGHT | D3DCLIP_BACK,
12634 D3DCLIP_LEFT,
12635 D3DCLIP_LEFT | D3DCLIP_FRONT,
12637 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
12640 vp_data = vp_template;
12641 vp_data.dwWidth = 256;
12642 vp_data.dwHeight = 256;
12643 vp_data.dvScaleX = 1;
12644 vp_data.dvScaleY = 1;
12645 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12646 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12647 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
12648 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12649 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12650 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12651 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
12653 static const DWORD flags[] =
12656 D3DCLIP_BACK,
12658 D3DCLIP_FRONT,
12660 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
12663 /* Finally try to figure out how the DWORD dwOffscreen works.
12664 * It is a logical AND of the vertices' dwFlags members. */
12665 vp_data = vp_template;
12666 vp_data.dwWidth = 5;
12667 vp_data.dwHeight = 5;
12668 vp_data.dvScaleX = 10000.0f;
12669 vp_data.dvScaleY = 10000.0f;
12670 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12671 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12672 transformdata.lpIn = cliptest;
12673 offscreen = 0xdeadbeef;
12674 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12675 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12676 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12677 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12679 offscreen = 0xdeadbeef;
12680 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12681 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12682 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12683 ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
12684 offscreen = 0xdeadbeef;
12685 hr = IDirect3DViewport2_TransformVertices(viewport, 2,
12686 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12687 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12688 ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
12689 hr = IDirect3DViewport2_TransformVertices(viewport, 3,
12690 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12691 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12692 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12694 transformdata.lpIn = cliptest + 1;
12695 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12696 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12697 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12698 ok(offscreen == (D3DCLIP_BACK | D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
12700 transformdata.lpIn = cliptest + 2;
12701 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12702 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12703 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12704 ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
12705 offscreen = 0xdeadbeef;
12706 hr = IDirect3DViewport2_TransformVertices(viewport, 2,
12707 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12708 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12709 ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
12711 transformdata.lpIn = cliptest + 3;
12712 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12713 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12714 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12715 ok(offscreen == (D3DCLIP_FRONT | D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
12717 transformdata.lpIn = offscreentest;
12718 transformdata.dwInSize = sizeof(offscreentest[0]);
12719 vp_data = vp_template;
12720 vp_data.dwWidth = 257;
12721 vp_data.dwHeight = 257;
12722 vp_data.dvScaleX = 1.0f;
12723 vp_data.dvScaleY = 1.0f;
12724 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12725 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12726 offscreen = 0xdeadbeef;
12727 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12728 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12729 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12730 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12732 vp_data.dwWidth = 256;
12733 vp_data.dwHeight = 256;
12734 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12735 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12736 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12737 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12738 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12739 ok(offscreen == D3DCLIP_RIGHT, "Offscreen is %x.\n", offscreen);
12741 /* Test the effect of Matrices.
12743 * Basically the x coordinate ends up as ((x + 1) * 2 + 0) * 5 and
12744 * y as ((y + 0) * 2 + 1) * 5. The 5 comes from dvScaleX/Y, 2 from
12745 * the view matrix and the +1's from the world and projection matrix. */
12746 vp_data.dwX = 0;
12747 vp_data.dwY = 0;
12748 vp_data.dwWidth = 256;
12749 vp_data.dwHeight = 256;
12750 vp_data.dvScaleX = 5.0f;
12751 vp_data.dvScaleY = 5.0f;
12752 vp_data.dvMinZ = 0.0f;
12753 vp_data.dvMaxZ = 1.0f;
12754 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12755 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12757 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat_translate1);
12758 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12759 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat_scale);
12760 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12761 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat_translate2);
12762 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12764 transformdata.lpIn = position_tests;
12765 transformdata.dwInSize = sizeof(position_tests[0]);
12766 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12767 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12768 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12770 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12772 static const struct vec4 cmp[] =
12774 {138.0f, 123.0f, 0.0f, 1.0f}, {148.0f, 113.0f, 2.0f, 1.0f}, {128.0f, 133.0f, -2.0f, 1.0f},
12775 {143.0f, 118.0f, 1.0f, 1.0f}, {133.0f, 128.0f, -1.0f, 1.0f}, {133.0f, 128.0f, 0.0f, 1.0f}
12778 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12779 "Vertex %u differs. Got %f %f %f %f.\n", i,
12780 out[i].x, out[i].y, out[i].z, out[i].w);
12783 /* Invalid flags. */
12784 offscreen = 0xdeadbeef;
12785 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12786 &transformdata, 0, &offscreen);
12787 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
12788 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
12790 /* NULL transform data. */
12791 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12792 NULL, D3DTRANSFORM_UNCLIPPED, &offscreen);
12793 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
12794 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
12795 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
12796 NULL, D3DTRANSFORM_UNCLIPPED, &offscreen);
12797 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
12798 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
12800 /* NULL transform data and NULL dwOffscreen.
12802 * Valid transform data + NULL dwOffscreen -> crash. */
12803 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12804 NULL, D3DTRANSFORM_UNCLIPPED, NULL);
12805 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
12807 /* No vertices. */
12808 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
12809 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12810 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12811 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12812 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
12813 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12814 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12815 ok(offscreen == ~0U, "Offscreen is %x.\n", offscreen);
12817 /* Invalid sizes. */
12818 offscreen = 0xdeadbeef;
12819 transformdata.dwSize = sizeof(transformdata) - 1;
12820 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12821 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12822 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
12823 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
12824 transformdata.dwSize = sizeof(transformdata) + 1;
12825 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12826 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12827 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
12828 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
12830 /* NULL lpIn or lpOut -> crash, except when transforming 0 vertices. */
12831 transformdata.dwSize = sizeof(transformdata);
12832 transformdata.lpIn = NULL;
12833 transformdata.lpOut = NULL;
12834 offscreen = 0xdeadbeef;
12835 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
12836 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12837 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12838 ok(offscreen == ~0U, "Offscreen is %x.\n", offscreen);
12840 /* Test how vertices are transformed during draws. */
12841 vp_data.dwX = 20;
12842 vp_data.dwY = 20;
12843 vp_data.dwWidth = 200;
12844 vp_data.dwHeight = 400;
12845 vp_data.dvScaleX = 20.0f;
12846 vp_data.dvScaleY = 50.0f;
12847 vp_data.dvMinZ = 0.0f;
12848 vp_data.dvMaxZ = 1.0f;
12849 hr = IDirect3DViewport3_SetViewport(viewport, &vp_data);
12850 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12851 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
12852 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
12854 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
12855 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12857 hr = IDirect3DDevice3_BeginScene(device);
12858 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12859 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12860 quad, 4, 0);
12861 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12862 hr = IDirect3DDevice3_EndScene(device);
12863 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12865 color = get_surface_color(rt, 128, 143);
12866 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12867 color = get_surface_color(rt, 132, 143);
12868 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12869 color = get_surface_color(rt, 128, 147);
12870 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12871 color = get_surface_color(rt, 132, 147);
12872 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12874 color = get_surface_color(rt, 177, 217);
12875 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12876 color = get_surface_color(rt, 181, 217);
12877 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12878 color = get_surface_color(rt, 177, 221);
12879 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12880 color = get_surface_color(rt, 181, 221);
12881 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12883 /* Test D3DVIEWPORT2 behavior. */
12884 vp2_data.dwSize = sizeof(vp2_data);
12885 vp2_data.dwX = 20;
12886 vp2_data.dwY = 20;
12887 vp2_data.dwWidth = 200;
12888 vp2_data.dwHeight = 400;
12889 vp2_data.dvClipX = -0.5f;
12890 vp2_data.dvClipY = 4.0f;
12891 vp2_data.dvClipWidth = 5.0f;
12892 vp2_data.dvClipHeight = 10.0f;
12893 vp2_data.dvMinZ = 0.0f;
12894 vp2_data.dvMaxZ = 2.0f;
12895 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2_data);
12896 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
12897 transformdata.lpIn = position_tests;
12898 transformdata.lpOut = out;
12899 hr = IDirect3DViewport3_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12900 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12901 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12902 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12904 static const struct vec4 cmp[] =
12906 {120.0f, 140.0f, 0.0f, 1.0f}, {200.0f, 60.0f, 1.0f, 1.0f}, {40.0f, 220.0f, -1.0f, 1.0f},
12907 {160.0f, 100.0f, 0.5f, 1.0f}, { 80.0f, 180.0f, -0.5f, 1.0f}, {80.0f, 180.0f, 0.0f, 1.0f}
12910 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12911 "Vertex %u differs. Got %f %f %f %f.\n", i,
12912 out[i].x, out[i].y, out[i].z, out[i].w);
12915 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x0000ff00, 0.0f, 0);
12916 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12918 hr = IDirect3DDevice3_BeginScene(device);
12919 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12920 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12921 quad, 4, 0);
12922 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12923 hr = IDirect3DDevice3_EndScene(device);
12924 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12926 color = get_surface_color(rt, 58, 118);
12927 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12928 color = get_surface_color(rt, 62, 118);
12929 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12930 color = get_surface_color(rt, 58, 122);
12931 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12932 color = get_surface_color(rt, 62, 122);
12933 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12935 color = get_surface_color(rt, 157, 177);
12936 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12937 color = get_surface_color(rt, 161, 177);
12938 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12939 color = get_surface_color(rt, 157, 181);
12940 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12941 color = get_surface_color(rt, 161, 181);
12942 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12944 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat_identity);
12945 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12946 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat_identity);
12947 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12948 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat_transform3);
12949 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12951 vp2_data.dwX = 0.0;
12952 vp2_data.dwY = 0.0;
12953 vp2_data.dwWidth = 1;
12954 vp2_data.dwHeight = 1;
12955 vp2_data.dvClipX = -12.8f;
12956 vp2_data.dvClipY = 12.8f + mat_transform3._42 / mat_transform3._44;
12957 vp2_data.dvClipWidth = 25.6f;
12958 vp2_data.dvClipHeight = 25.6f;
12959 vp2_data.dvMinZ = 0.0f;
12960 vp2_data.dvMaxZ = 0.5f;
12961 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2_data);
12962 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
12963 transformdata.lpIn = cliptest;
12964 transformdata.dwInSize = sizeof(cliptest[0]);
12965 offscreen = 0xdeadbeef;
12966 hr = IDirect3DViewport3_TransformVertices(viewport, ARRAY_SIZE(cliptest),
12967 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12968 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12969 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12970 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
12972 static const D3DHVERTEX cmp_h[] =
12974 {0, { 25.59f}, { 44.79f}, { 1.0f }},
12975 {D3DCLIP_RIGHT | D3DCLIP_TOP | D3DCLIP_BACK, { 25.61f}, { 44.81f}, { 1.01f}},
12976 {0, {-25.59f}, {-6.39f }, { 0.0f }},
12977 {D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,{-25.61f}, {-6.41f }, {-0.01f}},
12979 ok(compare_float(U1(cmp_h[i]).hx, U1(out_h[i]).hx, 4096)
12980 && compare_float(U2(cmp_h[i]).hy, U2(out_h[i]).hy, 4096)
12981 && compare_float(U3(cmp_h[i]).hz, U3(out_h[i]).hz, 4096)
12982 && cmp_h[i].dwFlags == out_h[i].dwFlags,
12983 "HVertex %u differs. Got %#x %f %f %f.\n", i,
12984 out_h[i].dwFlags, U1(out_h[i]).hx, U2(out_h[i]).hy, U3(out_h[i]).hz);
12987 destroy_viewport(device, viewport);
12988 IDirectDrawSurface4_Release(rt);
12989 refcount = IDirect3DDevice3_Release(device);
12990 ok(!refcount, "Device has %u references left.\n", refcount);
12991 DestroyWindow(window);
12994 static void test_display_mode_surface_pixel_format(void)
12996 unsigned int width, height, bpp;
12997 IDirectDrawSurface4 *surface;
12998 DDSURFACEDESC2 surface_desc;
12999 IDirectDraw4 *ddraw;
13000 ULONG refcount;
13001 HWND window;
13002 HRESULT hr;
13004 if (!(ddraw = create_ddraw()))
13006 skip("Failed to create ddraw.\n");
13007 return;
13010 surface_desc.dwSize = sizeof(surface_desc);
13011 hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc);
13012 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
13013 width = surface_desc.dwWidth;
13014 height = surface_desc.dwHeight;
13016 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
13017 0, 0, width, height, NULL, NULL, NULL, NULL);
13018 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
13019 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13021 bpp = 0;
13022 if (SUCCEEDED(IDirectDraw4_SetDisplayMode(ddraw, width, height, 16, 0, 0)))
13023 bpp = 16;
13024 if (SUCCEEDED(IDirectDraw4_SetDisplayMode(ddraw, width, height, 24, 0, 0)))
13025 bpp = 24;
13026 if (SUCCEEDED(IDirectDraw4_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
13027 bpp = 32;
13028 ok(bpp, "Set display mode failed.\n");
13030 surface_desc.dwSize = sizeof(surface_desc);
13031 hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc);
13032 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
13033 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
13034 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
13035 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
13036 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
13038 memset(&surface_desc, 0, sizeof(surface_desc));
13039 surface_desc.dwSize = sizeof(surface_desc);
13040 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
13041 U5(surface_desc).dwBackBufferCount = 1;
13042 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE;
13043 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13044 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
13045 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
13046 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
13047 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
13048 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
13049 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
13050 U4(surface_desc).ddpfPixelFormat.dwFlags);
13051 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
13052 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
13053 IDirectDrawSurface4_Release(surface);
13055 memset(&surface_desc, 0, sizeof(surface_desc));
13056 surface_desc.dwSize = sizeof(surface_desc);
13057 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
13058 surface_desc.dwWidth = width;
13059 surface_desc.dwHeight = height;
13060 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13061 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13062 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
13063 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
13064 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
13065 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
13066 U4(surface_desc).ddpfPixelFormat.dwFlags);
13067 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
13068 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
13069 IDirectDrawSurface4_Release(surface);
13071 refcount = IDirectDraw4_Release(ddraw);
13072 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13073 DestroyWindow(window);
13076 static void test_surface_desc_size(void)
13078 union
13080 DWORD dwSize;
13081 DDSURFACEDESC desc1;
13082 DDSURFACEDESC2 desc2;
13083 BYTE blob[1024];
13084 } desc;
13085 IDirectDrawSurface4 *surface4;
13086 IDirectDrawSurface3 *surface3;
13087 IDirectDrawSurface *surface;
13088 DDSURFACEDESC2 surface_desc;
13089 HRESULT expected_hr, hr;
13090 IDirectDraw4 *ddraw;
13091 unsigned int i, j;
13092 ULONG refcount;
13094 static const struct
13096 unsigned int caps;
13097 const char *name;
13099 surface_caps[] =
13101 {DDSCAPS_OFFSCREENPLAIN, "offscreenplain"},
13102 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "systemmemory texture"},
13103 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "videomemory texture"},
13105 static const unsigned int desc_sizes[] =
13107 sizeof(DDSURFACEDESC),
13108 sizeof(DDSURFACEDESC2),
13109 sizeof(DDSURFACEDESC) + 1,
13110 sizeof(DDSURFACEDESC2) + 1,
13111 2 * sizeof(DDSURFACEDESC),
13112 2 * sizeof(DDSURFACEDESC2),
13113 sizeof(DDSURFACEDESC) - 1,
13114 sizeof(DDSURFACEDESC2) - 1,
13115 sizeof(DDSURFACEDESC) / 2,
13116 sizeof(DDSURFACEDESC2) / 2,
13120 sizeof(desc) / 2,
13121 sizeof(desc) - 100,
13124 if (!(ddraw = create_ddraw()))
13126 skip("Failed to create ddraw.\n");
13127 return;
13129 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
13130 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13132 for (i = 0; i < ARRAY_SIZE(surface_caps); ++i)
13134 memset(&surface_desc, 0, sizeof(surface_desc));
13135 surface_desc.dwSize = sizeof(surface_desc);
13136 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
13137 surface_desc.ddsCaps.dwCaps = surface_caps[i].caps;
13138 surface_desc.dwHeight = 128;
13139 surface_desc.dwWidth = 128;
13140 if (FAILED(IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL)))
13142 skip("Failed to create surface, type %s.\n", surface_caps[i].name);
13143 continue;
13145 hr = IDirectDrawSurface_QueryInterface(surface4, &IID_IDirectDrawSurface, (void **)&surface);
13146 ok(hr == DD_OK, "Failed to query IDirectDrawSurface, hr %#x, type %s.\n", hr, surface_caps[i].name);
13147 hr = IDirectDrawSurface_QueryInterface(surface4, &IID_IDirectDrawSurface3, (void **)&surface3);
13148 ok(hr == DD_OK, "Failed to query IDirectDrawSurface3, hr %#x, type %s.\n", hr, surface_caps[i].name);
13150 /* GetSurfaceDesc() */
13151 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13153 memset(&desc, 0, sizeof(desc));
13154 desc.dwSize = desc_sizes[j];
13155 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
13156 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc.desc1);
13157 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13158 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13160 memset(&desc, 0, sizeof(desc));
13161 desc.dwSize = desc_sizes[j];
13162 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
13163 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &desc.desc1);
13164 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13165 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13167 memset(&desc, 0, sizeof(desc));
13168 desc.dwSize = desc_sizes[j];
13169 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC2) ? DD_OK : DDERR_INVALIDPARAMS;
13170 hr = IDirectDrawSurface4_GetSurfaceDesc(surface4, &desc.desc2);
13171 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13172 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13175 /* Lock() */
13176 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13178 const BOOL valid_size = desc_sizes[j] == sizeof(DDSURFACEDESC)
13179 || desc_sizes[j] == sizeof(DDSURFACEDESC2);
13180 DWORD expected_texture_stage;
13182 memset(&desc, 0, sizeof(desc));
13183 desc.dwSize = desc_sizes[j];
13184 desc.desc2.dwTextureStage = 0xdeadbeef;
13185 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13186 hr = IDirectDrawSurface_Lock(surface, NULL, &desc.desc1, 0, 0);
13187 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13188 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13189 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13190 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
13191 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13192 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
13193 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13194 if (SUCCEEDED(hr))
13196 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
13197 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
13198 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
13199 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
13200 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13201 todo_wine_if(!expected_texture_stage)
13202 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13203 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
13204 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13205 IDirectDrawSurface_Unlock(surface, NULL);
13208 memset(&desc, 0, sizeof(desc));
13209 desc.dwSize = desc_sizes[j];
13210 desc.desc2.dwTextureStage = 0xdeadbeef;
13211 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13212 hr = IDirectDrawSurface3_Lock(surface3, NULL, &desc.desc1, 0, 0);
13213 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13214 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13215 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13216 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
13217 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13218 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
13219 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13220 if (SUCCEEDED(hr))
13222 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
13223 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
13224 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
13225 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
13226 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13227 todo_wine_if(!expected_texture_stage)
13228 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13229 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
13230 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13231 IDirectDrawSurface3_Unlock(surface3, NULL);
13234 memset(&desc, 0, sizeof(desc));
13235 desc.dwSize = desc_sizes[j];
13236 desc.desc2.dwTextureStage = 0xdeadbeef;
13237 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13238 hr = IDirectDrawSurface4_Lock(surface4, NULL, &desc.desc2, 0, 0);
13239 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13240 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13241 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13242 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
13243 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13244 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
13245 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13246 if (SUCCEEDED(hr))
13248 ok(desc.desc2.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
13249 desc.desc2.dwWidth, desc_sizes[j], surface_caps[i].name);
13250 ok(desc.desc2.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
13251 desc.desc2.dwHeight, desc_sizes[j], surface_caps[i].name);
13252 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13253 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13254 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
13255 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13256 IDirectDrawSurface4_Unlock(surface4, NULL);
13260 IDirectDrawSurface4_Release(surface4);
13261 IDirectDrawSurface3_Release(surface3);
13262 IDirectDrawSurface_Release(surface);
13265 /* GetDisplayMode() */
13266 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13268 memset(&desc, 0xcc, sizeof(desc));
13269 desc.dwSize = desc_sizes[j];
13270 expected_hr = (desc.dwSize == sizeof(DDSURFACEDESC) || desc.dwSize == sizeof(DDSURFACEDESC2))
13271 ? DD_OK : DDERR_INVALIDPARAMS;
13272 hr = IDirectDraw4_GetDisplayMode(ddraw, &desc.desc2);
13273 ok(hr == expected_hr, "Got hr %#x, expected %#x, size %u.\n", hr, expected_hr, desc_sizes[j]);
13274 if (SUCCEEDED(hr))
13276 ok(desc.dwSize == sizeof(DDSURFACEDESC2), "Wrong size %u for %u.\n", desc.dwSize, desc_sizes[j]);
13277 ok(desc.blob[desc_sizes[j]] == 0xcc, "Overflow for size %u.\n", desc_sizes[j]);
13278 ok(desc.blob[desc_sizes[j] - 1] != 0xcc, "Struct not cleared for size %u.\n", desc_sizes[j]);
13282 refcount = IDirectDraw4_Release(ddraw);
13283 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13286 static void test_get_surface_from_dc(void)
13288 IDirectDrawSurface *surface1, *tmp;
13289 IDirectDrawSurface4 *surface;
13290 DDSURFACEDESC2 surface_desc;
13291 IDirectDraw4 *ddraw;
13292 HDC dc, device_dc;
13293 ULONG refcount;
13294 HWND window;
13295 HRESULT hr;
13296 DWORD ret;
13298 window = create_window();
13299 ddraw = create_ddraw();
13300 ok(!!ddraw, "Failed to create a ddraw object.\n");
13301 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13302 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13304 memset(&surface_desc, 0, sizeof(surface_desc));
13305 surface_desc.dwSize = sizeof(surface_desc);
13306 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
13307 surface_desc.dwWidth = 64;
13308 surface_desc.dwHeight = 64;
13309 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13311 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13312 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13313 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirectDrawSurface, (void **)&surface1);
13314 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
13316 refcount = get_refcount((IUnknown *)surface1);
13317 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13318 refcount = get_refcount((IUnknown *)surface);
13319 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13321 hr = IDirectDrawSurface4_GetDC(surface, &dc);
13322 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
13324 tmp = (void *)0xdeadbeef;
13325 device_dc = (void *)0xdeadbeef;
13326 hr = GetSurfaceFromDC(NULL, &tmp, &device_dc);
13327 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13328 ok(!tmp, "Got unexpected surface %p.\n", tmp);
13329 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
13331 device_dc = (void *)0xdeadbeef;
13332 hr = GetSurfaceFromDC(dc, NULL, &device_dc);
13333 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
13334 ok(device_dc == (void *)0xdeadbeef, "Got unexpected device_dc %p.\n", device_dc);
13336 tmp = (void *)0xdeadbeef;
13337 hr = GetSurfaceFromDC(dc, &tmp, NULL);
13338 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
13339 ok(!tmp, "Got unexpected surface %p.\n", tmp);
13341 hr = GetSurfaceFromDC(dc, &tmp, &device_dc);
13342 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
13343 ok(tmp == surface1, "Got unexpected surface %p, expected %p.\n", tmp, surface1);
13344 IDirectDrawSurface_Release(tmp);
13346 ret = GetObjectType(device_dc);
13347 todo_wine ok(ret == OBJ_DC, "Got unexpected object type %#x.\n", ret);
13348 ret = GetDeviceCaps(device_dc, TECHNOLOGY);
13349 todo_wine ok(ret == DT_RASDISPLAY, "Got unexpected technology %#x.\n", ret);
13351 hr = IDirectDraw4_GetSurfaceFromDC(ddraw, dc, NULL);
13352 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
13354 hr = IDirectDraw4_GetSurfaceFromDC(ddraw, dc, (IDirectDrawSurface4 **)&tmp);
13355 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
13356 ok(tmp == surface1, "Got unexpected surface %p, expected %p.\n", tmp, surface1);
13358 refcount = get_refcount((IUnknown *)surface1);
13359 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
13360 refcount = get_refcount((IUnknown *)surface);
13361 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13363 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
13364 ok(SUCCEEDED(hr), "ReleaseDC failed, hr %#x.\n", hr);
13366 IDirectDrawSurface_Release(tmp);
13368 dc = CreateCompatibleDC(NULL);
13369 ok(!!dc, "CreateCompatibleDC failed.\n");
13371 tmp = (void *)0xdeadbeef;
13372 device_dc = (void *)0xdeadbeef;
13373 hr = GetSurfaceFromDC(dc, &tmp, &device_dc);
13374 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13375 ok(!tmp, "Got unexpected surface %p.\n", tmp);
13376 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
13378 tmp = (void *)0xdeadbeef;
13379 hr = IDirectDraw4_GetSurfaceFromDC(ddraw, dc, (IDirectDrawSurface4 **)&tmp);
13380 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13381 ok(!tmp, "Got unexpected surface %p.\n", tmp);
13383 ok(DeleteDC(dc), "DeleteDC failed.\n");
13385 tmp = (void *)0xdeadbeef;
13386 hr = IDirectDraw4_GetSurfaceFromDC(ddraw, NULL, (IDirectDrawSurface4 **)&tmp);
13387 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13388 ok(!tmp, "Got unexpected surface %p.\n", tmp);
13390 IDirectDrawSurface4_Release(surface);
13391 IDirectDrawSurface_Release(surface1);
13392 IDirectDraw4_Release(ddraw);
13393 DestroyWindow(window);
13396 static void test_ck_operation(void)
13398 IDirectDrawSurface4 *src, *dst;
13399 IDirectDrawSurface *src1, *dst1;
13400 DDSURFACEDESC2 surface_desc;
13401 IDirectDraw4 *ddraw;
13402 ULONG refcount;
13403 HWND window;
13404 HRESULT hr;
13405 D3DCOLOR *color;
13406 unsigned int i;
13407 DDCOLORKEY ckey;
13408 DDBLTFX fx;
13410 window = create_window();
13411 ddraw = create_ddraw();
13412 ok(!!ddraw, "Failed to create a ddraw object.\n");
13413 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13414 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13416 memset(&surface_desc, 0, sizeof(surface_desc));
13417 surface_desc.dwSize = sizeof(surface_desc);
13418 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
13419 surface_desc.dwWidth = 4;
13420 surface_desc.dwHeight = 1;
13421 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13422 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
13423 U1(U4(surface_desc.ddpfPixelFormat)).dwRGBBitCount = 32;
13424 U2(U4(surface_desc.ddpfPixelFormat)).dwRBitMask = 0x00ff0000;
13425 U3(U4(surface_desc.ddpfPixelFormat)).dwGBitMask = 0x0000ff00;
13426 U4(U4(surface_desc.ddpfPixelFormat)).dwBBitMask = 0x000000ff;
13427 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL);
13428 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13430 surface_desc.dwFlags |= DDSD_CKSRCBLT;
13431 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff00ff;
13432 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff00ff;
13433 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL);
13434 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13436 hr = IDirectDrawSurface4_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13437 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13438 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
13439 color = surface_desc.lpSurface;
13440 color[0] = 0x77010203;
13441 color[1] = 0x00010203;
13442 color[2] = 0x77ff00ff;
13443 color[3] = 0x00ff00ff;
13444 hr = IDirectDrawSurface4_Unlock(src, NULL);
13445 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13447 for (i = 0; i < 2; ++i)
13449 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13450 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13451 color = surface_desc.lpSurface;
13452 color[0] = 0xcccccccc;
13453 color[1] = 0xcccccccc;
13454 color[2] = 0xcccccccc;
13455 color[3] = 0xcccccccc;
13456 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13457 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13459 if (i)
13461 hr = IDirectDrawSurface4_BltFast(dst, 0, 0, src, NULL, DDBLTFAST_SRCCOLORKEY);
13462 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13464 else
13466 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, NULL);
13467 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13470 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT | DDLOCK_READONLY, NULL);
13471 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13472 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
13473 color = surface_desc.lpSurface;
13474 /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
13475 * color keying, but copy it to the destination surface. Others (sysmem surfaces) apply it for
13476 * color keying, but do not copy it into the destination surface. Nvidia neither uses it for
13477 * color keying nor copies it. */
13478 ok((color[0] == 0x77010203 && color[1] == 0x00010203
13479 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* AMD, Wine */
13480 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
13481 && color[2] == 0x00ff00ff && color[3] == 0xcccccccc) /* Sysmem surfaces? */
13482 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
13483 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Nvidia */
13484 || broken(color[0] == 0xff010203 && color[1] == 0xff010203
13485 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Testbot */,
13486 "Destination data after blitting is %08x %08x %08x %08x, i=%u.\n",
13487 color[0], color[1], color[2], color[3], i);
13488 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13489 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13492 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13493 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13494 ok(ckey.dwColorSpaceLowValue == 0x00ff00ff && ckey.dwColorSpaceHighValue == 0x00ff00ff,
13495 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13497 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
13498 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13499 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13501 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13502 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13503 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13504 ok(ckey.dwColorSpaceLowValue == 0x0000ff00 && ckey.dwColorSpaceHighValue == 0x0000ff00,
13505 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13507 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0;
13508 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0;
13509 hr = IDirectDrawSurface4_GetSurfaceDesc(src, &surface_desc);
13510 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
13511 ok(surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0x0000ff00
13512 && surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0x0000ff00,
13513 "Got unexpected color key low=%08x high=%08x.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue,
13514 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue);
13516 /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */
13517 ckey.dwColorSpaceLowValue = 0x000000ff;
13518 ckey.dwColorSpaceHighValue = 0x00000000;
13519 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13520 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13522 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13523 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13524 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13525 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
13526 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13528 ckey.dwColorSpaceLowValue = 0x000000ff;
13529 ckey.dwColorSpaceHighValue = 0x00000001;
13530 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13531 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13533 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13534 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13535 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13536 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
13537 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13539 ckey.dwColorSpaceLowValue = 0x000000fe;
13540 ckey.dwColorSpaceHighValue = 0x000000fd;
13541 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13542 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13544 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13545 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13546 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13547 ok(ckey.dwColorSpaceLowValue == 0x000000fe && ckey.dwColorSpaceHighValue == 0x000000fe,
13548 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13550 IDirectDrawSurface4_Release(src);
13551 IDirectDrawSurface4_Release(dst);
13553 /* Test source and destination keys and where they are read from. Use a surface with alpha
13554 * to avoid driver-dependent content in the X channel. */
13555 memset(&surface_desc, 0, sizeof(surface_desc));
13556 surface_desc.dwSize = sizeof(surface_desc);
13557 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
13558 surface_desc.dwWidth = 6;
13559 surface_desc.dwHeight = 1;
13560 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13561 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
13562 U1(U4(surface_desc.ddpfPixelFormat)).dwRGBBitCount = 32;
13563 U2(U4(surface_desc.ddpfPixelFormat)).dwRBitMask = 0x00ff0000;
13564 U3(U4(surface_desc.ddpfPixelFormat)).dwGBitMask = 0x0000ff00;
13565 U4(U4(surface_desc.ddpfPixelFormat)).dwBBitMask = 0x000000ff;
13566 U5(U4(surface_desc.ddpfPixelFormat)).dwRGBAlphaBitMask = 0xff000000;
13567 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL);
13568 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13569 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL);
13570 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13572 ckey.dwColorSpaceLowValue = 0x0000ff00;
13573 ckey.dwColorSpaceHighValue = 0x0000ff00;
13574 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
13575 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13576 ckey.dwColorSpaceLowValue = 0x00ff0000;
13577 ckey.dwColorSpaceHighValue = 0x00ff0000;
13578 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_DESTBLT, &ckey);
13579 ok(SUCCEEDED(hr) || hr == DDERR_NOCOLORKEYHW, "Failed to set color key, hr %#x.\n", hr);
13580 if (FAILED(hr))
13582 /* Nvidia reject dest keys, AMD allows them. This applies to vidmem and sysmem surfaces. */
13583 skip("Failed to set destination color key, skipping related tests.\n");
13584 goto done;
13587 ckey.dwColorSpaceLowValue = 0x000000ff;
13588 ckey.dwColorSpaceHighValue = 0x000000ff;
13589 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13590 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13591 ckey.dwColorSpaceLowValue = 0x000000aa;
13592 ckey.dwColorSpaceHighValue = 0x000000aa;
13593 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_DESTBLT, &ckey);
13594 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13596 memset(&fx, 0, sizeof(fx));
13597 fx.dwSize = sizeof(fx);
13598 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x00110000;
13599 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x00110000;
13600 fx.ddckDestColorkey.dwColorSpaceHighValue = 0x00001100;
13601 fx.ddckDestColorkey.dwColorSpaceLowValue = 0x00001100;
13603 hr = IDirectDrawSurface4_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13604 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13605 color = surface_desc.lpSurface;
13606 color[0] = 0x000000ff; /* Applies to src blt key in src surface. */
13607 color[1] = 0x000000aa; /* Applies to dst blt key in src surface. */
13608 color[2] = 0x00ff0000; /* Dst color key in dst surface. */
13609 color[3] = 0x0000ff00; /* Src color key in dst surface. */
13610 color[4] = 0x00001100; /* Src color key in ddbltfx. */
13611 color[5] = 0x00110000; /* Dst color key in ddbltfx. */
13612 hr = IDirectDrawSurface4_Unlock(src, NULL);
13613 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13615 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13616 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13617 color = surface_desc.lpSurface;
13618 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13619 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13620 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13622 /* Test a blit without keying. */
13623 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, 0, &fx);
13624 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13626 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13627 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13628 color = surface_desc.lpSurface;
13629 /* Should have copied src data unmodified to dst. */
13630 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13631 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13632 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13633 color[0], color[1], color[2], color[3], color[4], color[5]);
13635 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13636 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13637 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13639 /* Src key. */
13640 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
13641 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13643 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13644 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13645 color = surface_desc.lpSurface;
13646 /* Src key applied to color[0]. It is unmodified, the others are copied. */
13647 ok(color[0] == 0x55555555 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13648 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13649 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13650 color[0], color[1], color[2], color[3], color[4], color[5]);
13652 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13653 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13654 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13656 /* Src override. */
13657 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
13658 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13660 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13661 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13662 color = surface_desc.lpSurface;
13663 /* Override key applied to color[5]. It is unmodified, the others are copied. */
13664 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13665 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x55555555,
13666 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13667 color[0], color[1], color[2], color[3], color[4], color[5]);
13669 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13670 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13671 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13673 /* Src override AND src key. That is not supposed to work. */
13674 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx);
13675 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13677 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13678 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13679 color = surface_desc.lpSurface;
13680 /* Ensure the destination was not changed. */
13681 ok(color[0] == 0x55555555 && color[1] == 0x55555555 && color[2] == 0x55555555 &&
13682 color[3] == 0x55555555 && color[4] == 0x55555555 && color[5] == 0x55555555,
13683 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13684 color[0], color[1], color[2], color[3], color[4], color[5]);
13686 /* Use different dst colors for the dst key test. */
13687 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13688 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13689 color[2] = 0x00001100; /* Dest key in override. */
13690 color[3] = 0x00001100; /* Dest key in override. */
13691 color[4] = 0x000000aa; /* Dest key in src surface. */
13692 color[5] = 0x000000aa; /* Dest key in src surface. */
13693 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13694 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13696 /* Dest key blit. The key is taken from the DESTINATION surface in v4! */
13697 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13698 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13700 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13701 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13702 color = surface_desc.lpSurface;
13703 /* Dst key applied to color[0,1], they are the only changed pixels. */
13704 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
13705 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13706 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13707 color[0], color[1], color[2], color[3], color[4], color[5]);
13709 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13710 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13711 color[2] = 0x00001100; /* Dest key in override. */
13712 color[3] = 0x00001100; /* Dest key in override. */
13713 color[4] = 0x000000aa; /* Dest key in src surface. */
13714 color[5] = 0x000000aa; /* Dest key in src surface. */
13715 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13716 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13718 /* What happens with a QI'd older version of the interface? It takes the key
13719 * from the source surface. */
13720 hr = IDirectDrawSurface4_QueryInterface(src, &IID_IDirectDrawSurface, (void **)&src1);
13721 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
13722 hr = IDirectDrawSurface4_QueryInterface(dst, &IID_IDirectDrawSurface, (void **)&dst1);
13723 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
13725 hr = IDirectDrawSurface_Blt(dst1, NULL, src1, NULL, DDBLT_KEYDEST, &fx);
13726 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13728 IDirectDrawSurface_Release(dst1);
13729 IDirectDrawSurface_Release(src1);
13731 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13732 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13733 color = surface_desc.lpSurface;
13734 /* Dst key applied to color[4,5], they are the only changed pixels. */
13735 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
13736 color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000,
13737 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13738 color[0], color[1], color[2], color[3], color[4], color[5]);
13740 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13741 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13742 color[2] = 0x00001100; /* Dest key in override. */
13743 color[3] = 0x00001100; /* Dest key in override. */
13744 color[4] = 0x000000aa; /* Dest key in src surface. */
13745 color[5] = 0x000000aa; /* Dest key in src surface. */
13746 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13747 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13749 /* Dest override key blit. */
13750 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
13751 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13753 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13754 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13755 color = surface_desc.lpSurface;
13756 /* Dst key applied to color[2,3], they are the only changed pixels. */
13757 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00ff0000 &&
13758 color[3] == 0x0000ff00 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13759 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13760 color[0], color[1], color[2], color[3], color[4], color[5]);
13762 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13763 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13764 color[2] = 0x00001100; /* Dest key in override. */
13765 color[3] = 0x00001100; /* Dest key in override. */
13766 color[4] = 0x000000aa; /* Dest key in src surface. */
13767 color[5] = 0x000000aa; /* Dest key in src surface. */
13768 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13769 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13771 /* Dest override together with surface key. Supposed to fail. */
13772 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx);
13773 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13775 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13776 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13777 color = surface_desc.lpSurface;
13778 /* Destination is unchanged. */
13779 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
13780 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13781 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13782 color[0], color[1], color[2], color[3], color[4], color[5]);
13783 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13784 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13786 /* Source and destination key. This is driver dependent. New HW treats it like
13787 * DDBLT_KEYSRC. Older HW and some software renderers apply both keys. */
13788 if (0)
13790 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx);
13791 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13793 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13794 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13795 color = surface_desc.lpSurface;
13796 /* Color[0] is filtered by the src key, 2-5 are filtered by the dst key, if
13797 * the driver applies it. */
13798 ok(color[0] == 0x00ff0000 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13799 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13800 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13801 color[0], color[1], color[2], color[3], color[4], color[5]);
13803 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13804 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13805 color[2] = 0x00001100; /* Dest key in override. */
13806 color[3] = 0x00001100; /* Dest key in override. */
13807 color[4] = 0x000000aa; /* Dest key in src surface. */
13808 color[5] = 0x000000aa; /* Dest key in src surface. */
13809 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13810 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13813 /* Override keys without ddbltfx parameter fail */
13814 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, NULL);
13815 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13816 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, NULL);
13817 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13819 /* Try blitting without keys in the source surface. */
13820 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, NULL);
13821 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13822 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_DESTBLT, NULL);
13823 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13825 /* That fails now. Do not bother to check that the data is unmodified. */
13826 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
13827 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13829 /* Dest key blit still works, the destination surface key is used in v4. */
13830 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13831 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13833 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13834 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13835 color = surface_desc.lpSurface;
13836 /* Dst key applied to color[0,1], they are the only changed pixels. */
13837 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
13838 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13839 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13840 color[0], color[1], color[2], color[3], color[4], color[5]);
13841 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13842 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13844 /* Try blitting without keys in the destination surface. */
13845 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_SRCBLT, NULL);
13846 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13847 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_DESTBLT, NULL);
13848 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13850 /* This fails, as sanity would dictate. */
13851 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13852 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13854 done:
13855 IDirectDrawSurface4_Release(src);
13856 IDirectDrawSurface4_Release(dst);
13857 refcount = IDirectDraw4_Release(ddraw);
13858 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13859 DestroyWindow(window);
13862 static void test_vb_refcount(void)
13864 ULONG prev_d3d_refcount, prev_device_refcount;
13865 ULONG cur_d3d_refcount, cur_device_refcount;
13866 IDirect3DVertexBuffer *vb, *vb1;
13867 IDirect3DVertexBuffer7 *vb7;
13868 D3DVERTEXBUFFERDESC vb_desc;
13869 IDirect3DDevice3 *device;
13870 IDirect3D3 *d3d;
13871 ULONG refcount;
13872 IUnknown *unk;
13873 HWND window;
13874 HRESULT hr;
13876 window = create_window();
13877 if (!(device = create_device(window, DDSCL_NORMAL)))
13879 skip("Failed to create a 3D device, skipping test.\n");
13880 DestroyWindow(window);
13881 return;
13884 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
13885 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
13887 prev_d3d_refcount = get_refcount((IUnknown *)d3d);
13888 prev_device_refcount = get_refcount((IUnknown *)device);
13890 memset(&vb_desc, 0, sizeof(vb_desc));
13891 vb_desc.dwSize = sizeof(vb_desc);
13892 vb_desc.dwFVF = D3DFVF_XYZ;
13893 vb_desc.dwNumVertices = 4;
13894 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &vb, 0, NULL);
13895 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
13897 cur_d3d_refcount = get_refcount((IUnknown *)d3d);
13898 cur_device_refcount = get_refcount((IUnknown *)device);
13899 ok(cur_d3d_refcount == prev_d3d_refcount, "D3D object refcount changed from %u to %u.\n",
13900 prev_d3d_refcount, cur_d3d_refcount);
13901 ok(cur_device_refcount == prev_device_refcount, "Device refcount changed from %u to %u.\n",
13902 prev_device_refcount, cur_device_refcount);
13904 hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IDirect3DVertexBuffer, (void **)&vb1);
13905 ok(hr == DD_OK, "Failed to query IDirect3DVertexBuffer, hr %#x.\n", hr);
13906 IDirect3DVertexBuffer_Release(vb1);
13908 hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IDirect3DVertexBuffer7, (void **)&vb7);
13909 ok(hr == E_NOINTERFACE, "Querying IDirect3DVertexBuffer7 returned unexpected hr %#x.\n", hr);
13911 hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IUnknown, (void **)&unk);
13912 ok(hr == DD_OK, "Failed to query IUnknown, hr %#x.\n", hr);
13913 ok((IUnknown *)vb == unk,
13914 "IDirect3DVertexBuffer and IUnknown interface pointers don't match, %p != %p.\n", vb, unk);
13915 IUnknown_Release(unk);
13917 refcount = IDirect3DVertexBuffer_Release(vb);
13918 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
13919 IDirect3D3_Release(d3d);
13920 refcount = IDirect3DDevice3_Release(device);
13921 ok(!refcount, "Device has %u references left.\n", refcount);
13922 DestroyWindow(window);
13925 static void test_compute_sphere_visibility(void)
13927 static D3DMATRIX proj_1 =
13929 1.810660f, 0.000000f, 0.000000f, 0.000000f,
13930 0.000000f, 2.414213f, 0.000000f, 0.000000f,
13931 0.000000f, 0.000000f, 1.020408f, 1.000000f,
13932 0.000000f, 0.000000f, -0.102041f, 0.000000f,
13934 static D3DMATRIX proj_2 =
13936 10.0f, 0.0f, 0.0f, 0.0f,
13937 0.0f, 10.0f, 0.0f, 0.0f,
13938 0.0f, 0.0f, 10.0f, 0.0f,
13939 0.0f, 0.0f, 0.0f, 1.0f,
13941 static D3DMATRIX view_1 =
13943 1.000000f, 0.000000f, 0.000000f, 0.000000f,
13944 0.000000f, 0.768221f, -0.640185f, 0.000000f,
13945 -0.000000f, 0.640185f, 0.768221f, 0.000000f,
13946 -14.852037f, 9.857489f, 11.600972f, 1.000000f,
13948 static D3DMATRIX identity =
13950 1.0f, 0.0f, 0.0f, 0.0f,
13951 0.0f, 1.0f, 0.0f, 0.0f,
13952 0.0f, 0.0f, 1.0f, 0.0f,
13953 0.0f, 0.0f, 0.0f, 1.0f,
13955 static struct
13957 D3DMATRIX *view, *proj;
13958 unsigned int sphere_count;
13959 D3DVECTOR center[3];
13960 D3DVALUE radius[3];
13961 const DWORD expected[3];
13962 BOOL todo;
13964 tests[] =
13966 {&view_1, &proj_1, 1, {{{11.461533f}, {-4.761727f}, {-1.171646f}}}, {38.252632f}, {0x1555}},
13967 {&view_1, &proj_1, 3, {{{-3.515620f}, {-1.560661f}, {-12.464638f}},
13968 {{14.290396f}, {-2.981143f}, {-24.311312f}},
13969 {{1.461626f}, {-6.093709f}, {-13.901010f}}},
13970 {4.354097f, 12.500704f, 17.251318f}, {0x154a, 0x1555, 0x1555}},
13971 {&identity, &proj_2, 1, {{{0.0f}, {0.0f}, {0.05f}}}, {0.04f}, {0x1555}, TRUE},
13972 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.5f}}}, {0.5f}, {0x1401}},
13973 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {0.0f}, {0x401}},
13974 {&identity, &identity, 1, {{{-1.0f}, {-1.0f}, {0.5f}}}, {0.25f}, {0x1505}, TRUE}, /* 5 */
13975 {&identity, &identity, 1, {{{-20.0f}, {0.0f}, {0.5f}}}, {3.0f}, {0x154a}},
13976 {&identity, &identity, 1, {{{20.0f}, {0.0f}, {0.5f}}}, {3.0f}, {0x1562}},
13977 {&identity, &identity, 1, {{{0.0f}, {-20.0f}, {0.5f}}}, {3.0f}, {0x1616}},
13978 {&identity, &identity, 1, {{{0.0f}, {20.0f}, {0.5f}}}, {3.0f}, {0x1496}},
13979 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {-20.0f}}}, {3.0f}, {0x956}}, /* 10 */
13980 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {20.0f}}}, {3.0f}, {0x2156}},
13982 IDirect3DViewport3 *viewport;
13983 IDirect3DDevice3 *device;
13984 unsigned int i, j;
13985 DWORD result[3];
13986 ULONG refcount;
13987 HWND window;
13988 HRESULT hr;
13990 window = create_window();
13991 if (!(device = create_device(window, DDSCL_NORMAL)))
13993 skip("Failed to create a 3D device, skipping test.\n");
13994 DestroyWindow(window);
13995 return;
13998 viewport = create_viewport(device, 0, 0, 640, 480);
13999 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
14000 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
14002 IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
14004 for (i = 0; i < ARRAY_SIZE(tests); ++i)
14006 IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, tests[i].view);
14007 IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].proj);
14009 hr = IDirect3DDevice3_ComputeSphereVisibility(device, tests[i].center, tests[i].radius,
14010 tests[i].sphere_count, 0, result);
14011 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14013 for (j = 0; j < tests[i].sphere_count; ++j)
14014 todo_wine_if(tests[i].todo)
14015 ok(result[j] == tests[i].expected[j], "Test %u sphere %u: expected %#x, got %#x.\n",
14016 i, j, tests[i].expected[j], result[j]);
14019 destroy_viewport(device, viewport);
14020 refcount = IDirect3DDevice3_Release(device);
14021 ok(!refcount, "Device has %u references left.\n", refcount);
14022 DestroyWindow(window);
14025 static void test_texture_stages_limits(void)
14027 IDirectDrawSurface4 *surface;
14028 DDSURFACEDESC2 surface_desc;
14029 IDirect3DTexture2 *texture;
14030 IDirect3DDevice3 *device;
14031 IDirectDraw4 *ddraw;
14032 IDirect3D3 *d3d;
14033 unsigned int i;
14034 ULONG refcount;
14035 HWND window;
14036 HRESULT hr;
14038 window = create_window();
14039 if (!(device = create_device(window, DDSCL_NORMAL)))
14041 skip("Failed to create 3D device.\n");
14042 DestroyWindow(window);
14043 return;
14045 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
14046 ok(SUCCEEDED(hr), "Failed to get Direct3D interface, hr %#x.\n", hr);
14047 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
14048 ok(SUCCEEDED(hr), "Failed to get DirectDraw interface, hr %#x.\n", hr);
14049 IDirect3D3_Release(d3d);
14051 memset(&surface_desc, 0, sizeof(surface_desc));
14052 surface_desc.dwSize = sizeof(surface_desc);
14053 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
14054 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
14055 surface_desc.dwWidth = 16;
14056 surface_desc.dwHeight = 16;
14057 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
14058 ok(hr == DD_OK, "Failed to create surface, hr %#x.\n", hr);
14059 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
14060 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
14061 IDirectDrawSurface4_Release(surface);
14063 for (i = 0; i < 8; ++i)
14065 hr = IDirect3DDevice3_SetTexture(device, i, texture);
14066 ok(hr == D3D_OK, "Failed to set texture %u, hr %#x.\n", i, hr);
14067 hr = IDirect3DDevice3_SetTexture(device, i, NULL);
14068 ok(hr == D3D_OK, "Failed to set texture %u, hr %#x.\n", i, hr);
14069 hr = IDirect3DDevice3_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
14070 ok(hr == D3D_OK, "Failed to set texture stage state %u, hr %#x.\n", i, hr);
14073 IDirectDraw4_Release(ddraw);
14074 IDirect3DTexture2_Release(texture);
14075 refcount = IDirect3DDevice3_Release(device);
14076 ok(!refcount, "Device has %u references left.\n", refcount);
14077 DestroyWindow(window);
14080 static void test_set_render_state(void)
14082 IDirect3DDevice3 *device;
14083 ULONG refcount;
14084 HWND window;
14085 DWORD state;
14086 HRESULT hr;
14088 window = create_window();
14089 if (!(device = create_device(window, DDSCL_NORMAL)))
14091 skip("Failed to create 3D device.\n");
14092 DestroyWindow(window);
14093 return;
14096 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, TRUE);
14097 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14098 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, FALSE);
14099 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14101 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
14102 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14103 state = 0xdeadbeef;
14104 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, &state);
14105 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14106 ok(!state, "Got unexpected render state %#x.\n", state);
14107 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
14108 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14109 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, &state);
14110 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14111 ok(state == D3DTBLEND_MODULATE, "Got unexpected render state %#x.\n", state);
14113 refcount = IDirect3DDevice3_Release(device);
14114 ok(!refcount, "Device has %u references left.\n", refcount);
14115 DestroyWindow(window);
14118 static void test_map_synchronisation(void)
14120 LARGE_INTEGER frequency, diff, ts[3];
14121 IDirect3DVertexBuffer *buffer;
14122 IDirect3DViewport3 *viewport;
14123 unsigned int i, j, tri_count;
14124 D3DVERTEXBUFFERDESC vb_desc;
14125 IDirect3DDevice3 *device;
14126 BOOL unsynchronised, ret;
14127 IDirectDrawSurface4 *rt;
14128 IDirect3D3 *d3d;
14129 D3DCOLOR colour;
14130 ULONG refcount;
14131 HWND window;
14132 HRESULT hr;
14134 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
14136 /* DDLOCK_DISCARDCONTENTS and DDLOCK_NOOVERWRITE were introduced with
14137 * ddraw7 and are ignored in earlier versions. */
14138 static const struct
14140 unsigned int flags;
14141 BOOL unsynchronised;
14143 tests[] =
14145 {0, FALSE},
14146 {DDLOCK_NOOVERWRITE, FALSE},
14147 {DDLOCK_DISCARDCONTENTS, FALSE},
14148 {DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS, FALSE},
14151 static const struct quad
14153 struct
14155 struct vec3 position;
14156 DWORD diffuse;
14157 } strip[4];
14159 quad1 =
14162 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
14163 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
14164 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
14165 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
14168 quad2 =
14171 {{-1.0f, -1.0f, 0.0f}, 0xffffff00},
14172 {{-1.0f, 1.0f, 0.0f}, 0xffffff00},
14173 {{ 1.0f, -1.0f, 0.0f}, 0xffffff00},
14174 {{ 1.0f, 1.0f, 0.0f}, 0xffffff00},
14177 struct quad *quads;
14179 window = create_window();
14180 ok(!!window, "Failed to create a window.\n");
14182 if (!(device = create_device(window, DDSCL_NORMAL)))
14184 skip("Failed to create a D3D device, skipping tests.\n");
14185 DestroyWindow(window);
14186 return;
14189 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
14190 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
14192 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
14193 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
14194 viewport = create_viewport(device, 0, 0, 640, 480);
14195 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
14196 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
14198 tri_count = 0x1000;
14200 ret = QueryPerformanceFrequency(&frequency);
14201 ok(ret, "Failed to get performance counter frequency.\n");
14203 vb_desc.dwSize = sizeof(vb_desc);
14204 vb_desc.dwCaps = D3DVBCAPS_WRITEONLY;
14205 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
14206 vb_desc.dwNumVertices = tri_count + 2;
14207 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &buffer, 0, NULL);
14208 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
14209 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&quads, NULL);
14210 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
14211 for (j = 0; j < vb_desc.dwNumVertices / 4; ++j)
14213 quads[j] = quad1;
14215 hr = IDirect3DVertexBuffer_Unlock(buffer);
14216 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
14218 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
14219 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
14221 /* Initial draw to initialise states, compile shaders, etc. */
14222 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14223 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14224 hr = IDirect3DDevice3_BeginScene(device);
14225 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14226 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
14227 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14228 hr = IDirect3DDevice3_EndScene(device);
14229 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14230 /* Read the result to ensure the GPU has finished drawing. */
14231 colour = get_surface_color(rt, 320, 240);
14233 /* Time drawing tri_count triangles. */
14234 ret = QueryPerformanceCounter(&ts[0]);
14235 ok(ret, "Failed to read performance counter.\n");
14236 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14237 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14238 hr = IDirect3DDevice3_BeginScene(device);
14239 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14240 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
14241 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14242 hr = IDirect3DDevice3_EndScene(device);
14243 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14244 colour = get_surface_color(rt, 320, 240);
14245 /* Time drawing a single triangle. */
14246 ret = QueryPerformanceCounter(&ts[1]);
14247 ok(ret, "Failed to read performance counter.\n");
14248 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14249 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14250 hr = IDirect3DDevice3_BeginScene(device);
14251 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14252 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 3, 0);
14253 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14254 hr = IDirect3DDevice3_EndScene(device);
14255 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14256 colour = get_surface_color(rt, 320, 240);
14257 ret = QueryPerformanceCounter(&ts[2]);
14258 ok(ret, "Failed to read performance counter.\n");
14260 IDirect3DVertexBuffer_Release(buffer);
14262 /* Estimate the number of triangles we can draw in 100ms. */
14263 diff.QuadPart = ts[1].QuadPart - ts[0].QuadPart + ts[1].QuadPart - ts[2].QuadPart;
14264 tri_count = (tri_count * frequency.QuadPart) / (diff.QuadPart * 10);
14265 tri_count = ((tri_count + 2 + 3) & ~3) - 2;
14266 vb_desc.dwNumVertices = tri_count + 2;
14268 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
14270 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &buffer, 0, NULL);
14271 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
14272 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&quads, NULL);
14273 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
14274 for (j = 0; j < vb_desc.dwNumVertices / 4; ++j)
14276 quads[j] = quad1;
14278 hr = IDirect3DVertexBuffer_Unlock(buffer);
14279 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
14281 /* Start a draw operation. */
14282 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14283 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14284 hr = IDirect3DDevice3_BeginScene(device);
14285 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14286 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
14287 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14288 hr = IDirect3DDevice3_EndScene(device);
14289 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14291 /* Map the last quad while the draw is in progress. */
14292 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_WAIT | tests[i].flags, (void **)&quads, NULL);
14293 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
14294 quads[(vb_desc.dwNumVertices / 4) - 1] = quad2;
14295 hr = IDirect3DVertexBuffer_Unlock(buffer);
14296 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
14298 colour = get_surface_color(rt, 320, 240);
14299 unsynchronised = compare_color(colour, 0x00ffff00, 1);
14300 ok(tests[i].unsynchronised == unsynchronised, "Expected %s map for flags %#x.\n",
14301 tests[i].unsynchronised ? "unsynchronised" : "synchronised", tests[i].flags);
14303 IDirect3DVertexBuffer_Release(buffer);
14306 destroy_viewport(device, viewport);
14307 IDirectDrawSurface4_Release(rt);
14308 IDirect3D3_Release(d3d);
14309 refcount = IDirect3DDevice3_Release(device);
14310 ok(!refcount, "Device has %u references left.\n", refcount);
14311 DestroyWindow(window);
14314 static void test_depth_readback(void)
14316 DWORD depth, expected_depth, max_diff;
14317 IDirectDrawSurface4 *rt, *ds;
14318 IDirect3DViewport3 *viewport;
14319 DDSURFACEDESC2 surface_desc;
14320 IDirect3DDevice3 *device;
14321 unsigned int i, x, y;
14322 IDirectDraw4 *ddraw;
14323 IDirect3D3 *d3d;
14324 ULONG refcount;
14325 HWND window;
14326 HRESULT hr;
14327 RECT r;
14329 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
14330 static struct
14332 struct vec3 position;
14333 DWORD diffuse;
14335 quad[] =
14337 {{-1.0f, -1.0f, 0.1f}, 0xff00ff00},
14338 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
14339 {{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
14340 {{ 1.0f, 1.0f, 0.9f}, 0xff00ff00},
14343 static const struct
14345 unsigned int z_depth, s_depth, z_mask, s_mask;
14346 BOOL todo;
14348 tests[] =
14350 {16, 0, 0x0000ffff, 0x00000000},
14351 {24, 0, 0x00ffffff, 0x00000000},
14352 {32, 0, 0x00ffffff, 0x00000000},
14353 {32, 8, 0x00ffffff, 0xff000000, TRUE},
14354 {32, 0, 0xffffffff, 0x00000000},
14357 window = create_window();
14358 ok(!!window, "Failed to create a window.\n");
14360 if (!(device = create_device(window, DDSCL_NORMAL)))
14362 skip("Failed to create a D3D device, skipping tests.\n");
14363 DestroyWindow(window);
14364 return;
14367 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
14368 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
14369 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
14370 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
14372 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
14373 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
14374 viewport = create_viewport(device, 0, 0, 640, 480);
14375 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
14376 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
14378 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
14379 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
14381 ds = get_depth_stencil(device);
14382 hr = IDirectDrawSurface4_DeleteAttachedSurface(rt, 0, ds);
14383 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
14384 IDirectDrawSurface4_Release(ds);
14386 for (i = 0; i < ARRAY_SIZE(tests); ++i)
14388 memset(&surface_desc, 0, sizeof(surface_desc));
14389 surface_desc.dwSize = sizeof(surface_desc);
14390 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
14391 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
14392 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
14393 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
14394 if (tests[i].s_depth)
14395 U4(surface_desc).ddpfPixelFormat.dwFlags |= DDPF_STENCILBUFFER;
14396 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = tests[i].z_depth;
14397 U2(U4(surface_desc).ddpfPixelFormat).dwStencilBitDepth = tests[i].s_depth;
14398 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = tests[i].z_mask;
14399 U4(U4(surface_desc).ddpfPixelFormat).dwStencilBitMask = tests[i].s_mask;
14400 surface_desc.dwWidth = 640;
14401 surface_desc.dwHeight = 480;
14402 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &ds, NULL);
14403 if (FAILED(hr))
14405 skip("Format %u not supported, skipping test.\n", i);
14406 continue;
14409 hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
14410 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
14411 hr = IDirect3DDevice3_SetRenderTarget(device, rt, 0);
14412 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
14414 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect,
14415 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
14416 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14417 hr = IDirect3DDevice3_BeginScene(device);
14418 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14419 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0);
14420 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14421 hr = IDirect3DDevice3_EndScene(device);
14422 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14424 for (y = 60; y < 480; y += 120)
14426 for (x = 80; x < 640; x += 160)
14428 SetRect(&r, x, y, x + 1, y + 1);
14429 memset(&surface_desc, 0, sizeof(surface_desc));
14430 surface_desc.dwSize = sizeof(surface_desc);
14431 hr = IDirectDrawSurface4_Lock(ds, &r, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
14432 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14434 depth = *((DWORD *)surface_desc.lpSurface) & tests[i].z_mask;
14435 expected_depth = (x * (0.9 / 640.0) + y * (0.1 / 480.0)) * tests[i].z_mask;
14436 max_diff = ((0.5f * 0.9f) / 640.0f) * tests[i].z_mask;
14437 todo_wine_if(tests[i].todo)
14438 ok(abs(expected_depth - depth) <= max_diff,
14439 "Test %u: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n",
14440 i, depth, expected_depth - depth, expected_depth, max_diff, x, y);
14442 hr = IDirectDrawSurface4_Unlock(ds, &r);
14443 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14447 hr = IDirectDrawSurface4_DeleteAttachedSurface(rt, 0, ds);
14448 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
14449 IDirectDrawSurface4_Release(ds);
14452 destroy_viewport(device, viewport);
14453 IDirectDrawSurface4_Release(rt);
14454 IDirectDraw4_Release(ddraw);
14455 IDirect3D3_Release(d3d);
14456 refcount = IDirect3DDevice3_Release(device);
14457 ok(!refcount, "Device has %u references left.\n", refcount);
14458 DestroyWindow(window);
14461 static void test_clear(void)
14463 D3DRECT rect_negneg, rect_full = {{0}, {0}, {640}, {480}};
14464 IDirect3DViewport3 *viewport, *viewport2, *viewport3;
14465 IDirect3DDevice3 *device;
14466 IDirectDrawSurface4 *rt;
14467 IDirectDraw4 *ddraw;
14468 IDirect3D3 *d3d;
14469 D3DRECT rect[2];
14470 D3DCOLOR color;
14471 ULONG refcount;
14472 HWND window;
14473 HRESULT hr;
14475 window = create_window();
14476 if (!(device = create_device(window, DDSCL_NORMAL)))
14478 skip("Failed to create 3D device.\n");
14479 DestroyWindow(window);
14480 return;
14483 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
14484 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
14485 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
14486 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
14488 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
14489 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
14491 viewport = create_viewport(device, 0, 0, 640, 480);
14492 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
14493 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
14495 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
14496 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14498 /* Positive x, negative y. */
14499 U1(rect[0]).x1 = 0;
14500 U2(rect[0]).y1 = 480;
14501 U3(rect[0]).x2 = 320;
14502 U4(rect[0]).y2 = 240;
14504 /* Positive x, positive y. */
14505 U1(rect[1]).x1 = 0;
14506 U2(rect[1]).y1 = 0;
14507 U3(rect[1]).x2 = 320;
14508 U4(rect[1]).y2 = 240;
14510 /* Clear 2 rectangles with one call. Unlike d3d8/9, the refrast does not
14511 * refuse negative rectangles, but it will not clear them either. */
14512 hr = IDirect3DViewport3_Clear2(viewport, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
14513 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14515 color = get_surface_color(rt, 160, 360);
14516 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 3 (pos, neg) has color 0x%08x.\n", color);
14517 color = get_surface_color(rt, 160, 120);
14518 ok(compare_color(color, 0x00ff0000, 0), "Clear rectangle 1 (pos, pos) has color 0x%08x.\n", color);
14519 color = get_surface_color(rt, 480, 360);
14520 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (NULL) has color 0x%08x.\n", color);
14521 color = get_surface_color(rt, 480, 120);
14522 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (neg, neg) has color 0x%08x.\n", color);
14524 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
14525 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14526 /* negative x, negative y.
14527 * Also ignored, except on WARP, which clears the entire screen. */
14528 rect_negneg.x1 = 640;
14529 rect_negneg.y1 = 240;
14530 rect_negneg.x2 = 320;
14531 rect_negneg.y2 = 0;
14532 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
14533 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14535 color = get_surface_color(rt, 160, 360);
14536 ok(compare_color(color, 0x00ffffff, 0)
14537 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14538 "Got unexpected color 0x%08x.\n", color);
14539 color = get_surface_color(rt, 160, 120);
14540 ok(compare_color(color, 0x00ffffff, 0)
14541 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14542 "Got unexpected color 0x%08x.\n", color);
14543 color = get_surface_color(rt, 480, 360);
14544 ok(compare_color(color, 0x00ffffff, 0)
14545 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14546 "Got unexpected color 0x%08x.\n", color);
14547 color = get_surface_color(rt, 480, 120);
14548 ok(compare_color(color, 0x00ffffff, 0)
14549 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14550 "Got unexpected color 0x%08x.\n", color);
14552 /* Test how the viewport affects clears. */
14553 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
14554 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14556 viewport2 = create_viewport(device, 160, 120, 160, 120);
14557 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport2);
14558 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
14560 hr = IDirect3DViewport3_Clear2(viewport2, 1, &rect_full, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14561 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14563 viewport3 = create_viewport(device, 320, 240, 320, 240);
14564 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport3);
14565 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
14567 U1(rect[0]).x1 = 160;
14568 U2(rect[0]).y1 = 120;
14569 U3(rect[0]).x2 = 480;
14570 U4(rect[0]).y2 = 360;
14571 hr = IDirect3DViewport3_Clear2(viewport3, 1, &rect[0], D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
14572 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14574 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
14575 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
14577 color = get_surface_color(rt, 158, 118);
14578 ok(compare_color(color, 0x00ffffff, 0), "(158, 118) has color 0x%08x.\n", color);
14579 color = get_surface_color(rt, 162, 118);
14580 ok(compare_color(color, 0x00ffffff, 0), "(162, 118) has color 0x%08x.\n", color);
14581 color = get_surface_color(rt, 158, 122);
14582 ok(compare_color(color, 0x00ffffff, 0), "(158, 122) has color 0x%08x.\n", color);
14583 color = get_surface_color(rt, 162, 122);
14584 ok(compare_color(color, 0x000000ff, 0), "(162, 122) has color 0x%08x.\n", color);
14586 color = get_surface_color(rt, 318, 238);
14587 ok(compare_color(color, 0x000000ff, 0), "(318, 238) has color 0x%08x.\n", color);
14588 color = get_surface_color(rt, 322, 238);
14589 ok(compare_color(color, 0x00ffffff, 0), "(322, 328) has color 0x%08x.\n", color);
14590 color = get_surface_color(rt, 318, 242);
14591 ok(compare_color(color, 0x00ffffff, 0), "(318, 242) has color 0x%08x.\n", color);
14592 color = get_surface_color(rt, 322, 242);
14593 ok(compare_color(color, 0x0000ff00, 0), "(322, 242) has color 0x%08x.\n", color);
14595 color = get_surface_color(rt, 478, 358);
14596 ok(compare_color(color, 0x0000ff00, 0), "(478, 358) has color 0x%08x.\n", color);
14597 color = get_surface_color(rt, 482, 358);
14598 ok(compare_color(color, 0x00ffffff, 0), "(482, 358) has color 0x%08x.\n", color);
14599 color = get_surface_color(rt, 478, 362);
14600 ok(compare_color(color, 0x00ffffff, 0), "(478, 362) has color 0x%08x.\n", color);
14601 color = get_surface_color(rt, 482, 362);
14602 ok(compare_color(color, 0x00ffffff, 0), "(482, 362) has color 0x%08x.\n", color);
14604 /* The clear rectangle is rendertarget absolute, not relative to the
14605 * viewport. */
14606 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
14607 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14608 U1(rect[0]).x1 = 330;
14609 U2(rect[0]).y1 = 250;
14610 U3(rect[0]).x2 = 340;
14611 U4(rect[0]).y2 = 260;
14612 hr = IDirect3DViewport3_Clear2(viewport3, 1, &rect[0], D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
14613 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14615 color = get_surface_color(rt, 328, 248);
14616 ok(compare_color(color, 0x00ffffff, 0), "(328, 248) has color 0x%08x.\n", color);
14617 color = get_surface_color(rt, 332, 248);
14618 ok(compare_color(color, 0x00ffffff, 0), "(332, 248) has color 0x%08x.\n", color);
14619 color = get_surface_color(rt, 328, 252);
14620 ok(compare_color(color, 0x00ffffff, 0), "(328, 252) has color 0x%08x.\n", color);
14621 color = get_surface_color(rt, 332, 252);
14622 ok(compare_color(color, 0x0000ff00, 0), "(332, 252) has color 0x%08x.\n", color);
14624 color = get_surface_color(rt, 338, 248);
14625 ok(compare_color(color, 0x00ffffff, 0), "(338, 248) has color 0x%08x.\n", color);
14626 color = get_surface_color(rt, 342, 248);
14627 ok(compare_color(color, 0x00ffffff, 0), "(342, 248) has color 0x%08x.\n", color);
14628 color = get_surface_color(rt, 338, 252);
14629 ok(compare_color(color, 0x0000ff00, 0), "(338, 252) has color 0x%08x.\n", color);
14630 color = get_surface_color(rt, 342, 252);
14631 ok(compare_color(color, 0x00ffffff, 0), "(342, 252) has color 0x%08x.\n", color);
14633 color = get_surface_color(rt, 328, 258);
14634 ok(compare_color(color, 0x00ffffff, 0), "(328, 258) has color 0x%08x.\n", color);
14635 color = get_surface_color(rt, 332, 258);
14636 ok(compare_color(color, 0x0000ff00, 0), "(332, 258) has color 0x%08x.\n", color);
14637 color = get_surface_color(rt, 328, 262);
14638 ok(compare_color(color, 0x00ffffff, 0), "(328, 262) has color 0x%08x.\n", color);
14639 color = get_surface_color(rt, 332, 262);
14640 ok(compare_color(color, 0x00ffffff, 0), "(332, 262) has color 0x%08x.\n", color);
14642 color = get_surface_color(rt, 338, 258);
14643 ok(compare_color(color, 0x0000ff00, 0), "(338, 258) has color 0x%08x.\n", color);
14644 color = get_surface_color(rt, 342, 258);
14645 ok(compare_color(color, 0x00ffffff, 0), "(342, 258) has color 0x%08x.\n", color);
14646 color = get_surface_color(rt, 338, 262);
14647 ok(compare_color(color, 0x00ffffff, 0), "(338, 262) has color 0x%08x.\n", color);
14648 color = get_surface_color(rt, 342, 262);
14649 ok(compare_color(color, 0x00ffffff, 0), "(342, 262) has color 0x%08x.\n", color);
14651 /* COLORWRITEENABLE, SRGBWRITEENABLE and scissor rectangles do not exist
14652 * in d3d3. */
14654 IDirect3DViewport3_Release(viewport3);
14655 IDirect3DViewport3_Release(viewport2);
14656 IDirect3DViewport3_Release(viewport);
14657 IDirectDrawSurface4_Release(rt);
14658 IDirectDraw4_Release(ddraw);
14659 IDirect3D3_Release(d3d);
14660 refcount = IDirect3DDevice3_Release(device);
14661 ok(!refcount, "Device has %u references left.\n", refcount);
14662 DestroyWindow(window);
14665 struct enum_surfaces_param
14667 IDirectDrawSurface4 *surfaces[8];
14668 unsigned int count;
14671 static HRESULT WINAPI enum_surfaces_cb(IDirectDrawSurface4 *surface, DDSURFACEDESC2 *desc, void *context)
14673 struct enum_surfaces_param *param = context;
14674 BOOL found = FALSE;
14675 unsigned int i;
14677 for (i = 0; i < ARRAY_SIZE(param->surfaces); ++i)
14679 if (param->surfaces[i] == surface)
14681 found = TRUE;
14682 break;
14686 ok(found, "Unexpected surface %p enumerated.\n", surface);
14687 IDirectDrawSurface4_Release(surface);
14688 ++param->count;
14690 return DDENUMRET_OK;
14693 static void test_enum_surfaces(void)
14695 struct enum_surfaces_param param = {{0}};
14696 DDSURFACEDESC2 desc;
14697 IDirectDraw4 *ddraw;
14698 HRESULT hr;
14700 ddraw = create_ddraw();
14701 ok(!!ddraw, "Failed to create a ddraw object.\n");
14703 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
14704 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
14706 memset(&desc, 0, sizeof(desc));
14707 desc.dwSize = sizeof(desc);
14708 desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
14709 desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
14710 U2(desc).dwMipMapCount = 3;
14711 desc.dwWidth = 32;
14712 desc.dwHeight = 32;
14713 hr = IDirectDraw4_CreateSurface(ddraw, &desc, &param.surfaces[0], NULL);
14714 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
14716 hr = IDirectDrawSurface4_GetAttachedSurface(param.surfaces[0], &desc.ddsCaps, &param.surfaces[1]);
14717 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
14718 hr = IDirectDrawSurface4_GetAttachedSurface(param.surfaces[1], &desc.ddsCaps, &param.surfaces[2]);
14719 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
14720 hr = IDirectDrawSurface4_GetAttachedSurface(param.surfaces[2], &desc.ddsCaps, &param.surfaces[3]);
14721 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
14722 ok(!param.surfaces[3], "Got unexpected pointer %p.\n", param.surfaces[3]);
14724 hr = IDirectDraw4_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
14725 &desc, &param, enum_surfaces_cb);
14726 ok(SUCCEEDED(hr), "Failed to enumerate surfaces, hr %#x.\n", hr);
14727 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
14729 param.count = 0;
14730 hr = IDirectDraw4_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
14731 NULL, &param, enum_surfaces_cb);
14732 ok(SUCCEEDED(hr), "Failed to enumerate surfaces, hr %#x.\n", hr);
14733 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
14735 IDirectDrawSurface4_Release(param.surfaces[2]);
14736 IDirectDrawSurface4_Release(param.surfaces[1]);
14737 IDirectDrawSurface4_Release(param.surfaces[0]);
14738 IDirectDraw4_Release(ddraw);
14741 START_TEST(ddraw4)
14743 DDDEVICEIDENTIFIER identifier;
14744 DEVMODEW current_mode;
14745 IDirectDraw4 *ddraw;
14746 HMODULE dwmapi;
14748 if (!(ddraw = create_ddraw()))
14750 skip("Failed to create a ddraw object, skipping tests.\n");
14751 return;
14754 if (ddraw_get_identifier(ddraw, &identifier))
14756 trace("Driver string: \"%s\"\n", identifier.szDriver);
14757 trace("Description string: \"%s\"\n", identifier.szDescription);
14758 trace("Driver version %d.%d.%d.%d\n",
14759 HIWORD(U(identifier.liDriverVersion).HighPart), LOWORD(U(identifier.liDriverVersion).HighPart),
14760 HIWORD(U(identifier.liDriverVersion).LowPart), LOWORD(U(identifier.liDriverVersion).LowPart));
14762 IDirectDraw4_Release(ddraw);
14764 memset(&current_mode, 0, sizeof(current_mode));
14765 current_mode.dmSize = sizeof(current_mode);
14766 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
14767 registry_mode.dmSize = sizeof(registry_mode);
14768 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
14769 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
14770 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
14772 skip("Current mode does not match registry mode, skipping test.\n");
14773 return;
14776 if ((dwmapi = LoadLibraryA("dwmapi.dll")))
14777 pDwmIsCompositionEnabled = (void *)GetProcAddress(dwmapi, "DwmIsCompositionEnabled");
14779 test_process_vertices();
14780 test_coop_level_create_device_window();
14781 test_clipper_blt();
14782 test_coop_level_d3d_state();
14783 test_surface_interface_mismatch();
14784 test_coop_level_threaded();
14785 test_depth_blit();
14786 test_texture_load_ckey();
14787 test_viewport();
14788 test_zenable();
14789 test_ck_rgba();
14790 test_ck_default();
14791 test_ck_complex();
14792 test_surface_qi();
14793 test_device_qi();
14794 test_wndproc();
14795 test_window_style();
14796 test_redundant_mode_set();
14797 test_coop_level_mode_set();
14798 test_coop_level_mode_set_multi();
14799 test_initialize();
14800 test_coop_level_surf_create();
14801 test_vb_discard();
14802 test_coop_level_multi_window();
14803 test_draw_strided();
14804 test_lighting();
14805 test_specular_lighting();
14806 test_clear_rect_count();
14807 test_coop_level_versions();
14808 test_lighting_interface_versions();
14809 test_coop_level_activateapp();
14810 test_texturemanage();
14811 test_block_formats_creation();
14812 test_unsupported_formats();
14813 test_rt_caps();
14814 test_primary_caps();
14815 test_surface_lock();
14816 test_surface_discard();
14817 test_flip();
14818 test_set_surface_desc();
14819 test_user_memory_getdc();
14820 test_sysmem_overlay();
14821 test_primary_palette();
14822 test_surface_attachment();
14823 test_private_data();
14824 test_pixel_format();
14825 test_create_surface_pitch();
14826 test_mipmap();
14827 test_palette_complex();
14828 test_p8_blit();
14829 test_material();
14830 test_palette_gdi();
14831 test_palette_alpha();
14832 test_vb_writeonly();
14833 test_lost_device();
14834 test_surface_desc_lock();
14835 test_texturemapblend();
14836 test_signed_formats();
14837 test_color_fill();
14838 test_texcoordindex();
14839 test_colorkey_precision();
14840 test_range_colorkey();
14841 test_shademode();
14842 test_lockrect_invalid();
14843 test_yv12_overlay();
14844 test_offscreen_overlay();
14845 test_overlay_rect();
14846 test_blt();
14847 test_blt_z_alpha();
14848 test_color_clamping();
14849 test_getdc();
14850 test_draw_primitive();
14851 test_edge_antialiasing_blending();
14852 test_transform_vertices();
14853 test_display_mode_surface_pixel_format();
14854 test_surface_desc_size();
14855 test_get_surface_from_dc();
14856 test_ck_operation();
14857 test_vb_refcount();
14858 test_compute_sphere_visibility();
14859 test_texture_stages_limits();
14860 test_set_render_state();
14861 test_map_synchronisation();
14862 test_depth_readback();
14863 test_clear();
14864 test_enum_surfaces();