ddraw/tests: Mark WARP negative rectangle handling broken.
[wine.git] / dlls / ddraw / tests / ddraw4.c
blobdab1e6d0f97defb811d97a5a9db680b3a1143235
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 IDirectDraw4_Release(ddraw);
3658 static void test_vb_discard(void)
3660 static const struct vec4 quad[] =
3662 { 0.0f, 480.0f, 0.0f, 1.0f},
3663 { 0.0f, 0.0f, 0.0f, 1.0f},
3664 {640.0f, 480.0f, 0.0f, 1.0f},
3665 {640.0f, 0.0f, 0.0f, 1.0f},
3668 IDirect3DDevice3 *device;
3669 IDirect3D3 *d3d;
3670 IDirect3DVertexBuffer *buffer;
3671 HWND window;
3672 HRESULT hr;
3673 D3DVERTEXBUFFERDESC desc;
3674 BYTE *data;
3675 static const unsigned int vbsize = 16;
3676 unsigned int i;
3678 window = create_window();
3679 if (!(device = create_device(window, DDSCL_NORMAL)))
3681 skip("Failed to create a 3D device, skipping test.\n");
3682 DestroyWindow(window);
3683 return;
3686 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
3687 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
3689 memset(&desc, 0, sizeof(desc));
3690 desc.dwSize = sizeof(desc);
3691 desc.dwCaps = D3DVBCAPS_WRITEONLY;
3692 desc.dwFVF = D3DFVF_XYZRHW;
3693 desc.dwNumVertices = vbsize;
3694 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &buffer, 0, NULL);
3695 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3697 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3698 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3699 memcpy(data, quad, sizeof(quad));
3700 hr = IDirect3DVertexBuffer_Unlock(buffer);
3701 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3703 hr = IDirect3DDevice3_BeginScene(device);
3704 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3705 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
3706 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3707 hr = IDirect3DDevice3_EndScene(device);
3708 ok(SUCCEEDED(hr), "Failed to end scene, 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 memset(data, 0xaa, sizeof(struct vec4) * vbsize);
3713 hr = IDirect3DVertexBuffer_Unlock(buffer);
3714 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3716 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3717 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3718 for (i = 0; i < sizeof(struct vec4) * vbsize; i++)
3720 if (data[i] != 0xaa)
3722 ok(FALSE, "Vertex buffer data byte %u is 0x%02x, expected 0xaa\n", i, data[i]);
3723 break;
3726 hr = IDirect3DVertexBuffer_Unlock(buffer);
3727 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3729 IDirect3DVertexBuffer_Release(buffer);
3730 IDirect3D3_Release(d3d);
3731 IDirect3DDevice3_Release(device);
3732 DestroyWindow(window);
3735 static void test_coop_level_multi_window(void)
3737 HWND window1, window2;
3738 IDirectDraw4 *ddraw;
3739 HRESULT hr;
3741 window1 = create_window();
3742 window2 = create_window();
3743 ddraw = create_ddraw();
3744 ok(!!ddraw, "Failed to create a ddraw object.\n");
3746 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
3747 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3748 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3749 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3750 ok(IsWindow(window1), "Window 1 was destroyed.\n");
3751 ok(IsWindow(window2), "Window 2 was destroyed.\n");
3753 IDirectDraw4_Release(ddraw);
3754 DestroyWindow(window2);
3755 DestroyWindow(window1);
3758 static void test_draw_strided(void)
3760 static struct vec3 position[] =
3762 {-1.0, -1.0, 0.0},
3763 {-1.0, 1.0, 0.0},
3764 { 1.0, 1.0, 0.0},
3765 { 1.0, -1.0, 0.0},
3767 static DWORD diffuse[] =
3769 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
3771 static WORD indices[] =
3773 0, 1, 2, 2, 3, 0
3776 IDirectDrawSurface4 *rt;
3777 IDirect3DDevice3 *device;
3778 D3DCOLOR color;
3779 HWND window;
3780 HRESULT hr;
3781 D3DDRAWPRIMITIVESTRIDEDDATA strided;
3782 IDirect3DViewport3 *viewport;
3783 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3785 window = create_window();
3786 if (!(device = create_device(window, DDSCL_NORMAL)))
3788 skip("Failed to create a 3D device, skipping test.\n");
3789 DestroyWindow(window);
3790 return;
3793 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
3794 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3795 viewport = create_viewport(device, 0, 0, 640, 480);
3796 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
3797 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
3798 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
3799 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
3801 hr = IDirect3DDevice3_BeginScene(device);
3802 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3804 memset(&strided, 0x55, sizeof(strided));
3805 strided.position.lpvData = position;
3806 strided.position.dwStride = sizeof(*position);
3807 strided.diffuse.lpvData = diffuse;
3808 strided.diffuse.dwStride = sizeof(*diffuse);
3809 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE,
3810 &strided, 4, indices, 6, 0);
3811 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3813 hr = IDirect3DDevice3_EndScene(device);
3814 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3816 color = get_surface_color(rt, 320, 240);
3817 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3819 IDirect3DViewport3_Release(viewport);
3820 IDirectDrawSurface4_Release(rt);
3821 IDirect3DDevice3_Release(device);
3822 DestroyWindow(window);
3825 static void test_lighting(void)
3827 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3828 static D3DMATRIX mat =
3830 1.0f, 0.0f, 0.0f, 0.0f,
3831 0.0f, 1.0f, 0.0f, 0.0f,
3832 0.0f, 0.0f, 1.0f, 0.0f,
3833 0.0f, 0.0f, 0.0f, 1.0f,
3835 mat_singular =
3837 1.0f, 0.0f, 1.0f, 0.0f,
3838 0.0f, 1.0f, 0.0f, 0.0f,
3839 1.0f, 0.0f, 1.0f, 0.0f,
3840 0.0f, 0.0f, 0.5f, 1.0f,
3842 mat_transf =
3844 0.0f, 0.0f, 1.0f, 0.0f,
3845 0.0f, 1.0f, 0.0f, 0.0f,
3846 -1.0f, 0.0f, 0.0f, 0.0f,
3847 10.f, 10.0f, 10.0f, 1.0f,
3849 mat_nonaffine =
3851 1.0f, 0.0f, 0.0f, 0.0f,
3852 0.0f, 1.0f, 0.0f, 0.0f,
3853 0.0f, 0.0f, 1.0f, -1.0f,
3854 10.f, 10.0f, 10.0f, 0.0f,
3856 static struct
3858 struct vec3 position;
3859 DWORD diffuse;
3861 unlitquad[] =
3863 {{-1.0f, -1.0f, 0.1f}, 0xffff0000},
3864 {{-1.0f, 0.0f, 0.1f}, 0xffff0000},
3865 {{ 0.0f, 0.0f, 0.1f}, 0xffff0000},
3866 {{ 0.0f, -1.0f, 0.1f}, 0xffff0000},
3868 litquad[] =
3870 {{-1.0f, 0.0f, 0.1f}, 0xff00ff00},
3871 {{-1.0f, 1.0f, 0.1f}, 0xff00ff00},
3872 {{ 0.0f, 1.0f, 0.1f}, 0xff00ff00},
3873 {{ 0.0f, 0.0f, 0.1f}, 0xff00ff00},
3875 static struct
3877 struct vec3 position;
3878 struct vec3 normal;
3879 DWORD diffuse;
3881 unlitnquad[] =
3883 {{0.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3884 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3885 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3886 {{1.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3888 litnquad[] =
3890 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3891 {{0.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3892 {{1.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3893 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3895 nquad[] =
3897 {{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3898 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3899 {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3900 {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3902 rotatedquad[] =
3904 {{-10.0f, -11.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3905 {{-10.0f, -9.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3906 {{-10.0f, -9.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3907 {{-10.0f, -11.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3909 translatedquad[] =
3911 {{-11.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3912 {{-11.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3913 {{ -9.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3914 {{ -9.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3916 static WORD indices[] = {0, 1, 2, 2, 3, 0};
3917 static const struct
3919 D3DMATRIX *world_matrix;
3920 void *quad;
3921 DWORD expected;
3922 const char *message;
3924 tests[] =
3926 {&mat, nquad, 0x000000ff, "Lit quad with light"},
3927 {&mat_singular, nquad, 0x000000b4, "Lit quad with singular world matrix"},
3928 {&mat_transf, rotatedquad, 0x000000ff, "Lit quad with transformation matrix"},
3929 {&mat_nonaffine, translatedquad, 0x000000ff, "Lit quad with non-affine matrix"},
3932 HWND window;
3933 IDirect3D3 *d3d;
3934 IDirect3DDevice3 *device;
3935 IDirectDrawSurface4 *rt;
3936 IDirect3DViewport3 *viewport;
3937 IDirect3DMaterial3 *material;
3938 IDirect3DLight *light;
3939 D3DMATERIALHANDLE mat_handle;
3940 D3DLIGHT2 light_desc;
3941 HRESULT hr;
3942 DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
3943 DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
3944 D3DCOLOR color;
3945 ULONG refcount;
3946 unsigned int i;
3948 window = create_window();
3949 if (!(device = create_device(window, DDSCL_NORMAL)))
3951 skip("Failed to create a 3D device, skipping test.\n");
3952 DestroyWindow(window);
3953 return;
3956 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
3957 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
3959 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
3960 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3962 viewport = create_viewport(device, 0, 0, 640, 480);
3963 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
3964 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
3966 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
3967 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3969 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
3970 ok(SUCCEEDED(hr), "Failed to set world transformation, hr %#x.\n", hr);
3971 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
3972 ok(SUCCEEDED(hr), "Failed to set view transformation, hr %#x.\n", hr);
3973 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
3974 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
3975 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
3976 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
3977 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
3978 ok(SUCCEEDED(hr), "Failed to disable zbuffer, hr %#x.\n", hr);
3979 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
3980 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
3981 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
3982 ok(SUCCEEDED(hr), "Failed to disable stencil buffer, hr %#x.\n", hr);
3983 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
3984 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
3986 hr = IDirect3DDevice3_BeginScene(device);
3987 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3989 /* There is no D3DRENDERSTATE_LIGHTING on ddraw < 7. */
3990 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3991 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
3992 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, unlitquad, 4,
3993 indices, 6, 0);
3994 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3996 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
3997 ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
3998 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, litquad, 4,
3999 indices, 6, 0);
4000 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4002 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
4003 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
4004 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, unlitnquad, 4,
4005 indices, 6, 0);
4006 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4008 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
4009 ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
4010 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, litnquad, 4,
4011 indices, 6, 0);
4012 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4014 hr = IDirect3DDevice3_EndScene(device);
4015 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4017 color = get_surface_color(rt, 160, 360);
4018 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x.\n", color);
4019 color = get_surface_color(rt, 160, 120);
4020 ok(color == 0x0000ff00, "Lit quad without normals has color 0x%08x.\n", color);
4021 color = get_surface_color(rt, 480, 360);
4022 ok(color == 0x000000ff, "Unlit quad with normals has color 0x%08x.\n", color);
4023 color = get_surface_color(rt, 480, 120);
4024 ok(color == 0x00ffff00, "Lit quad with normals has color 0x%08x.\n", color);
4026 material = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
4027 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
4028 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
4029 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
4030 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
4032 hr = IDirect3D3_CreateLight(d3d, &light, NULL);
4033 ok(SUCCEEDED(hr), "Failed to create a light object, hr %#x.\n", hr);
4034 memset(&light_desc, 0, sizeof(light_desc));
4035 light_desc.dwSize = sizeof(light_desc);
4036 light_desc.dltType = D3DLIGHT_DIRECTIONAL;
4037 U1(light_desc.dcvColor).r = 1.0f;
4038 U2(light_desc.dcvColor).g = 1.0f;
4039 U3(light_desc.dcvColor).b = 1.0f;
4040 U4(light_desc.dcvColor).a = 1.0f;
4041 U3(light_desc.dvDirection).z = 1.0f;
4042 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
4043 ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
4044 hr = IDirect3DViewport3_AddLight(viewport, light);
4045 ok(SUCCEEDED(hr), "Failed to add a light to the viewport, hr %#x.\n", hr);
4047 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
4048 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4050 hr = IDirect3DDevice3_BeginScene(device);
4051 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4053 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, nquad,
4054 4, indices, 6, 0);
4055 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4057 hr = IDirect3DDevice3_EndScene(device);
4058 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4060 color = get_surface_color(rt, 320, 240);
4061 ok(color == 0x00000000, "Lit quad with no light has color 0x%08x.\n", color);
4063 light_desc.dwFlags = D3DLIGHT_ACTIVE;
4064 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
4065 ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
4067 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4069 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
4070 ok(SUCCEEDED(hr), "Failed to set world transformation, hr %#x.\n", hr);
4072 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
4073 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4075 hr = IDirect3DDevice3_BeginScene(device);
4076 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4078 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, tests[i].quad,
4079 4, indices, 6, 0);
4080 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4082 hr = IDirect3DDevice3_EndScene(device);
4083 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4085 color = get_surface_color(rt, 320, 240);
4086 ok(color == tests[i].expected, "%s has color 0x%08x.\n", tests[i].message, color);
4089 hr = IDirect3DViewport3_DeleteLight(viewport, light);
4090 ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#x.\n", hr);
4091 IDirect3DLight_Release(light);
4092 destroy_material(material);
4093 IDirect3DViewport3_Release(viewport);
4094 IDirectDrawSurface4_Release(rt);
4095 refcount = IDirect3DDevice3_Release(device);
4096 ok(!refcount, "Device has %u references left.\n", refcount);
4097 IDirect3D3_Release(d3d);
4098 DestroyWindow(window);
4101 static void test_specular_lighting(void)
4103 static const unsigned int vertices_side = 5;
4104 const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
4105 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
4106 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
4107 static D3DMATRIX mat =
4109 1.0f, 0.0f, 0.0f, 0.0f,
4110 0.0f, 1.0f, 0.0f, 0.0f,
4111 0.0f, 0.0f, 1.0f, 0.0f,
4112 0.0f, 0.0f, 0.0f, 1.0f,
4114 static D3DLIGHT2 directional =
4116 sizeof(D3DLIGHT2),
4117 D3DLIGHT_DIRECTIONAL,
4118 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4119 {{0.0f}, {0.0f}, {0.0f}},
4120 {{0.0f}, {0.0f}, {1.0f}},
4122 point =
4124 sizeof(D3DLIGHT2),
4125 D3DLIGHT_POINT,
4126 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4127 {{0.0f}, {0.0f}, {0.0f}},
4128 {{0.0f}, {0.0f}, {0.0f}},
4129 100.0f,
4130 0.0f,
4131 0.0f, 0.0f, 1.0f,
4133 spot =
4135 sizeof(D3DLIGHT2),
4136 D3DLIGHT_SPOT,
4137 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4138 {{0.0f}, {0.0f}, {0.0f}},
4139 {{0.0f}, {0.0f}, {1.0f}},
4140 100.0f,
4141 1.0f,
4142 0.0f, 0.0f, 1.0f,
4143 M_PI / 12.0f, M_PI / 3.0f
4145 parallelpoint =
4147 sizeof(D3DLIGHT2),
4148 D3DLIGHT_PARALLELPOINT,
4149 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4150 {{0.5f}, {0.0f}, {-1.0f}},
4151 {{0.0f}, {0.0f}, {0.0f}},
4153 point_side =
4155 sizeof(D3DLIGHT2),
4156 D3DLIGHT_POINT,
4157 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4158 {{-1.1f}, {0.0f}, {1.1f}},
4159 {{0.0f}, {0.0f}, {0.0f}},
4160 100.0f,
4161 0.0f,
4162 1.0f, 0.0f, 0.0f,
4164 point_far =
4166 sizeof(D3DLIGHT2),
4167 D3DLIGHT_POINT,
4168 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4169 {{0.0f}, {0.0f}, {0.1f}},
4170 {{0.0f}, {0.0f}, {0.0f}},
4171 1.0f,
4172 0.0f,
4173 1.0f, 0.0f, 0.0f,
4175 static const struct expected_color
4177 unsigned int x, y;
4178 D3DCOLOR color;
4180 expected_directional[] =
4182 {160, 120, 0x003c3c3c},
4183 {320, 120, 0x00717171},
4184 {480, 120, 0x003c3c3c},
4185 {160, 240, 0x00717171},
4186 {320, 240, 0x00ffffff},
4187 {480, 240, 0x00717171},
4188 {160, 360, 0x003c3c3c},
4189 {320, 360, 0x00717171},
4190 {480, 360, 0x003c3c3c},
4192 expected_point[] =
4194 {160, 120, 0x00000000},
4195 {320, 120, 0x00090909},
4196 {480, 120, 0x00000000},
4197 {160, 240, 0x00090909},
4198 {320, 240, 0x00fafafa},
4199 {480, 240, 0x00090909},
4200 {160, 360, 0x00000000},
4201 {320, 360, 0x00090909},
4202 {480, 360, 0x00000000},
4204 expected_spot[] =
4206 {160, 120, 0x00000000},
4207 {320, 120, 0x00020202},
4208 {480, 120, 0x00000000},
4209 {160, 240, 0x00020202},
4210 {320, 240, 0x00fafafa},
4211 {480, 240, 0x00020202},
4212 {160, 360, 0x00000000},
4213 {320, 360, 0x00020202},
4214 {480, 360, 0x00000000},
4216 expected_parallelpoint[] =
4218 {160, 120, 0x00050505},
4219 {320, 120, 0x002c2c2c},
4220 {480, 120, 0x006e6e6e},
4221 {160, 240, 0x00090909},
4222 {320, 240, 0x00717171},
4223 {480, 240, 0x00ffffff},
4224 {160, 360, 0x00050505},
4225 {320, 360, 0x002c2c2c},
4226 {480, 360, 0x006e6e6e},
4228 expected_point_side[] =
4230 {160, 120, 0x00000000},
4231 {320, 120, 0x00000000},
4232 {480, 120, 0x00000000},
4233 {160, 240, 0x00000000},
4234 {320, 240, 0x00000000},
4235 {480, 240, 0x00000000},
4236 {160, 360, 0x00000000},
4237 {320, 360, 0x00000000},
4238 {480, 360, 0x00000000},
4240 expected_point_far[] =
4242 {160, 120, 0x00000000},
4243 {320, 120, 0x00000000},
4244 {480, 120, 0x00000000},
4245 {160, 240, 0x00000000},
4246 {320, 240, 0x00ffffff},
4247 {480, 240, 0x00000000},
4248 {160, 360, 0x00000000},
4249 {320, 360, 0x00000000},
4250 {480, 360, 0x00000000},
4252 static const struct
4254 D3DLIGHT2 *light;
4255 BOOL local_viewer;
4256 float specular_power;
4257 const struct expected_color *expected;
4258 unsigned int expected_count;
4260 tests[] =
4262 /* D3DRENDERSTATE_LOCALVIEWER does not exist in D3D < 7 (the behavior is
4263 * the one you get on newer D3D versions with it set as TRUE). */
4264 {&directional, FALSE, 30.0f, expected_directional, ARRAY_SIZE(expected_directional)},
4265 {&directional, TRUE, 30.0f, expected_directional, ARRAY_SIZE(expected_directional)},
4266 {&point, TRUE, 30.0f, expected_point, ARRAY_SIZE(expected_point)},
4267 {&spot, TRUE, 30.0f, expected_spot, ARRAY_SIZE(expected_spot)},
4268 {&parallelpoint, TRUE, 30.0f, expected_parallelpoint, ARRAY_SIZE(expected_parallelpoint)},
4269 {&point_side, TRUE, 0.0f, expected_point_side, ARRAY_SIZE(expected_point_side)},
4270 {&point_far, TRUE, 1.0f, expected_point_far, ARRAY_SIZE(expected_point_far)},
4272 IDirect3D3 *d3d;
4273 IDirect3DDevice3 *device;
4274 IDirectDrawSurface4 *rt;
4275 IDirect3DViewport3 *viewport;
4276 IDirect3DMaterial3 *material;
4277 IDirect3DLight *light;
4278 D3DMATERIALHANDLE mat_handle;
4279 D3DCOLOR color;
4280 ULONG refcount;
4281 HWND window;
4282 HRESULT hr;
4283 unsigned int i, j, x, y;
4284 struct
4286 struct vec3 position;
4287 struct vec3 normal;
4288 } *quad;
4289 WORD *indices;
4291 window = create_window();
4292 if (!(device = create_device(window, DDSCL_NORMAL)))
4294 skip("Failed to create a 3D device, skipping test.\n");
4295 DestroyWindow(window);
4296 return;
4299 quad = HeapAlloc(GetProcessHeap(), 0, vertices_side * vertices_side * sizeof(*quad));
4300 indices = HeapAlloc(GetProcessHeap(), 0, indices_count * sizeof(*indices));
4301 for (i = 0, y = 0; y < vertices_side; ++y)
4303 for (x = 0; x < vertices_side; ++x)
4305 quad[i].position.x = x * 2.0f / (vertices_side - 1) - 1.0f;
4306 quad[i].position.y = y * 2.0f / (vertices_side - 1) - 1.0f;
4307 quad[i].position.z = 1.0f;
4308 quad[i].normal.x = 0.0f;
4309 quad[i].normal.y = 0.0f;
4310 quad[i++].normal.z = -1.0f;
4313 for (i = 0, y = 0; y < (vertices_side - 1); ++y)
4315 for (x = 0; x < (vertices_side - 1); ++x)
4317 indices[i++] = y * vertices_side + x + 1;
4318 indices[i++] = y * vertices_side + x;
4319 indices[i++] = (y + 1) * vertices_side + x;
4320 indices[i++] = y * vertices_side + x + 1;
4321 indices[i++] = (y + 1) * vertices_side + x;
4322 indices[i++] = (y + 1) * vertices_side + x + 1;
4326 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
4327 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
4329 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
4330 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4332 viewport = create_viewport(device, 0, 0, 640, 480);
4333 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
4334 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
4336 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
4337 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
4338 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
4339 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
4340 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
4341 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
4342 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
4343 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
4344 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
4345 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
4346 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4347 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
4349 hr = IDirect3D3_CreateLight(d3d, &light, NULL);
4350 ok(SUCCEEDED(hr), "Failed to create a light object, hr %#x.\n", hr);
4351 hr = IDirect3DViewport3_AddLight(viewport, light);
4352 ok(SUCCEEDED(hr), "Failed to add a light to the viewport, hr %#x.\n", hr);
4354 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
4355 ok(SUCCEEDED(hr), "Failed to enable specular lighting, hr %#x.\n", hr);
4357 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4359 tests[i].light->dwFlags = D3DLIGHT_ACTIVE;
4360 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)tests[i].light);
4361 ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
4363 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LOCALVIEWER, tests[i].local_viewer);
4364 ok(SUCCEEDED(hr), "Failed to set local viewer state, hr %#x.\n", hr);
4366 material = create_specular_material(device, 1.0f, 1.0f, 1.0f, 1.0f, tests[i].specular_power);
4367 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
4368 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
4369 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
4370 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
4372 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
4373 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4375 hr = IDirect3DDevice3_BeginScene(device);
4376 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4378 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, quad,
4379 vertices_side * vertices_side, indices, indices_count, 0);
4380 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4382 hr = IDirect3DDevice3_EndScene(device);
4383 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4385 for (j = 0; j < tests[i].expected_count; ++j)
4387 color = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
4388 ok(compare_color(color, tests[i].expected[j].color, 1),
4389 "Expected color 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
4390 tests[i].expected[j].color, tests[i].expected[j].x,
4391 tests[i].expected[j].y, color, i);
4394 destroy_material(material);
4397 hr = IDirect3DViewport3_DeleteLight(viewport, light);
4398 ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#x.\n", hr);
4399 IDirect3DLight_Release(light);
4400 IDirect3DViewport3_Release(viewport);
4401 IDirectDrawSurface4_Release(rt);
4402 refcount = IDirect3DDevice3_Release(device);
4403 ok(!refcount, "Device has %u references left.\n", refcount);
4404 IDirect3D3_Release(d3d);
4405 DestroyWindow(window);
4406 HeapFree(GetProcessHeap(), 0, indices);
4407 HeapFree(GetProcessHeap(), 0, quad);
4410 static void test_clear_rect_count(void)
4412 IDirectDrawSurface4 *rt;
4413 IDirect3DDevice3 *device;
4414 D3DCOLOR color;
4415 HWND window;
4416 HRESULT hr;
4417 IDirect3DViewport3 *viewport;
4418 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
4420 window = create_window();
4421 if (!(device = create_device(window, DDSCL_NORMAL)))
4423 skip("Failed to create a 3D device, skipping test.\n");
4424 DestroyWindow(window);
4425 return;
4428 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
4429 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4431 viewport = create_viewport(device, 0, 0, 640, 480);
4432 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
4433 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
4434 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00ffffff, 0.0f, 0);
4435 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
4436 hr = IDirect3DViewport3_Clear2(viewport, 0, &clear_rect, D3DCLEAR_TARGET, 0x00ff0000, 0.0f, 0);
4437 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
4438 hr = IDirect3DViewport3_Clear2(viewport, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 0.0f, 0);
4439 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
4440 hr = IDirect3DViewport3_Clear2(viewport, 1, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
4441 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
4443 color = get_surface_color(rt, 320, 240);
4444 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x000000ff, 1)),
4445 "Got unexpected color 0x%08x.\n", color);
4447 IDirect3DViewport3_Release(viewport);
4448 IDirectDrawSurface4_Release(rt);
4449 IDirect3DDevice3_Release(device);
4450 DestroyWindow(window);
4453 static BOOL test_mode_restored(IDirectDraw4 *ddraw, HWND window)
4455 DDSURFACEDESC2 ddsd1, ddsd2;
4456 HRESULT hr;
4458 memset(&ddsd1, 0, sizeof(ddsd1));
4459 ddsd1.dwSize = sizeof(ddsd1);
4460 hr = IDirectDraw4_GetDisplayMode(ddraw, &ddsd1);
4461 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4463 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4464 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4465 hr = set_display_mode(ddraw, 640, 480);
4466 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
4467 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4468 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4470 memset(&ddsd2, 0, sizeof(ddsd2));
4471 ddsd2.dwSize = sizeof(ddsd2);
4472 hr = IDirectDraw4_GetDisplayMode(ddraw, &ddsd2);
4473 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4474 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
4475 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4477 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
4480 static void test_coop_level_versions(void)
4482 HWND window;
4483 IDirectDraw *ddraw;
4484 HRESULT hr;
4485 BOOL restored;
4486 IDirectDrawSurface *surface;
4487 IDirectDraw4 *ddraw4;
4488 DDSURFACEDESC ddsd;
4490 window = create_window();
4491 ddraw4 = create_ddraw();
4492 ok(!!ddraw4, "Failed to create a ddraw object.\n");
4493 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
4494 restored = test_mode_restored(ddraw4, window);
4495 ok(restored, "Display mode not restored in new ddraw object\n");
4497 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
4498 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
4499 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4501 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4502 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4503 restored = test_mode_restored(ddraw4, window);
4504 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
4506 /* A successful one does */
4507 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4508 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4509 restored = test_mode_restored(ddraw4, window);
4510 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
4512 IDirectDraw_Release(ddraw);
4513 IDirectDraw4_Release(ddraw4);
4515 ddraw4 = create_ddraw();
4516 ok(!!ddraw4, "Failed to create a ddraw object.\n");
4517 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
4518 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4520 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
4521 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4522 restored = test_mode_restored(ddraw4, window);
4523 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
4525 IDirectDraw_Release(ddraw);
4526 IDirectDraw4_Release(ddraw4);
4528 /* A failing call does not restore the ddraw2+ behavior */
4529 ddraw4 = create_ddraw();
4530 ok(!!ddraw4, "Failed to create a ddraw object.\n");
4531 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
4532 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4534 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4535 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4536 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4537 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4538 restored = test_mode_restored(ddraw4, window);
4539 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
4541 IDirectDraw_Release(ddraw);
4542 IDirectDraw4_Release(ddraw4);
4544 /* Neither does a sequence of successful calls with the new interface */
4545 ddraw4 = create_ddraw();
4546 ok(!!ddraw4, "Failed to create a ddraw object.\n");
4547 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
4548 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4550 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4551 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4552 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4553 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4554 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_NORMAL);
4555 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4557 restored = test_mode_restored(ddraw4, window);
4558 ok(!restored, "Display mode restored after ddraw1-ddraw4 SetCooperativeLevel() call sequence\n");
4559 IDirectDraw_Release(ddraw);
4560 IDirectDraw4_Release(ddraw4);
4562 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
4563 ddraw4 = create_ddraw();
4564 ok(!!ddraw4, "Failed to create a ddraw object.\n");
4565 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
4566 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4568 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_NORMAL);
4569 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4571 memset(&ddsd, 0, sizeof(ddsd));
4572 ddsd.dwSize = sizeof(ddsd);
4573 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4574 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4575 ddsd.dwWidth = ddsd.dwHeight = 8;
4576 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4577 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
4578 IDirectDrawSurface_Release(surface);
4579 restored = test_mode_restored(ddraw4, window);
4580 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
4582 IDirectDraw_Release(ddraw);
4583 IDirectDraw4_Release(ddraw4);
4584 DestroyWindow(window);
4587 static void test_lighting_interface_versions(void)
4589 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
4590 IDirect3DMaterial3 *emissive;
4591 IDirect3DViewport3 *viewport;
4592 IDirect3DDevice3 *device;
4593 IDirectDrawSurface4 *rt;
4594 D3DCOLOR color;
4595 HWND window;
4596 HRESULT hr;
4597 D3DMATERIALHANDLE mat_handle;
4598 DWORD rs;
4599 unsigned int i;
4600 ULONG ref;
4601 static D3DVERTEX quad[] =
4603 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4604 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4605 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4606 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4609 #define FVF_COLORVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_SPECULAR)
4610 static struct
4612 struct vec3 position;
4613 struct vec3 normal;
4614 DWORD diffuse, specular;
4616 quad2[] =
4618 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4619 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4620 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4621 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4624 static D3DLVERTEX lquad[] =
4626 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4627 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4628 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4629 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4632 #define FVF_LVERTEX2 (D3DFVF_LVERTEX & ~D3DFVF_RESERVED1)
4633 static struct
4635 struct vec3 position;
4636 DWORD diffuse, specular;
4637 struct vec2 texcoord;
4639 lquad2[] =
4641 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4642 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4643 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4644 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4647 static D3DTLVERTEX tlquad[] =
4649 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4650 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4651 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4652 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4655 static const struct
4657 DWORD vertextype;
4658 void *data;
4659 DWORD d3drs_lighting, d3drs_specular;
4660 DWORD draw_flags;
4661 D3DCOLOR color;
4663 tests[] =
4665 /* Lighting is enabled when all of these conditions are met:
4666 * 1) No pretransformed position(D3DFVF_XYZRHW)
4667 * 2) Normals are available (D3DFVF_NORMAL)
4668 * 3) D3DDP_DONOTLIGHT is not set.
4670 * D3DRENDERSTATE_LIGHTING is ignored, it is not defined
4671 * in this d3d version */
4673 /* 0 */
4674 { D3DFVF_VERTEX, quad, FALSE, FALSE, 0, 0x0000ff00},
4675 { D3DFVF_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
4676 { D3DFVF_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
4677 { D3DFVF_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
4678 { D3DFVF_VERTEX, quad, FALSE, TRUE, 0, 0x0000ff00},
4679 { D3DFVF_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
4680 { D3DFVF_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
4681 { D3DFVF_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
4683 /* 8 */
4684 { FVF_COLORVERTEX, quad2, FALSE, FALSE, 0, 0x0000ff00},
4685 { FVF_COLORVERTEX, quad2, TRUE, FALSE, 0, 0x0000ff00},
4686 { FVF_COLORVERTEX, quad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4687 { FVF_COLORVERTEX, quad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4688 /* The specular color in the vertex is ignored because
4689 * D3DRENDERSTATE_COLORVERTEX is not enabled */
4690 { FVF_COLORVERTEX, quad2, FALSE, TRUE, 0, 0x0000ff00},
4691 { FVF_COLORVERTEX, quad2, TRUE, TRUE, 0, 0x0000ff00},
4692 { FVF_COLORVERTEX, quad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4693 { FVF_COLORVERTEX, quad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4695 /* 16 */
4696 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
4697 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, 0, 0x00ff0000},
4698 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4699 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4700 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
4701 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, 0, 0x00ff8080},
4702 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4703 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4705 /* 24 */
4706 { FVF_LVERTEX2, lquad2, FALSE, FALSE, 0, 0x00ff0000},
4707 { FVF_LVERTEX2, lquad2, TRUE, FALSE, 0, 0x00ff0000},
4708 { FVF_LVERTEX2, lquad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4709 { FVF_LVERTEX2, lquad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4710 { FVF_LVERTEX2, lquad2, FALSE, TRUE, 0, 0x00ff8080},
4711 { FVF_LVERTEX2, lquad2, TRUE, TRUE, 0, 0x00ff8080},
4712 { FVF_LVERTEX2, lquad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4713 { FVF_LVERTEX2, lquad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4715 /* 32 */
4716 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
4717 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
4718 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4719 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4720 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
4721 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
4722 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4723 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4726 window = create_window();
4727 if (!(device = create_device(window, DDSCL_NORMAL)))
4729 skip("Failed to create a 3D device, skipping test.\n");
4730 DestroyWindow(window);
4731 return;
4734 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
4735 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4737 viewport = create_viewport(device, 0, 0, 640, 480);
4738 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
4739 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
4741 emissive = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
4742 hr = IDirect3DMaterial3_GetHandle(emissive, device, &mat_handle);
4743 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
4744 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
4745 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
4746 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
4747 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr);
4749 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
4750 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#x.\n", hr);
4751 ok(rs == FALSE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#x, expected FALSE.\n", rs);
4753 for (i = 0; i < ARRAY_SIZE(tests); i++)
4755 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff202020, 0.0f, 0);
4756 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4758 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
4759 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#x.\n", hr);
4760 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
4761 tests[i].d3drs_specular);
4762 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#x.\n", hr);
4764 hr = IDirect3DDevice3_BeginScene(device);
4765 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4766 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
4767 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
4768 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4769 hr = IDirect3DDevice3_EndScene(device);
4770 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4772 color = get_surface_color(rt, 320, 240);
4773 ok(compare_color(color, tests[i].color, 1),
4774 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
4775 color, tests[i].color, i);
4778 destroy_material(emissive);
4779 IDirectDrawSurface4_Release(rt);
4780 ref = IDirect3DDevice3_Release(device);
4781 ok(ref == 0, "Device not properly released, refcount %u.\n", ref);
4782 DestroyWindow(window);
4785 static struct
4787 BOOL received;
4788 IDirectDraw4 *ddraw;
4789 HWND window;
4790 DWORD coop_level;
4791 } activateapp_testdata;
4793 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
4795 if (message == WM_ACTIVATEAPP)
4797 if (activateapp_testdata.ddraw)
4799 HRESULT hr;
4800 activateapp_testdata.received = FALSE;
4801 hr = IDirectDraw4_SetCooperativeLevel(activateapp_testdata.ddraw,
4802 activateapp_testdata.window, activateapp_testdata.coop_level);
4803 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
4804 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
4806 activateapp_testdata.received = TRUE;
4809 return DefWindowProcA(hwnd, message, wparam, lparam);
4812 static void test_coop_level_activateapp(void)
4814 IDirectDraw4 *ddraw;
4815 HRESULT hr;
4816 HWND window;
4817 WNDCLASSA wc = {0};
4818 DDSURFACEDESC2 ddsd;
4819 IDirectDrawSurface4 *surface;
4821 ddraw = create_ddraw();
4822 ok(!!ddraw, "Failed to create a ddraw object.\n");
4824 wc.lpfnWndProc = activateapp_test_proc;
4825 wc.lpszClassName = "ddraw_test_wndproc_wc";
4826 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4828 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
4829 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
4831 /* Exclusive with window already active. */
4832 SetForegroundWindow(window);
4833 activateapp_testdata.received = FALSE;
4834 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4835 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4836 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
4837 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4838 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4840 /* Exclusive with window not active. */
4841 SetForegroundWindow(GetDesktopWindow());
4842 activateapp_testdata.received = FALSE;
4843 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4844 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4845 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4846 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4847 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4849 /* Normal with window not active, then exclusive with the same window. */
4850 SetForegroundWindow(GetDesktopWindow());
4851 activateapp_testdata.received = FALSE;
4852 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4853 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4854 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
4855 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4856 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4857 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4858 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4859 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4861 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
4862 SetForegroundWindow(GetDesktopWindow());
4863 activateapp_testdata.received = FALSE;
4864 activateapp_testdata.ddraw = ddraw;
4865 activateapp_testdata.window = window;
4866 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
4867 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4868 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4869 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4870 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4871 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4873 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
4874 * succeeding. Another switch to exclusive and back to normal is needed to release the
4875 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
4876 * WM_ACTIVATEAPP messages. */
4877 activateapp_testdata.ddraw = NULL;
4878 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4879 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4880 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4881 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4883 /* Setting DDSCL_NORMAL with recursive invocation. */
4884 SetForegroundWindow(GetDesktopWindow());
4885 activateapp_testdata.received = FALSE;
4886 activateapp_testdata.ddraw = ddraw;
4887 activateapp_testdata.window = window;
4888 activateapp_testdata.coop_level = DDSCL_NORMAL;
4889 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4890 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4891 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4893 /* DDraw is in exclusive mode now. */
4894 memset(&ddsd, 0, sizeof(ddsd));
4895 ddsd.dwSize = sizeof(ddsd);
4896 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
4897 U5(ddsd).dwBackBufferCount = 1;
4898 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
4899 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
4900 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4901 IDirectDrawSurface4_Release(surface);
4903 /* Recover again, just to be sure. */
4904 activateapp_testdata.ddraw = NULL;
4905 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4906 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4907 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4908 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4910 DestroyWindow(window);
4911 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
4912 IDirectDraw4_Release(ddraw);
4915 static void test_texturemanage(void)
4917 IDirectDraw4 *ddraw;
4918 HRESULT hr;
4919 DDSURFACEDESC2 ddsd;
4920 IDirectDrawSurface4 *surface;
4921 unsigned int i;
4922 DDCAPS hal_caps, hel_caps;
4923 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
4924 static const struct
4926 DWORD caps_in, caps2_in;
4927 HRESULT hr;
4928 DWORD caps_out, caps2_out;
4930 tests[] =
4932 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4933 ~0U, ~0U},
4934 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4935 ~0U, ~0U},
4936 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4937 ~0U, ~0U},
4938 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4939 ~0U, ~0U},
4940 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DD_OK,
4941 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE},
4942 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DD_OK,
4943 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE},
4944 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
4945 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_LOCALVIDMEM, 0},
4946 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
4947 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0},
4949 {0, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4950 ~0U, ~0U},
4951 {0, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4952 ~0U, ~0U},
4953 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4954 ~0U, ~0U},
4955 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4956 ~0U, ~0U},
4957 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4958 ~0U, ~0U},
4959 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4960 ~0U, ~0U},
4961 {DDSCAPS_VIDEOMEMORY, 0, DD_OK,
4962 DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY, 0},
4963 {DDSCAPS_SYSTEMMEMORY, 0, DD_OK,
4964 DDSCAPS_SYSTEMMEMORY, 0},
4967 ddraw = create_ddraw();
4968 ok(!!ddraw, "Failed to create a ddraw object.\n");
4969 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4970 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4972 memset(&hal_caps, 0, sizeof(hal_caps));
4973 hal_caps.dwSize = sizeof(hal_caps);
4974 memset(&hel_caps, 0, sizeof(hel_caps));
4975 hel_caps.dwSize = sizeof(hel_caps);
4976 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, &hel_caps);
4977 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
4978 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
4980 skip("Managed textures not supported, skipping managed texture test.\n");
4981 IDirectDraw4_Release(ddraw);
4982 return;
4985 for (i = 0; i < ARRAY_SIZE(tests); i++)
4987 memset(&ddsd, 0, sizeof(ddsd));
4988 ddsd.dwSize = sizeof(ddsd);
4989 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4990 ddsd.ddsCaps.dwCaps = tests[i].caps_in;
4991 ddsd.ddsCaps.dwCaps2 = tests[i].caps2_in;
4992 ddsd.dwWidth = 4;
4993 ddsd.dwHeight = 4;
4995 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
4996 ok(hr == tests[i].hr, "Got unexpected, hr %#x, case %u.\n", hr, i);
4997 if (FAILED(hr))
4998 continue;
5000 memset(&ddsd, 0, sizeof(ddsd));
5001 ddsd.dwSize = sizeof(ddsd);
5002 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5003 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5005 ok(ddsd.ddsCaps.dwCaps == tests[i].caps_out,
5006 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
5007 tests[i].caps_in, tests[i].caps2_in, tests[i].caps_out, ddsd.ddsCaps.dwCaps, i);
5008 ok(ddsd.ddsCaps.dwCaps2 == tests[i].caps2_out,
5009 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
5010 tests[i].caps_in, tests[i].caps2_in, tests[i].caps2_out, ddsd.ddsCaps.dwCaps2, i);
5012 IDirectDrawSurface4_Release(surface);
5015 IDirectDraw4_Release(ddraw);
5018 #define SUPPORT_DXT1 0x01
5019 #define SUPPORT_DXT2 0x02
5020 #define SUPPORT_DXT3 0x04
5021 #define SUPPORT_DXT4 0x08
5022 #define SUPPORT_DXT5 0x10
5023 #define SUPPORT_YUY2 0x20
5024 #define SUPPORT_UYVY 0x40
5026 static HRESULT WINAPI test_block_formats_creation_cb(DDPIXELFORMAT *fmt, void *ctx)
5028 DWORD *supported_fmts = ctx;
5030 if (!(fmt->dwFlags & DDPF_FOURCC))
5031 return DDENUMRET_OK;
5033 switch (fmt->dwFourCC)
5035 case MAKEFOURCC('D','X','T','1'):
5036 *supported_fmts |= SUPPORT_DXT1;
5037 break;
5038 case MAKEFOURCC('D','X','T','2'):
5039 *supported_fmts |= SUPPORT_DXT2;
5040 break;
5041 case MAKEFOURCC('D','X','T','3'):
5042 *supported_fmts |= SUPPORT_DXT3;
5043 break;
5044 case MAKEFOURCC('D','X','T','4'):
5045 *supported_fmts |= SUPPORT_DXT4;
5046 break;
5047 case MAKEFOURCC('D','X','T','5'):
5048 *supported_fmts |= SUPPORT_DXT5;
5049 break;
5050 case MAKEFOURCC('Y','U','Y','2'):
5051 *supported_fmts |= SUPPORT_YUY2;
5052 break;
5053 case MAKEFOURCC('U','Y','V','Y'):
5054 *supported_fmts |= SUPPORT_UYVY;
5055 break;
5056 default:
5057 break;
5060 return DDENUMRET_OK;
5063 static void test_block_formats_creation(void)
5065 HRESULT hr, expect_hr;
5066 unsigned int i, j, w, h;
5067 HWND window;
5068 IDirectDraw4 *ddraw;
5069 IDirect3D3 *d3d;
5070 IDirect3DDevice3 *device;
5071 IDirectDrawSurface4 *surface;
5072 DWORD supported_fmts = 0, supported_overlay_fmts = 0;
5073 DWORD num_fourcc_codes = 0, *fourcc_codes;
5074 DDSURFACEDESC2 ddsd;
5075 DDCAPS hal_caps;
5076 void *mem;
5078 static const struct
5080 DWORD fourcc;
5081 const char *name;
5082 DWORD support_flag;
5083 unsigned int block_width;
5084 unsigned int block_height;
5085 unsigned int block_size;
5086 BOOL create_size_checked, overlay;
5088 formats[] =
5090 {MAKEFOURCC('D','X','T','1'), "D3DFMT_DXT1", SUPPORT_DXT1, 4, 4, 8, TRUE, FALSE},
5091 {MAKEFOURCC('D','X','T','2'), "D3DFMT_DXT2", SUPPORT_DXT2, 4, 4, 16, TRUE, FALSE},
5092 {MAKEFOURCC('D','X','T','3'), "D3DFMT_DXT3", SUPPORT_DXT3, 4, 4, 16, TRUE, FALSE},
5093 {MAKEFOURCC('D','X','T','4'), "D3DFMT_DXT4", SUPPORT_DXT4, 4, 4, 16, TRUE, FALSE},
5094 {MAKEFOURCC('D','X','T','5'), "D3DFMT_DXT5", SUPPORT_DXT5, 4, 4, 16, TRUE, FALSE},
5095 {MAKEFOURCC('Y','U','Y','2'), "D3DFMT_YUY2", SUPPORT_YUY2, 2, 1, 4, FALSE, TRUE },
5096 {MAKEFOURCC('U','Y','V','Y'), "D3DFMT_UYVY", SUPPORT_UYVY, 2, 1, 4, FALSE, TRUE },
5098 static const struct
5100 DWORD caps, caps2;
5101 const char *name;
5102 BOOL overlay;
5104 types[] =
5106 /* DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY fails to create any fourcc
5107 * surface with DDERR_INVALIDPIXELFORMAT. Don't care about it for now.
5109 * Nvidia returns E_FAIL on DXTN DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY.
5110 * Other hw / drivers successfully create those surfaces. Ignore them, this
5111 * suggests that no game uses this, otherwise Nvidia would support it. */
5113 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0,
5114 "videomemory texture", FALSE
5117 DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY, 0,
5118 "videomemory overlay", TRUE
5121 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0,
5122 "systemmemory texture", FALSE
5125 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
5126 "managed texture", FALSE
5129 enum size_type
5131 SIZE_TYPE_ZERO,
5132 SIZE_TYPE_PITCH,
5133 SIZE_TYPE_SIZE,
5135 static const struct
5137 DWORD flags;
5138 enum size_type size_type;
5139 int rel_size;
5140 HRESULT hr;
5142 user_mem_tests[] =
5144 {DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DD_OK},
5145 {DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
5146 {DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
5147 {DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
5148 {DDSD_LPSURFACE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
5149 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
5150 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
5151 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
5152 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 1, DD_OK},
5153 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, -1, DDERR_INVALIDPARAMS},
5154 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
5155 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
5156 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_SIZE, 0, DD_OK},
5157 {DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
5160 window = create_window();
5161 if (!(device = create_device(window, DDSCL_NORMAL)))
5163 skip("Failed to create a 3D device, skipping test.\n");
5164 DestroyWindow(window);
5165 return;
5168 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
5169 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5170 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **) &ddraw);
5171 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5172 IDirect3D3_Release(d3d);
5174 hr = IDirect3DDevice3_EnumTextureFormats(device, test_block_formats_creation_cb,
5175 &supported_fmts);
5176 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
5178 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
5179 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
5180 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5181 num_fourcc_codes * sizeof(*fourcc_codes));
5182 if (!fourcc_codes)
5183 goto cleanup;
5184 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
5185 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
5186 for (i = 0; i < num_fourcc_codes; i++)
5188 for (j = 0; j < ARRAY_SIZE(formats); j++)
5190 if (fourcc_codes[i] == formats[j].fourcc)
5191 supported_overlay_fmts |= formats[j].support_flag;
5194 HeapFree(GetProcessHeap(), 0, fourcc_codes);
5196 memset(&hal_caps, 0, sizeof(hal_caps));
5197 hal_caps.dwSize = sizeof(hal_caps);
5198 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
5199 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5201 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * 2 * 16 + 1);
5203 for (i = 0; i < ARRAY_SIZE(formats); i++)
5205 for (j = 0; j < ARRAY_SIZE(types); j++)
5207 BOOL support;
5209 if (formats[i].overlay != types[j].overlay
5210 || (types[j].overlay && !(hal_caps.dwCaps & DDCAPS_OVERLAY)))
5211 continue;
5213 if (formats[i].overlay)
5214 support = supported_overlay_fmts & formats[i].support_flag;
5215 else
5216 support = supported_fmts & formats[i].support_flag;
5218 for (w = 1; w <= 8; w++)
5220 for (h = 1; h <= 8; h++)
5222 BOOL block_aligned = TRUE;
5223 BOOL todo = FALSE;
5225 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
5226 block_aligned = FALSE;
5228 memset(&ddsd, 0, sizeof(ddsd));
5229 ddsd.dwSize = sizeof(ddsd);
5230 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5231 ddsd.ddsCaps.dwCaps = types[j].caps;
5232 ddsd.ddsCaps.dwCaps2 = types[j].caps2;
5233 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5234 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
5235 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
5236 ddsd.dwWidth = w;
5237 ddsd.dwHeight = h;
5239 /* TODO: Handle power of two limitations. I cannot test the pow2
5240 * behavior on windows because I have no hardware that doesn't at
5241 * least support np2_conditional. There's probably no HW that
5242 * supports DXTN textures but no conditional np2 textures. */
5243 if (!support && !(types[j].caps & DDSCAPS_SYSTEMMEMORY))
5244 expect_hr = DDERR_INVALIDPARAMS;
5245 else if (formats[i].create_size_checked && !block_aligned)
5247 expect_hr = DDERR_INVALIDPARAMS;
5248 if (!(types[j].caps & DDSCAPS_TEXTURE))
5249 todo = TRUE;
5251 else
5252 expect_hr = D3D_OK;
5254 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5255 todo_wine_if (todo)
5256 ok(hr == expect_hr,
5257 "Got unexpected hr %#x for format %s, resource type %s, size %ux%u, expected %#x.\n",
5258 hr, formats[i].name, types[j].name, w, h, expect_hr);
5260 if (SUCCEEDED(hr))
5261 IDirectDrawSurface4_Release(surface);
5266 if (formats[i].overlay)
5267 continue;
5269 for (j = 0; j < ARRAY_SIZE(user_mem_tests); ++j)
5271 memset(&ddsd, 0, sizeof(ddsd));
5272 ddsd.dwSize = sizeof(ddsd);
5273 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | user_mem_tests[j].flags;
5274 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE;
5276 switch (user_mem_tests[j].size_type)
5278 case SIZE_TYPE_ZERO:
5279 U1(ddsd).dwLinearSize = 0;
5280 break;
5282 case SIZE_TYPE_PITCH:
5283 U1(ddsd).dwLinearSize = 2 * formats[i].block_size;
5284 break;
5286 case SIZE_TYPE_SIZE:
5287 U1(ddsd).dwLinearSize = 2 * 2 * formats[i].block_size;
5288 break;
5290 U1(ddsd).dwLinearSize += user_mem_tests[j].rel_size;
5292 ddsd.lpSurface = mem;
5293 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5294 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
5295 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
5296 ddsd.dwWidth = 8;
5297 ddsd.dwHeight = 8;
5299 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5300 ok(hr == user_mem_tests[j].hr, "Test %u: Got unexpected hr %#x, format %s.\n", j, hr, formats[i].name);
5302 if (FAILED(hr))
5303 continue;
5305 memset(&ddsd, 0, sizeof(ddsd));
5306 ddsd.dwSize = sizeof(ddsd);
5307 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5308 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", j, hr);
5309 ok(ddsd.dwFlags == (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_LINEARSIZE),
5310 "Test %u: Got unexpected flags %#x.\n", j, ddsd.dwFlags);
5311 if (user_mem_tests[j].flags & DDSD_LPSURFACE)
5312 ok(U1(ddsd).dwLinearSize == ~0u, "Test %u: Got unexpected linear size %#x.\n",
5313 j, U1(ddsd).dwLinearSize);
5314 else
5315 ok(U1(ddsd).dwLinearSize == 2 * 2 * formats[i].block_size,
5316 "Test %u: Got unexpected linear size %#x, expected %#x.\n",
5317 j, U1(ddsd).dwLinearSize, 2 * 2 * formats[i].block_size);
5318 IDirectDrawSurface4_Release(surface);
5322 HeapFree(GetProcessHeap(), 0, mem);
5323 cleanup:
5324 IDirectDraw4_Release(ddraw);
5325 IDirect3DDevice3_Release(device);
5326 DestroyWindow(window);
5329 struct format_support_check
5331 const DDPIXELFORMAT *format;
5332 BOOL supported;
5335 static HRESULT WINAPI test_unsupported_formats_cb(DDPIXELFORMAT *fmt, void *ctx)
5337 struct format_support_check *format = ctx;
5339 if (!memcmp(format->format, fmt, sizeof(*fmt)))
5341 format->supported = TRUE;
5342 return DDENUMRET_CANCEL;
5345 return DDENUMRET_OK;
5348 static void test_unsupported_formats(void)
5350 HRESULT hr;
5351 BOOL expect_success;
5352 HWND window;
5353 IDirectDraw4 *ddraw;
5354 IDirect3D3 *d3d;
5355 IDirect3DDevice3 *device;
5356 IDirectDrawSurface4 *surface;
5357 DDSURFACEDESC2 ddsd;
5358 unsigned int i, j;
5359 DWORD expected_caps;
5360 static const struct
5362 const char *name;
5363 DDPIXELFORMAT fmt;
5365 formats[] =
5368 "D3DFMT_A8R8G8B8",
5370 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
5371 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
5375 "D3DFMT_P8",
5377 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5378 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
5382 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
5384 window = create_window();
5385 if (!(device = create_device(window, DDSCL_NORMAL)))
5387 skip("Failed to create a 3D device, skipping test.\n");
5388 DestroyWindow(window);
5389 return;
5392 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
5393 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5394 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **) &ddraw);
5395 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5396 IDirect3D3_Release(d3d);
5398 for (i = 0; i < ARRAY_SIZE(formats); i++)
5400 struct format_support_check check = {&formats[i].fmt, FALSE};
5401 hr = IDirect3DDevice3_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
5402 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
5404 for (j = 0; j < ARRAY_SIZE(caps); j++)
5406 memset(&ddsd, 0, sizeof(ddsd));
5407 ddsd.dwSize = sizeof(ddsd);
5408 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5409 U4(ddsd).ddpfPixelFormat = formats[i].fmt;
5410 ddsd.dwWidth = 4;
5411 ddsd.dwHeight = 4;
5412 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
5414 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
5415 expect_success = FALSE;
5416 else
5417 expect_success = TRUE;
5419 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5420 ok(SUCCEEDED(hr) == expect_success,
5421 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
5422 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
5423 if (FAILED(hr))
5424 continue;
5426 memset(&ddsd, 0, sizeof(ddsd));
5427 ddsd.dwSize = sizeof(ddsd);
5428 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5429 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5431 if (caps[j] & DDSCAPS_VIDEOMEMORY)
5432 expected_caps = DDSCAPS_VIDEOMEMORY;
5433 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
5434 expected_caps = DDSCAPS_SYSTEMMEMORY;
5435 else if (check.supported)
5436 expected_caps = DDSCAPS_VIDEOMEMORY;
5437 else
5438 expected_caps = DDSCAPS_SYSTEMMEMORY;
5440 ok(ddsd.ddsCaps.dwCaps & expected_caps,
5441 "Expected capability %#x, format %s, input cap %#x.\n",
5442 expected_caps, formats[i].name, caps[j]);
5444 IDirectDrawSurface4_Release(surface);
5448 IDirectDraw4_Release(ddraw);
5449 IDirect3DDevice3_Release(device);
5450 DestroyWindow(window);
5453 static void test_rt_caps(void)
5455 PALETTEENTRY palette_entries[256];
5456 IDirectDrawPalette *palette;
5457 IDirectDraw4 *ddraw;
5458 DDPIXELFORMAT z_fmt;
5459 IDirect3D3 *d3d;
5460 unsigned int i;
5461 ULONG refcount;
5462 HWND window;
5463 HRESULT hr;
5465 static const DDPIXELFORMAT p8_fmt =
5467 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5468 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
5471 const struct
5473 const DDPIXELFORMAT *pf;
5474 DWORD caps_in;
5475 DWORD caps_out;
5476 HRESULT create_device_hr;
5477 HRESULT set_rt_hr, alternative_set_rt_hr;
5479 test_data[] =
5482 NULL,
5483 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5484 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5485 D3D_OK,
5486 D3D_OK,
5487 D3D_OK,
5490 NULL,
5491 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5492 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5493 D3D_OK,
5494 D3D_OK,
5495 D3D_OK,
5498 NULL,
5499 DDSCAPS_OFFSCREENPLAIN,
5500 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5501 DDERR_INVALIDCAPS,
5502 DDERR_INVALIDCAPS,
5503 DDERR_INVALIDCAPS,
5506 NULL,
5507 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5508 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5509 D3DERR_SURFACENOTINVIDMEM,
5510 D3D_OK,
5511 D3D_OK,
5514 NULL,
5515 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5516 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5517 DDERR_INVALIDCAPS,
5518 DDERR_INVALIDCAPS,
5519 DDERR_INVALIDCAPS,
5522 NULL,
5523 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5524 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5525 D3D_OK,
5526 D3D_OK,
5527 D3D_OK,
5530 NULL,
5531 DDSCAPS_3DDEVICE,
5532 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5533 D3D_OK,
5534 D3D_OK,
5535 D3D_OK,
5538 NULL,
5540 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5541 DDERR_INVALIDCAPS,
5542 DDERR_INVALIDCAPS,
5543 DDERR_INVALIDCAPS,
5546 NULL,
5547 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5548 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5549 D3DERR_SURFACENOTINVIDMEM,
5550 D3D_OK,
5551 D3D_OK,
5554 NULL,
5555 DDSCAPS_SYSTEMMEMORY,
5556 DDSCAPS_SYSTEMMEMORY,
5557 DDERR_INVALIDCAPS,
5558 DDERR_INVALIDCAPS,
5559 DDERR_INVALIDCAPS,
5562 &p8_fmt,
5564 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5565 DDERR_INVALIDCAPS,
5566 DDERR_INVALIDCAPS,
5567 DDERR_INVALIDCAPS,
5570 &p8_fmt,
5571 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5572 ~0U /* AMD r200 */,
5573 DDERR_NOPALETTEATTACHED,
5574 DDERR_INVALIDCAPS,
5575 DDERR_INVALIDCAPS,
5578 &p8_fmt,
5579 DDSCAPS_OFFSCREENPLAIN,
5580 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5581 DDERR_INVALIDCAPS,
5582 DDERR_INVALIDCAPS,
5583 DDERR_INVALIDCAPS,
5586 &p8_fmt,
5587 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5588 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5589 DDERR_NOPALETTEATTACHED,
5590 DDERR_INVALIDCAPS,
5591 DDERR_INVALIDCAPS,
5594 &p8_fmt,
5595 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5596 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5597 DDERR_INVALIDCAPS,
5598 DDERR_INVALIDCAPS,
5599 DDERR_INVALIDCAPS,
5602 &z_fmt,
5603 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
5604 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5605 DDERR_INVALIDCAPS,
5606 DDERR_INVALIDPIXELFORMAT,
5607 D3D_OK /* r200 */,
5610 &z_fmt,
5611 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5612 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5613 DDERR_INVALIDCAPS,
5614 DDERR_INVALIDPIXELFORMAT,
5615 D3D_OK /* r200 */,
5618 &z_fmt,
5619 DDSCAPS_ZBUFFER,
5620 DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5621 DDERR_INVALIDCAPS,
5622 DDERR_INVALIDCAPS,
5623 DDERR_INVALIDCAPS,
5626 &z_fmt,
5627 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5628 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5629 DDERR_INVALIDCAPS,
5630 DDERR_INVALIDPIXELFORMAT,
5631 D3D_OK /* r200 */,
5634 &z_fmt,
5635 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5636 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5637 DDERR_INVALIDCAPS,
5638 DDERR_INVALIDCAPS,
5639 DDERR_INVALIDCAPS,
5643 window = create_window();
5644 ddraw = create_ddraw();
5645 ok(!!ddraw, "Failed to create a ddraw object.\n");
5646 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5647 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5649 if (FAILED(IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
5651 skip("D3D interface is not available, skipping test.\n");
5652 goto done;
5655 memset(&z_fmt, 0, sizeof(z_fmt));
5656 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
5657 if (FAILED(hr) || !z_fmt.dwSize)
5659 skip("No depth buffer formats available, skipping test.\n");
5660 IDirect3D3_Release(d3d);
5661 goto done;
5664 memset(palette_entries, 0, sizeof(palette_entries));
5665 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
5666 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5668 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5670 IDirectDrawSurface4 *surface, *rt, *expected_rt, *tmp;
5671 DDSURFACEDESC2 surface_desc;
5672 IDirect3DDevice3 *device;
5674 memset(&surface_desc, 0, sizeof(surface_desc));
5675 surface_desc.dwSize = sizeof(surface_desc);
5676 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5677 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5678 if (test_data[i].pf)
5680 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5681 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5683 surface_desc.dwWidth = 640;
5684 surface_desc.dwHeight = 480;
5685 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5686 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
5687 i, test_data[i].caps_in, hr);
5689 memset(&surface_desc, 0, sizeof(surface_desc));
5690 surface_desc.dwSize = sizeof(surface_desc);
5691 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
5692 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5693 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
5694 "Test %u: Got unexpected caps %#x, expected %#x.\n",
5695 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5697 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
5698 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
5699 i, hr, test_data[i].create_device_hr);
5700 if (FAILED(hr))
5702 if (hr == DDERR_NOPALETTEATTACHED)
5704 hr = IDirectDrawSurface4_SetPalette(surface, palette);
5705 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
5706 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
5707 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
5708 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
5709 else
5710 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
5712 IDirectDrawSurface4_Release(surface);
5714 memset(&surface_desc, 0, sizeof(surface_desc));
5715 surface_desc.dwSize = sizeof(surface_desc);
5716 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5717 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5718 surface_desc.dwWidth = 640;
5719 surface_desc.dwHeight = 480;
5720 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5721 ok(SUCCEEDED(hr), "Test %u: Failed to create surface, hr %#x.\n", i, hr);
5723 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
5724 ok(SUCCEEDED(hr), "Test %u: Failed to create device, hr %#x.\n", i, hr);
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 = test_data[i].caps_in;
5731 if (test_data[i].pf)
5733 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5734 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5736 surface_desc.dwWidth = 640;
5737 surface_desc.dwHeight = 480;
5738 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &rt, NULL);
5739 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
5740 i, test_data[i].caps_in, hr);
5742 hr = IDirect3DDevice3_SetRenderTarget(device, rt, 0);
5743 ok(hr == test_data[i].set_rt_hr || broken(hr == test_data[i].alternative_set_rt_hr),
5744 "Test %u: Got unexpected hr %#x, expected %#x.\n",
5745 i, hr, test_data[i].set_rt_hr);
5746 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
5747 expected_rt = rt;
5748 else
5749 expected_rt = surface;
5751 hr = IDirect3DDevice3_GetRenderTarget(device, &tmp);
5752 ok(SUCCEEDED(hr), "Test %u: Failed to get render target, hr %#x.\n", i, hr);
5753 ok(tmp == expected_rt, "Test %u: Got unexpected rt %p.\n", i, tmp);
5755 IDirectDrawSurface4_Release(tmp);
5756 IDirectDrawSurface4_Release(rt);
5757 refcount = IDirect3DDevice3_Release(device);
5758 ok(refcount == 0, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
5759 refcount = IDirectDrawSurface4_Release(surface);
5760 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
5763 IDirectDrawPalette_Release(palette);
5764 IDirect3D3_Release(d3d);
5766 done:
5767 refcount = IDirectDraw4_Release(ddraw);
5768 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5769 DestroyWindow(window);
5772 static void test_primary_caps(void)
5774 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
5775 IDirectDrawSurface4 *surface;
5776 DDSURFACEDESC2 surface_desc;
5777 IDirectDraw4 *ddraw;
5778 unsigned int i;
5779 ULONG refcount;
5780 HWND window;
5781 HRESULT hr;
5783 static const struct
5785 DWORD coop_level;
5786 DWORD caps_in;
5787 DWORD back_buffer_count;
5788 HRESULT hr;
5789 DWORD caps_out;
5791 test_data[] =
5794 DDSCL_NORMAL,
5795 DDSCAPS_PRIMARYSURFACE,
5796 ~0u,
5797 DD_OK,
5798 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
5801 DDSCL_NORMAL,
5802 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
5803 ~0u,
5804 DDERR_INVALIDCAPS,
5805 ~0u,
5808 DDSCL_NORMAL,
5809 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
5810 ~0u,
5811 DDERR_INVALIDCAPS,
5812 ~0u,
5815 DDSCL_NORMAL,
5816 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
5817 ~0u,
5818 DDERR_INVALIDCAPS,
5819 ~0u,
5822 DDSCL_NORMAL,
5823 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
5824 ~0u,
5825 DDERR_INVALIDCAPS,
5826 ~0u,
5829 DDSCL_NORMAL,
5830 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
5831 ~0u,
5832 DDERR_INVALIDCAPS,
5833 ~0u,
5836 DDSCL_NORMAL,
5837 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5838 ~0u,
5839 DDERR_INVALIDCAPS,
5840 ~0u,
5843 DDSCL_NORMAL,
5844 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5846 DDERR_INVALIDCAPS,
5847 ~0u,
5850 DDSCL_NORMAL,
5851 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5853 DDERR_NOEXCLUSIVEMODE,
5854 ~0u,
5857 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5858 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5860 DDERR_INVALIDCAPS,
5861 ~0u,
5864 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5865 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5867 DD_OK,
5868 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
5871 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5872 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
5874 DDERR_INVALIDCAPS,
5875 ~0u,
5878 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5879 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
5881 DDERR_INVALIDCAPS,
5882 ~0u,
5886 window = create_window();
5887 ddraw = create_ddraw();
5888 ok(!!ddraw, "Failed to create a ddraw object.\n");
5890 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5892 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
5893 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5895 memset(&surface_desc, 0, sizeof(surface_desc));
5896 surface_desc.dwSize = sizeof(surface_desc);
5897 surface_desc.dwFlags = DDSD_CAPS;
5898 if (test_data[i].back_buffer_count != ~0u)
5899 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
5900 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5901 U5(surface_desc).dwBackBufferCount = test_data[i].back_buffer_count;
5902 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5903 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
5904 if (FAILED(hr))
5905 continue;
5907 memset(&surface_desc, 0, sizeof(surface_desc));
5908 surface_desc.dwSize = sizeof(surface_desc);
5909 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
5910 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5911 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
5912 "Test %u: Got unexpected caps %#x, expected %#x.\n",
5913 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5915 IDirectDrawSurface4_Release(surface);
5918 refcount = IDirectDraw4_Release(ddraw);
5919 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5920 DestroyWindow(window);
5923 static void test_surface_lock(void)
5925 IDirectDraw4 *ddraw;
5926 IDirect3D3 *d3d = NULL;
5927 IDirectDrawSurface4 *surface;
5928 HRESULT hr;
5929 HWND window;
5930 unsigned int i;
5931 DDSURFACEDESC2 ddsd;
5932 ULONG refcount;
5933 DDPIXELFORMAT z_fmt;
5934 static const struct
5936 DWORD caps;
5937 DWORD caps2;
5938 const char *name;
5940 tests[] =
5943 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
5945 "videomemory offscreenplain"
5948 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5950 "systemmemory offscreenplain"
5953 DDSCAPS_PRIMARYSURFACE,
5955 "primary"
5958 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
5960 "videomemory texture"
5963 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
5964 DDSCAPS2_OPAQUE,
5965 "opaque videomemory texture"
5968 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
5970 "systemmemory texture"
5973 DDSCAPS_TEXTURE,
5974 DDSCAPS2_TEXTUREMANAGE,
5975 "managed texture"
5978 DDSCAPS_TEXTURE,
5979 DDSCAPS2_D3DTEXTUREMANAGE,
5980 "managed texture"
5983 DDSCAPS_TEXTURE,
5984 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_OPAQUE,
5985 "opaque managed texture"
5988 DDSCAPS_TEXTURE,
5989 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_OPAQUE,
5990 "opaque managed texture"
5993 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5995 "render target"
5998 DDSCAPS_ZBUFFER,
6000 "Z buffer"
6004 window = create_window();
6005 ddraw = create_ddraw();
6006 ok(!!ddraw, "Failed to create a ddraw object.\n");
6007 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6008 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6010 if (FAILED(IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
6012 skip("D3D interface is not available, skipping test.\n");
6013 goto done;
6016 memset(&z_fmt, 0, sizeof(z_fmt));
6017 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
6018 if (FAILED(hr) || !z_fmt.dwSize)
6020 skip("No depth buffer formats available, skipping test.\n");
6021 goto done;
6024 for (i = 0; i < ARRAY_SIZE(tests); i++)
6026 memset(&ddsd, 0, sizeof(ddsd));
6027 ddsd.dwSize = sizeof(ddsd);
6028 ddsd.dwFlags = DDSD_CAPS;
6029 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
6031 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6032 ddsd.dwWidth = 64;
6033 ddsd.dwHeight = 64;
6035 if (tests[i].caps & DDSCAPS_ZBUFFER)
6037 ddsd.dwFlags |= DDSD_PIXELFORMAT;
6038 U4(ddsd).ddpfPixelFormat = z_fmt;
6040 ddsd.ddsCaps.dwCaps = tests[i].caps;
6041 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
6043 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6044 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
6046 memset(&ddsd, 0, sizeof(ddsd));
6047 ddsd.dwSize = sizeof(ddsd);
6048 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
6049 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
6050 if (SUCCEEDED(hr))
6052 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6053 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
6056 memset(&ddsd, 0, sizeof(ddsd));
6057 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
6058 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, tests[i].name);
6060 IDirectDrawSurface4_Release(surface);
6063 done:
6064 if (d3d)
6065 IDirect3D3_Release(d3d);
6066 refcount = IDirectDraw4_Release(ddraw);
6067 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6068 DestroyWindow(window);
6071 static void test_surface_discard(void)
6073 IDirect3DDevice3 *device;
6074 IDirect3D3 *d3d;
6075 IDirectDraw4 *ddraw;
6076 HRESULT hr;
6077 HWND window;
6078 DDSURFACEDESC2 ddsd;
6079 IDirectDrawSurface4 *surface, *target;
6080 void *addr;
6081 static const struct
6083 DWORD caps, caps2;
6084 BOOL discard;
6086 tests[] =
6088 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, TRUE},
6089 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
6090 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, TRUE},
6091 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
6092 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE},
6093 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
6094 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE},
6095 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
6097 unsigned int i;
6099 window = create_window();
6100 if (!(device = create_device(window, DDSCL_NORMAL)))
6102 skip("Failed to create a 3D device, skipping test.\n");
6103 DestroyWindow(window);
6104 return;
6106 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
6107 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
6108 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
6109 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
6110 hr = IDirect3DDevice3_GetRenderTarget(device, &target);
6111 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
6113 for (i = 0; i < ARRAY_SIZE(tests); i++)
6115 BOOL discarded;
6117 memset(&ddsd, 0, sizeof(ddsd));
6118 ddsd.dwSize = sizeof(ddsd);
6119 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6120 ddsd.ddsCaps.dwCaps = tests[i].caps;
6121 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
6122 ddsd.dwWidth = 64;
6123 ddsd.dwHeight = 64;
6124 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6125 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x, case %u.\n", hr, i);
6127 memset(&ddsd, 0, sizeof(ddsd));
6128 ddsd.dwSize = sizeof(ddsd);
6129 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, 0, NULL);
6130 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6131 addr = ddsd.lpSurface;
6132 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6133 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6135 memset(&ddsd, 0, sizeof(ddsd));
6136 ddsd.dwSize = sizeof(ddsd);
6137 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
6138 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6139 discarded = ddsd.lpSurface != addr;
6140 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6141 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6143 hr = IDirectDrawSurface4_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
6144 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
6146 memset(&ddsd, 0, sizeof(ddsd));
6147 ddsd.dwSize = sizeof(ddsd);
6148 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
6149 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6150 discarded |= ddsd.lpSurface != addr;
6151 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6152 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6154 IDirectDrawSurface4_Release(surface);
6156 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
6157 * AMD r500, evergreen). Windows XP, at least on AMD r200, does not. */
6158 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
6161 IDirectDrawSurface4_Release(target);
6162 IDirectDraw4_Release(ddraw);
6163 IDirect3D3_Release(d3d);
6164 IDirect3DDevice3_Release(device);
6165 DestroyWindow(window);
6168 static void fill_surface(IDirectDrawSurface4 *surface, D3DCOLOR color)
6170 DDSURFACEDESC2 surface_desc = {sizeof(surface_desc)};
6171 HRESULT hr;
6172 unsigned int x, y;
6173 DWORD *ptr;
6175 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
6176 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6178 for (y = 0; y < surface_desc.dwHeight; ++y)
6180 ptr = (DWORD *)((BYTE *)surface_desc.lpSurface + y * surface_desc.lPitch);
6181 for (x = 0; x < surface_desc.dwWidth; ++x)
6183 ptr[x] = color;
6187 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6188 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6191 static void test_flip(void)
6193 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
6194 IDirectDrawSurface4 *frontbuffer, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
6195 DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}};
6196 DDSURFACEDESC2 surface_desc;
6197 BOOL sysmem_primary;
6198 IDirectDraw4 *ddraw;
6199 DWORD expected_caps;
6200 unsigned int i;
6201 D3DCOLOR color;
6202 ULONG refcount;
6203 HWND window;
6204 HRESULT hr;
6206 static const struct
6208 const char *name;
6209 DWORD caps;
6211 test_data[] =
6213 {"PRIMARYSURFACE", DDSCAPS_PRIMARYSURFACE},
6214 {"OFFSCREENPLAIN", DDSCAPS_OFFSCREENPLAIN},
6215 {"TEXTURE", DDSCAPS_TEXTURE},
6218 window = create_window();
6219 ddraw = create_ddraw();
6220 ok(!!ddraw, "Failed to create a ddraw object.\n");
6222 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6223 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6225 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6227 /* Creating a flippable texture induces a BSoD on some versions of the
6228 * Intel graphics driver. At least Intel GMA 950 with driver version
6229 * 6.14.10.4926 on Windows XP SP3 is affected. */
6230 if ((test_data[i].caps & DDSCAPS_TEXTURE) && ddraw_is_intel(ddraw))
6232 win_skip("Skipping flippable texture test.\n");
6233 continue;
6236 memset(&surface_desc, 0, sizeof(surface_desc));
6237 surface_desc.dwSize = sizeof(surface_desc);
6238 surface_desc.dwFlags = DDSD_CAPS;
6239 if (!(test_data[i].caps & DDSCAPS_PRIMARYSURFACE))
6240 surface_desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6241 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
6242 surface_desc.dwWidth = 512;
6243 surface_desc.dwHeight = 512;
6244 U5(surface_desc).dwBackBufferCount = 3;
6245 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6246 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6248 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
6249 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
6250 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6251 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6253 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
6254 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
6255 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6256 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6258 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
6259 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6260 todo_wine_if(test_data[i].caps & DDSCAPS_TEXTURE)
6261 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
6262 if (FAILED(hr))
6263 continue;
6265 memset(&surface_desc, 0, sizeof(surface_desc));
6266 surface_desc.dwSize = sizeof(surface_desc);
6267 hr = IDirectDrawSurface4_GetSurfaceDesc(frontbuffer, &surface_desc);
6268 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6269 expected_caps = DDSCAPS_FRONTBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
6270 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
6271 expected_caps |= DDSCAPS_VISIBLE;
6272 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6273 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6274 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
6276 hr = IDirectDrawSurface4_GetAttachedSurface(frontbuffer, &caps, &backbuffer1);
6277 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6278 memset(&surface_desc, 0, sizeof(surface_desc));
6279 surface_desc.dwSize = sizeof(surface_desc);
6280 hr = IDirectDrawSurface4_GetSurfaceDesc(backbuffer1, &surface_desc);
6281 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6282 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6283 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6284 expected_caps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER);
6285 expected_caps |= DDSCAPS_BACKBUFFER;
6286 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6287 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6289 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
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(backbuffer2, &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_BACKBUFFER;
6298 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6299 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6301 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
6302 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6303 memset(&surface_desc, 0, sizeof(surface_desc));
6304 surface_desc.dwSize = sizeof(surface_desc);
6305 hr = IDirectDrawSurface4_GetSurfaceDesc(backbuffer3, &surface_desc);
6306 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6307 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6308 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6309 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6310 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6312 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer3, &caps, &surface);
6313 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6314 ok(surface == frontbuffer, "%s: Got unexpected surface %p, expected %p.\n",
6315 test_data[i].name, surface, frontbuffer);
6316 IDirectDrawSurface4_Release(surface);
6318 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
6319 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
6320 hr = IDirectDrawSurface4_IsLost(frontbuffer);
6321 ok(hr == DD_OK, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6322 hr = IDirectDrawSurface4_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6323 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
6324 ok(hr == DDERR_NOEXCLUSIVEMODE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6325 else
6326 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6327 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6328 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
6329 hr = IDirectDrawSurface4_IsLost(frontbuffer);
6330 todo_wine ok(hr == DDERR_SURFACELOST, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6331 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
6332 ok(SUCCEEDED(hr), "%s: Failed to restore surfaces, hr %#x.\n", test_data[i].name, hr);
6334 memset(&surface_desc, 0, sizeof(surface_desc));
6335 surface_desc.dwSize = sizeof(surface_desc);
6336 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6337 surface_desc.ddsCaps.dwCaps = 0;
6338 surface_desc.dwWidth = 640;
6339 surface_desc.dwHeight = 480;
6340 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6341 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
6342 hr = IDirectDrawSurface4_Flip(frontbuffer, surface, DDFLIP_WAIT);
6343 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6344 IDirectDrawSurface4_Release(surface);
6346 hr = IDirectDrawSurface4_Flip(frontbuffer, frontbuffer, DDFLIP_WAIT);
6347 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6348 hr = IDirectDrawSurface4_Flip(backbuffer1, NULL, DDFLIP_WAIT);
6349 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6350 hr = IDirectDrawSurface4_Flip(backbuffer2, NULL, DDFLIP_WAIT);
6351 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6352 hr = IDirectDrawSurface4_Flip(backbuffer3, NULL, DDFLIP_WAIT);
6353 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6355 /* The Nvidia Geforce 7 driver cannot do a color fill on a texture backbuffer after
6356 * the backbuffer has been locked. Do it ourselves as a workaround. Unlike ddraw1
6357 * and 2 GetSurfaceDesc does not cause issues in ddraw4 and ddraw7. */
6358 fill_surface(backbuffer1, 0xffff0000);
6359 fill_surface(backbuffer2, 0xff00ff00);
6360 fill_surface(backbuffer3, 0xff0000ff);
6362 hr = IDirectDrawSurface4_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6363 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6364 color = get_surface_color(backbuffer1, 320, 240);
6365 /* The testbot seems to just copy the contents of one surface to all the
6366 * others, instead of properly flipping. */
6367 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6368 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6369 color = get_surface_color(backbuffer2, 320, 240);
6370 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6371 fill_surface(backbuffer3, 0xffff0000);
6373 hr = IDirectDrawSurface4_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6374 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6375 color = get_surface_color(backbuffer1, 320, 240);
6376 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6377 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6378 color = get_surface_color(backbuffer2, 320, 240);
6379 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6380 fill_surface(backbuffer3, 0xff00ff00);
6382 hr = IDirectDrawSurface4_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6383 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6384 color = get_surface_color(backbuffer1, 320, 240);
6385 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6386 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6387 color = get_surface_color(backbuffer2, 320, 240);
6388 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6389 fill_surface(backbuffer3, 0xff0000ff);
6391 hr = IDirectDrawSurface4_Flip(frontbuffer, backbuffer1, DDFLIP_WAIT);
6392 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6393 color = get_surface_color(backbuffer2, 320, 240);
6394 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6395 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6396 color = get_surface_color(backbuffer3, 320, 240);
6397 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6398 fill_surface(backbuffer1, 0xffff0000);
6400 hr = IDirectDrawSurface4_Flip(frontbuffer, backbuffer2, DDFLIP_WAIT);
6401 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6402 color = get_surface_color(backbuffer1, 320, 240);
6403 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6404 color = get_surface_color(backbuffer3, 320, 240);
6405 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6406 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6407 fill_surface(backbuffer2, 0xff00ff00);
6409 hr = IDirectDrawSurface4_Flip(frontbuffer, backbuffer3, DDFLIP_WAIT);
6410 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6411 color = get_surface_color(backbuffer1, 320, 240);
6412 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6413 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6414 color = get_surface_color(backbuffer2, 320, 240);
6415 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6417 IDirectDrawSurface4_Release(backbuffer3);
6418 IDirectDrawSurface4_Release(backbuffer2);
6419 IDirectDrawSurface4_Release(backbuffer1);
6420 IDirectDrawSurface4_Release(frontbuffer);
6423 refcount = IDirectDraw4_Release(ddraw);
6424 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6425 DestroyWindow(window);
6428 static void reset_ddsd(DDSURFACEDESC2 *ddsd)
6430 memset(ddsd, 0, sizeof(*ddsd));
6431 ddsd->dwSize = sizeof(*ddsd);
6434 static void test_set_surface_desc(void)
6436 IDirectDraw4 *ddraw;
6437 HWND window;
6438 HRESULT hr;
6439 DDSURFACEDESC2 ddsd;
6440 IDirectDrawSurface4 *surface;
6441 BYTE data[16*16*4];
6442 ULONG ref;
6443 unsigned int i;
6444 static const struct
6446 DWORD caps, caps2;
6447 BOOL supported;
6448 const char *name;
6450 invalid_caps_tests[] =
6452 {DDSCAPS_VIDEOMEMORY, 0, FALSE, "videomemory plain"},
6453 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, TRUE, "systemmemory texture"},
6454 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE, "managed texture"},
6455 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE, "managed texture"},
6456 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, 0, FALSE, "systemmemory primary"},
6459 window = create_window();
6460 ddraw = create_ddraw();
6461 ok(!!ddraw, "Failed to create a ddraw object.\n");
6462 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6463 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6465 reset_ddsd(&ddsd);
6466 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6467 ddsd.dwWidth = 8;
6468 ddsd.dwHeight = 8;
6469 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6470 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6471 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6472 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6473 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6474 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6475 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6477 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6478 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6480 reset_ddsd(&ddsd);
6481 ddsd.dwFlags = DDSD_LPSURFACE;
6482 ddsd.lpSurface = data;
6483 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6484 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6486 /* Redundantly setting the same lpSurface is not an error. */
6487 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6488 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6489 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6490 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6491 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6492 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
6494 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, 0, NULL);
6495 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6496 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6497 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
6498 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6499 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6501 reset_ddsd(&ddsd);
6502 ddsd.dwFlags = DDSD_LPSURFACE;
6503 ddsd.lpSurface = data;
6504 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 1);
6505 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
6507 ddsd.lpSurface = NULL;
6508 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6509 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
6511 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, NULL, 0);
6512 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
6514 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6515 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6516 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6517 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6518 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6520 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
6521 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6522 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
6524 ddsd.dwFlags = DDSD_CAPS;
6525 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6526 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
6528 /* dwCaps = 0 is allowed, but ignored. Caps2 can be anything and is ignored too. */
6529 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
6530 ddsd.lpSurface = data;
6531 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6532 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6533 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6534 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6535 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6536 ddsd.ddsCaps.dwCaps = 0;
6537 ddsd.ddsCaps.dwCaps2 = 0xdeadbeef;
6538 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6539 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6541 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6542 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6543 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6544 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6545 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6547 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
6548 reset_ddsd(&ddsd);
6549 ddsd.dwFlags = DDSD_HEIGHT;
6550 ddsd.dwHeight = 16;
6551 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6552 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
6554 ddsd.lpSurface = data;
6555 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
6556 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6557 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6559 ddsd.dwHeight = 0;
6560 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6561 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
6563 reset_ddsd(&ddsd);
6564 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6565 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
6566 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6567 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6569 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0 */
6570 reset_ddsd(&ddsd);
6571 ddsd.dwFlags = DDSD_PITCH;
6572 U1(ddsd).lPitch = 8 * 4;
6573 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6574 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
6576 ddsd.dwFlags = DDSD_WIDTH;
6577 ddsd.dwWidth = 16;
6578 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6579 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
6581 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
6582 ddsd.lpSurface = data;
6583 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6584 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
6586 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
6587 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6588 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
6590 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6591 U1(ddsd).lPitch = 16 * 4;
6592 ddsd.dwWidth = 16;
6593 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6594 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6596 reset_ddsd(&ddsd);
6597 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6598 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6599 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6600 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6601 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
6603 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
6605 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
6606 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6607 U1(ddsd).lPitch = 4 * 4;
6608 ddsd.lpSurface = data;
6609 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6610 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
6612 U1(ddsd).lPitch = 4;
6613 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6614 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
6616 U1(ddsd).lPitch = 16 * 4 + 1;
6617 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6618 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
6620 U1(ddsd).lPitch = 16 * 4 + 3;
6621 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6622 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
6624 U1(ddsd).lPitch = -4;
6625 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6626 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
6628 U1(ddsd).lPitch = 16 * 4;
6629 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6630 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6632 reset_ddsd(&ddsd);
6633 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6634 U1(ddsd).lPitch = 0;
6635 ddsd.dwWidth = 16;
6636 ddsd.lpSurface = data;
6637 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6638 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
6640 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6641 U1(ddsd).lPitch = 16 * 4;
6642 ddsd.dwWidth = 0;
6643 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6644 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
6646 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
6647 ddsd.dwFlags = DDSD_PIXELFORMAT;
6648 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6649 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6650 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6651 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6652 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6653 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6654 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6655 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
6657 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
6658 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6659 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6661 /* Can't set color keys. */
6662 reset_ddsd(&ddsd);
6663 ddsd.dwFlags = DDSD_CKSRCBLT;
6664 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
6665 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
6666 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6667 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
6669 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
6670 ddsd.lpSurface = data;
6671 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6672 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
6674 IDirectDrawSurface4_Release(surface);
6676 /* SetSurfaceDesc needs systemmemory surfaces.
6678 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing DDSD_LINEARSIZE is moot. */
6679 for (i = 0; i < ARRAY_SIZE(invalid_caps_tests); i++)
6681 reset_ddsd(&ddsd);
6682 ddsd.dwFlags = DDSD_CAPS;
6683 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
6684 ddsd.ddsCaps.dwCaps2 = invalid_caps_tests[i].caps2;
6685 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
6687 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6688 ddsd.dwWidth = 8;
6689 ddsd.dwHeight = 8;
6690 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6691 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6692 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6693 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6694 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6695 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6698 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6699 ok(SUCCEEDED(hr) || hr == DDERR_NODIRECTDRAWHW, "Failed to create surface, hr %#x.\n", hr);
6700 if (FAILED(hr))
6702 skip("Cannot create a %s surface, skipping vidmem SetSurfaceDesc test.\n",
6703 invalid_caps_tests[i].name);
6704 goto done;
6707 reset_ddsd(&ddsd);
6708 ddsd.dwFlags = DDSD_LPSURFACE;
6709 ddsd.lpSurface = data;
6710 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6711 if (invalid_caps_tests[i].supported)
6713 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6715 else
6717 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
6718 invalid_caps_tests[i].name, hr);
6720 /* Check priority of error conditions. */
6721 ddsd.dwFlags = DDSD_WIDTH;
6722 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6723 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
6724 invalid_caps_tests[i].name, hr);
6727 IDirectDrawSurface4_Release(surface);
6730 done:
6731 ref = IDirectDraw4_Release(ddraw);
6732 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6733 DestroyWindow(window);
6736 static void test_user_memory_getdc(void)
6738 IDirectDraw4 *ddraw;
6739 HWND window;
6740 HRESULT hr;
6741 DDSURFACEDESC2 ddsd;
6742 IDirectDrawSurface4 *surface;
6743 DWORD data[16][16];
6744 HBITMAP bitmap;
6745 DIBSECTION dib;
6746 ULONG ref;
6747 int size;
6748 HDC dc;
6749 unsigned int x, y;
6751 window = create_window();
6752 ddraw = create_ddraw();
6753 ok(!!ddraw, "Failed to create a ddraw object.\n");
6755 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6756 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6758 reset_ddsd(&ddsd);
6759 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6760 ddsd.dwWidth = 16;
6761 ddsd.dwHeight = 16;
6762 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6763 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6764 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6765 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6766 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6767 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6768 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6769 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6770 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6772 memset(data, 0xaa, sizeof(data));
6773 reset_ddsd(&ddsd);
6774 ddsd.dwFlags = DDSD_LPSURFACE;
6775 ddsd.lpSurface = data;
6776 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6777 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6779 hr = IDirectDrawSurface4_GetDC(surface, &dc);
6780 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6781 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
6782 ok(!!bitmap, "Failed to get bitmap.\n");
6783 size = GetObjectA(bitmap, sizeof(dib), &dib);
6784 ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
6785 ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
6786 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
6787 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
6788 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
6789 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6791 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
6792 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
6794 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
6795 ddsd.lpSurface = data;
6796 ddsd.dwWidth = 4;
6797 ddsd.dwHeight = 8;
6798 U1(ddsd).lPitch = sizeof(*data);
6799 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6800 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6802 memset(data, 0xaa, sizeof(data));
6803 hr = IDirectDrawSurface4_GetDC(surface, &dc);
6804 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6805 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
6806 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
6807 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
6808 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6810 for (y = 0; y < 4; y++)
6812 for (x = 0; x < 4; x++)
6814 if ((x == 1 || x == 2) && (y == 1 || y == 2))
6815 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
6816 x, y, data[y][x]);
6817 else
6818 ok(data[y][x] == 0x00000000, "Expected color 0x00000000 on position %ux%u, got %#x.\n",
6819 x, y, data[y][x]);
6822 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
6823 data[0][5]);
6824 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
6825 data[7][3]);
6826 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
6827 data[7][4]);
6828 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
6829 data[8][0]);
6831 IDirectDrawSurface4_Release(surface);
6832 ref = IDirectDraw4_Release(ddraw);
6833 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6834 DestroyWindow(window);
6837 static void test_sysmem_overlay(void)
6839 IDirectDraw4 *ddraw;
6840 HWND window;
6841 HRESULT hr;
6842 DDSURFACEDESC2 ddsd;
6843 IDirectDrawSurface4 *surface;
6844 ULONG ref;
6846 window = create_window();
6847 ddraw = create_ddraw();
6848 ok(!!ddraw, "Failed to create a ddraw object.\n");
6850 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6851 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6853 reset_ddsd(&ddsd);
6854 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
6855 ddsd.dwWidth = 16;
6856 ddsd.dwHeight = 16;
6857 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
6858 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6859 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6860 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6861 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6862 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6863 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6864 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6865 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
6867 ref = IDirectDraw4_Release(ddraw);
6868 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6869 DestroyWindow(window);
6872 static void test_primary_palette(void)
6874 DDSCAPS2 surface_caps = {DDSCAPS_FLIP, 0, 0, {0}};
6875 IDirectDrawSurface4 *primary, *backbuffer;
6876 PALETTEENTRY palette_entries[256];
6877 IDirectDrawPalette *palette, *tmp;
6878 DDSURFACEDESC2 surface_desc;
6879 IDirectDraw4 *ddraw;
6880 DWORD palette_caps;
6881 ULONG refcount;
6882 HWND window;
6883 HRESULT hr;
6885 window = create_window();
6886 ddraw = create_ddraw();
6887 ok(!!ddraw, "Failed to create a ddraw object.\n");
6888 if (FAILED(IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
6890 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
6891 IDirectDraw4_Release(ddraw);
6892 DestroyWindow(window);
6893 return;
6895 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6896 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6898 memset(&surface_desc, 0, sizeof(surface_desc));
6899 surface_desc.dwSize = sizeof(surface_desc);
6900 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
6901 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
6902 U5(surface_desc).dwBackBufferCount = 1;
6903 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
6904 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6905 hr = IDirectDrawSurface4_GetAttachedSurface(primary, &surface_caps, &backbuffer);
6906 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
6908 memset(palette_entries, 0, sizeof(palette_entries));
6909 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
6910 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6911 refcount = get_refcount((IUnknown *)palette);
6912 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6914 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6915 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6916 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
6918 hr = IDirectDrawSurface4_SetPalette(primary, palette);
6919 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6921 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
6922 * and is generally somewhat broken with respect to 8 bpp / palette
6923 * handling. */
6924 if (SUCCEEDED(IDirectDrawSurface4_GetPalette(backbuffer, &tmp)))
6926 win_skip("Broken palette handling detected, skipping tests.\n");
6927 IDirectDrawPalette_Release(tmp);
6928 IDirectDrawPalette_Release(palette);
6929 /* The Windows 8 testbot keeps extra references to the primary and
6930 * backbuffer while in 8 bpp mode. */
6931 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
6932 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
6933 goto done;
6936 refcount = get_refcount((IUnknown *)palette);
6937 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6939 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6940 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6941 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
6942 "Got unexpected palette caps %#x.\n", palette_caps);
6944 hr = IDirectDrawSurface4_SetPalette(primary, NULL);
6945 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6946 refcount = get_refcount((IUnknown *)palette);
6947 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6949 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6950 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6951 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
6953 hr = IDirectDrawSurface4_SetPalette(primary, palette);
6954 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6955 refcount = get_refcount((IUnknown *)palette);
6956 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6958 hr = IDirectDrawSurface4_GetPalette(primary, &tmp);
6959 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
6960 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
6961 IDirectDrawPalette_Release(tmp);
6962 hr = IDirectDrawSurface4_GetPalette(backbuffer, &tmp);
6963 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6965 refcount = IDirectDrawPalette_Release(palette);
6966 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6967 refcount = IDirectDrawPalette_Release(palette);
6968 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6970 /* Note that this only seems to work when the palette is attached to the
6971 * primary surface. When attached to a regular surface, attempting to get
6972 * the palette here will cause an access violation. */
6973 hr = IDirectDrawSurface4_GetPalette(primary, &tmp);
6974 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6976 hr = IDirectDrawSurface4_IsLost(primary);
6977 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6979 memset(&surface_desc, 0, sizeof(surface_desc));
6980 surface_desc.dwSize = sizeof(surface_desc);
6981 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &surface_desc);
6982 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6983 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
6984 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
6985 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 8, "Got unexpected bit count %u.\n",
6986 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
6988 hr = set_display_mode(ddraw, 640, 480);
6989 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
6991 memset(&surface_desc, 0, sizeof(surface_desc));
6992 surface_desc.dwSize = sizeof(surface_desc);
6993 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &surface_desc);
6994 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6995 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
6996 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
6997 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
6998 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
6999 "Got unexpected bit count %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
7001 hr = IDirectDrawSurface4_IsLost(primary);
7002 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7003 hr = IDirectDrawSurface4_Restore(primary);
7004 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
7005 hr = IDirectDrawSurface4_IsLost(primary);
7006 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7008 memset(&surface_desc, 0, sizeof(surface_desc));
7009 surface_desc.dwSize = sizeof(surface_desc);
7010 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &surface_desc);
7011 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7012 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
7013 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
7014 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
7015 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
7016 "Got unexpected bit count %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
7018 done:
7019 refcount = IDirectDrawSurface4_Release(backbuffer);
7020 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7021 refcount = IDirectDrawSurface4_Release(primary);
7022 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7023 refcount = IDirectDraw4_Release(ddraw);
7024 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7025 DestroyWindow(window);
7028 static HRESULT WINAPI surface_counter(IDirectDrawSurface4 *surface, DDSURFACEDESC2 *desc, void *context)
7030 UINT *surface_count = context;
7032 ++(*surface_count);
7033 IDirectDrawSurface_Release(surface);
7035 return DDENUMRET_OK;
7038 static void test_surface_attachment(void)
7040 IDirectDrawSurface4 *surface1, *surface2, *surface3, *surface4;
7041 IDirectDrawSurface *surface1v1, *surface2v1;
7042 DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, {0}};
7043 DDSURFACEDESC2 surface_desc;
7044 IDirectDraw4 *ddraw;
7045 UINT surface_count;
7046 ULONG refcount;
7047 HWND window;
7048 HRESULT hr;
7050 window = create_window();
7051 ddraw = create_ddraw();
7052 ok(!!ddraw, "Failed to create a ddraw object.\n");
7053 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7054 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7056 memset(&surface_desc, 0, sizeof(surface_desc));
7057 surface_desc.dwSize = sizeof(surface_desc);
7058 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
7059 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7060 U2(surface_desc).dwMipMapCount = 3;
7061 surface_desc.dwWidth = 128;
7062 surface_desc.dwHeight = 128;
7063 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7064 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7066 hr = IDirectDrawSurface4_GetAttachedSurface(surface1, &caps, &surface2);
7067 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
7068 hr = IDirectDrawSurface4_GetAttachedSurface(surface2, &caps, &surface3);
7069 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
7070 hr = IDirectDrawSurface4_GetAttachedSurface(surface3, &caps, &surface4);
7071 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7073 surface_count = 0;
7074 IDirectDrawSurface4_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
7075 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
7076 surface_count = 0;
7077 IDirectDrawSurface4_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
7078 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
7079 surface_count = 0;
7080 IDirectDrawSurface4_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
7081 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
7083 memset(&surface_desc, 0, sizeof(surface_desc));
7084 surface_desc.dwSize = sizeof(surface_desc);
7085 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7086 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
7087 surface_desc.dwWidth = 16;
7088 surface_desc.dwHeight = 16;
7089 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7090 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7092 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface4);
7093 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7094 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface1);
7095 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7096 hr = IDirectDrawSurface4_AddAttachedSurface(surface3, surface4);
7097 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7098 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface3);
7099 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7100 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface4);
7101 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7102 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface2);
7103 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7105 IDirectDrawSurface4_Release(surface4);
7107 memset(&surface_desc, 0, sizeof(surface_desc));
7108 surface_desc.dwSize = sizeof(surface_desc);
7109 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7110 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7111 surface_desc.dwWidth = 16;
7112 surface_desc.dwHeight = 16;
7113 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7114 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7116 if (SUCCEEDED(hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface4)))
7118 skip("Running on refrast, skipping some tests.\n");
7119 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface4);
7120 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7122 else
7124 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7125 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface1);
7126 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7127 hr = IDirectDrawSurface4_AddAttachedSurface(surface3, surface4);
7128 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7129 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface3);
7130 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7131 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface4);
7132 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7133 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface2);
7134 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7137 IDirectDrawSurface4_Release(surface4);
7138 IDirectDrawSurface4_Release(surface3);
7139 IDirectDrawSurface4_Release(surface2);
7140 IDirectDrawSurface4_Release(surface1);
7142 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7143 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7145 /* Try a single primary and two offscreen plain surfaces. */
7146 memset(&surface_desc, 0, sizeof(surface_desc));
7147 surface_desc.dwSize = sizeof(surface_desc);
7148 surface_desc.dwFlags = DDSD_CAPS;
7149 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7150 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7151 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7153 memset(&surface_desc, 0, sizeof(surface_desc));
7154 surface_desc.dwSize = sizeof(surface_desc);
7155 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7156 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7157 surface_desc.dwWidth = registry_mode.dmPelsWidth;
7158 surface_desc.dwHeight = registry_mode.dmPelsHeight;
7159 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7160 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7162 memset(&surface_desc, 0, sizeof(surface_desc));
7163 surface_desc.dwSize = sizeof(surface_desc);
7164 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7165 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7166 surface_desc.dwWidth = registry_mode.dmPelsWidth;
7167 surface_desc.dwHeight = registry_mode.dmPelsHeight;
7168 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7169 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7171 /* This one has a different size. */
7172 memset(&surface_desc, 0, sizeof(surface_desc));
7173 surface_desc.dwSize = sizeof(surface_desc);
7174 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7175 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7176 surface_desc.dwWidth = 128;
7177 surface_desc.dwHeight = 128;
7178 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7179 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7181 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface2);
7182 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7183 /* Try the reverse without detaching first. */
7184 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface1);
7185 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
7186 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
7187 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7189 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface1);
7190 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7191 /* Try to detach reversed. */
7192 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
7193 ok(hr == DDERR_CANNOTDETACHSURFACE, "Got unexpected hr %#x.\n", hr);
7194 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface2, 0, surface1);
7195 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7197 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface3);
7198 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7199 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface2, 0, surface3);
7200 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7202 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface4);
7203 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7204 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface1);
7205 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7207 IDirectDrawSurface4_Release(surface4);
7208 IDirectDrawSurface4_Release(surface3);
7209 IDirectDrawSurface4_Release(surface2);
7210 IDirectDrawSurface4_Release(surface1);
7212 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
7213 memset(&surface_desc, 0, sizeof(surface_desc));
7214 surface_desc.dwSize = sizeof(surface_desc);
7215 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7216 surface_desc.dwWidth = 64;
7217 surface_desc.dwHeight = 64;
7218 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
7219 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7220 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
7221 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
7222 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
7223 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
7224 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
7225 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7226 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7227 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7228 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7230 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
7231 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
7232 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
7233 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
7234 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7235 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7237 hr = IDirectDrawSurface4_QueryInterface(surface1, &IID_IDirectDrawSurface, (void **)&surface1v1);
7238 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
7239 hr = IDirectDrawSurface4_QueryInterface(surface2, &IID_IDirectDrawSurface, (void **)&surface2v1);
7240 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
7242 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface2);
7243 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7244 refcount = get_refcount((IUnknown *)surface2);
7245 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7246 refcount = get_refcount((IUnknown *)surface2v1);
7247 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7248 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface2);
7249 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
7250 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7251 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7252 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
7253 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
7255 /* Attaching while already attached to other surface. */
7256 hr = IDirectDrawSurface4_AddAttachedSurface(surface3, surface2);
7257 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7258 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface3, 0, surface2);
7259 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7260 IDirectDrawSurface4_Release(surface3);
7262 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
7263 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7264 refcount = get_refcount((IUnknown *)surface2);
7265 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7266 refcount = get_refcount((IUnknown *)surface2v1);
7267 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7269 /* DeleteAttachedSurface() when attaching via IDirectDrawSurface. */
7270 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7271 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7272 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
7273 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
7274 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
7275 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7276 refcount = IDirectDrawSurface4_Release(surface2);
7277 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7278 refcount = IDirectDrawSurface4_Release(surface1);
7279 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7281 /* Automatic detachment on release. */
7282 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7283 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7284 refcount = get_refcount((IUnknown *)surface2v1);
7285 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7286 refcount = IDirectDrawSurface_Release(surface1v1);
7287 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7288 refcount = IDirectDrawSurface_Release(surface2v1);
7289 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7290 refcount = IDirectDraw4_Release(ddraw);
7291 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7292 DestroyWindow(window);
7295 static void test_private_data(void)
7297 IDirectDraw4 *ddraw;
7298 IDirectDrawSurface4 *surface, *surface2;
7299 DDSURFACEDESC2 surface_desc;
7300 ULONG refcount, refcount2, refcount3;
7301 IUnknown *ptr;
7302 DWORD size = sizeof(ptr);
7303 HRESULT hr;
7304 HWND window;
7305 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7306 DWORD data[] = {1, 2, 3, 4};
7307 DDCAPS hal_caps;
7308 static const GUID ddraw_private_data_test_guid =
7310 0xfdb37466,
7311 0x428f,
7312 0x4edf,
7313 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
7315 static const GUID ddraw_private_data_test_guid2 =
7317 0x2e5afac2,
7318 0x87b5,
7319 0x4c10,
7320 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
7323 window = create_window();
7324 ddraw = create_ddraw();
7325 ok(!!ddraw, "Failed to create a ddraw object.\n");
7326 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7327 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7329 reset_ddsd(&surface_desc);
7330 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
7331 surface_desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
7332 surface_desc.dwHeight = 4;
7333 surface_desc.dwWidth = 4;
7334 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7335 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7337 /* NULL pointers are not valid, but don't cause a crash. */
7338 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL,
7339 sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
7340 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7341 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 0, 0);
7342 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7343 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 1, 0);
7344 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7346 /* DDSPD_IUNKNOWNPOINTER needs sizeof(IUnknown *) bytes of data. */
7347 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7348 0, DDSPD_IUNKNOWNPOINTER);
7349 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7350 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7351 5, DDSPD_IUNKNOWNPOINTER);
7352 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7353 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7354 sizeof(ddraw) * 2, DDSPD_IUNKNOWNPOINTER);
7355 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7357 /* Note that with a size != 0 and size != sizeof(IUnknown *) and
7358 * DDSPD_IUNKNOWNPOINTER set SetPrivateData in ddraw4 and ddraw7
7359 * erases the old content and returns an error. This behavior has
7360 * been fixed in d3d8 and d3d9. Unless an application is found
7361 * that depends on this we don't care about this behavior. */
7362 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7363 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7364 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7365 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7366 0, DDSPD_IUNKNOWNPOINTER);
7367 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7368 size = sizeof(ptr);
7369 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7370 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7371 hr = IDirectDrawSurface4_FreePrivateData(surface, &ddraw_private_data_test_guid);
7372 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7374 refcount = get_refcount((IUnknown *)ddraw);
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 refcount2 = get_refcount((IUnknown *)ddraw);
7379 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
7381 hr = IDirectDrawSurface4_FreePrivateData(surface, &ddraw_private_data_test_guid);
7382 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7383 refcount2 = get_refcount((IUnknown *)ddraw);
7384 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
7386 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7387 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7388 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7389 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, surface,
7390 sizeof(surface), DDSPD_IUNKNOWNPOINTER);
7391 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7392 refcount2 = get_refcount((IUnknown *)ddraw);
7393 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
7395 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7396 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7397 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7398 size = 2 * sizeof(ptr);
7399 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7400 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7401 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7402 refcount2 = get_refcount(ptr);
7403 /* Object is NOT addref'ed by the getter. */
7404 ok(ptr == (IUnknown *)ddraw, "Returned interface pointer is %p, expected %p.\n", ptr, ddraw);
7405 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
7407 ptr = (IUnknown *)0xdeadbeef;
7408 size = 1;
7409 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
7410 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7411 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7412 size = 2 * sizeof(ptr);
7413 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
7414 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7415 ok(size == 2 * sizeof(ptr), "Got unexpected size %u.\n", size);
7416 size = 1;
7417 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7418 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7419 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7420 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7421 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid2, NULL, NULL);
7422 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7423 size = 0xdeadbabe;
7424 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid2, &ptr, &size);
7425 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7426 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7427 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
7428 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, NULL);
7429 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7431 refcount3 = IDirectDrawSurface4_Release(surface);
7432 ok(!refcount3, "Got unexpected refcount %u.\n", refcount3);
7434 /* Destroying the surface frees the reference held on the private data. It also frees
7435 * the reference the surface is holding on its creating object. */
7436 refcount2 = get_refcount((IUnknown *)ddraw);
7437 ok(refcount2 == refcount - 1, "Got unexpected refcount %u.\n", refcount2);
7439 memset(&hal_caps, 0, sizeof(hal_caps));
7440 hal_caps.dwSize = sizeof(hal_caps);
7441 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
7442 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7443 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) == (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
7445 reset_ddsd(&surface_desc);
7446 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT;
7447 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7448 surface_desc.dwHeight = 4;
7449 surface_desc.dwWidth = 4;
7450 U2(surface_desc).dwMipMapCount = 2;
7451 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7452 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7453 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &surface2);
7454 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7456 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, data, sizeof(data), 0);
7457 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7458 hr = IDirectDrawSurface4_GetPrivateData(surface2, &ddraw_private_data_test_guid, NULL, NULL);
7459 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7461 IDirectDrawSurface4_Release(surface2);
7462 IDirectDrawSurface4_Release(surface);
7464 else
7465 skip("Mipmapped textures not supported, skipping mipmap private data test.\n");
7467 refcount = IDirectDraw4_Release(ddraw);
7468 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7469 DestroyWindow(window);
7472 static void test_pixel_format(void)
7474 HWND window, window2 = NULL;
7475 HDC hdc, hdc2 = NULL;
7476 HMODULE gl = NULL;
7477 int format, test_format;
7478 PIXELFORMATDESCRIPTOR pfd;
7479 IDirectDraw4 *ddraw = NULL;
7480 IDirectDrawClipper *clipper = NULL;
7481 DDSURFACEDESC2 ddsd;
7482 IDirectDrawSurface4 *primary = NULL;
7483 DDBLTFX fx;
7484 HRESULT hr;
7486 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7487 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7488 if (!window)
7490 skip("Failed to create window\n");
7491 return;
7494 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7495 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7497 hdc = GetDC(window);
7498 if (!hdc)
7500 skip("Failed to get DC\n");
7501 goto cleanup;
7504 if (window2)
7505 hdc2 = GetDC(window2);
7507 gl = LoadLibraryA("opengl32.dll");
7508 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
7510 format = GetPixelFormat(hdc);
7511 ok(format == 0, "new window has pixel format %d\n", format);
7513 ZeroMemory(&pfd, sizeof(pfd));
7514 pfd.nSize = sizeof(pfd);
7515 pfd.nVersion = 1;
7516 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
7517 pfd.iPixelType = PFD_TYPE_RGBA;
7518 pfd.iLayerType = PFD_MAIN_PLANE;
7519 format = ChoosePixelFormat(hdc, &pfd);
7520 if (format <= 0)
7522 skip("no pixel format available\n");
7523 goto cleanup;
7526 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
7528 skip("failed to set pixel format\n");
7529 goto cleanup;
7532 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
7534 skip("failed to set pixel format on second window\n");
7535 if (hdc2)
7537 ReleaseDC(window2, hdc2);
7538 hdc2 = NULL;
7542 ddraw = create_ddraw();
7543 ok(!!ddraw, "Failed to create a ddraw object.\n");
7545 test_format = GetPixelFormat(hdc);
7546 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7548 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7549 if (FAILED(hr))
7551 skip("Failed to set cooperative level, hr %#x.\n", hr);
7552 goto cleanup;
7555 test_format = GetPixelFormat(hdc);
7556 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7558 if (hdc2)
7560 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL);
7561 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
7562 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
7563 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
7565 test_format = GetPixelFormat(hdc);
7566 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7568 test_format = GetPixelFormat(hdc2);
7569 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7572 memset(&ddsd, 0, sizeof(ddsd));
7573 ddsd.dwSize = sizeof(ddsd);
7574 ddsd.dwFlags = DDSD_CAPS;
7575 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7577 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
7578 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
7580 test_format = GetPixelFormat(hdc);
7581 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7583 if (hdc2)
7585 test_format = GetPixelFormat(hdc2);
7586 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7589 if (clipper)
7591 hr = IDirectDrawSurface4_SetClipper(primary, clipper);
7592 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
7594 test_format = GetPixelFormat(hdc);
7595 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7597 test_format = GetPixelFormat(hdc2);
7598 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7601 memset(&fx, 0, sizeof(fx));
7602 fx.dwSize = sizeof(fx);
7603 hr = IDirectDrawSurface4_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7604 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
7606 test_format = GetPixelFormat(hdc);
7607 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7609 if (hdc2)
7611 test_format = GetPixelFormat(hdc2);
7612 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7615 cleanup:
7616 if (primary) IDirectDrawSurface4_Release(primary);
7617 if (clipper) IDirectDrawClipper_Release(clipper);
7618 if (ddraw) IDirectDraw4_Release(ddraw);
7619 if (gl) FreeLibrary(gl);
7620 if (hdc) ReleaseDC(window, hdc);
7621 if (hdc2) ReleaseDC(window2, hdc2);
7622 if (window) DestroyWindow(window);
7623 if (window2) DestroyWindow(window2);
7626 static void test_create_surface_pitch(void)
7628 IDirectDrawSurface4 *surface;
7629 DDSURFACEDESC2 surface_desc;
7630 IDirectDraw4 *ddraw;
7631 unsigned int i;
7632 ULONG refcount;
7633 HWND window;
7634 HRESULT hr;
7635 void *mem;
7637 static const struct
7639 DWORD caps;
7640 DWORD flags_in;
7641 DWORD pitch_in;
7642 HRESULT hr;
7643 DWORD flags_out;
7644 DWORD pitch_out32;
7645 DWORD pitch_out64;
7647 test_data[] =
7649 /* 0 */
7650 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7651 0, 0, DD_OK,
7652 DDSD_PITCH, 0x100, 0x100},
7653 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7654 DDSD_PITCH, 0x104, DD_OK,
7655 DDSD_PITCH, 0x100, 0x100},
7656 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7657 DDSD_PITCH, 0x0f8, DD_OK,
7658 DDSD_PITCH, 0x100, 0x100},
7659 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7660 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
7661 0, 0, 0 },
7662 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7663 0, 0, DD_OK,
7664 DDSD_PITCH, 0x100, 0x0fc},
7665 /* 5 */
7666 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7667 DDSD_PITCH, 0x104, DD_OK,
7668 DDSD_PITCH, 0x100, 0x0fc},
7669 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7670 DDSD_PITCH, 0x0f8, DD_OK,
7671 DDSD_PITCH, 0x100, 0x0fc},
7672 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7673 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
7674 DDSD_PITCH, 0x100, 0x0fc},
7675 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7676 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
7677 0, 0, 0 },
7678 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7679 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
7680 DDSD_PITCH, 0x100, 0x100},
7681 /* 10 */
7682 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7683 DDSD_LPSURFACE | DDSD_PITCH, 0x0fe, DDERR_INVALIDPARAMS,
7684 0, 0, 0 },
7685 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7686 DDSD_LPSURFACE | DDSD_PITCH, 0x0fc, DD_OK,
7687 DDSD_PITCH, 0x0fc, 0x0fc},
7688 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7689 DDSD_LPSURFACE | DDSD_PITCH, 0x0f8, DDERR_INVALIDPARAMS,
7690 0, 0, 0 },
7691 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7692 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x100, DDERR_INVALIDPARAMS,
7693 0, 0, 0 },
7694 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7695 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x3f00, DDERR_INVALIDPARAMS,
7696 0, 0, 0 },
7697 /* 15 */
7698 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7699 DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, 0x100, DD_OK,
7700 DDSD_PITCH, 0x100, 0x100},
7701 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
7702 0, 0, DDERR_INVALIDCAPS,
7703 0, 0, 0 },
7704 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7705 0, 0, DD_OK,
7706 DDSD_PITCH, 0x100, 0 },
7707 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7708 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
7709 0, 0, 0 },
7710 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
7711 0, 0, DDERR_INVALIDCAPS,
7712 0, 0, 0 },
7713 /* 20 */
7714 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7715 0, 0, DD_OK,
7716 DDSD_PITCH, 0x100, 0 },
7717 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7718 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
7719 DDSD_PITCH, 0x100, 0 },
7721 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
7723 window = create_window();
7724 ddraw = create_ddraw();
7725 ok(!!ddraw, "Failed to create a ddraw object.\n");
7726 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7727 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7729 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
7731 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
7733 memset(&surface_desc, 0, sizeof(surface_desc));
7734 surface_desc.dwSize = sizeof(surface_desc);
7735 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
7736 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
7737 surface_desc.dwWidth = 63;
7738 surface_desc.dwHeight = 63;
7739 U1(surface_desc).lPitch = test_data[i].pitch_in;
7740 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7741 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
7742 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
7743 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7744 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7745 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7746 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7747 if (test_data[i].flags_in & DDSD_LPSURFACE)
7749 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
7750 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, expected_hr);
7751 surface_desc.lpSurface = mem;
7752 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7754 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
7755 continue;
7756 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
7757 if (FAILED(hr))
7758 continue;
7760 memset(&surface_desc, 0, sizeof(surface_desc));
7761 surface_desc.dwSize = sizeof(surface_desc);
7762 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
7763 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
7764 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
7765 "Test %u: Got unexpected flags %#x, expected %#x.\n",
7766 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
7767 /* The pitch for textures seems to be implementation specific. */
7768 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
7770 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
7771 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
7772 "Test %u: Got unexpected pitch %u, expected %u.\n",
7773 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
7774 else
7775 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
7776 "Test %u: Got unexpected pitch %u, expected %u.\n",
7777 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
7779 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
7781 IDirectDrawSurface4_Release(surface);
7784 HeapFree(GetProcessHeap(), 0, mem);
7785 refcount = IDirectDraw4_Release(ddraw);
7786 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7787 DestroyWindow(window);
7790 static void test_mipmap(void)
7792 IDirectDrawSurface4 *surface, *surface2;
7793 DDSURFACEDESC2 surface_desc;
7794 IDirectDraw4 *ddraw;
7795 unsigned int i;
7796 ULONG refcount;
7797 HWND window;
7798 HRESULT hr;
7799 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7800 DDCAPS hal_caps;
7802 static const struct
7804 DWORD flags;
7805 DWORD caps;
7806 DWORD width;
7807 DWORD height;
7808 DWORD mipmap_count_in;
7809 HRESULT hr;
7810 DWORD mipmap_count_out;
7812 tests[] =
7814 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
7815 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS, 0},
7816 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
7817 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS, 0},
7818 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 6},
7819 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 6},
7822 window = create_window();
7823 ddraw = create_ddraw();
7824 ok(!!ddraw, "Failed to create a ddraw object.\n");
7825 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7826 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7828 memset(&hal_caps, 0, sizeof(hal_caps));
7829 hal_caps.dwSize = sizeof(hal_caps);
7830 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
7831 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7832 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
7834 skip("Mipmapped textures not supported, skipping tests.\n");
7835 IDirectDraw4_Release(ddraw);
7836 DestroyWindow(window);
7837 return;
7840 for (i = 0; i < ARRAY_SIZE(tests); ++i)
7842 memset(&surface_desc, 0, sizeof(surface_desc));
7843 surface_desc.dwSize = sizeof(surface_desc);
7844 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
7845 surface_desc.ddsCaps.dwCaps = tests[i].caps;
7846 surface_desc.dwWidth = tests[i].width;
7847 surface_desc.dwHeight = tests[i].height;
7848 if (tests[i].flags & DDSD_MIPMAPCOUNT)
7849 U2(surface_desc).dwMipMapCount = tests[i].mipmap_count_in;
7850 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7851 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
7852 if (FAILED(hr))
7853 continue;
7855 memset(&surface_desc, 0, sizeof(surface_desc));
7856 surface_desc.dwSize = sizeof(surface_desc);
7857 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
7858 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
7859 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
7860 "Test %u: Got unexpected flags %#x.\n", i, surface_desc.dwFlags);
7861 ok(U2(surface_desc).dwMipMapCount == tests[i].mipmap_count_out,
7862 "Test %u: Got unexpected mipmap count %u.\n", i, U2(surface_desc).dwMipMapCount);
7864 if (U2(surface_desc).dwMipMapCount > 1)
7866 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &surface2);
7867 ok(SUCCEEDED(hr), "Test %u: Failed to get attached surface, hr %#x.\n", i, hr);
7869 memset(&surface_desc, 0, sizeof(surface_desc));
7870 surface_desc.dwSize = sizeof(surface_desc);
7871 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, 0, NULL);
7872 ok(SUCCEEDED(hr), "Test %u: Failed to lock surface, hr %#x.\n", i, hr);
7873 memset(&surface_desc, 0, sizeof(surface_desc));
7874 surface_desc.dwSize = sizeof(surface_desc);
7875 hr = IDirectDrawSurface4_Lock(surface2, NULL, &surface_desc, 0, NULL);
7876 ok(SUCCEEDED(hr), "Test %u: Failed to lock surface, hr %#x.\n", i, hr);
7877 IDirectDrawSurface4_Unlock(surface2, NULL);
7878 IDirectDrawSurface4_Unlock(surface, NULL);
7880 IDirectDrawSurface4_Release(surface2);
7883 IDirectDrawSurface4_Release(surface);
7886 refcount = IDirectDraw4_Release(ddraw);
7887 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7888 DestroyWindow(window);
7891 static void test_palette_complex(void)
7893 IDirectDrawSurface4 *surface, *mipmap, *tmp;
7894 DDSURFACEDESC2 surface_desc;
7895 IDirectDraw4 *ddraw;
7896 IDirectDrawPalette *palette, *palette2, *palette_mipmap;
7897 ULONG refcount;
7898 HWND window;
7899 HRESULT hr;
7900 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7901 DDCAPS hal_caps;
7902 PALETTEENTRY palette_entries[256];
7903 unsigned int i;
7904 HDC dc;
7905 RGBQUAD rgbquad;
7906 UINT count;
7908 window = create_window();
7909 ddraw = create_ddraw();
7910 ok(!!ddraw, "Failed to create a ddraw object.\n");
7911 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7912 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7914 memset(&hal_caps, 0, sizeof(hal_caps));
7915 hal_caps.dwSize = sizeof(hal_caps);
7916 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
7917 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7918 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
7920 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
7921 IDirectDraw4_Release(ddraw);
7922 DestroyWindow(window);
7923 return;
7926 memset(&surface_desc, 0, sizeof(surface_desc));
7927 surface_desc.dwSize = sizeof(surface_desc);
7928 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7929 surface_desc.dwWidth = 128;
7930 surface_desc.dwHeight = 128;
7931 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7932 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7933 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7934 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
7935 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7936 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7938 memset(palette_entries, 0, sizeof(palette_entries));
7939 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7940 palette_entries, &palette, NULL);
7941 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7943 memset(palette_entries, 0, sizeof(palette_entries));
7944 palette_entries[1].peRed = 0xff;
7945 palette_entries[1].peGreen = 0x80;
7946 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7947 palette_entries, &palette_mipmap, NULL);
7948 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7950 palette2 = (void *)0xdeadbeef;
7951 hr = IDirectDrawSurface4_GetPalette(surface, &palette2);
7952 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
7953 ok(!palette2, "Got unexpected palette %p.\n", palette2);
7954 hr = IDirectDrawSurface4_SetPalette(surface, palette);
7955 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7956 hr = IDirectDrawSurface4_GetPalette(surface, &palette2);
7957 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
7958 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
7959 IDirectDrawPalette_Release(palette2);
7961 mipmap = surface;
7962 IDirectDrawSurface4_AddRef(mipmap);
7963 for (i = 0; i < 7; ++i)
7965 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
7966 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
7967 palette2 = (void *)0xdeadbeef;
7968 hr = IDirectDrawSurface4_GetPalette(tmp, &palette2);
7969 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
7970 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
7972 hr = IDirectDrawSurface4_SetPalette(tmp, palette_mipmap);
7973 ok(SUCCEEDED(hr), "Failed to set palette, i %u, hr %#x.\n", i, hr);
7975 hr = IDirectDrawSurface4_GetPalette(tmp, &palette2);
7976 ok(SUCCEEDED(hr), "Failed to get palette, i %u, hr %#x.\n", i, hr);
7977 ok(palette_mipmap == palette2, "Got unexpected palette %p.\n", palette2);
7978 IDirectDrawPalette_Release(palette2);
7980 hr = IDirectDrawSurface4_GetDC(tmp, &dc);
7981 ok(SUCCEEDED(hr), "Failed to get DC, i %u, hr %#x.\n", i, hr);
7982 count = GetDIBColorTable(dc, 1, 1, &rgbquad);
7983 ok(count == 1, "Expected count 1, got %u.\n", count);
7984 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x.\n", rgbquad.rgbRed);
7985 ok(rgbquad.rgbGreen == 0x80, "Expected rgbGreen = 0x80, got %#x.\n", rgbquad.rgbGreen);
7986 ok(rgbquad.rgbBlue == 0x0, "Expected rgbBlue = 0x0, got %#x.\n", rgbquad.rgbBlue);
7987 hr = IDirectDrawSurface4_ReleaseDC(tmp, dc);
7988 ok(SUCCEEDED(hr), "Failed to release DC, i %u, hr %#x.\n", i, hr);
7990 IDirectDrawSurface4_Release(mipmap);
7991 mipmap = tmp;
7994 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
7995 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7996 IDirectDrawSurface4_Release(mipmap);
7997 refcount = IDirectDrawSurface4_Release(surface);
7998 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7999 refcount = IDirectDrawPalette_Release(palette_mipmap);
8000 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8001 refcount = IDirectDrawPalette_Release(palette);
8002 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8004 refcount = IDirectDraw4_Release(ddraw);
8005 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8006 DestroyWindow(window);
8009 static void test_p8_blit(void)
8011 IDirectDrawSurface4 *src, *dst, *dst_p8;
8012 DDSURFACEDESC2 surface_desc;
8013 IDirectDraw4 *ddraw;
8014 IDirectDrawPalette *palette, *palette2;
8015 ULONG refcount;
8016 HWND window;
8017 HRESULT hr;
8018 PALETTEENTRY palette_entries[256];
8019 unsigned int x;
8020 DDBLTFX fx;
8021 BOOL is_warp;
8022 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
8023 static const BYTE src_data2[] = {0x10, 0x5, 0x4, 0x3, 0x2, 0x1, 0xff, 0x80};
8024 static const BYTE expected_p8[] = {0x10, 0x1, 0x4, 0x3, 0x4, 0x5, 0xff, 0x80};
8025 static const D3DCOLOR expected[] =
8027 0x00101010, 0x00010101, 0x00020202, 0x00030303,
8028 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
8030 D3DCOLOR color;
8032 window = create_window();
8033 ddraw = create_ddraw();
8034 ok(!!ddraw, "Failed to create a ddraw object.\n");
8035 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8036 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8037 is_warp = ddraw_is_warp(ddraw);
8039 memset(palette_entries, 0, sizeof(palette_entries));
8040 palette_entries[1].peGreen = 0xff;
8041 palette_entries[2].peBlue = 0xff;
8042 palette_entries[3].peFlags = 0xff;
8043 palette_entries[4].peRed = 0xff;
8044 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8045 palette_entries, &palette, NULL);
8046 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8047 palette_entries[1].peBlue = 0xff;
8048 palette_entries[2].peGreen = 0xff;
8049 palette_entries[3].peRed = 0xff;
8050 palette_entries[4].peFlags = 0x0;
8051 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8052 palette_entries, &palette2, NULL);
8053 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8055 memset(&surface_desc, 0, sizeof(surface_desc));
8056 surface_desc.dwSize = sizeof(surface_desc);
8057 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8058 surface_desc.dwWidth = 8;
8059 surface_desc.dwHeight = 1;
8060 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8061 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8062 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8063 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
8064 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL);
8065 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8066 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_p8, NULL);
8067 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8068 hr = IDirectDrawSurface4_SetPalette(dst_p8, palette2);
8069 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8071 memset(&surface_desc, 0, sizeof(surface_desc));
8072 surface_desc.dwSize = sizeof(surface_desc);
8073 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8074 surface_desc.dwWidth = 8;
8075 surface_desc.dwHeight = 1;
8076 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8077 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8078 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
8079 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8080 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8081 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8082 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8083 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
8084 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL);
8085 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8087 memset(&surface_desc, 0, sizeof(surface_desc));
8088 surface_desc.dwSize = sizeof(surface_desc);
8089 hr = IDirectDrawSurface4_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
8090 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
8091 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
8092 hr = IDirectDrawSurface4_Unlock(src, NULL);
8093 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
8095 hr = IDirectDrawSurface4_Lock(dst_p8, NULL, &surface_desc, DDLOCK_WAIT, NULL);
8096 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
8097 memcpy(surface_desc.lpSurface, src_data2, sizeof(src_data2));
8098 hr = IDirectDrawSurface4_Unlock(dst_p8, NULL);
8099 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
8101 hr = IDirectDrawSurface4_SetPalette(src, palette);
8102 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8103 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
8104 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
8105 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
8106 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
8107 "Failed to blit, hr %#x.\n", hr);
8109 if (SUCCEEDED(hr))
8111 for (x = 0; x < ARRAY_SIZE(expected); x++)
8113 color = get_surface_color(dst, x, 0);
8114 todo_wine ok(compare_color(color, expected[x], 0),
8115 "Pixel %u: Got color %#x, expected %#x.\n",
8116 x, color, expected[x]);
8120 memset(&fx, 0, sizeof(fx));
8121 fx.dwSize = sizeof(fx);
8122 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x2;
8123 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x2;
8124 hr = IDirectDrawSurface4_Blt(dst_p8, NULL, src, NULL, DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &fx);
8125 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
8127 hr = IDirectDrawSurface4_Lock(dst_p8, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
8128 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
8129 /* A color keyed P8 blit doesn't do anything on WARP - it just leaves the data in the destination
8130 * surface untouched. P8 blits without color keys work. Error checking (DDBLT_KEYSRC without a key
8131 * for example) also works as expected.
8133 * Using DDBLT_KEYSRC instead of DDBLT_KEYSRCOVERRIDE doesn't change this. Doing this blit with
8134 * the display mode set to P8 doesn't help either. */
8135 ok(!memcmp(surface_desc.lpSurface, expected_p8, sizeof(expected_p8))
8136 || broken(is_warp && !memcmp(surface_desc.lpSurface, src_data2, sizeof(src_data2))),
8137 "Got unexpected P8 color key blit result.\n");
8138 hr = IDirectDrawSurface4_Unlock(dst_p8, NULL);
8139 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
8141 IDirectDrawSurface4_Release(src);
8142 IDirectDrawSurface4_Release(dst);
8143 IDirectDrawSurface4_Release(dst_p8);
8144 IDirectDrawPalette_Release(palette);
8145 IDirectDrawPalette_Release(palette2);
8147 refcount = IDirectDraw4_Release(ddraw);
8148 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8149 DestroyWindow(window);
8152 static void test_material(void)
8154 D3DMATERIALHANDLE mat_handle, tmp;
8155 IDirect3DMaterial3 *material;
8156 IDirect3DViewport3 *viewport;
8157 IDirect3DDevice3 *device;
8158 IDirectDrawSurface4 *rt;
8159 D3DCOLOR color;
8160 ULONG refcount;
8161 unsigned int i;
8162 HWND window;
8163 HRESULT hr;
8164 BOOL valid;
8166 static struct
8168 struct vec3 position;
8169 struct vec3 normal;
8170 D3DCOLOR diffuse;
8172 quad1[] =
8174 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
8175 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
8176 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
8177 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
8179 quad2[] =
8181 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
8182 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
8183 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
8184 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
8186 static const struct
8188 void *data;
8189 BOOL material;
8190 D3DCOLOR expected_color;
8192 test_data[] =
8194 {quad1, TRUE, 0x0000ff00},
8195 {quad2, TRUE, 0x0000ff00},
8196 {quad1, FALSE, 0x00ffffff},
8197 {quad2, FALSE, 0x00ff0000},
8199 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
8201 window = create_window();
8202 if (!(device = create_device(window, DDSCL_NORMAL)))
8204 skip("Failed to create a 3D device, skipping test.\n");
8205 DestroyWindow(window);
8206 return;
8209 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
8210 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8212 viewport = create_viewport(device, 0, 0, 640, 480);
8213 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
8214 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
8216 material = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
8217 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
8218 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
8220 hr = IDirect3DDevice3_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
8221 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
8222 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
8223 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
8224 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
8225 hr = IDirect3DDevice3_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
8226 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
8227 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
8228 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, 0);
8229 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
8230 hr = IDirect3DDevice3_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
8231 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
8232 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
8234 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
8236 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect,
8237 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
8238 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8240 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, test_data[i].material ? mat_handle : 0);
8241 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
8243 hr = IDirect3DDevice3_BeginScene(device);
8244 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8245 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
8246 D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE, test_data[i].data, 4, 0);
8247 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8248 hr = IDirect3DDevice3_EndScene(device);
8249 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8250 color = get_surface_color(rt, 320, 240);
8251 ok(compare_color(color, test_data[i].expected_color, 1),
8252 "Got unexpected color 0x%08x, test %u.\n", color, i);
8255 destroy_material(material);
8256 material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
8257 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
8258 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
8260 hr = IDirect3DViewport3_SetBackground(viewport, mat_handle);
8261 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
8262 hr = IDirect3DViewport3_GetBackground(viewport, &tmp, &valid);
8263 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
8264 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
8265 ok(valid, "Got unexpected valid %#x.\n", valid);
8266 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8267 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8268 color = get_surface_color(rt, 320, 240);
8269 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
8271 hr = IDirect3DViewport3_SetBackground(viewport, 0);
8272 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8273 hr = IDirect3DViewport3_GetBackground(viewport, &tmp, &valid);
8274 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
8275 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
8276 ok(valid, "Got unexpected valid %#x.\n", valid);
8277 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8278 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8279 color = get_surface_color(rt, 320, 240);
8280 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
8282 destroy_viewport(device, viewport);
8283 viewport = create_viewport(device, 0, 0, 640, 480);
8285 hr = IDirect3DViewport3_GetBackground(viewport, &tmp, &valid);
8286 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
8287 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
8288 ok(!valid, "Got unexpected valid %#x.\n", valid);
8289 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8290 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8291 color = get_surface_color(rt, 320, 240);
8292 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x.\n", color);
8294 destroy_viewport(device, viewport);
8295 destroy_material(material);
8296 IDirectDrawSurface4_Release(rt);
8297 refcount = IDirect3DDevice3_Release(device);
8298 ok(!refcount, "Device has %u references left.\n", refcount);
8299 DestroyWindow(window);
8302 static void test_palette_gdi(void)
8304 IDirectDrawSurface4 *surface, *primary;
8305 DDSURFACEDESC2 surface_desc;
8306 IDirectDraw4 *ddraw;
8307 IDirectDrawPalette *palette, *palette2;
8308 ULONG refcount;
8309 HWND window;
8310 HRESULT hr;
8311 PALETTEENTRY palette_entries[256];
8312 UINT i;
8313 HDC dc;
8314 DDBLTFX fx;
8315 RECT r;
8316 COLORREF color;
8317 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
8318 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
8319 * not the point of this test. */
8320 static const RGBQUAD expected1[] =
8322 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8323 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
8325 static const RGBQUAD expected2[] =
8327 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8328 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
8330 static const RGBQUAD expected3[] =
8332 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
8333 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
8335 HPALETTE ddraw_palette_handle;
8336 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
8337 RGBQUAD rgbquad[255];
8338 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
8340 window = create_window();
8341 ddraw = create_ddraw();
8342 ok(!!ddraw, "Failed to create a ddraw object.\n");
8343 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8344 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8346 memset(&surface_desc, 0, sizeof(surface_desc));
8347 surface_desc.dwSize = sizeof(surface_desc);
8348 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8349 surface_desc.dwWidth = 16;
8350 surface_desc.dwHeight = 16;
8351 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8352 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8353 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8354 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
8355 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8356 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8358 /* Avoid colors from the Windows default palette. */
8359 memset(palette_entries, 0, sizeof(palette_entries));
8360 palette_entries[1].peRed = 0x01;
8361 palette_entries[2].peGreen = 0x02;
8362 palette_entries[3].peBlue = 0x03;
8363 palette_entries[4].peRed = 0x13;
8364 palette_entries[4].peGreen = 0x14;
8365 palette_entries[4].peBlue = 0x15;
8366 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8367 palette_entries, &palette, NULL);
8368 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8370 /* If there is no palette assigned and the display mode is not 8 bpp, some
8371 * drivers refuse to create a DC while others allow it. If a DC is created,
8372 * the DIB color table is uninitialized and contains random colors. No error
8373 * is generated when trying to read pixels and random garbage is returned.
8375 * The most likely explanation is that if the driver creates a DC, it (or
8376 * the higher-level runtime) uses GetSystemPaletteEntries to find the
8377 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
8378 * contains uninitialized garbage. See comments below for the P8 case. */
8380 hr = IDirectDrawSurface4_SetPalette(surface, palette);
8381 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8382 hr = IDirectDrawSurface4_GetDC(surface, &dc);
8383 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8384 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8385 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8386 "Got unexpected palette %p, expected %p.\n",
8387 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8389 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8390 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8391 for (i = 0; i < ARRAY_SIZE(expected1); i++)
8393 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
8394 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8395 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8396 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
8398 for (; i < ARRAY_SIZE(rgbquad); i++)
8400 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8401 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8402 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8405 /* Update the palette while the DC is in use. This does not modify the DC. */
8406 palette_entries[4].peRed = 0x23;
8407 palette_entries[4].peGreen = 0x24;
8408 palette_entries[4].peBlue = 0x25;
8409 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
8410 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8412 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8413 ok(i == 1, "Expected count 1, got %u.\n", i);
8414 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8415 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8416 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8417 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8419 /* Neither does re-setting the palette. */
8420 hr = IDirectDrawSurface4_SetPalette(surface, NULL);
8421 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8422 hr = IDirectDrawSurface4_SetPalette(surface, palette);
8423 ok(SUCCEEDED(hr), "Failed to set palette, 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 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
8433 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8435 /* Refresh the DC. This updates the palette. */
8436 hr = IDirectDrawSurface4_GetDC(surface, &dc);
8437 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8438 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8439 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8440 for (i = 0; i < ARRAY_SIZE(expected2); i++)
8442 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8443 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8444 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8445 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8447 for (; i < ARRAY_SIZE(rgbquad); i++)
8449 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8450 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8451 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8453 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
8454 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8456 refcount = IDirectDrawSurface4_Release(surface);
8457 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8459 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
8460 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8461 if (FAILED(IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8463 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8464 IDirectDrawPalette_Release(palette);
8465 IDirectDraw4_Release(ddraw);
8466 DestroyWindow(window);
8467 return;
8469 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
8471 memset(&surface_desc, 0, sizeof(surface_desc));
8472 surface_desc.dwSize = sizeof(surface_desc);
8473 surface_desc.dwFlags = DDSD_CAPS;
8474 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8475 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
8476 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8478 memset(&fx, 0, sizeof(fx));
8479 fx.dwSize = sizeof(fx);
8480 U5(fx).dwFillColor = 3;
8481 SetRect(&r, 0, 0, 319, 479);
8482 hr = IDirectDrawSurface4_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8483 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
8484 SetRect(&r, 320, 0, 639, 479);
8485 U5(fx).dwFillColor = 4;
8486 hr = IDirectDrawSurface4_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8487 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
8489 hr = IDirectDrawSurface4_SetPalette(primary, palette);
8490 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8491 hr = IDirectDrawSurface4_GetDC(primary, &dc);
8492 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8494 color = GetPixel(dc, 160, 240);
8495 ok(color == 0x00030000, "Clear index 3: Got unexpected color 0x%08x.\n", color);
8496 color = GetPixel(dc, 480, 240);
8497 ok(color == 0x00252423, "Clear index 4: Got unexpected color 0x%08x.\n", color);
8499 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8500 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8501 "Got unexpected palette %p, expected %p.\n",
8502 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8503 SelectPalette(dc, ddraw_palette_handle, FALSE);
8505 /* The primary uses the system palette. In exclusive mode, the system palette matches
8506 * the ddraw palette attached to the primary, so the result is what you would expect
8507 * from a regular surface. Tests for the interaction between the ddraw palette and
8508 * the system palette are not included pending an application that depends on this.
8509 * The relation between those causes problems on Windows Vista and newer for games
8510 * like Age of Empires or StarCraft. Don't emulate it without a real need. */
8511 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8512 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8513 for (i = 0; i < ARRAY_SIZE(expected2); i++)
8515 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8516 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8517 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8518 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8520 for (; i < ARRAY_SIZE(rgbquad); i++)
8522 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8523 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8524 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8526 hr = IDirectDrawSurface4_ReleaseDC(primary, dc);
8527 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8529 memset(&surface_desc, 0, sizeof(surface_desc));
8530 surface_desc.dwSize = sizeof(surface_desc);
8531 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8532 surface_desc.dwWidth = 16;
8533 surface_desc.dwHeight = 16;
8534 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8535 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8536 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8538 /* Here the offscreen surface appears to use the primary's palette,
8539 * but in all likelihood it is actually the system palette. */
8540 hr = IDirectDrawSurface4_GetDC(surface, &dc);
8541 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8542 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8543 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8544 for (i = 0; i < ARRAY_SIZE(expected2); i++)
8546 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8547 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8548 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8549 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8551 for (; i < ARRAY_SIZE(rgbquad); i++)
8553 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8554 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8555 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8557 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
8558 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8560 /* On real hardware a change to the primary surface's palette applies immediately,
8561 * even on device contexts from offscreen surfaces that do not have their own
8562 * palette. On the testbot VMs this is not the case. Don't test this until we
8563 * know of an application that depends on this. */
8565 memset(palette_entries, 0, sizeof(palette_entries));
8566 palette_entries[1].peBlue = 0x40;
8567 palette_entries[2].peRed = 0x40;
8568 palette_entries[3].peGreen = 0x40;
8569 palette_entries[4].peRed = 0x12;
8570 palette_entries[4].peGreen = 0x34;
8571 palette_entries[4].peBlue = 0x56;
8572 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8573 palette_entries, &palette2, NULL);
8574 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8575 hr = IDirectDrawSurface4_SetPalette(surface, palette2);
8576 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8578 /* A palette assigned to the offscreen surface overrides the primary / system
8579 * palette. */
8580 hr = IDirectDrawSurface4_GetDC(surface, &dc);
8581 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8582 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8583 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8584 for (i = 0; i < ARRAY_SIZE(expected3); i++)
8586 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
8587 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8588 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8589 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
8591 for (; i < ARRAY_SIZE(rgbquad); i++)
8593 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8594 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8595 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8597 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
8598 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8600 refcount = IDirectDrawSurface4_Release(surface);
8601 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8603 /* The Windows 8 testbot keeps extra references to the primary and
8604 * backbuffer while in 8 bpp mode. */
8605 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
8606 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
8608 refcount = IDirectDrawSurface4_Release(primary);
8609 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8610 refcount = IDirectDrawPalette_Release(palette2);
8611 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8612 refcount = IDirectDrawPalette_Release(palette);
8613 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8614 refcount = IDirectDraw4_Release(ddraw);
8615 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8616 DestroyWindow(window);
8619 static void test_palette_alpha(void)
8621 IDirectDrawSurface4 *surface;
8622 DDSURFACEDESC2 surface_desc;
8623 IDirectDraw4 *ddraw;
8624 IDirectDrawPalette *palette;
8625 ULONG refcount;
8626 HWND window;
8627 HRESULT hr;
8628 PALETTEENTRY palette_entries[256];
8629 unsigned int i;
8630 static const struct
8632 DWORD caps, flags;
8633 BOOL attach_allowed;
8634 const char *name;
8636 test_data[] =
8638 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
8639 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
8640 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
8643 window = create_window();
8644 ddraw = create_ddraw();
8645 ok(!!ddraw, "Failed to create a ddraw object.\n");
8646 if (FAILED(IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8648 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8649 IDirectDraw4_Release(ddraw);
8650 DestroyWindow(window);
8651 return;
8653 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8654 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8656 memset(palette_entries, 0, sizeof(palette_entries));
8657 palette_entries[1].peFlags = 0x42;
8658 palette_entries[2].peFlags = 0xff;
8659 palette_entries[3].peFlags = 0x80;
8660 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
8661 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8663 memset(palette_entries, 0x66, sizeof(palette_entries));
8664 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
8665 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
8666 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8667 palette_entries[0].peFlags);
8668 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8669 palette_entries[1].peFlags);
8670 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
8671 palette_entries[2].peFlags);
8672 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
8673 palette_entries[3].peFlags);
8675 IDirectDrawPalette_Release(palette);
8677 memset(palette_entries, 0, sizeof(palette_entries));
8678 palette_entries[1].peFlags = 0x42;
8679 palette_entries[1].peRed = 0xff;
8680 palette_entries[2].peFlags = 0xff;
8681 palette_entries[3].peFlags = 0x80;
8682 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
8683 palette_entries, &palette, NULL);
8684 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8686 memset(palette_entries, 0x66, sizeof(palette_entries));
8687 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
8688 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
8689 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8690 palette_entries[0].peFlags);
8691 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8692 palette_entries[1].peFlags);
8693 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
8694 palette_entries[2].peFlags);
8695 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
8696 palette_entries[3].peFlags);
8698 for (i = 0; i < ARRAY_SIZE(test_data); i++)
8700 memset(&surface_desc, 0, sizeof(surface_desc));
8701 surface_desc.dwSize = sizeof(surface_desc);
8702 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
8703 surface_desc.dwWidth = 128;
8704 surface_desc.dwHeight = 128;
8705 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
8706 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8707 ok(SUCCEEDED(hr), "Failed to create %s surface, hr %#x.\n", test_data[i].name, hr);
8709 hr = IDirectDrawSurface4_SetPalette(surface, palette);
8710 if (test_data[i].attach_allowed)
8711 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#x.\n", test_data[i].name, hr);
8712 else
8713 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x, %s surface.\n", hr, test_data[i].name);
8715 if (SUCCEEDED(hr))
8717 HDC dc;
8718 RGBQUAD rgbquad;
8719 UINT retval;
8721 hr = IDirectDrawSurface4_GetDC(surface, &dc);
8722 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
8723 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
8724 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
8725 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
8726 rgbquad.rgbRed, test_data[i].name);
8727 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
8728 rgbquad.rgbGreen, test_data[i].name);
8729 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
8730 rgbquad.rgbBlue, test_data[i].name);
8731 ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
8732 rgbquad.rgbReserved, test_data[i].name);
8733 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
8734 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8736 IDirectDrawSurface4_Release(surface);
8739 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
8740 memset(&surface_desc, 0, sizeof(surface_desc));
8741 surface_desc.dwSize = sizeof(surface_desc);
8742 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8743 surface_desc.dwWidth = 128;
8744 surface_desc.dwHeight = 128;
8745 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8746 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8747 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
8748 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8749 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8750 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8751 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8752 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8753 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8754 hr = IDirectDrawSurface4_SetPalette(surface, palette);
8755 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
8756 IDirectDrawSurface4_Release(surface);
8758 /* The Windows 8 testbot keeps extra references to the primary
8759 * while in 8 bpp mode. */
8760 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
8761 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
8763 refcount = IDirectDrawPalette_Release(palette);
8764 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8765 refcount = IDirectDraw4_Release(ddraw);
8766 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8767 DestroyWindow(window);
8770 static void test_vb_writeonly(void)
8772 IDirect3DDevice3 *device;
8773 IDirect3D3 *d3d;
8774 IDirect3DVertexBuffer *buffer;
8775 HWND window;
8776 HRESULT hr;
8777 D3DVERTEXBUFFERDESC desc;
8778 void *ptr;
8779 static const struct vec4 quad[] =
8781 { 0.0f, 480.0f, 0.0f, 1.0f},
8782 { 0.0f, 0.0f, 0.0f, 1.0f},
8783 {640.0f, 480.0f, 0.0f, 1.0f},
8784 {640.0f, 0.0f, 0.0f, 1.0f},
8787 window = create_window();
8788 if (!(device = create_device(window, DDSCL_NORMAL)))
8790 skip("Failed to create a 3D device, skipping test.\n");
8791 DestroyWindow(window);
8792 return;
8795 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
8796 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
8798 memset(&desc, 0, sizeof(desc));
8799 desc.dwSize = sizeof(desc);
8800 desc.dwCaps = D3DVBCAPS_WRITEONLY;
8801 desc.dwFVF = D3DFVF_XYZRHW;
8802 desc.dwNumVertices = ARRAY_SIZE(quad);
8803 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &buffer, 0, NULL);
8804 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
8806 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, &ptr, NULL);
8807 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8808 memcpy(ptr, quad, sizeof(quad));
8809 hr = IDirect3DVertexBuffer_Unlock(buffer);
8810 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8812 hr = IDirect3DDevice3_BeginScene(device);
8813 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8814 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
8815 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8816 hr = IDirect3DDevice3_EndScene(device);
8817 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8819 hr = IDirect3DVertexBuffer_Lock(buffer, 0, &ptr, NULL);
8820 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8821 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
8822 hr = IDirect3DVertexBuffer_Unlock(buffer);
8823 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8825 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_READONLY, &ptr, NULL);
8826 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8827 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
8828 hr = IDirect3DVertexBuffer_Unlock(buffer);
8829 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8831 IDirect3DVertexBuffer_Release(buffer);
8832 IDirect3D3_Release(d3d);
8833 IDirect3DDevice3_Release(device);
8834 DestroyWindow(window);
8837 static void test_lost_device(void)
8839 IDirectDrawSurface4 *surface;
8840 DDSURFACEDESC2 surface_desc;
8841 HWND window1, window2;
8842 IDirectDraw4 *ddraw;
8843 ULONG refcount;
8844 HRESULT hr;
8845 BOOL ret;
8847 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8848 0, 0, 640, 480, 0, 0, 0, 0);
8849 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8850 0, 0, 640, 480, 0, 0, 0, 0);
8851 ddraw = create_ddraw();
8852 ok(!!ddraw, "Failed to create a ddraw object.\n");
8853 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8854 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8856 memset(&surface_desc, 0, sizeof(surface_desc));
8857 surface_desc.dwSize = sizeof(surface_desc);
8858 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8859 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8860 U5(surface_desc).dwBackBufferCount = 1;
8861 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8862 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8864 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8865 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8866 hr = IDirectDrawSurface4_IsLost(surface);
8867 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8868 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8869 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8871 ret = SetForegroundWindow(GetDesktopWindow());
8872 ok(ret, "Failed to set foreground window.\n");
8873 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8874 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8875 hr = IDirectDrawSurface4_IsLost(surface);
8876 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8877 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8878 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8880 ret = SetForegroundWindow(window1);
8881 ok(ret, "Failed to set foreground window.\n");
8882 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8883 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8884 hr = IDirectDrawSurface4_IsLost(surface);
8885 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8886 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8887 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8889 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
8890 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8891 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8892 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8893 hr = IDirectDrawSurface4_IsLost(surface);
8894 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8895 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8896 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8898 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
8899 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8900 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8901 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8902 hr = IDirectDrawSurface4_IsLost(surface);
8903 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8904 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8905 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8907 /* Trying to restore the primary will crash, probably because flippable
8908 * surfaces can't exist in DDSCL_NORMAL. */
8909 IDirectDrawSurface4_Release(surface);
8910 memset(&surface_desc, 0, sizeof(surface_desc));
8911 surface_desc.dwSize = sizeof(surface_desc);
8912 surface_desc.dwFlags = DDSD_CAPS;
8913 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8914 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8915 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8917 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8918 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8919 hr = IDirectDrawSurface4_IsLost(surface);
8920 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8922 ret = SetForegroundWindow(GetDesktopWindow());
8923 ok(ret, "Failed to set foreground window.\n");
8924 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8925 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8926 hr = IDirectDrawSurface4_IsLost(surface);
8927 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8929 ret = SetForegroundWindow(window1);
8930 ok(ret, "Failed to set foreground window.\n");
8931 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8932 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8933 hr = IDirectDrawSurface4_IsLost(surface);
8934 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8936 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8937 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8938 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8939 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8940 hr = IDirectDrawSurface4_IsLost(surface);
8941 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8943 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
8944 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8945 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8946 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8947 hr = IDirectDrawSurface4_IsLost(surface);
8948 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8950 IDirectDrawSurface4_Release(surface);
8951 memset(&surface_desc, 0, sizeof(surface_desc));
8952 surface_desc.dwSize = sizeof(surface_desc);
8953 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8954 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8955 U5(surface_desc).dwBackBufferCount = 1;
8956 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8957 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8959 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8960 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8961 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8962 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8963 hr = IDirectDrawSurface4_IsLost(surface);
8964 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8965 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8966 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8968 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
8969 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8970 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8971 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8972 hr = IDirectDrawSurface4_IsLost(surface);
8973 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8974 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8975 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8977 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
8978 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8979 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8980 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8981 hr = IDirectDrawSurface4_IsLost(surface);
8982 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8983 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8984 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8986 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
8987 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8988 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8989 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8990 hr = IDirectDrawSurface4_IsLost(surface);
8991 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8992 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
8993 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8995 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
8996 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8997 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
8998 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8999 hr = IDirectDrawSurface4_IsLost(surface);
9000 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9001 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
9002 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9004 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9005 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9006 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
9007 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9008 hr = IDirectDrawSurface4_IsLost(surface);
9009 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9010 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
9011 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9013 IDirectDrawSurface4_Release(surface);
9014 refcount = IDirectDraw4_Release(ddraw);
9015 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9016 DestroyWindow(window2);
9017 DestroyWindow(window1);
9020 static void test_surface_desc_lock(void)
9022 IDirectDrawSurface4 *surface;
9023 DDSURFACEDESC2 surface_desc;
9024 IDirectDraw4 *ddraw;
9025 ULONG refcount;
9026 HWND window;
9027 HRESULT hr;
9029 window = create_window();
9030 ddraw = create_ddraw();
9031 ok(!!ddraw, "Failed to create a ddraw object.\n");
9032 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9033 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9035 memset(&surface_desc, 0, sizeof(surface_desc));
9036 surface_desc.dwSize = sizeof(surface_desc);
9037 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
9038 surface_desc.dwWidth = 16;
9039 surface_desc.dwHeight = 16;
9040 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9041 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9042 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9044 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9045 surface_desc.dwSize = sizeof(surface_desc);
9046 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
9047 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9048 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9050 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9051 surface_desc.dwSize = sizeof(surface_desc);
9052 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, 0, NULL);
9053 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9054 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9055 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9056 surface_desc.dwSize = sizeof(surface_desc);
9057 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
9058 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9059 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9060 hr = IDirectDrawSurface4_Unlock(surface, NULL);
9061 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9063 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9064 surface_desc.dwSize = sizeof(surface_desc);
9065 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
9066 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9067 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9069 IDirectDrawSurface4_Release(surface);
9070 refcount = IDirectDraw4_Release(ddraw);
9071 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9072 DestroyWindow(window);
9075 static void test_texturemapblend(void)
9077 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
9078 static RECT rect = {0, 0, 64, 128};
9079 IDirectDrawSurface4 *surface, *rt;
9080 IDirect3DViewport3 *viewport;
9081 DDSURFACEDESC2 surface_desc;
9082 IDirect3DTexture2 *texture;
9083 IDirect3DDevice3 *device;
9084 IDirectDraw4 *ddraw;
9085 IDirect3D3 *d3d;
9086 DDCOLORKEY ckey;
9087 D3DCOLOR color;
9088 ULONG refcount;
9089 HWND window;
9090 DDBLTFX fx;
9091 HRESULT hr;
9093 static struct
9095 struct vec4 position;
9096 D3DCOLOR diffuse;
9097 struct vec2 texcoord;
9099 test1_quads[] =
9101 {{ 0.0f, 0.0f, 0.0f, 1.0f}, 0xffffffff, {0.0f, 0.0f}},
9102 {{ 0.0f, 240.0f, 0.0f, 1.0f}, 0xffffffff, {0.0f, 1.0f}},
9103 {{640.0f, 0.0f, 0.0f, 1.0f}, 0xffffffff, {1.0f, 0.0f}},
9104 {{640.0f, 240.0f, 0.0f, 1.0f}, 0xffffffff, {1.0f, 1.0f}},
9105 {{ 0.0f, 240.0f, 0.0f, 1.0f}, 0x80ffffff, {0.0f, 0.0f}},
9106 {{ 0.0f, 480.0f, 0.0f, 1.0f}, 0x80ffffff, {0.0f, 1.0f}},
9107 {{640.0f, 240.0f, 0.0f, 1.0f}, 0x80ffffff, {1.0f, 0.0f}},
9108 {{640.0f, 480.0f, 0.0f, 1.0f}, 0x80ffffff, {1.0f, 1.0f}},
9110 test2_quads[] =
9112 {{ 0.0f, 0.0f, 0.0f, 1.0f}, 0x00ff0080, {0.0f, 0.0f}},
9113 {{ 0.0f, 240.0f, 0.0f, 1.0f}, 0x00ff0080, {0.0f, 1.0f}},
9114 {{640.0f, 0.0f, 0.0f, 1.0f}, 0x00ff0080, {1.0f, 0.0f}},
9115 {{640.0f, 240.0f, 0.0f, 1.0f}, 0x00ff0080, {1.0f, 1.0f}},
9116 {{ 0.0f, 240.0f, 0.0f, 1.0f}, 0x008000ff, {0.0f, 0.0f}},
9117 {{ 0.0f, 480.0f, 0.0f, 1.0f}, 0x008000ff, {0.0f, 1.0f}},
9118 {{640.0f, 240.0f, 0.0f, 1.0f}, 0x008000ff, {1.0f, 0.0f}},
9119 {{640.0f, 480.0f, 0.0f, 1.0f}, 0x008000ff, {1.0f, 1.0f}},
9122 window = create_window();
9123 if (!(device = create_device(window, DDSCL_NORMAL)))
9125 skip("Failed to create a 3D device, skipping test.\n");
9126 DestroyWindow(window);
9127 return;
9130 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
9131 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9132 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
9133 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
9134 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
9135 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9137 viewport = create_viewport(device, 0, 0, 640, 480);
9138 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
9139 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
9141 /* Test alpha with DDPF_ALPHAPIXELS texture - should be taken from texture
9142 * alpha channel.
9144 * The vertex alpha is completely ignored in this case, so case 1 and 2
9145 * combined are not a D3DTOP_MODULATE with texture alpha = 0xff in case 2
9146 * (no alpha in texture). */
9147 memset(&surface_desc, 0, sizeof(surface_desc));
9148 surface_desc.dwSize = sizeof(surface_desc);
9149 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9150 surface_desc.dwHeight = 128;
9151 surface_desc.dwWidth = 128;
9152 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9153 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9154 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
9155 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9156 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9157 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9158 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9159 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
9160 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9161 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9163 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9164 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
9165 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
9166 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9168 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9169 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
9171 memset(&fx, 0, sizeof(fx));
9172 fx.dwSize = sizeof(fx);
9173 U5(fx).dwFillColor = 0xff0000ff;
9174 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9175 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9176 U5(fx).dwFillColor = 0x800000ff;
9177 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9178 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9180 /* Note that the ddraw1 version of this test runs tests 1-3 with
9181 * D3DRENDERSTATE_COLORKEYENABLE enabled, whereas this version only runs
9182 * test 4 with color keying on. Because no color key is set on the texture
9183 * this should not result in different behavior. */
9184 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
9185 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9186 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
9187 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9188 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
9189 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9190 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
9191 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9192 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
9193 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9194 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
9195 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9197 hr = IDirect3DDevice3_BeginScene(device);
9198 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9199 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9200 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[0], 4, 0);
9201 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9202 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9203 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[4], 4, 0);
9204 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9205 hr = IDirect3DDevice3_EndScene(device);
9206 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9208 color = get_surface_color(rt, 5, 5);
9209 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9210 color = get_surface_color(rt, 400, 5);
9211 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9212 color = get_surface_color(rt, 5, 245);
9213 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9214 color = get_surface_color(rt, 400, 245);
9215 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9217 hr = IDirect3DDevice3_SetTexture(device, 0, NULL);
9218 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9219 IDirect3DTexture2_Release(texture);
9220 refcount = IDirectDrawSurface4_Release(surface);
9221 ok(!refcount, "Surface not properly released, refcount %u.\n", refcount);
9223 /* Test alpha with texture that has no alpha channel - alpha should be
9224 * taken from diffuse vertex color. */
9225 memset(&surface_desc, 0, sizeof(surface_desc));
9226 surface_desc.dwSize = sizeof(surface_desc);
9227 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9228 surface_desc.dwHeight = 128;
9229 surface_desc.dwWidth = 128;
9230 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9231 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9232 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
9233 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9234 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9235 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9236 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9238 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9239 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9241 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9242 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
9243 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
9244 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9246 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9247 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
9249 U5(fx).dwFillColor = 0xff0000ff;
9250 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9251 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9252 U5(fx).dwFillColor = 0x800000ff;
9253 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9254 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9256 hr = IDirect3DDevice3_BeginScene(device);
9257 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9258 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9259 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[0], 4, 0);
9260 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9261 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9262 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[4], 4, 0);
9263 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9264 hr = IDirect3DDevice3_EndScene(device);
9265 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9267 color = get_surface_color(rt, 5, 5);
9268 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9269 color = get_surface_color(rt, 400, 5);
9270 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9271 color = get_surface_color(rt, 5, 245);
9272 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9273 color = get_surface_color(rt, 400, 245);
9274 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9276 hr = IDirect3DDevice3_SetTexture(device, 0, NULL);
9277 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9278 IDirect3DTexture2_Release(texture);
9279 refcount = IDirectDrawSurface4_Release(surface);
9280 ok(!refcount, "Surface not properly released, refcount %u.\n", refcount);
9282 /* Test RGB - should multiply color components from diffuse vertex color
9283 * and texture. */
9284 memset(&surface_desc, 0, sizeof(surface_desc));
9285 surface_desc.dwSize = sizeof(surface_desc);
9286 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9287 surface_desc.dwHeight = 128;
9288 surface_desc.dwWidth = 128;
9289 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9290 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9291 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
9292 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9293 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9294 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9295 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9296 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
9297 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9298 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9300 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9301 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
9302 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
9303 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9305 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9306 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
9308 U5(fx).dwFillColor = 0x00ffffff;
9309 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9310 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9311 U5(fx).dwFillColor = 0x00ffff80;
9312 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9313 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9315 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
9316 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9318 hr = IDirect3DDevice3_BeginScene(device);
9319 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9320 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9321 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test2_quads[0], 4, 0);
9322 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9323 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9324 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test2_quads[4], 4, 0);
9325 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9326 hr = IDirect3DDevice3_EndScene(device);
9327 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9329 color = get_surface_color(rt, 5, 5);
9330 ok(compare_color(color, 0x00ff0040, 2), "Got unexpected color 0x%08x.\n", color);
9331 color = get_surface_color(rt, 400, 5);
9332 ok(compare_color(color, 0x00ff0080, 2), "Got unexpected color 0x%08x.\n", color);
9333 color = get_surface_color(rt, 5, 245);
9334 ok(compare_color(color, 0x00800080, 2), "Got unexpected color 0x%08x.\n", color);
9335 color = get_surface_color(rt, 400, 245);
9336 ok(compare_color(color, 0x008000ff, 2), "Got unexpected color 0x%08x.\n", color);
9338 hr = IDirect3DDevice3_SetTexture(device, 0, NULL);
9339 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9340 IDirect3DTexture2_Release(texture);
9341 refcount = IDirectDrawSurface4_Release(surface);
9342 ok(!refcount, "Surface not properly released, refcount %u.\n", refcount);
9344 /* Test alpha again, now with color keyed texture (colorkey emulation in
9345 * wine can interfere). */
9346 memset(&surface_desc, 0, sizeof(surface_desc));
9347 surface_desc.dwSize = sizeof(surface_desc);
9348 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9349 surface_desc.dwHeight = 128;
9350 surface_desc.dwWidth = 128;
9351 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9352 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9353 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
9354 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
9355 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
9356 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
9357 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
9359 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9360 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9362 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9363 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
9364 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
9365 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9367 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9368 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
9370 U5(fx).dwFillColor = 0xf800;
9371 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9372 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9373 U5(fx).dwFillColor = 0x001f;
9374 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9375 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9377 ckey.dwColorSpaceLowValue = 0x001f;
9378 ckey.dwColorSpaceHighValue = 0x001f;
9379 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9380 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
9382 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
9383 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9384 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
9385 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9387 hr = IDirect3DDevice3_BeginScene(device);
9388 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9389 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9390 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[0], 4, 0);
9391 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9392 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9393 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[4], 4, 0);
9394 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9395 hr = IDirect3DDevice3_EndScene(device);
9396 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9398 color = get_surface_color(rt, 5, 5);
9399 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
9400 color = get_surface_color(rt, 400, 5);
9401 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
9402 color = get_surface_color(rt, 5, 245);
9403 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
9404 color = get_surface_color(rt, 400, 245);
9405 ok(compare_color(color, 0x00800000, 2), "Got unexpected color 0x%08x.\n", color);
9407 hr = IDirect3DDevice3_SetTexture(device, 0, NULL);
9408 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9409 IDirect3DTexture2_Release(texture);
9410 refcount = IDirectDrawSurface4_Release(surface);
9411 ok(!refcount, "Surface not properly released, refcount %u.\n", refcount);
9413 destroy_viewport(device, viewport);
9414 IDirectDrawSurface4_Release(rt);
9415 IDirect3DDevice3_Release(device);
9416 IDirect3D3_Release(d3d);
9417 refcount = IDirectDraw4_Release(ddraw);
9418 ok(!refcount, "Ddraw object not properly released, refcount %u.\n", refcount);
9419 DestroyWindow(window);
9422 static void test_signed_formats(void)
9424 HRESULT hr;
9425 IDirect3DDevice3 *device;
9426 IDirect3D3 *d3d;
9427 IDirectDraw4 *ddraw;
9428 IDirectDrawSurface4 *surface, *rt;
9429 IDirect3DTexture2 *texture;
9430 IDirect3DViewport3 *viewport;
9431 DDSURFACEDESC2 surface_desc;
9432 ULONG refcount;
9433 HWND window;
9434 D3DCOLOR color, expected_color;
9435 D3DRECT clear_rect;
9436 static struct
9438 struct vec3 position;
9439 struct vec2 texcoord;
9441 quad[] =
9443 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
9444 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
9445 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
9446 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
9448 /* See test_signed_formats() in dlls/d3d9/tests/visual.c for an explanation
9449 * of these values. */
9450 static const USHORT content_v8u8[4][4] =
9452 {0x0000, 0x7f7f, 0x8880, 0x0000},
9453 {0x0080, 0x8000, 0x7f00, 0x007f},
9454 {0x193b, 0xe8c8, 0x0808, 0xf8f8},
9455 {0x4444, 0xc0c0, 0xa066, 0x22e0},
9457 static const DWORD content_x8l8v8u8[4][4] =
9459 {0x00000000, 0x00ff7f7f, 0x00008880, 0x00ff0000},
9460 {0x00000080, 0x00008000, 0x00007f00, 0x0000007f},
9461 {0x0041193b, 0x0051e8c8, 0x00040808, 0x00fff8f8},
9462 {0x00824444, 0x0000c0c0, 0x00c2a066, 0x009222e0},
9464 static const USHORT content_l6v5u5[4][4] =
9466 {0x0000, 0xfdef, 0x0230, 0xfc00},
9467 {0x0010, 0x0200, 0x01e0, 0x000f},
9468 {0x4067, 0x53b9, 0x0421, 0xffff},
9469 {0x8108, 0x0318, 0xc28c, 0x909c},
9471 static const struct
9473 const char *name;
9474 const void *content;
9475 SIZE_T pixel_size;
9476 BOOL blue;
9477 unsigned int slop, slop_broken;
9478 DDPIXELFORMAT format;
9480 formats[] =
9483 "D3DFMT_V8U8", content_v8u8, sizeof(WORD), FALSE, 1, 0,
9485 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV, 0,
9486 {16}, {0x000000ff}, {0x0000ff00}, {0x00000000}, {0x00000000}
9490 "D3DFMT_X8L8V8U8", content_x8l8v8u8, sizeof(DWORD), TRUE, 1, 0,
9492 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
9493 {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}
9497 "D3DFMT_L6V5U5", content_l6v5u5, sizeof(WORD), TRUE, 4, 7,
9499 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
9500 {16}, {0x0000001f}, {0x000003e0}, {0x0000fc00}, {0x00000000}
9504 /* No V16U16 or Q8W8V8U8 support in ddraw. */
9506 static const D3DCOLOR expected_colors[4][4] =
9508 {0x00808080, 0x00fefeff, 0x00010780, 0x008080ff},
9509 {0x00018080, 0x00800180, 0x0080fe80, 0x00fe8080},
9510 {0x00ba98a0, 0x004767a8, 0x00888881, 0x007878ff},
9511 {0x00c3c3c0, 0x003f3f80, 0x00e51fe1, 0x005fa2c8},
9513 unsigned int i, width, x, y;
9514 D3DDEVICEDESC device_desc, hel_desc;
9516 window = create_window();
9517 if (!(device = create_device(window, DDSCL_NORMAL)))
9519 skip("Failed to create a 3D device, skipping test.\n");
9520 DestroyWindow(window);
9521 return;
9524 memset(&device_desc, 0, sizeof(device_desc));
9525 device_desc.dwSize = sizeof(device_desc);
9526 memset(&hel_desc, 0, sizeof(hel_desc));
9527 hel_desc.dwSize = sizeof(hel_desc);
9528 hr = IDirect3DDevice3_GetCaps(device, &device_desc, &hel_desc);
9529 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9530 if (!(device_desc.dwTextureOpCaps & D3DTEXOPCAPS_BLENDFACTORALPHA))
9532 skip("D3DTOP_BLENDFACTORALPHA not supported, skipping bumpmap format tests.\n");
9533 goto done;
9536 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
9537 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9538 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
9539 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
9540 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
9541 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9543 memset(&surface_desc, 0, sizeof(surface_desc));
9544 surface_desc.dwSize = sizeof(surface_desc);
9545 hr = IDirectDrawSurface4_GetSurfaceDesc(rt, &surface_desc);
9546 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9547 viewport = create_viewport(device, 0, 0, surface_desc.dwWidth, surface_desc.dwHeight);
9548 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
9549 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
9550 U1(clear_rect).x1 = 0;
9551 U2(clear_rect).y1 = 0;
9552 U3(clear_rect).x2 = surface_desc.dwWidth;
9553 U4(clear_rect).y2 = surface_desc.dwHeight;
9555 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
9556 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9558 /* dst = tex * 0.5 + 1.0 * (1.0 - 0.5) = tex * 0.5 + 0.5 */
9559 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x80ffffff);
9560 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9561 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BLENDFACTORALPHA);
9562 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9563 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9564 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9565 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
9566 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9568 for (i = 0; i < ARRAY_SIZE(formats); i++)
9570 for (width = 1; width < 5; width += 3)
9572 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
9573 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
9575 memset(&surface_desc, 0, sizeof(surface_desc));
9576 surface_desc.dwSize = sizeof(surface_desc);
9577 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
9578 surface_desc.dwWidth = width;
9579 surface_desc.dwHeight = 4;
9580 U4(surface_desc).ddpfPixelFormat = formats[i].format;
9581 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
9582 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9583 if (FAILED(hr))
9585 skip("%s textures not supported, skipping.\n", formats[i].name);
9586 continue;
9588 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, format %s.\n", hr, formats[i].name);
9590 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9591 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture2 interface, hr %#x, format %s.\n",
9592 hr, formats[i].name);
9593 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
9594 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x, format %s.\n", hr, formats[i].name);
9595 IDirect3DTexture2_Release(texture);
9597 memset(&surface_desc, 0, sizeof(surface_desc));
9598 surface_desc.dwSize = sizeof(surface_desc);
9599 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, 0, NULL);
9600 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, format %s.\n", hr, formats[i].name);
9601 for (y = 0; y < 4; y++)
9603 memcpy((char *)surface_desc.lpSurface + y * U1(surface_desc).lPitch,
9604 (char *)formats[i].content + y * 4 * formats[i].pixel_size,
9605 width * formats[i].pixel_size);
9607 hr = IDirectDrawSurface4_Unlock(surface, NULL);
9608 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, format %s.\n", hr, formats[i].name);
9610 hr = IDirect3DDevice3_BeginScene(device);
9611 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9612 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9613 D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
9614 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9615 hr = IDirect3DDevice3_EndScene(device);
9616 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9618 for (y = 0; y < 4; y++)
9620 for (x = 0; x < width; x++)
9622 expected_color = expected_colors[y][x];
9623 if (!formats[i].blue)
9624 expected_color |= 0x000000ff;
9626 color = get_surface_color(rt, 80 + 160 * x, 60 + 120 * y);
9627 ok(compare_color(color, expected_color, formats[i].slop)
9628 || broken(compare_color(color, expected_color, formats[i].slop_broken)),
9629 "Expected color 0x%08x, got 0x%08x, format %s, location %ux%u.\n",
9630 expected_color, color, formats[i].name, x, y);
9634 IDirectDrawSurface4_Release(surface);
9638 destroy_viewport(device, viewport);
9639 IDirectDrawSurface4_Release(rt);
9640 IDirectDraw4_Release(ddraw);
9641 IDirect3D3_Release(d3d);
9643 done:
9644 refcount = IDirect3DDevice3_Release(device);
9645 ok(!refcount, "Device has %u references left.\n", refcount);
9646 DestroyWindow(window);
9649 static void test_color_fill(void)
9651 HRESULT hr;
9652 IDirect3DDevice3 *device;
9653 IDirect3D3 *d3d;
9654 IDirectDraw4 *ddraw;
9655 IDirectDrawSurface4 *surface, *surface2;
9656 DDSURFACEDESC2 surface_desc;
9657 DDPIXELFORMAT z_fmt;
9658 ULONG refcount;
9659 HWND window;
9660 unsigned int i;
9661 DDBLTFX fx;
9662 RECT rect = {5, 5, 7, 7};
9663 DWORD *color;
9664 DWORD supported_fmts = 0, num_fourcc_codes, *fourcc_codes;
9665 DDCAPS hal_caps;
9666 static const struct
9668 DWORD caps, caps2;
9669 HRESULT colorfill_hr, depthfill_hr;
9670 BOOL rop_success;
9671 const char *name;
9672 DWORD result;
9673 BOOL check_result;
9674 DDPIXELFORMAT format;
9676 tests[] =
9679 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9680 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
9682 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9683 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9687 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
9688 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
9690 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9691 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9695 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
9696 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
9698 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9699 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9703 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
9704 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
9706 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9707 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9711 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
9712 DD_OK, DDERR_INVALIDPARAMS, TRUE, "managed texture RGB", 0xdeadbeef, TRUE,
9714 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9715 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9719 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY, 0,
9720 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0xdeadbeef, TRUE,
9721 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
9724 DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY, 0,
9725 DDERR_INVALIDPARAMS, DD_OK, TRUE, "sysmem zbuffer", 0xdeadbeef, TRUE,
9726 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
9729 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
9730 * different afterwards. DX9+ GPUs set one of the two luminance values
9731 * in each block, but AMD and Nvidia GPUs disagree on which luminance
9732 * value they set. r200 (dx8) just sets the entire block to the clear
9733 * value. */
9734 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9735 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
9737 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
9738 {0}, {0}, {0}, {0}, {0}
9742 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9743 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
9745 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
9746 {0}, {0}, {0}, {0}, {0}
9750 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
9751 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
9753 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
9754 {0}, {0}, {0}, {0}, {0}
9758 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
9759 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
9761 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
9762 {0}, {0}, {0}, {0}, {0}
9766 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
9767 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
9769 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
9770 {0}, {0}, {0}, {0}, {0}
9774 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
9775 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
9777 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
9778 {0}, {0}, {0}, {0}, {0}
9782 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
9783 * surface works, presumably because it is handled by the runtime instead of
9784 * the driver. */
9785 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9786 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
9788 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
9789 {8}, {0}, {0}, {0}, {0}
9793 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
9794 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
9796 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
9797 {8}, {0}, {0}, {0}, {0}
9801 static const struct
9803 DWORD rop;
9804 const char *name;
9805 HRESULT hr;
9807 rops[] =
9809 {SRCCOPY, "SRCCOPY", DD_OK},
9810 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
9811 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
9812 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
9813 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
9814 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
9815 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
9816 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
9817 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
9818 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
9819 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
9820 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
9821 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
9822 {BLACKNESS, "BLACKNESS", DD_OK},
9823 {WHITENESS, "WHITENESS", DD_OK},
9824 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
9827 window = create_window();
9828 if (!(device = create_device(window, DDSCL_NORMAL)))
9830 skip("Failed to create a 3D device, skipping test.\n");
9831 DestroyWindow(window);
9832 return;
9835 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
9836 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9837 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
9838 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
9840 memset(&z_fmt, 0, sizeof(z_fmt));
9841 IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
9842 if (!z_fmt.dwSize)
9843 skip("No Z buffer formats supported, skipping Z buffer colorfill test.\n");
9845 IDirect3DDevice3_EnumTextureFormats(device, test_block_formats_creation_cb, &supported_fmts);
9846 if (!(supported_fmts & SUPPORT_DXT1))
9847 skip("DXT1 textures not supported, skipping DXT1 colorfill test.\n");
9849 IDirect3D3_Release(d3d);
9851 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
9852 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
9853 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
9854 num_fourcc_codes * sizeof(*fourcc_codes));
9855 if (!fourcc_codes)
9856 goto done;
9857 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
9858 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
9859 for (i = 0; i < num_fourcc_codes; i++)
9861 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
9862 supported_fmts |= SUPPORT_YUY2;
9863 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
9864 supported_fmts |= SUPPORT_UYVY;
9866 HeapFree(GetProcessHeap(), 0, fourcc_codes);
9868 memset(&hal_caps, 0, sizeof(hal_caps));
9869 hal_caps.dwSize = sizeof(hal_caps);
9870 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
9871 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9873 if (!(supported_fmts & (SUPPORT_YUY2 | SUPPORT_UYVY)) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
9874 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
9876 for (i = 0; i < ARRAY_SIZE(tests); i++)
9878 DWORD expected_broken = tests[i].result;
9880 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
9881 memset(&fx, 0, sizeof(fx));
9882 fx.dwSize = sizeof(fx);
9883 U5(fx).dwFillColor = 0xdeadbeef;
9885 memset(&surface_desc, 0, sizeof(surface_desc));
9886 surface_desc.dwSize = sizeof(surface_desc);
9887 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9888 surface_desc.dwWidth = 64;
9889 surface_desc.dwHeight = 64;
9890 U4(surface_desc).ddpfPixelFormat = tests[i].format;
9891 surface_desc.ddsCaps.dwCaps = tests[i].caps;
9892 surface_desc.ddsCaps.dwCaps2 = tests[i].caps2;
9894 if (tests[i].format.dwFourCC == MAKEFOURCC('D','X','T','1') && !(supported_fmts & SUPPORT_DXT1))
9895 continue;
9896 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !(supported_fmts & SUPPORT_YUY2))
9897 continue;
9898 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !(supported_fmts & SUPPORT_UYVY))
9899 continue;
9900 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
9901 continue;
9903 if (tests[i].caps & DDSCAPS_ZBUFFER)
9905 if (!z_fmt.dwSize)
9906 continue;
9908 U4(surface_desc).ddpfPixelFormat = z_fmt;
9909 /* Some drivers seem to convert depth values incorrectly or not at
9910 * all. Affects at least AMD PALM, 8.17.10.1247. */
9911 if (tests[i].caps & DDSCAPS_VIDEOMEMORY)
9913 DWORD expected;
9914 float f, g;
9916 expected = tests[i].result & U3(z_fmt).dwZBitMask;
9917 f = ceilf(log2f(expected + 1.0f));
9918 g = (f + 1.0f) / 2.0f;
9919 g -= (int)g;
9920 expected_broken = (expected / exp2f(f) - g) * 256;
9921 expected_broken *= 0x01010101;
9925 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9926 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, surface %s.\n", hr, tests[i].name);
9928 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9929 todo_wine_if (tests[i].format.dwFourCC)
9930 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9931 hr, tests[i].colorfill_hr, tests[i].name);
9933 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9934 todo_wine_if (tests[i].format.dwFourCC)
9935 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9936 hr, tests[i].colorfill_hr, tests[i].name);
9938 if (SUCCEEDED(hr) && tests[i].check_result)
9940 memset(&surface_desc, 0, sizeof(surface_desc));
9941 surface_desc.dwSize = sizeof(surface_desc);
9942 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9943 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9944 color = surface_desc.lpSurface;
9945 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
9946 *color, tests[i].result, tests[i].name);
9947 hr = IDirectDrawSurface4_Unlock(surface, NULL);
9948 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9951 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9952 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9953 hr, tests[i].depthfill_hr, tests[i].name);
9954 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9955 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9956 hr, tests[i].depthfill_hr, tests[i].name);
9958 if (SUCCEEDED(hr) && tests[i].check_result)
9960 memset(&surface_desc, 0, sizeof(surface_desc));
9961 surface_desc.dwSize = sizeof(surface_desc);
9962 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9963 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9964 color = surface_desc.lpSurface;
9965 ok((*color & U3(z_fmt).dwZBitMask) == (tests[i].result & U3(z_fmt).dwZBitMask)
9966 || broken((*color & U3(z_fmt).dwZBitMask) == (expected_broken & U3(z_fmt).dwZBitMask)),
9967 "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
9968 *color & U3(z_fmt).dwZBitMask, tests[i].result & U3(z_fmt).dwZBitMask, tests[i].name);
9969 hr = IDirectDrawSurface4_Unlock(surface, NULL);
9970 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9973 U5(fx).dwFillColor = 0xdeadbeef;
9974 fx.dwROP = BLACKNESS;
9975 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9976 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
9977 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
9978 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
9979 U5(fx).dwFillColor, tests[i].name);
9981 if (SUCCEEDED(hr) && tests[i].check_result)
9983 memset(&surface_desc, 0, sizeof(surface_desc));
9984 surface_desc.dwSize = sizeof(surface_desc);
9985 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9986 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9987 color = surface_desc.lpSurface;
9988 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
9989 *color, tests[i].name);
9990 hr = IDirectDrawSurface4_Unlock(surface, NULL);
9991 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9994 fx.dwROP = WHITENESS;
9995 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9996 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
9997 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
9998 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
9999 U5(fx).dwFillColor, tests[i].name);
10001 if (SUCCEEDED(hr) && tests[i].check_result)
10003 memset(&surface_desc, 0, sizeof(surface_desc));
10004 surface_desc.dwSize = sizeof(surface_desc);
10005 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10006 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10007 color = surface_desc.lpSurface;
10008 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
10009 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
10010 *color, tests[i].name);
10011 hr = IDirectDrawSurface4_Unlock(surface, NULL);
10012 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10015 IDirectDrawSurface4_Release(surface);
10018 memset(&fx, 0, sizeof(fx));
10019 fx.dwSize = sizeof(fx);
10020 U5(fx).dwFillColor = 0xdeadbeef;
10021 fx.dwROP = WHITENESS;
10023 memset(&surface_desc, 0, sizeof(surface_desc));
10024 surface_desc.dwSize = sizeof(surface_desc);
10025 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10026 surface_desc.dwWidth = 64;
10027 surface_desc.dwHeight = 64;
10028 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10029 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10030 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10031 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10032 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10033 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10034 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
10035 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10036 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10037 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
10038 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10040 /* No DDBLTFX. */
10041 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
10042 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10043 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
10044 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10046 /* Unused source rectangle. */
10047 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10048 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10049 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10050 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10052 /* Unused source surface. */
10053 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10054 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10055 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10056 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10057 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10058 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10059 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10060 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10062 /* Inverted destination or source rectangle. */
10063 SetRect(&rect, 5, 7, 7, 5);
10064 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10065 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10066 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10067 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10068 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10069 ok(hr == DDERR_INVALIDPARAMS, "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(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10075 /* Negative rectangle. */
10076 SetRect(&rect, -1, -1, 5, 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, &rect, 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 /* Out of bounds rectangle. */
10089 SetRect(&rect, 0, 0, 65, 65);
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, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10093 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10095 /* Combine multiple flags. */
10096 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10097 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10098 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
10099 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10100 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
10101 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10103 for (i = 0; i < ARRAY_SIZE(rops); i++)
10105 fx.dwROP = rops[i].rop;
10106 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10107 ok(hr == rops[i].hr, "Got unexpected hr %#x for rop %s.\n", hr, rops[i].name);
10110 IDirectDrawSurface4_Release(surface2);
10111 IDirectDrawSurface4_Release(surface);
10113 if (!z_fmt.dwSize)
10114 goto done;
10116 memset(&surface_desc, 0, sizeof(surface_desc));
10117 surface_desc.dwSize = sizeof(surface_desc);
10118 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10119 surface_desc.dwWidth = 64;
10120 surface_desc.dwHeight = 64;
10121 U4(surface_desc).ddpfPixelFormat = z_fmt;
10122 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
10123 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10124 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10125 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
10126 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10128 /* No DDBLTFX. */
10129 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
10130 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10132 /* Unused source rectangle. */
10133 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10134 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10136 /* Unused source surface. */
10137 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10138 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10139 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10140 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10142 /* Inverted destination or source rectangle. */
10143 SetRect(&rect, 5, 7, 7, 5);
10144 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10145 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10146 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10147 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10148 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10149 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10150 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10151 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10153 /* Negative rectangle. */
10154 SetRect(&rect, -1, -1, 5, 5);
10155 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10156 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10157 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10158 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10159 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10160 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10161 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10162 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10164 /* Out of bounds rectangle. */
10165 SetRect(&rect, 0, 0, 65, 65);
10166 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10167 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10169 /* Combine multiple flags. */
10170 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10171 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10173 IDirectDrawSurface4_Release(surface2);
10174 IDirectDrawSurface4_Release(surface);
10176 done:
10177 IDirectDraw4_Release(ddraw);
10178 refcount = IDirect3DDevice3_Release(device);
10179 ok(!refcount, "Device has %u references left.\n", refcount);
10180 DestroyWindow(window);
10183 static void test_texcoordindex(void)
10185 static struct
10187 struct vec3 pos;
10188 struct vec2 texcoord1;
10189 struct vec2 texcoord2;
10190 struct vec2 texcoord3;
10192 quad[] =
10194 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f}},
10195 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f}},
10196 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}},
10197 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}},
10199 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_TEX3;
10200 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
10201 IDirect3DDevice3 *device;
10202 IDirect3D3 *d3d;
10203 IDirectDraw4 *ddraw;
10204 IDirectDrawSurface4 *rt;
10205 IDirect3DViewport3 *viewport;
10206 HWND window;
10207 HRESULT hr;
10208 IDirectDrawSurface4 *surface1, *surface2;
10209 IDirect3DTexture2 *texture1, *texture2;
10210 DDSURFACEDESC2 surface_desc;
10211 ULONG refcount;
10212 D3DCOLOR color;
10213 DWORD *ptr;
10215 window = create_window();
10216 if (!(device = create_device(window, DDSCL_NORMAL)))
10218 skip("Failed to create a 3D device, skipping test.\n");
10219 DestroyWindow(window);
10220 return;
10223 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
10224 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
10225 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
10226 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
10227 IDirect3D3_Release(d3d);
10229 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
10230 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10232 memset(&surface_desc, 0, sizeof(surface_desc));
10233 surface_desc.dwSize = sizeof(surface_desc);
10234 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10235 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10236 surface_desc.dwWidth = 2;
10237 surface_desc.dwHeight = 2;
10238 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10239 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
10240 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10241 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10242 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10243 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10244 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
10245 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
10246 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10247 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
10248 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10250 memset(&surface_desc, 0, sizeof(surface_desc));
10251 surface_desc.dwSize = sizeof(surface_desc);
10252 hr = IDirectDrawSurface4_Lock(surface1, 0, &surface_desc, 0, NULL);
10253 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10254 ptr = surface_desc.lpSurface;
10255 ptr[0] = 0xff000000;
10256 ptr[1] = 0xff00ff00;
10257 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
10258 ptr[0] = 0xff0000ff;
10259 ptr[1] = 0xff00ffff;
10260 hr = IDirectDrawSurface4_Unlock(surface1, NULL);
10261 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10263 memset(&surface_desc, 0, sizeof(surface_desc));
10264 surface_desc.dwSize = sizeof(surface_desc);
10265 hr = IDirectDrawSurface4_Lock(surface2, 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] = 0xff0000ff;
10270 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
10271 ptr[0] = 0xffff0000;
10272 ptr[1] = 0xffff00ff;
10273 hr = IDirectDrawSurface4_Unlock(surface2, 0);
10274 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10276 viewport = create_viewport(device, 0, 0, 640, 480);
10277 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
10278 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
10280 hr = IDirectDrawSurface4_QueryInterface(surface1, &IID_IDirect3DTexture2, (void **)&texture1);
10281 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
10282 hr = IDirectDrawSurface4_QueryInterface(surface2, &IID_IDirect3DTexture2, (void **)&texture2);
10283 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
10284 hr = IDirect3DDevice3_SetTexture(device, 0, texture1);
10285 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
10286 hr = IDirect3DDevice3_SetTexture(device, 1, texture2);
10287 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
10288 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10289 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10290 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
10291 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10292 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10293 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10294 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD);
10295 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10296 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10297 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10298 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
10299 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10300 hr = IDirect3DDevice3_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
10301 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10303 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_TEXCOORDINDEX, 1);
10304 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10305 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 0);
10306 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10308 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
10309 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
10311 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
10312 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10314 hr = IDirect3DDevice3_BeginScene(device);
10315 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10316 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
10317 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10318 hr = IDirect3DDevice3_EndScene(device);
10319 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10321 color = get_surface_color(rt, 160, 120);
10322 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10323 color = get_surface_color(rt, 480, 120);
10324 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10325 color = get_surface_color(rt, 160, 360);
10326 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
10327 color = get_surface_color(rt, 480, 360);
10328 ok(compare_color(color, 0x00ffffff, 2), "Got unexpected color 0x%08x.\n", color);
10330 /* D3DTSS_TEXTURETRANSFORMFLAGS was introduced in D3D7, can't test it here. */
10332 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 2);
10333 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10335 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
10336 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10338 hr = IDirect3DDevice3_BeginScene(device);
10339 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10340 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
10341 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10342 hr = IDirect3DDevice3_EndScene(device);
10343 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10345 color = get_surface_color(rt, 160, 120);
10346 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10347 color = get_surface_color(rt, 480, 120);
10348 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10349 color = get_surface_color(rt, 160, 360);
10350 ok(compare_color(color, 0x00ff00ff, 2), "Got unexpected color 0x%08x.\n", color);
10351 color = get_surface_color(rt, 480, 360);
10352 ok(compare_color(color, 0x00ffff00, 2), "Got unexpected color 0x%08x.\n", color);
10354 IDirect3DTexture2_Release(texture2);
10355 IDirect3DTexture2_Release(texture1);
10356 IDirectDrawSurface4_Release(surface2);
10357 IDirectDrawSurface4_Release(surface1);
10359 destroy_viewport(device, viewport);
10361 IDirectDrawSurface4_Release(rt);
10362 IDirectDraw_Release(ddraw);
10363 refcount = IDirect3DDevice3_Release(device);
10364 ok(!refcount, "Device has %u references left.\n", refcount);
10365 DestroyWindow(window);
10368 static void test_colorkey_precision(void)
10370 static struct
10372 struct vec3 pos;
10373 struct vec2 texcoord;
10375 quad[] =
10377 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
10378 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
10379 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
10380 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
10382 IDirect3DDevice3 *device;
10383 IDirect3D3 *d3d;
10384 IDirectDraw4 *ddraw;
10385 IDirectDrawSurface4 *rt;
10386 IDirect3DViewport3 *viewport;
10387 HWND window;
10388 HRESULT hr;
10389 IDirectDrawSurface4 *src, *dst, *texture;
10390 IDirect3DTexture2 *d3d_texture;
10391 DDSURFACEDESC2 surface_desc, lock_desc;
10392 ULONG refcount;
10393 D3DCOLOR color;
10394 unsigned int t, c;
10395 DDCOLORKEY ckey;
10396 DDBLTFX fx;
10397 DWORD data[4] = {0}, color_mask;
10398 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
10399 BOOL is_nvidia, is_warp;
10400 static const struct
10402 unsigned int max, shift, bpp, clear;
10403 const char *name;
10404 BOOL skip_nv;
10405 DDPIXELFORMAT fmt;
10407 tests[] =
10410 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8", FALSE,
10412 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10413 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
10418 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel", FALSE,
10420 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10421 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
10426 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel", FALSE,
10428 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10429 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
10434 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4", TRUE,
10436 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10437 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
10442 window = create_window();
10443 if (!(device = create_device(window, DDSCL_NORMAL)))
10445 skip("Failed to create a 3D device, skipping test.\n");
10446 DestroyWindow(window);
10447 return;
10450 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
10451 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
10452 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
10453 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
10454 IDirect3D3_Release(d3d);
10455 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
10456 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10458 is_nvidia = ddraw_is_nvidia(ddraw);
10459 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
10460 * (color key doesn't match although the values are equal), and a false
10461 * positive when the color key is 0 and the texture contains the value 1.
10462 * I don't want to mark this broken unconditionally since this would
10463 * essentially disable the test on Windows. Also on random occasions
10464 * 254 == 255 and 255 != 255.*/
10465 is_warp = ddraw_is_warp(ddraw);
10467 viewport = create_viewport(device, 0, 0, 640, 480);
10468 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
10469 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
10471 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10472 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
10473 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
10474 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
10475 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
10476 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
10477 /* Multiply the texture read result with 0, that way the result color if the key doesn't
10478 * match is constant. In theory color keying works without reading the texture result
10479 * (meaning we could just op=arg1, arg1=tfactor), but the Geforce7 Windows driver begs
10480 * to differ. */
10481 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
10482 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10483 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10484 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10485 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
10486 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10487 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x00000000);
10488 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10490 memset(&fx, 0, sizeof(fx));
10491 fx.dwSize = sizeof(fx);
10492 memset(&lock_desc, 0, sizeof(lock_desc));
10493 lock_desc.dwSize = sizeof(lock_desc);
10495 for (t = 0; t < ARRAY_SIZE(tests); ++t)
10497 if (is_nvidia && tests[t].skip_nv)
10499 win_skip("Skipping test %s on Nvidia Windows drivers.\n", tests[t].name);
10500 continue;
10503 memset(&surface_desc, 0, sizeof(surface_desc));
10504 surface_desc.dwSize = sizeof(surface_desc);
10505 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10506 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10507 surface_desc.dwWidth = 4;
10508 surface_desc.dwHeight = 1;
10509 U4(surface_desc).ddpfPixelFormat = tests[t].fmt;
10510 /* Windows XP (at least with the r200 driver, other drivers untested) produces
10511 * garbage when doing color keyed texture->texture blits. */
10512 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL);
10513 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10514 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL);
10515 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10517 U5(fx).dwFillColor = tests[t].clear;
10518 /* On the w8 testbot (WARP driver) the blit result has different values in the
10519 * X channel. */
10520 color_mask = U2(tests[t].fmt).dwRBitMask
10521 | U3(tests[t].fmt).dwGBitMask
10522 | U4(tests[t].fmt).dwBBitMask;
10524 for (c = 0; c <= tests[t].max; ++c)
10526 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
10527 * texture after it has been set once... */
10528 surface_desc.dwFlags |= DDSD_CKSRCBLT;
10529 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10530 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
10531 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
10532 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &texture, NULL);
10533 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10534 hr = IDirectDrawSurface4_QueryInterface(texture, &IID_IDirect3DTexture2, (void **)&d3d_texture);
10535 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
10536 hr = IDirect3DDevice3_SetTexture(device, 0, d3d_texture);
10537 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
10539 hr = IDirectDrawSurface4_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10540 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
10542 hr = IDirectDrawSurface4_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
10543 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10544 switch (tests[t].bpp)
10546 case 4:
10547 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
10548 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
10549 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
10550 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
10551 break;
10553 case 2:
10554 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
10555 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
10556 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
10557 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
10558 break;
10560 hr = IDirectDrawSurface4_Unlock(src, 0);
10561 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10562 hr = IDirectDrawSurface4_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
10563 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
10565 ckey.dwColorSpaceLowValue = c << tests[t].shift;
10566 ckey.dwColorSpaceHighValue = c << tests[t].shift;
10567 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
10568 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10570 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
10571 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
10573 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
10574 hr = IDirectDrawSurface4_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
10575 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10576 switch (tests[t].bpp)
10578 case 4:
10579 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
10580 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
10581 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
10582 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
10583 break;
10585 case 2:
10586 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
10587 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
10588 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
10589 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
10590 break;
10592 hr = IDirectDrawSurface4_Unlock(dst, 0);
10593 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10595 if (!c)
10597 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10598 tests[t].clear, data[0], tests[t].name, c);
10600 if (data[3] == tests[t].clear)
10602 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
10603 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
10604 * even when a different surface is used. The blit itself doesn't draw anything,
10605 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
10606 * never be masked out by the key.
10608 * On Windows 10 the problem is worse, Blt just hangs. For this reason the ARGB4444
10609 * test is disabled entirely.
10611 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
10612 * terrible on WARP. */
10613 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
10614 IDirect3DTexture2_Release(d3d_texture);
10615 IDirectDrawSurface4_Release(texture);
10616 IDirectDrawSurface4_Release(src);
10617 IDirectDrawSurface4_Release(dst);
10618 goto done;
10621 else
10622 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10623 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
10625 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10626 tests[t].clear, data[1], tests[t].name, c);
10628 if (c == tests[t].max)
10629 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10630 tests[t].clear, data[2], tests[t].name, c);
10631 else
10632 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10633 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
10635 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
10636 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10638 hr = IDirect3DDevice3_BeginScene(device);
10639 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10640 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
10641 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10642 hr = IDirect3DDevice3_EndScene(device);
10643 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10645 color = get_surface_color(rt, 80, 240);
10646 if (!c)
10647 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10648 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10649 color, tests[t].name, c);
10650 else
10651 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
10652 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10653 color, tests[t].name, c);
10655 color = get_surface_color(rt, 240, 240);
10656 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10657 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10658 color, tests[t].name, c);
10660 color = get_surface_color(rt, 400, 240);
10661 if (c == tests[t].max)
10662 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10663 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10664 color, tests[t].name, c);
10665 else
10666 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
10667 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10668 color, tests[t].name, c);
10670 IDirect3DTexture2_Release(d3d_texture);
10671 IDirectDrawSurface4_Release(texture);
10673 IDirectDrawSurface4_Release(src);
10674 IDirectDrawSurface4_Release(dst);
10676 done:
10678 destroy_viewport(device, viewport);
10679 IDirectDrawSurface4_Release(rt);
10680 IDirectDraw4_Release(ddraw);
10681 refcount = IDirect3DDevice3_Release(device);
10682 ok(!refcount, "Device has %u references left.\n", refcount);
10683 DestroyWindow(window);
10686 static void test_range_colorkey(void)
10688 IDirectDraw4 *ddraw;
10689 HWND window;
10690 HRESULT hr;
10691 IDirectDrawSurface4 *surface;
10692 DDSURFACEDESC2 surface_desc;
10693 ULONG refcount;
10694 DDCOLORKEY ckey;
10696 window = create_window();
10697 ddraw = create_ddraw();
10698 ok(!!ddraw, "Failed to create a ddraw object.\n");
10699 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10700 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10702 memset(&surface_desc, 0, sizeof(surface_desc));
10703 surface_desc.dwSize = sizeof(surface_desc);
10704 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
10705 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10706 surface_desc.dwWidth = 1;
10707 surface_desc.dwHeight = 1;
10708 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10709 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10710 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10711 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10712 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10713 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
10715 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
10716 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10717 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
10718 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10719 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10721 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
10722 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10723 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10724 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10726 /* Same for DDSCAPS_OFFSCREENPLAIN. */
10727 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10728 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10729 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
10730 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10731 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10733 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
10734 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10735 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10736 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10738 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10739 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10740 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10741 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10743 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
10744 ckey.dwColorSpaceLowValue = 0x00000000;
10745 ckey.dwColorSpaceHighValue = 0x00000001;
10746 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10747 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10749 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10750 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10751 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10752 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10754 ckey.dwColorSpaceLowValue = 0x00000001;
10755 ckey.dwColorSpaceHighValue = 0x00000000;
10756 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10757 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10759 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10760 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10761 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10762 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10764 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
10765 ckey.dwColorSpaceLowValue = 0x00000000;
10766 ckey.dwColorSpaceHighValue = 0x00000000;
10767 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10768 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10770 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
10771 ckey.dwColorSpaceLowValue = 0x00000001;
10772 ckey.dwColorSpaceHighValue = 0x00000000;
10773 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10774 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10775 ckey.dwColorSpaceLowValue = 0x00000000;
10776 ckey.dwColorSpaceHighValue = 0x00000001;
10777 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10778 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10779 /* Range destination keys don't work either. */
10780 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
10781 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10783 /* Just to show it's not because of A, R, and G having equal values. */
10784 ckey.dwColorSpaceLowValue = 0x00000000;
10785 ckey.dwColorSpaceHighValue = 0x01010101;
10786 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10787 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10789 /* None of these operations modified the key. */
10790 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10791 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10792 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10793 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10795 IDirectDrawSurface4_Release(surface),
10796 refcount = IDirectDraw4_Release(ddraw);
10797 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
10798 DestroyWindow(window);
10801 static void test_shademode(void)
10803 IDirect3DVertexBuffer *vb_strip, *vb_list, *buffer;
10804 IDirect3DViewport3 *viewport;
10805 IDirect3DDevice3 *device;
10806 D3DVERTEXBUFFERDESC desc;
10807 IDirectDrawSurface4 *rt;
10808 DWORD color0, color1;
10809 void *data = NULL;
10810 IDirect3D3 *d3d;
10811 ULONG refcount;
10812 UINT i, count;
10813 HWND window;
10814 HRESULT hr;
10815 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
10816 static const struct
10818 struct vec3 position;
10819 DWORD diffuse;
10821 quad_strip[] =
10823 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
10824 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
10825 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
10826 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
10828 quad_list[] =
10830 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
10831 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
10832 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
10834 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
10835 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
10836 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
10838 static const struct
10840 DWORD primtype;
10841 DWORD shademode;
10842 DWORD color0, color1;
10844 tests[] =
10846 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x0000ff00},
10847 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
10848 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
10849 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
10850 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
10851 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
10854 window = create_window();
10855 if (!(device = create_device(window, DDSCL_NORMAL)))
10857 skip("Failed to create a 3D device, skipping test.\n");
10858 DestroyWindow(window);
10859 return;
10862 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
10863 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
10864 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
10865 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10867 viewport = create_viewport(device, 0, 0, 640, 480);
10868 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
10869 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
10871 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
10872 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
10874 memset(&desc, 0, sizeof(desc));
10875 desc.dwSize = sizeof(desc);
10876 desc.dwCaps = D3DVBCAPS_WRITEONLY;
10877 desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
10878 desc.dwNumVertices = ARRAY_SIZE(quad_strip);
10879 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &vb_strip, 0, NULL);
10880 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
10881 hr = IDirect3DVertexBuffer_Lock(vb_strip, 0, &data, NULL);
10882 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
10883 memcpy(data, quad_strip, sizeof(quad_strip));
10884 hr = IDirect3DVertexBuffer_Unlock(vb_strip);
10885 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
10887 desc.dwNumVertices = ARRAY_SIZE(quad_list);
10888 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &vb_list, 0, NULL);
10889 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
10890 hr = IDirect3DVertexBuffer_Lock(vb_list, 0, &data, NULL);
10891 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
10892 memcpy(data, quad_list, sizeof(quad_list));
10893 hr = IDirect3DVertexBuffer_Unlock(vb_list);
10894 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
10896 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
10897 * the color fixups we have to do for FLAT shading will be dependent on that. */
10899 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10901 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
10902 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
10904 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
10905 ok(hr == D3D_OK, "Failed to set shade mode, hr %#x.\n", hr);
10907 hr = IDirect3DDevice3_BeginScene(device);
10908 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10909 buffer = tests[i].primtype == D3DPT_TRIANGLESTRIP ? vb_strip : vb_list;
10910 count = tests[i].primtype == D3DPT_TRIANGLESTRIP ? 4 : 6;
10911 hr = IDirect3DDevice3_DrawPrimitiveVB(device, tests[i].primtype, buffer, 0, count, 0);
10912 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10913 hr = IDirect3DDevice3_EndScene(device);
10914 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10916 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
10917 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
10919 /* For D3DSHADE_FLAT it should take the color of the first vertex of
10920 * each triangle. This requires EXT_provoking_vertex or similar
10921 * functionality being available. */
10922 /* PHONG should be the same as GOURAUD, since no hardware implements
10923 * this. */
10924 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
10925 i, color0, tests[i].color0);
10926 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
10927 i, color1, tests[i].color1);
10930 IDirect3DVertexBuffer_Release(vb_strip);
10931 IDirect3DVertexBuffer_Release(vb_list);
10932 destroy_viewport(device, viewport);
10933 IDirectDrawSurface4_Release(rt);
10934 IDirect3D3_Release(d3d);
10935 refcount = IDirect3DDevice3_Release(device);
10936 ok(!refcount, "Device has %u references left.\n", refcount);
10937 DestroyWindow(window);
10940 static void test_lockrect_invalid(void)
10942 unsigned int i, r;
10943 IDirectDraw4 *ddraw;
10944 IDirectDrawSurface4 *surface;
10945 HWND window;
10946 HRESULT hr;
10947 DDSURFACEDESC2 surface_desc;
10948 DDCAPS hal_caps;
10949 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
10950 static RECT valid[] =
10952 {60, 60, 68, 68},
10953 {60, 60, 60, 68},
10954 {60, 60, 68, 60},
10955 {120, 60, 128, 68},
10956 {60, 120, 68, 128},
10958 static RECT invalid[] =
10960 {68, 60, 60, 68}, /* left > right */
10961 {60, 68, 68, 60}, /* top > bottom */
10962 {-8, 60, 0, 68}, /* left < surface */
10963 {60, -8, 68, 0}, /* top < surface */
10964 {-16, 60, -8, 68}, /* right < surface */
10965 {60, -16, 68, -8}, /* bottom < surface */
10966 {60, 60, 136, 68}, /* right > surface */
10967 {60, 60, 68, 136}, /* bottom > surface */
10968 {136, 60, 144, 68}, /* left > surface */
10969 {60, 136, 68, 144}, /* top > surface */
10971 static const struct
10973 DWORD caps, caps2;
10974 const char *name;
10975 HRESULT hr;
10977 resources[] =
10979 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", DDERR_INVALIDPARAMS},
10980 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", DDERR_INVALIDPARAMS},
10981 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", DDERR_INVALIDPARAMS},
10982 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", DDERR_INVALIDPARAMS},
10983 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", DDERR_INVALIDPARAMS},
10986 window = create_window();
10987 ddraw = create_ddraw();
10988 ok(!!ddraw, "Failed to create a ddraw object.\n");
10989 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10990 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10992 memset(&hal_caps, 0, sizeof(hal_caps));
10993 hal_caps.dwSize = sizeof(hal_caps);
10994 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
10995 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
10996 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
10997 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
10999 skip("Required surface types not supported, skipping test.\n");
11000 goto done;
11003 for (r = 0; r < ARRAY_SIZE(resources); ++r)
11005 memset(&surface_desc, 0, sizeof(surface_desc));
11006 surface_desc.dwSize = sizeof(surface_desc);
11007 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11008 surface_desc.ddsCaps.dwCaps = resources[r].caps;
11009 surface_desc.ddsCaps.dwCaps2 = resources[r].caps2;
11010 surface_desc.dwWidth = 128;
11011 surface_desc.dwHeight = 128;
11012 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11013 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11014 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
11015 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xff0000;
11016 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x00ff00;
11017 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000ff;
11019 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11020 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, resources[r].name);
11022 hr = IDirectDrawSurface4_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
11023 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
11025 for (i = 0; i < ARRAY_SIZE(valid); ++i)
11027 RECT *rect = &valid[i];
11029 memset(&surface_desc, 0, sizeof(surface_desc));
11030 surface_desc.dwSize = sizeof(surface_desc);
11032 hr = IDirectDrawSurface4_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
11033 ok(SUCCEEDED(hr), "Lock failed (%#x) for rect %s, type %s.\n",
11034 hr, wine_dbgstr_rect(rect), resources[r].name);
11036 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11037 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11040 for (i = 0; i < ARRAY_SIZE(invalid); ++i)
11042 RECT *rect = &invalid[i];
11044 memset(&surface_desc, 1, sizeof(surface_desc));
11045 surface_desc.dwSize = sizeof(surface_desc);
11047 hr = IDirectDrawSurface4_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
11048 ok(hr == resources[r].hr, "Lock returned %#x for rect %s, type %s.\n",
11049 hr, wine_dbgstr_rect(rect), resources[r].name);
11050 if (SUCCEEDED(hr))
11052 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11053 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11055 else
11056 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
11059 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
11060 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#x, type %s.\n",
11061 hr, resources[r].name);
11062 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
11063 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#x, type %s.\n",
11064 hr, resources[r].name);
11065 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11066 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11068 hr = IDirectDrawSurface4_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
11069 ok(SUCCEEDED(hr), "Lock(rect = %s) failed (%#x).\n", wine_dbgstr_rect(&valid[0]), hr);
11070 hr = IDirectDrawSurface4_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
11071 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = %s) failed (%#x).\n",
11072 wine_dbgstr_rect(&valid[0]), hr);
11074 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
11075 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
11077 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11078 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11080 IDirectDrawSurface4_Release(surface);
11083 done:
11084 IDirectDraw4_Release(ddraw);
11085 DestroyWindow(window);
11088 static void test_yv12_overlay(void)
11090 IDirectDrawSurface4 *src_surface, *dst_surface;
11091 RECT rect = {13, 17, 14, 18};
11092 unsigned int offset, y;
11093 DDSURFACEDESC2 desc;
11094 unsigned char *base;
11095 IDirectDraw4 *ddraw;
11096 HWND window;
11097 HRESULT hr;
11099 window = create_window();
11100 ddraw = create_ddraw();
11101 ok(!!ddraw, "Failed to create a ddraw object.\n");
11102 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11103 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11105 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
11107 skip("Failed to create a YV12 overlay, skipping test.\n");
11108 goto done;
11111 memset(&desc, 0, sizeof(desc));
11112 desc.dwSize = sizeof(desc);
11113 hr = IDirectDrawSurface4_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
11114 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11116 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
11117 "Got unexpected flags %#x.\n", desc.dwFlags);
11118 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
11119 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
11120 "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps);
11121 ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth);
11122 ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight);
11123 /* The overlay pitch seems to have 256 byte alignment. */
11124 ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch);
11126 /* Fill the surface with some data for the blit test. */
11127 base = desc.lpSurface;
11128 /* Luminance */
11129 for (y = 0; y < desc.dwHeight; ++y)
11131 memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth);
11133 /* V */
11134 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
11136 memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth);
11138 /* U */
11139 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
11141 memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth);
11144 hr = IDirectDrawSurface4_Unlock(src_surface, NULL);
11145 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11147 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
11148 * other block-based formats like DXT the entire Y channel is stored in
11149 * one big chunk of memory, followed by the chroma channels. So partial
11150 * locks do not really make sense. Show that they are allowed nevertheless
11151 * and the offset points into the luminance data. */
11152 hr = IDirectDrawSurface4_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
11153 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11154 offset = ((const unsigned char *)desc.lpSurface - base);
11155 ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n",
11156 offset, rect.top * U1(desc).lPitch + rect.left);
11157 hr = IDirectDrawSurface4_Unlock(src_surface, NULL);
11158 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11160 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
11162 /* Windows XP with a Radeon X1600 GPU refuses to create a second
11163 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
11164 skip("Failed to create a second YV12 surface, skipping blit test.\n");
11165 IDirectDrawSurface4_Release(src_surface);
11166 goto done;
11169 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
11170 /* VMware rejects YV12 blits. This behavior has not been seen on real
11171 * hardware yet, so mark it broken. */
11172 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr);
11174 if (SUCCEEDED(hr))
11176 memset(&desc, 0, sizeof(desc));
11177 desc.dwSize = sizeof(desc);
11178 hr = IDirectDrawSurface4_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
11179 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11181 base = desc.lpSurface;
11182 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
11183 base += desc.dwHeight * U1(desc).lPitch;
11184 todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
11185 base += desc.dwHeight / 4 * U1(desc).lPitch;
11186 todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
11188 hr = IDirectDrawSurface4_Unlock(dst_surface, NULL);
11189 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11192 IDirectDrawSurface4_Release(dst_surface);
11193 IDirectDrawSurface4_Release(src_surface);
11194 done:
11195 IDirectDraw4_Release(ddraw);
11196 DestroyWindow(window);
11199 static BOOL dwm_enabled(void)
11201 BOOL ret = FALSE;
11203 if (!strcmp(winetest_platform, "wine"))
11204 return FALSE;
11205 if (!pDwmIsCompositionEnabled)
11206 return FALSE;
11207 if (FAILED(pDwmIsCompositionEnabled(&ret)))
11208 return FALSE;
11209 return ret;
11212 static void test_offscreen_overlay(void)
11214 IDirectDrawSurface4 *overlay, *offscreen, *primary;
11215 DDSURFACEDESC2 surface_desc;
11216 IDirectDraw4 *ddraw;
11217 HWND window;
11218 HRESULT hr;
11219 HDC dc;
11221 window = create_window();
11222 ddraw = create_ddraw();
11223 ok(!!ddraw, "Failed to create a ddraw object.\n");
11224 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11225 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11227 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
11229 skip("Failed to create a UYVY overlay, skipping test.\n");
11230 goto done;
11233 memset(&surface_desc, 0, sizeof(surface_desc));
11234 surface_desc.dwSize = sizeof(surface_desc);
11235 surface_desc.dwFlags = DDSD_CAPS;
11236 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
11237 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
11238 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
11240 /* On Windows 7, and probably Vista, UpdateOverlay() will return
11241 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
11242 * surface prevents this by disabling the dwm. */
11243 hr = IDirectDrawSurface4_GetDC(primary, &dc);
11244 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
11245 hr = IDirectDrawSurface4_ReleaseDC(primary, dc);
11246 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
11248 /* Try to overlay a NULL surface. */
11249 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
11250 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11251 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
11252 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11254 /* Try to overlay an offscreen surface. */
11255 memset(&surface_desc, 0, sizeof(surface_desc));
11256 surface_desc.dwSize = sizeof(surface_desc);
11257 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
11258 surface_desc.dwWidth = 64;
11259 surface_desc.dwHeight = 64;
11260 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11261 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11262 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11263 U4(surface_desc).ddpfPixelFormat.dwFourCC = 0;
11264 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
11265 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
11266 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
11267 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
11268 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
11269 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
11271 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
11272 ok(SUCCEEDED(hr) || broken(hr == DDERR_OUTOFCAPS && dwm_enabled())
11273 || broken(hr == E_NOTIMPL && ddraw_is_vmware(ddraw)),
11274 "Failed to update overlay, hr %#x.\n", hr);
11276 /* Try to overlay the primary with a non-overlay surface. */
11277 hr = IDirectDrawSurface4_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
11278 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
11279 hr = IDirectDrawSurface4_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_HIDE, NULL);
11280 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
11282 IDirectDrawSurface4_Release(offscreen);
11283 IDirectDrawSurface4_Release(primary);
11284 IDirectDrawSurface4_Release(overlay);
11285 done:
11286 IDirectDraw4_Release(ddraw);
11287 DestroyWindow(window);
11290 static void test_overlay_rect(void)
11292 IDirectDrawSurface4 *overlay, *primary = NULL;
11293 DDSURFACEDESC2 surface_desc;
11294 RECT rect = {0, 0, 64, 64};
11295 IDirectDraw4 *ddraw;
11296 LONG pos_x, pos_y;
11297 HRESULT hr, hr2;
11298 HWND window;
11299 HDC dc;
11301 window = create_window();
11302 ddraw = create_ddraw();
11303 ok(!!ddraw, "Failed to create a ddraw object.\n");
11304 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11305 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11307 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
11309 skip("Failed to create a UYVY overlay, skipping test.\n");
11310 goto done;
11313 memset(&surface_desc, 0, sizeof(surface_desc));
11314 surface_desc.dwSize = sizeof(surface_desc);
11315 surface_desc.dwFlags = DDSD_CAPS;
11316 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
11317 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
11318 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
11320 /* On Windows 7, and probably Vista, UpdateOverlay() will return
11321 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
11322 * surface prevents this by disabling the dwm. */
11323 hr = IDirectDrawSurface4_GetDC(primary, &dc);
11324 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
11325 hr = IDirectDrawSurface4_ReleaseDC(primary, dc);
11326 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
11328 /* On Windows 8 and newer DWM can't be turned off, making overlays unusable. */
11329 if (dwm_enabled())
11331 win_skip("Cannot disable DWM, skipping overlay test.\n");
11332 goto done;
11335 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is
11336 * used. This is not true in Windows Vista and earlier, but changed in
11337 * Windows 7. */
11338 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
11339 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11340 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
11341 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11342 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
11343 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11345 /* Show that the overlay position is the (top, left) coordinate of the
11346 * destination rectangle. */
11347 OffsetRect(&rect, 32, 16);
11348 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
11349 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11350 pos_x = -1; pos_y = -1;
11351 hr = IDirectDrawSurface4_GetOverlayPosition(overlay, &pos_x, &pos_y);
11352 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
11353 ok(pos_x == rect.left, "Got unexpected pos_x %d, expected %d.\n", pos_x, rect.left);
11354 ok(pos_y == rect.top, "Got unexpected pos_y %d, expected %d.\n", pos_y, rect.top);
11356 /* Passing a NULL dest rect sets the position to 0/0. Visually it can be
11357 * seen that the overlay overlays the whole primary(==screen). */
11358 hr2 = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
11359 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS || hr2 == DDERR_OUTOFCAPS, "Got unexpected hr %#x.\n", hr2);
11360 hr = IDirectDrawSurface4_GetOverlayPosition(overlay, &pos_x, &pos_y);
11361 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
11362 if (SUCCEEDED(hr2))
11364 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
11365 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
11367 else
11369 ok(pos_x == 32, "Got unexpected pos_x %d.\n", pos_x);
11370 ok(pos_y == 16, "Got unexpected pos_y %d.\n", pos_y);
11373 /* The position cannot be retrieved when the overlay is not shown. */
11374 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
11375 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11376 pos_x = -1; pos_y = -1;
11377 hr = IDirectDrawSurface4_GetOverlayPosition(overlay, &pos_x, &pos_y);
11378 ok(hr == DDERR_OVERLAYNOTVISIBLE, "Got unexpected hr %#x.\n", hr);
11379 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
11380 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
11382 IDirectDrawSurface4_Release(overlay);
11383 done:
11384 if (primary)
11385 IDirectDrawSurface4_Release(primary);
11386 IDirectDraw4_Release(ddraw);
11387 DestroyWindow(window);
11390 static void test_blt(void)
11392 IDirectDrawSurface4 *surface, *rt;
11393 DDSURFACEDESC2 surface_desc;
11394 IDirect3DDevice3 *device;
11395 IDirectDraw4 *ddraw;
11396 IDirect3D3 *d3d;
11397 unsigned int i;
11398 ULONG refcount;
11399 HWND window;
11400 HRESULT hr;
11402 static struct
11404 RECT src_rect;
11405 RECT dst_rect;
11406 HRESULT hr;
11408 test_data[] =
11410 {{160, 0, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit. */
11411 {{160, 480, 640, 0}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, flipped source. */
11412 {{640, 0, 160, 480}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, mirrored source. */
11413 {{160, 0, 480, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched x. */
11414 {{160, 160, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched y. */
11415 {{ 0, 0, 640, 480}, { 0, 0, 640, 480}, DD_OK}, /* Full surface blit. */
11416 {{ 0, 0, 640, 480}, { 0, 480, 640, 0}, DDERR_INVALIDRECT}, /* Full surface, flipped destination. */
11417 {{ 0, 0, 640, 480}, {640, 0, 0, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored destination. */
11418 {{ 0, 480, 640, 0}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, flipped source. */
11419 {{640, 0, 0, 480}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored source. */
11422 window = create_window();
11423 if (!(device = create_device(window, DDSCL_NORMAL)))
11425 skip("Failed to create a 3D device, skipping test.\n");
11426 DestroyWindow(window);
11427 return;
11430 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
11431 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
11432 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
11433 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
11434 IDirect3D3_Release(d3d);
11435 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
11436 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11438 memset(&surface_desc, 0, sizeof(surface_desc));
11439 surface_desc.dwSize = sizeof(surface_desc);
11440 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
11441 surface_desc.dwWidth = 640;
11442 surface_desc.dwHeight = 480;
11443 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11444 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11445 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11447 hr = IDirectDrawSurface4_Blt(surface, NULL, surface, NULL, 0, NULL);
11448 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
11450 hr = IDirectDrawSurface4_Blt(surface, NULL, rt, NULL, 0, NULL);
11451 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
11453 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
11455 hr = IDirectDrawSurface4_Blt(surface, &test_data[i].dst_rect,
11456 surface, &test_data[i].src_rect, DDBLT_WAIT, NULL);
11457 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
11459 hr = IDirectDrawSurface4_Blt(surface, &test_data[i].dst_rect,
11460 rt, &test_data[i].src_rect, DDBLT_WAIT, NULL);
11461 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
11463 hr = IDirectDrawSurface4_Blt(surface, &test_data[i].dst_rect,
11464 NULL, &test_data[i].src_rect, DDBLT_WAIT, NULL);
11465 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
11467 hr = IDirectDrawSurface4_Blt(surface, &test_data[i].dst_rect, NULL, NULL, DDBLT_WAIT, NULL);
11468 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
11471 IDirectDrawSurface4_Release(surface);
11472 IDirectDrawSurface4_Release(rt);
11473 IDirectDraw4_Release(ddraw);
11474 refcount = IDirect3DDevice3_Release(device);
11475 ok(!refcount, "Device has %u references left.\n", refcount);
11476 DestroyWindow(window);
11479 static void test_blt_z_alpha(void)
11481 DWORD blt_flags[] =
11483 /* 0 */
11484 DDBLT_ALPHADEST,
11485 DDBLT_ALPHADESTCONSTOVERRIDE,
11486 DDBLT_ALPHADESTNEG,
11487 DDBLT_ALPHADESTSURFACEOVERRIDE,
11488 DDBLT_ALPHAEDGEBLEND,
11489 /* 5 */
11490 DDBLT_ALPHASRC,
11491 DDBLT_ALPHASRCCONSTOVERRIDE,
11492 DDBLT_ALPHASRCNEG,
11493 DDBLT_ALPHASRCSURFACEOVERRIDE,
11494 DDBLT_ZBUFFER,
11495 /* 10 */
11496 DDBLT_ZBUFFERDESTCONSTOVERRIDE,
11497 DDBLT_ZBUFFERDESTOVERRIDE,
11498 DDBLT_ZBUFFERSRCCONSTOVERRIDE,
11499 DDBLT_ZBUFFERSRCOVERRIDE,
11501 IDirectDrawSurface4 *src_surface, *dst_surface;
11502 DDSURFACEDESC2 surface_desc;
11503 IDirectDraw4 *ddraw;
11504 DDPIXELFORMAT pf;
11505 ULONG refcount;
11506 unsigned int i;
11507 D3DCOLOR color;
11508 HWND window;
11509 HRESULT hr;
11510 DDBLTFX fx;
11512 window = create_window();
11513 ddraw = create_ddraw();
11514 ok(!!ddraw, "Failed to create a ddraw object.\n");
11515 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11516 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11518 memset(&pf, 0, sizeof(pf));
11519 pf.dwSize = sizeof(pf);
11520 pf.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
11521 U1(pf).dwRGBBitCount = 32;
11522 U2(pf).dwRBitMask = 0x00ff0000;
11523 U3(pf).dwGBitMask = 0x0000ff00;
11524 U4(pf).dwBBitMask = 0x000000ff;
11525 U5(pf).dwRGBAlphaBitMask = 0xff000000;
11527 memset(&surface_desc, 0, sizeof(surface_desc));
11528 surface_desc.dwSize = sizeof(surface_desc);
11529 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
11530 surface_desc.dwWidth = 64;
11531 surface_desc.dwHeight = 64;
11532 U4(surface_desc).ddpfPixelFormat = pf;
11533 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11535 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
11536 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
11537 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
11538 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
11540 memset(&fx, 0, sizeof(fx));
11541 fx.dwSize = sizeof(fx);
11542 fx.dwZBufferOpCode = D3DCMP_NEVER;
11543 fx.dwZDestConstBitDepth = 32;
11544 U1(fx).dwZDestConst = 0x11111111;
11545 fx.dwZSrcConstBitDepth = 32;
11546 U2(fx).dwZSrcConst = 0xeeeeeeee;
11547 fx.dwAlphaEdgeBlendBitDepth = 8;
11548 fx.dwAlphaEdgeBlend = 0x7f;
11549 fx.dwAlphaDestConstBitDepth = 8;
11550 U3(fx).dwAlphaDestConst = 0xdd;
11551 fx.dwAlphaSrcConstBitDepth = 8;
11552 U4(fx).dwAlphaSrcConst = 0x22;
11554 for (i = 0; i < ARRAY_SIZE(blt_flags); ++i)
11556 fx.dwFillColor = 0x3300ff00;
11557 hr = IDirectDrawSurface4_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11558 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
11560 fx.dwFillColor = 0xccff0000;
11561 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11562 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
11564 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, src_surface, NULL, blt_flags[i] | DDBLT_WAIT, &fx);
11565 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
11567 color = get_surface_color(dst_surface, 32, 32);
11568 ok(compare_color(color, 0x0000ff00, 0), "Test %u: Got unexpected color 0x%08x.\n", i, color);
11571 IDirectDrawSurface4_Release(dst_surface);
11572 IDirectDrawSurface4_Release(src_surface);
11573 refcount = IDirectDraw4_Release(ddraw);
11574 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
11575 DestroyWindow(window);
11578 static void test_color_clamping(void)
11580 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
11581 static D3DMATRIX mat =
11583 1.0f, 0.0f, 0.0f, 0.0f,
11584 0.0f, 1.0f, 0.0f, 0.0f,
11585 0.0f, 0.0f, 1.0f, 0.0f,
11586 0.0f, 0.0f, 0.0f, 1.0f,
11588 static struct vec3 quad[] =
11590 {-1.0f, -1.0f, 0.1f},
11591 {-1.0f, 1.0f, 0.1f},
11592 { 1.0f, -1.0f, 0.1f},
11593 { 1.0f, 1.0f, 0.1f},
11595 IDirect3DViewport3 *viewport;
11596 IDirect3DDevice3 *device;
11597 IDirectDrawSurface4 *rt;
11598 ULONG refcount;
11599 D3DCOLOR color;
11600 HWND window;
11601 HRESULT hr;
11603 window = create_window();
11604 if (!(device = create_device(window, DDSCL_NORMAL)))
11606 skip("Failed to create a 3D device, skipping test.\n");
11607 DestroyWindow(window);
11608 return;
11611 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
11612 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11614 viewport = create_viewport(device, 0, 0, 640, 480);
11615 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
11616 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
11618 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
11619 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
11620 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
11621 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
11622 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
11623 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
11624 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
11625 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
11626 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
11627 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
11628 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
11629 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
11630 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
11631 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
11632 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
11633 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
11634 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
11635 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
11637 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0xff404040);
11638 ok(SUCCEEDED(hr), "Failed to set texture factor, hr %#x.\n", hr);
11639 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_ADD);
11640 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11641 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
11642 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11643 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_SPECULAR);
11644 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11645 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_MODULATE);
11646 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11647 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TFACTOR);
11648 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11649 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
11650 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11652 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
11653 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
11655 hr = IDirect3DDevice3_BeginScene(device);
11656 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11658 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
11659 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11661 hr = IDirect3DDevice3_EndScene(device);
11662 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11664 color = get_surface_color(rt, 320, 240);
11665 ok(compare_color(color, 0x00404040, 1), "Got unexpected color 0x%08x.\n", color);
11667 destroy_viewport(device, viewport);
11668 IDirectDrawSurface4_Release(rt);
11669 refcount = IDirect3DDevice3_Release(device);
11670 ok(!refcount, "Device has %u references left.\n", refcount);
11671 DestroyWindow(window);
11674 static void test_getdc(void)
11676 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
11677 IDirectDrawSurface4 *surface, *surface2, *tmp;
11678 DDSURFACEDESC2 surface_desc, map_desc;
11679 IDirectDraw4 *ddraw;
11680 unsigned int i;
11681 HWND window;
11682 HDC dc, dc2;
11683 HRESULT hr;
11685 static const struct
11687 const char *name;
11688 DDPIXELFORMAT format;
11689 BOOL getdc_supported;
11690 HRESULT alt_result;
11692 test_data[] =
11694 {"D3DFMT_A8R8G8B8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11695 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}}, TRUE},
11696 {"D3DFMT_X8R8G8B8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
11697 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}}, TRUE},
11698 {"D3DFMT_R5G6B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11699 {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}}, TRUE},
11700 {"D3DFMT_X1R5G5B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11701 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}}, TRUE},
11702 {"D3DFMT_A1R5G5B5", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
11703 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}}, TRUE},
11704 {"D3DFMT_A4R4G4B4", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
11705 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11706 {"D3DFMT_X4R4G4B4", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11707 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11708 {"D3DFMT_A2R10G10B10", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11709 {0xc0000000}, {0x3ff00000}, {0x000ffc00}, {0x000003ff}}, TRUE},
11710 {"D3DFMT_A8B8G8R8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11711 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11712 {"D3DFMT_X8B8G8R8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
11713 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11714 {"D3DFMT_R3G3B2", {sizeof(test_data->format), DDPF_RGB, 0, {8},
11715 {0x000000e0}, {0x0000001c}, {0x00000003}, {0x00000000}}, FALSE},
11716 /* GetDC() on a P8 surface fails unless the display mode is 8 bpp.
11717 * This is not implemented in wine yet, so disable the test for now.
11718 * Succeeding P8 GetDC() calls are tested in the ddraw:visual test.
11719 {"D3DFMT_P8", {sizeof(test_data->format), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0, {8 },
11720 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11722 {"D3DFMT_L8", {sizeof(test_data->format), DDPF_LUMINANCE, 0, {8},
11723 {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11724 {"D3DFMT_A8L8", {sizeof(test_data->format), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0, {16},
11725 {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}}, FALSE},
11726 {"D3DFMT_DXT1", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'), {0},
11727 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11728 {"D3DFMT_DXT2", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'), {0},
11729 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11730 {"D3DFMT_DXT3", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'), {0},
11731 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11732 {"D3DFMT_DXT4", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'), {0},
11733 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11734 {"D3DFMT_DXT5", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'), {0},
11735 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11738 window = create_window();
11739 ddraw = create_ddraw();
11740 ok(!!ddraw, "Failed to create a ddraw object.\n");
11741 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11742 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11744 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
11746 memset(&surface_desc, 0, sizeof(surface_desc));
11747 surface_desc.dwSize = sizeof(surface_desc);
11748 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11749 surface_desc.dwWidth = 64;
11750 surface_desc.dwHeight = 64;
11751 U4(surface_desc).ddpfPixelFormat = test_data[i].format;
11752 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11754 if (FAILED(IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11756 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11757 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
11758 if (FAILED(hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11760 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
11761 continue;
11765 dc = (void *)0x1234;
11766 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11767 if (test_data[i].getdc_supported)
11768 ok(SUCCEEDED(hr) || broken(hr == test_data[i].alt_result),
11769 "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11770 else
11771 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11773 if (SUCCEEDED(hr))
11775 unsigned int width_bytes;
11776 DIBSECTION dib;
11777 HBITMAP bitmap;
11778 DWORD type;
11779 int size;
11781 type = GetObjectType(dc);
11782 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
11783 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
11784 type = GetObjectType(bitmap);
11785 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
11787 size = GetObjectA(bitmap, sizeof(dib), &dib);
11788 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, test_data[i].name);
11789 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
11790 dib.dsBm.bmType, test_data[i].name);
11791 ok(dib.dsBm.bmWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
11792 dib.dsBm.bmWidth, test_data[i].name);
11793 ok(dib.dsBm.bmHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
11794 dib.dsBm.bmHeight, test_data[i].name);
11795 width_bytes = ((dib.dsBm.bmWidth * U1(test_data[i].format).dwRGBBitCount + 31) >> 3) & ~3;
11796 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
11797 dib.dsBm.bmWidthBytes, test_data[i].name);
11798 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
11799 dib.dsBm.bmPlanes, test_data[i].name);
11800 ok(dib.dsBm.bmBitsPixel == U1(test_data[i].format).dwRGBBitCount,
11801 "Got unexpected bit count %d for format %s.\n",
11802 dib.dsBm.bmBitsPixel, test_data[i].name);
11803 ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n",
11804 dib.dsBm.bmBits, test_data[i].name);
11806 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
11807 dib.dsBmih.biSize, test_data[i].name);
11808 ok(dib.dsBmih.biWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
11809 dib.dsBmih.biHeight, test_data[i].name);
11810 ok(dib.dsBmih.biHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
11811 dib.dsBmih.biHeight, test_data[i].name);
11812 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
11813 dib.dsBmih.biPlanes, test_data[i].name);
11814 ok(dib.dsBmih.biBitCount == U1(test_data[i].format).dwRGBBitCount,
11815 "Got unexpected bit count %u for format %s.\n",
11816 dib.dsBmih.biBitCount, test_data[i].name);
11817 ok(dib.dsBmih.biCompression == (U1(test_data[i].format).dwRGBBitCount == 16 ? BI_BITFIELDS : BI_RGB)
11818 || broken(U1(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
11819 "Got unexpected compression %#x for format %s.\n",
11820 dib.dsBmih.biCompression, test_data[i].name);
11821 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
11822 dib.dsBmih.biSizeImage, test_data[i].name);
11823 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
11824 dib.dsBmih.biXPelsPerMeter, test_data[i].name);
11825 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
11826 dib.dsBmih.biYPelsPerMeter, test_data[i].name);
11827 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
11828 dib.dsBmih.biClrUsed, test_data[i].name);
11829 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
11830 dib.dsBmih.biClrImportant, test_data[i].name);
11832 if (dib.dsBmih.biCompression == BI_BITFIELDS)
11834 ok((dib.dsBitfields[0] == U2(test_data[i].format).dwRBitMask
11835 && dib.dsBitfields[1] == U3(test_data[i].format).dwGBitMask
11836 && dib.dsBitfields[2] == U4(test_data[i].format).dwBBitMask)
11837 || broken(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2]),
11838 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
11839 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
11841 else
11843 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
11844 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
11845 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
11847 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, test_data[i].name);
11848 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, test_data[i].name);
11850 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11851 ok(hr == DD_OK, "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11853 else
11855 ok(!dc, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
11858 IDirectDrawSurface4_Release(surface);
11860 if (FAILED(hr))
11861 continue;
11863 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
11864 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
11865 if (FAILED(hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11867 skip("Failed to create mip-mapped texture for format %s (hr %#x), skipping tests.\n",
11868 test_data[i].name, hr);
11869 continue;
11872 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &tmp);
11873 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
11874 hr = IDirectDrawSurface4_GetAttachedSurface(tmp, &caps, &surface2);
11875 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
11876 IDirectDrawSurface4_Release(tmp);
11878 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11879 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11880 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11881 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11882 hr = IDirectDrawSurface4_GetDC(surface2, &dc);
11883 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11884 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc);
11885 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11887 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11888 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11889 dc2 = (void *)0x1234;
11890 hr = IDirectDrawSurface4_GetDC(surface, &dc2);
11891 ok(hr == DDERR_DCALREADYCREATED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11892 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
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_ReleaseDC(surface, dc);
11896 ok(hr == DDERR_NODC, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11898 map_desc.dwSize = sizeof(map_desc);
11899 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11900 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11901 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11902 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11903 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11904 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11905 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11906 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11908 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11909 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11910 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11911 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11912 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11913 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11915 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11916 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11917 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11918 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11919 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11920 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11921 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11922 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11924 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11925 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11926 hr = IDirectDrawSurface4_GetDC(surface2, &dc2);
11927 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11928 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc2);
11929 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11930 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11931 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11933 hr = IDirectDrawSurface4_GetDC(surface2, &dc);
11934 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11935 hr = IDirectDrawSurface4_GetDC(surface, &dc2);
11936 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11937 hr = IDirectDrawSurface4_ReleaseDC(surface, dc2);
11938 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11939 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc);
11940 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11942 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11943 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11944 hr = IDirectDrawSurface4_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11945 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11946 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
11947 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11948 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11949 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11951 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11952 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11953 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11954 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11955 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11956 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11957 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11958 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11960 hr = IDirectDrawSurface4_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11961 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11962 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11963 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11964 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11965 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11966 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
11967 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11969 hr = IDirectDrawSurface4_GetDC(surface, &dc);
11970 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11971 hr = IDirectDrawSurface4_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11972 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11973 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
11974 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11975 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
11976 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11978 hr = IDirectDrawSurface4_GetDC(surface2, &dc);
11979 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11980 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11981 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11982 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11983 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11984 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc);
11985 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11987 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11988 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11989 hr = IDirectDrawSurface4_GetDC(surface2, &dc);
11990 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11991 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11992 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11993 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc);
11994 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11995 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11996 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11998 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
11999 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12000 hr = IDirectDrawSurface4_GetDC(surface, &dc);
12001 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12002 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
12003 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12004 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
12005 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12006 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
12007 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12009 IDirectDrawSurface4_Release(surface2);
12010 IDirectDrawSurface4_Release(surface);
12013 IDirectDraw4_Release(ddraw);
12014 DestroyWindow(window);
12017 static void test_draw_primitive(void)
12019 static WORD indices[] = {0, 1, 2, 3};
12020 static struct vec3 quad[] =
12022 {-1.0f, -1.0f, 0.0f},
12023 {-1.0f, 1.0f, 0.0f},
12024 { 1.0f, -1.0f, 0.0f},
12025 { 1.0f, 1.0f, 0.0f},
12027 D3DDRAWPRIMITIVESTRIDEDDATA strided;
12028 IDirect3DViewport3 *viewport;
12029 D3DVERTEXBUFFERDESC vb_desc;
12030 IDirect3DVertexBuffer *vb;
12031 IDirect3DDevice3 *device;
12032 IDirect3D3 *d3d;
12033 ULONG refcount;
12034 HWND window;
12035 HRESULT hr;
12036 void *data;
12038 window = create_window();
12039 if (!(device = create_device(window, DDSCL_NORMAL)))
12041 skip("Failed to create a 3D device, skipping test.\n");
12042 DestroyWindow(window);
12043 return;
12046 viewport = create_viewport(device, 0, 0, 640, 480);
12047 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
12048 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
12050 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
12051 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
12053 memset(&vb_desc, 0, sizeof(vb_desc));
12054 vb_desc.dwSize = sizeof(vb_desc);
12055 vb_desc.dwFVF = D3DFVF_XYZ;
12056 vb_desc.dwNumVertices = 4;
12057 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &vb, 0, NULL);
12058 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
12060 IDirect3D3_Release(d3d);
12062 memset(&strided, 0, sizeof(strided));
12064 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, NULL, 0, 0);
12065 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12066 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device,
12067 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, NULL, 0, 0);
12068 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12069 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, NULL, 0, 0);
12070 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12071 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, 0);
12072 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12073 hr = IDirect3DDevice3_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, 0);
12074 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12075 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, 0);
12076 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12078 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, indices, 4, 0);
12079 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12080 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device,
12081 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, indices, 4, 0);
12082 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12083 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, indices, 4, 0);
12084 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12086 strided.position.lpvData = quad;
12087 strided.position.dwStride = sizeof(*quad);
12088 hr = IDirect3DVertexBuffer_Lock(vb, 0, &data, NULL);
12089 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
12090 memcpy(data, quad, sizeof(quad));
12091 hr = IDirect3DVertexBuffer_Unlock(vb);
12092 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
12094 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, NULL, 0, 0);
12095 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12096 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device,
12097 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, NULL, 0, 0);
12098 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12099 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, NULL, 0, 0);
12100 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12101 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
12102 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12103 hr = IDirect3DDevice3_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, 0);
12104 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12105 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
12106 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12107 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, indices, 4, 0);
12108 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12109 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device,
12110 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, indices, 4, 0);
12111 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12112 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, indices, 4, 0);
12113 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12115 IDirect3DVertexBuffer_Release(vb);
12116 destroy_viewport(device, viewport);
12117 refcount = IDirect3DDevice3_Release(device);
12118 ok(!refcount, "Device has %u references left.\n", refcount);
12119 DestroyWindow(window);
12122 static void test_edge_antialiasing_blending(void)
12124 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
12125 IDirectDrawSurface4 *offscreen, *ds;
12126 D3DDEVICEDESC hal_desc, hel_desc;
12127 IDirect3DViewport3 *viewport;
12128 DDSURFACEDESC2 surface_desc;
12129 IDirect3DDevice3 *device;
12130 IDirectDraw4 *ddraw;
12131 IDirect3D3 *d3d;
12132 ULONG refcount;
12133 D3DCOLOR color;
12134 HWND window;
12135 HRESULT hr;
12137 static D3DMATRIX mat =
12139 1.0f, 0.0f, 0.0f, 0.0f,
12140 0.0f, 1.0f, 0.0f, 0.0f,
12141 0.0f, 0.0f, 1.0f, 0.0f,
12142 0.0f, 0.0f, 0.0f, 1.0f,
12144 static struct
12146 struct vec3 position;
12147 DWORD diffuse;
12149 green_quad[] =
12151 {{-1.0f, -1.0f, 0.1f}, 0x7f00ff00},
12152 {{-1.0f, 1.0f, 0.1f}, 0x7f00ff00},
12153 {{ 1.0f, -1.0f, 0.1f}, 0x7f00ff00},
12154 {{ 1.0f, 1.0f, 0.1f}, 0x7f00ff00},
12156 static struct
12158 struct vec3 position;
12159 DWORD diffuse;
12161 red_quad[] =
12163 {{-1.0f, -1.0f, 0.1f}, 0xccff0000},
12164 {{-1.0f, 1.0f, 0.1f}, 0xccff0000},
12165 {{ 1.0f, -1.0f, 0.1f}, 0xccff0000},
12166 {{ 1.0f, 1.0f, 0.1f}, 0xccff0000},
12169 window = create_window();
12170 if (!(device = create_device(window, DDSCL_NORMAL)))
12172 skip("Failed to create a 3D device.\n");
12173 DestroyWindow(window);
12174 return;
12177 memset(&hal_desc, 0, sizeof(hal_desc));
12178 hal_desc.dwSize = sizeof(hal_desc);
12179 memset(&hel_desc, 0, sizeof(hel_desc));
12180 hel_desc.dwSize = sizeof(hel_desc);
12181 hr = IDirect3DDevice3_GetCaps(device, &hal_desc, &hel_desc);
12182 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
12183 trace("HAL line edge antialiasing support: %#x.\n",
12184 hal_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12185 trace("HAL triangle edge antialiasing support: %#x.\n",
12186 hal_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12187 trace("HEL line edge antialiasing support: %#x.\n",
12188 hel_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12189 trace("HEL triangle edge antialiasing support: %#x.\n",
12190 hel_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12192 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
12193 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
12194 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
12195 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
12196 IDirect3D3_Release(d3d);
12198 memset(&surface_desc, 0, sizeof(surface_desc));
12199 surface_desc.dwSize = sizeof(surface_desc);
12200 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
12201 surface_desc.dwWidth = 640;
12202 surface_desc.dwHeight = 480;
12203 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
12204 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
12205 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
12206 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
12207 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
12208 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
12209 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
12210 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
12211 ok(hr == D3D_OK, "Creating the offscreen render target failed, hr %#x.\n", hr);
12213 ds = get_depth_stencil(device);
12214 hr = IDirectDrawSurface_AddAttachedSurface(offscreen, ds);
12215 todo_wine ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
12216 IDirectDrawSurface_Release(ds);
12218 hr = IDirect3DDevice3_SetRenderTarget(device, offscreen, 0);
12219 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
12221 viewport = create_viewport(device, 0, 0, 640, 480);
12222 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
12223 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
12225 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
12226 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12227 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
12228 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
12229 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
12230 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
12231 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
12232 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
12233 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
12234 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
12235 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
12236 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
12237 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
12238 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
12239 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
12240 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
12241 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
12242 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
12244 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
12245 ok(SUCCEEDED(hr), "Failed to enable blending, hr %#x.\n", hr);
12246 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
12247 ok(SUCCEEDED(hr), "Failed to set src blend, hr %#x.\n", hr);
12248 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
12249 ok(SUCCEEDED(hr), "Failed to set dest blend, hr %#x.\n", hr);
12251 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
12252 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
12253 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
12254 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12255 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
12256 ok(SUCCEEDED(hr), "Failed to set alpha op, hr %#x.\n", hr);
12257 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
12258 ok(SUCCEEDED(hr), "Failed to set alpha arg, hr %#x.\n", hr);
12260 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
12261 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12262 hr = IDirect3DDevice3_BeginScene(device);
12263 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12264 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12265 green_quad, 4, 0);
12266 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12267 hr = IDirect3DDevice3_EndScene(device);
12268 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12269 color = get_surface_color(offscreen, 320, 240);
12270 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
12272 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
12273 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12274 hr = IDirect3DDevice3_BeginScene(device);
12275 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12276 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12277 red_quad, 4, 0);
12278 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12279 hr = IDirect3DDevice3_EndScene(device);
12280 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12281 color = get_surface_color(offscreen, 320, 240);
12282 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
12284 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
12285 ok(SUCCEEDED(hr), "Failed to disable blending, hr %#x.\n", hr);
12287 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
12288 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12289 hr = IDirect3DDevice3_BeginScene(device);
12290 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12291 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12292 green_quad, 4, 0);
12293 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12294 hr = IDirect3DDevice3_EndScene(device);
12295 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12296 color = get_surface_color(offscreen, 320, 240);
12297 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12299 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
12300 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12301 hr = IDirect3DDevice3_BeginScene(device);
12302 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12303 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12304 red_quad, 4, 0);
12305 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12306 hr = IDirect3DDevice3_EndScene(device);
12307 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12308 color = get_surface_color(offscreen, 320, 240);
12309 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12311 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_EDGEANTIALIAS, TRUE);
12312 ok(SUCCEEDED(hr), "Failed to enable edge antialiasing, hr %#x.\n", hr);
12314 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
12315 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12316 hr = IDirect3DDevice3_BeginScene(device);
12317 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12318 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12319 green_quad, 4, 0);
12320 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12321 hr = IDirect3DDevice3_EndScene(device);
12322 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12323 color = get_surface_color(offscreen, 320, 240);
12324 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12326 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
12327 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12328 hr = IDirect3DDevice3_BeginScene(device);
12329 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12330 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12331 red_quad, 4, 0);
12332 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12333 hr = IDirect3DDevice3_EndScene(device);
12334 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12335 color = get_surface_color(offscreen, 320, 240);
12336 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12338 IDirectDrawSurface4_Release(offscreen);
12339 IDirectDraw3_Release(ddraw);
12340 destroy_viewport(device, viewport);
12341 refcount = IDirect3DDevice3_Release(device);
12342 ok(!refcount, "Device has %u references left.\n", refcount);
12343 DestroyWindow(window);
12346 /* TransformVertices always writes 32 bytes regardless of the input / output stride.
12347 * The stride is honored for navigating to the next vertex. 3 floats input position
12348 * are read, and 16 bytes extra vertex data are copied around. */
12349 struct transform_input
12351 float x, y, z, unused1; /* Position data, transformed. */
12352 DWORD v1, v2, v3, v4; /* Extra data, e.g. color and texture coords, copied. */
12353 DWORD unused2;
12356 struct transform_output
12358 float x, y, z, w;
12359 DWORD v1, v2, v3, v4;
12360 DWORD unused3, unused4;
12363 static void test_transform_vertices(void)
12365 IDirect3DDevice3 *device;
12366 IDirectDrawSurface4 *rt;
12367 ULONG refcount;
12368 HWND window;
12369 HRESULT hr;
12370 D3DCOLOR color;
12371 IDirect3DViewport3 *viewport;
12372 static struct transform_input position_tests[] =
12374 { 0.0f, 0.0f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
12375 { 1.0f, 1.0f, 1.0f, 8.0f, 6, 7, 8, 9, 10},
12376 {-1.0f, -1.0f, -1.0f, 4.0f, 11, 12, 13, 14, 15},
12377 { 0.5f, 0.5f, 0.5f, 2.0f, 16, 17, 18, 19, 20},
12378 {-0.5f, -0.5f, -0.5f, 1.0f, ~1U, ~2U, ~3U, ~4U, ~5U},
12379 {-0.5f, -0.5f, 0.0f, 0.0f, ~6U, ~7U, ~8U, ~9U, ~0U},
12381 static struct transform_input cliptest[] =
12383 { 25.59f, 25.59f, 1.0f, 0.0f, 1, 2, 3, 4, 5},
12384 { 25.61f, 25.61f, 1.01f, 0.0f, 1, 2, 3, 4, 5},
12385 {-25.59f, -25.59f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
12386 {-25.61f, -25.61f, -0.01f, 0.0f, 1, 2, 3, 4, 5},
12388 static struct transform_input offscreentest[] =
12390 {128.1f, 0.0f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
12392 struct transform_output out[ARRAY_SIZE(position_tests)];
12393 D3DHVERTEX out_h[ARRAY_SIZE(position_tests)];
12394 D3DTRANSFORMDATA transformdata;
12395 static const D3DVIEWPORT vp_template =
12397 sizeof(vp_template), 0, 0, 256, 256, 5.0f, 5.0f, 256.0f, 256.0f, -25.0f, 60.0f
12399 D3DVIEWPORT vp_data =
12401 sizeof(vp_data), 0, 0, 256, 256, 1.0f, 1.0f, 256.0f, 256.0f, 0.0f, 1.0f
12403 D3DVIEWPORT2 vp2_data;
12404 unsigned int i;
12405 DWORD offscreen;
12406 static D3DMATRIX mat_scale =
12408 2.0f, 0.0f, 0.0f, 0.0f,
12409 0.0f, 2.0f, 0.0f, 0.0f,
12410 0.0f, 0.0f, 2.0f, 0.0f,
12411 0.0f, 0.0f, 0.0f, 1.0f,
12413 mat_translate1 =
12415 1.0f, 0.0f, 0.0f, 0.0f,
12416 0.0f, 1.0f, 0.0f, 0.0f,
12417 0.0f, 0.0f, 1.0f, 0.0f,
12418 1.0f, 0.0f, 0.0f, 1.0f,
12420 mat_translate2 =
12422 1.0f, 0.0f, 0.0f, 0.0f,
12423 0.0f, 1.0f, 0.0f, 0.0f,
12424 0.0f, 0.0f, 1.0f, 0.0f,
12425 0.0f, 1.0f, 0.0f, 1.0f,
12427 mat_transform3 =
12429 1.0f, 0.0f, 0.0f, 0.0f,
12430 0.0f, 1.0f, 0.0f, 0.0f,
12431 0.0f, 0.0f, 1.0f, 0.0f,
12432 0.0f, 19.2f, 0.0f, 2.0f,
12434 mat_identity =
12436 1.0f, 0.0f, 0.0f, 0.0f,
12437 0.0f, 1.0f, 0.0f, 0.0f,
12438 0.0f, 0.0f, 1.0f, 0.0f,
12439 0.0f, 0.0f, 0.0f, 1.0f,
12441 static struct
12443 struct vec3 position;
12444 DWORD color;
12446 quad[] =
12448 {{-0.75f, -0.5f , 0.0f}, 0xffff0000},
12449 {{-0.75f, 0.25f, 0.0f}, 0xffff0000},
12450 {{ 0.5f, -0.5f , 0.0f}, 0xffff0000},
12451 {{ 0.5f, 0.25f, 0.0f}, 0xffff0000},
12453 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
12455 for (i = 0; i < ARRAY_SIZE(out); ++i)
12457 out[i].unused3 = 0xdeadbeef;
12458 out[i].unused4 = 0xcafecafe;
12461 window = create_window();
12462 if (!(device = create_device(window, DDSCL_NORMAL)))
12464 skip("Failed to create a 3D device.\n");
12465 DestroyWindow(window);
12466 return;
12468 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
12469 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
12471 viewport = create_viewport(device, 0, 0, 256, 256);
12472 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12473 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12475 memset(&transformdata, 0, sizeof(transformdata));
12476 transformdata.dwSize = sizeof(transformdata);
12477 transformdata.lpIn = position_tests;
12478 transformdata.dwInSize = sizeof(position_tests[0]);
12479 transformdata.lpOut = out;
12480 transformdata.dwOutSize = sizeof(out[0]);
12481 transformdata.lpHOut = NULL;
12483 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12484 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12485 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12486 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12488 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12490 static const struct vec4 cmp[] =
12492 {128.0f, 128.0f, 0.0f, 1.0f}, {129.0f, 127.0f, 1.0f, 1.0f}, {127.0f, 129.0f, -1.0f, 1.0f},
12493 {128.5f, 127.5f, 0.5f, 1.0f}, {127.5f, 128.5f, -0.5f, 1.0f}, {127.5f, 128.5f, 0.0f, 1.0f}
12496 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12497 "Vertex %u differs. Got %f %f %f %f.\n", i,
12498 out[i].x, out[i].y, out[i].z, out[i].w);
12499 ok(out[i].v1 == position_tests[i].v1 && out[i].v2 == position_tests[i].v2
12500 && out[i].v3 == position_tests[i].v3 && out[i].v4 == position_tests[i].v4,
12501 "Vertex %u payload is %u %u %u %u.\n", i, out[i].v1, out[i].v2, out[i].v3, out[i].v4);
12502 ok(out[i].unused3 == 0xdeadbeef && out[i].unused4 == 0xcafecafe,
12503 "Vertex %u unused data is %#x, %#x.\n", i, out[i].unused3, out[i].unused4);
12506 vp_data = vp_template;
12507 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12508 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12509 offscreen = 0xdeadbeef;
12510 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12511 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12512 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12513 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12515 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12517 static const struct vec4 cmp[] =
12519 {128.0f, 128.0f, 0.0f, 1.0f}, {133.0f, 123.0f, 1.0f, 1.0f}, {123.0f, 133.0f, -1.0f, 1.0f},
12520 {130.5f, 125.5f, 0.5f, 1.0f}, {125.5f, 130.5f, -0.5f, 1.0f}, {125.5f, 130.5f, 0.0f, 1.0f}
12522 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12523 "Vertex %u differs. Got %f %f %f %f.\n", i,
12524 out[i].x, out[i].y, out[i].z, out[i].w);
12527 vp_data.dwX = 10;
12528 vp_data.dwY = 20;
12529 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12530 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12531 offscreen = 0xdeadbeef;
12532 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12533 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12534 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12535 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12536 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12538 static const struct vec4 cmp[] =
12540 {138.0f, 148.0f, 0.0f, 1.0f}, {143.0f, 143.0f, 1.0f, 1.0f}, {133.0f, 153.0f, -1.0f, 1.0f},
12541 {140.5f, 145.5f, 0.5f, 1.0f}, {135.5f, 150.5f, -0.5f, 1.0f}, {135.5f, 150.5f, 0.0f, 1.0f}
12543 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12544 "Vertex %u differs. Got %f %f %f %f.\n", i,
12545 out[i].x, out[i].y, out[i].z, out[i].w);
12548 transformdata.lpHOut = out_h;
12549 offscreen = 0xdeadbeef;
12550 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12551 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12552 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12553 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12554 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12556 static const D3DHVERTEX cmp_h[] =
12558 {0, { 0.0f}, { 0.0f}, { 0.0f}}, {0, { 1.0f}, { 1.0f}, {1.0f}},
12559 {D3DCLIP_FRONT, {-1.0f}, {-1.0f}, {-1.0f}}, {0, { 0.5f}, { 0.5f}, {0.5f}},
12560 {D3DCLIP_FRONT, {-0.5f}, {-0.5f}, {-0.5f}}, {0, {-0.5f}, {-0.5f}, {0.0f}}
12562 ok(compare_float(U1(cmp_h[i]).hx, U1(out_h[i]).hx, 4096)
12563 && compare_float(U2(cmp_h[i]).hy, U2(out_h[i]).hy, 4096)
12564 && compare_float(U3(cmp_h[i]).hz, U3(out_h[i]).hz, 4096)
12565 && cmp_h[i].dwFlags == out_h[i].dwFlags,
12566 "HVertex %u differs. Got %#x %f %f %f.\n", i,
12567 out_h[i].dwFlags, U1(out_h[i]).hx, U2(out_h[i]).hy, U3(out_h[i]).hz);
12569 /* No scheme has been found behind those return values. It seems to be
12570 * whatever data windows has when throwing the vertex away. Modify the
12571 * input test vertices to test this more. Depending on the input data
12572 * it can happen that the z coord gets written into y, or similar things. */
12573 if (0)
12575 static const struct vec4 cmp[] =
12577 {138.0f, 148.0f, 0.0f, 1.0f}, {143.0f, 143.0f, 1.0f, 1.0f}, { -1.0f, -1.0f, 0.5f, 1.0f},
12578 {140.5f, 145.5f, 0.5f, 1.0f}, { -0.5f, -0.5f, -0.5f, 1.0f}, {135.5f, 150.5f, 0.0f, 1.0f}
12580 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12581 "Vertex %u differs. Got %f %f %f %f.\n", i,
12582 out[i].x, out[i].y, out[i].z, out[i].w);
12586 transformdata.lpIn = cliptest;
12587 transformdata.dwInSize = sizeof(cliptest[0]);
12588 offscreen = 0xdeadbeef;
12589 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
12590 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12591 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12592 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12593 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
12595 static const DWORD flags[] =
12598 D3DCLIP_RIGHT | D3DCLIP_BACK | D3DCLIP_TOP,
12600 D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
12602 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
12605 vp_data = vp_template;
12606 vp_data.dwWidth = 10;
12607 vp_data.dwHeight = 480;
12608 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12609 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12610 offscreen = 0xdeadbeef;
12611 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
12612 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12613 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12614 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12615 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
12617 static const DWORD flags[] =
12619 D3DCLIP_RIGHT,
12620 D3DCLIP_RIGHT | D3DCLIP_BACK,
12621 D3DCLIP_LEFT,
12622 D3DCLIP_LEFT | D3DCLIP_FRONT,
12624 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
12627 vp_data = vp_template;
12628 vp_data.dwWidth = 256;
12629 vp_data.dwHeight = 256;
12630 vp_data.dvScaleX = 1;
12631 vp_data.dvScaleY = 1;
12632 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12633 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12634 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
12635 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12636 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12637 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12638 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
12640 static const DWORD flags[] =
12643 D3DCLIP_BACK,
12645 D3DCLIP_FRONT,
12647 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
12650 /* Finally try to figure out how the DWORD dwOffscreen works.
12651 * It is a logical AND of the vertices' dwFlags members. */
12652 vp_data = vp_template;
12653 vp_data.dwWidth = 5;
12654 vp_data.dwHeight = 5;
12655 vp_data.dvScaleX = 10000.0f;
12656 vp_data.dvScaleY = 10000.0f;
12657 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12658 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12659 transformdata.lpIn = cliptest;
12660 offscreen = 0xdeadbeef;
12661 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12662 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12663 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12664 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12666 offscreen = 0xdeadbeef;
12667 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12668 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12669 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12670 ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
12671 offscreen = 0xdeadbeef;
12672 hr = IDirect3DViewport2_TransformVertices(viewport, 2,
12673 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12674 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12675 ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
12676 hr = IDirect3DViewport2_TransformVertices(viewport, 3,
12677 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12678 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12679 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12681 transformdata.lpIn = cliptest + 1;
12682 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12683 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12684 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12685 ok(offscreen == (D3DCLIP_BACK | D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
12687 transformdata.lpIn = cliptest + 2;
12688 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12689 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12690 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12691 ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
12692 offscreen = 0xdeadbeef;
12693 hr = IDirect3DViewport2_TransformVertices(viewport, 2,
12694 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12695 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12696 ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
12698 transformdata.lpIn = cliptest + 3;
12699 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12700 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12701 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12702 ok(offscreen == (D3DCLIP_FRONT | D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
12704 transformdata.lpIn = offscreentest;
12705 transformdata.dwInSize = sizeof(offscreentest[0]);
12706 vp_data = vp_template;
12707 vp_data.dwWidth = 257;
12708 vp_data.dwHeight = 257;
12709 vp_data.dvScaleX = 1.0f;
12710 vp_data.dvScaleY = 1.0f;
12711 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12712 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12713 offscreen = 0xdeadbeef;
12714 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12715 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12716 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12717 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12719 vp_data.dwWidth = 256;
12720 vp_data.dwHeight = 256;
12721 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12722 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12723 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12724 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12725 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12726 ok(offscreen == D3DCLIP_RIGHT, "Offscreen is %x.\n", offscreen);
12728 /* Test the effect of Matrices.
12730 * Basically the x coordinate ends up as ((x + 1) * 2 + 0) * 5 and
12731 * y as ((y + 0) * 2 + 1) * 5. The 5 comes from dvScaleX/Y, 2 from
12732 * the view matrix and the +1's from the world and projection matrix. */
12733 vp_data.dwX = 0;
12734 vp_data.dwY = 0;
12735 vp_data.dwWidth = 256;
12736 vp_data.dwHeight = 256;
12737 vp_data.dvScaleX = 5.0f;
12738 vp_data.dvScaleY = 5.0f;
12739 vp_data.dvMinZ = 0.0f;
12740 vp_data.dvMaxZ = 1.0f;
12741 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12742 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12744 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat_translate1);
12745 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12746 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat_scale);
12747 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12748 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat_translate2);
12749 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12751 transformdata.lpIn = position_tests;
12752 transformdata.dwInSize = sizeof(position_tests[0]);
12753 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12754 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12755 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12757 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12759 static const struct vec4 cmp[] =
12761 {138.0f, 123.0f, 0.0f, 1.0f}, {148.0f, 113.0f, 2.0f, 1.0f}, {128.0f, 133.0f, -2.0f, 1.0f},
12762 {143.0f, 118.0f, 1.0f, 1.0f}, {133.0f, 128.0f, -1.0f, 1.0f}, {133.0f, 128.0f, 0.0f, 1.0f}
12765 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12766 "Vertex %u differs. Got %f %f %f %f.\n", i,
12767 out[i].x, out[i].y, out[i].z, out[i].w);
12770 /* Invalid flags. */
12771 offscreen = 0xdeadbeef;
12772 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12773 &transformdata, 0, &offscreen);
12774 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
12775 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
12777 /* NULL transform data. */
12778 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12779 NULL, D3DTRANSFORM_UNCLIPPED, &offscreen);
12780 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
12781 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
12782 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
12783 NULL, D3DTRANSFORM_UNCLIPPED, &offscreen);
12784 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
12785 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
12787 /* NULL transform data and NULL dwOffscreen.
12789 * Valid transform data + NULL dwOffscreen -> crash. */
12790 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12791 NULL, D3DTRANSFORM_UNCLIPPED, NULL);
12792 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
12794 /* No vertices. */
12795 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
12796 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12797 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12798 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12799 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
12800 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12801 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12802 ok(offscreen == ~0U, "Offscreen is %x.\n", offscreen);
12804 /* Invalid sizes. */
12805 offscreen = 0xdeadbeef;
12806 transformdata.dwSize = sizeof(transformdata) - 1;
12807 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12808 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12809 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
12810 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
12811 transformdata.dwSize = sizeof(transformdata) + 1;
12812 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12813 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12814 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
12815 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
12817 /* NULL lpIn or lpOut -> crash, except when transforming 0 vertices. */
12818 transformdata.dwSize = sizeof(transformdata);
12819 transformdata.lpIn = NULL;
12820 transformdata.lpOut = NULL;
12821 offscreen = 0xdeadbeef;
12822 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
12823 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12824 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12825 ok(offscreen == ~0U, "Offscreen is %x.\n", offscreen);
12827 /* Test how vertices are transformed during draws. */
12828 vp_data.dwX = 20;
12829 vp_data.dwY = 20;
12830 vp_data.dwWidth = 200;
12831 vp_data.dwHeight = 400;
12832 vp_data.dvScaleX = 20.0f;
12833 vp_data.dvScaleY = 50.0f;
12834 vp_data.dvMinZ = 0.0f;
12835 vp_data.dvMaxZ = 1.0f;
12836 hr = IDirect3DViewport3_SetViewport(viewport, &vp_data);
12837 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12838 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
12839 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
12841 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
12842 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12844 hr = IDirect3DDevice3_BeginScene(device);
12845 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12846 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12847 quad, 4, 0);
12848 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12849 hr = IDirect3DDevice3_EndScene(device);
12850 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12852 color = get_surface_color(rt, 128, 143);
12853 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12854 color = get_surface_color(rt, 132, 143);
12855 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12856 color = get_surface_color(rt, 128, 147);
12857 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12858 color = get_surface_color(rt, 132, 147);
12859 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12861 color = get_surface_color(rt, 177, 217);
12862 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12863 color = get_surface_color(rt, 181, 217);
12864 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12865 color = get_surface_color(rt, 177, 221);
12866 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12867 color = get_surface_color(rt, 181, 221);
12868 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12870 /* Test D3DVIEWPORT2 behavior. */
12871 vp2_data.dwSize = sizeof(vp2_data);
12872 vp2_data.dwX = 20;
12873 vp2_data.dwY = 20;
12874 vp2_data.dwWidth = 200;
12875 vp2_data.dwHeight = 400;
12876 vp2_data.dvClipX = -0.5f;
12877 vp2_data.dvClipY = 4.0f;
12878 vp2_data.dvClipWidth = 5.0f;
12879 vp2_data.dvClipHeight = 10.0f;
12880 vp2_data.dvMinZ = 0.0f;
12881 vp2_data.dvMaxZ = 2.0f;
12882 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2_data);
12883 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
12884 transformdata.lpIn = position_tests;
12885 transformdata.lpOut = out;
12886 hr = IDirect3DViewport3_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12887 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12888 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12889 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12891 static const struct vec4 cmp[] =
12893 {120.0f, 140.0f, 0.0f, 1.0f}, {200.0f, 60.0f, 1.0f, 1.0f}, {40.0f, 220.0f, -1.0f, 1.0f},
12894 {160.0f, 100.0f, 0.5f, 1.0f}, { 80.0f, 180.0f, -0.5f, 1.0f}, {80.0f, 180.0f, 0.0f, 1.0f}
12897 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12898 "Vertex %u differs. Got %f %f %f %f.\n", i,
12899 out[i].x, out[i].y, out[i].z, out[i].w);
12902 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x0000ff00, 0.0f, 0);
12903 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12905 hr = IDirect3DDevice3_BeginScene(device);
12906 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12907 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12908 quad, 4, 0);
12909 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12910 hr = IDirect3DDevice3_EndScene(device);
12911 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12913 color = get_surface_color(rt, 58, 118);
12914 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12915 color = get_surface_color(rt, 62, 118);
12916 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12917 color = get_surface_color(rt, 58, 122);
12918 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12919 color = get_surface_color(rt, 62, 122);
12920 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12922 color = get_surface_color(rt, 157, 177);
12923 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12924 color = get_surface_color(rt, 161, 177);
12925 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12926 color = get_surface_color(rt, 157, 181);
12927 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12928 color = get_surface_color(rt, 161, 181);
12929 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12931 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat_identity);
12932 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12933 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat_identity);
12934 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12935 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat_transform3);
12936 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12938 vp2_data.dwX = 0.0;
12939 vp2_data.dwY = 0.0;
12940 vp2_data.dwWidth = 1;
12941 vp2_data.dwHeight = 1;
12942 vp2_data.dvClipX = -12.8f;
12943 vp2_data.dvClipY = 12.8f + mat_transform3._42 / mat_transform3._44;
12944 vp2_data.dvClipWidth = 25.6f;
12945 vp2_data.dvClipHeight = 25.6f;
12946 vp2_data.dvMinZ = 0.0f;
12947 vp2_data.dvMaxZ = 0.5f;
12948 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2_data);
12949 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
12950 transformdata.lpIn = cliptest;
12951 transformdata.dwInSize = sizeof(cliptest[0]);
12952 offscreen = 0xdeadbeef;
12953 hr = IDirect3DViewport3_TransformVertices(viewport, ARRAY_SIZE(cliptest),
12954 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12955 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12956 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12957 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
12959 static const D3DHVERTEX cmp_h[] =
12961 {0, { 25.59f}, { 44.79f}, { 1.0f }},
12962 {D3DCLIP_RIGHT | D3DCLIP_TOP | D3DCLIP_BACK, { 25.61f}, { 44.81f}, { 1.01f}},
12963 {0, {-25.59f}, {-6.39f }, { 0.0f }},
12964 {D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,{-25.61f}, {-6.41f }, {-0.01f}},
12966 ok(compare_float(U1(cmp_h[i]).hx, U1(out_h[i]).hx, 4096)
12967 && compare_float(U2(cmp_h[i]).hy, U2(out_h[i]).hy, 4096)
12968 && compare_float(U3(cmp_h[i]).hz, U3(out_h[i]).hz, 4096)
12969 && cmp_h[i].dwFlags == out_h[i].dwFlags,
12970 "HVertex %u differs. Got %#x %f %f %f.\n", i,
12971 out_h[i].dwFlags, U1(out_h[i]).hx, U2(out_h[i]).hy, U3(out_h[i]).hz);
12974 destroy_viewport(device, viewport);
12975 IDirectDrawSurface4_Release(rt);
12976 refcount = IDirect3DDevice3_Release(device);
12977 ok(!refcount, "Device has %u references left.\n", refcount);
12978 DestroyWindow(window);
12981 static void test_display_mode_surface_pixel_format(void)
12983 unsigned int width, height, bpp;
12984 IDirectDrawSurface4 *surface;
12985 DDSURFACEDESC2 surface_desc;
12986 IDirectDraw4 *ddraw;
12987 ULONG refcount;
12988 HWND window;
12989 HRESULT hr;
12991 if (!(ddraw = create_ddraw()))
12993 skip("Failed to create ddraw.\n");
12994 return;
12997 surface_desc.dwSize = sizeof(surface_desc);
12998 hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc);
12999 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
13000 width = surface_desc.dwWidth;
13001 height = surface_desc.dwHeight;
13003 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
13004 0, 0, width, height, NULL, NULL, NULL, NULL);
13005 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
13006 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13008 bpp = 0;
13009 if (SUCCEEDED(IDirectDraw4_SetDisplayMode(ddraw, width, height, 16, 0, 0)))
13010 bpp = 16;
13011 if (SUCCEEDED(IDirectDraw4_SetDisplayMode(ddraw, width, height, 24, 0, 0)))
13012 bpp = 24;
13013 if (SUCCEEDED(IDirectDraw4_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
13014 bpp = 32;
13015 ok(bpp, "Set display mode failed.\n");
13017 surface_desc.dwSize = sizeof(surface_desc);
13018 hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc);
13019 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
13020 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
13021 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
13022 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
13023 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
13025 memset(&surface_desc, 0, sizeof(surface_desc));
13026 surface_desc.dwSize = sizeof(surface_desc);
13027 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
13028 U5(surface_desc).dwBackBufferCount = 1;
13029 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE;
13030 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13031 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
13032 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
13033 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
13034 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
13035 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
13036 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
13037 U4(surface_desc).ddpfPixelFormat.dwFlags);
13038 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
13039 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
13040 IDirectDrawSurface4_Release(surface);
13042 memset(&surface_desc, 0, sizeof(surface_desc));
13043 surface_desc.dwSize = sizeof(surface_desc);
13044 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
13045 surface_desc.dwWidth = width;
13046 surface_desc.dwHeight = height;
13047 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13048 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13049 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
13050 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
13051 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
13052 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
13053 U4(surface_desc).ddpfPixelFormat.dwFlags);
13054 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
13055 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
13056 IDirectDrawSurface4_Release(surface);
13058 refcount = IDirectDraw4_Release(ddraw);
13059 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13060 DestroyWindow(window);
13063 static void test_surface_desc_size(void)
13065 union
13067 DWORD dwSize;
13068 DDSURFACEDESC desc1;
13069 DDSURFACEDESC2 desc2;
13070 BYTE blob[1024];
13071 } desc;
13072 IDirectDrawSurface4 *surface4;
13073 IDirectDrawSurface3 *surface3;
13074 IDirectDrawSurface *surface;
13075 DDSURFACEDESC2 surface_desc;
13076 HRESULT expected_hr, hr;
13077 IDirectDraw4 *ddraw;
13078 unsigned int i, j;
13079 ULONG refcount;
13081 static const struct
13083 unsigned int caps;
13084 const char *name;
13086 surface_caps[] =
13088 {DDSCAPS_OFFSCREENPLAIN, "offscreenplain"},
13089 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "systemmemory texture"},
13090 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "videomemory texture"},
13092 static const unsigned int desc_sizes[] =
13094 sizeof(DDSURFACEDESC),
13095 sizeof(DDSURFACEDESC2),
13096 sizeof(DDSURFACEDESC) + 1,
13097 sizeof(DDSURFACEDESC2) + 1,
13098 2 * sizeof(DDSURFACEDESC),
13099 2 * sizeof(DDSURFACEDESC2),
13100 sizeof(DDSURFACEDESC) - 1,
13101 sizeof(DDSURFACEDESC2) - 1,
13102 sizeof(DDSURFACEDESC) / 2,
13103 sizeof(DDSURFACEDESC2) / 2,
13107 sizeof(desc) / 2,
13108 sizeof(desc) - 100,
13111 if (!(ddraw = create_ddraw()))
13113 skip("Failed to create ddraw.\n");
13114 return;
13116 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
13117 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13119 for (i = 0; i < ARRAY_SIZE(surface_caps); ++i)
13121 memset(&surface_desc, 0, sizeof(surface_desc));
13122 surface_desc.dwSize = sizeof(surface_desc);
13123 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
13124 surface_desc.ddsCaps.dwCaps = surface_caps[i].caps;
13125 surface_desc.dwHeight = 128;
13126 surface_desc.dwWidth = 128;
13127 if (FAILED(IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL)))
13129 skip("Failed to create surface, type %s.\n", surface_caps[i].name);
13130 continue;
13132 hr = IDirectDrawSurface_QueryInterface(surface4, &IID_IDirectDrawSurface, (void **)&surface);
13133 ok(hr == DD_OK, "Failed to query IDirectDrawSurface, hr %#x, type %s.\n", hr, surface_caps[i].name);
13134 hr = IDirectDrawSurface_QueryInterface(surface4, &IID_IDirectDrawSurface3, (void **)&surface3);
13135 ok(hr == DD_OK, "Failed to query IDirectDrawSurface3, hr %#x, type %s.\n", hr, surface_caps[i].name);
13137 /* GetSurfaceDesc() */
13138 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13140 memset(&desc, 0, sizeof(desc));
13141 desc.dwSize = desc_sizes[j];
13142 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
13143 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc.desc1);
13144 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13145 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13147 memset(&desc, 0, sizeof(desc));
13148 desc.dwSize = desc_sizes[j];
13149 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
13150 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &desc.desc1);
13151 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13152 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13154 memset(&desc, 0, sizeof(desc));
13155 desc.dwSize = desc_sizes[j];
13156 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC2) ? DD_OK : DDERR_INVALIDPARAMS;
13157 hr = IDirectDrawSurface4_GetSurfaceDesc(surface4, &desc.desc2);
13158 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13159 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13162 /* Lock() */
13163 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13165 const BOOL valid_size = desc_sizes[j] == sizeof(DDSURFACEDESC)
13166 || desc_sizes[j] == sizeof(DDSURFACEDESC2);
13167 DWORD expected_texture_stage;
13169 memset(&desc, 0, sizeof(desc));
13170 desc.dwSize = desc_sizes[j];
13171 desc.desc2.dwTextureStage = 0xdeadbeef;
13172 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13173 hr = IDirectDrawSurface_Lock(surface, NULL, &desc.desc1, 0, 0);
13174 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13175 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13176 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13177 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
13178 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13179 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
13180 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13181 if (SUCCEEDED(hr))
13183 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
13184 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
13185 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
13186 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
13187 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13188 todo_wine_if(!expected_texture_stage)
13189 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13190 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
13191 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13192 IDirectDrawSurface_Unlock(surface, NULL);
13195 memset(&desc, 0, sizeof(desc));
13196 desc.dwSize = desc_sizes[j];
13197 desc.desc2.dwTextureStage = 0xdeadbeef;
13198 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13199 hr = IDirectDrawSurface3_Lock(surface3, NULL, &desc.desc1, 0, 0);
13200 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13201 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13202 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13203 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
13204 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13205 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
13206 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13207 if (SUCCEEDED(hr))
13209 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
13210 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
13211 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
13212 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
13213 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13214 todo_wine_if(!expected_texture_stage)
13215 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13216 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
13217 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13218 IDirectDrawSurface3_Unlock(surface3, NULL);
13221 memset(&desc, 0, sizeof(desc));
13222 desc.dwSize = desc_sizes[j];
13223 desc.desc2.dwTextureStage = 0xdeadbeef;
13224 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13225 hr = IDirectDrawSurface4_Lock(surface4, NULL, &desc.desc2, 0, 0);
13226 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13227 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13228 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13229 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
13230 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13231 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
13232 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13233 if (SUCCEEDED(hr))
13235 ok(desc.desc2.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
13236 desc.desc2.dwWidth, desc_sizes[j], surface_caps[i].name);
13237 ok(desc.desc2.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
13238 desc.desc2.dwHeight, desc_sizes[j], surface_caps[i].name);
13239 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13240 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13241 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
13242 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13243 IDirectDrawSurface4_Unlock(surface4, NULL);
13247 IDirectDrawSurface4_Release(surface4);
13248 IDirectDrawSurface3_Release(surface3);
13249 IDirectDrawSurface_Release(surface);
13252 /* GetDisplayMode() */
13253 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13255 memset(&desc, 0xcc, sizeof(desc));
13256 desc.dwSize = desc_sizes[j];
13257 expected_hr = (desc.dwSize == sizeof(DDSURFACEDESC) || desc.dwSize == sizeof(DDSURFACEDESC2))
13258 ? DD_OK : DDERR_INVALIDPARAMS;
13259 hr = IDirectDraw4_GetDisplayMode(ddraw, &desc.desc2);
13260 ok(hr == expected_hr, "Got hr %#x, expected %#x, size %u.\n", hr, expected_hr, desc_sizes[j]);
13261 if (SUCCEEDED(hr))
13263 ok(desc.dwSize == sizeof(DDSURFACEDESC2), "Wrong size %u for %u.\n", desc.dwSize, desc_sizes[j]);
13264 ok(desc.blob[desc_sizes[j]] == 0xcc, "Overflow for size %u.\n", desc_sizes[j]);
13265 ok(desc.blob[desc_sizes[j] - 1] != 0xcc, "Struct not cleared for size %u.\n", desc_sizes[j]);
13269 refcount = IDirectDraw4_Release(ddraw);
13270 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13273 static void test_get_surface_from_dc(void)
13275 IDirectDrawSurface *surface1, *tmp;
13276 IDirectDrawSurface4 *surface;
13277 DDSURFACEDESC2 surface_desc;
13278 IDirectDraw4 *ddraw;
13279 HDC dc, device_dc;
13280 ULONG refcount;
13281 HWND window;
13282 HRESULT hr;
13283 DWORD ret;
13285 window = create_window();
13286 ddraw = create_ddraw();
13287 ok(!!ddraw, "Failed to create a ddraw object.\n");
13288 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13289 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13291 memset(&surface_desc, 0, sizeof(surface_desc));
13292 surface_desc.dwSize = sizeof(surface_desc);
13293 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
13294 surface_desc.dwWidth = 64;
13295 surface_desc.dwHeight = 64;
13296 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13298 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13299 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13300 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirectDrawSurface, (void **)&surface1);
13301 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
13303 refcount = get_refcount((IUnknown *)surface1);
13304 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13305 refcount = get_refcount((IUnknown *)surface);
13306 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13308 hr = IDirectDrawSurface4_GetDC(surface, &dc);
13309 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
13311 tmp = (void *)0xdeadbeef;
13312 device_dc = (void *)0xdeadbeef;
13313 hr = GetSurfaceFromDC(NULL, &tmp, &device_dc);
13314 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13315 ok(!tmp, "Got unexpected surface %p.\n", tmp);
13316 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
13318 device_dc = (void *)0xdeadbeef;
13319 hr = GetSurfaceFromDC(dc, NULL, &device_dc);
13320 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
13321 ok(device_dc == (void *)0xdeadbeef, "Got unexpected device_dc %p.\n", device_dc);
13323 tmp = (void *)0xdeadbeef;
13324 hr = GetSurfaceFromDC(dc, &tmp, NULL);
13325 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
13326 ok(!tmp, "Got unexpected surface %p.\n", tmp);
13328 hr = GetSurfaceFromDC(dc, &tmp, &device_dc);
13329 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
13330 ok(tmp == surface1, "Got unexpected surface %p, expected %p.\n", tmp, surface1);
13331 IDirectDrawSurface_Release(tmp);
13333 ret = GetObjectType(device_dc);
13334 todo_wine ok(ret == OBJ_DC, "Got unexpected object type %#x.\n", ret);
13335 ret = GetDeviceCaps(device_dc, TECHNOLOGY);
13336 todo_wine ok(ret == DT_RASDISPLAY, "Got unexpected technology %#x.\n", ret);
13338 hr = IDirectDraw4_GetSurfaceFromDC(ddraw, dc, NULL);
13339 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
13341 hr = IDirectDraw4_GetSurfaceFromDC(ddraw, dc, (IDirectDrawSurface4 **)&tmp);
13342 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
13343 ok(tmp == surface1, "Got unexpected surface %p, expected %p.\n", tmp, surface1);
13345 refcount = get_refcount((IUnknown *)surface1);
13346 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
13347 refcount = get_refcount((IUnknown *)surface);
13348 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13350 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
13351 ok(SUCCEEDED(hr), "ReleaseDC failed, hr %#x.\n", hr);
13353 IDirectDrawSurface_Release(tmp);
13355 dc = CreateCompatibleDC(NULL);
13356 ok(!!dc, "CreateCompatibleDC failed.\n");
13358 tmp = (void *)0xdeadbeef;
13359 device_dc = (void *)0xdeadbeef;
13360 hr = GetSurfaceFromDC(dc, &tmp, &device_dc);
13361 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13362 ok(!tmp, "Got unexpected surface %p.\n", tmp);
13363 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
13365 tmp = (void *)0xdeadbeef;
13366 hr = IDirectDraw4_GetSurfaceFromDC(ddraw, dc, (IDirectDrawSurface4 **)&tmp);
13367 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13368 ok(!tmp, "Got unexpected surface %p.\n", tmp);
13370 ok(DeleteDC(dc), "DeleteDC failed.\n");
13372 tmp = (void *)0xdeadbeef;
13373 hr = IDirectDraw4_GetSurfaceFromDC(ddraw, NULL, (IDirectDrawSurface4 **)&tmp);
13374 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13375 ok(!tmp, "Got unexpected surface %p.\n", tmp);
13377 IDirectDrawSurface4_Release(surface);
13378 IDirectDrawSurface_Release(surface1);
13379 IDirectDraw4_Release(ddraw);
13380 DestroyWindow(window);
13383 static void test_ck_operation(void)
13385 IDirectDrawSurface4 *src, *dst;
13386 IDirectDrawSurface *src1, *dst1;
13387 DDSURFACEDESC2 surface_desc;
13388 IDirectDraw4 *ddraw;
13389 ULONG refcount;
13390 HWND window;
13391 HRESULT hr;
13392 D3DCOLOR *color;
13393 unsigned int i;
13394 DDCOLORKEY ckey;
13395 DDBLTFX fx;
13397 window = create_window();
13398 ddraw = create_ddraw();
13399 ok(!!ddraw, "Failed to create a ddraw object.\n");
13400 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13401 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13403 memset(&surface_desc, 0, sizeof(surface_desc));
13404 surface_desc.dwSize = sizeof(surface_desc);
13405 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
13406 surface_desc.dwWidth = 4;
13407 surface_desc.dwHeight = 1;
13408 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13409 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
13410 U1(U4(surface_desc.ddpfPixelFormat)).dwRGBBitCount = 32;
13411 U2(U4(surface_desc.ddpfPixelFormat)).dwRBitMask = 0x00ff0000;
13412 U3(U4(surface_desc.ddpfPixelFormat)).dwGBitMask = 0x0000ff00;
13413 U4(U4(surface_desc.ddpfPixelFormat)).dwBBitMask = 0x000000ff;
13414 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL);
13415 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13417 surface_desc.dwFlags |= DDSD_CKSRCBLT;
13418 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff00ff;
13419 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff00ff;
13420 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL);
13421 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13423 hr = IDirectDrawSurface4_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13424 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13425 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
13426 color = surface_desc.lpSurface;
13427 color[0] = 0x77010203;
13428 color[1] = 0x00010203;
13429 color[2] = 0x77ff00ff;
13430 color[3] = 0x00ff00ff;
13431 hr = IDirectDrawSurface4_Unlock(src, NULL);
13432 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13434 for (i = 0; i < 2; ++i)
13436 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13437 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13438 color = surface_desc.lpSurface;
13439 color[0] = 0xcccccccc;
13440 color[1] = 0xcccccccc;
13441 color[2] = 0xcccccccc;
13442 color[3] = 0xcccccccc;
13443 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13444 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13446 if (i)
13448 hr = IDirectDrawSurface4_BltFast(dst, 0, 0, src, NULL, DDBLTFAST_SRCCOLORKEY);
13449 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13451 else
13453 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, NULL);
13454 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13457 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT | DDLOCK_READONLY, NULL);
13458 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13459 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
13460 color = surface_desc.lpSurface;
13461 /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
13462 * color keying, but copy it to the destination surface. Others (sysmem surfaces) apply it for
13463 * color keying, but do not copy it into the destination surface. Nvidia neither uses it for
13464 * color keying nor copies it. */
13465 ok((color[0] == 0x77010203 && color[1] == 0x00010203
13466 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* AMD, Wine */
13467 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
13468 && color[2] == 0x00ff00ff && color[3] == 0xcccccccc) /* Sysmem surfaces? */
13469 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
13470 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Nvidia */
13471 || broken(color[0] == 0xff010203 && color[1] == 0xff010203
13472 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Testbot */,
13473 "Destination data after blitting is %08x %08x %08x %08x, i=%u.\n",
13474 color[0], color[1], color[2], color[3], i);
13475 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13476 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13479 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13480 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13481 ok(ckey.dwColorSpaceLowValue == 0x00ff00ff && ckey.dwColorSpaceHighValue == 0x00ff00ff,
13482 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13484 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
13485 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13486 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13488 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13489 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13490 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13491 ok(ckey.dwColorSpaceLowValue == 0x0000ff00 && ckey.dwColorSpaceHighValue == 0x0000ff00,
13492 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13494 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0;
13495 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0;
13496 hr = IDirectDrawSurface4_GetSurfaceDesc(src, &surface_desc);
13497 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
13498 ok(surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0x0000ff00
13499 && surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0x0000ff00,
13500 "Got unexpected color key low=%08x high=%08x.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue,
13501 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue);
13503 /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */
13504 ckey.dwColorSpaceLowValue = 0x000000ff;
13505 ckey.dwColorSpaceHighValue = 0x00000000;
13506 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13507 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13509 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13510 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13511 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13512 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
13513 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13515 ckey.dwColorSpaceLowValue = 0x000000ff;
13516 ckey.dwColorSpaceHighValue = 0x00000001;
13517 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13518 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13520 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13521 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13522 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13523 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
13524 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13526 ckey.dwColorSpaceLowValue = 0x000000fe;
13527 ckey.dwColorSpaceHighValue = 0x000000fd;
13528 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13529 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13531 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13532 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13533 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13534 ok(ckey.dwColorSpaceLowValue == 0x000000fe && ckey.dwColorSpaceHighValue == 0x000000fe,
13535 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13537 IDirectDrawSurface4_Release(src);
13538 IDirectDrawSurface4_Release(dst);
13540 /* Test source and destination keys and where they are read from. Use a surface with alpha
13541 * to avoid driver-dependent content in the X channel. */
13542 memset(&surface_desc, 0, sizeof(surface_desc));
13543 surface_desc.dwSize = sizeof(surface_desc);
13544 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
13545 surface_desc.dwWidth = 6;
13546 surface_desc.dwHeight = 1;
13547 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13548 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
13549 U1(U4(surface_desc.ddpfPixelFormat)).dwRGBBitCount = 32;
13550 U2(U4(surface_desc.ddpfPixelFormat)).dwRBitMask = 0x00ff0000;
13551 U3(U4(surface_desc.ddpfPixelFormat)).dwGBitMask = 0x0000ff00;
13552 U4(U4(surface_desc.ddpfPixelFormat)).dwBBitMask = 0x000000ff;
13553 U5(U4(surface_desc.ddpfPixelFormat)).dwRGBAlphaBitMask = 0xff000000;
13554 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL);
13555 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13556 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL);
13557 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13559 ckey.dwColorSpaceLowValue = 0x0000ff00;
13560 ckey.dwColorSpaceHighValue = 0x0000ff00;
13561 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
13562 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13563 ckey.dwColorSpaceLowValue = 0x00ff0000;
13564 ckey.dwColorSpaceHighValue = 0x00ff0000;
13565 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_DESTBLT, &ckey);
13566 ok(SUCCEEDED(hr) || hr == DDERR_NOCOLORKEYHW, "Failed to set color key, hr %#x.\n", hr);
13567 if (FAILED(hr))
13569 /* Nvidia reject dest keys, AMD allows them. This applies to vidmem and sysmem surfaces. */
13570 skip("Failed to set destination color key, skipping related tests.\n");
13571 goto done;
13574 ckey.dwColorSpaceLowValue = 0x000000ff;
13575 ckey.dwColorSpaceHighValue = 0x000000ff;
13576 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13577 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13578 ckey.dwColorSpaceLowValue = 0x000000aa;
13579 ckey.dwColorSpaceHighValue = 0x000000aa;
13580 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_DESTBLT, &ckey);
13581 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13583 memset(&fx, 0, sizeof(fx));
13584 fx.dwSize = sizeof(fx);
13585 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x00110000;
13586 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x00110000;
13587 fx.ddckDestColorkey.dwColorSpaceHighValue = 0x00001100;
13588 fx.ddckDestColorkey.dwColorSpaceLowValue = 0x00001100;
13590 hr = IDirectDrawSurface4_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13591 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13592 color = surface_desc.lpSurface;
13593 color[0] = 0x000000ff; /* Applies to src blt key in src surface. */
13594 color[1] = 0x000000aa; /* Applies to dst blt key in src surface. */
13595 color[2] = 0x00ff0000; /* Dst color key in dst surface. */
13596 color[3] = 0x0000ff00; /* Src color key in dst surface. */
13597 color[4] = 0x00001100; /* Src color key in ddbltfx. */
13598 color[5] = 0x00110000; /* Dst color key in ddbltfx. */
13599 hr = IDirectDrawSurface4_Unlock(src, NULL);
13600 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13602 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13603 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13604 color = surface_desc.lpSurface;
13605 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13606 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13607 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13609 /* Test a blit without keying. */
13610 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, 0, &fx);
13611 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13613 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13614 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13615 color = surface_desc.lpSurface;
13616 /* Should have copied src data unmodified to dst. */
13617 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13618 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13619 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13620 color[0], color[1], color[2], color[3], color[4], color[5]);
13622 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13623 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13624 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13626 /* Src key. */
13627 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
13628 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13630 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13631 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13632 color = surface_desc.lpSurface;
13633 /* Src key applied to color[0]. It is unmodified, the others are copied. */
13634 ok(color[0] == 0x55555555 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13635 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13636 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13637 color[0], color[1], color[2], color[3], color[4], color[5]);
13639 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13640 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13641 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13643 /* Src override. */
13644 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
13645 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13647 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13648 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13649 color = surface_desc.lpSurface;
13650 /* Override key applied to color[5]. It is unmodified, the others are copied. */
13651 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13652 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x55555555,
13653 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13654 color[0], color[1], color[2], color[3], color[4], color[5]);
13656 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13657 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13658 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13660 /* Src override AND src key. That is not supposed to work. */
13661 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx);
13662 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13664 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13665 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13666 color = surface_desc.lpSurface;
13667 /* Ensure the destination was not changed. */
13668 ok(color[0] == 0x55555555 && color[1] == 0x55555555 && color[2] == 0x55555555 &&
13669 color[3] == 0x55555555 && color[4] == 0x55555555 && color[5] == 0x55555555,
13670 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13671 color[0], color[1], color[2], color[3], color[4], color[5]);
13673 /* Use different dst colors for the dst key test. */
13674 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13675 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13676 color[2] = 0x00001100; /* Dest key in override. */
13677 color[3] = 0x00001100; /* Dest key in override. */
13678 color[4] = 0x000000aa; /* Dest key in src surface. */
13679 color[5] = 0x000000aa; /* Dest key in src surface. */
13680 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13681 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13683 /* Dest key blit. The key is taken from the DESTINATION surface in v4! */
13684 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13685 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13687 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13688 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13689 color = surface_desc.lpSurface;
13690 /* Dst key applied to color[0,1], they are the only changed pixels. */
13691 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
13692 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13693 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13694 color[0], color[1], color[2], color[3], color[4], color[5]);
13696 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13697 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13698 color[2] = 0x00001100; /* Dest key in override. */
13699 color[3] = 0x00001100; /* Dest key in override. */
13700 color[4] = 0x000000aa; /* Dest key in src surface. */
13701 color[5] = 0x000000aa; /* Dest key in src surface. */
13702 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13703 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13705 /* What happens with a QI'd older version of the interface? It takes the key
13706 * from the source surface. */
13707 hr = IDirectDrawSurface4_QueryInterface(src, &IID_IDirectDrawSurface, (void **)&src1);
13708 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
13709 hr = IDirectDrawSurface4_QueryInterface(dst, &IID_IDirectDrawSurface, (void **)&dst1);
13710 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
13712 hr = IDirectDrawSurface_Blt(dst1, NULL, src1, NULL, DDBLT_KEYDEST, &fx);
13713 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13715 IDirectDrawSurface_Release(dst1);
13716 IDirectDrawSurface_Release(src1);
13718 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13719 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13720 color = surface_desc.lpSurface;
13721 /* Dst key applied to color[4,5], they are the only changed pixels. */
13722 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
13723 color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000,
13724 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13725 color[0], color[1], color[2], color[3], color[4], color[5]);
13727 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13728 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13729 color[2] = 0x00001100; /* Dest key in override. */
13730 color[3] = 0x00001100; /* Dest key in override. */
13731 color[4] = 0x000000aa; /* Dest key in src surface. */
13732 color[5] = 0x000000aa; /* Dest key in src surface. */
13733 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13734 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13736 /* Dest override key blit. */
13737 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
13738 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13740 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13741 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13742 color = surface_desc.lpSurface;
13743 /* Dst key applied to color[2,3], they are the only changed pixels. */
13744 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00ff0000 &&
13745 color[3] == 0x0000ff00 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13746 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13747 color[0], color[1], color[2], color[3], color[4], color[5]);
13749 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13750 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13751 color[2] = 0x00001100; /* Dest key in override. */
13752 color[3] = 0x00001100; /* Dest key in override. */
13753 color[4] = 0x000000aa; /* Dest key in src surface. */
13754 color[5] = 0x000000aa; /* Dest key in src surface. */
13755 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13756 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13758 /* Dest override together with surface key. Supposed to fail. */
13759 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx);
13760 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13762 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13763 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13764 color = surface_desc.lpSurface;
13765 /* Destination is unchanged. */
13766 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
13767 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13768 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13769 color[0], color[1], color[2], color[3], color[4], color[5]);
13770 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13771 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13773 /* Source and destination key. This is driver dependent. New HW treats it like
13774 * DDBLT_KEYSRC. Older HW and some software renderers apply both keys. */
13775 if (0)
13777 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx);
13778 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13780 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13781 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13782 color = surface_desc.lpSurface;
13783 /* Color[0] is filtered by the src key, 2-5 are filtered by the dst key, if
13784 * the driver applies it. */
13785 ok(color[0] == 0x00ff0000 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13786 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13787 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13788 color[0], color[1], color[2], color[3], color[4], color[5]);
13790 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13791 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13792 color[2] = 0x00001100; /* Dest key in override. */
13793 color[3] = 0x00001100; /* Dest key in override. */
13794 color[4] = 0x000000aa; /* Dest key in src surface. */
13795 color[5] = 0x000000aa; /* Dest key in src surface. */
13796 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13797 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13800 /* Override keys without ddbltfx parameter fail */
13801 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, NULL);
13802 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13803 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, NULL);
13804 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13806 /* Try blitting without keys in the source surface. */
13807 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, NULL);
13808 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13809 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_DESTBLT, NULL);
13810 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13812 /* That fails now. Do not bother to check that the data is unmodified. */
13813 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
13814 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13816 /* Dest key blit still works, the destination surface key is used in v4. */
13817 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13818 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13820 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13821 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13822 color = surface_desc.lpSurface;
13823 /* Dst key applied to color[0,1], they are the only changed pixels. */
13824 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
13825 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13826 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13827 color[0], color[1], color[2], color[3], color[4], color[5]);
13828 hr = IDirectDrawSurface4_Unlock(dst, NULL);
13829 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13831 /* Try blitting without keys in the destination surface. */
13832 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_SRCBLT, NULL);
13833 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13834 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_DESTBLT, NULL);
13835 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13837 /* This fails, as sanity would dictate. */
13838 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13839 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13841 done:
13842 IDirectDrawSurface4_Release(src);
13843 IDirectDrawSurface4_Release(dst);
13844 refcount = IDirectDraw4_Release(ddraw);
13845 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13846 DestroyWindow(window);
13849 static void test_vb_refcount(void)
13851 ULONG prev_d3d_refcount, prev_device_refcount;
13852 ULONG cur_d3d_refcount, cur_device_refcount;
13853 IDirect3DVertexBuffer *vb, *vb1;
13854 IDirect3DVertexBuffer7 *vb7;
13855 D3DVERTEXBUFFERDESC vb_desc;
13856 IDirect3DDevice3 *device;
13857 IDirect3D3 *d3d;
13858 ULONG refcount;
13859 IUnknown *unk;
13860 HWND window;
13861 HRESULT hr;
13863 window = create_window();
13864 if (!(device = create_device(window, DDSCL_NORMAL)))
13866 skip("Failed to create a 3D device, skipping test.\n");
13867 DestroyWindow(window);
13868 return;
13871 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
13872 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
13874 prev_d3d_refcount = get_refcount((IUnknown *)d3d);
13875 prev_device_refcount = get_refcount((IUnknown *)device);
13877 memset(&vb_desc, 0, sizeof(vb_desc));
13878 vb_desc.dwSize = sizeof(vb_desc);
13879 vb_desc.dwFVF = D3DFVF_XYZ;
13880 vb_desc.dwNumVertices = 4;
13881 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &vb, 0, NULL);
13882 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
13884 cur_d3d_refcount = get_refcount((IUnknown *)d3d);
13885 cur_device_refcount = get_refcount((IUnknown *)device);
13886 ok(cur_d3d_refcount == prev_d3d_refcount, "D3D object refcount changed from %u to %u.\n",
13887 prev_d3d_refcount, cur_d3d_refcount);
13888 ok(cur_device_refcount == prev_device_refcount, "Device refcount changed from %u to %u.\n",
13889 prev_device_refcount, cur_device_refcount);
13891 hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IDirect3DVertexBuffer, (void **)&vb1);
13892 ok(hr == DD_OK, "Failed to query IDirect3DVertexBuffer, hr %#x.\n", hr);
13893 IDirect3DVertexBuffer_Release(vb1);
13895 hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IDirect3DVertexBuffer7, (void **)&vb7);
13896 ok(hr == E_NOINTERFACE, "Querying IDirect3DVertexBuffer7 returned unexpected hr %#x.\n", hr);
13898 hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IUnknown, (void **)&unk);
13899 ok(hr == DD_OK, "Failed to query IUnknown, hr %#x.\n", hr);
13900 ok((IUnknown *)vb == unk,
13901 "IDirect3DVertexBuffer and IUnknown interface pointers don't match, %p != %p.\n", vb, unk);
13902 IUnknown_Release(unk);
13904 refcount = IDirect3DVertexBuffer_Release(vb);
13905 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
13906 IDirect3D3_Release(d3d);
13907 refcount = IDirect3DDevice3_Release(device);
13908 ok(!refcount, "Device has %u references left.\n", refcount);
13909 DestroyWindow(window);
13912 static void test_compute_sphere_visibility(void)
13914 static D3DMATRIX proj_1 =
13916 1.810660f, 0.000000f, 0.000000f, 0.000000f,
13917 0.000000f, 2.414213f, 0.000000f, 0.000000f,
13918 0.000000f, 0.000000f, 1.020408f, 1.000000f,
13919 0.000000f, 0.000000f, -0.102041f, 0.000000f,
13921 static D3DMATRIX proj_2 =
13923 10.0f, 0.0f, 0.0f, 0.0f,
13924 0.0f, 10.0f, 0.0f, 0.0f,
13925 0.0f, 0.0f, 10.0f, 0.0f,
13926 0.0f, 0.0f, 0.0f, 1.0f,
13928 static D3DMATRIX view_1 =
13930 1.000000f, 0.000000f, 0.000000f, 0.000000f,
13931 0.000000f, 0.768221f, -0.640185f, 0.000000f,
13932 -0.000000f, 0.640185f, 0.768221f, 0.000000f,
13933 -14.852037f, 9.857489f, 11.600972f, 1.000000f,
13935 static D3DMATRIX identity =
13937 1.0f, 0.0f, 0.0f, 0.0f,
13938 0.0f, 1.0f, 0.0f, 0.0f,
13939 0.0f, 0.0f, 1.0f, 0.0f,
13940 0.0f, 0.0f, 0.0f, 1.0f,
13942 static struct
13944 D3DMATRIX *view, *proj;
13945 unsigned int sphere_count;
13946 D3DVECTOR center[3];
13947 D3DVALUE radius[3];
13948 const DWORD expected[3];
13949 BOOL todo;
13951 tests[] =
13953 {&view_1, &proj_1, 1, {{{11.461533f}, {-4.761727f}, {-1.171646f}}}, {38.252632f}, {0x1555}},
13954 {&view_1, &proj_1, 3, {{{-3.515620f}, {-1.560661f}, {-12.464638f}},
13955 {{14.290396f}, {-2.981143f}, {-24.311312f}},
13956 {{1.461626f}, {-6.093709f}, {-13.901010f}}},
13957 {4.354097f, 12.500704f, 17.251318f}, {0x154a, 0x1555, 0x1555}},
13958 {&identity, &proj_2, 1, {{{0.0f}, {0.0f}, {0.05f}}}, {0.04f}, {0x1555}, TRUE},
13959 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.5f}}}, {0.5f}, {0x1401}},
13960 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {0.0f}, {0x401}},
13961 {&identity, &identity, 1, {{{-1.0f}, {-1.0f}, {0.5f}}}, {0.25f}, {0x1505}, TRUE}, /* 5 */
13962 {&identity, &identity, 1, {{{-20.0f}, {0.0f}, {0.5f}}}, {3.0f}, {0x154a}},
13963 {&identity, &identity, 1, {{{20.0f}, {0.0f}, {0.5f}}}, {3.0f}, {0x1562}},
13964 {&identity, &identity, 1, {{{0.0f}, {-20.0f}, {0.5f}}}, {3.0f}, {0x1616}},
13965 {&identity, &identity, 1, {{{0.0f}, {20.0f}, {0.5f}}}, {3.0f}, {0x1496}},
13966 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {-20.0f}}}, {3.0f}, {0x956}}, /* 10 */
13967 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {20.0f}}}, {3.0f}, {0x2156}},
13969 IDirect3DViewport3 *viewport;
13970 IDirect3DDevice3 *device;
13971 unsigned int i, j;
13972 DWORD result[3];
13973 ULONG refcount;
13974 HWND window;
13975 HRESULT hr;
13977 window = create_window();
13978 if (!(device = create_device(window, DDSCL_NORMAL)))
13980 skip("Failed to create a 3D device, skipping test.\n");
13981 DestroyWindow(window);
13982 return;
13985 viewport = create_viewport(device, 0, 0, 640, 480);
13986 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
13987 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
13989 IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
13991 for (i = 0; i < ARRAY_SIZE(tests); ++i)
13993 IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, tests[i].view);
13994 IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].proj);
13996 hr = IDirect3DDevice3_ComputeSphereVisibility(device, tests[i].center, tests[i].radius,
13997 tests[i].sphere_count, 0, result);
13998 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14000 for (j = 0; j < tests[i].sphere_count; ++j)
14001 todo_wine_if(tests[i].todo)
14002 ok(result[j] == tests[i].expected[j], "Test %u sphere %u: expected %#x, got %#x.\n",
14003 i, j, tests[i].expected[j], result[j]);
14006 destroy_viewport(device, viewport);
14007 refcount = IDirect3DDevice3_Release(device);
14008 ok(!refcount, "Device has %u references left.\n", refcount);
14009 DestroyWindow(window);
14012 static void test_map_synchronisation(void)
14014 LARGE_INTEGER frequency, diff, ts[3];
14015 IDirect3DVertexBuffer *buffer;
14016 IDirect3DViewport3 *viewport;
14017 unsigned int i, j, tri_count;
14018 D3DVERTEXBUFFERDESC vb_desc;
14019 IDirect3DDevice3 *device;
14020 BOOL unsynchronised, ret;
14021 IDirectDrawSurface4 *rt;
14022 IDirect3D3 *d3d;
14023 D3DCOLOR colour;
14024 ULONG refcount;
14025 HWND window;
14026 HRESULT hr;
14028 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
14030 /* DDLOCK_DISCARDCONTENTS and DDLOCK_NOOVERWRITE were introduced with
14031 * ddraw7 and are ignored in earlier versions. */
14032 static const struct
14034 unsigned int flags;
14035 BOOL unsynchronised;
14037 tests[] =
14039 {0, FALSE},
14040 {DDLOCK_NOOVERWRITE, FALSE},
14041 {DDLOCK_DISCARDCONTENTS, FALSE},
14042 {DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS, FALSE},
14045 static const struct quad
14047 struct
14049 struct vec3 position;
14050 DWORD diffuse;
14051 } strip[4];
14053 quad1 =
14056 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
14057 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
14058 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
14059 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
14062 quad2 =
14065 {{-1.0f, -1.0f, 0.0f}, 0xffffff00},
14066 {{-1.0f, 1.0f, 0.0f}, 0xffffff00},
14067 {{ 1.0f, -1.0f, 0.0f}, 0xffffff00},
14068 {{ 1.0f, 1.0f, 0.0f}, 0xffffff00},
14071 struct quad *quads;
14073 window = create_window();
14074 ok(!!window, "Failed to create a window.\n");
14076 if (!(device = create_device(window, DDSCL_NORMAL)))
14078 skip("Failed to create a D3D device, skipping tests.\n");
14079 DestroyWindow(window);
14080 return;
14083 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
14084 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
14086 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
14087 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
14088 viewport = create_viewport(device, 0, 0, 640, 480);
14089 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
14090 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
14092 tri_count = 0x1000;
14094 ret = QueryPerformanceFrequency(&frequency);
14095 ok(ret, "Failed to get performance counter frequency.\n");
14097 vb_desc.dwSize = sizeof(vb_desc);
14098 vb_desc.dwCaps = D3DVBCAPS_WRITEONLY;
14099 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
14100 vb_desc.dwNumVertices = tri_count + 2;
14101 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &buffer, 0, NULL);
14102 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
14103 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&quads, NULL);
14104 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
14105 for (j = 0; j < vb_desc.dwNumVertices / 4; ++j)
14107 quads[j] = quad1;
14109 hr = IDirect3DVertexBuffer_Unlock(buffer);
14110 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
14112 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
14113 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
14115 /* Initial draw to initialise states, compile shaders, etc. */
14116 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14117 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14118 hr = IDirect3DDevice3_BeginScene(device);
14119 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14120 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
14121 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14122 hr = IDirect3DDevice3_EndScene(device);
14123 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14124 /* Read the result to ensure the GPU has finished drawing. */
14125 colour = get_surface_color(rt, 320, 240);
14127 /* Time drawing tri_count triangles. */
14128 ret = QueryPerformanceCounter(&ts[0]);
14129 ok(ret, "Failed to read performance counter.\n");
14130 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14131 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14132 hr = IDirect3DDevice3_BeginScene(device);
14133 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14134 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
14135 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14136 hr = IDirect3DDevice3_EndScene(device);
14137 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14138 colour = get_surface_color(rt, 320, 240);
14139 /* Time drawing a single triangle. */
14140 ret = QueryPerformanceCounter(&ts[1]);
14141 ok(ret, "Failed to read performance counter.\n");
14142 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14143 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14144 hr = IDirect3DDevice3_BeginScene(device);
14145 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14146 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 3, 0);
14147 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14148 hr = IDirect3DDevice3_EndScene(device);
14149 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14150 colour = get_surface_color(rt, 320, 240);
14151 ret = QueryPerformanceCounter(&ts[2]);
14152 ok(ret, "Failed to read performance counter.\n");
14154 IDirect3DVertexBuffer_Release(buffer);
14156 /* Estimate the number of triangles we can draw in 100ms. */
14157 diff.QuadPart = ts[1].QuadPart - ts[0].QuadPart + ts[1].QuadPart - ts[2].QuadPart;
14158 tri_count = (tri_count * frequency.QuadPart) / (diff.QuadPart * 10);
14159 tri_count = ((tri_count + 2 + 3) & ~3) - 2;
14160 vb_desc.dwNumVertices = tri_count + 2;
14162 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
14164 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &buffer, 0, NULL);
14165 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
14166 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&quads, NULL);
14167 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
14168 for (j = 0; j < vb_desc.dwNumVertices / 4; ++j)
14170 quads[j] = quad1;
14172 hr = IDirect3DVertexBuffer_Unlock(buffer);
14173 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
14175 /* Start a draw operation. */
14176 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14177 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14178 hr = IDirect3DDevice3_BeginScene(device);
14179 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14180 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
14181 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14182 hr = IDirect3DDevice3_EndScene(device);
14183 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14185 /* Map the last quad while the draw is in progress. */
14186 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_WAIT | tests[i].flags, (void **)&quads, NULL);
14187 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
14188 quads[(vb_desc.dwNumVertices / 4) - 1] = quad2;
14189 hr = IDirect3DVertexBuffer_Unlock(buffer);
14190 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
14192 colour = get_surface_color(rt, 320, 240);
14193 unsynchronised = compare_color(colour, 0x00ffff00, 1);
14194 ok(tests[i].unsynchronised == unsynchronised, "Expected %s map for flags %#x.\n",
14195 tests[i].unsynchronised ? "unsynchronised" : "synchronised", tests[i].flags);
14197 IDirect3DVertexBuffer_Release(buffer);
14200 destroy_viewport(device, viewport);
14201 IDirectDrawSurface4_Release(rt);
14202 IDirect3D3_Release(d3d);
14203 refcount = IDirect3DDevice3_Release(device);
14204 ok(!refcount, "Device has %u references left.\n", refcount);
14205 DestroyWindow(window);
14208 static void test_depth_readback(void)
14210 DWORD depth, expected_depth, max_diff;
14211 IDirectDrawSurface4 *rt, *ds;
14212 IDirect3DViewport3 *viewport;
14213 DDSURFACEDESC2 surface_desc;
14214 IDirect3DDevice3 *device;
14215 unsigned int i, x, y;
14216 IDirectDraw4 *ddraw;
14217 IDirect3D3 *d3d;
14218 ULONG refcount;
14219 HWND window;
14220 HRESULT hr;
14221 RECT r;
14223 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
14224 static struct
14226 struct vec3 position;
14227 DWORD diffuse;
14229 quad[] =
14231 {{-1.0f, -1.0f, 0.1f}, 0xff00ff00},
14232 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
14233 {{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
14234 {{ 1.0f, 1.0f, 0.9f}, 0xff00ff00},
14237 static const struct
14239 unsigned int z_depth, s_depth, z_mask, s_mask;
14240 BOOL todo;
14242 tests[] =
14244 {16, 0, 0x0000ffff, 0x00000000},
14245 {24, 0, 0x00ffffff, 0x00000000},
14246 {32, 0, 0x00ffffff, 0x00000000},
14247 {32, 8, 0x00ffffff, 0xff000000, TRUE},
14248 {32, 0, 0xffffffff, 0x00000000},
14251 window = create_window();
14252 ok(!!window, "Failed to create a window.\n");
14254 if (!(device = create_device(window, DDSCL_NORMAL)))
14256 skip("Failed to create a D3D device, skipping tests.\n");
14257 DestroyWindow(window);
14258 return;
14261 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
14262 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
14263 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
14264 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
14266 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
14267 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
14268 viewport = create_viewport(device, 0, 0, 640, 480);
14269 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
14270 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
14272 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
14273 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
14275 ds = get_depth_stencil(device);
14276 hr = IDirectDrawSurface4_DeleteAttachedSurface(rt, 0, ds);
14277 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
14278 IDirectDrawSurface4_Release(ds);
14280 for (i = 0; i < ARRAY_SIZE(tests); ++i)
14282 memset(&surface_desc, 0, sizeof(surface_desc));
14283 surface_desc.dwSize = sizeof(surface_desc);
14284 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
14285 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
14286 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
14287 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
14288 if (tests[i].s_depth)
14289 U4(surface_desc).ddpfPixelFormat.dwFlags |= DDPF_STENCILBUFFER;
14290 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = tests[i].z_depth;
14291 U2(U4(surface_desc).ddpfPixelFormat).dwStencilBitDepth = tests[i].s_depth;
14292 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = tests[i].z_mask;
14293 U4(U4(surface_desc).ddpfPixelFormat).dwStencilBitMask = tests[i].s_mask;
14294 surface_desc.dwWidth = 640;
14295 surface_desc.dwHeight = 480;
14296 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &ds, NULL);
14297 if (FAILED(hr))
14299 skip("Format %u not supported, skipping test.\n", i);
14300 continue;
14303 hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
14304 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
14305 hr = IDirect3DDevice3_SetRenderTarget(device, rt, 0);
14306 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
14308 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect,
14309 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
14310 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14311 hr = IDirect3DDevice3_BeginScene(device);
14312 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14313 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0);
14314 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14315 hr = IDirect3DDevice3_EndScene(device);
14316 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14318 for (y = 60; y < 480; y += 120)
14320 for (x = 80; x < 640; x += 160)
14322 SetRect(&r, x, y, x + 1, y + 1);
14323 memset(&surface_desc, 0, sizeof(surface_desc));
14324 surface_desc.dwSize = sizeof(surface_desc);
14325 hr = IDirectDrawSurface4_Lock(ds, &r, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
14326 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14328 depth = *((DWORD *)surface_desc.lpSurface) & tests[i].z_mask;
14329 expected_depth = (x * (0.9 / 640.0) + y * (0.1 / 480.0)) * tests[i].z_mask;
14330 max_diff = ((0.5f * 0.9f) / 640.0f) * tests[i].z_mask;
14331 todo_wine_if(tests[i].todo)
14332 ok(abs(expected_depth - depth) <= max_diff,
14333 "Test %u: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n",
14334 i, depth, expected_depth - depth, expected_depth, max_diff, x, y);
14336 hr = IDirectDrawSurface4_Unlock(ds, &r);
14337 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14341 hr = IDirectDrawSurface4_DeleteAttachedSurface(rt, 0, ds);
14342 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
14343 IDirectDrawSurface4_Release(ds);
14346 destroy_viewport(device, viewport);
14347 IDirectDrawSurface4_Release(rt);
14348 IDirectDraw4_Release(ddraw);
14349 IDirect3D3_Release(d3d);
14350 refcount = IDirect3DDevice3_Release(device);
14351 ok(!refcount, "Device has %u references left.\n", refcount);
14352 DestroyWindow(window);
14355 static void test_clear(void)
14357 D3DRECT rect_negneg, rect_full = {{0}, {0}, {640}, {480}};
14358 IDirect3DViewport3 *viewport, *viewport2, *viewport3;
14359 IDirect3DDevice3 *device;
14360 IDirectDrawSurface4 *rt;
14361 IDirectDraw4 *ddraw;
14362 IDirect3D3 *d3d;
14363 D3DRECT rect[2];
14364 D3DCOLOR color;
14365 ULONG refcount;
14366 HWND window;
14367 HRESULT hr;
14369 window = create_window();
14370 if (!(device = create_device(window, DDSCL_NORMAL)))
14372 skip("Failed to create 3D device.\n");
14373 DestroyWindow(window);
14374 return;
14377 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
14378 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
14379 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
14380 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
14382 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
14383 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
14385 viewport = create_viewport(device, 0, 0, 640, 480);
14386 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
14387 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
14389 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
14390 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14392 /* Positive x, negative y. */
14393 U1(rect[0]).x1 = 0;
14394 U2(rect[0]).y1 = 480;
14395 U3(rect[0]).x2 = 320;
14396 U4(rect[0]).y2 = 240;
14398 /* Positive x, positive y. */
14399 U1(rect[1]).x1 = 0;
14400 U2(rect[1]).y1 = 0;
14401 U3(rect[1]).x2 = 320;
14402 U4(rect[1]).y2 = 240;
14404 /* Clear 2 rectangles with one call. Unlike d3d8/9, the refrast does not
14405 * refuse negative rectangles, but it will not clear them either. */
14406 hr = IDirect3DViewport3_Clear2(viewport, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
14407 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14409 color = get_surface_color(rt, 160, 360);
14410 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 3 (pos, neg) has color 0x%08x.\n", color);
14411 color = get_surface_color(rt, 160, 120);
14412 ok(compare_color(color, 0x00ff0000, 0), "Clear rectangle 1 (pos, pos) has color 0x%08x.\n", color);
14413 color = get_surface_color(rt, 480, 360);
14414 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (NULL) has color 0x%08x.\n", color);
14415 color = get_surface_color(rt, 480, 120);
14416 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (neg, neg) has color 0x%08x.\n", color);
14418 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
14419 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14420 /* negative x, negative y.
14421 * Also ignored, except on WARP, which clears the entire screen. */
14422 rect_negneg.x1 = 640;
14423 rect_negneg.y1 = 240;
14424 rect_negneg.x2 = 320;
14425 rect_negneg.y2 = 0;
14426 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
14427 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14429 color = get_surface_color(rt, 160, 360);
14430 ok(compare_color(color, 0x00ffffff, 0)
14431 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14432 "Got unexpected color 0x%08x.\n", color);
14433 color = get_surface_color(rt, 160, 120);
14434 ok(compare_color(color, 0x00ffffff, 0)
14435 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14436 "Got unexpected color 0x%08x.\n", color);
14437 color = get_surface_color(rt, 480, 360);
14438 ok(compare_color(color, 0x00ffffff, 0)
14439 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14440 "Got unexpected color 0x%08x.\n", color);
14441 color = get_surface_color(rt, 480, 120);
14442 ok(compare_color(color, 0x00ffffff, 0)
14443 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14444 "Got unexpected color 0x%08x.\n", color);
14446 /* Test how the viewport affects clears. */
14447 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
14448 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14450 viewport2 = create_viewport(device, 160, 120, 160, 120);
14451 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport2);
14452 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
14454 hr = IDirect3DViewport3_Clear2(viewport2, 1, &rect_full, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14455 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14457 viewport3 = create_viewport(device, 320, 240, 320, 240);
14458 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport3);
14459 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
14461 U1(rect[0]).x1 = 160;
14462 U2(rect[0]).y1 = 120;
14463 U3(rect[0]).x2 = 480;
14464 U4(rect[0]).y2 = 360;
14465 hr = IDirect3DViewport3_Clear2(viewport3, 1, &rect[0], D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
14466 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14468 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
14469 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
14471 color = get_surface_color(rt, 158, 118);
14472 ok(compare_color(color, 0x00ffffff, 0), "(158, 118) has color 0x%08x.\n", color);
14473 color = get_surface_color(rt, 162, 118);
14474 ok(compare_color(color, 0x00ffffff, 0), "(162, 118) has color 0x%08x.\n", color);
14475 color = get_surface_color(rt, 158, 122);
14476 ok(compare_color(color, 0x00ffffff, 0), "(158, 122) has color 0x%08x.\n", color);
14477 color = get_surface_color(rt, 162, 122);
14478 ok(compare_color(color, 0x000000ff, 0), "(162, 122) has color 0x%08x.\n", color);
14480 color = get_surface_color(rt, 318, 238);
14481 ok(compare_color(color, 0x000000ff, 0), "(318, 238) has color 0x%08x.\n", color);
14482 color = get_surface_color(rt, 322, 238);
14483 ok(compare_color(color, 0x00ffffff, 0), "(322, 328) has color 0x%08x.\n", color);
14484 color = get_surface_color(rt, 318, 242);
14485 ok(compare_color(color, 0x00ffffff, 0), "(318, 242) has color 0x%08x.\n", color);
14486 color = get_surface_color(rt, 322, 242);
14487 ok(compare_color(color, 0x0000ff00, 0), "(322, 242) has color 0x%08x.\n", color);
14489 color = get_surface_color(rt, 478, 358);
14490 ok(compare_color(color, 0x0000ff00, 0), "(478, 358) has color 0x%08x.\n", color);
14491 color = get_surface_color(rt, 482, 358);
14492 ok(compare_color(color, 0x00ffffff, 0), "(482, 358) has color 0x%08x.\n", color);
14493 color = get_surface_color(rt, 478, 362);
14494 ok(compare_color(color, 0x00ffffff, 0), "(478, 362) has color 0x%08x.\n", color);
14495 color = get_surface_color(rt, 482, 362);
14496 ok(compare_color(color, 0x00ffffff, 0), "(482, 362) has color 0x%08x.\n", color);
14498 /* The clear rectangle is rendertarget absolute, not relative to the
14499 * viewport. */
14500 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
14501 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14502 U1(rect[0]).x1 = 330;
14503 U2(rect[0]).y1 = 250;
14504 U3(rect[0]).x2 = 340;
14505 U4(rect[0]).y2 = 260;
14506 hr = IDirect3DViewport3_Clear2(viewport3, 1, &rect[0], D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
14507 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14509 color = get_surface_color(rt, 328, 248);
14510 ok(compare_color(color, 0x00ffffff, 0), "(328, 248) has color 0x%08x.\n", color);
14511 color = get_surface_color(rt, 332, 248);
14512 ok(compare_color(color, 0x00ffffff, 0), "(332, 248) has color 0x%08x.\n", color);
14513 color = get_surface_color(rt, 328, 252);
14514 ok(compare_color(color, 0x00ffffff, 0), "(328, 252) has color 0x%08x.\n", color);
14515 color = get_surface_color(rt, 332, 252);
14516 ok(compare_color(color, 0x0000ff00, 0), "(332, 252) has color 0x%08x.\n", color);
14518 color = get_surface_color(rt, 338, 248);
14519 ok(compare_color(color, 0x00ffffff, 0), "(338, 248) has color 0x%08x.\n", color);
14520 color = get_surface_color(rt, 342, 248);
14521 ok(compare_color(color, 0x00ffffff, 0), "(342, 248) has color 0x%08x.\n", color);
14522 color = get_surface_color(rt, 338, 252);
14523 ok(compare_color(color, 0x0000ff00, 0), "(338, 252) has color 0x%08x.\n", color);
14524 color = get_surface_color(rt, 342, 252);
14525 ok(compare_color(color, 0x00ffffff, 0), "(342, 252) has color 0x%08x.\n", color);
14527 color = get_surface_color(rt, 328, 258);
14528 ok(compare_color(color, 0x00ffffff, 0), "(328, 258) has color 0x%08x.\n", color);
14529 color = get_surface_color(rt, 332, 258);
14530 ok(compare_color(color, 0x0000ff00, 0), "(332, 258) has color 0x%08x.\n", color);
14531 color = get_surface_color(rt, 328, 262);
14532 ok(compare_color(color, 0x00ffffff, 0), "(328, 262) has color 0x%08x.\n", color);
14533 color = get_surface_color(rt, 332, 262);
14534 ok(compare_color(color, 0x00ffffff, 0), "(332, 262) has color 0x%08x.\n", color);
14536 color = get_surface_color(rt, 338, 258);
14537 ok(compare_color(color, 0x0000ff00, 0), "(338, 258) has color 0x%08x.\n", color);
14538 color = get_surface_color(rt, 342, 258);
14539 ok(compare_color(color, 0x00ffffff, 0), "(342, 258) has color 0x%08x.\n", color);
14540 color = get_surface_color(rt, 338, 262);
14541 ok(compare_color(color, 0x00ffffff, 0), "(338, 262) has color 0x%08x.\n", color);
14542 color = get_surface_color(rt, 342, 262);
14543 ok(compare_color(color, 0x00ffffff, 0), "(342, 262) has color 0x%08x.\n", color);
14545 /* COLORWRITEENABLE, SRGBWRITEENABLE and scissor rectangles do not exist
14546 * in d3d3. */
14548 IDirect3DViewport3_Release(viewport3);
14549 IDirect3DViewport3_Release(viewport2);
14550 IDirect3DViewport3_Release(viewport);
14551 IDirectDrawSurface4_Release(rt);
14552 IDirectDraw4_Release(ddraw);
14553 IDirect3D3_Release(d3d);
14554 refcount = IDirect3DDevice3_Release(device);
14555 ok(!refcount, "Device has %u references left.\n", refcount);
14556 DestroyWindow(window);
14559 START_TEST(ddraw4)
14561 DDDEVICEIDENTIFIER identifier;
14562 DEVMODEW current_mode;
14563 IDirectDraw4 *ddraw;
14564 HMODULE dwmapi;
14566 if (!(ddraw = create_ddraw()))
14568 skip("Failed to create a ddraw object, skipping tests.\n");
14569 return;
14572 if (ddraw_get_identifier(ddraw, &identifier))
14574 trace("Driver string: \"%s\"\n", identifier.szDriver);
14575 trace("Description string: \"%s\"\n", identifier.szDescription);
14576 trace("Driver version %d.%d.%d.%d\n",
14577 HIWORD(U(identifier.liDriverVersion).HighPart), LOWORD(U(identifier.liDriverVersion).HighPart),
14578 HIWORD(U(identifier.liDriverVersion).LowPart), LOWORD(U(identifier.liDriverVersion).LowPart));
14580 IDirectDraw4_Release(ddraw);
14582 memset(&current_mode, 0, sizeof(current_mode));
14583 current_mode.dmSize = sizeof(current_mode);
14584 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
14585 registry_mode.dmSize = sizeof(registry_mode);
14586 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
14587 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
14588 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
14590 skip("Current mode does not match registry mode, skipping test.\n");
14591 return;
14594 if ((dwmapi = LoadLibraryA("dwmapi.dll")))
14595 pDwmIsCompositionEnabled = (void *)GetProcAddress(dwmapi, "DwmIsCompositionEnabled");
14597 test_process_vertices();
14598 test_coop_level_create_device_window();
14599 test_clipper_blt();
14600 test_coop_level_d3d_state();
14601 test_surface_interface_mismatch();
14602 test_coop_level_threaded();
14603 test_depth_blit();
14604 test_texture_load_ckey();
14605 test_viewport();
14606 test_zenable();
14607 test_ck_rgba();
14608 test_ck_default();
14609 test_ck_complex();
14610 test_surface_qi();
14611 test_device_qi();
14612 test_wndproc();
14613 test_window_style();
14614 test_redundant_mode_set();
14615 test_coop_level_mode_set();
14616 test_coop_level_mode_set_multi();
14617 test_initialize();
14618 test_coop_level_surf_create();
14619 test_vb_discard();
14620 test_coop_level_multi_window();
14621 test_draw_strided();
14622 test_lighting();
14623 test_specular_lighting();
14624 test_clear_rect_count();
14625 test_coop_level_versions();
14626 test_lighting_interface_versions();
14627 test_coop_level_activateapp();
14628 test_texturemanage();
14629 test_block_formats_creation();
14630 test_unsupported_formats();
14631 test_rt_caps();
14632 test_primary_caps();
14633 test_surface_lock();
14634 test_surface_discard();
14635 test_flip();
14636 test_set_surface_desc();
14637 test_user_memory_getdc();
14638 test_sysmem_overlay();
14639 test_primary_palette();
14640 test_surface_attachment();
14641 test_private_data();
14642 test_pixel_format();
14643 test_create_surface_pitch();
14644 test_mipmap();
14645 test_palette_complex();
14646 test_p8_blit();
14647 test_material();
14648 test_palette_gdi();
14649 test_palette_alpha();
14650 test_vb_writeonly();
14651 test_lost_device();
14652 test_surface_desc_lock();
14653 test_texturemapblend();
14654 test_signed_formats();
14655 test_color_fill();
14656 test_texcoordindex();
14657 test_colorkey_precision();
14658 test_range_colorkey();
14659 test_shademode();
14660 test_lockrect_invalid();
14661 test_yv12_overlay();
14662 test_offscreen_overlay();
14663 test_overlay_rect();
14664 test_blt();
14665 test_blt_z_alpha();
14666 test_color_clamping();
14667 test_getdc();
14668 test_draw_primitive();
14669 test_edge_antialiasing_blending();
14670 test_transform_vertices();
14671 test_display_mode_surface_pixel_format();
14672 test_surface_desc_size();
14673 test_get_surface_from_dc();
14674 test_ck_operation();
14675 test_vb_refcount();
14676 test_compute_sphere_visibility();
14677 test_map_synchronisation();
14678 test_depth_readback();
14679 test_clear();