wined3d: Drop support for WINED3DFMT_D32_UNORM.
[wine.git] / dlls / ddraw / tests / ddraw4.c
blobbc58c1817c362c58c408d3d1305e3248f87550db
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 "wine/heap.h"
24 #include <limits.h>
25 #include <math.h>
26 #include "ddrawi.h"
27 #include "d3dhal.h"
29 HRESULT WINAPI GetSurfaceFromDC(HDC dc, struct IDirectDrawSurface **surface, HDC *device_dc);
31 static BOOL is_ddraw64 = sizeof(DWORD) != sizeof(DWORD *);
32 static DEVMODEW registry_mode;
34 static HRESULT (WINAPI *pDwmIsCompositionEnabled)(BOOL *);
36 struct vec2
38 float x, y;
41 struct vec3
43 float x, y, z;
46 struct vec4
48 float x, y, z, w;
51 struct create_window_thread_param
53 HWND window;
54 HANDLE window_created;
55 HANDLE destroy_window;
56 HANDLE thread;
59 static BOOL compare_float(float f, float g, unsigned int ulps)
61 int x = *(int *)&f;
62 int y = *(int *)&g;
64 if (x < 0)
65 x = INT_MIN - x;
66 if (y < 0)
67 y = INT_MIN - y;
69 if (abs(x - y) > ulps)
70 return FALSE;
72 return TRUE;
75 static BOOL compare_vec4(const struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
77 return compare_float(vec->x, x, ulps)
78 && compare_float(vec->y, y, ulps)
79 && compare_float(vec->z, z, ulps)
80 && compare_float(vec->w, w, ulps);
83 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
85 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
86 c1 >>= 8; c2 >>= 8;
87 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
88 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 return TRUE;
95 static BOOL ddraw_get_identifier(IDirectDraw4 *ddraw, DDDEVICEIDENTIFIER *identifier)
97 HRESULT hr;
99 hr = IDirectDraw4_GetDeviceIdentifier(ddraw, identifier, 0);
100 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#x.\n", hr);
102 return SUCCEEDED(hr);
105 static BOOL ddraw_is_warp(IDirectDraw4 *ddraw)
107 DDDEVICEIDENTIFIER identifier;
109 return strcmp(winetest_platform, "wine")
110 && ddraw_get_identifier(ddraw, &identifier)
111 && strstr(identifier.szDriver, "warp");
114 static BOOL ddraw_is_vendor(IDirectDraw4 *ddraw, DWORD vendor)
116 DDDEVICEIDENTIFIER identifier;
118 return strcmp(winetest_platform, "wine")
119 && ddraw_get_identifier(ddraw, &identifier)
120 && identifier.dwVendorId == vendor;
123 static BOOL ddraw_is_intel(IDirectDraw4 *ddraw)
125 return ddraw_is_vendor(ddraw, 0x8086);
128 static BOOL ddraw_is_nvidia(IDirectDraw4 *ddraw)
130 return ddraw_is_vendor(ddraw, 0x10de);
133 static BOOL ddraw_is_vmware(IDirectDraw4 *ddraw)
135 return ddraw_is_vendor(ddraw, 0x15ad);
138 static IDirectDrawSurface4 *create_overlay(IDirectDraw4 *ddraw,
139 unsigned int width, unsigned int height, DWORD format)
141 IDirectDrawSurface4 *surface;
142 DDSURFACEDESC2 desc;
144 memset(&desc, 0, sizeof(desc));
145 desc.dwSize = sizeof(desc);
146 desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
147 desc.dwWidth = width;
148 desc.dwHeight = height;
149 desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
150 U4(desc).ddpfPixelFormat.dwSize = sizeof(U4(desc).ddpfPixelFormat);
151 U4(desc).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
152 U4(desc).ddpfPixelFormat.dwFourCC = format;
154 if (FAILED(IDirectDraw4_CreateSurface(ddraw, &desc, &surface, NULL)))
155 return NULL;
156 return surface;
159 static HWND create_window(void)
161 RECT r = {0, 0, 640, 480};
163 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
165 return CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
166 CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
169 static DWORD WINAPI create_window_thread_proc(void *param)
171 struct create_window_thread_param *p = param;
172 DWORD res;
173 BOOL ret;
175 p->window = create_window();
176 ret = SetEvent(p->window_created);
177 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
179 for (;;)
181 MSG msg;
183 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
184 DispatchMessageA(&msg);
185 res = WaitForSingleObject(p->destroy_window, 100);
186 if (res == WAIT_OBJECT_0)
187 break;
188 if (res != WAIT_TIMEOUT)
190 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
191 break;
195 DestroyWindow(p->window);
197 return 0;
200 static void create_window_thread(struct create_window_thread_param *p)
202 DWORD res, tid;
204 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
205 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
206 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
207 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
208 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
209 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
210 res = WaitForSingleObject(p->window_created, INFINITE);
211 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
214 static void destroy_window_thread(struct create_window_thread_param *p)
216 SetEvent(p->destroy_window);
217 WaitForSingleObject(p->thread, INFINITE);
218 CloseHandle(p->destroy_window);
219 CloseHandle(p->window_created);
220 CloseHandle(p->thread);
223 static IDirectDrawSurface4 *get_depth_stencil(IDirect3DDevice3 *device)
225 IDirectDrawSurface4 *rt, *ret;
226 DDSCAPS2 caps = {DDSCAPS_ZBUFFER, 0, 0, {0}};
227 HRESULT hr;
229 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
230 ok(SUCCEEDED(hr), "Failed to get the render target, hr %#x.\n", hr);
231 hr = IDirectDrawSurface4_GetAttachedSurface(rt, &caps, &ret);
232 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
233 IDirectDrawSurface4_Release(rt);
234 return ret;
237 static HRESULT set_display_mode(IDirectDraw4 *ddraw, DWORD width, DWORD height)
239 if (SUCCEEDED(IDirectDraw4_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
240 return DD_OK;
241 return IDirectDraw4_SetDisplayMode(ddraw, width, height, 24, 0, 0);
244 static D3DCOLOR get_surface_color(IDirectDrawSurface4 *surface, UINT x, UINT y)
246 RECT rect = {x, y, x + 1, y + 1};
247 DDSURFACEDESC2 surface_desc;
248 D3DCOLOR color;
249 HRESULT hr;
251 memset(&surface_desc, 0, sizeof(surface_desc));
252 surface_desc.dwSize = sizeof(surface_desc);
254 hr = IDirectDrawSurface4_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
255 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
256 if (FAILED(hr))
257 return 0xdeadbeef;
259 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
261 hr = IDirectDrawSurface4_Unlock(surface, &rect);
262 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
264 return color;
267 static void check_rect(IDirectDrawSurface4 *surface, RECT r, const char *message)
269 LONG x_coords[2][2] =
271 {r.left - 1, r.left + 1},
272 {r.right + 1, r.right - 1},
274 LONG y_coords[2][2] =
276 {r.top - 1, r.top + 1},
277 {r.bottom + 1, r.bottom - 1}
279 unsigned int i, j, x_side, y_side;
280 DWORD color;
281 LONG x, y;
283 for (i = 0; i < 2; ++i)
285 for (j = 0; j < 2; ++j)
287 for (x_side = 0; x_side < 2; ++x_side)
289 for (y_side = 0; y_side < 2; ++y_side)
291 DWORD expected = (x_side == 1 && y_side == 1) ? 0x00ffffff : 0x00000000;
293 x = x_coords[i][x_side];
294 y = y_coords[j][y_side];
295 if (x < 0 || x >= 640 || y < 0 || y >= 480)
296 continue;
297 color = get_surface_color(surface, x, y);
298 ok(color == expected, "%s: Pixel (%d, %d) has color %08x, expected %08x\n",
299 message, x, y, color, expected);
306 static HRESULT CALLBACK enum_z_fmt(DDPIXELFORMAT *format, void *ctx)
308 DDPIXELFORMAT *z_fmt = ctx;
310 if (U1(*format).dwZBufferBitDepth > U1(*z_fmt).dwZBufferBitDepth)
311 *z_fmt = *format;
313 return DDENUMRET_OK;
316 static IDirectDraw4 *create_ddraw(void)
318 IDirectDraw4 *ddraw4;
319 IDirectDraw *ddraw1;
320 HRESULT hr;
322 if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
323 return NULL;
325 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw4, (void **)&ddraw4);
326 IDirectDraw_Release(ddraw1);
327 if (FAILED(hr))
328 return NULL;
330 return ddraw4;
333 static IDirect3DDevice3 *create_device(HWND window, DWORD coop_level)
335 IDirectDrawSurface4 *surface, *ds;
336 IDirect3DDevice3 *device = NULL;
337 DDSURFACEDESC2 surface_desc;
338 IDirectDraw4 *ddraw4;
339 DDPIXELFORMAT z_fmt;
340 IDirect3D3 *d3d3;
341 HRESULT hr;
343 if (!(ddraw4 = create_ddraw()))
344 return NULL;
346 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, coop_level);
347 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
349 memset(&surface_desc, 0, sizeof(surface_desc));
350 surface_desc.dwSize = sizeof(surface_desc);
351 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
352 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
353 surface_desc.dwWidth = 640;
354 surface_desc.dwHeight = 480;
356 hr = IDirectDraw4_CreateSurface(ddraw4, &surface_desc, &surface, NULL);
357 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
359 if (coop_level & DDSCL_NORMAL)
361 IDirectDrawClipper *clipper;
363 hr = IDirectDraw4_CreateClipper(ddraw4, 0, &clipper, NULL);
364 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
365 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
366 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
367 hr = IDirectDrawSurface4_SetClipper(surface, clipper);
368 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
369 IDirectDrawClipper_Release(clipper);
372 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirect3D3, (void **)&d3d3);
373 IDirectDraw4_Release(ddraw4);
374 if (FAILED(hr))
376 IDirectDrawSurface4_Release(surface);
377 return NULL;
380 memset(&z_fmt, 0, sizeof(z_fmt));
381 hr = IDirect3D3_EnumZBufferFormats(d3d3, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
382 if (FAILED(hr) || !z_fmt.dwSize)
384 IDirect3D3_Release(d3d3);
385 IDirectDrawSurface4_Release(surface);
386 return NULL;
389 memset(&surface_desc, 0, sizeof(surface_desc));
390 surface_desc.dwSize = sizeof(surface_desc);
391 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
392 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
393 U4(surface_desc).ddpfPixelFormat = z_fmt;
394 surface_desc.dwWidth = 640;
395 surface_desc.dwHeight = 480;
396 hr = IDirectDraw4_CreateSurface(ddraw4, &surface_desc, &ds, NULL);
397 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
398 if (FAILED(hr))
400 IDirect3D3_Release(d3d3);
401 IDirectDrawSurface4_Release(surface);
402 return NULL;
405 hr = IDirectDrawSurface4_AddAttachedSurface(surface, ds);
406 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
407 IDirectDrawSurface4_Release(ds);
408 if (FAILED(hr))
410 IDirect3D3_Release(d3d3);
411 IDirectDrawSurface4_Release(surface);
412 return NULL;
415 hr = IDirect3D3_CreateDevice(d3d3, &IID_IDirect3DHALDevice, surface, &device, NULL);
416 IDirect3D3_Release(d3d3);
417 IDirectDrawSurface4_Release(surface);
418 if (FAILED(hr))
419 return NULL;
421 return device;
424 static IDirect3DViewport3 *create_viewport(IDirect3DDevice3 *device, UINT x, UINT y, UINT w, UINT h)
426 IDirect3DViewport3 *viewport;
427 D3DVIEWPORT2 vp;
428 IDirect3D3 *d3d;
429 HRESULT hr;
431 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
432 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
433 hr = IDirect3D3_CreateViewport(d3d, &viewport, NULL);
434 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
435 hr = IDirect3DDevice3_AddViewport(device, viewport);
436 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
437 memset(&vp, 0, sizeof(vp));
438 vp.dwSize = sizeof(vp);
439 vp.dwX = x;
440 vp.dwY = y;
441 vp.dwWidth = w;
442 vp.dwHeight = h;
443 vp.dvClipX = -1.0f;
444 vp.dvClipY = 1.0f;
445 vp.dvClipWidth = 2.0f;
446 vp.dvClipHeight = 2.0f;
447 vp.dvMinZ = 0.0f;
448 vp.dvMaxZ = 1.0f;
449 hr = IDirect3DViewport3_SetViewport2(viewport, &vp);
450 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
451 IDirect3D3_Release(d3d);
453 return viewport;
456 static void destroy_viewport(IDirect3DDevice3 *device, IDirect3DViewport3 *viewport)
458 HRESULT hr;
460 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
461 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
462 IDirect3DViewport3_Release(viewport);
465 static IDirect3DMaterial3 *create_material(IDirect3DDevice3 *device, D3DMATERIAL *mat)
467 IDirect3DMaterial3 *material;
468 IDirect3D3 *d3d;
469 HRESULT hr;
471 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
472 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
473 hr = IDirect3D3_CreateMaterial(d3d, &material, NULL);
474 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
475 hr = IDirect3DMaterial3_SetMaterial(material, mat);
476 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
477 IDirect3D3_Release(d3d);
479 return material;
482 static IDirect3DMaterial3 *create_diffuse_material(IDirect3DDevice3 *device, float r, float g, float b, float a)
484 D3DMATERIAL mat;
486 memset(&mat, 0, sizeof(mat));
487 mat.dwSize = sizeof(mat);
488 U1(U(mat).diffuse).r = r;
489 U2(U(mat).diffuse).g = g;
490 U3(U(mat).diffuse).b = b;
491 U4(U(mat).diffuse).a = a;
493 return create_material(device, &mat);
496 static IDirect3DMaterial3 *create_diffuse_and_ambient_material(IDirect3DDevice3 *device,
497 float r, float g, float b, float a)
499 D3DMATERIAL mat;
501 memset(&mat, 0, sizeof(mat));
502 mat.dwSize = sizeof(mat);
503 U1(U(mat).diffuse).r = r;
504 U2(U(mat).diffuse).g = g;
505 U3(U(mat).diffuse).b = b;
506 U4(U(mat).diffuse).a = a;
508 U1(U(mat).ambient).r = r;
509 U2(U(mat).ambient).g = g;
510 U3(U(mat).ambient).b = b;
511 U4(U(mat).ambient).a = a;
513 return create_material(device, &mat);
516 static IDirect3DMaterial3 *create_specular_material(IDirect3DDevice3 *device,
517 float r, float g, float b, float a, float power)
519 D3DMATERIAL mat;
521 memset(&mat, 0, sizeof(mat));
522 mat.dwSize = sizeof(mat);
523 U1(U2(mat).specular).r = r;
524 U2(U2(mat).specular).g = g;
525 U3(U2(mat).specular).b = b;
526 U4(U2(mat).specular).a = a;
527 U4(mat).power = power;
529 return create_material(device, &mat);
532 static IDirect3DMaterial3 *create_emissive_material(IDirect3DDevice3 *device, float r, float g, float b, float a)
534 D3DMATERIAL mat;
536 memset(&mat, 0, sizeof(mat));
537 mat.dwSize = sizeof(mat);
538 U1(U3(mat).emissive).r = r;
539 U2(U3(mat).emissive).g = g;
540 U3(U3(mat).emissive).b = b;
541 U4(U3(mat).emissive).a = a;
543 return create_material(device, &mat);
546 static void destroy_material(IDirect3DMaterial3 *material)
548 IDirect3DMaterial3_Release(material);
551 struct message
553 UINT message;
554 BOOL check_wparam;
555 WPARAM expect_wparam;
556 HRESULT ddraw_state;
559 static const struct message *expect_messages;
560 static IDirectDraw4 *focus_test_ddraw;
562 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
564 HRESULT hr;
566 if (expect_messages && message == expect_messages->message)
568 if (expect_messages->check_wparam)
569 ok (wparam == expect_messages->expect_wparam,
570 "Got unexpected wparam %lx for message %x, expected %lx.\n",
571 wparam, message, expect_messages->expect_wparam);
573 if (focus_test_ddraw)
575 hr = IDirectDraw4_TestCooperativeLevel(focus_test_ddraw);
576 ok(hr == expect_messages->ddraw_state, "Got ddraw state %#x on message %#x, expected %#x.\n",
577 hr, message, expect_messages->ddraw_state);
580 ++expect_messages;
583 return DefWindowProcA(hwnd, message, wparam, lparam);
586 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
587 * interface. This prevents subsequent SetCooperativeLevel() calls on a
588 * different window from failing with DDERR_HWNDALREADYSET. */
589 static void fix_wndproc(HWND window, LONG_PTR proc)
591 IDirectDraw4 *ddraw;
592 HRESULT hr;
594 if (!(ddraw = create_ddraw()))
595 return;
597 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
598 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
599 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
600 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
601 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
603 IDirectDraw4_Release(ddraw);
606 static void test_process_vertices(void)
608 IDirect3DVertexBuffer *src_vb, *dst_vb;
609 IDirect3DViewport3 *viewport;
610 D3DVERTEXBUFFERDESC vb_desc;
611 IDirect3DDevice3 *device;
612 struct vec3 *src_data;
613 struct vec4 *dst_data;
614 IDirect3D3 *d3d3;
615 D3DVIEWPORT2 vp2;
616 D3DVIEWPORT vp1;
617 HWND window;
618 HRESULT hr;
620 static D3DMATRIX identity =
622 1.0f, 0.0f, 0.0f, 0.0f,
623 0.0f, 1.0f, 0.0f, 0.0f,
624 0.0f, 0.0f, 1.0f, 0.0f,
625 0.0f, 0.0f, 0.0f, 1.0f,
627 static D3DMATRIX projection =
629 1.0f, 0.0f, 0.0f, 0.0f,
630 0.0f, 1.0f, 0.0f, 0.0f,
631 0.0f, 0.0f, 1.0f, 0.0f,
632 6.0f, 7.0f, 8.0f, 1.0f,
635 window = create_window();
636 if (!(device = create_device(window, DDSCL_NORMAL)))
638 skip("Failed to create a 3D device, skipping test.\n");
639 DestroyWindow(window);
640 return;
643 hr = IDirect3DDevice3_GetDirect3D(device, &d3d3);
644 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
646 memset(&vb_desc, 0, sizeof(vb_desc));
647 vb_desc.dwSize = sizeof(vb_desc);
648 vb_desc.dwFVF = D3DFVF_XYZ;
649 vb_desc.dwNumVertices = 3;
650 hr = IDirect3D3_CreateVertexBuffer(d3d3, &vb_desc, &src_vb, 0, NULL);
651 ok(SUCCEEDED(hr), "Failed to create source vertex buffer, hr %#x.\n", hr);
653 hr = IDirect3DVertexBuffer_Lock(src_vb, DDLOCK_WRITEONLY, (void **)&src_data, NULL);
654 ok(SUCCEEDED(hr), "Failed to lock source vertex buffer, hr %#x.\n", hr);
655 src_data[0].x = -1.0f;
656 src_data[0].y = -1.0f;
657 src_data[0].z = -1.0f;
658 src_data[1].x = 0.0f;
659 src_data[1].y = 0.0f;
660 src_data[1].z = 0.0f;
661 src_data[2].x = 1.0f;
662 src_data[2].y = 1.0f;
663 src_data[2].z = 1.0f;
664 hr = IDirect3DVertexBuffer_Unlock(src_vb);
665 ok(SUCCEEDED(hr), "Failed to unlock source vertex buffer, hr %#x.\n", hr);
667 memset(&vb_desc, 0, sizeof(vb_desc));
668 vb_desc.dwSize = sizeof(vb_desc);
669 vb_desc.dwFVF = D3DFVF_XYZRHW;
670 vb_desc.dwNumVertices = 3;
671 hr = IDirect3D3_CreateVertexBuffer(d3d3, &vb_desc, &dst_vb, 0, NULL);
672 ok(SUCCEEDED(hr), "Failed to create destination vertex buffer, hr %#x.\n", hr);
674 hr = IDirect3D3_CreateViewport(d3d3, &viewport, NULL);
675 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
676 hr = IDirect3DDevice3_AddViewport(device, viewport);
677 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
678 vp2.dwSize = sizeof(vp2);
679 vp2.dwX = 10;
680 vp2.dwY = 20;
681 vp2.dwWidth = 100;
682 vp2.dwHeight = 200;
683 vp2.dvClipX = 2.0f;
684 vp2.dvClipY = 3.0f;
685 vp2.dvClipWidth = 4.0f;
686 vp2.dvClipHeight = 5.0f;
687 vp2.dvMinZ = -2.0f;
688 vp2.dvMaxZ = 3.0f;
689 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2);
690 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
691 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
692 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
694 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
695 ok(SUCCEEDED(hr), "Failed to set world transformation, hr %#x.\n", hr);
696 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &identity);
697 ok(SUCCEEDED(hr), "Failed to set view transformation, hr %#x.\n", hr);
698 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity);
699 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
701 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
702 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
704 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
705 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
706 ok(compare_vec4(&dst_data[0], -6.500e+1f, +1.800e+2f, +2.000e-1f, +1.000e+0f, 4096),
707 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
708 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
709 ok(compare_vec4(&dst_data[1], -4.000e+1f, +1.400e+2f, +4.000e-1f, +1.000e+0f, 4096),
710 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
711 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
712 ok(compare_vec4(&dst_data[2], -1.500e+1f, +1.000e+2f, +6.000e-1f, +1.000e+0f, 4096),
713 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
714 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
715 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
716 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
718 hr = IDirect3DDevice3_MultiplyTransform(device, D3DTRANSFORMSTATE_PROJECTION, &projection);
719 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
721 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
722 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
724 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
725 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
726 ok(compare_vec4(&dst_data[0], +8.500e+1f, -1.000e+2f, +1.800e+0f, +1.000e+0f, 4096),
727 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
728 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
729 ok(compare_vec4(&dst_data[1], +1.100e+2f, -1.400e+2f, +2.000e+0f, +1.000e+0f, 4096),
730 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
731 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
732 ok(compare_vec4(&dst_data[2], +1.350e+2f, -1.800e+2f, +2.200e+0f, +1.000e+0f, 4096),
733 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
734 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
735 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
736 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
738 vp2.dwSize = sizeof(vp2);
739 vp2.dwX = 30;
740 vp2.dwY = 40;
741 vp2.dwWidth = 90;
742 vp2.dwHeight = 80;
743 vp2.dvClipX = 4.0f;
744 vp2.dvClipY = 6.0f;
745 vp2.dvClipWidth = 2.0f;
746 vp2.dvClipHeight = 4.0f;
747 vp2.dvMinZ = 3.0f;
748 vp2.dvMaxZ = -2.0f;
749 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2);
750 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
752 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
753 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
755 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
756 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
757 ok(compare_vec4(&dst_data[0], +7.500e+1f, +4.000e+1f, -8.000e-1f, +1.000e+0f, 4096),
758 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
759 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
760 ok(compare_vec4(&dst_data[1], +1.200e+2f, +2.000e+1f, -1.000e+0f, +1.000e+0f, 4096),
761 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
762 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
763 ok(compare_vec4(&dst_data[2], +1.650e+2f, +0.000e+0f, -1.200e+0f, +1.000e+0f, 4096),
764 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
765 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
766 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
767 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
769 vp1.dwSize = sizeof(vp1);
770 vp1.dwX = 30;
771 vp1.dwY = 40;
772 vp1.dwWidth = 90;
773 vp1.dwHeight = 80;
774 vp1.dvScaleX = 7.0f;
775 vp1.dvScaleY = 2.0f;
776 vp1.dvMaxX = 6.0f;
777 vp1.dvMaxY = 10.0f;
778 vp1.dvMinZ = -2.0f;
779 vp1.dvMaxZ = 3.0f;
780 hr = IDirect3DViewport3_SetViewport(viewport, &vp1);
781 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
783 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
784 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
786 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
787 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
788 ok(compare_vec4(&dst_data[0], +1.100e+2f, +6.800e+1f, +7.000e+0f, +1.000e+0f, 4096),
789 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
790 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
791 ok(compare_vec4(&dst_data[1], +1.170e+2f, +6.600e+1f, +8.000e+0f, +1.000e+0f, 4096),
792 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
793 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
794 ok(compare_vec4(&dst_data[2], +1.240e+2f, +6.400e+1f, +9.000e+0f, +1.000e+0f, 4096),
795 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
796 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
797 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
798 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
800 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
801 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
803 IDirect3DVertexBuffer_Release(dst_vb);
804 IDirect3DVertexBuffer_Release(src_vb);
805 IDirect3DViewport3_Release(viewport);
806 IDirect3D3_Release(d3d3);
807 IDirect3DDevice3_Release(device);
808 DestroyWindow(window);
811 static void test_coop_level_create_device_window(void)
813 HWND focus_window, device_window;
814 IDirectDraw4 *ddraw;
815 HRESULT hr;
817 focus_window = create_window();
818 ddraw = create_ddraw();
819 ok(!!ddraw, "Failed to create a ddraw object.\n");
821 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
822 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
823 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
824 ok(!device_window, "Unexpected device window found.\n");
825 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
826 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
827 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
828 ok(!device_window, "Unexpected device window found.\n");
829 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
830 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
831 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
832 ok(!device_window, "Unexpected device window found.\n");
833 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
834 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
835 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
836 ok(!device_window, "Unexpected device window found.\n");
837 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
838 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
839 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
840 ok(!device_window, "Unexpected device window found.\n");
842 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
843 if (broken(hr == DDERR_INVALIDPARAMS))
845 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
846 IDirectDraw4_Release(ddraw);
847 DestroyWindow(focus_window);
848 return;
851 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
852 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
853 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
854 ok(!device_window, "Unexpected device window found.\n");
855 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
856 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
857 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
858 ok(!device_window, "Unexpected device window found.\n");
860 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
861 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
862 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
863 ok(!device_window, "Unexpected device window found.\n");
864 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
865 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
866 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
867 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
868 ok(!!device_window, "Device window not found.\n");
870 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
871 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
872 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
873 ok(!device_window, "Unexpected device window found.\n");
874 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
875 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
876 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
877 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
878 ok(!!device_window, "Device window not found.\n");
880 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
881 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
882 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
883 ok(!device_window, "Unexpected device window found.\n");
884 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
885 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
886 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
887 ok(!device_window, "Unexpected device window found.\n");
888 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
889 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
890 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
891 ok(!device_window, "Unexpected device window found.\n");
892 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
893 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
894 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
895 ok(!!device_window, "Device window not found.\n");
897 IDirectDraw4_Release(ddraw);
898 DestroyWindow(focus_window);
901 static void test_clipper_blt(void)
903 IDirectDrawSurface4 *src_surface, *dst_surface;
904 RECT client_rect, src_rect;
905 IDirectDrawClipper *clipper;
906 DDSURFACEDESC2 surface_desc;
907 unsigned int i, j, x, y;
908 IDirectDraw4 *ddraw;
909 RGNDATA *rgn_data;
910 D3DCOLOR color;
911 ULONG refcount;
912 HRGN r1, r2;
913 HWND window;
914 DDBLTFX fx;
915 HRESULT hr;
916 DWORD *ptr;
917 DWORD ret;
919 static const DWORD src_data[] =
921 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
922 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
923 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
925 static const D3DCOLOR expected1[] =
927 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
928 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
929 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
930 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
932 /* Nvidia on Windows seems to have an off-by-one error
933 * when processing source rectangles. Our left = 1 and
934 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
935 * read as well, but only for the edge pixels on the
936 * output image. The bug happens on the y axis as well,
937 * but we only read one row there, and all source rows
938 * contain the same data. This bug is not dependent on
939 * the presence of a clipper. */
940 static const D3DCOLOR expected1_broken[] =
942 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
943 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
944 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
945 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
947 static const D3DCOLOR expected2[] =
949 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
950 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
951 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
952 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
955 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
956 10, 10, 640, 480, 0, 0, 0, 0);
957 ShowWindow(window, SW_SHOW);
958 ddraw = create_ddraw();
959 ok(!!ddraw, "Failed to create a ddraw object.\n");
961 ret = GetClientRect(window, &client_rect);
962 ok(ret, "Failed to get client rect.\n");
963 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
964 ok(ret, "Failed to map client rect.\n");
966 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
967 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
969 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL);
970 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
971 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
972 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
973 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
974 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
975 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
976 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
977 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
978 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
979 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
980 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
981 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
982 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
983 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
984 "Got unexpected bounding rect %s, expected %s.\n",
985 wine_dbgstr_rect(&rgn_data->rdh.rcBound), wine_dbgstr_rect(&client_rect));
986 HeapFree(GetProcessHeap(), 0, rgn_data);
988 r1 = CreateRectRgn(0, 0, 320, 240);
989 ok(!!r1, "Failed to create region.\n");
990 r2 = CreateRectRgn(320, 240, 640, 480);
991 ok(!!r2, "Failed to create region.\n");
992 CombineRgn(r1, r1, r2, RGN_OR);
993 ret = GetRegionData(r1, 0, NULL);
994 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
995 ret = GetRegionData(r1, ret, rgn_data);
996 ok(!!ret, "Failed to get region data.\n");
998 DeleteObject(r2);
999 DeleteObject(r1);
1001 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
1002 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
1003 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
1004 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
1005 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
1006 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
1008 HeapFree(GetProcessHeap(), 0, rgn_data);
1010 memset(&surface_desc, 0, sizeof(surface_desc));
1011 surface_desc.dwSize = sizeof(surface_desc);
1012 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1013 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1014 surface_desc.dwWidth = 640;
1015 surface_desc.dwHeight = 480;
1016 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1017 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
1018 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1019 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1020 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1021 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1023 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
1024 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
1025 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
1026 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1028 memset(&fx, 0, sizeof(fx));
1029 fx.dwSize = sizeof(fx);
1030 hr = IDirectDrawSurface4_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1031 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
1032 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1033 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
1035 hr = IDirectDrawSurface4_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
1036 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
1037 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
1038 ptr = surface_desc.lpSurface;
1039 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
1040 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
1041 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
1042 hr = IDirectDrawSurface4_Unlock(src_surface, NULL);
1043 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
1045 hr = IDirectDrawSurface4_SetClipper(dst_surface, clipper);
1046 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
1048 SetRect(&src_rect, 1, 1, 5, 2);
1049 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
1050 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
1051 for (i = 0; i < 4; ++i)
1053 for (j = 0; j < 4; ++j)
1055 x = 80 * ((2 * j) + 1);
1056 y = 60 * ((2 * i) + 1);
1057 color = get_surface_color(dst_surface, x, y);
1058 ok(compare_color(color, expected1[i * 4 + j], 1)
1059 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
1060 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
1064 U5(fx).dwFillColor = 0xff0000ff;
1065 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1066 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
1067 for (i = 0; i < 4; ++i)
1069 for (j = 0; j < 4; ++j)
1071 x = 80 * ((2 * j) + 1);
1072 y = 60 * ((2 * i) + 1);
1073 color = get_surface_color(dst_surface, x, y);
1074 ok(compare_color(color, expected2[i * 4 + j], 1),
1075 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
1079 hr = IDirectDrawSurface4_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
1080 ok(hr == DDERR_BLTFASTCANTCLIP, "Got unexpected hr %#x.\n", hr);
1082 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
1083 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
1084 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1085 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
1086 DestroyWindow(window);
1087 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1088 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
1089 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
1090 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
1091 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1092 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
1093 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
1094 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
1095 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1096 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
1097 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1098 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
1100 IDirectDrawSurface4_Release(dst_surface);
1101 IDirectDrawSurface4_Release(src_surface);
1102 refcount = IDirectDrawClipper_Release(clipper);
1103 ok(!refcount, "Clipper has %u references left.\n", refcount);
1104 IDirectDraw4_Release(ddraw);
1107 static void test_coop_level_d3d_state(void)
1109 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1110 IDirectDrawSurface4 *rt, *surface;
1111 IDirect3DViewport3 *viewport;
1112 IDirect3DDevice3 *device;
1113 IDirectDraw4 *ddraw;
1114 IDirect3D3 *d3d;
1115 D3DCOLOR color;
1116 DWORD value;
1117 HWND window;
1118 HRESULT hr;
1120 window = create_window();
1121 if (!(device = create_device(window, DDSCL_NORMAL)))
1123 skip("Failed to create a 3D device, skipping test.\n");
1124 DestroyWindow(window);
1125 return;
1128 viewport = create_viewport(device, 0, 0, 640, 480);
1130 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1131 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1132 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
1133 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1134 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
1135 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1136 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1137 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
1138 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
1139 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
1140 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1141 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1142 color = get_surface_color(rt, 320, 240);
1143 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1145 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1146 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1147 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1148 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1149 IDirect3D3_Release(d3d);
1150 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1151 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1152 hr = IDirectDrawSurface4_IsLost(rt);
1153 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
1154 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
1155 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
1156 IDirectDraw4_Release(ddraw);
1158 hr = IDirect3DDevice3_GetRenderTarget(device, &surface);
1159 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1160 ok(surface == rt, "Got unexpected surface %p.\n", surface);
1161 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
1162 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1163 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
1164 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1165 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1166 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
1167 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
1168 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1169 color = get_surface_color(rt, 320, 240);
1170 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1172 destroy_viewport(device, viewport);
1173 IDirectDrawSurface4_Release(surface);
1174 IDirectDrawSurface4_Release(rt);
1175 IDirect3DDevice3_Release(device);
1176 DestroyWindow(window);
1179 static void test_surface_interface_mismatch(void)
1181 IDirectDraw4 *ddraw = NULL;
1182 IDirect3D3 *d3d = NULL;
1183 IDirectDrawSurface4 *surface = NULL, *ds;
1184 IDirectDrawSurface3 *surface3 = NULL;
1185 IDirect3DDevice3 *device = NULL;
1186 IDirect3DViewport3 *viewport = NULL;
1187 DDSURFACEDESC2 surface_desc;
1188 DDPIXELFORMAT z_fmt;
1189 ULONG refcount;
1190 HRESULT hr;
1191 D3DCOLOR color;
1192 HWND window;
1193 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1195 window = create_window();
1196 ddraw = create_ddraw();
1197 ok(!!ddraw, "Failed to create a ddraw object.\n");
1198 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1199 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1201 memset(&surface_desc, 0, sizeof(surface_desc));
1202 surface_desc.dwSize = sizeof(surface_desc);
1203 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1204 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1205 surface_desc.dwWidth = 640;
1206 surface_desc.dwHeight = 480;
1208 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1209 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1211 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
1212 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface3, hr %#x.\n", hr);
1214 if (FAILED(IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
1216 skip("D3D interface is not available, skipping test.\n");
1217 goto cleanup;
1220 memset(&z_fmt, 0, sizeof(z_fmt));
1221 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
1222 if (FAILED(hr) || !z_fmt.dwSize)
1224 skip("No depth buffer formats available, skipping test.\n");
1225 goto cleanup;
1228 memset(&surface_desc, 0, sizeof(surface_desc));
1229 surface_desc.dwSize = sizeof(surface_desc);
1230 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
1231 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1232 U4(surface_desc).ddpfPixelFormat = z_fmt;
1233 surface_desc.dwWidth = 640;
1234 surface_desc.dwHeight = 480;
1235 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &ds, NULL);
1236 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
1237 if (FAILED(hr))
1238 goto cleanup;
1240 /* Using a different surface interface version still works */
1241 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
1242 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
1243 refcount = IDirectDrawSurface4_Release(ds);
1244 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
1245 if (FAILED(hr))
1246 goto cleanup;
1248 /* Here too */
1249 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface4 *)surface3, &device, NULL);
1250 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
1251 if (FAILED(hr))
1252 goto cleanup;
1254 viewport = create_viewport(device, 0, 0, 640, 480);
1256 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1257 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1258 color = get_surface_color(surface, 320, 240);
1259 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1261 cleanup:
1262 if (viewport)
1263 destroy_viewport(device, viewport);
1264 if (surface3) IDirectDrawSurface3_Release(surface3);
1265 if (surface) IDirectDrawSurface4_Release(surface);
1266 if (device) IDirect3DDevice3_Release(device);
1267 if (d3d) IDirect3D3_Release(d3d);
1268 if (ddraw) IDirectDraw4_Release(ddraw);
1269 DestroyWindow(window);
1272 static void test_coop_level_threaded(void)
1274 struct create_window_thread_param p;
1275 IDirectDraw4 *ddraw;
1276 HRESULT hr;
1278 ddraw = create_ddraw();
1279 ok(!!ddraw, "Failed to create a ddraw object.\n");
1280 create_window_thread(&p);
1282 hr = IDirectDraw4_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1283 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1285 IDirectDraw4_Release(ddraw);
1286 destroy_window_thread(&p);
1289 static void test_depth_blit(void)
1291 static struct
1293 float x, y, z;
1294 DWORD color;
1296 quad1[] =
1298 { -1.0, 1.0, 0.50f, 0xff00ff00},
1299 { 1.0, 1.0, 0.50f, 0xff00ff00},
1300 { -1.0, -1.0, 0.50f, 0xff00ff00},
1301 { 1.0, -1.0, 0.50f, 0xff00ff00},
1303 static const D3DCOLOR expected_colors[4][4] =
1305 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1306 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1307 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1308 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1310 DDSURFACEDESC2 ddsd_new, ddsd_existing;
1312 IDirect3DDevice3 *device;
1313 IDirectDrawSurface4 *ds1, *ds2, *ds3, *rt;
1314 IDirect3DViewport3 *viewport;
1315 RECT src_rect, dst_rect;
1316 unsigned int i, j;
1317 D3DCOLOR color;
1318 HRESULT hr;
1319 IDirect3D3 *d3d;
1320 IDirectDraw4 *ddraw;
1321 DDBLTFX fx;
1322 HWND window;
1323 D3DRECT d3drect;
1325 window = create_window();
1326 if (!(device = create_device(window, DDSCL_NORMAL)))
1328 skip("Failed to create a 3D device, skipping test.\n");
1329 DestroyWindow(window);
1330 return;
1333 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1334 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
1335 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1336 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
1337 IDirect3D3_Release(d3d);
1339 ds1 = get_depth_stencil(device);
1341 memset(&ddsd_new, 0, sizeof(ddsd_new));
1342 ddsd_new.dwSize = sizeof(ddsd_new);
1343 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1344 ddsd_existing.dwSize = sizeof(ddsd_existing);
1345 hr = IDirectDrawSurface4_GetSurfaceDesc(ds1, &ddsd_existing);
1346 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
1347 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1348 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1349 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1350 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1351 U4(ddsd_new).ddpfPixelFormat = U4(ddsd_existing).ddpfPixelFormat;
1352 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1353 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1354 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1355 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1356 IDirectDraw4_Release(ddraw);
1358 viewport = create_viewport(device, 0, 0, ddsd_existing.dwWidth, ddsd_existing.dwHeight);
1359 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1360 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
1362 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1363 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
1364 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1365 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
1367 U1(d3drect).x1 = U2(d3drect).y1 = 0;
1368 U3(d3drect).x2 = ddsd_existing.dwWidth; U4(d3drect).y2 = ddsd_existing.dwHeight;
1369 hr = IDirect3DViewport3_Clear2(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
1370 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
1372 /* Partial blit. */
1373 SetRect(&src_rect, 0, 0, 320, 240);
1374 SetRect(&dst_rect, 0, 0, 320, 240);
1375 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1376 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1377 /* Different locations. */
1378 SetRect(&src_rect, 0, 0, 320, 240);
1379 SetRect(&dst_rect, 320, 240, 640, 480);
1380 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1381 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1382 /* Stretched. */
1383 SetRect(&src_rect, 0, 0, 320, 240);
1384 SetRect(&dst_rect, 0, 0, 640, 480);
1385 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1386 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1387 /* Flipped. */
1388 SetRect(&src_rect, 0, 480, 640, 0);
1389 SetRect(&dst_rect, 0, 0, 640, 480);
1390 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1391 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1392 SetRect(&src_rect, 0, 0, 640, 480);
1393 SetRect(&dst_rect, 0, 480, 640, 0);
1394 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1395 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1396 /* Full, explicit. */
1397 SetRect(&src_rect, 0, 0, 640, 480);
1398 SetRect(&dst_rect, 0, 0, 640, 480);
1399 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1400 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1401 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1403 /* Depth blit inside a BeginScene / EndScene pair */
1404 hr = IDirect3DDevice3_BeginScene(device);
1405 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1406 /* From the current depth stencil */
1407 hr = IDirectDrawSurface4_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1408 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1409 /* To the current depth stencil */
1410 hr = IDirectDrawSurface4_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1411 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1412 /* Between unbound surfaces */
1413 hr = IDirectDrawSurface4_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1414 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1415 hr = IDirect3DDevice3_EndScene(device);
1416 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1418 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1419 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1420 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1421 * a reliable result(z = 0.0) */
1422 memset(&fx, 0, sizeof(fx));
1423 fx.dwSize = sizeof(fx);
1424 hr = IDirectDrawSurface4_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1425 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1427 hr = IDirect3DViewport3_Clear2(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
1428 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1429 SetRect(&dst_rect, 0, 0, 320, 240);
1430 hr = IDirectDrawSurface4_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1431 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1432 IDirectDrawSurface4_Release(ds3);
1433 IDirectDrawSurface4_Release(ds2);
1434 IDirectDrawSurface4_Release(ds1);
1436 hr = IDirect3DDevice3_BeginScene(device);
1437 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1438 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1439 quad1, 4, 0);
1440 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1441 hr = IDirect3DDevice3_EndScene(device);
1442 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1444 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1445 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1446 for (i = 0; i < 4; ++i)
1448 for (j = 0; j < 4; ++j)
1450 unsigned int x = 80 * ((2 * j) + 1);
1451 unsigned int y = 60 * ((2 * i) + 1);
1452 color = get_surface_color(rt, x, y);
1453 ok(compare_color(color, expected_colors[i][j], 1),
1454 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1457 IDirectDrawSurface4_Release(rt);
1459 destroy_viewport(device, viewport);
1460 IDirect3DDevice3_Release(device);
1461 DestroyWindow(window);
1464 static void test_texture_load_ckey(void)
1466 IDirectDraw4 *ddraw;
1467 IDirectDrawSurface4 *src;
1468 IDirectDrawSurface4 *dst;
1469 IDirect3DTexture2 *src_tex;
1470 IDirect3DTexture2 *dst_tex;
1471 DDSURFACEDESC2 ddsd;
1472 HRESULT hr;
1473 DDCOLORKEY ckey;
1475 ddraw = create_ddraw();
1476 ok(!!ddraw, "Failed to create a ddraw object.\n");
1477 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
1478 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1480 memset(&ddsd, 0, sizeof(ddsd));
1481 ddsd.dwSize = sizeof(ddsd);
1482 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1483 ddsd.dwHeight = 128;
1484 ddsd.dwWidth = 128;
1485 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1486 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &src, NULL);
1487 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1488 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1489 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &dst, NULL);
1490 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1492 hr = IDirectDrawSurface4_QueryInterface(src, &IID_IDirect3DTexture2, (void **)&src_tex);
1493 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get Direct3DTexture2 interface, hr %#x.\n", hr);
1494 if (FAILED(hr))
1496 /* 64 bit ddraw does not support d3d */
1497 skip("Could not get Direct3DTexture2 interface, skipping texture::Load color keying tests.\n");
1498 IDirectDrawSurface4_Release(dst);
1499 IDirectDrawSurface4_Release(src);
1500 IDirectDraw4_Release(ddraw);
1501 return;
1503 hr = IDirectDrawSurface4_QueryInterface(dst, &IID_IDirect3DTexture2, (void **)&dst_tex);
1504 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture2 interface, hr %#x.\n", hr);
1506 /* No surface has a color key */
1507 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1508 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1509 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1510 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1511 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1512 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1513 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1515 /* Source surface has a color key */
1516 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1517 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1518 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1519 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1520 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1521 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1522 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1523 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1524 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1526 /* Both surfaces have a color key: Dest ckey is overwritten */
1527 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1528 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1529 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1530 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1531 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1532 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1533 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1534 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1535 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1537 /* Only the destination has a color key: It is not deleted */
1538 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1539 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1540 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1541 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1542 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1543 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1544 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1545 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1546 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1547 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1549 IDirect3DTexture2_Release(dst_tex);
1550 IDirect3DTexture2_Release(src_tex);
1551 IDirectDrawSurface4_Release(dst);
1552 IDirectDrawSurface4_Release(src);
1553 IDirectDraw4_Release(ddraw);
1556 static ULONG get_refcount(IUnknown *test_iface)
1558 IUnknown_AddRef(test_iface);
1559 return IUnknown_Release(test_iface);
1562 static void test_viewport_object(void)
1564 IDirectDraw4 *ddraw;
1565 IDirect3D3 *d3d;
1566 HRESULT hr, old_d3d_ref;
1567 ULONG ref;
1568 D3DVIEWPORT vp;
1569 D3DVIEWPORT2 vp2;
1570 IDirect3DViewport *viewport;
1571 IDirect3DViewport2 *viewport2;
1572 IDirect3DViewport3 *viewport3, *another_vp, *test_vp;
1573 IDirectDrawGammaControl *gamma;
1574 IUnknown *unknown;
1575 HWND window;
1576 IDirect3DDevice3 *device;
1577 union
1579 D3DVIEWPORT2 vp2;
1580 D3DVIEWPORT vp1;
1581 BYTE blob[1024];
1582 } desc;
1584 window = create_window();
1585 if (!(device = create_device(window, DDSCL_NORMAL)))
1587 skip("Failed to create a 3D device, skipping test.\n");
1588 DestroyWindow(window);
1589 return;
1591 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1592 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
1593 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1594 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
1595 old_d3d_ref = get_refcount((IUnknown *) d3d);
1597 hr = IDirect3D3_CreateViewport(d3d, &viewport3, NULL);
1598 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1599 ref = get_refcount((IUnknown *)viewport3);
1600 ok(ref == 1, "Got unexpected refcount %u.\n", ref);
1601 ref = get_refcount((IUnknown *)d3d);
1602 ok(ref == old_d3d_ref, "Got unexpected refcount %u.\n", ref);
1604 memset(&desc, 0, sizeof(desc));
1605 hr = IDirect3DViewport3_GetViewport(viewport3, &desc.vp1);
1606 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1607 desc.vp1.dwSize = sizeof(desc.vp1) + 1;
1608 hr = IDirect3DViewport3_GetViewport(viewport3, &desc.vp1);
1609 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1610 desc.vp1.dwSize = sizeof(desc.vp1) - 1;
1611 hr = IDirect3DViewport3_GetViewport(viewport3, &desc.vp1);
1612 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1613 desc.vp1.dwSize = sizeof(desc.vp1);
1614 hr = IDirect3DViewport3_GetViewport(viewport3, &desc.vp1);
1615 ok(hr == D3DERR_VIEWPORTDATANOTSET, "Got unexpected hr %#x.\n", hr);
1616 ok(desc.vp1.dwSize == sizeof(desc.vp1), "Got unexpected dwSize %u.\n", desc.vp1.dwSize);
1617 hr = IDirect3DViewport3_GetViewport2(viewport3, &desc.vp2);
1618 ok(hr == D3DERR_VIEWPORTDATANOTSET, "Got unexpected hr %#x.\n", hr);
1619 ok(desc.vp2.dwSize == sizeof(desc.vp2), "Got unexpected dwSize %u.\n", desc.vp2.dwSize);
1620 desc.vp2.dwSize = sizeof(desc.vp2) + 1;
1621 hr = IDirect3DViewport3_GetViewport2(viewport3, &desc.vp2);
1622 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1624 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1625 hr = IDirect3DViewport2_QueryInterface(viewport3, &IID_IDirectDrawGammaControl, (void **)&gamma);
1626 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
1627 ok(!gamma, "Interface not set to NULL by failed QI call: %p\n", gamma);
1628 /* NULL iid: Segfaults */
1630 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IDirect3DViewport, (void **)&viewport);
1631 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport, hr %#x.\n", hr);
1632 ref = get_refcount((IUnknown *)viewport);
1633 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1634 ref = get_refcount((IUnknown *)viewport3);
1635 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1636 IDirect3DViewport_Release(viewport);
1637 viewport = NULL;
1639 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IDirect3DViewport3, (void **)&viewport2);
1640 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1641 ref = get_refcount((IUnknown *)viewport2);
1642 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1643 ref = get_refcount((IUnknown *)viewport3);
1644 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1645 IDirect3DViewport3_Release(viewport2);
1647 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IUnknown, (void **)&unknown);
1648 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1649 ref = get_refcount((IUnknown *)viewport3);
1650 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1651 ref = get_refcount(unknown);
1652 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1653 IUnknown_Release(unknown);
1655 hr = IDirect3DDevice3_DeleteViewport(device, NULL);
1656 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1657 hr = IDirect3DDevice3_GetCurrentViewport(device, NULL);
1658 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1660 hr = IDirect3D3_CreateViewport(d3d, &another_vp, NULL);
1661 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1663 /* Setting a viewport not in the viewport list fails */
1664 hr = IDirect3DDevice3_SetCurrentViewport(device, another_vp);
1665 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1667 /* AddViewport(NULL): Segfault */
1668 hr = IDirect3DDevice3_AddViewport(device, viewport3);
1669 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1670 ref = get_refcount((IUnknown *) viewport3);
1671 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1672 hr = IDirect3DDevice3_AddViewport(device, another_vp);
1673 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1674 ref = get_refcount((IUnknown *) another_vp);
1675 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1677 test_vp = (IDirect3DViewport3 *) 0xbaadc0de;
1678 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1679 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1680 ok(test_vp == (IDirect3DViewport3 *) 0xbaadc0de, "Got unexpected pointer %p\n", test_vp);
1682 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport3);
1683 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1684 ref = get_refcount((IUnknown *) viewport3);
1685 ok(ref == 3, "Got unexpected refcount %u.\n", ref);
1686 ref = get_refcount((IUnknown *) device);
1687 ok(ref == 1, "Got unexpected refcount %u.\n", ref);
1689 test_vp = NULL;
1690 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1691 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1692 ok(test_vp == viewport3, "Got unexpected viewport %p\n", test_vp);
1693 ref = get_refcount((IUnknown *) viewport3);
1694 ok(ref == 4, "Got unexpected refcount %u.\n", ref);
1695 if (test_vp)
1696 IDirect3DViewport3_Release(test_vp);
1698 /* GetCurrentViewport with a viewport set and NULL input param: Segfault */
1700 /* Cannot set the viewport to NULL */
1701 hr = IDirect3DDevice3_SetCurrentViewport(device, NULL);
1702 ok(hr == DDERR_INVALIDPARAMS, "Failed to set viewport to NULL, hr %#x.\n", hr);
1703 test_vp = NULL;
1704 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1705 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1706 ok(test_vp == viewport3, "Got unexpected viewport %p\n", test_vp);
1707 if (test_vp)
1708 IDirect3DViewport3_Release(test_vp);
1710 /* SetCurrentViewport properly releases the old viewport's reference */
1711 hr = IDirect3DDevice3_SetCurrentViewport(device, another_vp);
1712 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1713 ref = get_refcount((IUnknown *) viewport3);
1714 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1715 ref = get_refcount((IUnknown *) another_vp);
1716 ok(ref == 3, "Got unexpected refcount %u.\n", ref);
1718 /* Unlike device2::DeleteViewport, device3::DeleteViewport releases the
1719 * reference held by SetCurrentViewport */
1720 hr = IDirect3DDevice3_DeleteViewport(device, another_vp);
1721 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1722 ref = get_refcount((IUnknown *) another_vp);
1723 ok(ref == 1, "Got unexpected refcount %u.\n", ref);
1725 /* GetCurrentViewport still fails */
1726 test_vp = NULL;
1727 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1728 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1729 ok(!test_vp, "Got unexpected viewport %p\n", test_vp);
1731 /* Setting a different viewport doesn't have any surprises now */
1732 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport3);
1733 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1734 ref = get_refcount((IUnknown *) viewport3);
1735 ok(ref == 3, "Got unexpected refcount %u.\n", ref);
1736 ref = get_refcount((IUnknown *) another_vp);
1737 ok(ref == 1, "Got unexpected refcount %u.\n", ref);
1739 memset(&vp, 0, sizeof(vp));
1740 memset(&vp, 0, sizeof(vp2));
1741 vp.dwSize = vp2.dwSize = 0;
1742 vp.dwX = vp2.dwX = 0;
1743 vp.dwY = vp2.dwY = 0;
1744 vp.dwWidth = vp2.dwWidth = 640;
1745 vp.dwHeight = vp2.dwHeight = 480;
1746 vp.dvMinZ = vp2.dvMinZ = 0.0f;
1747 vp.dvMaxZ = vp2.dvMaxZ = 1.0f;
1748 vp.dvScaleX = vp.dwWidth / 2.0f;
1749 vp.dvScaleY = vp.dwHeight / 2.0f;
1750 vp.dvMaxX = 1.0f;
1751 vp.dvMaxY = 1.0f;
1752 vp2.dvClipX = -1.0f;
1753 vp2.dvClipY = 1.0f;
1754 vp2.dvClipWidth = 2.0f;
1755 vp2.dvClipHeight = 2.0f;
1756 hr = IDirect3DViewport3_SetViewport(viewport3, &vp);
1757 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1758 hr = IDirect3DViewport3_SetViewport2(viewport3, &vp2);
1759 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1761 vp.dwSize = sizeof(vp);
1762 hr = IDirect3DViewport3_SetViewport(viewport3, &vp);
1763 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
1764 vp2.dwSize = sizeof(vp2);
1765 hr = IDirect3DViewport3_SetViewport2(viewport3, &vp2);
1766 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
1768 /* Destroying the device removes the viewport and releases the reference */
1769 IDirect3DDevice3_Release(device);
1770 ref = get_refcount((IUnknown *) viewport3);
1771 ok(ref == 1, "Got unexpected refcount %u.\n", ref);
1773 vp.dwSize = sizeof(vp);
1774 hr = IDirect3DViewport3_SetViewport(viewport3, &vp);
1775 ok(hr == D3DERR_VIEWPORTHASNODEVICE, "Got unexpected hr %#x.\n", hr);
1776 vp2.dwSize = sizeof(vp2);
1777 hr = IDirect3DViewport3_SetViewport2(viewport3, &vp2);
1778 ok(hr == D3DERR_VIEWPORTHASNODEVICE, "Got unexpected hr %#x.\n", hr);
1780 ref = IDirect3DViewport3_Release(another_vp);
1781 ok(!ref, "Got unexpected refcount %u.\n", ref);
1782 ref = IDirect3DViewport3_Release(viewport3);
1783 ok(!ref, "Got unexpected refcount %u.\n", ref);
1784 IDirect3D3_Release(d3d);
1785 DestroyWindow(window);
1786 IDirectDraw4_Release(ddraw);
1789 static void test_zenable(void)
1791 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1792 static struct
1794 struct vec4 position;
1795 D3DCOLOR diffuse;
1797 tquad[] =
1799 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xff00ff00},
1800 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xff00ff00},
1801 {{640.0f, 480.0f, 1.5f, 1.0f}, 0xff00ff00},
1802 {{640.0f, 0.0f, 1.5f, 1.0f}, 0xff00ff00},
1804 IDirect3DViewport3 *viewport;
1805 IDirect3DDevice3 *device;
1806 IDirectDrawSurface4 *rt;
1807 D3DCOLOR color;
1808 HWND window;
1809 HRESULT hr;
1810 UINT x, y;
1811 UINT i, j;
1813 window = create_window();
1814 if (!(device = create_device(window, DDSCL_NORMAL)))
1816 skip("Failed to create a 3D device, skipping test.\n");
1817 DestroyWindow(window);
1818 return;
1821 viewport = create_viewport(device, 0, 0, 640, 480);
1822 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1823 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1825 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1826 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1828 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0f, 0);
1829 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1830 hr = IDirect3DDevice3_BeginScene(device);
1831 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1832 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, tquad, 4, 0);
1833 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1834 hr = IDirect3DDevice3_EndScene(device);
1835 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1837 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1838 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1839 for (i = 0; i < 4; ++i)
1841 for (j = 0; j < 4; ++j)
1843 x = 80 * ((2 * j) + 1);
1844 y = 60 * ((2 * i) + 1);
1845 color = get_surface_color(rt, x, y);
1846 ok(compare_color(color, 0x0000ff00, 1),
1847 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1850 IDirectDrawSurface4_Release(rt);
1852 destroy_viewport(device, viewport);
1853 IDirect3DDevice3_Release(device);
1854 DestroyWindow(window);
1857 static void test_ck_rgba(void)
1859 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1860 static struct
1862 struct vec4 position;
1863 struct vec2 texcoord;
1865 tquad[] =
1867 {{ 0.0f, 480.0f, 0.25f, 1.0f}, {0.0f, 0.0f}},
1868 {{ 0.0f, 0.0f, 0.25f, 1.0f}, {0.0f, 1.0f}},
1869 {{640.0f, 480.0f, 0.25f, 1.0f}, {1.0f, 0.0f}},
1870 {{640.0f, 0.0f, 0.25f, 1.0f}, {1.0f, 1.0f}},
1871 {{ 0.0f, 480.0f, 0.75f, 1.0f}, {0.0f, 0.0f}},
1872 {{ 0.0f, 0.0f, 0.75f, 1.0f}, {0.0f, 1.0f}},
1873 {{640.0f, 480.0f, 0.75f, 1.0f}, {1.0f, 0.0f}},
1874 {{640.0f, 0.0f, 0.75f, 1.0f}, {1.0f, 1.0f}},
1876 static const struct
1878 D3DCOLOR fill_color;
1879 BOOL color_key;
1880 BOOL blend;
1881 D3DCOLOR result1, result1_broken;
1882 D3DCOLOR result2, result2_broken;
1884 tests[] =
1886 /* r200 on Windows doesn't check the alpha component when applying the color
1887 * key, so the key matches on every texel. */
1888 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1889 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1890 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1891 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1892 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00ff0000, 0x00807f00, 0x000000ff},
1893 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x00ff0000, 0x0000ff00, 0x000000ff},
1894 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00, 0x00807f00, 0x00807f00},
1895 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1898 IDirectDrawSurface4 *surface;
1899 IDirect3DViewport3 *viewport;
1900 DDSURFACEDESC2 surface_desc;
1901 IDirect3DTexture2 *texture;
1902 IDirect3DDevice3 *device;
1903 IDirectDrawSurface4 *rt;
1904 IDirectDraw4 *ddraw;
1905 IDirect3D3 *d3d;
1906 D3DCOLOR color;
1907 HWND window;
1908 DDBLTFX fx;
1909 HRESULT hr;
1910 UINT i;
1912 window = create_window();
1913 if (!(device = create_device(window, DDSCL_NORMAL)))
1915 skip("Failed to create a 3D device, skipping test.\n");
1916 DestroyWindow(window);
1917 return;
1920 viewport = create_viewport(device, 0, 0, 640, 480);
1921 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1922 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1924 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1925 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1926 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1927 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1928 IDirect3D3_Release(d3d);
1930 memset(&surface_desc, 0, sizeof(surface_desc));
1931 surface_desc.dwSize = sizeof(surface_desc);
1932 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1933 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1934 surface_desc.dwWidth = 256;
1935 surface_desc.dwHeight = 256;
1936 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1937 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1938 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1939 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1940 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1941 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1942 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1943 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1944 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1945 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1946 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1947 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1948 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1950 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
1951 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1952 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1953 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1954 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1955 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1957 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1958 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1960 for (i = 0; i < ARRAY_SIZE(tests); ++i)
1962 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1963 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1964 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1965 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1967 memset(&fx, 0, sizeof(fx));
1968 fx.dwSize = sizeof(fx);
1969 U5(fx).dwFillColor = tests[i].fill_color;
1970 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1971 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1973 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect,
1974 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
1975 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1976 hr = IDirect3DDevice3_BeginScene(device);
1977 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1978 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1979 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1980 hr = IDirect3DDevice3_EndScene(device);
1981 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1983 color = get_surface_color(rt, 320, 240);
1984 ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
1985 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1986 tests[i].result1, i, color);
1988 U5(fx).dwFillColor = 0xff0000ff;
1989 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1990 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1992 hr = IDirect3DDevice3_BeginScene(device);
1993 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1994 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[4], 4, 0);
1995 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1996 hr = IDirect3DDevice3_EndScene(device);
1997 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1999 /* This tests that fragments that are masked out by the color key are
2000 * discarded, instead of just fully transparent. */
2001 color = get_surface_color(rt, 320, 240);
2002 ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
2003 "Expected color 0x%08x for test %u, got 0x%08x.\n",
2004 tests[i].result2, i, color);
2007 IDirectDrawSurface4_Release(rt);
2008 IDirect3DTexture2_Release(texture);
2009 IDirectDrawSurface4_Release(surface);
2010 destroy_viewport(device, viewport);
2011 IDirectDraw4_Release(ddraw);
2012 IDirect3DDevice3_Release(device);
2013 DestroyWindow(window);
2016 static void test_ck_default(void)
2018 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
2019 static struct
2021 struct vec4 position;
2022 struct vec2 texcoord;
2024 tquad[] =
2026 {{ 0.0f, 480.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
2027 {{ 0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
2028 {{640.0f, 480.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
2029 {{640.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
2031 IDirectDrawSurface4 *surface, *rt;
2032 IDirect3DViewport3 *viewport;
2033 DDSURFACEDESC2 surface_desc;
2034 IDirect3DTexture2 *texture;
2035 IDirect3DDevice3 *device;
2036 IDirectDraw4 *ddraw;
2037 IDirect3D3 *d3d;
2038 D3DCOLOR color;
2039 DWORD value;
2040 HWND window;
2041 DDBLTFX fx;
2042 HRESULT hr;
2044 window = create_window();
2045 if (!(device = create_device(window, DDSCL_NORMAL)))
2047 skip("Failed to create a 3D device, skipping test.\n");
2048 DestroyWindow(window);
2049 return;
2052 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
2053 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
2054 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
2055 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
2056 IDirect3D3_Release(d3d);
2058 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
2059 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
2061 viewport = create_viewport(device, 0, 0, 640, 480);
2062 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
2063 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
2065 memset(&surface_desc, 0, sizeof(surface_desc));
2066 surface_desc.dwSize = sizeof(surface_desc);
2067 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
2068 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2069 surface_desc.dwWidth = 256;
2070 surface_desc.dwHeight = 256;
2071 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
2072 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
2073 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
2074 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
2075 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
2076 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
2077 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
2078 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
2079 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2080 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2081 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
2082 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
2083 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
2084 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
2086 memset(&fx, 0, sizeof(fx));
2087 fx.dwSize = sizeof(fx);
2088 U5(fx).dwFillColor = 0x000000ff;
2089 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
2090 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
2092 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
2093 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2094 hr = IDirect3DDevice3_BeginScene(device);
2095 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
2096 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
2097 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
2098 ok(!value, "Got unexpected color keying state %#x.\n", value);
2099 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
2100 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
2101 hr = IDirect3DDevice3_EndScene(device);
2102 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
2103 color = get_surface_color(rt, 320, 240);
2104 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
2106 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
2107 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2108 hr = IDirect3DDevice3_BeginScene(device);
2109 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
2110 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
2111 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
2112 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
2113 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
2114 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
2115 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
2116 ok(!!value, "Got unexpected color keying state %#x.\n", value);
2117 hr = IDirect3DDevice3_EndScene(device);
2118 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
2119 color = get_surface_color(rt, 320, 240);
2120 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
2122 IDirect3DTexture_Release(texture);
2123 IDirectDrawSurface4_Release(surface);
2124 destroy_viewport(device, viewport);
2125 IDirectDrawSurface4_Release(rt);
2126 IDirect3DDevice3_Release(device);
2127 IDirectDraw4_Release(ddraw);
2128 DestroyWindow(window);
2131 static void test_ck_complex(void)
2133 IDirectDrawSurface4 *surface, *mipmap, *tmp;
2134 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
2135 DDSURFACEDESC2 surface_desc;
2136 IDirect3DDevice3 *device;
2137 DDCOLORKEY color_key;
2138 IDirectDraw4 *ddraw;
2139 IDirect3D3 *d3d;
2140 unsigned int i;
2141 ULONG refcount;
2142 HWND window;
2143 HRESULT hr;
2145 window = create_window();
2146 if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
2148 skip("Failed to create a 3D device, skipping test.\n");
2149 DestroyWindow(window);
2150 return;
2152 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
2153 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
2154 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
2155 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
2156 IDirect3D3_Release(d3d);
2158 memset(&surface_desc, 0, sizeof(surface_desc));
2159 surface_desc.dwSize = sizeof(surface_desc);
2160 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2161 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2162 surface_desc.dwWidth = 128;
2163 surface_desc.dwHeight = 128;
2164 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2165 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2167 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2168 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
2169 color_key.dwColorSpaceLowValue = 0x0000ff00;
2170 color_key.dwColorSpaceHighValue = 0x0000ff00;
2171 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2172 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2173 memset(&color_key, 0, sizeof(color_key));
2174 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2175 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2176 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2177 color_key.dwColorSpaceLowValue);
2178 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2179 color_key.dwColorSpaceHighValue);
2181 mipmap = surface;
2182 IDirectDrawSurface_AddRef(mipmap);
2183 for (i = 0; i < 7; ++i)
2185 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
2186 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
2188 hr = IDirectDrawSurface4_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2189 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
2190 color_key.dwColorSpaceLowValue = 0x000000ff;
2191 color_key.dwColorSpaceHighValue = 0x000000ff;
2192 hr = IDirectDrawSurface4_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2193 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x, i %u.\n", hr, i);
2194 memset(&color_key, 0, sizeof(color_key));
2195 hr = IDirectDrawSurface4_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2196 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x, i %u.\n", hr, i);
2197 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
2198 color_key.dwColorSpaceLowValue, i);
2199 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
2200 color_key.dwColorSpaceHighValue, i);
2202 IDirectDrawSurface_Release(mipmap);
2203 mipmap = tmp;
2206 memset(&color_key, 0, sizeof(color_key));
2207 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2208 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2209 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2210 color_key.dwColorSpaceLowValue);
2211 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2212 color_key.dwColorSpaceHighValue);
2214 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
2215 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
2216 IDirectDrawSurface_Release(mipmap);
2217 refcount = IDirectDrawSurface4_Release(surface);
2218 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2220 memset(&surface_desc, 0, sizeof(surface_desc));
2221 surface_desc.dwSize = sizeof(surface_desc);
2222 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
2223 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
2224 U5(surface_desc).dwBackBufferCount = 1;
2225 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2226 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2228 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2229 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
2230 color_key.dwColorSpaceLowValue = 0x0000ff00;
2231 color_key.dwColorSpaceHighValue = 0x0000ff00;
2232 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2233 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2234 memset(&color_key, 0, sizeof(color_key));
2235 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2236 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2237 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2238 color_key.dwColorSpaceLowValue);
2239 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2240 color_key.dwColorSpaceHighValue);
2242 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &tmp);
2243 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
2245 hr = IDirectDrawSurface4_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2246 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
2247 color_key.dwColorSpaceLowValue = 0x0000ff00;
2248 color_key.dwColorSpaceHighValue = 0x0000ff00;
2249 hr = IDirectDrawSurface4_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2250 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2251 memset(&color_key, 0, sizeof(color_key));
2252 hr = IDirectDrawSurface4_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2253 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2254 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2255 color_key.dwColorSpaceLowValue);
2256 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2257 color_key.dwColorSpaceHighValue);
2259 IDirectDrawSurface_Release(tmp);
2261 refcount = IDirectDrawSurface4_Release(surface);
2262 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2263 IDirectDraw4_Release(ddraw);
2264 refcount = IDirect3DDevice3_Release(device);
2265 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2266 DestroyWindow(window);
2269 struct qi_test
2271 REFIID iid;
2272 REFIID refcount_iid;
2273 HRESULT hr;
2276 static void test_qi(const char *test_name, IUnknown *base_iface,
2277 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
2279 ULONG refcount, expected_refcount;
2280 IUnknown *iface1, *iface2;
2281 HRESULT hr;
2282 UINT i, j;
2284 for (i = 0; i < entry_count; ++i)
2286 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
2287 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
2288 if (SUCCEEDED(hr))
2290 for (j = 0; j < entry_count; ++j)
2292 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
2293 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
2294 if (SUCCEEDED(hr))
2296 expected_refcount = 0;
2297 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
2298 ++expected_refcount;
2299 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
2300 ++expected_refcount;
2301 refcount = IUnknown_Release(iface2);
2302 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
2303 refcount, test_name, i, j, expected_refcount);
2307 expected_refcount = 0;
2308 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
2309 ++expected_refcount;
2310 refcount = IUnknown_Release(iface1);
2311 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
2312 refcount, test_name, i, expected_refcount);
2317 static void test_surface_qi(void)
2319 static const struct qi_test tests[] =
2321 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface4, S_OK },
2322 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface4, S_OK },
2323 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
2324 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2325 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
2326 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
2327 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
2328 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
2329 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
2330 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
2331 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
2332 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
2333 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
2334 {&IID_IDirect3D7, NULL, E_INVALIDARG },
2335 {&IID_IDirect3D3, NULL, E_INVALIDARG },
2336 {&IID_IDirect3D2, NULL, E_INVALIDARG },
2337 {&IID_IDirect3D, NULL, E_INVALIDARG },
2338 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
2339 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
2340 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
2341 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
2342 {&IID_IDirectDraw, NULL, E_INVALIDARG },
2343 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
2344 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
2345 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
2346 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
2347 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
2348 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
2349 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
2350 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
2351 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
2352 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
2353 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
2354 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
2355 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
2356 {NULL, NULL, E_INVALIDARG },
2359 IDirectDrawSurface4 *surface;
2360 DDSURFACEDESC2 surface_desc;
2361 IDirect3DDevice3 *device;
2362 IDirectDraw4 *ddraw;
2363 HWND window;
2364 HRESULT hr;
2366 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
2368 win_skip("DirectDrawCreateEx not available, skipping test.\n");
2369 return;
2372 window = create_window();
2373 /* Try to create a D3D device to see if the ddraw implementation supports
2374 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
2375 * doesn't support e.g. the IDirect3DTexture interfaces. */
2376 if (!(device = create_device(window, DDSCL_NORMAL)))
2378 skip("Failed to create a 3D device, skipping test.\n");
2379 DestroyWindow(window);
2380 return;
2382 IDirect3DDevice_Release(device);
2383 ddraw = create_ddraw();
2384 ok(!!ddraw, "Failed to create a ddraw object.\n");
2385 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2386 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2388 memset(&surface_desc, 0, sizeof(surface_desc));
2389 surface_desc.dwSize = sizeof(surface_desc);
2390 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2391 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2392 surface_desc.dwWidth = 512;
2393 surface_desc.dwHeight = 512;
2394 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, (IDirectDrawSurface4 **)0xdeadbeef, NULL);
2395 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
2396 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2397 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2399 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface4, tests, ARRAY_SIZE(tests));
2401 IDirectDrawSurface4_Release(surface);
2402 IDirectDraw4_Release(ddraw);
2403 DestroyWindow(window);
2406 static void test_device_qi(void)
2408 static const struct qi_test tests[] =
2410 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
2411 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
2412 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
2413 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2414 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
2415 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
2416 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
2417 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
2418 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
2419 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
2420 {&IID_IDirect3DDevice3, &IID_IDirect3DDevice3, S_OK },
2421 {&IID_IDirect3DDevice2, &IID_IDirect3DDevice3, S_OK },
2422 {&IID_IDirect3DDevice, &IID_IDirect3DDevice3, S_OK },
2423 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2424 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2425 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2426 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2427 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2428 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2429 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2430 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2431 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2432 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2433 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2434 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2435 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2436 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2437 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2438 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2439 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2440 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2441 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2442 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2443 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2444 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2445 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2446 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2447 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2448 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2449 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2450 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2451 {&IID_IUnknown, &IID_IDirect3DDevice3, S_OK },
2454 IDirect3DDevice3 *device;
2455 HWND window;
2457 window = create_window();
2458 if (!(device = create_device(window, DDSCL_NORMAL)))
2460 skip("Failed to create a 3D device, skipping test.\n");
2461 DestroyWindow(window);
2462 return;
2465 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice3, tests, ARRAY_SIZE(tests));
2467 IDirect3DDevice3_Release(device);
2468 DestroyWindow(window);
2471 static void test_wndproc(void)
2473 LONG_PTR proc, ddraw_proc;
2474 IDirectDraw4 *ddraw;
2475 WNDCLASSA wc = {0};
2476 HWND window;
2477 HRESULT hr;
2478 ULONG ref;
2480 static struct message messages[] =
2482 {WM_WINDOWPOSCHANGING, FALSE, 0},
2483 {WM_MOVE, FALSE, 0},
2484 {WM_SIZE, FALSE, 0},
2485 {WM_WINDOWPOSCHANGING, FALSE, 0},
2486 {WM_ACTIVATE, FALSE, 0},
2487 {WM_SETFOCUS, FALSE, 0},
2488 {0, FALSE, 0},
2491 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2492 ddraw = create_ddraw();
2493 ok(!!ddraw, "Failed to create a ddraw object.\n");
2495 wc.lpfnWndProc = test_proc;
2496 wc.lpszClassName = "ddraw_test_wndproc_wc";
2497 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2499 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2500 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2502 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2503 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2504 (LONG_PTR)test_proc, proc);
2505 expect_messages = messages;
2506 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2507 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2508 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2509 expect_messages = NULL;
2510 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2511 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2512 (LONG_PTR)test_proc, proc);
2513 ref = IDirectDraw4_Release(ddraw);
2514 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2515 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2516 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2517 (LONG_PTR)test_proc, proc);
2519 /* DDSCL_NORMAL doesn't. */
2520 ddraw = create_ddraw();
2521 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2522 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2523 (LONG_PTR)test_proc, proc);
2524 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2525 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2526 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2527 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2528 (LONG_PTR)test_proc, proc);
2529 ref = IDirectDraw4_Release(ddraw);
2530 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2531 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2532 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2533 (LONG_PTR)test_proc, proc);
2535 /* The original window proc is only restored by ddraw if the current
2536 * window proc matches the one ddraw set. This also affects switching
2537 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2538 ddraw = create_ddraw();
2539 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2540 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2541 (LONG_PTR)test_proc, proc);
2542 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2543 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2544 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2545 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2546 (LONG_PTR)test_proc, proc);
2547 ddraw_proc = proc;
2548 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2549 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2550 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2551 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2552 (LONG_PTR)test_proc, proc);
2553 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2554 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2555 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2556 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2557 (LONG_PTR)test_proc, proc);
2558 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2559 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2560 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2561 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2562 (LONG_PTR)DefWindowProcA, proc);
2563 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2564 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2565 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, ddraw_proc);
2566 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2567 (LONG_PTR)DefWindowProcA, proc);
2568 ref = IDirectDraw4_Release(ddraw);
2569 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2570 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2571 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2572 (LONG_PTR)test_proc, proc);
2574 ddraw = create_ddraw();
2575 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2576 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2577 (LONG_PTR)test_proc, proc);
2578 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2579 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2580 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2581 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2582 (LONG_PTR)test_proc, proc);
2583 ref = IDirectDraw4_Release(ddraw);
2584 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2585 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2586 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2587 (LONG_PTR)DefWindowProcA, proc);
2589 fix_wndproc(window, (LONG_PTR)test_proc);
2590 expect_messages = NULL;
2591 DestroyWindow(window);
2592 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2595 static void test_window_style(void)
2597 LONG style, exstyle, tmp, expected_style;
2598 RECT fullscreen_rect, r;
2599 IDirectDraw4 *ddraw;
2600 HWND window;
2601 HRESULT hr;
2602 ULONG ref;
2603 BOOL ret;
2605 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2606 0, 0, 100, 100, 0, 0, 0, 0);
2607 ddraw = create_ddraw();
2608 ok(!!ddraw, "Failed to create a ddraw object.\n");
2610 style = GetWindowLongA(window, GWL_STYLE);
2611 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2612 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2614 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2615 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2617 tmp = GetWindowLongA(window, GWL_STYLE);
2618 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2619 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2620 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2622 GetWindowRect(window, &r);
2623 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2624 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2625 GetClientRect(window, &r);
2626 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2628 ret = SetForegroundWindow(GetDesktopWindow());
2629 ok(ret, "Failed to set foreground window.\n");
2631 tmp = GetWindowLongA(window, GWL_STYLE);
2632 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2633 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2634 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2636 ret = SetForegroundWindow(window);
2637 ok(ret, "Failed to set foreground window.\n");
2638 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2639 * the next tests expect this. */
2640 ShowWindow(window, SW_HIDE);
2642 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2643 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2645 tmp = GetWindowLongA(window, GWL_STYLE);
2646 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2647 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2648 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2650 ShowWindow(window, SW_SHOW);
2651 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2652 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2654 tmp = GetWindowLongA(window, GWL_STYLE);
2655 expected_style = style | WS_VISIBLE;
2656 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2657 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2658 expected_style = exstyle | WS_EX_TOPMOST;
2659 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2661 ret = SetForegroundWindow(GetDesktopWindow());
2662 ok(ret, "Failed to set foreground window.\n");
2663 tmp = GetWindowLongA(window, GWL_STYLE);
2664 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
2665 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2666 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2667 expected_style = exstyle | WS_EX_TOPMOST;
2668 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2670 ref = IDirectDraw4_Release(ddraw);
2671 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2673 DestroyWindow(window);
2676 static void test_redundant_mode_set(void)
2678 DDSURFACEDESC2 surface_desc = {0};
2679 IDirectDraw4 *ddraw;
2680 RECT q, r, s;
2681 HWND window;
2682 HRESULT hr;
2683 ULONG ref;
2685 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2686 0, 0, 100, 100, 0, 0, 0, 0);
2687 ddraw = create_ddraw();
2688 ok(!!ddraw, "Failed to create a ddraw object.\n");
2690 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2691 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2693 surface_desc.dwSize = sizeof(surface_desc);
2694 hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc);
2695 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
2697 hr = IDirectDraw4_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2698 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2699 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2701 GetWindowRect(window, &q);
2702 r = q;
2703 r.right /= 2;
2704 r.bottom /= 2;
2705 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2706 GetWindowRect(window, &s);
2707 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2709 hr = IDirectDraw4_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2710 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2711 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2713 GetWindowRect(window, &s);
2714 ok(EqualRect(&r, &s) || broken(EqualRect(&q, &s) /* Windows 10 */),
2715 "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2717 ref = IDirectDraw4_Release(ddraw);
2718 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2720 DestroyWindow(window);
2723 static SIZE screen_size, screen_size2;
2725 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2727 if (message == WM_SIZE)
2729 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2730 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2733 return test_proc(hwnd, message, wparam, lparam);
2736 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2738 if (message == WM_SIZE)
2740 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
2741 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
2744 return test_proc(hwnd, message, wparam, lparam);
2747 struct test_coop_level_mode_set_enum_param
2749 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
2752 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC2 *surface_desc, void *context)
2754 struct test_coop_level_mode_set_enum_param *param = context;
2756 if (U1(U4(*surface_desc).ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
2757 return DDENUMRET_OK;
2758 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
2759 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
2760 return DDENUMRET_OK;
2762 if (!param->ddraw_width)
2764 param->ddraw_width = surface_desc->dwWidth;
2765 param->ddraw_height = surface_desc->dwHeight;
2766 return DDENUMRET_OK;
2768 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
2769 return DDENUMRET_OK;
2771 param->user32_width = surface_desc->dwWidth;
2772 param->user32_height = surface_desc->dwHeight;
2773 return DDENUMRET_CANCEL;
2776 static void test_coop_level_mode_set(void)
2778 IDirectDrawSurface4 *primary;
2779 RECT registry_rect, ddraw_rect, user32_rect, r;
2780 IDirectDraw4 *ddraw;
2781 DDSURFACEDESC2 ddsd;
2782 WNDCLASSA wc = {0};
2783 HWND window, window2;
2784 HRESULT hr;
2785 ULONG ref;
2786 MSG msg;
2787 struct test_coop_level_mode_set_enum_param param;
2788 DEVMODEW devmode;
2789 BOOL ret;
2790 LONG change_ret;
2792 static const struct message exclusive_messages[] =
2794 {WM_WINDOWPOSCHANGING, FALSE, 0},
2795 {WM_WINDOWPOSCHANGED, FALSE, 0},
2796 {WM_SIZE, FALSE, 0},
2797 {WM_DISPLAYCHANGE, FALSE, 0},
2798 {0, FALSE, 0},
2800 static const struct message exclusive_focus_loss_messages[] =
2802 {WM_ACTIVATE, TRUE, WA_INACTIVE, DD_OK},
2803 {WM_WINDOWPOSCHANGING, FALSE, 0, DD_OK}, /* Window resize due to mode change. */
2804 {WM_WINDOWPOSCHANGED, FALSE, 0, DD_OK},
2805 {WM_SIZE, TRUE, SIZE_RESTORED, DD_OK}, /* Generated by DefWindowProc. */
2806 {WM_DISPLAYCHANGE, FALSE, 0, DD_OK},
2807 {WM_KILLFOCUS, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
2808 {WM_WINDOWPOSCHANGING, FALSE, 0, DDERR_NOEXCLUSIVEMODE}, /* Window minimized. */
2809 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
2810 * SW_MINIMIZED, causing a recursive window activation that does not
2811 * produce the same result in Wine yet. Ignore the difference for now.
2812 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
2813 {WM_WINDOWPOSCHANGED, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
2814 {WM_MOVE, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
2815 {WM_SIZE, TRUE, SIZE_MINIMIZED, DDERR_NOEXCLUSIVEMODE},
2816 {WM_ACTIVATEAPP, TRUE, FALSE, DDERR_NOEXCLUSIVEMODE},
2817 {0, FALSE, 0, 0},
2819 static const struct message exclusive_focus_restore_messages[] =
2821 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
2822 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
2823 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
2824 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
2825 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
2826 /* Native redundantly sets the window size here. */
2827 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
2828 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
2829 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
2830 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
2831 {0, FALSE, 0},
2833 static const struct message sc_restore_messages[] =
2835 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
2836 {WM_WINDOWPOSCHANGING, FALSE, 0},
2837 {WM_WINDOWPOSCHANGED, FALSE, 0},
2838 {WM_SIZE, TRUE, SIZE_RESTORED},
2839 {0, FALSE, 0},
2841 static const struct message sc_minimize_messages[] =
2843 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
2844 {WM_WINDOWPOSCHANGING, FALSE, 0},
2845 {WM_WINDOWPOSCHANGED, FALSE, 0},
2846 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2847 {0, FALSE, 0},
2849 static const struct message sc_maximize_messages[] =
2851 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
2852 {WM_WINDOWPOSCHANGING, FALSE, 0},
2853 {WM_WINDOWPOSCHANGED, FALSE, 0},
2854 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
2855 {0, FALSE, 0},
2858 static const struct message normal_messages[] =
2860 {WM_DISPLAYCHANGE, FALSE, 0},
2861 {0, FALSE, 0},
2864 ddraw = create_ddraw();
2865 ok(!!ddraw, "Failed to create a ddraw object.\n");
2867 memset(&param, 0, sizeof(param));
2868 hr = IDirectDraw4_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
2869 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2870 ref = IDirectDraw4_Release(ddraw);
2871 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2873 if (!param.user32_height)
2875 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
2876 return;
2879 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2880 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
2881 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
2883 memset(&devmode, 0, sizeof(devmode));
2884 devmode.dmSize = sizeof(devmode);
2885 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2886 devmode.dmPelsWidth = param.user32_width;
2887 devmode.dmPelsHeight = param.user32_height;
2888 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2889 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2891 ddraw = create_ddraw();
2892 ok(!!ddraw, "Failed to create a ddraw object.\n");
2894 wc.lpfnWndProc = mode_set_proc;
2895 wc.lpszClassName = "ddraw_test_wndproc_wc";
2896 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2897 wc.lpfnWndProc = mode_set_proc2;
2898 wc.lpszClassName = "ddraw_test_wndproc_wc2";
2899 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2901 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2902 0, 0, 100, 100, 0, 0, 0, 0);
2903 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
2904 0, 0, 100, 100, 0, 0, 0, 0);
2906 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2907 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2909 GetWindowRect(window, &r);
2910 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2911 wine_dbgstr_rect(&r));
2913 memset(&ddsd, 0, sizeof(ddsd));
2914 ddsd.dwSize = sizeof(ddsd);
2915 ddsd.dwFlags = DDSD_CAPS;
2916 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2918 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2919 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2920 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2921 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2922 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2923 param.user32_width, ddsd.dwWidth);
2924 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2925 param.user32_height, ddsd.dwHeight);
2927 GetWindowRect(window, &r);
2928 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2929 wine_dbgstr_rect(&r));
2931 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2932 expect_messages = exclusive_messages;
2933 screen_size.cx = 0;
2934 screen_size.cy = 0;
2936 hr = IDirectDrawSurface4_IsLost(primary);
2937 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2938 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2939 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2940 hr = IDirectDrawSurface4_IsLost(primary);
2941 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2943 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2944 expect_messages = NULL;
2945 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
2946 "Expected screen size %ux%u, got %ux%u.\n",
2947 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
2949 GetWindowRect(window, &r);
2950 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2951 wine_dbgstr_rect(&r));
2953 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2954 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2955 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2956 param.user32_width, ddsd.dwWidth);
2957 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2958 param.user32_height, ddsd.dwHeight);
2959 IDirectDrawSurface4_Release(primary);
2961 memset(&ddsd, 0, sizeof(ddsd));
2962 ddsd.dwSize = sizeof(ddsd);
2963 ddsd.dwFlags = DDSD_CAPS;
2964 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2966 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2967 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2968 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2969 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2970 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2971 param.ddraw_width, ddsd.dwWidth);
2972 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2973 param.ddraw_height, ddsd.dwHeight);
2975 GetWindowRect(window, &r);
2976 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2977 wine_dbgstr_rect(&r));
2979 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2980 expect_messages = exclusive_messages;
2981 screen_size.cx = 0;
2982 screen_size.cy = 0;
2984 hr = IDirectDrawSurface4_IsLost(primary);
2985 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2986 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2987 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2988 hr = IDirectDrawSurface4_IsLost(primary);
2989 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2991 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2992 expect_messages = NULL;
2993 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
2994 "Expected screen size %ux%u, got %ux%u.\n",
2995 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
2997 GetWindowRect(window, &r);
2998 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2999 wine_dbgstr_rect(&r));
3001 expect_messages = exclusive_focus_loss_messages;
3002 focus_test_ddraw = ddraw;
3003 ret = SetForegroundWindow(GetDesktopWindow());
3004 ok(ret, "Failed to set foreground window.\n");
3005 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3006 focus_test_ddraw = NULL;
3008 memset(&devmode, 0, sizeof(devmode));
3009 devmode.dmSize = sizeof(devmode);
3010 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3011 ok(ret, "Failed to get display mode.\n");
3012 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3013 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
3014 devmode.dmPelsWidth, devmode.dmPelsHeight);
3016 expect_messages = exclusive_focus_restore_messages;
3017 ShowWindow(window, SW_RESTORE);
3018 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3020 GetWindowRect(window, &r);
3021 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3022 wine_dbgstr_rect(&r));
3023 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3024 ok(ret, "Failed to get display mode.\n");
3025 ok(devmode.dmPelsWidth == param.ddraw_width
3026 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpect screen size %ux%u.\n",
3027 devmode.dmPelsWidth, devmode.dmPelsHeight);
3029 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3030 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3031 /* Normally the primary should be restored here. Unfortunately this causes the
3032 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
3033 * testbot. Another Restore call would presumably avoid the crash, but it also moots
3034 * the point of the GetSurfaceDesc call. */
3036 expect_messages = sc_minimize_messages;
3037 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3038 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3039 expect_messages = NULL;
3041 expect_messages = sc_restore_messages;
3042 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
3043 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3044 expect_messages = NULL;
3046 expect_messages = sc_maximize_messages;
3047 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3048 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3049 expect_messages = NULL;
3051 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3052 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3054 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3055 expect_messages = exclusive_messages;
3056 screen_size.cx = 0;
3057 screen_size.cy = 0;
3059 hr = IDirectDrawSurface4_IsLost(primary);
3060 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3061 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
3062 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3063 hr = IDirectDrawSurface4_IsLost(primary);
3064 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3066 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3067 expect_messages = NULL;
3068 ok(screen_size.cx == registry_mode.dmPelsWidth
3069 && screen_size.cy == registry_mode.dmPelsHeight,
3070 "Expected screen size %ux%u, got %ux%u.\n",
3071 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
3073 GetWindowRect(window, &r);
3074 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3075 wine_dbgstr_rect(&r));
3077 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3078 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3079 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3080 param.ddraw_width, ddsd.dwWidth);
3081 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3082 param.ddraw_height, ddsd.dwHeight);
3083 IDirectDrawSurface4_Release(primary);
3085 /* For Wine. */
3086 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3087 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3089 memset(&ddsd, 0, sizeof(ddsd));
3090 ddsd.dwSize = sizeof(ddsd);
3091 ddsd.dwFlags = DDSD_CAPS;
3092 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3094 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3095 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3096 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3097 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3098 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3099 registry_mode.dmPelsWidth, ddsd.dwWidth);
3100 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3101 registry_mode.dmPelsHeight, ddsd.dwHeight);
3103 GetWindowRect(window, &r);
3104 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3105 wine_dbgstr_rect(&r));
3107 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3108 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3110 GetWindowRect(window, &r);
3111 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3112 wine_dbgstr_rect(&r));
3114 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3115 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3116 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3117 registry_mode.dmPelsWidth, ddsd.dwWidth);
3118 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3119 registry_mode.dmPelsHeight, ddsd.dwHeight);
3120 IDirectDrawSurface4_Release(primary);
3122 memset(&ddsd, 0, sizeof(ddsd));
3123 ddsd.dwSize = sizeof(ddsd);
3124 ddsd.dwFlags = DDSD_CAPS;
3125 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3127 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3128 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3129 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3130 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3131 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3132 registry_mode.dmPelsWidth, ddsd.dwWidth);
3133 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3134 registry_mode.dmPelsHeight, ddsd.dwHeight);
3136 GetWindowRect(window, &r);
3137 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3138 wine_dbgstr_rect(&r));
3140 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3141 expect_messages = normal_messages;
3142 screen_size.cx = 0;
3143 screen_size.cy = 0;
3145 hr = IDirectDrawSurface4_IsLost(primary);
3146 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3147 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3148 devmode.dmPelsWidth = param.user32_width;
3149 devmode.dmPelsHeight = param.user32_height;
3150 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3151 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3152 hr = IDirectDrawSurface4_IsLost(primary);
3153 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3155 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3156 expect_messages = NULL;
3157 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3159 GetWindowRect(window, &r);
3160 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3161 wine_dbgstr_rect(&r));
3163 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3164 expect_messages = normal_messages;
3165 screen_size.cx = 0;
3166 screen_size.cy = 0;
3168 hr = IDirectDrawSurface4_Restore(primary);
3169 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3170 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3171 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3172 hr = IDirectDrawSurface4_Restore(primary);
3173 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3174 hr = IDirectDrawSurface4_IsLost(primary);
3175 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3177 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3178 expect_messages = NULL;
3179 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3181 GetWindowRect(window, &r);
3182 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3183 wine_dbgstr_rect(&r));
3185 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3186 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3187 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3188 registry_mode.dmPelsWidth, ddsd.dwWidth);
3189 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3190 registry_mode.dmPelsHeight, ddsd.dwHeight);
3191 IDirectDrawSurface4_Release(primary);
3193 memset(&ddsd, 0, sizeof(ddsd));
3194 ddsd.dwSize = sizeof(ddsd);
3195 ddsd.dwFlags = DDSD_CAPS;
3196 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3198 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3199 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3200 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3201 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3202 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3203 param.ddraw_width, ddsd.dwWidth);
3204 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3205 param.ddraw_height, ddsd.dwHeight);
3207 GetWindowRect(window, &r);
3208 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3209 wine_dbgstr_rect(&r));
3211 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3212 expect_messages = normal_messages;
3213 screen_size.cx = 0;
3214 screen_size.cy = 0;
3216 hr = IDirectDrawSurface4_IsLost(primary);
3217 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3218 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
3219 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3220 hr = IDirectDrawSurface4_IsLost(primary);
3221 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3223 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3224 expect_messages = NULL;
3225 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3227 GetWindowRect(window, &r);
3228 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3229 wine_dbgstr_rect(&r));
3231 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3232 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3233 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3234 param.ddraw_width, ddsd.dwWidth);
3235 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3236 param.ddraw_height, ddsd.dwHeight);
3237 IDirectDrawSurface4_Release(primary);
3239 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3240 ok(ret, "Failed to get display mode.\n");
3241 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3242 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3243 "Expected resolution %ux%u, got %ux%u.\n",
3244 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3245 devmode.dmPelsWidth, devmode.dmPelsHeight);
3246 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3247 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3249 memset(&ddsd, 0, sizeof(ddsd));
3250 ddsd.dwSize = sizeof(ddsd);
3251 ddsd.dwFlags = DDSD_CAPS;
3252 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3254 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3255 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3256 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3257 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3258 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3259 registry_mode.dmPelsWidth, ddsd.dwWidth);
3260 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3261 registry_mode.dmPelsHeight, ddsd.dwHeight);
3263 GetWindowRect(window, &r);
3264 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3265 wine_dbgstr_rect(&r));
3267 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
3268 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
3269 * not DDSCL_FULLSCREEN. */
3270 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3271 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3273 GetWindowRect(window, &r);
3274 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3275 wine_dbgstr_rect(&r));
3277 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3278 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3279 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3280 registry_mode.dmPelsWidth, ddsd.dwWidth);
3281 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3282 registry_mode.dmPelsHeight, ddsd.dwHeight);
3283 IDirectDrawSurface4_Release(primary);
3285 memset(&ddsd, 0, sizeof(ddsd));
3286 ddsd.dwSize = sizeof(ddsd);
3287 ddsd.dwFlags = DDSD_CAPS;
3288 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3290 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3291 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3292 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3293 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3294 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3295 registry_mode.dmPelsWidth, ddsd.dwWidth);
3296 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3297 registry_mode.dmPelsHeight, ddsd.dwHeight);
3299 GetWindowRect(window, &r);
3300 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3301 wine_dbgstr_rect(&r));
3303 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3304 expect_messages = normal_messages;
3305 screen_size.cx = 0;
3306 screen_size.cy = 0;
3308 hr = IDirectDrawSurface4_IsLost(primary);
3309 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3310 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3311 devmode.dmPelsWidth = param.user32_width;
3312 devmode.dmPelsHeight = param.user32_height;
3313 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3314 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3315 hr = IDirectDrawSurface4_IsLost(primary);
3316 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3318 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3319 expect_messages = NULL;
3320 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3322 GetWindowRect(window, &r);
3323 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3324 wine_dbgstr_rect(&r));
3326 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3327 expect_messages = normal_messages;
3328 screen_size.cx = 0;
3329 screen_size.cy = 0;
3331 hr = IDirectDrawSurface4_Restore(primary);
3332 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3333 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3334 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3335 hr = IDirectDrawSurface4_Restore(primary);
3336 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3337 hr = IDirectDrawSurface4_IsLost(primary);
3338 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3340 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3341 expect_messages = NULL;
3342 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3344 GetWindowRect(window, &r);
3345 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3346 wine_dbgstr_rect(&r));
3348 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3349 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3350 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3351 registry_mode.dmPelsWidth, ddsd.dwWidth);
3352 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3353 registry_mode.dmPelsHeight, ddsd.dwHeight);
3354 IDirectDrawSurface4_Release(primary);
3356 memset(&ddsd, 0, sizeof(ddsd));
3357 ddsd.dwSize = sizeof(ddsd);
3358 ddsd.dwFlags = DDSD_CAPS;
3359 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3361 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3362 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3363 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3364 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3365 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3366 param.ddraw_width, ddsd.dwWidth);
3367 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3368 param.ddraw_height, ddsd.dwHeight);
3370 GetWindowRect(window, &r);
3371 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3372 wine_dbgstr_rect(&r));
3374 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3375 expect_messages = normal_messages;
3376 screen_size.cx = 0;
3377 screen_size.cy = 0;
3379 hr = IDirectDrawSurface4_IsLost(primary);
3380 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3381 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
3382 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3383 hr = IDirectDrawSurface4_IsLost(primary);
3384 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3386 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3387 expect_messages = NULL;
3388 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3390 GetWindowRect(window, &r);
3391 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3392 wine_dbgstr_rect(&r));
3394 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3395 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3396 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3397 param.ddraw_width, ddsd.dwWidth);
3398 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3399 param.ddraw_height, ddsd.dwHeight);
3400 IDirectDrawSurface4_Release(primary);
3402 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3403 ok(ret, "Failed to get display mode.\n");
3404 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3405 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3406 "Expected resolution %ux%u, got %ux%u.\n",
3407 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3408 devmode.dmPelsWidth, devmode.dmPelsHeight);
3409 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3410 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3412 memset(&ddsd, 0, sizeof(ddsd));
3413 ddsd.dwSize = sizeof(ddsd);
3414 ddsd.dwFlags = DDSD_CAPS;
3415 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3417 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3418 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3419 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3420 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3421 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3422 registry_mode.dmPelsWidth, ddsd.dwWidth);
3423 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3424 registry_mode.dmPelsHeight, ddsd.dwHeight);
3425 IDirectDrawSurface4_Release(primary);
3427 GetWindowRect(window, &r);
3428 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3429 wine_dbgstr_rect(&r));
3431 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
3432 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3433 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3434 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3435 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3437 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3438 expect_messages = exclusive_messages;
3439 screen_size.cx = 0;
3440 screen_size.cy = 0;
3442 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3443 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3445 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3446 expect_messages = NULL;
3447 ok(screen_size.cx == registry_mode.dmPelsWidth
3448 && screen_size.cy == registry_mode.dmPelsHeight,
3449 "Expected screen size %ux%u, got %ux%u.\n",
3450 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3451 screen_size.cx, screen_size.cy);
3453 GetWindowRect(window, &r);
3454 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3455 wine_dbgstr_rect(&r));
3457 memset(&ddsd, 0, sizeof(ddsd));
3458 ddsd.dwSize = sizeof(ddsd);
3459 ddsd.dwFlags = DDSD_CAPS;
3460 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3462 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3463 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3464 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3465 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3466 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3467 registry_mode.dmPelsWidth, ddsd.dwWidth);
3468 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3469 registry_mode.dmPelsHeight, ddsd.dwHeight);
3470 IDirectDrawSurface4_Release(primary);
3472 /* The screen restore is a property of DDSCL_EXCLUSIVE */
3473 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3474 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3475 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3476 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3478 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3479 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3481 memset(&ddsd, 0, sizeof(ddsd));
3482 ddsd.dwSize = sizeof(ddsd);
3483 ddsd.dwFlags = DDSD_CAPS;
3484 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3486 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3487 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3488 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3489 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3490 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3491 param.ddraw_width, ddsd.dwWidth);
3492 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3493 param.ddraw_height, ddsd.dwHeight);
3494 IDirectDrawSurface4_Release(primary);
3496 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
3497 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3499 /* If the window is changed at the same time, messages are sent to the new window. */
3500 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3501 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3502 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3503 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3505 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3506 expect_messages = exclusive_messages;
3507 screen_size.cx = 0;
3508 screen_size.cy = 0;
3509 screen_size2.cx = 0;
3510 screen_size2.cy = 0;
3512 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3513 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3515 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3516 expect_messages = NULL;
3517 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n",
3518 screen_size.cx, screen_size.cy);
3519 ok(screen_size2.cx == registry_mode.dmPelsWidth && screen_size2.cy == registry_mode.dmPelsHeight,
3520 "Expected screen size 2 %ux%u, got %ux%u.\n",
3521 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size2.cx, screen_size2.cy);
3523 GetWindowRect(window, &r);
3524 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3525 wine_dbgstr_rect(&r));
3526 GetWindowRect(window2, &r);
3527 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3528 wine_dbgstr_rect(&r));
3530 memset(&ddsd, 0, sizeof(ddsd));
3531 ddsd.dwSize = sizeof(ddsd);
3532 ddsd.dwFlags = DDSD_CAPS;
3533 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3535 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3536 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3537 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3538 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3539 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3540 registry_mode.dmPelsWidth, ddsd.dwWidth);
3541 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3542 registry_mode.dmPelsHeight, ddsd.dwHeight);
3543 IDirectDrawSurface4_Release(primary);
3545 ref = IDirectDraw4_Release(ddraw);
3546 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3548 GetWindowRect(window, &r);
3549 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3550 wine_dbgstr_rect(&r));
3552 expect_messages = NULL;
3553 DestroyWindow(window);
3554 DestroyWindow(window2);
3555 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3556 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
3559 static void test_coop_level_mode_set_multi(void)
3561 IDirectDraw4 *ddraw1, *ddraw2;
3562 UINT w, h;
3563 HWND window;
3564 HRESULT hr;
3565 ULONG ref;
3567 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3568 0, 0, 100, 100, 0, 0, 0, 0);
3569 ddraw1 = create_ddraw();
3570 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3572 /* With just a single ddraw object, the display mode is restored on
3573 * release. */
3574 hr = set_display_mode(ddraw1, 800, 600);
3575 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3576 w = GetSystemMetrics(SM_CXSCREEN);
3577 ok(w == 800, "Got unexpected screen width %u.\n", w);
3578 h = GetSystemMetrics(SM_CYSCREEN);
3579 ok(h == 600, "Got unexpected screen height %u.\n", h);
3581 ref = IDirectDraw4_Release(ddraw1);
3582 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3583 w = GetSystemMetrics(SM_CXSCREEN);
3584 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3585 h = GetSystemMetrics(SM_CYSCREEN);
3586 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3588 /* When there are multiple ddraw objects, the display mode is restored to
3589 * the initial mode, before the first SetDisplayMode() call. */
3590 ddraw1 = create_ddraw();
3591 hr = set_display_mode(ddraw1, 800, 600);
3592 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3593 w = GetSystemMetrics(SM_CXSCREEN);
3594 ok(w == 800, "Got unexpected screen width %u.\n", w);
3595 h = GetSystemMetrics(SM_CYSCREEN);
3596 ok(h == 600, "Got unexpected screen height %u.\n", h);
3598 ddraw2 = create_ddraw();
3599 hr = set_display_mode(ddraw2, 640, 480);
3600 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3601 w = GetSystemMetrics(SM_CXSCREEN);
3602 ok(w == 640, "Got unexpected screen width %u.\n", w);
3603 h = GetSystemMetrics(SM_CYSCREEN);
3604 ok(h == 480, "Got unexpected screen height %u.\n", h);
3606 ref = IDirectDraw4_Release(ddraw2);
3607 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3608 w = GetSystemMetrics(SM_CXSCREEN);
3609 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3610 h = GetSystemMetrics(SM_CYSCREEN);
3611 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3613 ref = IDirectDraw4_Release(ddraw1);
3614 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3615 w = GetSystemMetrics(SM_CXSCREEN);
3616 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3617 h = GetSystemMetrics(SM_CYSCREEN);
3618 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3620 /* Regardless of release ordering. */
3621 ddraw1 = create_ddraw();
3622 hr = set_display_mode(ddraw1, 800, 600);
3623 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3624 w = GetSystemMetrics(SM_CXSCREEN);
3625 ok(w == 800, "Got unexpected screen width %u.\n", w);
3626 h = GetSystemMetrics(SM_CYSCREEN);
3627 ok(h == 600, "Got unexpected screen height %u.\n", h);
3629 ddraw2 = create_ddraw();
3630 hr = set_display_mode(ddraw2, 640, 480);
3631 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3632 w = GetSystemMetrics(SM_CXSCREEN);
3633 ok(w == 640, "Got unexpected screen width %u.\n", w);
3634 h = GetSystemMetrics(SM_CYSCREEN);
3635 ok(h == 480, "Got unexpected screen height %u.\n", h);
3637 ref = IDirectDraw4_Release(ddraw1);
3638 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3639 w = GetSystemMetrics(SM_CXSCREEN);
3640 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3641 h = GetSystemMetrics(SM_CYSCREEN);
3642 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3644 ref = IDirectDraw4_Release(ddraw2);
3645 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3646 w = GetSystemMetrics(SM_CXSCREEN);
3647 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3648 h = GetSystemMetrics(SM_CYSCREEN);
3649 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3651 /* But only for ddraw objects that called SetDisplayMode(). */
3652 ddraw1 = create_ddraw();
3653 ddraw2 = create_ddraw();
3654 hr = set_display_mode(ddraw2, 640, 480);
3655 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3656 w = GetSystemMetrics(SM_CXSCREEN);
3657 ok(w == 640, "Got unexpected screen width %u.\n", w);
3658 h = GetSystemMetrics(SM_CYSCREEN);
3659 ok(h == 480, "Got unexpected screen height %u.\n", h);
3661 ref = IDirectDraw4_Release(ddraw1);
3662 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3663 w = GetSystemMetrics(SM_CXSCREEN);
3664 ok(w == 640, "Got unexpected screen width %u.\n", w);
3665 h = GetSystemMetrics(SM_CYSCREEN);
3666 ok(h == 480, "Got unexpected screen height %u.\n", h);
3668 ref = IDirectDraw4_Release(ddraw2);
3669 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3670 w = GetSystemMetrics(SM_CXSCREEN);
3671 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3672 h = GetSystemMetrics(SM_CYSCREEN);
3673 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3675 /* If there's a ddraw object that's currently in exclusive mode, it blocks
3676 * restoring the display mode. */
3677 ddraw1 = create_ddraw();
3678 hr = set_display_mode(ddraw1, 800, 600);
3679 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3680 w = GetSystemMetrics(SM_CXSCREEN);
3681 ok(w == 800, "Got unexpected screen width %u.\n", w);
3682 h = GetSystemMetrics(SM_CYSCREEN);
3683 ok(h == 600, "Got unexpected screen height %u.\n", h);
3685 ddraw2 = create_ddraw();
3686 hr = set_display_mode(ddraw2, 640, 480);
3687 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3688 w = GetSystemMetrics(SM_CXSCREEN);
3689 ok(w == 640, "Got unexpected screen width %u.\n", w);
3690 h = GetSystemMetrics(SM_CYSCREEN);
3691 ok(h == 480, "Got unexpected screen height %u.\n", h);
3693 hr = IDirectDraw4_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3694 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3696 ref = IDirectDraw4_Release(ddraw1);
3697 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3698 w = GetSystemMetrics(SM_CXSCREEN);
3699 ok(w == 640, "Got unexpected screen width %u.\n", w);
3700 h = GetSystemMetrics(SM_CYSCREEN);
3701 ok(h == 480, "Got unexpected screen height %u.\n", h);
3703 ref = IDirectDraw4_Release(ddraw2);
3704 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3705 w = GetSystemMetrics(SM_CXSCREEN);
3706 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3707 h = GetSystemMetrics(SM_CYSCREEN);
3708 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3710 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3711 ddraw1 = create_ddraw();
3712 hr = set_display_mode(ddraw1, 800, 600);
3713 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3714 w = GetSystemMetrics(SM_CXSCREEN);
3715 ok(w == 800, "Got unexpected screen width %u.\n", w);
3716 h = GetSystemMetrics(SM_CYSCREEN);
3717 ok(h == 600, "Got unexpected screen height %u.\n", h);
3719 hr = IDirectDraw4_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3720 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3722 ddraw2 = create_ddraw();
3723 hr = set_display_mode(ddraw2, 640, 480);
3724 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3726 ref = IDirectDraw4_Release(ddraw1);
3727 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3728 w = GetSystemMetrics(SM_CXSCREEN);
3729 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3730 h = GetSystemMetrics(SM_CYSCREEN);
3731 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3733 ref = IDirectDraw4_Release(ddraw2);
3734 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3735 w = GetSystemMetrics(SM_CXSCREEN);
3736 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3737 h = GetSystemMetrics(SM_CYSCREEN);
3738 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3740 DestroyWindow(window);
3743 static void test_initialize(void)
3745 IDirectDraw4 *ddraw;
3746 HRESULT hr;
3748 ddraw = create_ddraw();
3749 ok(!!ddraw, "Failed to create a ddraw object.\n");
3751 hr = IDirectDraw4_Initialize(ddraw, NULL);
3752 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
3753 IDirectDraw4_Release(ddraw);
3755 CoInitialize(NULL);
3756 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw4, (void **)&ddraw);
3757 ok(SUCCEEDED(hr), "Failed to create IDirectDraw4 instance, hr %#x.\n", hr);
3758 hr = IDirectDraw4_Initialize(ddraw, NULL);
3759 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
3760 hr = IDirectDraw4_Initialize(ddraw, NULL);
3761 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
3762 IDirectDraw4_Release(ddraw);
3763 CoUninitialize();
3766 static void test_coop_level_surf_create(void)
3768 IDirectDrawSurface4 *surface;
3769 IDirectDraw4 *ddraw;
3770 DDSURFACEDESC2 ddsd;
3771 HRESULT hr;
3773 ddraw = create_ddraw();
3774 ok(!!ddraw, "Failed to create a ddraw object.\n");
3776 memset(&ddsd, 0, sizeof(ddsd));
3777 ddsd.dwSize = sizeof(ddsd);
3778 ddsd.dwFlags = DDSD_CAPS;
3779 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3780 surface = (void *)0xdeadbeef;
3781 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
3782 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3783 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3785 surface = (void *)0xdeadbeef;
3786 hr = IDirectDraw4_CreateSurface(ddraw, NULL, &surface, NULL);
3787 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3788 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3790 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3791 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3793 surface = (void *)0xdeadbeef;
3794 hr = IDirectDraw4_CreateSurface(ddraw, NULL, &surface, NULL);
3795 ok(hr == DDERR_INVALIDPARAMS, "Unexpected hr %#x.\n", hr);
3796 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3798 IDirectDraw4_Release(ddraw);
3801 static void test_vb_discard(void)
3803 static const struct vec4 quad[] =
3805 { 0.0f, 480.0f, 0.0f, 1.0f},
3806 { 0.0f, 0.0f, 0.0f, 1.0f},
3807 {640.0f, 480.0f, 0.0f, 1.0f},
3808 {640.0f, 0.0f, 0.0f, 1.0f},
3811 IDirect3DDevice3 *device;
3812 IDirect3D3 *d3d;
3813 IDirect3DVertexBuffer *buffer;
3814 HWND window;
3815 HRESULT hr;
3816 D3DVERTEXBUFFERDESC desc;
3817 BYTE *data;
3818 static const unsigned int vbsize = 16;
3819 unsigned int i;
3821 window = create_window();
3822 if (!(device = create_device(window, DDSCL_NORMAL)))
3824 skip("Failed to create a 3D device, skipping test.\n");
3825 DestroyWindow(window);
3826 return;
3829 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
3830 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
3832 memset(&desc, 0, sizeof(desc));
3833 desc.dwSize = sizeof(desc);
3834 desc.dwCaps = D3DVBCAPS_WRITEONLY;
3835 desc.dwFVF = D3DFVF_XYZRHW;
3836 desc.dwNumVertices = vbsize;
3837 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &buffer, 0, NULL);
3838 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3840 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3841 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3842 memcpy(data, quad, sizeof(quad));
3843 hr = IDirect3DVertexBuffer_Unlock(buffer);
3844 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3846 hr = IDirect3DDevice3_BeginScene(device);
3847 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3848 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
3849 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3850 hr = IDirect3DDevice3_EndScene(device);
3851 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3853 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3854 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3855 memset(data, 0xaa, sizeof(struct vec4) * vbsize);
3856 hr = IDirect3DVertexBuffer_Unlock(buffer);
3857 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3859 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3860 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3861 for (i = 0; i < sizeof(struct vec4) * vbsize; i++)
3863 if (data[i] != 0xaa)
3865 ok(FALSE, "Vertex buffer data byte %u is 0x%02x, expected 0xaa\n", i, data[i]);
3866 break;
3869 hr = IDirect3DVertexBuffer_Unlock(buffer);
3870 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3872 IDirect3DVertexBuffer_Release(buffer);
3873 IDirect3D3_Release(d3d);
3874 IDirect3DDevice3_Release(device);
3875 DestroyWindow(window);
3878 static void test_coop_level_multi_window(void)
3880 HWND window1, window2;
3881 IDirectDraw4 *ddraw;
3882 HRESULT hr;
3884 window1 = create_window();
3885 window2 = create_window();
3886 ddraw = create_ddraw();
3887 ok(!!ddraw, "Failed to create a ddraw object.\n");
3889 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
3890 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3891 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3892 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3893 ok(IsWindow(window1), "Window 1 was destroyed.\n");
3894 ok(IsWindow(window2), "Window 2 was destroyed.\n");
3896 IDirectDraw4_Release(ddraw);
3897 DestroyWindow(window2);
3898 DestroyWindow(window1);
3901 static void test_draw_strided(void)
3903 static struct vec3 position[] =
3905 {-1.0, -1.0, 0.0},
3906 {-1.0, 1.0, 0.0},
3907 { 1.0, 1.0, 0.0},
3908 { 1.0, -1.0, 0.0},
3910 static DWORD diffuse[] =
3912 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
3914 static WORD indices[] =
3916 0, 1, 2, 2, 3, 0
3919 IDirectDrawSurface4 *rt;
3920 IDirect3DDevice3 *device;
3921 D3DCOLOR color;
3922 HWND window;
3923 HRESULT hr;
3924 D3DDRAWPRIMITIVESTRIDEDDATA strided;
3925 IDirect3DViewport3 *viewport;
3926 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3928 window = create_window();
3929 if (!(device = create_device(window, DDSCL_NORMAL)))
3931 skip("Failed to create a 3D device, skipping test.\n");
3932 DestroyWindow(window);
3933 return;
3936 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
3937 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3938 viewport = create_viewport(device, 0, 0, 640, 480);
3939 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
3940 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
3941 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
3942 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
3944 hr = IDirect3DDevice3_BeginScene(device);
3945 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3947 memset(&strided, 0x55, sizeof(strided));
3948 strided.position.lpvData = position;
3949 strided.position.dwStride = sizeof(*position);
3950 strided.diffuse.lpvData = diffuse;
3951 strided.diffuse.dwStride = sizeof(*diffuse);
3952 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE,
3953 &strided, 4, indices, 6, 0);
3954 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3956 hr = IDirect3DDevice3_EndScene(device);
3957 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3959 color = get_surface_color(rt, 320, 240);
3960 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3962 IDirect3DViewport3_Release(viewport);
3963 IDirectDrawSurface4_Release(rt);
3964 IDirect3DDevice3_Release(device);
3965 DestroyWindow(window);
3968 static void test_lighting(void)
3970 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3971 static D3DMATRIX mat =
3973 1.0f, 0.0f, 0.0f, 0.0f,
3974 0.0f, 1.0f, 0.0f, 0.0f,
3975 0.0f, 0.0f, 1.0f, 0.0f,
3976 0.0f, 0.0f, 0.0f, 1.0f,
3978 mat_singular =
3980 1.0f, 0.0f, 1.0f, 0.0f,
3981 0.0f, 1.0f, 0.0f, 0.0f,
3982 1.0f, 0.0f, 1.0f, 0.0f,
3983 0.0f, 0.0f, 0.5f, 1.0f,
3985 mat_transf =
3987 0.0f, 0.0f, 1.0f, 0.0f,
3988 0.0f, 1.0f, 0.0f, 0.0f,
3989 -1.0f, 0.0f, 0.0f, 0.0f,
3990 10.f, 10.0f, 10.0f, 1.0f,
3992 mat_nonaffine =
3994 1.0f, 0.0f, 0.0f, 0.0f,
3995 0.0f, 1.0f, 0.0f, 0.0f,
3996 0.0f, 0.0f, 1.0f, -1.0f,
3997 10.f, 10.0f, 10.0f, 0.0f,
3999 static struct vertex
4001 struct vec3 position;
4002 DWORD diffuse;
4004 unlitquad[] =
4006 {{-1.0f, -1.0f, 0.1f}, 0xffff0000},
4007 {{-1.0f, 0.0f, 0.1f}, 0xffff0000},
4008 {{ 0.0f, 0.0f, 0.1f}, 0xffff0000},
4009 {{ 0.0f, -1.0f, 0.1f}, 0xffff0000},
4011 litquad[] =
4013 {{-1.0f, 0.0f, 0.1f}, 0xff00ff00},
4014 {{-1.0f, 1.0f, 0.1f}, 0xff00ff00},
4015 {{ 0.0f, 1.0f, 0.1f}, 0xff00ff00},
4016 {{ 0.0f, 0.0f, 0.1f}, 0xff00ff00},
4018 static struct vertex_normal
4020 struct vec3 position;
4021 struct vec3 normal;
4022 DWORD diffuse;
4024 unlitnquad[] =
4026 {{0.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
4027 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
4028 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
4029 {{1.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
4031 litnquad[] =
4033 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
4034 {{0.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
4035 {{1.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
4036 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
4038 nquad[] =
4040 {{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4041 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4042 {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4043 {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4045 rotatedquad[] =
4047 {{-10.0f, -11.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
4048 {{-10.0f, -9.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
4049 {{-10.0f, -9.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
4050 {{-10.0f, -11.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
4052 translatedquad[] =
4054 {{-11.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4055 {{-11.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4056 {{ -9.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4057 {{ -9.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4059 static WORD indices[] = {0, 1, 2, 2, 3, 0};
4060 static const struct
4062 D3DMATRIX *world_matrix;
4063 void *quad;
4064 DWORD expected;
4065 const char *message;
4067 tests[] =
4069 {&mat, nquad, 0x000080ff, "Lit quad with light"},
4070 {&mat_singular, nquad, 0x000080b4, "Lit quad with singular world matrix"},
4071 {&mat_transf, rotatedquad, 0x000080ff, "Lit quad with transformation matrix"},
4072 {&mat_nonaffine, translatedquad, 0x000080ff, "Lit quad with non-affine matrix"},
4074 DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
4075 IDirect3DVertexBuffer *src_vb1, *src_vb2, *dst_vb;
4076 IDirect3DViewport3 *viewport, *viewport2;
4077 DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
4078 struct vertex_normal *src_data2;
4079 IDirect3DMaterial3 *material;
4080 D3DMATERIALHANDLE mat_handle;
4081 D3DVERTEXBUFFERDESC vb_desc;
4082 IDirect3DDevice3 *device;
4083 struct vertex *src_data1;
4084 IDirectDrawSurface4 *rt;
4085 IDirect3DLight *light;
4086 D3DLIGHT2 light_desc;
4087 IDirect3D3 *d3d;
4088 D3DCOLOR color;
4089 ULONG refcount;
4090 unsigned int i;
4091 HWND window;
4092 HRESULT hr;
4093 struct
4095 struct vec4 position;
4096 DWORD diffuse;
4097 DWORD specular;
4099 *dst_data;
4101 window = create_window();
4102 if (!(device = create_device(window, DDSCL_NORMAL)))
4104 skip("Failed to create a 3D device, skipping test.\n");
4105 DestroyWindow(window);
4106 return;
4109 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
4110 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4112 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
4113 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4115 viewport = create_viewport(device, 0, 0, 640, 480);
4116 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
4117 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4119 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
4120 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4122 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
4123 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4124 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
4125 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4126 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
4127 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4128 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
4129 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4130 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4131 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4132 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
4133 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4134 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
4135 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4137 hr = IDirect3DDevice3_BeginScene(device);
4138 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4140 memset(&vb_desc, 0, sizeof(vb_desc));
4141 vb_desc.dwSize = sizeof(vb_desc);
4142 vb_desc.dwFVF = fvf;
4143 vb_desc.dwNumVertices = 2;
4144 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &src_vb1, 0, NULL);
4145 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4146 vb_desc.dwSize = sizeof(vb_desc);
4147 vb_desc.dwFVF = nfvf;
4148 vb_desc.dwNumVertices = 2;
4149 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &src_vb2, 0, NULL);
4150 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4152 memset(&vb_desc, 0, sizeof(vb_desc));
4153 vb_desc.dwSize = sizeof(vb_desc);
4154 vb_desc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
4155 vb_desc.dwNumVertices = 4;
4156 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &dst_vb, 0, NULL);
4157 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4159 hr = IDirect3DVertexBuffer_Lock(src_vb1, 0, (void **)&src_data1, NULL);
4160 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4161 memcpy(src_data1, unlitquad, sizeof(*src_data1));
4162 memcpy(&src_data1[1], litquad, sizeof(*src_data1));
4163 hr = IDirect3DVertexBuffer_Unlock(src_vb1);
4164 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4166 hr = IDirect3DVertexBuffer_Lock(src_vb2, 0, (void **)&src_data2, NULL);
4167 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4168 memcpy(src_data2, unlitnquad, sizeof(*src_data2));
4169 memcpy(&src_data2[1], litnquad, sizeof(*src_data2));
4170 hr = IDirect3DVertexBuffer_Unlock(src_vb2);
4171 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4173 /* There is no D3DRENDERSTATE_LIGHTING on ddraw < 7. */
4174 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
4175 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4176 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0,
4177 1, src_vb1, 0, device, 0);
4178 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4179 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, unlitquad, 4,
4180 indices, 6, 0);
4181 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4183 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
4184 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4185 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 1,
4186 1, src_vb1, 1, device, 0);
4187 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4188 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, litquad, 4,
4189 indices, 6, 0);
4190 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4192 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
4193 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4194 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 2,
4195 1, src_vb2, 0, device, 0);
4196 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4197 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, unlitnquad, 4,
4198 indices, 6, 0);
4199 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4201 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
4202 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4203 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 3,
4204 1, src_vb2, 1, device, 0);
4205 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4206 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, litnquad, 4,
4207 indices, 6, 0);
4208 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4210 hr = IDirect3DDevice3_EndScene(device);
4211 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4213 hr = IDirect3DVertexBuffer_Lock(dst_vb, 0, (void **)&dst_data, NULL);
4214 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4216 color = get_surface_color(rt, 160, 360);
4217 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x.\n", color);
4218 ok(dst_data[0].diffuse == 0xffff0000,
4219 "Unlit quad without normals has color 0x%08x, expected 0xffff0000.\n", dst_data[0].diffuse);
4220 ok(!dst_data[0].specular,
4221 "Unexpected specular color 0x%08x.\n", dst_data[0].specular);
4223 color = get_surface_color(rt, 160, 120);
4224 ok(color == 0x0000ff00, "Lit quad without normals has color 0x%08x.\n", color);
4225 ok(dst_data[1].diffuse == 0xff00ff00,
4226 "Lit quad without normals has color 0x%08x, expected 0xff000000.\n", dst_data[1].diffuse);
4227 ok(!dst_data[1].specular,
4228 "Unexpected specular color 0x%08x.\n", dst_data[1].specular);
4230 color = get_surface_color(rt, 480, 360);
4231 ok(color == 0x000000ff, "Unlit quad with normals has color 0x%08x.\n", color);
4232 ok(dst_data[2].diffuse == 0xff0000ff,
4233 "Unlit quad with normals has color 0x%08x, expected 0xff0000ff.\n", dst_data[2].diffuse);
4234 ok(!dst_data[2].specular,
4235 "Unexpected specular color 0x%08x.\n", dst_data[2].specular);
4237 color = get_surface_color(rt, 480, 120);
4238 ok(color == 0x00ffff00, "Lit quad with normals has color 0x%08x.\n", color);
4239 ok(dst_data[3].diffuse == 0xffffff00,
4240 "Lit quad with normals has color 0x%08x, expected 0xff000000.\n", dst_data[3].diffuse);
4241 ok(!dst_data[3].specular,
4242 "Unexpected specular color 0x%08x.\n", dst_data[3].specular);
4244 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
4245 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4247 material = create_diffuse_and_ambient_material(device, 0.0f, 1.0f, 1.0f, 0.5f);
4248 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
4249 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4250 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
4251 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4252 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_AMBIENT, 0xff008000);
4253 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4255 hr = IDirect3D3_CreateLight(d3d, &light, NULL);
4256 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4257 memset(&light_desc, 0, sizeof(light_desc));
4258 light_desc.dwSize = sizeof(light_desc);
4259 light_desc.dltType = D3DLIGHT_DIRECTIONAL;
4260 U1(light_desc.dcvColor).r = 1.0f;
4261 U2(light_desc.dcvColor).g = 1.0f;
4262 U3(light_desc.dcvColor).b = 1.0f;
4263 U4(light_desc.dcvColor).a = 0.5f;
4264 U3(light_desc.dvDirection).z = 1.0f;
4265 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
4266 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4267 hr = IDirect3DViewport3_AddLight(viewport, light);
4268 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4269 hr = IDirect3DViewport3_AddLight(viewport, light);
4270 ok(hr == D3DERR_LIGHTHASVIEWPORT, "Got unexpected hr %#x.\n", hr);
4272 viewport2 = create_viewport(device, 0, 0, 640, 480);
4273 hr = IDirect3DViewport3_AddLight(viewport2, light);
4274 ok(hr == D3DERR_LIGHTHASVIEWPORT, "Got unexpected hr %#x.\n", hr);
4275 IDirect3DViewport3_Release(viewport2);
4277 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
4278 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4280 hr = IDirect3DDevice3_BeginScene(device);
4281 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4283 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, nquad,
4284 4, indices, 6, 0);
4285 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4287 hr = IDirect3DDevice3_EndScene(device);
4288 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4290 color = get_surface_color(rt, 320, 240);
4291 ok(color == 0x00008000, "Lit quad with no light has color 0x%08x.\n", color);
4293 light_desc.dwFlags = D3DLIGHT_ACTIVE;
4294 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
4295 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4296 hr = IDirect3DViewport3_DeleteLight(viewport, light);
4297 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4298 light_desc.dwFlags = 0;
4299 hr = IDirect3DLight_GetLight(light, (D3DLIGHT *)&light_desc);
4300 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4301 ok(light_desc.dwFlags == D3DLIGHT_ACTIVE, "Got unexpected flags %#x.\n", light_desc.dwFlags);
4303 hr = IDirect3DViewport3_AddLight(viewport, light);
4304 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4306 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4308 hr = IDirect3DVertexBuffer_Lock(src_vb2, 0, (void **)&src_data2, NULL);
4309 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4310 memcpy(src_data2, tests[i].quad, sizeof(*src_data2));
4311 hr = IDirect3DVertexBuffer_Unlock(src_vb2);
4312 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4314 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
4315 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4317 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
4318 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4320 hr = IDirect3DDevice3_BeginScene(device);
4321 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4323 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 0,
4324 1, src_vb2, 0, device, 0);
4325 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4326 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, tests[i].quad,
4327 4, indices, 6, 0);
4328 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4330 hr = IDirect3DDevice3_EndScene(device);
4331 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4333 hr = IDirect3DVertexBuffer_Lock(dst_vb, 0, (void **)&dst_data, NULL);
4334 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4336 color = get_surface_color(rt, 320, 240);
4337 ok(color == tests[i].expected, "%s has color 0x%08x.\n", tests[i].message, color);
4338 ok(dst_data[0].diffuse == (tests[i].expected | 0xff000000),
4339 "%s has color 0x%08x.\n", tests[i].message, dst_data[0].diffuse);
4340 ok(!dst_data[0].specular,
4341 "%s has specular color 0x%08x.\n", tests[i].message, dst_data[0].specular);
4343 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
4344 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4347 IDirect3DVertexBuffer_Release(src_vb1);
4348 IDirect3DVertexBuffer_Release(src_vb2);
4349 IDirect3DVertexBuffer_Release(dst_vb);
4351 hr = IDirect3DViewport3_DeleteLight(viewport, light);
4352 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4353 IDirect3DLight_Release(light);
4354 destroy_material(material);
4355 IDirect3DViewport3_Release(viewport);
4356 IDirectDrawSurface4_Release(rt);
4357 refcount = IDirect3DDevice3_Release(device);
4358 ok(!refcount, "Device has %u references left.\n", refcount);
4359 IDirect3D3_Release(d3d);
4360 DestroyWindow(window);
4363 static void test_specular_lighting(void)
4365 static const unsigned int vertices_side = 5;
4366 const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
4367 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
4368 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
4369 static D3DMATRIX mat =
4371 1.0f, 0.0f, 0.0f, 0.0f,
4372 0.0f, 1.0f, 0.0f, 0.0f,
4373 0.0f, 0.0f, 1.0f, 0.0f,
4374 0.0f, 0.0f, 0.0f, 1.0f,
4376 static const struct vertex
4378 struct vec3 position;
4379 struct vec3 normal;
4381 vertices[] =
4383 {{-0.5f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4384 {{ 0.0f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4385 {{ 0.5f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4386 {{-0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4387 {{ 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4388 {{ 0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4389 {{-0.5f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4390 {{ 0.0f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4391 {{ 0.5f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4394 static D3DLIGHT2 directional =
4396 sizeof(D3DLIGHT2),
4397 D3DLIGHT_DIRECTIONAL,
4398 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4399 {{0.0f}, {0.0f}, {0.0f}},
4400 {{0.0f}, {0.0f}, {1.0f}},
4402 point =
4404 sizeof(D3DLIGHT2),
4405 D3DLIGHT_POINT,
4406 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4407 {{0.0f}, {0.0f}, {0.0f}},
4408 {{0.0f}, {0.0f}, {0.0f}},
4409 100.0f,
4410 0.0f,
4411 0.0f, 0.0f, 1.0f,
4413 spot =
4415 sizeof(D3DLIGHT2),
4416 D3DLIGHT_SPOT,
4417 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4418 {{0.0f}, {0.0f}, {0.0f}},
4419 {{0.0f}, {0.0f}, {1.0f}},
4420 100.0f,
4421 1.0f,
4422 0.0f, 0.0f, 1.0f,
4423 M_PI / 12.0f, M_PI / 3.0f
4425 parallelpoint =
4427 sizeof(D3DLIGHT2),
4428 D3DLIGHT_PARALLELPOINT,
4429 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4430 {{0.5f}, {0.0f}, {-1.0f}},
4431 {{0.0f}, {0.0f}, {0.0f}},
4433 point_side =
4435 sizeof(D3DLIGHT2),
4436 D3DLIGHT_POINT,
4437 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4438 {{-1.1f}, {0.0f}, {1.1f}},
4439 {{0.0f}, {0.0f}, {0.0f}},
4440 100.0f,
4441 0.0f,
4442 1.0f, 0.0f, 0.0f,
4444 point_far =
4446 sizeof(D3DLIGHT2),
4447 D3DLIGHT_POINT,
4448 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4449 {{0.0f}, {0.0f}, {0.1f}},
4450 {{0.0f}, {0.0f}, {0.0f}},
4451 1.0f,
4452 0.0f,
4453 1.0f, 0.0f, 0.0f,
4455 static const struct expected_color
4457 unsigned int x, y;
4458 D3DCOLOR color;
4460 expected_directional[] =
4462 {160, 120, 0x003c3c3c},
4463 {320, 120, 0x00717171},
4464 {480, 120, 0x003c3c3c},
4465 {160, 240, 0x00717171},
4466 {320, 240, 0x00ffffff},
4467 {480, 240, 0x00717171},
4468 {160, 360, 0x003c3c3c},
4469 {320, 360, 0x00717171},
4470 {480, 360, 0x003c3c3c},
4472 expected_point[] =
4474 {160, 120, 0x00000000},
4475 {320, 120, 0x00090909},
4476 {480, 120, 0x00000000},
4477 {160, 240, 0x00090909},
4478 {320, 240, 0x00fafafa},
4479 {480, 240, 0x00090909},
4480 {160, 360, 0x00000000},
4481 {320, 360, 0x00090909},
4482 {480, 360, 0x00000000},
4484 expected_spot[] =
4486 {160, 120, 0x00000000},
4487 {320, 120, 0x00020202},
4488 {480, 120, 0x00000000},
4489 {160, 240, 0x00020202},
4490 {320, 240, 0x00fafafa},
4491 {480, 240, 0x00020202},
4492 {160, 360, 0x00000000},
4493 {320, 360, 0x00020202},
4494 {480, 360, 0x00000000},
4496 expected_parallelpoint[] =
4498 {160, 120, 0x00050505},
4499 {320, 120, 0x002c2c2c},
4500 {480, 120, 0x006e6e6e},
4501 {160, 240, 0x00090909},
4502 {320, 240, 0x00717171},
4503 {480, 240, 0x00ffffff},
4504 {160, 360, 0x00050505},
4505 {320, 360, 0x002c2c2c},
4506 {480, 360, 0x006e6e6e},
4508 expected_point_far[] =
4510 {160, 120, 0x00000000},
4511 {320, 120, 0x00000000},
4512 {480, 120, 0x00000000},
4513 {160, 240, 0x00000000},
4514 {320, 240, 0x00ffffff},
4515 {480, 240, 0x00000000},
4516 {160, 360, 0x00000000},
4517 {320, 360, 0x00000000},
4518 {480, 360, 0x00000000},
4520 expected_zero[] =
4522 {160, 120, 0x00000000},
4523 {320, 120, 0x00000000},
4524 {480, 120, 0x00000000},
4525 {160, 240, 0x00000000},
4526 {320, 240, 0x00000000},
4527 {480, 240, 0x00000000},
4528 {160, 360, 0x00000000},
4529 {320, 360, 0x00000000},
4530 {480, 360, 0x00000000},
4532 static const struct
4534 D3DLIGHT2 *light;
4535 BOOL local_viewer;
4536 float specular_power;
4537 const struct expected_color *expected;
4538 unsigned int expected_count;
4540 tests[] =
4542 /* D3DRENDERSTATE_LOCALVIEWER does not exist in D3D < 7 (the behavior is
4543 * the one you get on newer D3D versions with it set as TRUE). */
4544 {&directional, FALSE, 30.0f, expected_directional, ARRAY_SIZE(expected_directional)},
4545 {&directional, TRUE, 30.0f, expected_directional, ARRAY_SIZE(expected_directional)},
4546 {&point, TRUE, 30.0f, expected_point, ARRAY_SIZE(expected_point)},
4547 {&spot, TRUE, 30.0f, expected_spot, ARRAY_SIZE(expected_spot)},
4548 {&parallelpoint, TRUE, 30.0f, expected_parallelpoint, ARRAY_SIZE(expected_parallelpoint)},
4549 {&point_side, TRUE, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
4550 {&point_far, TRUE, 1.0f, expected_point_far, ARRAY_SIZE(expected_point_far)},
4551 {&directional, FALSE, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
4552 {&directional, TRUE, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
4553 {&point, TRUE, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
4554 {&spot, TRUE, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
4555 {&parallelpoint, TRUE, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
4556 {&point_far, TRUE, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
4559 IDirect3DLight *light, *dummy_lights[64];
4560 IDirect3DVertexBuffer *src_vb, *dst_vb;
4561 struct vertex *quad, *src_data;
4562 D3DVERTEXBUFFERDESC vb_desc;
4563 D3DMATERIALHANDLE mat_handle;
4564 IDirect3DViewport3 *viewport;
4565 IDirect3DMaterial3 *material;
4566 IDirect3DDevice3 *device;
4567 IDirectDrawSurface4 *rt;
4568 D3DLIGHT2 light_desc;
4569 IDirect3D3 *d3d;
4570 D3DCOLOR color;
4571 ULONG refcount;
4572 HWND window;
4573 HRESULT hr;
4574 unsigned int i, j, x, y;
4575 struct
4577 struct vec4 position;
4578 DWORD diffuse;
4579 DWORD specular;
4580 } *dst_data;
4581 WORD *indices;
4583 window = create_window();
4584 if (!(device = create_device(window, DDSCL_NORMAL)))
4586 skip("Failed to create a 3D device, skipping test.\n");
4587 DestroyWindow(window);
4588 return;
4591 quad = heap_alloc(vertices_side * vertices_side * sizeof(*quad));
4592 indices = heap_alloc(indices_count * sizeof(*indices));
4593 for (i = 0, y = 0; y < vertices_side; ++y)
4595 for (x = 0; x < vertices_side; ++x)
4597 quad[i].position.x = x * 2.0f / (vertices_side - 1) - 1.0f;
4598 quad[i].position.y = y * 2.0f / (vertices_side - 1) - 1.0f;
4599 quad[i].position.z = 1.0f;
4600 quad[i].normal.x = 0.0f;
4601 quad[i].normal.y = 0.0f;
4602 quad[i++].normal.z = -1.0f;
4605 for (i = 0, y = 0; y < (vertices_side - 1); ++y)
4607 for (x = 0; x < (vertices_side - 1); ++x)
4609 indices[i++] = y * vertices_side + x + 1;
4610 indices[i++] = y * vertices_side + x;
4611 indices[i++] = (y + 1) * vertices_side + x;
4612 indices[i++] = y * vertices_side + x + 1;
4613 indices[i++] = (y + 1) * vertices_side + x;
4614 indices[i++] = (y + 1) * vertices_side + x + 1;
4618 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
4619 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4621 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
4622 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4624 viewport = create_viewport(device, 0, 0, 640, 480);
4625 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
4626 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4628 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
4629 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4630 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
4631 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4632 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
4633 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4634 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
4635 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4636 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4637 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4639 memset(&light_desc, 0, sizeof(light_desc));
4640 light_desc.dwSize = sizeof(light_desc);
4641 light_desc.dltType = D3DLIGHT_DIRECTIONAL;
4642 light_desc.dwFlags = D3DLIGHT_ACTIVE;
4643 U3(light_desc.dvDirection).z = 1.0f;
4645 for (i = 0; i < ARRAY_SIZE(dummy_lights); ++i)
4647 hr = IDirect3D3_CreateLight(d3d, &dummy_lights[i], NULL);
4648 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4649 hr = IDirect3DViewport3_AddLight(viewport, dummy_lights[i]);
4650 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4651 hr = IDirect3DLight_SetLight(dummy_lights[i], (D3DLIGHT *)&light_desc);
4652 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4655 hr = IDirect3D3_CreateLight(d3d, &light, NULL);
4656 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4657 hr = IDirect3DViewport3_AddLight(viewport, light);
4658 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4660 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
4661 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4663 memset(&vb_desc, 0, sizeof(vb_desc));
4664 vb_desc.dwSize = sizeof(vb_desc);
4665 vb_desc.dwFVF = fvf;
4666 vb_desc.dwNumVertices = ARRAY_SIZE(vertices);
4667 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &src_vb, 0, NULL);
4668 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4669 hr = IDirect3DVertexBuffer_Lock(src_vb, 0, (void **)&src_data, NULL);
4670 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4671 memcpy(src_data, vertices, sizeof(vertices));
4672 hr = IDirect3DVertexBuffer_Unlock(src_vb);
4673 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4675 memset(&vb_desc, 0, sizeof(vb_desc));
4676 vb_desc.dwSize = sizeof(vb_desc);
4677 vb_desc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
4678 vb_desc.dwNumVertices = ARRAY_SIZE(vertices);
4679 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &dst_vb, 0, NULL);
4680 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4682 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4684 tests[i].light->dwFlags = D3DLIGHT_ACTIVE;
4685 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)tests[i].light);
4686 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4688 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LOCALVIEWER, tests[i].local_viewer);
4689 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4691 material = create_specular_material(device, 1.0f, 1.0f, 1.0f, 0.5f, tests[i].specular_power);
4692 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
4693 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4694 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
4695 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4697 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
4698 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4700 hr = IDirect3DDevice3_BeginScene(device);
4701 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4703 hr = IDirect3DVertexBuffer_Lock(dst_vb, 0, (void **)&dst_data, NULL);
4704 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4705 memset(dst_data, 0, sizeof(*dst_data) * ARRAY_SIZE(vertices));
4706 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
4707 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4709 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 0,
4710 ARRAY_SIZE(vertices), src_vb, 0, device, 0);
4711 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4712 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, quad,
4713 vertices_side * vertices_side, indices, indices_count, 0);
4714 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4716 hr = IDirect3DDevice3_EndScene(device);
4717 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4719 hr = IDirect3DVertexBuffer_Lock(dst_vb, 0, (void **)&dst_data, NULL);
4720 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4722 for (j = 0; j < tests[i].expected_count; ++j)
4724 color = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
4725 ok(compare_color(color, tests[i].expected[j].color, 1),
4726 "Expected color 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
4727 tests[i].expected[j].color, tests[i].expected[j].x,
4728 tests[i].expected[j].y, color, i);
4729 ok(!dst_data[j].diffuse, "Expected color 0x00000000 for vertex %u, got 0x%08x, case %u.\n",
4730 j, dst_data[j].diffuse, i);
4731 ok(compare_color(dst_data[j].specular, tests[i].expected[j].color, 1),
4732 "Expected color 0x%08x for vertex %u, got 0x%08x, case %u.\n",
4733 tests[i].expected[j].color, j, dst_data[j].specular, i);
4735 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
4736 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4738 destroy_material(material);
4741 for (i = 0; i < ARRAY_SIZE(dummy_lights); ++i)
4742 IDirect3DLight_Release(dummy_lights[i]);
4744 IDirect3DVertexBuffer_Release(dst_vb);
4745 IDirect3DVertexBuffer_Release(src_vb);
4747 hr = IDirect3DViewport3_DeleteLight(viewport, light);
4748 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4749 IDirect3DLight_Release(light);
4750 IDirect3DViewport3_Release(viewport);
4751 IDirectDrawSurface4_Release(rt);
4752 refcount = IDirect3DDevice3_Release(device);
4753 ok(!refcount, "Device has %u references left.\n", refcount);
4754 IDirect3D3_Release(d3d);
4755 DestroyWindow(window);
4756 heap_free(indices);
4757 heap_free(quad);
4760 static void test_clear_rect_count(void)
4762 IDirectDrawSurface4 *rt;
4763 IDirect3DDevice3 *device;
4764 D3DCOLOR color;
4765 HWND window;
4766 HRESULT hr;
4767 IDirect3DViewport3 *viewport;
4768 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
4770 window = create_window();
4771 if (!(device = create_device(window, DDSCL_NORMAL)))
4773 skip("Failed to create a 3D device, skipping test.\n");
4774 DestroyWindow(window);
4775 return;
4778 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
4779 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4781 viewport = create_viewport(device, 0, 0, 640, 480);
4782 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
4783 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
4784 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00ffffff, 0.0f, 0);
4785 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
4786 hr = IDirect3DViewport3_Clear2(viewport, 0, &clear_rect, D3DCLEAR_TARGET, 0x00ff0000, 0.0f, 0);
4787 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
4788 hr = IDirect3DViewport3_Clear2(viewport, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 0.0f, 0);
4789 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
4790 hr = IDirect3DViewport3_Clear2(viewport, 1, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
4791 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
4793 color = get_surface_color(rt, 320, 240);
4794 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x000000ff, 1)),
4795 "Got unexpected color 0x%08x.\n", color);
4797 IDirect3DViewport3_Release(viewport);
4798 IDirectDrawSurface4_Release(rt);
4799 IDirect3DDevice3_Release(device);
4800 DestroyWindow(window);
4803 static BOOL test_mode_restored(IDirectDraw4 *ddraw, HWND window)
4805 DDSURFACEDESC2 ddsd1, ddsd2;
4806 HRESULT hr;
4808 memset(&ddsd1, 0, sizeof(ddsd1));
4809 ddsd1.dwSize = sizeof(ddsd1);
4810 hr = IDirectDraw4_GetDisplayMode(ddraw, &ddsd1);
4811 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4813 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4814 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4815 hr = set_display_mode(ddraw, 640, 480);
4816 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
4817 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4818 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4820 memset(&ddsd2, 0, sizeof(ddsd2));
4821 ddsd2.dwSize = sizeof(ddsd2);
4822 hr = IDirectDraw4_GetDisplayMode(ddraw, &ddsd2);
4823 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4824 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
4825 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4827 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
4830 static void test_coop_level_versions(void)
4832 HWND window;
4833 IDirectDraw *ddraw;
4834 HRESULT hr;
4835 BOOL restored;
4836 IDirectDrawSurface *surface;
4837 IDirectDraw4 *ddraw4;
4838 DDSURFACEDESC ddsd;
4840 window = create_window();
4841 ddraw4 = create_ddraw();
4842 ok(!!ddraw4, "Failed to create a ddraw object.\n");
4843 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
4844 restored = test_mode_restored(ddraw4, window);
4845 ok(restored, "Display mode not restored in new ddraw object\n");
4847 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
4848 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
4849 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4851 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4852 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4853 restored = test_mode_restored(ddraw4, window);
4854 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
4856 /* A successful one does */
4857 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4858 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4859 restored = test_mode_restored(ddraw4, window);
4860 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
4862 IDirectDraw_Release(ddraw);
4863 IDirectDraw4_Release(ddraw4);
4865 ddraw4 = create_ddraw();
4866 ok(!!ddraw4, "Failed to create a ddraw object.\n");
4867 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
4868 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4870 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
4871 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4872 restored = test_mode_restored(ddraw4, window);
4873 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
4875 IDirectDraw_Release(ddraw);
4876 IDirectDraw4_Release(ddraw4);
4878 /* A failing call does not restore the ddraw2+ behavior */
4879 ddraw4 = create_ddraw();
4880 ok(!!ddraw4, "Failed to create a ddraw object.\n");
4881 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
4882 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4884 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4885 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4886 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4887 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4888 restored = test_mode_restored(ddraw4, window);
4889 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
4891 IDirectDraw_Release(ddraw);
4892 IDirectDraw4_Release(ddraw4);
4894 /* Neither does a sequence of successful calls with the new interface */
4895 ddraw4 = create_ddraw();
4896 ok(!!ddraw4, "Failed to create a ddraw object.\n");
4897 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
4898 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4900 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4901 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4902 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4903 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4904 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_NORMAL);
4905 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4907 restored = test_mode_restored(ddraw4, window);
4908 ok(!restored, "Display mode restored after ddraw1-ddraw4 SetCooperativeLevel() call sequence\n");
4909 IDirectDraw_Release(ddraw);
4910 IDirectDraw4_Release(ddraw4);
4912 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
4913 ddraw4 = create_ddraw();
4914 ok(!!ddraw4, "Failed to create a ddraw object.\n");
4915 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
4916 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4918 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_NORMAL);
4919 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4921 memset(&ddsd, 0, sizeof(ddsd));
4922 ddsd.dwSize = sizeof(ddsd);
4923 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4924 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4925 ddsd.dwWidth = ddsd.dwHeight = 8;
4926 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4927 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
4928 IDirectDrawSurface_Release(surface);
4929 restored = test_mode_restored(ddraw4, window);
4930 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
4932 IDirectDraw_Release(ddraw);
4933 IDirectDraw4_Release(ddraw4);
4934 DestroyWindow(window);
4937 static void test_lighting_interface_versions(void)
4939 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
4940 IDirect3DMaterial3 *emissive;
4941 IDirect3DViewport3 *viewport;
4942 IDirect3DDevice3 *device;
4943 IDirectDrawSurface4 *rt;
4944 D3DCOLOR color;
4945 HWND window;
4946 HRESULT hr;
4947 D3DMATERIALHANDLE mat_handle;
4948 DWORD rs;
4949 unsigned int i;
4950 ULONG ref;
4951 static D3DVERTEX quad[] =
4953 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4954 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4955 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4956 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4959 #define FVF_COLORVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_SPECULAR)
4960 static struct
4962 struct vec3 position;
4963 struct vec3 normal;
4964 DWORD diffuse, specular;
4966 quad2[] =
4968 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4969 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4970 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4971 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4974 static D3DLVERTEX lquad[] =
4976 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4977 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4978 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4979 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4982 #define FVF_LVERTEX2 (D3DFVF_LVERTEX & ~D3DFVF_RESERVED1)
4983 static struct
4985 struct vec3 position;
4986 DWORD diffuse, specular;
4987 struct vec2 texcoord;
4989 lquad2[] =
4991 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4992 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4993 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4994 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4997 static D3DTLVERTEX tlquad[] =
4999 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
5000 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
5001 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
5002 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
5005 static const struct
5007 DWORD vertextype;
5008 void *data;
5009 DWORD d3drs_lighting, d3drs_specular;
5010 DWORD draw_flags;
5011 D3DCOLOR color;
5013 tests[] =
5015 /* Lighting is enabled when all of these conditions are met:
5016 * 1) No pretransformed position(D3DFVF_XYZRHW)
5017 * 2) Normals are available (D3DFVF_NORMAL)
5018 * 3) D3DDP_DONOTLIGHT is not set.
5020 * D3DRENDERSTATE_LIGHTING is ignored, it is not defined
5021 * in this d3d version */
5023 /* 0 */
5024 { D3DFVF_VERTEX, quad, FALSE, FALSE, 0, 0x0000ff00},
5025 { D3DFVF_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
5026 { D3DFVF_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
5027 { D3DFVF_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
5028 { D3DFVF_VERTEX, quad, FALSE, TRUE, 0, 0x0000ff00},
5029 { D3DFVF_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
5030 { D3DFVF_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
5031 { D3DFVF_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
5033 /* 8 */
5034 { FVF_COLORVERTEX, quad2, FALSE, FALSE, 0, 0x0000ff00},
5035 { FVF_COLORVERTEX, quad2, TRUE, FALSE, 0, 0x0000ff00},
5036 { FVF_COLORVERTEX, quad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
5037 { FVF_COLORVERTEX, quad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
5038 /* The specular color in the vertex is ignored because
5039 * D3DRENDERSTATE_COLORVERTEX is not enabled */
5040 { FVF_COLORVERTEX, quad2, FALSE, TRUE, 0, 0x0000ff00},
5041 { FVF_COLORVERTEX, quad2, TRUE, TRUE, 0, 0x0000ff00},
5042 { FVF_COLORVERTEX, quad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
5043 { FVF_COLORVERTEX, quad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
5045 /* 16 */
5046 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
5047 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, 0, 0x00ff0000},
5048 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
5049 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
5050 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
5051 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, 0, 0x00ff8080},
5052 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
5053 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
5055 /* 24 */
5056 { FVF_LVERTEX2, lquad2, FALSE, FALSE, 0, 0x00ff0000},
5057 { FVF_LVERTEX2, lquad2, TRUE, FALSE, 0, 0x00ff0000},
5058 { FVF_LVERTEX2, lquad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
5059 { FVF_LVERTEX2, lquad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
5060 { FVF_LVERTEX2, lquad2, FALSE, TRUE, 0, 0x00ff8080},
5061 { FVF_LVERTEX2, lquad2, TRUE, TRUE, 0, 0x00ff8080},
5062 { FVF_LVERTEX2, lquad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
5063 { FVF_LVERTEX2, lquad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
5065 /* 32 */
5066 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
5067 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
5068 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
5069 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
5070 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
5071 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
5072 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
5073 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
5076 window = create_window();
5077 if (!(device = create_device(window, DDSCL_NORMAL)))
5079 skip("Failed to create a 3D device, skipping test.\n");
5080 DestroyWindow(window);
5081 return;
5084 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
5085 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
5087 viewport = create_viewport(device, 0, 0, 640, 480);
5088 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
5089 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
5091 emissive = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
5092 hr = IDirect3DMaterial3_GetHandle(emissive, device, &mat_handle);
5093 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
5094 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
5095 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
5096 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
5097 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr);
5099 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
5100 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#x.\n", hr);
5101 ok(rs == FALSE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#x, expected FALSE.\n", rs);
5103 for (i = 0; i < ARRAY_SIZE(tests); i++)
5105 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff202020, 0.0f, 0);
5106 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
5108 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
5109 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#x.\n", hr);
5110 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
5111 tests[i].d3drs_specular);
5112 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#x.\n", hr);
5114 hr = IDirect3DDevice3_BeginScene(device);
5115 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5116 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
5117 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
5118 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5119 hr = IDirect3DDevice3_EndScene(device);
5120 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5122 color = get_surface_color(rt, 320, 240);
5123 ok(compare_color(color, tests[i].color, 1),
5124 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
5125 color, tests[i].color, i);
5128 destroy_material(emissive);
5129 destroy_viewport(device, viewport);
5130 IDirectDrawSurface4_Release(rt);
5131 ref = IDirect3DDevice3_Release(device);
5132 ok(ref == 0, "Device not properly released, refcount %u.\n", ref);
5133 DestroyWindow(window);
5136 static struct
5138 BOOL received;
5139 IDirectDraw4 *ddraw;
5140 HWND window;
5141 DWORD coop_level;
5142 } activateapp_testdata;
5144 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
5146 if (message == WM_ACTIVATEAPP)
5148 if (activateapp_testdata.ddraw)
5150 HRESULT hr;
5151 activateapp_testdata.received = FALSE;
5152 hr = IDirectDraw4_SetCooperativeLevel(activateapp_testdata.ddraw,
5153 activateapp_testdata.window, activateapp_testdata.coop_level);
5154 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
5155 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
5157 activateapp_testdata.received = TRUE;
5160 return DefWindowProcA(hwnd, message, wparam, lparam);
5163 static void test_coop_level_activateapp(void)
5165 IDirectDraw4 *ddraw;
5166 HRESULT hr;
5167 HWND window;
5168 WNDCLASSA wc = {0};
5169 DDSURFACEDESC2 ddsd;
5170 IDirectDrawSurface4 *surface;
5172 ddraw = create_ddraw();
5173 ok(!!ddraw, "Failed to create a ddraw object.\n");
5175 wc.lpfnWndProc = activateapp_test_proc;
5176 wc.lpszClassName = "ddraw_test_wndproc_wc";
5177 ok(RegisterClassA(&wc), "Failed to register window class.\n");
5179 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
5180 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
5182 /* Exclusive with window already active. */
5183 SetForegroundWindow(window);
5184 activateapp_testdata.received = FALSE;
5185 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5186 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5187 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
5188 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5189 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5191 /* Exclusive with window not active. */
5192 SetForegroundWindow(GetDesktopWindow());
5193 activateapp_testdata.received = FALSE;
5194 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5195 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5196 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5197 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5198 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5200 /* Normal with window not active, then exclusive with the same window. */
5201 SetForegroundWindow(GetDesktopWindow());
5202 activateapp_testdata.received = FALSE;
5203 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5204 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5205 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
5206 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5207 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5208 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5209 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5210 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5212 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
5213 SetForegroundWindow(GetDesktopWindow());
5214 activateapp_testdata.received = FALSE;
5215 activateapp_testdata.ddraw = ddraw;
5216 activateapp_testdata.window = window;
5217 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
5218 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5219 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5220 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5221 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5222 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5224 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
5225 * succeeding. Another switch to exclusive and back to normal is needed to release the
5226 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
5227 * WM_ACTIVATEAPP messages. */
5228 activateapp_testdata.ddraw = NULL;
5229 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5230 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5231 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5232 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5234 /* Setting DDSCL_NORMAL with recursive invocation. */
5235 SetForegroundWindow(GetDesktopWindow());
5236 activateapp_testdata.received = FALSE;
5237 activateapp_testdata.ddraw = ddraw;
5238 activateapp_testdata.window = window;
5239 activateapp_testdata.coop_level = DDSCL_NORMAL;
5240 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5241 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5242 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5244 /* DDraw is in exclusive mode now. */
5245 memset(&ddsd, 0, sizeof(ddsd));
5246 ddsd.dwSize = sizeof(ddsd);
5247 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
5248 U5(ddsd).dwBackBufferCount = 1;
5249 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
5250 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5251 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5252 IDirectDrawSurface4_Release(surface);
5254 /* Recover again, just to be sure. */
5255 activateapp_testdata.ddraw = NULL;
5256 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5257 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5258 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5259 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5261 DestroyWindow(window);
5262 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
5263 IDirectDraw4_Release(ddraw);
5266 static void test_texturemanage(void)
5268 IDirectDraw4 *ddraw;
5269 HRESULT hr;
5270 DDSURFACEDESC2 ddsd;
5271 IDirectDrawSurface4 *surface;
5272 unsigned int i;
5273 DDCAPS hal_caps, hel_caps;
5274 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
5275 static const struct
5277 DWORD caps_in, caps2_in;
5278 HRESULT hr;
5279 DWORD caps_out, caps2_out;
5281 tests[] =
5283 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5284 ~0U, ~0U},
5285 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5286 ~0U, ~0U},
5287 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5288 ~0U, ~0U},
5289 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5290 ~0U, ~0U},
5291 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DD_OK,
5292 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE},
5293 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DD_OK,
5294 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE},
5295 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
5296 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_LOCALVIDMEM, 0},
5297 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
5298 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0},
5300 {0, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5301 ~0U, ~0U},
5302 {0, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5303 ~0U, ~0U},
5304 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5305 ~0U, ~0U},
5306 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5307 ~0U, ~0U},
5308 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5309 ~0U, ~0U},
5310 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5311 ~0U, ~0U},
5312 {DDSCAPS_VIDEOMEMORY, 0, DD_OK,
5313 DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY, 0},
5314 {DDSCAPS_SYSTEMMEMORY, 0, DD_OK,
5315 DDSCAPS_SYSTEMMEMORY, 0},
5318 ddraw = create_ddraw();
5319 ok(!!ddraw, "Failed to create a ddraw object.\n");
5320 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5321 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5323 memset(&hal_caps, 0, sizeof(hal_caps));
5324 hal_caps.dwSize = sizeof(hal_caps);
5325 memset(&hel_caps, 0, sizeof(hel_caps));
5326 hel_caps.dwSize = sizeof(hel_caps);
5327 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, &hel_caps);
5328 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5329 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
5331 skip("Managed textures not supported, skipping managed texture test.\n");
5332 IDirectDraw4_Release(ddraw);
5333 return;
5336 for (i = 0; i < ARRAY_SIZE(tests); i++)
5338 memset(&ddsd, 0, sizeof(ddsd));
5339 ddsd.dwSize = sizeof(ddsd);
5340 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5341 ddsd.ddsCaps.dwCaps = tests[i].caps_in;
5342 ddsd.ddsCaps.dwCaps2 = tests[i].caps2_in;
5343 ddsd.dwWidth = 4;
5344 ddsd.dwHeight = 4;
5346 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5347 ok(hr == tests[i].hr, "Got unexpected, hr %#x, case %u.\n", hr, i);
5348 if (FAILED(hr))
5349 continue;
5351 memset(&ddsd, 0, sizeof(ddsd));
5352 ddsd.dwSize = sizeof(ddsd);
5353 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5354 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5356 ok(ddsd.ddsCaps.dwCaps == tests[i].caps_out,
5357 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
5358 tests[i].caps_in, tests[i].caps2_in, tests[i].caps_out, ddsd.ddsCaps.dwCaps, i);
5359 ok(ddsd.ddsCaps.dwCaps2 == tests[i].caps2_out,
5360 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
5361 tests[i].caps_in, tests[i].caps2_in, tests[i].caps2_out, ddsd.ddsCaps.dwCaps2, i);
5363 IDirectDrawSurface4_Release(surface);
5366 IDirectDraw4_Release(ddraw);
5369 #define SUPPORT_DXT1 0x01
5370 #define SUPPORT_DXT2 0x02
5371 #define SUPPORT_DXT3 0x04
5372 #define SUPPORT_DXT4 0x08
5373 #define SUPPORT_DXT5 0x10
5374 #define SUPPORT_YUY2 0x20
5375 #define SUPPORT_UYVY 0x40
5377 static HRESULT WINAPI test_block_formats_creation_cb(DDPIXELFORMAT *fmt, void *ctx)
5379 DWORD *supported_fmts = ctx;
5381 if (!(fmt->dwFlags & DDPF_FOURCC))
5382 return DDENUMRET_OK;
5384 switch (fmt->dwFourCC)
5386 case MAKEFOURCC('D','X','T','1'):
5387 *supported_fmts |= SUPPORT_DXT1;
5388 break;
5389 case MAKEFOURCC('D','X','T','2'):
5390 *supported_fmts |= SUPPORT_DXT2;
5391 break;
5392 case MAKEFOURCC('D','X','T','3'):
5393 *supported_fmts |= SUPPORT_DXT3;
5394 break;
5395 case MAKEFOURCC('D','X','T','4'):
5396 *supported_fmts |= SUPPORT_DXT4;
5397 break;
5398 case MAKEFOURCC('D','X','T','5'):
5399 *supported_fmts |= SUPPORT_DXT5;
5400 break;
5401 case MAKEFOURCC('Y','U','Y','2'):
5402 *supported_fmts |= SUPPORT_YUY2;
5403 break;
5404 case MAKEFOURCC('U','Y','V','Y'):
5405 *supported_fmts |= SUPPORT_UYVY;
5406 break;
5407 default:
5408 break;
5411 return DDENUMRET_OK;
5414 static void test_block_formats_creation(void)
5416 HRESULT hr, expect_hr;
5417 unsigned int i, j, w, h;
5418 HWND window;
5419 IDirectDraw4 *ddraw;
5420 IDirect3D3 *d3d;
5421 IDirect3DDevice3 *device;
5422 IDirectDrawSurface4 *surface;
5423 DWORD supported_fmts = 0, supported_overlay_fmts = 0;
5424 DWORD num_fourcc_codes = 0, *fourcc_codes;
5425 DDSURFACEDESC2 ddsd;
5426 DDCAPS hal_caps;
5427 void *mem;
5429 static const struct
5431 DWORD fourcc;
5432 const char *name;
5433 DWORD support_flag;
5434 unsigned int block_width;
5435 unsigned int block_height;
5436 unsigned int block_size;
5437 BOOL create_size_checked, overlay;
5439 formats[] =
5441 {MAKEFOURCC('D','X','T','1'), "D3DFMT_DXT1", SUPPORT_DXT1, 4, 4, 8, TRUE, FALSE},
5442 {MAKEFOURCC('D','X','T','2'), "D3DFMT_DXT2", SUPPORT_DXT2, 4, 4, 16, TRUE, FALSE},
5443 {MAKEFOURCC('D','X','T','3'), "D3DFMT_DXT3", SUPPORT_DXT3, 4, 4, 16, TRUE, FALSE},
5444 {MAKEFOURCC('D','X','T','4'), "D3DFMT_DXT4", SUPPORT_DXT4, 4, 4, 16, TRUE, FALSE},
5445 {MAKEFOURCC('D','X','T','5'), "D3DFMT_DXT5", SUPPORT_DXT5, 4, 4, 16, TRUE, FALSE},
5446 {MAKEFOURCC('Y','U','Y','2'), "D3DFMT_YUY2", SUPPORT_YUY2, 2, 1, 4, FALSE, TRUE },
5447 {MAKEFOURCC('U','Y','V','Y'), "D3DFMT_UYVY", SUPPORT_UYVY, 2, 1, 4, FALSE, TRUE },
5449 static const struct
5451 DWORD caps, caps2;
5452 const char *name;
5453 BOOL overlay;
5455 types[] =
5457 /* DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY fails to create any fourcc
5458 * surface with DDERR_INVALIDPIXELFORMAT. Don't care about it for now.
5460 * Nvidia returns E_FAIL on DXTN DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY.
5461 * Other hw / drivers successfully create those surfaces. Ignore them, this
5462 * suggests that no game uses this, otherwise Nvidia would support it. */
5464 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0,
5465 "videomemory texture", FALSE
5468 DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY, 0,
5469 "videomemory overlay", TRUE
5472 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0,
5473 "systemmemory texture", FALSE
5476 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
5477 "managed texture", FALSE
5480 enum size_type
5482 SIZE_TYPE_ZERO,
5483 SIZE_TYPE_PITCH,
5484 SIZE_TYPE_SIZE,
5486 static const struct
5488 DWORD flags;
5489 enum size_type size_type;
5490 int rel_size;
5491 HRESULT hr;
5493 user_mem_tests[] =
5495 {DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DD_OK},
5496 {DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
5497 {DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
5498 {DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
5499 {DDSD_LPSURFACE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
5500 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
5501 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
5502 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
5503 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 1, DD_OK},
5504 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, -1, DDERR_INVALIDPARAMS},
5505 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
5506 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
5507 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_SIZE, 0, DD_OK},
5508 {DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
5511 window = create_window();
5512 if (!(device = create_device(window, DDSCL_NORMAL)))
5514 skip("Failed to create a 3D device, skipping test.\n");
5515 DestroyWindow(window);
5516 return;
5519 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
5520 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5521 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **) &ddraw);
5522 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5523 IDirect3D3_Release(d3d);
5525 hr = IDirect3DDevice3_EnumTextureFormats(device, test_block_formats_creation_cb,
5526 &supported_fmts);
5527 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
5529 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
5530 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
5531 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5532 num_fourcc_codes * sizeof(*fourcc_codes));
5533 if (!fourcc_codes)
5534 goto cleanup;
5535 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
5536 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
5537 for (i = 0; i < num_fourcc_codes; i++)
5539 for (j = 0; j < ARRAY_SIZE(formats); j++)
5541 if (fourcc_codes[i] == formats[j].fourcc)
5542 supported_overlay_fmts |= formats[j].support_flag;
5545 HeapFree(GetProcessHeap(), 0, fourcc_codes);
5547 memset(&hal_caps, 0, sizeof(hal_caps));
5548 hal_caps.dwSize = sizeof(hal_caps);
5549 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
5550 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5552 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * 2 * 16 + 1);
5554 for (i = 0; i < ARRAY_SIZE(formats); i++)
5556 for (j = 0; j < ARRAY_SIZE(types); j++)
5558 BOOL support;
5560 if (formats[i].overlay != types[j].overlay
5561 || (types[j].overlay && !(hal_caps.dwCaps & DDCAPS_OVERLAY)))
5562 continue;
5564 if (formats[i].overlay)
5565 support = supported_overlay_fmts & formats[i].support_flag;
5566 else
5567 support = supported_fmts & formats[i].support_flag;
5569 for (w = 1; w <= 8; w++)
5571 for (h = 1; h <= 8; h++)
5573 BOOL block_aligned = TRUE;
5574 BOOL todo = FALSE;
5576 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
5577 block_aligned = FALSE;
5579 memset(&ddsd, 0, sizeof(ddsd));
5580 ddsd.dwSize = sizeof(ddsd);
5581 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5582 ddsd.ddsCaps.dwCaps = types[j].caps;
5583 ddsd.ddsCaps.dwCaps2 = types[j].caps2;
5584 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5585 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
5586 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
5587 ddsd.dwWidth = w;
5588 ddsd.dwHeight = h;
5590 /* TODO: Handle power of two limitations. I cannot test the pow2
5591 * behavior on windows because I have no hardware that doesn't at
5592 * least support np2_conditional. There's probably no HW that
5593 * supports DXTN textures but no conditional np2 textures. */
5594 if (!support && !(types[j].caps & DDSCAPS_SYSTEMMEMORY))
5595 expect_hr = DDERR_INVALIDPARAMS;
5596 else if (formats[i].create_size_checked && !block_aligned)
5598 expect_hr = DDERR_INVALIDPARAMS;
5599 if (!(types[j].caps & DDSCAPS_TEXTURE))
5600 todo = TRUE;
5602 else
5603 expect_hr = D3D_OK;
5605 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5606 todo_wine_if (todo)
5607 ok(hr == expect_hr,
5608 "Got unexpected hr %#x for format %s, resource type %s, size %ux%u, expected %#x.\n",
5609 hr, formats[i].name, types[j].name, w, h, expect_hr);
5611 if (SUCCEEDED(hr))
5612 IDirectDrawSurface4_Release(surface);
5617 if (formats[i].overlay)
5618 continue;
5620 for (j = 0; j < ARRAY_SIZE(user_mem_tests); ++j)
5622 memset(&ddsd, 0, sizeof(ddsd));
5623 ddsd.dwSize = sizeof(ddsd);
5624 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | user_mem_tests[j].flags;
5625 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE;
5627 switch (user_mem_tests[j].size_type)
5629 case SIZE_TYPE_ZERO:
5630 U1(ddsd).dwLinearSize = 0;
5631 break;
5633 case SIZE_TYPE_PITCH:
5634 U1(ddsd).dwLinearSize = 2 * formats[i].block_size;
5635 break;
5637 case SIZE_TYPE_SIZE:
5638 U1(ddsd).dwLinearSize = 2 * 2 * formats[i].block_size;
5639 break;
5641 U1(ddsd).dwLinearSize += user_mem_tests[j].rel_size;
5643 ddsd.lpSurface = mem;
5644 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5645 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
5646 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
5647 ddsd.dwWidth = 8;
5648 ddsd.dwHeight = 8;
5650 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5651 ok(hr == user_mem_tests[j].hr, "Test %u: Got unexpected hr %#x, format %s.\n", j, hr, formats[i].name);
5653 if (FAILED(hr))
5654 continue;
5656 memset(&ddsd, 0, sizeof(ddsd));
5657 ddsd.dwSize = sizeof(ddsd);
5658 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5659 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", j, hr);
5660 ok(ddsd.dwFlags == (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_LINEARSIZE),
5661 "Test %u: Got unexpected flags %#x.\n", j, ddsd.dwFlags);
5662 if (user_mem_tests[j].flags & DDSD_LPSURFACE)
5663 ok(U1(ddsd).dwLinearSize == ~0u, "Test %u: Got unexpected linear size %#x.\n",
5664 j, U1(ddsd).dwLinearSize);
5665 else
5666 ok(U1(ddsd).dwLinearSize == 2 * 2 * formats[i].block_size,
5667 "Test %u: Got unexpected linear size %#x, expected %#x.\n",
5668 j, U1(ddsd).dwLinearSize, 2 * 2 * formats[i].block_size);
5669 IDirectDrawSurface4_Release(surface);
5673 HeapFree(GetProcessHeap(), 0, mem);
5674 cleanup:
5675 IDirectDraw4_Release(ddraw);
5676 IDirect3DDevice3_Release(device);
5677 DestroyWindow(window);
5680 struct format_support_check
5682 const DDPIXELFORMAT *format;
5683 BOOL supported;
5686 static HRESULT WINAPI test_unsupported_formats_cb(DDPIXELFORMAT *fmt, void *ctx)
5688 struct format_support_check *format = ctx;
5690 if (!memcmp(format->format, fmt, sizeof(*fmt)))
5692 format->supported = TRUE;
5693 return DDENUMRET_CANCEL;
5696 return DDENUMRET_OK;
5699 static void test_unsupported_formats(void)
5701 HRESULT hr;
5702 BOOL expect_success;
5703 HWND window;
5704 IDirectDraw4 *ddraw;
5705 IDirect3D3 *d3d;
5706 IDirect3DDevice3 *device;
5707 IDirectDrawSurface4 *surface;
5708 DDSURFACEDESC2 ddsd;
5709 unsigned int i, j;
5710 DWORD expected_caps;
5711 static const struct
5713 const char *name;
5714 DDPIXELFORMAT fmt;
5716 formats[] =
5719 "D3DFMT_A8R8G8B8",
5721 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
5722 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
5726 "D3DFMT_P8",
5728 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5729 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
5733 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
5735 window = create_window();
5736 if (!(device = create_device(window, DDSCL_NORMAL)))
5738 skip("Failed to create a 3D device, skipping test.\n");
5739 DestroyWindow(window);
5740 return;
5743 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
5744 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5745 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **) &ddraw);
5746 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5747 IDirect3D3_Release(d3d);
5749 for (i = 0; i < ARRAY_SIZE(formats); i++)
5751 struct format_support_check check = {&formats[i].fmt, FALSE};
5752 hr = IDirect3DDevice3_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
5753 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
5755 for (j = 0; j < ARRAY_SIZE(caps); j++)
5757 memset(&ddsd, 0, sizeof(ddsd));
5758 ddsd.dwSize = sizeof(ddsd);
5759 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5760 U4(ddsd).ddpfPixelFormat = formats[i].fmt;
5761 ddsd.dwWidth = 4;
5762 ddsd.dwHeight = 4;
5763 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
5765 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
5766 expect_success = FALSE;
5767 else
5768 expect_success = TRUE;
5770 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5771 ok(SUCCEEDED(hr) == expect_success,
5772 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
5773 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
5774 if (FAILED(hr))
5775 continue;
5777 memset(&ddsd, 0, sizeof(ddsd));
5778 ddsd.dwSize = sizeof(ddsd);
5779 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5780 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5782 if (caps[j] & DDSCAPS_VIDEOMEMORY)
5783 expected_caps = DDSCAPS_VIDEOMEMORY;
5784 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
5785 expected_caps = DDSCAPS_SYSTEMMEMORY;
5786 else if (check.supported)
5787 expected_caps = DDSCAPS_VIDEOMEMORY;
5788 else
5789 expected_caps = DDSCAPS_SYSTEMMEMORY;
5791 ok(ddsd.ddsCaps.dwCaps & expected_caps,
5792 "Expected capability %#x, format %s, input cap %#x.\n",
5793 expected_caps, formats[i].name, caps[j]);
5795 IDirectDrawSurface4_Release(surface);
5799 IDirectDraw4_Release(ddraw);
5800 IDirect3DDevice3_Release(device);
5801 DestroyWindow(window);
5804 static void test_rt_caps(void)
5806 PALETTEENTRY palette_entries[256];
5807 IDirectDrawPalette *palette;
5808 IDirectDraw4 *ddraw;
5809 DDPIXELFORMAT z_fmt;
5810 IDirect3D3 *d3d;
5811 unsigned int i;
5812 ULONG refcount;
5813 HWND window;
5814 HRESULT hr;
5816 static const DDPIXELFORMAT p8_fmt =
5818 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5819 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
5822 const struct
5824 const DDPIXELFORMAT *pf;
5825 DWORD caps_in;
5826 DWORD caps_out;
5827 HRESULT create_device_hr;
5828 HRESULT set_rt_hr, alternative_set_rt_hr;
5830 test_data[] =
5833 NULL,
5834 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5835 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5836 D3D_OK,
5837 D3D_OK,
5838 D3D_OK,
5841 NULL,
5842 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5843 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5844 D3D_OK,
5845 D3D_OK,
5846 D3D_OK,
5849 NULL,
5850 DDSCAPS_OFFSCREENPLAIN,
5851 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5852 DDERR_INVALIDCAPS,
5853 DDERR_INVALIDCAPS,
5854 DDERR_INVALIDCAPS,
5857 NULL,
5858 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5859 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5860 D3DERR_SURFACENOTINVIDMEM,
5861 D3D_OK,
5862 D3D_OK,
5865 NULL,
5866 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5867 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5868 DDERR_INVALIDCAPS,
5869 DDERR_INVALIDCAPS,
5870 DDERR_INVALIDCAPS,
5873 NULL,
5874 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5875 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5876 D3D_OK,
5877 D3D_OK,
5878 D3D_OK,
5881 NULL,
5882 DDSCAPS_3DDEVICE,
5883 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5884 D3D_OK,
5885 D3D_OK,
5886 D3D_OK,
5889 NULL,
5891 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5892 DDERR_INVALIDCAPS,
5893 DDERR_INVALIDCAPS,
5894 DDERR_INVALIDCAPS,
5897 NULL,
5898 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5899 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5900 D3DERR_SURFACENOTINVIDMEM,
5901 D3D_OK,
5902 D3D_OK,
5905 NULL,
5906 DDSCAPS_SYSTEMMEMORY,
5907 DDSCAPS_SYSTEMMEMORY,
5908 DDERR_INVALIDCAPS,
5909 DDERR_INVALIDCAPS,
5910 DDERR_INVALIDCAPS,
5913 &p8_fmt,
5915 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5916 DDERR_INVALIDCAPS,
5917 DDERR_INVALIDCAPS,
5918 DDERR_INVALIDCAPS,
5921 &p8_fmt,
5922 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5923 ~0U /* AMD r200 */,
5924 DDERR_NOPALETTEATTACHED,
5925 DDERR_INVALIDCAPS,
5926 DDERR_INVALIDCAPS,
5929 &p8_fmt,
5930 DDSCAPS_OFFSCREENPLAIN,
5931 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5932 DDERR_INVALIDCAPS,
5933 DDERR_INVALIDCAPS,
5934 DDERR_INVALIDCAPS,
5937 &p8_fmt,
5938 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5939 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5940 DDERR_NOPALETTEATTACHED,
5941 DDERR_INVALIDCAPS,
5942 DDERR_INVALIDCAPS,
5945 &p8_fmt,
5946 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5947 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5948 DDERR_INVALIDCAPS,
5949 DDERR_INVALIDCAPS,
5950 DDERR_INVALIDCAPS,
5953 &z_fmt,
5954 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
5955 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5956 DDERR_INVALIDCAPS,
5957 DDERR_INVALIDPIXELFORMAT,
5958 D3D_OK /* r200 */,
5961 &z_fmt,
5962 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5963 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5964 DDERR_INVALIDCAPS,
5965 DDERR_INVALIDPIXELFORMAT,
5966 D3D_OK /* r200 */,
5969 &z_fmt,
5970 DDSCAPS_ZBUFFER,
5971 DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5972 DDERR_INVALIDCAPS,
5973 DDERR_INVALIDCAPS,
5974 DDERR_INVALIDCAPS,
5977 &z_fmt,
5978 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5979 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5980 DDERR_INVALIDCAPS,
5981 DDERR_INVALIDPIXELFORMAT,
5982 D3D_OK /* r200 */,
5985 &z_fmt,
5986 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5987 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5988 DDERR_INVALIDCAPS,
5989 DDERR_INVALIDCAPS,
5990 DDERR_INVALIDCAPS,
5994 window = create_window();
5995 ddraw = create_ddraw();
5996 ok(!!ddraw, "Failed to create a ddraw object.\n");
5997 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5998 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6000 if (FAILED(IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
6002 skip("D3D interface is not available, skipping test.\n");
6003 goto done;
6006 memset(&z_fmt, 0, sizeof(z_fmt));
6007 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
6008 if (FAILED(hr) || !z_fmt.dwSize)
6010 skip("No depth buffer formats available, skipping test.\n");
6011 IDirect3D3_Release(d3d);
6012 goto done;
6015 memset(palette_entries, 0, sizeof(palette_entries));
6016 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
6017 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6019 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6021 IDirectDrawSurface4 *surface, *rt, *expected_rt, *tmp;
6022 DDSURFACEDESC2 surface_desc;
6023 IDirect3DDevice3 *device;
6025 memset(&surface_desc, 0, sizeof(surface_desc));
6026 surface_desc.dwSize = sizeof(surface_desc);
6027 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6028 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
6029 if (test_data[i].pf)
6031 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
6032 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
6034 surface_desc.dwWidth = 640;
6035 surface_desc.dwHeight = 480;
6036 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6037 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
6038 i, test_data[i].caps_in, hr);
6040 memset(&surface_desc, 0, sizeof(surface_desc));
6041 surface_desc.dwSize = sizeof(surface_desc);
6042 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
6043 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
6044 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
6045 "Test %u: Got unexpected caps %#x, expected %#x.\n",
6046 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
6048 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
6049 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
6050 i, hr, test_data[i].create_device_hr);
6051 if (FAILED(hr))
6053 if (hr == DDERR_NOPALETTEATTACHED)
6055 hr = IDirectDrawSurface4_SetPalette(surface, palette);
6056 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
6057 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
6058 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
6059 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
6060 else
6061 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
6063 IDirectDrawSurface4_Release(surface);
6065 memset(&surface_desc, 0, sizeof(surface_desc));
6066 surface_desc.dwSize = sizeof(surface_desc);
6067 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6068 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
6069 surface_desc.dwWidth = 640;
6070 surface_desc.dwHeight = 480;
6071 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6072 ok(SUCCEEDED(hr), "Test %u: Failed to create surface, hr %#x.\n", i, hr);
6074 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
6075 ok(SUCCEEDED(hr), "Test %u: Failed to create device, hr %#x.\n", i, hr);
6078 memset(&surface_desc, 0, sizeof(surface_desc));
6079 surface_desc.dwSize = sizeof(surface_desc);
6080 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6081 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
6082 if (test_data[i].pf)
6084 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
6085 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
6087 surface_desc.dwWidth = 640;
6088 surface_desc.dwHeight = 480;
6089 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &rt, NULL);
6090 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
6091 i, test_data[i].caps_in, hr);
6093 hr = IDirect3DDevice3_SetRenderTarget(device, rt, 0);
6094 ok(hr == test_data[i].set_rt_hr || broken(hr == test_data[i].alternative_set_rt_hr),
6095 "Test %u: Got unexpected hr %#x, expected %#x.\n",
6096 i, hr, test_data[i].set_rt_hr);
6097 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
6098 expected_rt = rt;
6099 else
6100 expected_rt = surface;
6102 hr = IDirect3DDevice3_GetRenderTarget(device, &tmp);
6103 ok(SUCCEEDED(hr), "Test %u: Failed to get render target, hr %#x.\n", i, hr);
6104 ok(tmp == expected_rt, "Test %u: Got unexpected rt %p.\n", i, tmp);
6106 IDirectDrawSurface4_Release(tmp);
6107 IDirectDrawSurface4_Release(rt);
6108 refcount = IDirect3DDevice3_Release(device);
6109 ok(refcount == 0, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
6110 refcount = IDirectDrawSurface4_Release(surface);
6111 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
6114 IDirectDrawPalette_Release(palette);
6115 IDirect3D3_Release(d3d);
6117 done:
6118 refcount = IDirectDraw4_Release(ddraw);
6119 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6120 DestroyWindow(window);
6123 static void test_primary_caps(void)
6125 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
6126 IDirectDrawSurface4 *surface;
6127 DDSURFACEDESC2 surface_desc;
6128 IDirectDraw4 *ddraw;
6129 unsigned int i;
6130 ULONG refcount;
6131 HWND window;
6132 HRESULT hr;
6134 static const struct
6136 DWORD coop_level;
6137 DWORD caps_in;
6138 DWORD back_buffer_count;
6139 HRESULT hr;
6140 DWORD caps_out;
6142 test_data[] =
6145 DDSCL_NORMAL,
6146 DDSCAPS_PRIMARYSURFACE,
6147 ~0u,
6148 DD_OK,
6149 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
6152 DDSCL_NORMAL,
6153 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
6154 ~0u,
6155 DDERR_INVALIDCAPS,
6156 ~0u,
6159 DDSCL_NORMAL,
6160 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
6161 ~0u,
6162 DDERR_INVALIDCAPS,
6163 ~0u,
6166 DDSCL_NORMAL,
6167 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
6168 ~0u,
6169 DDERR_INVALIDCAPS,
6170 ~0u,
6173 DDSCL_NORMAL,
6174 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
6175 ~0u,
6176 DDERR_INVALIDCAPS,
6177 ~0u,
6180 DDSCL_NORMAL,
6181 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
6182 ~0u,
6183 DDERR_INVALIDCAPS,
6184 ~0u,
6187 DDSCL_NORMAL,
6188 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6189 ~0u,
6190 DDERR_INVALIDCAPS,
6191 ~0u,
6194 DDSCL_NORMAL,
6195 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6197 DDERR_INVALIDCAPS,
6198 ~0u,
6201 DDSCL_NORMAL,
6202 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6204 DDERR_NOEXCLUSIVEMODE,
6205 ~0u,
6208 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
6209 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6211 DDERR_INVALIDCAPS,
6212 ~0u,
6215 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
6216 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6218 DD_OK,
6219 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
6222 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
6223 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
6225 DDERR_INVALIDCAPS,
6226 ~0u,
6229 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
6230 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
6232 DDERR_INVALIDCAPS,
6233 ~0u,
6237 window = create_window();
6238 ddraw = create_ddraw();
6239 ok(!!ddraw, "Failed to create a ddraw object.\n");
6241 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6243 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
6244 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6246 memset(&surface_desc, 0, sizeof(surface_desc));
6247 surface_desc.dwSize = sizeof(surface_desc);
6248 surface_desc.dwFlags = DDSD_CAPS;
6249 if (test_data[i].back_buffer_count != ~0u)
6250 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
6251 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
6252 U5(surface_desc).dwBackBufferCount = test_data[i].back_buffer_count;
6253 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6254 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
6255 if (FAILED(hr))
6256 continue;
6258 memset(&surface_desc, 0, sizeof(surface_desc));
6259 surface_desc.dwSize = sizeof(surface_desc);
6260 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
6261 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
6262 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
6263 "Test %u: Got unexpected caps %#x, expected %#x.\n",
6264 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
6266 IDirectDrawSurface4_Release(surface);
6269 refcount = IDirectDraw4_Release(ddraw);
6270 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6271 DestroyWindow(window);
6274 static void test_surface_lock(void)
6276 IDirectDraw4 *ddraw;
6277 IDirect3D3 *d3d = NULL;
6278 IDirectDrawSurface4 *surface;
6279 HRESULT hr;
6280 HWND window;
6281 unsigned int i;
6282 DDSURFACEDESC2 ddsd;
6283 ULONG refcount;
6284 DDPIXELFORMAT z_fmt;
6285 static const struct
6287 DWORD caps;
6288 DWORD caps2;
6289 const char *name;
6291 tests[] =
6294 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
6296 "videomemory offscreenplain"
6299 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
6301 "systemmemory offscreenplain"
6304 DDSCAPS_PRIMARYSURFACE,
6306 "primary"
6309 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
6311 "videomemory texture"
6314 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
6315 DDSCAPS2_OPAQUE,
6316 "opaque videomemory texture"
6319 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
6321 "systemmemory texture"
6324 DDSCAPS_TEXTURE,
6325 DDSCAPS2_TEXTUREMANAGE,
6326 "managed texture"
6329 DDSCAPS_TEXTURE,
6330 DDSCAPS2_D3DTEXTUREMANAGE,
6331 "managed texture"
6334 DDSCAPS_TEXTURE,
6335 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_OPAQUE,
6336 "opaque managed texture"
6339 DDSCAPS_TEXTURE,
6340 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_OPAQUE,
6341 "opaque managed texture"
6344 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
6346 "render target"
6349 DDSCAPS_ZBUFFER,
6351 "Z buffer"
6355 window = create_window();
6356 ddraw = create_ddraw();
6357 ok(!!ddraw, "Failed to create a ddraw object.\n");
6358 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6359 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6361 if (FAILED(IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
6363 skip("D3D interface is not available, skipping test.\n");
6364 goto done;
6367 memset(&z_fmt, 0, sizeof(z_fmt));
6368 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
6369 if (FAILED(hr) || !z_fmt.dwSize)
6371 skip("No depth buffer formats available, skipping test.\n");
6372 goto done;
6375 for (i = 0; i < ARRAY_SIZE(tests); i++)
6377 memset(&ddsd, 0, sizeof(ddsd));
6378 ddsd.dwSize = sizeof(ddsd);
6379 ddsd.dwFlags = DDSD_CAPS;
6380 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
6382 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6383 ddsd.dwWidth = 64;
6384 ddsd.dwHeight = 64;
6386 if (tests[i].caps & DDSCAPS_ZBUFFER)
6388 ddsd.dwFlags |= DDSD_PIXELFORMAT;
6389 U4(ddsd).ddpfPixelFormat = z_fmt;
6391 ddsd.ddsCaps.dwCaps = tests[i].caps;
6392 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
6394 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6395 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
6397 memset(&ddsd, 0, sizeof(ddsd));
6398 ddsd.dwSize = sizeof(ddsd);
6399 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
6400 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
6401 if (SUCCEEDED(hr))
6403 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6404 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
6407 memset(&ddsd, 0, sizeof(ddsd));
6408 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
6409 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, tests[i].name);
6411 IDirectDrawSurface4_Release(surface);
6414 done:
6415 if (d3d)
6416 IDirect3D3_Release(d3d);
6417 refcount = IDirectDraw4_Release(ddraw);
6418 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6419 DestroyWindow(window);
6422 static void test_surface_discard(void)
6424 IDirect3DDevice3 *device;
6425 IDirect3D3 *d3d;
6426 IDirectDraw4 *ddraw;
6427 HRESULT hr;
6428 HWND window;
6429 DDSURFACEDESC2 ddsd;
6430 IDirectDrawSurface4 *surface, *target;
6431 void *addr;
6432 static const struct
6434 DWORD caps, caps2;
6435 BOOL discard;
6437 tests[] =
6439 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, TRUE},
6440 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
6441 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, TRUE},
6442 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
6443 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE},
6444 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
6445 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE},
6446 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
6448 unsigned int i;
6450 window = create_window();
6451 if (!(device = create_device(window, DDSCL_NORMAL)))
6453 skip("Failed to create a 3D device, skipping test.\n");
6454 DestroyWindow(window);
6455 return;
6457 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
6458 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
6459 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
6460 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
6461 hr = IDirect3DDevice3_GetRenderTarget(device, &target);
6462 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
6464 for (i = 0; i < ARRAY_SIZE(tests); i++)
6466 BOOL discarded;
6468 memset(&ddsd, 0, sizeof(ddsd));
6469 ddsd.dwSize = sizeof(ddsd);
6470 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6471 ddsd.ddsCaps.dwCaps = tests[i].caps;
6472 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
6473 ddsd.dwWidth = 64;
6474 ddsd.dwHeight = 64;
6475 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6476 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x, case %u.\n", hr, i);
6478 memset(&ddsd, 0, sizeof(ddsd));
6479 ddsd.dwSize = sizeof(ddsd);
6480 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, 0, NULL);
6481 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6482 addr = ddsd.lpSurface;
6483 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6484 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6486 memset(&ddsd, 0, sizeof(ddsd));
6487 ddsd.dwSize = sizeof(ddsd);
6488 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
6489 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6490 discarded = ddsd.lpSurface != addr;
6491 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6492 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6494 hr = IDirectDrawSurface4_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
6495 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
6497 memset(&ddsd, 0, sizeof(ddsd));
6498 ddsd.dwSize = sizeof(ddsd);
6499 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
6500 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6501 discarded |= ddsd.lpSurface != addr;
6502 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6503 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6505 IDirectDrawSurface4_Release(surface);
6507 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
6508 * AMD r500, evergreen). Windows XP, at least on AMD r200, does not. */
6509 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
6512 IDirectDrawSurface4_Release(target);
6513 IDirectDraw4_Release(ddraw);
6514 IDirect3D3_Release(d3d);
6515 IDirect3DDevice3_Release(device);
6516 DestroyWindow(window);
6519 static void fill_surface(IDirectDrawSurface4 *surface, D3DCOLOR color)
6521 DDSURFACEDESC2 surface_desc = {sizeof(surface_desc)};
6522 HRESULT hr;
6523 unsigned int x, y;
6524 DWORD *ptr;
6526 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
6527 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6529 for (y = 0; y < surface_desc.dwHeight; ++y)
6531 ptr = (DWORD *)((BYTE *)surface_desc.lpSurface + y * U1(surface_desc).lPitch);
6532 for (x = 0; x < surface_desc.dwWidth; ++x)
6534 ptr[x] = color;
6538 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6539 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6542 static void test_flip(void)
6544 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
6545 IDirectDrawSurface4 *frontbuffer, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
6546 DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}};
6547 DDSURFACEDESC2 surface_desc;
6548 BOOL sysmem_primary;
6549 IDirectDraw4 *ddraw;
6550 DWORD expected_caps;
6551 unsigned int i;
6552 D3DCOLOR color;
6553 ULONG refcount;
6554 HWND window;
6555 HRESULT hr;
6557 static const struct
6559 const char *name;
6560 DWORD caps;
6562 test_data[] =
6564 {"PRIMARYSURFACE", DDSCAPS_PRIMARYSURFACE},
6565 {"OFFSCREENPLAIN", DDSCAPS_OFFSCREENPLAIN},
6566 {"TEXTURE", DDSCAPS_TEXTURE},
6569 window = create_window();
6570 ddraw = create_ddraw();
6571 ok(!!ddraw, "Failed to create a ddraw object.\n");
6573 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6574 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6576 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6578 /* Creating a flippable texture induces a BSoD on some versions of the
6579 * Intel graphics driver. At least Intel GMA 950 with driver version
6580 * 6.14.10.4926 on Windows XP SP3 is affected. */
6581 if ((test_data[i].caps & DDSCAPS_TEXTURE) && ddraw_is_intel(ddraw))
6583 win_skip("Skipping flippable texture test.\n");
6584 continue;
6587 memset(&surface_desc, 0, sizeof(surface_desc));
6588 surface_desc.dwSize = sizeof(surface_desc);
6589 surface_desc.dwFlags = DDSD_CAPS;
6590 if (!(test_data[i].caps & DDSCAPS_PRIMARYSURFACE))
6591 surface_desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6592 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
6593 surface_desc.dwWidth = 512;
6594 surface_desc.dwHeight = 512;
6595 U5(surface_desc).dwBackBufferCount = 3;
6596 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6597 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6599 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
6600 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
6601 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6602 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6604 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
6605 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
6606 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6607 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6609 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
6610 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6611 todo_wine_if(test_data[i].caps & DDSCAPS_TEXTURE)
6612 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
6613 if (FAILED(hr))
6614 continue;
6616 memset(&surface_desc, 0, sizeof(surface_desc));
6617 surface_desc.dwSize = sizeof(surface_desc);
6618 hr = IDirectDrawSurface4_GetSurfaceDesc(frontbuffer, &surface_desc);
6619 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6620 expected_caps = DDSCAPS_FRONTBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
6621 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
6622 expected_caps |= DDSCAPS_VISIBLE;
6623 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6624 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6625 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
6627 hr = IDirectDrawSurface4_GetAttachedSurface(frontbuffer, &caps, &backbuffer1);
6628 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6629 memset(&surface_desc, 0, sizeof(surface_desc));
6630 surface_desc.dwSize = sizeof(surface_desc);
6631 hr = IDirectDrawSurface4_GetSurfaceDesc(backbuffer1, &surface_desc);
6632 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6633 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6634 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6635 expected_caps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER);
6636 expected_caps |= DDSCAPS_BACKBUFFER;
6637 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6638 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6640 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
6641 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6642 memset(&surface_desc, 0, sizeof(surface_desc));
6643 surface_desc.dwSize = sizeof(surface_desc);
6644 hr = IDirectDrawSurface4_GetSurfaceDesc(backbuffer2, &surface_desc);
6645 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6646 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6647 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6648 expected_caps &= ~DDSCAPS_BACKBUFFER;
6649 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6650 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6652 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
6653 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6654 memset(&surface_desc, 0, sizeof(surface_desc));
6655 surface_desc.dwSize = sizeof(surface_desc);
6656 hr = IDirectDrawSurface4_GetSurfaceDesc(backbuffer3, &surface_desc);
6657 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6658 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6659 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6660 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6661 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6663 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer3, &caps, &surface);
6664 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6665 ok(surface == frontbuffer, "%s: Got unexpected surface %p, expected %p.\n",
6666 test_data[i].name, surface, frontbuffer);
6667 IDirectDrawSurface4_Release(surface);
6669 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
6670 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
6671 hr = IDirectDrawSurface4_IsLost(frontbuffer);
6672 ok(hr == DD_OK, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6673 hr = IDirectDrawSurface4_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6674 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
6675 ok(hr == DDERR_NOEXCLUSIVEMODE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6676 else
6677 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6678 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6679 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
6680 hr = IDirectDrawSurface4_IsLost(frontbuffer);
6681 todo_wine ok(hr == DDERR_SURFACELOST, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6682 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
6683 ok(SUCCEEDED(hr), "%s: Failed to restore surfaces, hr %#x.\n", test_data[i].name, hr);
6685 memset(&surface_desc, 0, sizeof(surface_desc));
6686 surface_desc.dwSize = sizeof(surface_desc);
6687 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6688 surface_desc.ddsCaps.dwCaps = 0;
6689 surface_desc.dwWidth = 640;
6690 surface_desc.dwHeight = 480;
6691 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6692 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
6693 hr = IDirectDrawSurface4_Flip(frontbuffer, surface, DDFLIP_WAIT);
6694 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6695 IDirectDrawSurface4_Release(surface);
6697 hr = IDirectDrawSurface4_Flip(frontbuffer, frontbuffer, DDFLIP_WAIT);
6698 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6699 hr = IDirectDrawSurface4_Flip(backbuffer1, NULL, DDFLIP_WAIT);
6700 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6701 hr = IDirectDrawSurface4_Flip(backbuffer2, NULL, DDFLIP_WAIT);
6702 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6703 hr = IDirectDrawSurface4_Flip(backbuffer3, NULL, DDFLIP_WAIT);
6704 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6706 /* The Nvidia Geforce 7 driver cannot do a color fill on a texture backbuffer after
6707 * the backbuffer has been locked. Do it ourselves as a workaround. Unlike ddraw1
6708 * and 2 GetSurfaceDesc does not cause issues in ddraw4 and ddraw7. */
6709 fill_surface(backbuffer1, 0xffff0000);
6710 fill_surface(backbuffer2, 0xff00ff00);
6711 fill_surface(backbuffer3, 0xff0000ff);
6713 hr = IDirectDrawSurface4_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6714 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6715 color = get_surface_color(backbuffer1, 320, 240);
6716 /* The testbot seems to just copy the contents of one surface to all the
6717 * others, instead of properly flipping. */
6718 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6719 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6720 color = get_surface_color(backbuffer2, 320, 240);
6721 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6722 fill_surface(backbuffer3, 0xffff0000);
6724 hr = IDirectDrawSurface4_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6725 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6726 color = get_surface_color(backbuffer1, 320, 240);
6727 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6728 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6729 color = get_surface_color(backbuffer2, 320, 240);
6730 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6731 fill_surface(backbuffer3, 0xff00ff00);
6733 hr = IDirectDrawSurface4_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6734 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6735 color = get_surface_color(backbuffer1, 320, 240);
6736 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6737 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6738 color = get_surface_color(backbuffer2, 320, 240);
6739 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6740 fill_surface(backbuffer3, 0xff0000ff);
6742 hr = IDirectDrawSurface4_Flip(frontbuffer, backbuffer1, DDFLIP_WAIT);
6743 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6744 color = get_surface_color(backbuffer2, 320, 240);
6745 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6746 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6747 color = get_surface_color(backbuffer3, 320, 240);
6748 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6749 fill_surface(backbuffer1, 0xffff0000);
6751 hr = IDirectDrawSurface4_Flip(frontbuffer, backbuffer2, DDFLIP_WAIT);
6752 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6753 color = get_surface_color(backbuffer1, 320, 240);
6754 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6755 color = get_surface_color(backbuffer3, 320, 240);
6756 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6757 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6758 fill_surface(backbuffer2, 0xff00ff00);
6760 hr = IDirectDrawSurface4_Flip(frontbuffer, backbuffer3, DDFLIP_WAIT);
6761 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6762 color = get_surface_color(backbuffer1, 320, 240);
6763 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6764 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6765 color = get_surface_color(backbuffer2, 320, 240);
6766 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6768 IDirectDrawSurface4_Release(backbuffer3);
6769 IDirectDrawSurface4_Release(backbuffer2);
6770 IDirectDrawSurface4_Release(backbuffer1);
6771 IDirectDrawSurface4_Release(frontbuffer);
6774 refcount = IDirectDraw4_Release(ddraw);
6775 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6776 DestroyWindow(window);
6779 static void reset_ddsd(DDSURFACEDESC2 *ddsd)
6781 memset(ddsd, 0, sizeof(*ddsd));
6782 ddsd->dwSize = sizeof(*ddsd);
6785 static void test_set_surface_desc(void)
6787 IDirectDraw4 *ddraw;
6788 HWND window;
6789 HRESULT hr;
6790 DDSURFACEDESC2 ddsd;
6791 IDirectDrawSurface4 *surface;
6792 BYTE data[16*16*4];
6793 ULONG ref;
6794 unsigned int i;
6795 static const struct
6797 DWORD caps, caps2;
6798 BOOL supported;
6799 const char *name;
6801 invalid_caps_tests[] =
6803 {DDSCAPS_VIDEOMEMORY, 0, FALSE, "videomemory plain"},
6804 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, TRUE, "systemmemory texture"},
6805 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE, "managed texture"},
6806 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE, "managed texture"},
6807 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, 0, FALSE, "systemmemory primary"},
6810 window = create_window();
6811 ddraw = create_ddraw();
6812 ok(!!ddraw, "Failed to create a ddraw object.\n");
6813 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6814 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6816 reset_ddsd(&ddsd);
6817 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6818 ddsd.dwWidth = 8;
6819 ddsd.dwHeight = 8;
6820 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6821 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6822 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6823 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6824 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6825 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6826 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6828 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6829 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6831 reset_ddsd(&ddsd);
6832 ddsd.dwFlags = DDSD_LPSURFACE;
6833 ddsd.lpSurface = data;
6834 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6835 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6837 /* Redundantly setting the same lpSurface is not an error. */
6838 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6839 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6840 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6841 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6842 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6843 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
6845 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, 0, NULL);
6846 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6847 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6848 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
6849 hr = IDirectDrawSurface4_Unlock(surface, NULL);
6850 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6852 reset_ddsd(&ddsd);
6853 ddsd.dwFlags = DDSD_LPSURFACE;
6854 ddsd.lpSurface = data;
6855 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 1);
6856 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
6858 ddsd.lpSurface = NULL;
6859 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6860 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
6862 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, NULL, 0);
6863 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
6865 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6866 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6867 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6868 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6869 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6871 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
6872 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6873 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
6875 ddsd.dwFlags = DDSD_CAPS;
6876 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6877 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
6879 /* dwCaps = 0 is allowed, but ignored. Caps2 can be anything and is ignored too. */
6880 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
6881 ddsd.lpSurface = data;
6882 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6883 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6884 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6885 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6886 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6887 ddsd.ddsCaps.dwCaps = 0;
6888 ddsd.ddsCaps.dwCaps2 = 0xdeadbeef;
6889 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6890 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6892 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6893 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6894 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6895 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6896 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6898 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
6899 reset_ddsd(&ddsd);
6900 ddsd.dwFlags = DDSD_HEIGHT;
6901 ddsd.dwHeight = 16;
6902 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6903 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
6905 ddsd.lpSurface = data;
6906 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
6907 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6908 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6910 ddsd.dwHeight = 0;
6911 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6912 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
6914 reset_ddsd(&ddsd);
6915 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6916 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
6917 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6918 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6920 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0 */
6921 reset_ddsd(&ddsd);
6922 ddsd.dwFlags = DDSD_PITCH;
6923 U1(ddsd).lPitch = 8 * 4;
6924 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6925 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
6927 ddsd.dwFlags = DDSD_WIDTH;
6928 ddsd.dwWidth = 16;
6929 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6930 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
6932 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
6933 ddsd.lpSurface = data;
6934 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6935 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
6937 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
6938 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6939 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
6941 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6942 U1(ddsd).lPitch = 16 * 4;
6943 ddsd.dwWidth = 16;
6944 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6945 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6947 reset_ddsd(&ddsd);
6948 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6949 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6950 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6951 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6952 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
6954 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
6956 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
6957 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6958 U1(ddsd).lPitch = 4 * 4;
6959 ddsd.lpSurface = data;
6960 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6961 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
6963 U1(ddsd).lPitch = 4;
6964 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6965 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
6967 U1(ddsd).lPitch = 16 * 4 + 1;
6968 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6969 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
6971 U1(ddsd).lPitch = 16 * 4 + 3;
6972 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6973 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
6975 U1(ddsd).lPitch = -4;
6976 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6977 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
6979 U1(ddsd).lPitch = 16 * 4;
6980 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6981 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6983 reset_ddsd(&ddsd);
6984 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6985 U1(ddsd).lPitch = 0;
6986 ddsd.dwWidth = 16;
6987 ddsd.lpSurface = data;
6988 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6989 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
6991 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6992 U1(ddsd).lPitch = 16 * 4;
6993 ddsd.dwWidth = 0;
6994 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
6995 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
6997 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
6998 ddsd.dwFlags = DDSD_PIXELFORMAT;
6999 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7000 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7001 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7002 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7003 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7004 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7005 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7006 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
7008 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
7009 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7010 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7012 /* Can't set color keys. */
7013 reset_ddsd(&ddsd);
7014 ddsd.dwFlags = DDSD_CKSRCBLT;
7015 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
7016 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
7017 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7018 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
7020 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
7021 ddsd.lpSurface = data;
7022 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7023 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
7025 IDirectDrawSurface4_Release(surface);
7027 /* SetSurfaceDesc needs systemmemory surfaces.
7029 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing DDSD_LINEARSIZE is moot. */
7030 for (i = 0; i < ARRAY_SIZE(invalid_caps_tests); i++)
7032 reset_ddsd(&ddsd);
7033 ddsd.dwFlags = DDSD_CAPS;
7034 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
7035 ddsd.ddsCaps.dwCaps2 = invalid_caps_tests[i].caps2;
7036 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
7038 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7039 ddsd.dwWidth = 8;
7040 ddsd.dwHeight = 8;
7041 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7042 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7043 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7044 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7045 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7046 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7049 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
7050 ok(SUCCEEDED(hr) || hr == DDERR_NODIRECTDRAWHW, "Failed to create surface, hr %#x.\n", hr);
7051 if (FAILED(hr))
7053 skip("Cannot create a %s surface, skipping vidmem SetSurfaceDesc test.\n",
7054 invalid_caps_tests[i].name);
7055 goto done;
7058 reset_ddsd(&ddsd);
7059 ddsd.dwFlags = DDSD_LPSURFACE;
7060 ddsd.lpSurface = data;
7061 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7062 if (invalid_caps_tests[i].supported)
7064 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7066 else
7068 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
7069 invalid_caps_tests[i].name, hr);
7071 /* Check priority of error conditions. */
7072 ddsd.dwFlags = DDSD_WIDTH;
7073 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7074 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
7075 invalid_caps_tests[i].name, hr);
7078 IDirectDrawSurface4_Release(surface);
7081 done:
7082 ref = IDirectDraw4_Release(ddraw);
7083 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
7084 DestroyWindow(window);
7087 static void test_user_memory_getdc(void)
7089 IDirectDraw4 *ddraw;
7090 HWND window;
7091 HRESULT hr;
7092 DDSURFACEDESC2 ddsd;
7093 IDirectDrawSurface4 *surface;
7094 DWORD data[16][16];
7095 HBITMAP bitmap;
7096 DIBSECTION dib;
7097 ULONG ref;
7098 int size;
7099 HDC dc;
7100 unsigned int x, y;
7102 window = create_window();
7103 ddraw = create_ddraw();
7104 ok(!!ddraw, "Failed to create a ddraw object.\n");
7106 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7107 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7109 reset_ddsd(&ddsd);
7110 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
7111 ddsd.dwWidth = 16;
7112 ddsd.dwHeight = 16;
7113 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7114 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7115 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7116 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7117 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7118 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7119 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7120 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
7121 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7123 memset(data, 0xaa, sizeof(data));
7124 reset_ddsd(&ddsd);
7125 ddsd.dwFlags = DDSD_LPSURFACE;
7126 ddsd.lpSurface = data;
7127 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7128 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7130 hr = IDirectDrawSurface4_GetDC(surface, &dc);
7131 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7132 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
7133 ok(!!bitmap, "Failed to get bitmap.\n");
7134 size = GetObjectA(bitmap, sizeof(dib), &dib);
7135 ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
7136 ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
7137 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
7138 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
7139 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
7140 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7142 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
7143 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
7145 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
7146 ddsd.lpSurface = data;
7147 ddsd.dwWidth = 4;
7148 ddsd.dwHeight = 8;
7149 U1(ddsd).lPitch = sizeof(*data);
7150 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7151 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7153 memset(data, 0xaa, sizeof(data));
7154 hr = IDirectDrawSurface4_GetDC(surface, &dc);
7155 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7156 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
7157 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
7158 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
7159 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7161 for (y = 0; y < 4; y++)
7163 for (x = 0; x < 4; x++)
7165 if ((x == 1 || x == 2) && (y == 1 || y == 2))
7166 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
7167 x, y, data[y][x]);
7168 else
7169 ok(data[y][x] == 0x00000000, "Expected color 0x00000000 on position %ux%u, got %#x.\n",
7170 x, y, data[y][x]);
7173 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
7174 data[0][5]);
7175 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
7176 data[7][3]);
7177 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
7178 data[7][4]);
7179 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
7180 data[8][0]);
7182 IDirectDrawSurface4_Release(surface);
7183 ref = IDirectDraw4_Release(ddraw);
7184 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
7185 DestroyWindow(window);
7188 static void test_sysmem_overlay(void)
7190 IDirectDraw4 *ddraw;
7191 HWND window;
7192 HRESULT hr;
7193 DDSURFACEDESC2 ddsd;
7194 IDirectDrawSurface4 *surface;
7195 ULONG ref;
7197 window = create_window();
7198 ddraw = create_ddraw();
7199 ok(!!ddraw, "Failed to create a ddraw object.\n");
7201 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7202 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7204 reset_ddsd(&ddsd);
7205 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
7206 ddsd.dwWidth = 16;
7207 ddsd.dwHeight = 16;
7208 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
7209 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7210 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7211 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7212 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7213 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7214 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7215 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
7216 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
7218 ref = IDirectDraw4_Release(ddraw);
7219 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
7220 DestroyWindow(window);
7223 static void test_primary_palette(void)
7225 DDSCAPS2 surface_caps = {DDSCAPS_FLIP, 0, 0, {0}};
7226 IDirectDrawSurface4 *primary, *backbuffer;
7227 PALETTEENTRY palette_entries[256];
7228 IDirectDrawPalette *palette, *tmp;
7229 DDSURFACEDESC2 surface_desc;
7230 IDirectDraw4 *ddraw;
7231 DWORD palette_caps;
7232 ULONG refcount;
7233 HWND window;
7234 HRESULT hr;
7236 window = create_window();
7237 ddraw = create_ddraw();
7238 ok(!!ddraw, "Failed to create a ddraw object.\n");
7239 if (FAILED(IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
7241 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
7242 IDirectDraw4_Release(ddraw);
7243 DestroyWindow(window);
7244 return;
7246 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7247 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7249 memset(&surface_desc, 0, sizeof(surface_desc));
7250 surface_desc.dwSize = sizeof(surface_desc);
7251 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
7252 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
7253 U5(surface_desc).dwBackBufferCount = 1;
7254 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
7255 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7256 hr = IDirectDrawSurface4_GetAttachedSurface(primary, &surface_caps, &backbuffer);
7257 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7259 memset(palette_entries, 0, sizeof(palette_entries));
7260 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
7261 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7262 refcount = get_refcount((IUnknown *)palette);
7263 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7265 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
7266 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
7267 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
7269 hr = IDirectDrawSurface4_SetPalette(primary, palette);
7270 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7272 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
7273 * and is generally somewhat broken with respect to 8 bpp / palette
7274 * handling. */
7275 if (SUCCEEDED(IDirectDrawSurface4_GetPalette(backbuffer, &tmp)))
7277 win_skip("Broken palette handling detected, skipping tests.\n");
7278 IDirectDrawPalette_Release(tmp);
7279 IDirectDrawPalette_Release(palette);
7280 /* The Windows 8 testbot keeps extra references to the primary and
7281 * backbuffer while in 8 bpp mode. */
7282 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
7283 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
7284 goto done;
7287 refcount = get_refcount((IUnknown *)palette);
7288 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7290 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
7291 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
7292 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
7293 "Got unexpected palette caps %#x.\n", palette_caps);
7295 hr = IDirectDrawSurface4_SetPalette(primary, NULL);
7296 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7297 refcount = get_refcount((IUnknown *)palette);
7298 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7300 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
7301 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
7302 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
7304 hr = IDirectDrawSurface4_SetPalette(primary, palette);
7305 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7306 refcount = get_refcount((IUnknown *)palette);
7307 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7309 hr = IDirectDrawSurface4_GetPalette(primary, &tmp);
7310 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
7311 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
7312 IDirectDrawPalette_Release(tmp);
7313 hr = IDirectDrawSurface4_GetPalette(backbuffer, &tmp);
7314 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
7316 refcount = IDirectDrawPalette_Release(palette);
7317 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7318 refcount = IDirectDrawPalette_Release(palette);
7319 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7321 /* Note that this only seems to work when the palette is attached to the
7322 * primary surface. When attached to a regular surface, attempting to get
7323 * the palette here will cause an access violation. */
7324 hr = IDirectDrawSurface4_GetPalette(primary, &tmp);
7325 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
7327 hr = IDirectDrawSurface4_IsLost(primary);
7328 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7330 memset(&surface_desc, 0, sizeof(surface_desc));
7331 surface_desc.dwSize = sizeof(surface_desc);
7332 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &surface_desc);
7333 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7334 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
7335 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
7336 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 8, "Got unexpected bit count %u.\n",
7337 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
7339 hr = set_display_mode(ddraw, 640, 480);
7340 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
7342 memset(&surface_desc, 0, sizeof(surface_desc));
7343 surface_desc.dwSize = sizeof(surface_desc);
7344 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &surface_desc);
7345 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7346 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
7347 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
7348 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
7349 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
7350 "Got unexpected bit count %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
7352 hr = IDirectDrawSurface4_IsLost(primary);
7353 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7354 hr = IDirectDrawSurface4_Restore(primary);
7355 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
7356 hr = IDirectDrawSurface4_IsLost(primary);
7357 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7359 memset(&surface_desc, 0, sizeof(surface_desc));
7360 surface_desc.dwSize = sizeof(surface_desc);
7361 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &surface_desc);
7362 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7363 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
7364 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
7365 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
7366 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
7367 "Got unexpected bit count %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
7369 done:
7370 refcount = IDirectDrawSurface4_Release(backbuffer);
7371 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7372 refcount = IDirectDrawSurface4_Release(primary);
7373 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7374 refcount = IDirectDraw4_Release(ddraw);
7375 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7376 DestroyWindow(window);
7379 static HRESULT WINAPI surface_counter(IDirectDrawSurface4 *surface, DDSURFACEDESC2 *desc, void *context)
7381 UINT *surface_count = context;
7383 ++(*surface_count);
7384 IDirectDrawSurface_Release(surface);
7386 return DDENUMRET_OK;
7389 static void test_surface_attachment(void)
7391 IDirectDrawSurface4 *surface1, *surface2, *surface3, *surface4;
7392 IDirectDrawSurface *surface1v1, *surface2v1;
7393 DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, {0}};
7394 DDSURFACEDESC2 surface_desc;
7395 IDirectDraw4 *ddraw;
7396 UINT surface_count;
7397 ULONG refcount;
7398 HWND window;
7399 HRESULT hr;
7401 window = create_window();
7402 ddraw = create_ddraw();
7403 ok(!!ddraw, "Failed to create a ddraw object.\n");
7404 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7405 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7407 memset(&surface_desc, 0, sizeof(surface_desc));
7408 surface_desc.dwSize = sizeof(surface_desc);
7409 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
7410 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7411 U2(surface_desc).dwMipMapCount = 3;
7412 surface_desc.dwWidth = 128;
7413 surface_desc.dwHeight = 128;
7414 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7415 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7417 hr = IDirectDrawSurface4_GetAttachedSurface(surface1, &caps, &surface2);
7418 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
7419 hr = IDirectDrawSurface4_GetAttachedSurface(surface2, &caps, &surface3);
7420 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
7421 hr = IDirectDrawSurface4_GetAttachedSurface(surface3, &caps, &surface4);
7422 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7424 surface_count = 0;
7425 IDirectDrawSurface4_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
7426 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
7427 surface_count = 0;
7428 IDirectDrawSurface4_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
7429 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
7430 surface_count = 0;
7431 IDirectDrawSurface4_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
7432 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
7434 memset(&surface_desc, 0, sizeof(surface_desc));
7435 surface_desc.dwSize = sizeof(surface_desc);
7436 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7437 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
7438 surface_desc.dwWidth = 16;
7439 surface_desc.dwHeight = 16;
7440 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7441 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7443 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface4);
7444 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7445 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface1);
7446 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7447 hr = IDirectDrawSurface4_AddAttachedSurface(surface3, surface4);
7448 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7449 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface3);
7450 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7451 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface4);
7452 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7453 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface2);
7454 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7456 IDirectDrawSurface4_Release(surface4);
7458 memset(&surface_desc, 0, sizeof(surface_desc));
7459 surface_desc.dwSize = sizeof(surface_desc);
7460 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7461 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7462 surface_desc.dwWidth = 16;
7463 surface_desc.dwHeight = 16;
7464 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7465 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7467 if (SUCCEEDED(hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface4)))
7469 skip("Running on refrast, skipping some tests.\n");
7470 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface4);
7471 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7473 else
7475 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7476 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface1);
7477 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7478 hr = IDirectDrawSurface4_AddAttachedSurface(surface3, surface4);
7479 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7480 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface3);
7481 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7482 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface4);
7483 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7484 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface2);
7485 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7488 IDirectDrawSurface4_Release(surface4);
7489 IDirectDrawSurface4_Release(surface3);
7490 IDirectDrawSurface4_Release(surface2);
7491 IDirectDrawSurface4_Release(surface1);
7493 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7494 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7496 /* Try a single primary and two offscreen plain surfaces. */
7497 memset(&surface_desc, 0, sizeof(surface_desc));
7498 surface_desc.dwSize = sizeof(surface_desc);
7499 surface_desc.dwFlags = DDSD_CAPS;
7500 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7501 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7502 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7504 memset(&surface_desc, 0, sizeof(surface_desc));
7505 surface_desc.dwSize = sizeof(surface_desc);
7506 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7507 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7508 surface_desc.dwWidth = registry_mode.dmPelsWidth;
7509 surface_desc.dwHeight = registry_mode.dmPelsHeight;
7510 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7511 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7513 memset(&surface_desc, 0, sizeof(surface_desc));
7514 surface_desc.dwSize = sizeof(surface_desc);
7515 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7516 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7517 surface_desc.dwWidth = registry_mode.dmPelsWidth;
7518 surface_desc.dwHeight = registry_mode.dmPelsHeight;
7519 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7520 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7522 /* This one has a different size. */
7523 memset(&surface_desc, 0, sizeof(surface_desc));
7524 surface_desc.dwSize = sizeof(surface_desc);
7525 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7526 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7527 surface_desc.dwWidth = 128;
7528 surface_desc.dwHeight = 128;
7529 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7530 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7532 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface2);
7533 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7534 /* Try the reverse without detaching first. */
7535 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface1);
7536 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
7537 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
7538 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7540 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface1);
7541 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7542 /* Try to detach reversed. */
7543 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
7544 ok(hr == DDERR_CANNOTDETACHSURFACE, "Got unexpected hr %#x.\n", hr);
7545 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface2, 0, surface1);
7546 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7548 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface3);
7549 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7550 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface2, 0, surface3);
7551 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7553 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface4);
7554 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7555 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface1);
7556 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7558 IDirectDrawSurface4_Release(surface4);
7559 IDirectDrawSurface4_Release(surface3);
7560 IDirectDrawSurface4_Release(surface2);
7561 IDirectDrawSurface4_Release(surface1);
7563 /* Test depth surfaces of different sizes. */
7564 memset(&surface_desc, 0, sizeof(surface_desc));
7565 surface_desc.dwSize = sizeof(surface_desc);
7566 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7567 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
7568 surface_desc.dwWidth = 64;
7569 surface_desc.dwHeight = 64;
7570 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7571 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
7573 memset(&surface_desc, 0, sizeof(surface_desc));
7574 surface_desc.dwSize = sizeof(surface_desc);
7575 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
7576 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
7577 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7578 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
7579 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
7580 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
7581 surface_desc.dwWidth = 32;
7582 surface_desc.dwHeight = 32;
7583 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7584 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
7585 surface_desc.dwWidth = 64;
7586 surface_desc.dwHeight = 64;
7587 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7588 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
7589 surface_desc.dwWidth = 128;
7590 surface_desc.dwHeight = 128;
7591 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7592 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
7594 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
7595 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7596 if (SUCCEEDED(hr))
7597 IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface3);
7598 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface3);
7599 ok(hr == D3D_OK, "Failed to attach depth buffer, hr %#x.\n", hr);
7600 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface3);
7601 ok(hr == D3D_OK, "Failed to detach depth buffer, hr %#x.\n", hr);
7602 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
7603 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7605 IDirectDrawSurface4_Release(surface4);
7606 IDirectDrawSurface4_Release(surface3);
7607 IDirectDrawSurface4_Release(surface2);
7608 IDirectDrawSurface4_Release(surface1);
7610 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
7611 memset(&surface_desc, 0, sizeof(surface_desc));
7612 surface_desc.dwSize = sizeof(surface_desc);
7613 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7614 surface_desc.dwWidth = 64;
7615 surface_desc.dwHeight = 64;
7616 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
7617 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7618 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
7619 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
7620 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
7621 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
7622 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
7623 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7624 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7625 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7626 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7628 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
7629 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
7630 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
7631 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
7632 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7633 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7635 hr = IDirectDrawSurface4_QueryInterface(surface1, &IID_IDirectDrawSurface, (void **)&surface1v1);
7636 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
7637 hr = IDirectDrawSurface4_QueryInterface(surface2, &IID_IDirectDrawSurface, (void **)&surface2v1);
7638 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
7640 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface2);
7641 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7642 refcount = get_refcount((IUnknown *)surface2);
7643 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7644 refcount = get_refcount((IUnknown *)surface2v1);
7645 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7646 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface2);
7647 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
7648 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7649 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7650 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
7651 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
7653 /* Attaching while already attached to other surface. */
7654 hr = IDirectDrawSurface4_AddAttachedSurface(surface3, surface2);
7655 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7656 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface3, 0, surface2);
7657 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7658 IDirectDrawSurface4_Release(surface3);
7660 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
7661 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7662 refcount = get_refcount((IUnknown *)surface2);
7663 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7664 refcount = get_refcount((IUnknown *)surface2v1);
7665 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7667 /* DeleteAttachedSurface() when attaching via IDirectDrawSurface. */
7668 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7669 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7670 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
7671 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
7672 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
7673 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7674 refcount = IDirectDrawSurface4_Release(surface2);
7675 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7676 refcount = IDirectDrawSurface4_Release(surface1);
7677 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7679 /* Automatic detachment on release. */
7680 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7681 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7682 refcount = get_refcount((IUnknown *)surface2v1);
7683 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7684 refcount = IDirectDrawSurface_Release(surface1v1);
7685 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7686 refcount = IDirectDrawSurface_Release(surface2v1);
7687 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7688 refcount = IDirectDraw4_Release(ddraw);
7689 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7690 DestroyWindow(window);
7693 static void test_private_data(void)
7695 IDirectDraw4 *ddraw;
7696 IDirectDrawSurface4 *surface, *surface2;
7697 DDSURFACEDESC2 surface_desc;
7698 ULONG refcount, refcount2, refcount3;
7699 IUnknown *ptr;
7700 DWORD size = sizeof(ptr);
7701 HRESULT hr;
7702 HWND window;
7703 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7704 DWORD data[] = {1, 2, 3, 4};
7705 DDCAPS hal_caps;
7706 static const GUID ddraw_private_data_test_guid =
7708 0xfdb37466,
7709 0x428f,
7710 0x4edf,
7711 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
7713 static const GUID ddraw_private_data_test_guid2 =
7715 0x2e5afac2,
7716 0x87b5,
7717 0x4c10,
7718 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
7721 window = create_window();
7722 ddraw = create_ddraw();
7723 ok(!!ddraw, "Failed to create a ddraw object.\n");
7724 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7725 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7727 reset_ddsd(&surface_desc);
7728 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
7729 surface_desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
7730 surface_desc.dwHeight = 4;
7731 surface_desc.dwWidth = 4;
7732 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7733 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7735 /* NULL pointers are not valid, but don't cause a crash. */
7736 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL,
7737 sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
7738 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7739 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 0, 0);
7740 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7741 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 1, 0);
7742 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7744 /* DDSPD_IUNKNOWNPOINTER needs sizeof(IUnknown *) bytes of data. */
7745 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7746 0, DDSPD_IUNKNOWNPOINTER);
7747 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7748 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7749 5, DDSPD_IUNKNOWNPOINTER);
7750 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7751 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7752 sizeof(ddraw) * 2, DDSPD_IUNKNOWNPOINTER);
7753 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7755 /* Note that with a size != 0 and size != sizeof(IUnknown *) and
7756 * DDSPD_IUNKNOWNPOINTER set SetPrivateData in ddraw4 and ddraw7
7757 * erases the old content and returns an error. This behavior has
7758 * been fixed in d3d8 and d3d9. Unless an application is found
7759 * that depends on this we don't care about this behavior. */
7760 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7761 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7762 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7763 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7764 0, DDSPD_IUNKNOWNPOINTER);
7765 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7766 size = sizeof(ptr);
7767 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7768 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7769 hr = IDirectDrawSurface4_FreePrivateData(surface, &ddraw_private_data_test_guid);
7770 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7772 refcount = get_refcount((IUnknown *)ddraw);
7773 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7774 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7775 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7776 refcount2 = get_refcount((IUnknown *)ddraw);
7777 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
7779 hr = IDirectDrawSurface4_FreePrivateData(surface, &ddraw_private_data_test_guid);
7780 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7781 refcount2 = get_refcount((IUnknown *)ddraw);
7782 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
7784 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7785 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7786 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7787 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, surface,
7788 sizeof(surface), DDSPD_IUNKNOWNPOINTER);
7789 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7790 refcount2 = get_refcount((IUnknown *)ddraw);
7791 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
7793 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7794 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7795 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7796 size = 2 * sizeof(ptr);
7797 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7798 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7799 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7800 refcount2 = get_refcount(ptr);
7801 /* Object is NOT addref'ed by the getter. */
7802 ok(ptr == (IUnknown *)ddraw, "Returned interface pointer is %p, expected %p.\n", ptr, ddraw);
7803 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
7805 ptr = (IUnknown *)0xdeadbeef;
7806 size = 1;
7807 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
7808 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7809 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7810 size = 2 * sizeof(ptr);
7811 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
7812 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7813 ok(size == 2 * sizeof(ptr), "Got unexpected size %u.\n", size);
7814 size = 1;
7815 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7816 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7817 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7818 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7819 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid2, NULL, NULL);
7820 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7821 size = 0xdeadbabe;
7822 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid2, &ptr, &size);
7823 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7824 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7825 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
7826 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, NULL);
7827 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7829 refcount3 = IDirectDrawSurface4_Release(surface);
7830 ok(!refcount3, "Got unexpected refcount %u.\n", refcount3);
7832 /* Destroying the surface frees the reference held on the private data. It also frees
7833 * the reference the surface is holding on its creating object. */
7834 refcount2 = get_refcount((IUnknown *)ddraw);
7835 ok(refcount2 == refcount - 1, "Got unexpected refcount %u.\n", refcount2);
7837 memset(&hal_caps, 0, sizeof(hal_caps));
7838 hal_caps.dwSize = sizeof(hal_caps);
7839 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
7840 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7841 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) == (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
7843 reset_ddsd(&surface_desc);
7844 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT;
7845 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7846 surface_desc.dwHeight = 4;
7847 surface_desc.dwWidth = 4;
7848 U2(surface_desc).dwMipMapCount = 2;
7849 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7850 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7851 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &surface2);
7852 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7854 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, data, sizeof(data), 0);
7855 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7856 hr = IDirectDrawSurface4_GetPrivateData(surface2, &ddraw_private_data_test_guid, NULL, NULL);
7857 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7859 IDirectDrawSurface4_Release(surface2);
7860 IDirectDrawSurface4_Release(surface);
7862 else
7863 skip("Mipmapped textures not supported, skipping mipmap private data test.\n");
7865 refcount = IDirectDraw4_Release(ddraw);
7866 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7867 DestroyWindow(window);
7870 static void test_pixel_format(void)
7872 HWND window, window2 = NULL;
7873 HDC hdc, hdc2 = NULL;
7874 HMODULE gl = NULL;
7875 int format, test_format;
7876 PIXELFORMATDESCRIPTOR pfd;
7877 IDirectDraw4 *ddraw = NULL;
7878 IDirectDrawClipper *clipper = NULL;
7879 DDSURFACEDESC2 ddsd;
7880 IDirectDrawSurface4 *primary = NULL;
7881 DDBLTFX fx;
7882 HRESULT hr;
7884 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7885 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7886 if (!window)
7888 skip("Failed to create window\n");
7889 return;
7892 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7893 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7895 hdc = GetDC(window);
7896 if (!hdc)
7898 skip("Failed to get DC\n");
7899 goto cleanup;
7902 if (window2)
7903 hdc2 = GetDC(window2);
7905 gl = LoadLibraryA("opengl32.dll");
7906 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
7908 format = GetPixelFormat(hdc);
7909 ok(format == 0, "new window has pixel format %d\n", format);
7911 ZeroMemory(&pfd, sizeof(pfd));
7912 pfd.nSize = sizeof(pfd);
7913 pfd.nVersion = 1;
7914 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
7915 pfd.iPixelType = PFD_TYPE_RGBA;
7916 pfd.iLayerType = PFD_MAIN_PLANE;
7917 format = ChoosePixelFormat(hdc, &pfd);
7918 if (format <= 0)
7920 skip("no pixel format available\n");
7921 goto cleanup;
7924 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
7926 skip("failed to set pixel format\n");
7927 goto cleanup;
7930 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
7932 skip("failed to set pixel format on second window\n");
7933 if (hdc2)
7935 ReleaseDC(window2, hdc2);
7936 hdc2 = NULL;
7940 ddraw = create_ddraw();
7941 ok(!!ddraw, "Failed to create a ddraw object.\n");
7943 test_format = GetPixelFormat(hdc);
7944 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7946 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7947 if (FAILED(hr))
7949 skip("Failed to set cooperative level, hr %#x.\n", hr);
7950 goto cleanup;
7953 test_format = GetPixelFormat(hdc);
7954 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7956 if (hdc2)
7958 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL);
7959 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
7960 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
7961 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
7963 test_format = GetPixelFormat(hdc);
7964 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7966 test_format = GetPixelFormat(hdc2);
7967 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7970 memset(&ddsd, 0, sizeof(ddsd));
7971 ddsd.dwSize = sizeof(ddsd);
7972 ddsd.dwFlags = DDSD_CAPS;
7973 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7975 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
7976 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
7978 test_format = GetPixelFormat(hdc);
7979 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7981 if (hdc2)
7983 test_format = GetPixelFormat(hdc2);
7984 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7987 if (clipper)
7989 hr = IDirectDrawSurface4_SetClipper(primary, clipper);
7990 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
7992 test_format = GetPixelFormat(hdc);
7993 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7995 test_format = GetPixelFormat(hdc2);
7996 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7999 memset(&fx, 0, sizeof(fx));
8000 fx.dwSize = sizeof(fx);
8001 hr = IDirectDrawSurface4_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8002 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
8004 test_format = GetPixelFormat(hdc);
8005 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8007 if (hdc2)
8009 test_format = GetPixelFormat(hdc2);
8010 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
8013 cleanup:
8014 if (primary) IDirectDrawSurface4_Release(primary);
8015 if (clipper) IDirectDrawClipper_Release(clipper);
8016 if (ddraw) IDirectDraw4_Release(ddraw);
8017 if (gl) FreeLibrary(gl);
8018 if (hdc) ReleaseDC(window, hdc);
8019 if (hdc2) ReleaseDC(window2, hdc2);
8020 DestroyWindow(window);
8021 if (window2) DestroyWindow(window2);
8024 static void test_create_surface_pitch(void)
8026 IDirectDrawSurface4 *surface;
8027 DDSURFACEDESC2 surface_desc;
8028 IDirectDraw4 *ddraw;
8029 unsigned int i;
8030 ULONG refcount;
8031 HWND window;
8032 HRESULT hr;
8033 void *mem;
8035 static const struct
8037 DWORD caps;
8038 DWORD flags_in;
8039 DWORD pitch_in;
8040 HRESULT hr;
8041 DWORD flags_out;
8042 DWORD pitch_out32;
8043 DWORD pitch_out64;
8045 test_data[] =
8047 /* 0 */
8048 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
8049 0, 0, DD_OK,
8050 DDSD_PITCH, 0x100, 0x100},
8051 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
8052 DDSD_PITCH, 0x104, DD_OK,
8053 DDSD_PITCH, 0x100, 0x100},
8054 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
8055 DDSD_PITCH, 0x0f8, DD_OK,
8056 DDSD_PITCH, 0x100, 0x100},
8057 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
8058 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
8059 0, 0, 0 },
8060 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8061 0, 0, DD_OK,
8062 DDSD_PITCH, 0x100, 0x0fc},
8063 /* 5 */
8064 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8065 DDSD_PITCH, 0x104, DD_OK,
8066 DDSD_PITCH, 0x100, 0x0fc},
8067 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8068 DDSD_PITCH, 0x0f8, DD_OK,
8069 DDSD_PITCH, 0x100, 0x0fc},
8070 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8071 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
8072 DDSD_PITCH, 0x100, 0x0fc},
8073 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8074 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
8075 0, 0, 0 },
8076 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8077 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
8078 DDSD_PITCH, 0x100, 0x100},
8079 /* 10 */
8080 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8081 DDSD_LPSURFACE | DDSD_PITCH, 0x0fe, DDERR_INVALIDPARAMS,
8082 0, 0, 0 },
8083 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8084 DDSD_LPSURFACE | DDSD_PITCH, 0x0fc, DD_OK,
8085 DDSD_PITCH, 0x0fc, 0x0fc},
8086 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8087 DDSD_LPSURFACE | DDSD_PITCH, 0x0f8, DDERR_INVALIDPARAMS,
8088 0, 0, 0 },
8089 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8090 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x100, DDERR_INVALIDPARAMS,
8091 0, 0, 0 },
8092 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8093 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x3f00, DDERR_INVALIDPARAMS,
8094 0, 0, 0 },
8095 /* 15 */
8096 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8097 DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, 0x100, DD_OK,
8098 DDSD_PITCH, 0x100, 0x100},
8099 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
8100 0, 0, DDERR_INVALIDCAPS,
8101 0, 0, 0 },
8102 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
8103 0, 0, DD_OK,
8104 DDSD_PITCH, 0x100, 0 },
8105 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
8106 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
8107 0, 0, 0 },
8108 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
8109 0, 0, DDERR_INVALIDCAPS,
8110 0, 0, 0 },
8111 /* 20 */
8112 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
8113 0, 0, DD_OK,
8114 DDSD_PITCH, 0x100, 0 },
8115 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
8116 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
8117 DDSD_PITCH, 0x100, 0 },
8119 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
8121 window = create_window();
8122 ddraw = create_ddraw();
8123 ok(!!ddraw, "Failed to create a ddraw object.\n");
8124 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8125 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8127 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
8129 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
8131 memset(&surface_desc, 0, sizeof(surface_desc));
8132 surface_desc.dwSize = sizeof(surface_desc);
8133 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
8134 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
8135 surface_desc.dwWidth = 63;
8136 surface_desc.dwHeight = 63;
8137 U1(surface_desc).lPitch = test_data[i].pitch_in;
8138 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8139 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
8140 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8141 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8142 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8143 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8144 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8145 if (test_data[i].flags_in & DDSD_LPSURFACE)
8147 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
8148 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, expected_hr);
8149 surface_desc.lpSurface = mem;
8150 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8152 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
8153 continue;
8154 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
8155 if (FAILED(hr))
8156 continue;
8158 memset(&surface_desc, 0, sizeof(surface_desc));
8159 surface_desc.dwSize = sizeof(surface_desc);
8160 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
8161 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
8162 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
8163 "Test %u: Got unexpected flags %#x, expected %#x.\n",
8164 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
8165 /* The pitch for textures seems to be implementation specific. */
8166 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
8168 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
8169 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
8170 "Test %u: Got unexpected pitch %u, expected %u.\n",
8171 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
8172 else
8173 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
8174 "Test %u: Got unexpected pitch %u, expected %u.\n",
8175 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
8177 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
8179 IDirectDrawSurface4_Release(surface);
8182 HeapFree(GetProcessHeap(), 0, mem);
8183 refcount = IDirectDraw4_Release(ddraw);
8184 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8185 DestroyWindow(window);
8188 static void test_mipmap(void)
8190 IDirectDrawSurface4 *surface, *surface_base, *surface_mip;
8191 unsigned int i, mipmap_count;
8192 DDSURFACEDESC2 surface_desc;
8193 IDirectDraw4 *ddraw;
8194 ULONG refcount;
8195 HWND window;
8196 HRESULT hr;
8197 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
8198 DDCAPS hal_caps;
8200 static const struct
8202 DWORD flags;
8203 DWORD caps;
8204 DWORD width;
8205 DWORD height;
8206 DWORD mipmap_count_in;
8207 HRESULT hr;
8208 DWORD mipmap_count_out;
8210 tests[] =
8212 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
8213 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS, 0},
8214 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
8215 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS, 0},
8216 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 6},
8217 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 6},
8220 window = create_window();
8221 ddraw = create_ddraw();
8222 ok(!!ddraw, "Failed to create a ddraw object.\n");
8223 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8224 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8226 memset(&hal_caps, 0, sizeof(hal_caps));
8227 hal_caps.dwSize = sizeof(hal_caps);
8228 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
8229 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8230 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
8232 skip("Mipmapped textures not supported, skipping tests.\n");
8233 IDirectDraw4_Release(ddraw);
8234 DestroyWindow(window);
8235 return;
8238 for (i = 0; i < ARRAY_SIZE(tests); ++i)
8240 memset(&surface_desc, 0, sizeof(surface_desc));
8241 surface_desc.dwSize = sizeof(surface_desc);
8242 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
8243 surface_desc.ddsCaps.dwCaps = tests[i].caps;
8244 surface_desc.dwWidth = tests[i].width;
8245 surface_desc.dwHeight = tests[i].height;
8246 if (tests[i].flags & DDSD_MIPMAPCOUNT)
8247 U2(surface_desc).dwMipMapCount = tests[i].mipmap_count_in;
8248 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8249 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
8250 if (FAILED(hr))
8251 continue;
8253 memset(&surface_desc, 0, sizeof(surface_desc));
8254 surface_desc.dwSize = sizeof(surface_desc);
8255 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
8256 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
8257 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
8258 "Test %u: Got unexpected flags %#x.\n", i, surface_desc.dwFlags);
8259 ok(U2(surface_desc).dwMipMapCount == tests[i].mipmap_count_out,
8260 "Test %u: Got unexpected mipmap count %u.\n", i, U2(surface_desc).dwMipMapCount);
8262 surface_base = surface;
8263 IDirectDrawSurface4_AddRef(surface_base);
8264 mipmap_count = U2(surface_desc).dwMipMapCount;
8265 while (mipmap_count > 1)
8267 hr = IDirectDrawSurface4_GetAttachedSurface(surface_base, &caps, &surface_mip);
8268 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get attached surface, hr %#x.\n", i, mipmap_count, hr);
8270 memset(&surface_desc, 0, sizeof(surface_desc));
8271 surface_desc.dwSize = sizeof(surface_desc);
8272 hr = IDirectDrawSurface4_GetSurfaceDesc(surface_base, &surface_desc);
8273 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get surface desc, hr %#x.\n", i, mipmap_count, hr);
8274 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
8275 "Test %u, %u: Got unexpected flags %#x.\n", i, mipmap_count, surface_desc.dwFlags);
8276 ok(U2(surface_desc).dwMipMapCount == mipmap_count,
8277 "Test %u, %u: Got unexpected mipmap count %u.\n",
8278 i, mipmap_count, U2(surface_desc).dwMipMapCount);
8280 memset(&surface_desc, 0, sizeof(surface_desc));
8281 surface_desc.dwSize = sizeof(surface_desc);
8282 hr = IDirectDrawSurface4_Lock(surface_base, NULL, &surface_desc, 0, NULL);
8283 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#x.\n", i, mipmap_count, hr);
8284 ok(surface_desc.dwMipMapCount == mipmap_count,
8285 "Test %u, %u: unexpected change of mipmap count %u.\n",
8286 i, mipmap_count, surface_desc.dwMipMapCount);
8287 memset(&surface_desc, 0, sizeof(surface_desc));
8288 surface_desc.dwSize = sizeof(surface_desc);
8289 hr = IDirectDrawSurface4_Lock(surface_mip, NULL, &surface_desc, 0, NULL);
8290 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#x.\n", i, mipmap_count, hr);
8291 ok(surface_desc.dwMipMapCount == mipmap_count - 1,
8292 "Test %u, %u: Child mipmap count unexpected %u\n", i, mipmap_count, surface_desc.dwMipMapCount);
8293 IDirectDrawSurface4_Unlock(surface_mip, NULL);
8294 IDirectDrawSurface4_Unlock(surface_base, NULL);
8296 IDirectDrawSurface4_Release(surface_base);
8297 surface_base = surface_mip;
8298 --mipmap_count;
8300 IDirectDrawSurface4_Release(surface_base);
8302 IDirectDrawSurface4_Release(surface);
8305 refcount = IDirectDraw4_Release(ddraw);
8306 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8307 DestroyWindow(window);
8310 static void test_palette_complex(void)
8312 IDirectDrawSurface4 *surface, *mipmap, *tmp;
8313 DDSURFACEDESC2 surface_desc;
8314 IDirectDraw4 *ddraw;
8315 IDirectDrawPalette *palette, *palette2, *palette_mipmap;
8316 ULONG refcount;
8317 HWND window;
8318 HRESULT hr;
8319 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
8320 DDCAPS hal_caps;
8321 PALETTEENTRY palette_entries[256];
8322 unsigned int i;
8323 HDC dc;
8324 RGBQUAD rgbquad;
8325 UINT count;
8327 window = create_window();
8328 ddraw = create_ddraw();
8329 ok(!!ddraw, "Failed to create a ddraw object.\n");
8330 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8331 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8333 memset(&hal_caps, 0, sizeof(hal_caps));
8334 hal_caps.dwSize = sizeof(hal_caps);
8335 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
8336 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8337 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
8339 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
8340 IDirectDraw4_Release(ddraw);
8341 DestroyWindow(window);
8342 return;
8345 memset(&surface_desc, 0, sizeof(surface_desc));
8346 surface_desc.dwSize = sizeof(surface_desc);
8347 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8348 surface_desc.dwWidth = 128;
8349 surface_desc.dwHeight = 128;
8350 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
8351 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8352 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8353 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
8354 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8355 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8357 memset(palette_entries, 0, sizeof(palette_entries));
8358 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8359 palette_entries, &palette, NULL);
8360 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8362 memset(palette_entries, 0, sizeof(palette_entries));
8363 palette_entries[1].peRed = 0xff;
8364 palette_entries[1].peGreen = 0x80;
8365 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8366 palette_entries, &palette_mipmap, NULL);
8367 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8369 palette2 = (void *)0xdeadbeef;
8370 hr = IDirectDrawSurface4_GetPalette(surface, &palette2);
8371 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
8372 ok(!palette2, "Got unexpected palette %p.\n", palette2);
8373 hr = IDirectDrawSurface4_SetPalette(surface, palette);
8374 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8375 hr = IDirectDrawSurface4_GetPalette(surface, &palette2);
8376 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
8377 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
8378 IDirectDrawPalette_Release(palette2);
8380 mipmap = surface;
8381 IDirectDrawSurface4_AddRef(mipmap);
8382 for (i = 0; i < 7; ++i)
8384 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
8385 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
8386 palette2 = (void *)0xdeadbeef;
8387 hr = IDirectDrawSurface4_GetPalette(tmp, &palette2);
8388 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
8389 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
8391 hr = IDirectDrawSurface4_SetPalette(tmp, palette_mipmap);
8392 ok(SUCCEEDED(hr), "Failed to set palette, i %u, hr %#x.\n", i, hr);
8394 hr = IDirectDrawSurface4_GetPalette(tmp, &palette2);
8395 ok(SUCCEEDED(hr), "Failed to get palette, i %u, hr %#x.\n", i, hr);
8396 ok(palette_mipmap == palette2, "Got unexpected palette %p.\n", palette2);
8397 IDirectDrawPalette_Release(palette2);
8399 hr = IDirectDrawSurface4_GetDC(tmp, &dc);
8400 ok(SUCCEEDED(hr), "Failed to get DC, i %u, hr %#x.\n", i, hr);
8401 count = GetDIBColorTable(dc, 1, 1, &rgbquad);
8402 ok(count == 1, "Expected count 1, got %u.\n", count);
8403 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x.\n", rgbquad.rgbRed);
8404 ok(rgbquad.rgbGreen == 0x80, "Expected rgbGreen = 0x80, got %#x.\n", rgbquad.rgbGreen);
8405 ok(rgbquad.rgbBlue == 0x0, "Expected rgbBlue = 0x0, got %#x.\n", rgbquad.rgbBlue);
8406 hr = IDirectDrawSurface4_ReleaseDC(tmp, dc);
8407 ok(SUCCEEDED(hr), "Failed to release DC, i %u, hr %#x.\n", i, hr);
8409 IDirectDrawSurface4_Release(mipmap);
8410 mipmap = tmp;
8413 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
8414 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8415 IDirectDrawSurface4_Release(mipmap);
8416 refcount = IDirectDrawSurface4_Release(surface);
8417 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8418 refcount = IDirectDrawPalette_Release(palette_mipmap);
8419 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8420 refcount = IDirectDrawPalette_Release(palette);
8421 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8423 refcount = IDirectDraw4_Release(ddraw);
8424 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8425 DestroyWindow(window);
8428 static void test_p8_blit(void)
8430 IDirectDrawSurface4 *src, *dst, *dst_p8;
8431 DDSURFACEDESC2 surface_desc;
8432 IDirectDraw4 *ddraw;
8433 IDirectDrawPalette *palette, *palette2;
8434 ULONG refcount;
8435 HWND window;
8436 HRESULT hr;
8437 PALETTEENTRY palette_entries[256];
8438 unsigned int x;
8439 DDBLTFX fx;
8440 BOOL is_warp;
8441 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
8442 static const BYTE src_data2[] = {0x10, 0x5, 0x4, 0x3, 0x2, 0x1, 0xff, 0x80};
8443 static const BYTE expected_p8[] = {0x10, 0x1, 0x4, 0x3, 0x4, 0x5, 0xff, 0x80};
8444 static const D3DCOLOR expected[] =
8446 0x00101010, 0x00010101, 0x00020202, 0x00030303,
8447 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
8449 D3DCOLOR color;
8451 window = create_window();
8452 ddraw = create_ddraw();
8453 ok(!!ddraw, "Failed to create a ddraw object.\n");
8454 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8455 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8456 is_warp = ddraw_is_warp(ddraw);
8458 memset(palette_entries, 0, sizeof(palette_entries));
8459 palette_entries[1].peGreen = 0xff;
8460 palette_entries[2].peBlue = 0xff;
8461 palette_entries[3].peFlags = 0xff;
8462 palette_entries[4].peRed = 0xff;
8463 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8464 palette_entries, &palette, NULL);
8465 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8466 palette_entries[1].peBlue = 0xff;
8467 palette_entries[2].peGreen = 0xff;
8468 palette_entries[3].peRed = 0xff;
8469 palette_entries[4].peFlags = 0x0;
8470 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8471 palette_entries, &palette2, NULL);
8472 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8474 memset(&surface_desc, 0, sizeof(surface_desc));
8475 surface_desc.dwSize = sizeof(surface_desc);
8476 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8477 surface_desc.dwWidth = 8;
8478 surface_desc.dwHeight = 1;
8479 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8480 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8481 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8482 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
8483 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL);
8484 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8485 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_p8, NULL);
8486 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8487 hr = IDirectDrawSurface4_SetPalette(dst_p8, palette2);
8488 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8490 memset(&surface_desc, 0, sizeof(surface_desc));
8491 surface_desc.dwSize = sizeof(surface_desc);
8492 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8493 surface_desc.dwWidth = 8;
8494 surface_desc.dwHeight = 1;
8495 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8496 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8497 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
8498 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8499 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8500 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8501 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8502 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
8503 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL);
8504 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8506 memset(&surface_desc, 0, sizeof(surface_desc));
8507 surface_desc.dwSize = sizeof(surface_desc);
8508 hr = IDirectDrawSurface4_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
8509 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
8510 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
8511 hr = IDirectDrawSurface4_Unlock(src, NULL);
8512 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
8514 hr = IDirectDrawSurface4_Lock(dst_p8, NULL, &surface_desc, DDLOCK_WAIT, NULL);
8515 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
8516 memcpy(surface_desc.lpSurface, src_data2, sizeof(src_data2));
8517 hr = IDirectDrawSurface4_Unlock(dst_p8, NULL);
8518 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
8520 hr = IDirectDrawSurface4_SetPalette(src, palette);
8521 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8522 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
8523 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
8524 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
8525 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
8526 "Failed to blit, hr %#x.\n", hr);
8528 if (SUCCEEDED(hr))
8530 for (x = 0; x < ARRAY_SIZE(expected); x++)
8532 color = get_surface_color(dst, x, 0);
8533 todo_wine ok(compare_color(color, expected[x], 0),
8534 "Pixel %u: Got color %#x, expected %#x.\n",
8535 x, color, expected[x]);
8539 memset(&fx, 0, sizeof(fx));
8540 fx.dwSize = sizeof(fx);
8541 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x2;
8542 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x2;
8543 hr = IDirectDrawSurface4_Blt(dst_p8, NULL, src, NULL, DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &fx);
8544 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
8546 hr = IDirectDrawSurface4_Lock(dst_p8, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
8547 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
8548 /* A color keyed P8 blit doesn't do anything on WARP - it just leaves the data in the destination
8549 * surface untouched. P8 blits without color keys work. Error checking (DDBLT_KEYSRC without a key
8550 * for example) also works as expected.
8552 * Using DDBLT_KEYSRC instead of DDBLT_KEYSRCOVERRIDE doesn't change this. Doing this blit with
8553 * the display mode set to P8 doesn't help either. */
8554 ok(!memcmp(surface_desc.lpSurface, expected_p8, sizeof(expected_p8))
8555 || broken(is_warp && !memcmp(surface_desc.lpSurface, src_data2, sizeof(src_data2))),
8556 "Got unexpected P8 color key blit result.\n");
8557 hr = IDirectDrawSurface4_Unlock(dst_p8, NULL);
8558 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
8560 IDirectDrawSurface4_Release(src);
8561 IDirectDrawSurface4_Release(dst);
8562 IDirectDrawSurface4_Release(dst_p8);
8563 IDirectDrawPalette_Release(palette);
8564 IDirectDrawPalette_Release(palette2);
8566 refcount = IDirectDraw4_Release(ddraw);
8567 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8568 DestroyWindow(window);
8571 static void test_material(void)
8573 D3DMATERIALHANDLE mat_handle, tmp;
8574 IDirect3DMaterial3 *material;
8575 IDirect3DViewport3 *viewport;
8576 IDirect3DDevice3 *device;
8577 IDirectDrawSurface4 *rt;
8578 D3DCOLOR color;
8579 ULONG refcount;
8580 unsigned int i;
8581 HWND window;
8582 HRESULT hr;
8583 BOOL valid;
8585 static struct
8587 struct vec3 position;
8588 struct vec3 normal;
8589 D3DCOLOR diffuse;
8591 quad1[] =
8593 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
8594 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
8595 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
8596 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
8598 quad2[] =
8600 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
8601 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
8602 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
8603 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
8605 static const struct
8607 void *data;
8608 BOOL material;
8609 D3DCOLOR expected_color;
8611 test_data[] =
8613 {quad1, TRUE, 0x0000ff00},
8614 {quad2, TRUE, 0x0000ff00},
8615 {quad1, FALSE, 0x00ffffff},
8616 {quad2, FALSE, 0x00ff0000},
8618 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
8620 window = create_window();
8621 if (!(device = create_device(window, DDSCL_NORMAL)))
8623 skip("Failed to create a 3D device, skipping test.\n");
8624 DestroyWindow(window);
8625 return;
8628 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
8629 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8631 viewport = create_viewport(device, 0, 0, 640, 480);
8632 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
8633 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
8635 material = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
8636 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
8637 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
8639 hr = IDirect3DDevice3_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
8640 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
8641 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
8642 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
8643 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
8644 hr = IDirect3DDevice3_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
8645 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
8646 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
8647 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, 0);
8648 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
8649 hr = IDirect3DDevice3_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
8650 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
8651 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
8653 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
8655 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect,
8656 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
8657 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8659 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, test_data[i].material ? mat_handle : 0);
8660 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
8662 hr = IDirect3DDevice3_BeginScene(device);
8663 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8664 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
8665 D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE, test_data[i].data, 4, 0);
8666 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8667 hr = IDirect3DDevice3_EndScene(device);
8668 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8669 color = get_surface_color(rt, 320, 240);
8670 ok(compare_color(color, test_data[i].expected_color, 1),
8671 "Got unexpected color 0x%08x, test %u.\n", color, i);
8674 destroy_material(material);
8675 material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
8676 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
8677 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
8679 hr = IDirect3DViewport3_SetBackground(viewport, mat_handle);
8680 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
8681 hr = IDirect3DViewport3_GetBackground(viewport, &tmp, &valid);
8682 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
8683 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
8684 ok(valid, "Got unexpected valid %#x.\n", valid);
8685 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8686 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8687 color = get_surface_color(rt, 320, 240);
8688 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
8690 hr = IDirect3DViewport3_SetBackground(viewport, 0);
8691 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8692 hr = IDirect3DViewport3_GetBackground(viewport, &tmp, &valid);
8693 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
8694 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
8695 ok(valid, "Got unexpected valid %#x.\n", valid);
8696 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8697 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8698 color = get_surface_color(rt, 320, 240);
8699 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
8701 destroy_viewport(device, viewport);
8702 viewport = create_viewport(device, 0, 0, 640, 480);
8704 hr = IDirect3DViewport3_GetBackground(viewport, &tmp, &valid);
8705 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
8706 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
8707 ok(!valid, "Got unexpected valid %#x.\n", valid);
8708 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8709 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8710 color = get_surface_color(rt, 320, 240);
8711 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x.\n", color);
8713 destroy_viewport(device, viewport);
8714 destroy_material(material);
8715 IDirectDrawSurface4_Release(rt);
8716 refcount = IDirect3DDevice3_Release(device);
8717 ok(!refcount, "Device has %u references left.\n", refcount);
8718 DestroyWindow(window);
8721 static void test_palette_gdi(void)
8723 IDirectDrawSurface4 *surface, *primary;
8724 DDSURFACEDESC2 surface_desc;
8725 IDirectDraw4 *ddraw;
8726 IDirectDrawPalette *palette, *palette2;
8727 ULONG refcount;
8728 HWND window;
8729 HRESULT hr;
8730 PALETTEENTRY palette_entries[256];
8731 UINT i;
8732 HDC dc;
8733 DDBLTFX fx;
8734 RECT r;
8735 COLORREF color;
8736 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
8737 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
8738 * not the point of this test. */
8739 static const RGBQUAD expected1[] =
8741 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8742 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
8744 static const RGBQUAD expected2[] =
8746 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8747 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
8749 static const RGBQUAD expected3[] =
8751 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
8752 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
8754 HPALETTE ddraw_palette_handle;
8755 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
8756 RGBQUAD rgbquad[255];
8757 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
8759 window = create_window();
8760 ddraw = create_ddraw();
8761 ok(!!ddraw, "Failed to create a ddraw object.\n");
8762 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8763 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8765 memset(&surface_desc, 0, sizeof(surface_desc));
8766 surface_desc.dwSize = sizeof(surface_desc);
8767 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8768 surface_desc.dwWidth = 16;
8769 surface_desc.dwHeight = 16;
8770 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8771 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8772 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8773 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
8774 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8775 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8777 /* Avoid colors from the Windows default palette. */
8778 memset(palette_entries, 0, sizeof(palette_entries));
8779 palette_entries[1].peRed = 0x01;
8780 palette_entries[2].peGreen = 0x02;
8781 palette_entries[3].peBlue = 0x03;
8782 palette_entries[4].peRed = 0x13;
8783 palette_entries[4].peGreen = 0x14;
8784 palette_entries[4].peBlue = 0x15;
8785 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8786 palette_entries, &palette, NULL);
8787 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8789 /* If there is no palette assigned and the display mode is not 8 bpp, some
8790 * drivers refuse to create a DC while others allow it. If a DC is created,
8791 * the DIB color table is uninitialized and contains random colors. No error
8792 * is generated when trying to read pixels and random garbage is returned.
8794 * The most likely explanation is that if the driver creates a DC, it (or
8795 * the higher-level runtime) uses GetSystemPaletteEntries to find the
8796 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
8797 * contains uninitialized garbage. See comments below for the P8 case. */
8799 hr = IDirectDrawSurface4_SetPalette(surface, palette);
8800 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8801 hr = IDirectDrawSurface4_GetDC(surface, &dc);
8802 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8803 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8804 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8805 "Got unexpected palette %p, expected %p.\n",
8806 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8808 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8809 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8810 for (i = 0; i < ARRAY_SIZE(expected1); i++)
8812 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
8813 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8814 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8815 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
8817 for (; i < ARRAY_SIZE(rgbquad); i++)
8819 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8820 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8821 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8824 /* Update the palette while the DC is in use. This does not modify the DC. */
8825 palette_entries[4].peRed = 0x23;
8826 palette_entries[4].peGreen = 0x24;
8827 palette_entries[4].peBlue = 0x25;
8828 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
8829 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8831 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8832 ok(i == 1, "Expected count 1, got %u.\n", i);
8833 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8834 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8835 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8836 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8838 /* Neither does re-setting the palette. */
8839 hr = IDirectDrawSurface4_SetPalette(surface, NULL);
8840 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8841 hr = IDirectDrawSurface4_SetPalette(surface, palette);
8842 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8844 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8845 ok(i == 1, "Expected count 1, got %u.\n", i);
8846 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8847 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8848 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8849 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8851 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
8852 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8854 /* Refresh the DC. This updates the palette. */
8855 hr = IDirectDrawSurface4_GetDC(surface, &dc);
8856 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8857 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8858 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8859 for (i = 0; i < ARRAY_SIZE(expected2); i++)
8861 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8862 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8863 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8864 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8866 for (; i < ARRAY_SIZE(rgbquad); i++)
8868 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8869 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8870 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8872 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
8873 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8875 refcount = IDirectDrawSurface4_Release(surface);
8876 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8878 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
8879 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8880 if (FAILED(IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8882 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8883 IDirectDrawPalette_Release(palette);
8884 IDirectDraw4_Release(ddraw);
8885 DestroyWindow(window);
8886 return;
8888 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
8890 memset(&surface_desc, 0, sizeof(surface_desc));
8891 surface_desc.dwSize = sizeof(surface_desc);
8892 surface_desc.dwFlags = DDSD_CAPS;
8893 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8894 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
8895 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8897 memset(&fx, 0, sizeof(fx));
8898 fx.dwSize = sizeof(fx);
8899 U5(fx).dwFillColor = 3;
8900 SetRect(&r, 0, 0, 319, 479);
8901 hr = IDirectDrawSurface4_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8902 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
8903 SetRect(&r, 320, 0, 639, 479);
8904 U5(fx).dwFillColor = 4;
8905 hr = IDirectDrawSurface4_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8906 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
8908 hr = IDirectDrawSurface4_SetPalette(primary, palette);
8909 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8910 hr = IDirectDrawSurface4_GetDC(primary, &dc);
8911 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8913 color = GetPixel(dc, 160, 240);
8914 ok(color == 0x00030000, "Clear index 3: Got unexpected color 0x%08x.\n", color);
8915 color = GetPixel(dc, 480, 240);
8916 ok(color == 0x00252423, "Clear index 4: Got unexpected color 0x%08x.\n", color);
8918 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8919 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8920 "Got unexpected palette %p, expected %p.\n",
8921 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8922 SelectPalette(dc, ddraw_palette_handle, FALSE);
8924 /* The primary uses the system palette. In exclusive mode, the system palette matches
8925 * the ddraw palette attached to the primary, so the result is what you would expect
8926 * from a regular surface. Tests for the interaction between the ddraw palette and
8927 * the system palette are not included pending an application that depends on this.
8928 * The relation between those causes problems on Windows Vista and newer for games
8929 * like Age of Empires or StarCraft. Don't emulate it without a real need. */
8930 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8931 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8932 for (i = 0; i < ARRAY_SIZE(expected2); i++)
8934 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8935 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8936 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8937 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8939 for (; i < ARRAY_SIZE(rgbquad); i++)
8941 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8942 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8943 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8945 hr = IDirectDrawSurface4_ReleaseDC(primary, dc);
8946 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8948 memset(&surface_desc, 0, sizeof(surface_desc));
8949 surface_desc.dwSize = sizeof(surface_desc);
8950 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8951 surface_desc.dwWidth = 16;
8952 surface_desc.dwHeight = 16;
8953 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8954 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8955 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8957 /* Here the offscreen surface appears to use the primary's palette,
8958 * but in all likelihood it is actually the system palette. */
8959 hr = IDirectDrawSurface4_GetDC(surface, &dc);
8960 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8961 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8962 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8963 for (i = 0; i < ARRAY_SIZE(expected2); i++)
8965 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8966 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8967 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8968 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8970 for (; i < ARRAY_SIZE(rgbquad); i++)
8972 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8973 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8974 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8976 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
8977 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8979 /* On real hardware a change to the primary surface's palette applies immediately,
8980 * even on device contexts from offscreen surfaces that do not have their own
8981 * palette. On the testbot VMs this is not the case. Don't test this until we
8982 * know of an application that depends on this. */
8984 memset(palette_entries, 0, sizeof(palette_entries));
8985 palette_entries[1].peBlue = 0x40;
8986 palette_entries[2].peRed = 0x40;
8987 palette_entries[3].peGreen = 0x40;
8988 palette_entries[4].peRed = 0x12;
8989 palette_entries[4].peGreen = 0x34;
8990 palette_entries[4].peBlue = 0x56;
8991 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8992 palette_entries, &palette2, NULL);
8993 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8994 hr = IDirectDrawSurface4_SetPalette(surface, palette2);
8995 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8997 /* A palette assigned to the offscreen surface overrides the primary / system
8998 * palette. */
8999 hr = IDirectDrawSurface4_GetDC(surface, &dc);
9000 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
9001 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
9002 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
9003 for (i = 0; i < ARRAY_SIZE(expected3); i++)
9005 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
9006 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
9007 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
9008 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
9010 for (; i < ARRAY_SIZE(rgbquad); i++)
9012 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
9013 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
9014 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
9016 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
9017 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9019 refcount = IDirectDrawSurface4_Release(surface);
9020 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9022 /* The Windows 8 testbot keeps extra references to the primary and
9023 * backbuffer while in 8 bpp mode. */
9024 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
9025 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
9027 refcount = IDirectDrawSurface4_Release(primary);
9028 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9029 refcount = IDirectDrawPalette_Release(palette2);
9030 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9031 refcount = IDirectDrawPalette_Release(palette);
9032 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9033 refcount = IDirectDraw4_Release(ddraw);
9034 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9035 DestroyWindow(window);
9038 static void test_palette_alpha(void)
9040 IDirectDrawSurface4 *surface;
9041 DDSURFACEDESC2 surface_desc;
9042 IDirectDraw4 *ddraw;
9043 IDirectDrawPalette *palette;
9044 ULONG refcount;
9045 HWND window;
9046 HRESULT hr;
9047 PALETTEENTRY palette_entries[256];
9048 unsigned int i;
9049 static const struct
9051 DWORD caps, flags;
9052 BOOL attach_allowed;
9053 const char *name;
9055 test_data[] =
9057 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
9058 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
9059 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
9062 window = create_window();
9063 ddraw = create_ddraw();
9064 ok(!!ddraw, "Failed to create a ddraw object.\n");
9065 if (FAILED(IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
9067 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
9068 IDirectDraw4_Release(ddraw);
9069 DestroyWindow(window);
9070 return;
9072 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9073 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9075 memset(palette_entries, 0, sizeof(palette_entries));
9076 palette_entries[1].peFlags = 0x42;
9077 palette_entries[2].peFlags = 0xff;
9078 palette_entries[3].peFlags = 0x80;
9079 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
9080 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
9082 memset(palette_entries, 0x66, sizeof(palette_entries));
9083 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
9084 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
9085 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
9086 palette_entries[0].peFlags);
9087 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
9088 palette_entries[1].peFlags);
9089 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
9090 palette_entries[2].peFlags);
9091 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
9092 palette_entries[3].peFlags);
9094 IDirectDrawPalette_Release(palette);
9096 memset(palette_entries, 0, sizeof(palette_entries));
9097 palette_entries[1].peFlags = 0x42;
9098 palette_entries[1].peRed = 0xff;
9099 palette_entries[2].peFlags = 0xff;
9100 palette_entries[3].peFlags = 0x80;
9101 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
9102 palette_entries, &palette, NULL);
9103 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
9105 memset(palette_entries, 0x66, sizeof(palette_entries));
9106 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
9107 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
9108 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
9109 palette_entries[0].peFlags);
9110 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
9111 palette_entries[1].peFlags);
9112 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
9113 palette_entries[2].peFlags);
9114 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
9115 palette_entries[3].peFlags);
9117 for (i = 0; i < ARRAY_SIZE(test_data); i++)
9119 memset(&surface_desc, 0, sizeof(surface_desc));
9120 surface_desc.dwSize = sizeof(surface_desc);
9121 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
9122 surface_desc.dwWidth = 128;
9123 surface_desc.dwHeight = 128;
9124 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
9125 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9126 ok(SUCCEEDED(hr), "Failed to create %s surface, hr %#x.\n", test_data[i].name, hr);
9128 hr = IDirectDrawSurface4_SetPalette(surface, palette);
9129 if (test_data[i].attach_allowed)
9130 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#x.\n", test_data[i].name, hr);
9131 else
9132 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x, %s surface.\n", hr, test_data[i].name);
9134 if (SUCCEEDED(hr))
9136 HDC dc;
9137 RGBQUAD rgbquad;
9138 UINT retval;
9140 hr = IDirectDrawSurface4_GetDC(surface, &dc);
9141 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
9142 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
9143 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
9144 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
9145 rgbquad.rgbRed, test_data[i].name);
9146 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
9147 rgbquad.rgbGreen, test_data[i].name);
9148 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
9149 rgbquad.rgbBlue, test_data[i].name);
9150 ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
9151 rgbquad.rgbReserved, test_data[i].name);
9152 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
9153 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9155 IDirectDrawSurface4_Release(surface);
9158 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
9159 memset(&surface_desc, 0, sizeof(surface_desc));
9160 surface_desc.dwSize = sizeof(surface_desc);
9161 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9162 surface_desc.dwWidth = 128;
9163 surface_desc.dwHeight = 128;
9164 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9165 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9166 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
9167 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9168 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9169 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9170 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9171 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9172 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9173 hr = IDirectDrawSurface4_SetPalette(surface, palette);
9174 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
9175 IDirectDrawSurface4_Release(surface);
9177 /* The Windows 8 testbot keeps extra references to the primary
9178 * while in 8 bpp mode. */
9179 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
9180 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
9182 refcount = IDirectDrawPalette_Release(palette);
9183 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9184 refcount = IDirectDraw4_Release(ddraw);
9185 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9186 DestroyWindow(window);
9189 static void test_vb_writeonly(void)
9191 IDirect3DDevice3 *device;
9192 IDirect3D3 *d3d;
9193 IDirect3DVertexBuffer *buffer;
9194 HWND window;
9195 HRESULT hr;
9196 D3DVERTEXBUFFERDESC desc;
9197 void *ptr;
9198 static const struct vec4 quad[] =
9200 { 0.0f, 480.0f, 0.0f, 1.0f},
9201 { 0.0f, 0.0f, 0.0f, 1.0f},
9202 {640.0f, 480.0f, 0.0f, 1.0f},
9203 {640.0f, 0.0f, 0.0f, 1.0f},
9206 window = create_window();
9207 if (!(device = create_device(window, DDSCL_NORMAL)))
9209 skip("Failed to create a 3D device, skipping test.\n");
9210 DestroyWindow(window);
9211 return;
9214 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
9215 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9217 memset(&desc, 0, sizeof(desc));
9218 desc.dwSize = sizeof(desc);
9219 desc.dwCaps = D3DVBCAPS_WRITEONLY;
9220 desc.dwFVF = D3DFVF_XYZRHW;
9221 desc.dwNumVertices = ARRAY_SIZE(quad);
9222 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &buffer, 0, NULL);
9223 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
9225 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, &ptr, NULL);
9226 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
9227 memcpy(ptr, quad, sizeof(quad));
9228 hr = IDirect3DVertexBuffer_Unlock(buffer);
9229 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
9231 hr = IDirect3DDevice3_BeginScene(device);
9232 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9233 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
9234 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9235 hr = IDirect3DDevice3_EndScene(device);
9236 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9238 hr = IDirect3DVertexBuffer_Lock(buffer, 0, &ptr, NULL);
9239 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
9240 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
9241 hr = IDirect3DVertexBuffer_Unlock(buffer);
9242 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
9244 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_READONLY, &ptr, NULL);
9245 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
9246 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
9247 hr = IDirect3DVertexBuffer_Unlock(buffer);
9248 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
9250 IDirect3DVertexBuffer_Release(buffer);
9251 IDirect3D3_Release(d3d);
9252 IDirect3DDevice3_Release(device);
9253 DestroyWindow(window);
9256 static void test_lost_device(void)
9258 IDirectDrawSurface4 *surface;
9259 DDSURFACEDESC2 surface_desc;
9260 HWND window1, window2;
9261 IDirectDraw4 *ddraw;
9262 ULONG refcount;
9263 HRESULT hr;
9264 BOOL ret;
9266 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9267 0, 0, 640, 480, 0, 0, 0, 0);
9268 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9269 0, 0, 640, 480, 0, 0, 0, 0);
9270 ddraw = create_ddraw();
9271 ok(!!ddraw, "Failed to create a ddraw object.\n");
9272 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9273 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9275 memset(&surface_desc, 0, sizeof(surface_desc));
9276 surface_desc.dwSize = sizeof(surface_desc);
9277 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
9278 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
9279 U5(surface_desc).dwBackBufferCount = 1;
9280 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9281 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9283 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
9284 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9285 hr = IDirectDrawSurface4_IsLost(surface);
9286 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9287 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
9288 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9290 ret = SetForegroundWindow(GetDesktopWindow());
9291 ok(ret, "Failed to set foreground window.\n");
9292 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
9293 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9294 hr = IDirectDrawSurface4_IsLost(surface);
9295 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9296 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
9297 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9299 ret = SetForegroundWindow(window1);
9300 ok(ret, "Failed to set foreground window.\n");
9301 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
9302 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9303 hr = IDirectDrawSurface4_IsLost(surface);
9304 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9305 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
9306 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9308 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
9309 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9310 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
9311 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9312 hr = IDirectDrawSurface4_IsLost(surface);
9313 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9314 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
9315 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9317 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
9318 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9319 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
9320 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9321 hr = IDirectDrawSurface4_IsLost(surface);
9322 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9323 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
9324 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9326 /* Trying to restore the primary will crash, probably because flippable
9327 * surfaces can't exist in DDSCL_NORMAL. */
9328 IDirectDrawSurface4_Release(surface);
9329 memset(&surface_desc, 0, sizeof(surface_desc));
9330 surface_desc.dwSize = sizeof(surface_desc);
9331 surface_desc.dwFlags = DDSD_CAPS;
9332 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
9333 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9334 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9336 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
9337 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9338 hr = IDirectDrawSurface4_IsLost(surface);
9339 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9341 ret = SetForegroundWindow(GetDesktopWindow());
9342 ok(ret, "Failed to set foreground window.\n");
9343 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
9344 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9345 hr = IDirectDrawSurface4_IsLost(surface);
9346 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9348 ret = SetForegroundWindow(window1);
9349 ok(ret, "Failed to set foreground window.\n");
9350 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
9351 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9352 hr = IDirectDrawSurface4_IsLost(surface);
9353 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9355 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9356 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9357 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
9358 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9359 hr = IDirectDrawSurface4_IsLost(surface);
9360 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9362 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
9363 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9364 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
9365 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9366 hr = IDirectDrawSurface4_IsLost(surface);
9367 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9369 IDirectDrawSurface4_Release(surface);
9370 memset(&surface_desc, 0, sizeof(surface_desc));
9371 surface_desc.dwSize = sizeof(surface_desc);
9372 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
9373 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
9374 U5(surface_desc).dwBackBufferCount = 1;
9375 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9376 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9378 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9379 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9380 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
9381 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9382 hr = IDirectDrawSurface4_IsLost(surface);
9383 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9384 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
9385 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9387 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
9388 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9389 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
9390 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9391 hr = IDirectDrawSurface4_IsLost(surface);
9392 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9393 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
9394 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9396 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
9397 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9398 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
9399 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9400 hr = IDirectDrawSurface4_IsLost(surface);
9401 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9402 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
9403 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9405 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
9406 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9407 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
9408 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9409 hr = IDirectDrawSurface4_IsLost(surface);
9410 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9411 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
9412 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9414 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
9415 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9416 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
9417 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9418 hr = IDirectDrawSurface4_IsLost(surface);
9419 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9420 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
9421 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9423 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9424 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9425 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
9426 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9427 hr = IDirectDrawSurface4_IsLost(surface);
9428 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9429 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
9430 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9432 IDirectDrawSurface4_Release(surface);
9433 refcount = IDirectDraw4_Release(ddraw);
9434 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9435 DestroyWindow(window2);
9436 DestroyWindow(window1);
9439 static void test_surface_desc_lock(void)
9441 IDirectDrawSurface4 *surface;
9442 DDSURFACEDESC2 surface_desc;
9443 IDirectDraw4 *ddraw;
9444 ULONG refcount;
9445 HWND window;
9446 HRESULT hr;
9448 window = create_window();
9449 ddraw = create_ddraw();
9450 ok(!!ddraw, "Failed to create a ddraw object.\n");
9451 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9452 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9454 memset(&surface_desc, 0, sizeof(surface_desc));
9455 surface_desc.dwSize = sizeof(surface_desc);
9456 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
9457 surface_desc.dwWidth = 16;
9458 surface_desc.dwHeight = 16;
9459 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9460 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9461 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9463 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9464 surface_desc.dwSize = sizeof(surface_desc);
9465 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
9466 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9467 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9469 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9470 surface_desc.dwSize = sizeof(surface_desc);
9471 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, 0, NULL);
9472 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9473 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9474 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9475 surface_desc.dwSize = sizeof(surface_desc);
9476 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
9477 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9478 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9479 hr = IDirectDrawSurface4_Unlock(surface, NULL);
9480 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9482 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9483 surface_desc.dwSize = sizeof(surface_desc);
9484 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
9485 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9486 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9488 IDirectDrawSurface4_Release(surface);
9489 refcount = IDirectDraw4_Release(ddraw);
9490 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9491 DestroyWindow(window);
9494 static void test_texturemapblend(void)
9496 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
9497 static RECT rect = {0, 0, 64, 128};
9498 IDirectDrawSurface4 *surface, *rt;
9499 IDirect3DViewport3 *viewport;
9500 DDSURFACEDESC2 surface_desc;
9501 IDirect3DTexture2 *texture;
9502 IDirect3DDevice3 *device;
9503 DWORD texturemapblend;
9504 IDirectDraw4 *ddraw;
9505 IDirect3D3 *d3d;
9506 DDCOLORKEY ckey;
9507 D3DCOLOR color;
9508 ULONG refcount;
9509 DWORD value;
9510 HWND window;
9511 DDBLTFX fx;
9512 HRESULT hr;
9514 static struct
9516 struct vec4 position;
9517 D3DCOLOR diffuse;
9518 struct vec2 texcoord;
9520 test1_quads[] =
9522 {{ 0.0f, 0.0f, 0.0f, 1.0f}, 0xffffffff, {0.0f, 0.0f}},
9523 {{ 0.0f, 240.0f, 0.0f, 1.0f}, 0xffffffff, {0.0f, 1.0f}},
9524 {{640.0f, 0.0f, 0.0f, 1.0f}, 0xffffffff, {1.0f, 0.0f}},
9525 {{640.0f, 240.0f, 0.0f, 1.0f}, 0xffffffff, {1.0f, 1.0f}},
9526 {{ 0.0f, 240.0f, 0.0f, 1.0f}, 0x80ffffff, {0.0f, 0.0f}},
9527 {{ 0.0f, 480.0f, 0.0f, 1.0f}, 0x80ffffff, {0.0f, 1.0f}},
9528 {{640.0f, 240.0f, 0.0f, 1.0f}, 0x80ffffff, {1.0f, 0.0f}},
9529 {{640.0f, 480.0f, 0.0f, 1.0f}, 0x80ffffff, {1.0f, 1.0f}},
9531 test2_quads[] =
9533 {{ 0.0f, 0.0f, 0.0f, 1.0f}, 0x00ff0080, {0.0f, 0.0f}},
9534 {{ 0.0f, 240.0f, 0.0f, 1.0f}, 0x00ff0080, {0.0f, 1.0f}},
9535 {{640.0f, 0.0f, 0.0f, 1.0f}, 0x00ff0080, {1.0f, 0.0f}},
9536 {{640.0f, 240.0f, 0.0f, 1.0f}, 0x00ff0080, {1.0f, 1.0f}},
9537 {{ 0.0f, 240.0f, 0.0f, 1.0f}, 0x008000ff, {0.0f, 0.0f}},
9538 {{ 0.0f, 480.0f, 0.0f, 1.0f}, 0x008000ff, {0.0f, 1.0f}},
9539 {{640.0f, 240.0f, 0.0f, 1.0f}, 0x008000ff, {1.0f, 0.0f}},
9540 {{640.0f, 480.0f, 0.0f, 1.0f}, 0x008000ff, {1.0f, 1.0f}},
9543 window = create_window();
9544 if (!(device = create_device(window, DDSCL_NORMAL)))
9546 skip("Failed to create a 3D device, skipping test.\n");
9547 DestroyWindow(window);
9548 return;
9551 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
9552 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9553 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
9554 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9555 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
9556 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9558 viewport = create_viewport(device, 0, 0, 640, 480);
9559 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
9560 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9562 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, &texturemapblend);
9563 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9564 ok(texturemapblend == D3DTBLEND_MODULATE, "Got unexpected texture map blend %#x.\n", texturemapblend);
9566 hr = IDirect3DDevice3_GetTextureStageState(device, 0, D3DTSS_ALPHAOP, &value);
9567 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9568 ok(value == D3DTOP_SELECTARG1, "Got unexpected D3DTSS_ALPHAOP value %#x.\n", value);
9570 /* Test alpha with DDPF_ALPHAPIXELS texture - should be taken from texture
9571 * alpha channel.
9573 * The vertex alpha is completely ignored in this case, so case 1 and 2
9574 * combined are not a D3DTOP_MODULATE with texture alpha = 0xff in case 2
9575 * (no alpha in texture). */
9576 memset(&surface_desc, 0, sizeof(surface_desc));
9577 surface_desc.dwSize = sizeof(surface_desc);
9578 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9579 surface_desc.dwHeight = 128;
9580 surface_desc.dwWidth = 128;
9581 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9582 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9583 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
9584 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9585 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9586 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9587 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9588 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
9589 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9590 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9592 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9593 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9594 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
9595 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9597 hr = IDirect3DDevice3_GetTextureStageState(device, 0, D3DTSS_ALPHAOP, &value);
9598 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9599 ok(value == D3DTOP_SELECTARG1, "Got unexpected D3DTSS_ALPHAOP value %#x.\n", value);
9601 hr = IDirect3DDevice3_SetTexture(device, 0, NULL);
9602 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9604 hr = IDirect3DDevice3_GetTextureStageState(device, 0, D3DTSS_ALPHAOP, &value);
9605 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9606 ok(value == D3DTOP_SELECTARG1, "Got unexpected D3DTSS_ALPHAOP value %#x.\n", value);
9608 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
9609 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9611 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9612 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9614 memset(&fx, 0, sizeof(fx));
9615 fx.dwSize = sizeof(fx);
9616 U5(fx).dwFillColor = 0xff0000ff;
9617 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9618 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9619 U5(fx).dwFillColor = 0x800000ff;
9620 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9621 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9623 /* Note that the ddraw1 version of this test runs tests 1-3 with
9624 * D3DRENDERSTATE_COLORKEYENABLE enabled, whereas this version only runs
9625 * test 4 with color keying on. Because no color key is set on the texture
9626 * this should not result in different behavior. */
9627 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
9628 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9629 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
9630 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9631 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
9632 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9633 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
9634 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9635 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
9636 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9638 #if 0
9639 /* Disable the call to test that the device has this state by default. */
9640 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
9641 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9642 #endif
9644 /* Texture stage state does not change so legacy texture blending stays enabled. */
9645 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
9646 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9648 hr = IDirect3DDevice3_BeginScene(device);
9649 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9650 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9651 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[0], 4, 0);
9652 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9653 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9654 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[4], 4, 0);
9655 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9656 hr = IDirect3DDevice3_EndScene(device);
9657 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9659 color = get_surface_color(rt, 5, 5);
9660 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9661 color = get_surface_color(rt, 400, 5);
9662 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9663 color = get_surface_color(rt, 5, 245);
9664 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9665 color = get_surface_color(rt, 400, 245);
9666 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9668 /* Turn legacy texture blending off. */
9669 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
9670 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9671 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
9672 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9673 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9674 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9675 hr = IDirect3DDevice3_BeginScene(device);
9676 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9677 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9678 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[0], 4, 0);
9679 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9680 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9681 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[4], 4, 0);
9682 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9683 hr = IDirect3DDevice3_EndScene(device);
9684 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9686 color = get_surface_color(rt, 5, 5);
9687 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9688 color = get_surface_color(rt, 400, 5);
9689 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9690 color = get_surface_color(rt, 5, 245);
9691 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9692 color = get_surface_color(rt, 400, 245);
9693 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9695 /* This doesn't turn legacy texture blending on again, as setting the same
9696 * _TEXTUREMAPBLEND value. */
9697 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
9698 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9699 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
9700 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9701 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9702 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9703 hr = IDirect3DDevice3_BeginScene(device);
9704 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9705 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9706 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[0], 4, 0);
9707 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9708 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9709 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[4], 4, 0);
9710 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9711 hr = IDirect3DDevice3_EndScene(device);
9712 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9714 color = get_surface_color(rt, 5, 5);
9715 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9716 color = get_surface_color(rt, 400, 5);
9717 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9718 color = get_surface_color(rt, 5, 245);
9719 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9720 color = get_surface_color(rt, 400, 245);
9721 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9723 /* Turn legacy texture blending on again. */
9724 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_ADD);
9725 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9726 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
9727 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9728 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
9729 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9730 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9731 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9732 hr = IDirect3DDevice3_BeginScene(device);
9733 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9734 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9735 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[0], 4, 0);
9736 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9737 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9738 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[4], 4, 0);
9739 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9740 hr = IDirect3DDevice3_EndScene(device);
9741 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9743 color = get_surface_color(rt, 5, 5);
9744 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9745 color = get_surface_color(rt, 400, 5);
9746 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9747 color = get_surface_color(rt, 5, 245);
9748 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9749 color = get_surface_color(rt, 400, 245);
9750 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9752 hr = IDirect3DDevice3_SetTexture(device, 0, NULL);
9753 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9754 IDirect3DTexture2_Release(texture);
9755 refcount = IDirectDrawSurface4_Release(surface);
9756 ok(!refcount, "Surface not properly released, refcount %u.\n", refcount);
9758 /* Test alpha with texture that has no alpha channel - alpha should be
9759 * taken from diffuse vertex color. */
9760 memset(&surface_desc, 0, sizeof(surface_desc));
9761 surface_desc.dwSize = sizeof(surface_desc);
9762 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9763 surface_desc.dwHeight = 128;
9764 surface_desc.dwWidth = 128;
9765 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9766 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9767 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
9768 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9769 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9770 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9771 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9773 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9774 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9776 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9777 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9778 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
9779 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9781 hr = IDirect3DDevice3_GetTextureStageState(device, 0, D3DTSS_ALPHAOP, &value);
9782 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9783 ok(value == D3DTOP_SELECTARG2, "Got unexpected D3DTSS_ALPHAOP value %#x.\n", value);
9785 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9786 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9788 U5(fx).dwFillColor = 0xff0000ff;
9789 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9790 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9791 U5(fx).dwFillColor = 0x800000ff;
9792 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9793 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9795 hr = IDirect3DDevice3_BeginScene(device);
9796 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9797 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9798 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[0], 4, 0);
9799 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9800 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9801 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[4], 4, 0);
9802 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9803 hr = IDirect3DDevice3_EndScene(device);
9804 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9806 color = get_surface_color(rt, 5, 5);
9807 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9808 color = get_surface_color(rt, 400, 5);
9809 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9810 color = get_surface_color(rt, 5, 245);
9811 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9812 color = get_surface_color(rt, 400, 245);
9813 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9815 hr = IDirect3DDevice3_SetTexture(device, 0, NULL);
9816 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9817 IDirect3DTexture2_Release(texture);
9818 refcount = IDirectDrawSurface4_Release(surface);
9819 ok(!refcount, "Surface not properly released, refcount %u.\n", refcount);
9821 /* Test RGB - should multiply color components from diffuse vertex color
9822 * and texture. */
9823 memset(&surface_desc, 0, sizeof(surface_desc));
9824 surface_desc.dwSize = sizeof(surface_desc);
9825 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9826 surface_desc.dwHeight = 128;
9827 surface_desc.dwWidth = 128;
9828 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9829 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9830 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
9831 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9832 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9833 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9834 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9835 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
9836 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9837 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9839 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9840 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
9841 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
9842 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9844 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9845 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
9847 U5(fx).dwFillColor = 0x00ffffff;
9848 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9849 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9850 U5(fx).dwFillColor = 0x00ffff80;
9851 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9852 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9854 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
9855 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9857 hr = IDirect3DDevice3_BeginScene(device);
9858 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9859 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9860 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test2_quads[0], 4, 0);
9861 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9862 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9863 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test2_quads[4], 4, 0);
9864 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9865 hr = IDirect3DDevice3_EndScene(device);
9866 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9868 color = get_surface_color(rt, 5, 5);
9869 ok(compare_color(color, 0x00ff0040, 2), "Got unexpected color 0x%08x.\n", color);
9870 color = get_surface_color(rt, 400, 5);
9871 ok(compare_color(color, 0x00ff0080, 2), "Got unexpected color 0x%08x.\n", color);
9872 color = get_surface_color(rt, 5, 245);
9873 ok(compare_color(color, 0x00800080, 2), "Got unexpected color 0x%08x.\n", color);
9874 color = get_surface_color(rt, 400, 245);
9875 ok(compare_color(color, 0x008000ff, 2), "Got unexpected color 0x%08x.\n", color);
9877 hr = IDirect3DDevice3_SetTexture(device, 0, NULL);
9878 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9879 IDirect3DTexture2_Release(texture);
9880 refcount = IDirectDrawSurface4_Release(surface);
9881 ok(!refcount, "Surface not properly released, refcount %u.\n", refcount);
9883 /* Test alpha again, now with color keyed texture (colorkey emulation in
9884 * wine can interfere). */
9885 memset(&surface_desc, 0, sizeof(surface_desc));
9886 surface_desc.dwSize = sizeof(surface_desc);
9887 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9888 surface_desc.dwHeight = 128;
9889 surface_desc.dwWidth = 128;
9890 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9891 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9892 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
9893 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
9894 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
9895 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
9896 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
9898 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9899 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9901 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9902 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
9903 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
9904 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9906 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9907 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
9909 U5(fx).dwFillColor = 0xf800;
9910 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9911 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9912 U5(fx).dwFillColor = 0x001f;
9913 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9914 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9916 ckey.dwColorSpaceLowValue = 0x001f;
9917 ckey.dwColorSpaceHighValue = 0x001f;
9918 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9919 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
9921 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
9922 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9923 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
9924 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9926 hr = IDirect3DDevice3_BeginScene(device);
9927 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9928 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9929 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[0], 4, 0);
9930 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9931 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9932 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[4], 4, 0);
9933 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9934 hr = IDirect3DDevice3_EndScene(device);
9935 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9937 color = get_surface_color(rt, 5, 5);
9938 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
9939 color = get_surface_color(rt, 400, 5);
9940 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
9941 color = get_surface_color(rt, 5, 245);
9942 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
9943 color = get_surface_color(rt, 400, 245);
9944 ok(compare_color(color, 0x00800000, 2), "Got unexpected color 0x%08x.\n", color);
9946 hr = IDirect3DDevice3_SetTexture(device, 0, NULL);
9947 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9948 IDirect3DTexture2_Release(texture);
9949 refcount = IDirectDrawSurface4_Release(surface);
9950 ok(!refcount, "Surface not properly released, refcount %u.\n", refcount);
9952 destroy_viewport(device, viewport);
9953 IDirectDrawSurface4_Release(rt);
9954 IDirect3DDevice3_Release(device);
9955 IDirect3D3_Release(d3d);
9956 refcount = IDirectDraw4_Release(ddraw);
9957 ok(!refcount, "Ddraw object not properly released, refcount %u.\n", refcount);
9958 DestroyWindow(window);
9961 static void test_signed_formats(void)
9963 HRESULT hr;
9964 IDirect3DDevice3 *device;
9965 IDirect3D3 *d3d;
9966 IDirectDraw4 *ddraw;
9967 IDirectDrawSurface4 *surface, *rt;
9968 IDirect3DTexture2 *texture;
9969 IDirect3DViewport3 *viewport;
9970 DDSURFACEDESC2 surface_desc;
9971 ULONG refcount;
9972 HWND window;
9973 D3DCOLOR color, expected_color;
9974 D3DRECT clear_rect;
9975 static struct
9977 struct vec3 position;
9978 struct vec2 texcoord;
9980 quad[] =
9982 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
9983 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
9984 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
9985 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
9987 /* See test_signed_formats() in dlls/d3d9/tests/visual.c for an explanation
9988 * of these values. */
9989 static const USHORT content_v8u8[4][4] =
9991 {0x0000, 0x7f7f, 0x8880, 0x0000},
9992 {0x0080, 0x8000, 0x7f00, 0x007f},
9993 {0x193b, 0xe8c8, 0x0808, 0xf8f8},
9994 {0x4444, 0xc0c0, 0xa066, 0x22e0},
9996 static const DWORD content_x8l8v8u8[4][4] =
9998 {0x00000000, 0x00ff7f7f, 0x00008880, 0x00ff0000},
9999 {0x00000080, 0x00008000, 0x00007f00, 0x0000007f},
10000 {0x0041193b, 0x0051e8c8, 0x00040808, 0x00fff8f8},
10001 {0x00824444, 0x0000c0c0, 0x00c2a066, 0x009222e0},
10003 static const USHORT content_l6v5u5[4][4] =
10005 {0x0000, 0xfdef, 0x0230, 0xfc00},
10006 {0x0010, 0x0200, 0x01e0, 0x000f},
10007 {0x4067, 0x53b9, 0x0421, 0xffff},
10008 {0x8108, 0x0318, 0xc28c, 0x909c},
10010 static const struct
10012 const char *name;
10013 const void *content;
10014 SIZE_T pixel_size;
10015 BOOL blue;
10016 unsigned int slop, slop_broken;
10017 DDPIXELFORMAT format;
10019 formats[] =
10022 "D3DFMT_V8U8", content_v8u8, sizeof(WORD), FALSE, 1, 0,
10024 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV, 0,
10025 {16}, {0x000000ff}, {0x0000ff00}, {0x00000000}, {0x00000000}
10029 "D3DFMT_X8L8V8U8", content_x8l8v8u8, sizeof(DWORD), TRUE, 1, 0,
10031 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
10032 {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}
10036 "D3DFMT_L6V5U5", content_l6v5u5, sizeof(WORD), TRUE, 4, 7,
10038 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
10039 {16}, {0x0000001f}, {0x000003e0}, {0x0000fc00}, {0x00000000}
10043 /* No V16U16 or Q8W8V8U8 support in ddraw. */
10045 static const D3DCOLOR expected_colors[4][4] =
10047 {0x00808080, 0x00fefeff, 0x00010780, 0x008080ff},
10048 {0x00018080, 0x00800180, 0x0080fe80, 0x00fe8080},
10049 {0x00ba98a0, 0x004767a8, 0x00888881, 0x007878ff},
10050 {0x00c3c3c0, 0x003f3f80, 0x00e51fe1, 0x005fa2c8},
10052 unsigned int i, width, x, y;
10053 D3DDEVICEDESC device_desc, hel_desc;
10055 window = create_window();
10056 if (!(device = create_device(window, DDSCL_NORMAL)))
10058 skip("Failed to create a 3D device, skipping test.\n");
10059 DestroyWindow(window);
10060 return;
10063 memset(&device_desc, 0, sizeof(device_desc));
10064 device_desc.dwSize = sizeof(device_desc);
10065 memset(&hel_desc, 0, sizeof(hel_desc));
10066 hel_desc.dwSize = sizeof(hel_desc);
10067 hr = IDirect3DDevice3_GetCaps(device, &device_desc, &hel_desc);
10068 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10069 if (!(device_desc.dwTextureOpCaps & D3DTEXOPCAPS_BLENDFACTORALPHA))
10071 skip("D3DTOP_BLENDFACTORALPHA not supported, skipping bumpmap format tests.\n");
10072 goto done;
10075 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
10076 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
10077 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
10078 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
10079 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
10080 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10082 memset(&surface_desc, 0, sizeof(surface_desc));
10083 surface_desc.dwSize = sizeof(surface_desc);
10084 hr = IDirectDrawSurface4_GetSurfaceDesc(rt, &surface_desc);
10085 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
10086 viewport = create_viewport(device, 0, 0, surface_desc.dwWidth, surface_desc.dwHeight);
10087 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
10088 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
10089 U1(clear_rect).x1 = 0;
10090 U2(clear_rect).y1 = 0;
10091 U3(clear_rect).x2 = surface_desc.dwWidth;
10092 U4(clear_rect).y2 = surface_desc.dwHeight;
10094 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
10095 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10097 /* dst = tex * 0.5 + 1.0 * (1.0 - 0.5) = tex * 0.5 + 0.5 */
10098 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x80ffffff);
10099 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10100 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BLENDFACTORALPHA);
10101 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
10102 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10103 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
10104 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
10105 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
10107 for (i = 0; i < ARRAY_SIZE(formats); i++)
10109 for (width = 1; width < 5; width += 3)
10111 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
10112 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
10114 memset(&surface_desc, 0, sizeof(surface_desc));
10115 surface_desc.dwSize = sizeof(surface_desc);
10116 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
10117 surface_desc.dwWidth = width;
10118 surface_desc.dwHeight = 4;
10119 U4(surface_desc).ddpfPixelFormat = formats[i].format;
10120 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
10121 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10122 if (FAILED(hr))
10124 skip("%s textures not supported, skipping.\n", formats[i].name);
10125 continue;
10127 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, format %s.\n", hr, formats[i].name);
10129 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
10130 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture2 interface, hr %#x, format %s.\n",
10131 hr, formats[i].name);
10132 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
10133 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x, format %s.\n", hr, formats[i].name);
10134 IDirect3DTexture2_Release(texture);
10136 memset(&surface_desc, 0, sizeof(surface_desc));
10137 surface_desc.dwSize = sizeof(surface_desc);
10138 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, 0, NULL);
10139 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, format %s.\n", hr, formats[i].name);
10140 for (y = 0; y < 4; y++)
10142 memcpy((char *)surface_desc.lpSurface + y * U1(surface_desc).lPitch,
10143 (char *)formats[i].content + y * 4 * formats[i].pixel_size,
10144 width * formats[i].pixel_size);
10146 hr = IDirectDrawSurface4_Unlock(surface, NULL);
10147 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, format %s.\n", hr, formats[i].name);
10149 hr = IDirect3DDevice3_BeginScene(device);
10150 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10151 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
10152 D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
10153 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10154 hr = IDirect3DDevice3_EndScene(device);
10155 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10157 for (y = 0; y < 4; y++)
10159 for (x = 0; x < width; x++)
10161 expected_color = expected_colors[y][x];
10162 if (!formats[i].blue)
10163 expected_color |= 0x000000ff;
10165 color = get_surface_color(rt, 80 + 160 * x, 60 + 120 * y);
10166 ok(compare_color(color, expected_color, formats[i].slop)
10167 || broken(compare_color(color, expected_color, formats[i].slop_broken)),
10168 "Expected color 0x%08x, got 0x%08x, format %s, location %ux%u.\n",
10169 expected_color, color, formats[i].name, x, y);
10173 IDirectDrawSurface4_Release(surface);
10177 destroy_viewport(device, viewport);
10178 IDirectDrawSurface4_Release(rt);
10179 IDirectDraw4_Release(ddraw);
10180 IDirect3D3_Release(d3d);
10182 done:
10183 refcount = IDirect3DDevice3_Release(device);
10184 ok(!refcount, "Device has %u references left.\n", refcount);
10185 DestroyWindow(window);
10188 static void test_color_fill(void)
10190 HRESULT hr;
10191 IDirect3DDevice3 *device;
10192 IDirect3D3 *d3d;
10193 IDirectDraw4 *ddraw;
10194 IDirectDrawSurface4 *surface, *surface2;
10195 DDSURFACEDESC2 surface_desc;
10196 DDPIXELFORMAT z_fmt;
10197 ULONG refcount;
10198 HWND window;
10199 unsigned int i;
10200 DDBLTFX fx;
10201 RECT rect = {5, 5, 7, 7};
10202 DWORD *color;
10203 DWORD supported_fmts = 0, num_fourcc_codes, *fourcc_codes;
10204 DDCAPS hal_caps;
10205 static const struct
10207 DWORD caps, caps2;
10208 HRESULT colorfill_hr, depthfill_hr;
10209 BOOL rop_success;
10210 const char *name;
10211 DWORD result;
10212 BOOL check_result;
10213 DDPIXELFORMAT format;
10215 tests[] =
10218 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
10219 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
10221 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10222 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
10226 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
10227 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
10229 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10230 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
10234 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
10235 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
10237 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10238 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
10242 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
10243 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
10245 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10246 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
10250 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
10251 DD_OK, DDERR_INVALIDPARAMS, TRUE, "managed texture RGB", 0xdeadbeef, TRUE,
10253 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10254 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
10258 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY, 0,
10259 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0xdeadbeef, TRUE,
10260 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
10263 DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY, 0,
10264 DDERR_INVALIDPARAMS, DD_OK, TRUE, "sysmem zbuffer", 0xdeadbeef, TRUE,
10265 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
10268 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
10269 * different afterwards. DX9+ GPUs set one of the two luminance values
10270 * in each block, but AMD and Nvidia GPUs disagree on which luminance
10271 * value they set. r200 (dx8) just sets the entire block to the clear
10272 * value. */
10273 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
10274 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
10276 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
10277 {0}, {0}, {0}, {0}, {0}
10281 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
10282 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
10284 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
10285 {0}, {0}, {0}, {0}, {0}
10289 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
10290 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
10292 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
10293 {0}, {0}, {0}, {0}, {0}
10297 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
10298 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
10300 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
10301 {0}, {0}, {0}, {0}, {0}
10305 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
10306 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
10308 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
10309 {0}, {0}, {0}, {0}, {0}
10313 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
10314 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
10316 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
10317 {0}, {0}, {0}, {0}, {0}
10321 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
10322 * surface works, presumably because it is handled by the runtime instead of
10323 * the driver. */
10324 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
10325 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
10327 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
10328 {8}, {0}, {0}, {0}, {0}
10332 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
10333 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
10335 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
10336 {8}, {0}, {0}, {0}, {0}
10340 static const struct
10342 DWORD rop;
10343 const char *name;
10344 HRESULT hr;
10346 rops[] =
10348 {SRCCOPY, "SRCCOPY", DD_OK},
10349 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
10350 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
10351 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
10352 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
10353 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
10354 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
10355 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
10356 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
10357 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
10358 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
10359 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
10360 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
10361 {BLACKNESS, "BLACKNESS", DD_OK},
10362 {WHITENESS, "WHITENESS", DD_OK},
10363 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
10366 window = create_window();
10367 if (!(device = create_device(window, DDSCL_NORMAL)))
10369 skip("Failed to create a 3D device, skipping test.\n");
10370 DestroyWindow(window);
10371 return;
10374 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
10375 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
10376 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
10377 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
10379 memset(&z_fmt, 0, sizeof(z_fmt));
10380 IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
10381 if (!z_fmt.dwSize)
10382 skip("No Z buffer formats supported, skipping Z buffer colorfill test.\n");
10384 IDirect3DDevice3_EnumTextureFormats(device, test_block_formats_creation_cb, &supported_fmts);
10385 if (!(supported_fmts & SUPPORT_DXT1))
10386 skip("DXT1 textures not supported, skipping DXT1 colorfill test.\n");
10388 IDirect3D3_Release(d3d);
10390 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
10391 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
10392 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
10393 num_fourcc_codes * sizeof(*fourcc_codes));
10394 if (!fourcc_codes)
10395 goto done;
10396 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
10397 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
10398 for (i = 0; i < num_fourcc_codes; i++)
10400 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
10401 supported_fmts |= SUPPORT_YUY2;
10402 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
10403 supported_fmts |= SUPPORT_UYVY;
10405 HeapFree(GetProcessHeap(), 0, fourcc_codes);
10407 memset(&hal_caps, 0, sizeof(hal_caps));
10408 hal_caps.dwSize = sizeof(hal_caps);
10409 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
10410 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
10412 if (!(supported_fmts & (SUPPORT_YUY2 | SUPPORT_UYVY)) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
10413 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
10415 for (i = 0; i < ARRAY_SIZE(tests); i++)
10417 DWORD expected_broken = tests[i].result;
10419 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
10420 memset(&fx, 0, sizeof(fx));
10421 fx.dwSize = sizeof(fx);
10422 U5(fx).dwFillColor = 0xdeadbeef;
10424 memset(&surface_desc, 0, sizeof(surface_desc));
10425 surface_desc.dwSize = sizeof(surface_desc);
10426 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10427 surface_desc.dwWidth = 64;
10428 surface_desc.dwHeight = 64;
10429 U4(surface_desc).ddpfPixelFormat = tests[i].format;
10430 surface_desc.ddsCaps.dwCaps = tests[i].caps;
10431 surface_desc.ddsCaps.dwCaps2 = tests[i].caps2;
10433 if (tests[i].format.dwFourCC == MAKEFOURCC('D','X','T','1') && !(supported_fmts & SUPPORT_DXT1))
10434 continue;
10435 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !(supported_fmts & SUPPORT_YUY2))
10436 continue;
10437 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !(supported_fmts & SUPPORT_UYVY))
10438 continue;
10439 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
10440 continue;
10442 if (tests[i].caps & DDSCAPS_ZBUFFER)
10444 if (!z_fmt.dwSize)
10445 continue;
10447 U4(surface_desc).ddpfPixelFormat = z_fmt;
10448 /* Some drivers seem to convert depth values incorrectly or not at
10449 * all. Affects at least AMD PALM, 8.17.10.1247. */
10450 if (tests[i].caps & DDSCAPS_VIDEOMEMORY)
10452 DWORD expected;
10453 float f, g;
10455 expected = tests[i].result & U3(z_fmt).dwZBitMask;
10456 f = ceilf(log2f(expected + 1.0f));
10457 g = (f + 1.0f) / 2.0f;
10458 g -= (int)g;
10459 expected_broken = (expected / exp2f(f) - g) * 256;
10460 expected_broken *= 0x01010101;
10464 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10465 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, surface %s.\n", hr, tests[i].name);
10467 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10468 todo_wine_if (tests[i].format.dwFourCC)
10469 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
10470 hr, tests[i].colorfill_hr, tests[i].name);
10472 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10473 todo_wine_if (tests[i].format.dwFourCC)
10474 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
10475 hr, tests[i].colorfill_hr, tests[i].name);
10477 if (SUCCEEDED(hr) && tests[i].check_result)
10479 memset(&surface_desc, 0, sizeof(surface_desc));
10480 surface_desc.dwSize = sizeof(surface_desc);
10481 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10482 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10483 color = surface_desc.lpSurface;
10484 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
10485 *color, tests[i].result, tests[i].name);
10486 hr = IDirectDrawSurface4_Unlock(surface, NULL);
10487 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10490 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10491 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
10492 hr, tests[i].depthfill_hr, tests[i].name);
10493 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10494 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
10495 hr, tests[i].depthfill_hr, tests[i].name);
10497 if (SUCCEEDED(hr) && tests[i].check_result)
10499 memset(&surface_desc, 0, sizeof(surface_desc));
10500 surface_desc.dwSize = sizeof(surface_desc);
10501 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10502 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10503 color = surface_desc.lpSurface;
10504 ok((*color & U3(z_fmt).dwZBitMask) == (tests[i].result & U3(z_fmt).dwZBitMask)
10505 || broken((*color & U3(z_fmt).dwZBitMask) == (expected_broken & U3(z_fmt).dwZBitMask)),
10506 "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
10507 *color & U3(z_fmt).dwZBitMask, tests[i].result & U3(z_fmt).dwZBitMask, tests[i].name);
10508 hr = IDirectDrawSurface4_Unlock(surface, NULL);
10509 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10512 U5(fx).dwFillColor = 0xdeadbeef;
10513 fx.dwROP = BLACKNESS;
10514 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10515 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
10516 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
10517 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
10518 U5(fx).dwFillColor, tests[i].name);
10520 if (SUCCEEDED(hr) && tests[i].check_result)
10522 memset(&surface_desc, 0, sizeof(surface_desc));
10523 surface_desc.dwSize = sizeof(surface_desc);
10524 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10525 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10526 color = surface_desc.lpSurface;
10527 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
10528 *color, tests[i].name);
10529 hr = IDirectDrawSurface4_Unlock(surface, NULL);
10530 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10533 fx.dwROP = WHITENESS;
10534 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10535 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
10536 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
10537 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
10538 U5(fx).dwFillColor, tests[i].name);
10540 if (SUCCEEDED(hr) && tests[i].check_result)
10542 memset(&surface_desc, 0, sizeof(surface_desc));
10543 surface_desc.dwSize = sizeof(surface_desc);
10544 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10545 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10546 color = surface_desc.lpSurface;
10547 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
10548 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
10549 *color, tests[i].name);
10550 hr = IDirectDrawSurface4_Unlock(surface, NULL);
10551 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10554 IDirectDrawSurface4_Release(surface);
10557 memset(&fx, 0, sizeof(fx));
10558 fx.dwSize = sizeof(fx);
10559 U5(fx).dwFillColor = 0xdeadbeef;
10560 fx.dwROP = WHITENESS;
10562 memset(&surface_desc, 0, sizeof(surface_desc));
10563 surface_desc.dwSize = sizeof(surface_desc);
10564 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10565 surface_desc.dwWidth = 64;
10566 surface_desc.dwHeight = 64;
10567 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10568 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10569 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10570 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10571 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10572 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10573 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
10574 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10575 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10576 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
10577 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10579 /* No DDBLTFX. */
10580 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
10581 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10582 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
10583 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10585 /* Unused source rectangle. */
10586 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10587 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10588 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10589 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10591 /* Unused source surface. */
10592 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10593 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10594 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10595 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10596 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10597 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10598 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10599 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10601 /* Inverted destination or source rectangle. */
10602 SetRect(&rect, 5, 7, 7, 5);
10603 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10604 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10605 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10606 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10607 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10608 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10609 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10610 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10611 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10612 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10614 /* Negative rectangle. */
10615 SetRect(&rect, -1, -1, 5, 5);
10616 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10617 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10618 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10619 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10620 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10621 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10622 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10623 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10624 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10625 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10627 /* Out of bounds rectangle. */
10628 SetRect(&rect, 0, 0, 65, 65);
10629 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10630 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10631 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10632 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10634 /* Combine multiple flags. */
10635 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10636 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10637 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
10638 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10639 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
10640 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10642 for (i = 0; i < ARRAY_SIZE(rops); i++)
10644 fx.dwROP = rops[i].rop;
10645 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10646 ok(hr == rops[i].hr, "Got unexpected hr %#x for rop %s.\n", hr, rops[i].name);
10649 IDirectDrawSurface4_Release(surface2);
10650 IDirectDrawSurface4_Release(surface);
10652 if (!z_fmt.dwSize)
10653 goto done;
10655 memset(&surface_desc, 0, sizeof(surface_desc));
10656 surface_desc.dwSize = sizeof(surface_desc);
10657 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10658 surface_desc.dwWidth = 64;
10659 surface_desc.dwHeight = 64;
10660 U4(surface_desc).ddpfPixelFormat = z_fmt;
10661 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
10662 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10663 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10664 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
10665 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10667 /* No DDBLTFX. */
10668 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
10669 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10671 /* Unused source rectangle. */
10672 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10673 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10675 /* Unused source surface. */
10676 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10677 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10678 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10679 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10681 /* Inverted destination or source rectangle. */
10682 SetRect(&rect, 5, 7, 7, 5);
10683 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10684 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10685 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10686 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10687 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10688 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10689 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10690 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10692 /* Negative rectangle. */
10693 SetRect(&rect, -1, -1, 5, 5);
10694 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10695 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10696 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10697 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10698 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10699 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10700 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10701 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10703 /* Out of bounds rectangle. */
10704 SetRect(&rect, 0, 0, 65, 65);
10705 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10706 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10708 /* Combine multiple flags. */
10709 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10710 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10712 IDirectDrawSurface4_Release(surface2);
10713 IDirectDrawSurface4_Release(surface);
10715 done:
10716 IDirectDraw4_Release(ddraw);
10717 refcount = IDirect3DDevice3_Release(device);
10718 ok(!refcount, "Device has %u references left.\n", refcount);
10719 DestroyWindow(window);
10722 static void test_texcoordindex(void)
10724 static struct
10726 struct vec3 pos;
10727 struct vec2 texcoord1;
10728 struct vec2 texcoord2;
10729 struct vec2 texcoord3;
10731 quad[] =
10733 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f}},
10734 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f}},
10735 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}},
10736 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}},
10738 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_TEX3;
10739 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
10740 IDirect3DDevice3 *device;
10741 IDirect3D3 *d3d;
10742 IDirectDraw4 *ddraw;
10743 IDirectDrawSurface4 *rt;
10744 IDirect3DViewport3 *viewport;
10745 HWND window;
10746 HRESULT hr;
10747 IDirectDrawSurface4 *surface1, *surface2;
10748 IDirect3DTexture2 *texture1, *texture2;
10749 DDSURFACEDESC2 surface_desc;
10750 ULONG refcount;
10751 D3DCOLOR color;
10752 DWORD *ptr;
10754 window = create_window();
10755 if (!(device = create_device(window, DDSCL_NORMAL)))
10757 skip("Failed to create a 3D device, skipping test.\n");
10758 DestroyWindow(window);
10759 return;
10762 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
10763 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
10764 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
10765 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
10766 IDirect3D3_Release(d3d);
10768 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
10769 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10771 memset(&surface_desc, 0, sizeof(surface_desc));
10772 surface_desc.dwSize = sizeof(surface_desc);
10773 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10774 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10775 surface_desc.dwWidth = 2;
10776 surface_desc.dwHeight = 2;
10777 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10778 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
10779 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10780 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10781 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10782 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10783 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
10784 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
10785 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10786 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
10787 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10789 memset(&surface_desc, 0, sizeof(surface_desc));
10790 surface_desc.dwSize = sizeof(surface_desc);
10791 hr = IDirectDrawSurface4_Lock(surface1, 0, &surface_desc, 0, NULL);
10792 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10793 ptr = surface_desc.lpSurface;
10794 ptr[0] = 0xff000000;
10795 ptr[1] = 0xff00ff00;
10796 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
10797 ptr[0] = 0xff0000ff;
10798 ptr[1] = 0xff00ffff;
10799 hr = IDirectDrawSurface4_Unlock(surface1, NULL);
10800 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10802 memset(&surface_desc, 0, sizeof(surface_desc));
10803 surface_desc.dwSize = sizeof(surface_desc);
10804 hr = IDirectDrawSurface4_Lock(surface2, 0, &surface_desc, 0, NULL);
10805 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10806 ptr = surface_desc.lpSurface;
10807 ptr[0] = 0xff000000;
10808 ptr[1] = 0xff0000ff;
10809 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
10810 ptr[0] = 0xffff0000;
10811 ptr[1] = 0xffff00ff;
10812 hr = IDirectDrawSurface4_Unlock(surface2, 0);
10813 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10815 viewport = create_viewport(device, 0, 0, 640, 480);
10816 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
10817 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
10819 hr = IDirectDrawSurface4_QueryInterface(surface1, &IID_IDirect3DTexture2, (void **)&texture1);
10820 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
10821 hr = IDirectDrawSurface4_QueryInterface(surface2, &IID_IDirect3DTexture2, (void **)&texture2);
10822 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
10823 hr = IDirect3DDevice3_SetTexture(device, 0, texture1);
10824 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
10825 hr = IDirect3DDevice3_SetTexture(device, 1, texture2);
10826 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
10827 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
10828 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10829 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10830 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10831 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD);
10832 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10833 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10834 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10835 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
10836 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10837 hr = IDirect3DDevice3_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
10838 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10840 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_TEXCOORDINDEX, 1);
10841 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10842 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 0);
10843 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10845 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
10846 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
10848 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
10849 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10851 hr = IDirect3DDevice3_BeginScene(device);
10852 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10853 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
10854 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10855 hr = IDirect3DDevice3_EndScene(device);
10856 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10858 color = get_surface_color(rt, 160, 120);
10859 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10860 color = get_surface_color(rt, 480, 120);
10861 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10862 color = get_surface_color(rt, 160, 360);
10863 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
10864 color = get_surface_color(rt, 480, 360);
10865 ok(compare_color(color, 0x00ffffff, 2), "Got unexpected color 0x%08x.\n", color);
10867 /* D3DTSS_TEXTURETRANSFORMFLAGS was introduced in D3D7, can't test it here. */
10869 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 2);
10870 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10872 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
10873 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10875 hr = IDirect3DDevice3_BeginScene(device);
10876 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10877 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
10878 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10879 hr = IDirect3DDevice3_EndScene(device);
10880 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10882 color = get_surface_color(rt, 160, 120);
10883 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10884 color = get_surface_color(rt, 480, 120);
10885 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10886 color = get_surface_color(rt, 160, 360);
10887 ok(compare_color(color, 0x00ff00ff, 2), "Got unexpected color 0x%08x.\n", color);
10888 color = get_surface_color(rt, 480, 360);
10889 ok(compare_color(color, 0x00ffff00, 2), "Got unexpected color 0x%08x.\n", color);
10891 IDirect3DTexture2_Release(texture2);
10892 IDirect3DTexture2_Release(texture1);
10893 IDirectDrawSurface4_Release(surface2);
10894 IDirectDrawSurface4_Release(surface1);
10896 destroy_viewport(device, viewport);
10898 IDirectDrawSurface4_Release(rt);
10899 IDirectDraw_Release(ddraw);
10900 refcount = IDirect3DDevice3_Release(device);
10901 ok(!refcount, "Device has %u references left.\n", refcount);
10902 DestroyWindow(window);
10905 static void test_colorkey_precision(void)
10907 static struct
10909 struct vec3 pos;
10910 struct vec2 texcoord;
10912 quad[] =
10914 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
10915 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
10916 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
10917 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
10919 IDirect3DDevice3 *device;
10920 IDirect3D3 *d3d;
10921 IDirectDraw4 *ddraw;
10922 IDirectDrawSurface4 *rt;
10923 IDirect3DViewport3 *viewport;
10924 HWND window;
10925 HRESULT hr;
10926 IDirectDrawSurface4 *src, *dst, *texture;
10927 IDirect3DTexture2 *d3d_texture;
10928 DDSURFACEDESC2 surface_desc, lock_desc;
10929 ULONG refcount;
10930 D3DCOLOR color;
10931 unsigned int t, c;
10932 DDCOLORKEY ckey;
10933 DDBLTFX fx;
10934 DWORD data[4] = {0}, color_mask;
10935 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
10936 BOOL is_nvidia, is_warp;
10937 static const struct
10939 unsigned int max, shift, bpp, clear;
10940 const char *name;
10941 BOOL skip_nv;
10942 DDPIXELFORMAT fmt;
10944 tests[] =
10947 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8", FALSE,
10949 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10950 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
10955 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel", FALSE,
10957 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10958 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
10963 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel", FALSE,
10965 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10966 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
10971 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4", TRUE,
10973 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10974 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
10979 window = create_window();
10980 if (!(device = create_device(window, DDSCL_NORMAL)))
10982 skip("Failed to create a 3D device, skipping test.\n");
10983 DestroyWindow(window);
10984 return;
10987 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
10988 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
10989 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
10990 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
10991 IDirect3D3_Release(d3d);
10992 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
10993 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10995 is_nvidia = ddraw_is_nvidia(ddraw);
10996 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
10997 * (color key doesn't match although the values are equal), and a false
10998 * positive when the color key is 0 and the texture contains the value 1.
10999 * I don't want to mark this broken unconditionally since this would
11000 * essentially disable the test on Windows. Also on random occasions
11001 * 254 == 255 and 255 != 255.*/
11002 is_warp = ddraw_is_warp(ddraw);
11004 viewport = create_viewport(device, 0, 0, 640, 480);
11005 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
11006 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
11008 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
11009 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
11010 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
11011 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
11012 /* Multiply the texture read result with 0, that way the result color if the key doesn't
11013 * match is constant. In theory color keying works without reading the texture result
11014 * (meaning we could just op=arg1, arg1=tfactor), but the Geforce7 Windows driver begs
11015 * to differ. */
11016 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
11017 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11018 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
11019 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11020 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
11021 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11022 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x00000000);
11023 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
11025 memset(&fx, 0, sizeof(fx));
11026 fx.dwSize = sizeof(fx);
11027 memset(&lock_desc, 0, sizeof(lock_desc));
11028 lock_desc.dwSize = sizeof(lock_desc);
11030 for (t = 0; t < ARRAY_SIZE(tests); ++t)
11032 if (is_nvidia && tests[t].skip_nv)
11034 win_skip("Skipping test %s on Nvidia Windows drivers.\n", tests[t].name);
11035 continue;
11038 memset(&surface_desc, 0, sizeof(surface_desc));
11039 surface_desc.dwSize = sizeof(surface_desc);
11040 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11041 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11042 surface_desc.dwWidth = 4;
11043 surface_desc.dwHeight = 1;
11044 U4(surface_desc).ddpfPixelFormat = tests[t].fmt;
11045 /* Windows XP (at least with the r200 driver, other drivers untested) produces
11046 * garbage when doing color keyed texture->texture blits. */
11047 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL);
11048 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11049 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL);
11050 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11052 U5(fx).dwFillColor = tests[t].clear;
11053 /* On the w8 testbot (WARP driver) the blit result has different values in the
11054 * X channel. */
11055 color_mask = U2(tests[t].fmt).dwRBitMask
11056 | U3(tests[t].fmt).dwGBitMask
11057 | U4(tests[t].fmt).dwBBitMask;
11059 for (c = 0; c <= tests[t].max; ++c)
11061 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
11062 * texture after it has been set once... */
11063 surface_desc.dwFlags |= DDSD_CKSRCBLT;
11064 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11065 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
11066 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
11067 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &texture, NULL);
11068 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11069 hr = IDirectDrawSurface4_QueryInterface(texture, &IID_IDirect3DTexture2, (void **)&d3d_texture);
11070 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
11071 hr = IDirect3DDevice3_SetTexture(device, 0, d3d_texture);
11072 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
11074 hr = IDirectDrawSurface4_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11075 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
11077 hr = IDirectDrawSurface4_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
11078 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11079 switch (tests[t].bpp)
11081 case 4:
11082 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
11083 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
11084 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
11085 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
11086 break;
11088 case 2:
11089 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
11090 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
11091 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
11092 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
11093 break;
11095 hr = IDirectDrawSurface4_Unlock(src, 0);
11096 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11097 hr = IDirectDrawSurface4_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
11098 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
11100 ckey.dwColorSpaceLowValue = c << tests[t].shift;
11101 ckey.dwColorSpaceHighValue = c << tests[t].shift;
11102 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
11103 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
11105 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
11106 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
11108 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
11109 hr = IDirectDrawSurface4_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
11110 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11111 switch (tests[t].bpp)
11113 case 4:
11114 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
11115 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
11116 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
11117 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
11118 break;
11120 case 2:
11121 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
11122 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
11123 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
11124 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
11125 break;
11127 hr = IDirectDrawSurface4_Unlock(dst, 0);
11128 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11130 if (!c)
11132 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
11133 tests[t].clear, data[0], tests[t].name, c);
11135 if (data[3] == tests[t].clear)
11137 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
11138 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
11139 * even when a different surface is used. The blit itself doesn't draw anything,
11140 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
11141 * never be masked out by the key.
11143 * On Windows 10 the problem is worse, Blt just hangs. For this reason the ARGB4444
11144 * test is disabled entirely.
11146 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
11147 * terrible on WARP. */
11148 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
11149 IDirect3DTexture2_Release(d3d_texture);
11150 IDirectDrawSurface4_Release(texture);
11151 IDirectDrawSurface4_Release(src);
11152 IDirectDrawSurface4_Release(dst);
11153 goto done;
11156 else
11157 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
11158 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
11160 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
11161 tests[t].clear, data[1], tests[t].name, c);
11163 if (c == tests[t].max)
11164 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
11165 tests[t].clear, data[2], tests[t].name, c);
11166 else
11167 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
11168 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
11170 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
11171 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
11173 hr = IDirect3DDevice3_BeginScene(device);
11174 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11175 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
11176 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11177 hr = IDirect3DDevice3_EndScene(device);
11178 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11180 color = get_surface_color(rt, 80, 240);
11181 if (!c)
11182 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
11183 "Got unexpected color 0x%08x, format %s, c=%u.\n",
11184 color, tests[t].name, c);
11185 else
11186 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
11187 "Got unexpected color 0x%08x, format %s, c=%u.\n",
11188 color, tests[t].name, c);
11190 color = get_surface_color(rt, 240, 240);
11191 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
11192 "Got unexpected color 0x%08x, format %s, c=%u.\n",
11193 color, tests[t].name, c);
11195 color = get_surface_color(rt, 400, 240);
11196 if (c == tests[t].max)
11197 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
11198 "Got unexpected color 0x%08x, format %s, c=%u.\n",
11199 color, tests[t].name, c);
11200 else
11201 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
11202 "Got unexpected color 0x%08x, format %s, c=%u.\n",
11203 color, tests[t].name, c);
11205 IDirect3DTexture2_Release(d3d_texture);
11206 IDirectDrawSurface4_Release(texture);
11208 IDirectDrawSurface4_Release(src);
11209 IDirectDrawSurface4_Release(dst);
11211 done:
11213 destroy_viewport(device, viewport);
11214 IDirectDrawSurface4_Release(rt);
11215 IDirectDraw4_Release(ddraw);
11216 refcount = IDirect3DDevice3_Release(device);
11217 ok(!refcount, "Device has %u references left.\n", refcount);
11218 DestroyWindow(window);
11221 static void test_range_colorkey(void)
11223 IDirectDraw4 *ddraw;
11224 HWND window;
11225 HRESULT hr;
11226 IDirectDrawSurface4 *surface;
11227 DDSURFACEDESC2 surface_desc;
11228 ULONG refcount;
11229 DDCOLORKEY ckey;
11231 window = create_window();
11232 ddraw = create_ddraw();
11233 ok(!!ddraw, "Failed to create a ddraw object.\n");
11234 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11235 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11237 memset(&surface_desc, 0, sizeof(surface_desc));
11238 surface_desc.dwSize = sizeof(surface_desc);
11239 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
11240 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11241 surface_desc.dwWidth = 1;
11242 surface_desc.dwHeight = 1;
11243 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11244 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
11245 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
11246 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
11247 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
11248 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
11250 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
11251 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
11252 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
11253 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11254 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11256 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
11257 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
11258 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11259 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11261 /* Same for DDSCAPS_OFFSCREENPLAIN. */
11262 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11263 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
11264 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
11265 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11266 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11268 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
11269 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
11270 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11271 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11273 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
11274 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
11275 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11276 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11278 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
11279 ckey.dwColorSpaceLowValue = 0x00000000;
11280 ckey.dwColorSpaceHighValue = 0x00000001;
11281 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11282 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
11284 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11285 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
11286 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
11287 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
11289 ckey.dwColorSpaceLowValue = 0x00000001;
11290 ckey.dwColorSpaceHighValue = 0x00000000;
11291 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11292 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
11294 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11295 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
11296 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
11297 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
11299 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
11300 ckey.dwColorSpaceLowValue = 0x00000000;
11301 ckey.dwColorSpaceHighValue = 0x00000000;
11302 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
11303 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
11305 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
11306 ckey.dwColorSpaceLowValue = 0x00000001;
11307 ckey.dwColorSpaceHighValue = 0x00000000;
11308 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
11309 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11310 ckey.dwColorSpaceLowValue = 0x00000000;
11311 ckey.dwColorSpaceHighValue = 0x00000001;
11312 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
11313 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11314 /* Range destination keys don't work either. */
11315 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
11316 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11318 /* Just to show it's not because of A, R, and G having equal values. */
11319 ckey.dwColorSpaceLowValue = 0x00000000;
11320 ckey.dwColorSpaceHighValue = 0x01010101;
11321 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
11322 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11324 /* None of these operations modified the key. */
11325 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11326 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
11327 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
11328 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
11330 IDirectDrawSurface4_Release(surface);
11331 refcount = IDirectDraw4_Release(ddraw);
11332 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
11333 DestroyWindow(window);
11336 static void test_shademode(void)
11338 IDirect3DVertexBuffer *vb_strip, *vb_list, *buffer;
11339 IDirect3DViewport3 *viewport;
11340 IDirect3DDevice3 *device;
11341 D3DVERTEXBUFFERDESC desc;
11342 IDirectDrawSurface4 *rt;
11343 DWORD color0, color1;
11344 void *data = NULL;
11345 IDirect3D3 *d3d;
11346 ULONG refcount;
11347 UINT i, count;
11348 HWND window;
11349 HRESULT hr;
11350 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
11351 static const struct
11353 struct vec3 position;
11354 DWORD diffuse;
11356 quad_strip[] =
11358 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
11359 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
11360 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
11361 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
11363 quad_list[] =
11365 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
11366 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
11367 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
11369 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
11370 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
11371 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
11373 static const struct
11375 DWORD primtype;
11376 DWORD shademode;
11377 DWORD color0, color1;
11379 tests[] =
11381 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x0000ff00},
11382 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
11383 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
11384 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
11385 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
11386 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
11389 window = create_window();
11390 if (!(device = create_device(window, DDSCL_NORMAL)))
11392 skip("Failed to create a 3D device, skipping test.\n");
11393 DestroyWindow(window);
11394 return;
11397 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
11398 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
11399 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
11400 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11402 viewport = create_viewport(device, 0, 0, 640, 480);
11403 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
11404 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
11406 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
11407 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
11409 memset(&desc, 0, sizeof(desc));
11410 desc.dwSize = sizeof(desc);
11411 desc.dwCaps = D3DVBCAPS_WRITEONLY;
11412 desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
11413 desc.dwNumVertices = ARRAY_SIZE(quad_strip);
11414 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &vb_strip, 0, NULL);
11415 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
11416 hr = IDirect3DVertexBuffer_Lock(vb_strip, 0, &data, NULL);
11417 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
11418 memcpy(data, quad_strip, sizeof(quad_strip));
11419 hr = IDirect3DVertexBuffer_Unlock(vb_strip);
11420 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
11422 desc.dwNumVertices = ARRAY_SIZE(quad_list);
11423 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &vb_list, 0, NULL);
11424 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
11425 hr = IDirect3DVertexBuffer_Lock(vb_list, 0, &data, NULL);
11426 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
11427 memcpy(data, quad_list, sizeof(quad_list));
11428 hr = IDirect3DVertexBuffer_Unlock(vb_list);
11429 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
11431 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
11432 * the color fixups we have to do for FLAT shading will be dependent on that. */
11434 for (i = 0; i < ARRAY_SIZE(tests); ++i)
11436 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
11437 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
11439 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
11440 ok(hr == D3D_OK, "Failed to set shade mode, hr %#x.\n", hr);
11442 hr = IDirect3DDevice3_BeginScene(device);
11443 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11444 buffer = tests[i].primtype == D3DPT_TRIANGLESTRIP ? vb_strip : vb_list;
11445 count = tests[i].primtype == D3DPT_TRIANGLESTRIP ? 4 : 6;
11446 hr = IDirect3DDevice3_DrawPrimitiveVB(device, tests[i].primtype, buffer, 0, count, 0);
11447 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11448 hr = IDirect3DDevice3_EndScene(device);
11449 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11451 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
11452 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
11454 /* For D3DSHADE_FLAT it should take the color of the first vertex of
11455 * each triangle. This requires EXT_provoking_vertex or similar
11456 * functionality being available. */
11457 /* PHONG should be the same as GOURAUD, since no hardware implements
11458 * this. */
11459 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
11460 i, color0, tests[i].color0);
11461 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
11462 i, color1, tests[i].color1);
11465 IDirect3DVertexBuffer_Release(vb_strip);
11466 IDirect3DVertexBuffer_Release(vb_list);
11467 destroy_viewport(device, viewport);
11468 IDirectDrawSurface4_Release(rt);
11469 IDirect3D3_Release(d3d);
11470 refcount = IDirect3DDevice3_Release(device);
11471 ok(!refcount, "Device has %u references left.\n", refcount);
11472 DestroyWindow(window);
11475 static void test_lockrect_invalid(void)
11477 unsigned int i, r;
11478 IDirectDraw4 *ddraw;
11479 IDirectDrawSurface4 *surface;
11480 HWND window;
11481 HRESULT hr;
11482 DDSURFACEDESC2 surface_desc;
11483 DDCAPS hal_caps;
11484 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
11485 static RECT valid[] =
11487 {60, 60, 68, 68},
11488 {60, 60, 60, 68},
11489 {60, 60, 68, 60},
11490 {120, 60, 128, 68},
11491 {60, 120, 68, 128},
11493 static RECT invalid[] =
11495 {68, 60, 60, 68}, /* left > right */
11496 {60, 68, 68, 60}, /* top > bottom */
11497 {-8, 60, 0, 68}, /* left < surface */
11498 {60, -8, 68, 0}, /* top < surface */
11499 {-16, 60, -8, 68}, /* right < surface */
11500 {60, -16, 68, -8}, /* bottom < surface */
11501 {60, 60, 136, 68}, /* right > surface */
11502 {60, 60, 68, 136}, /* bottom > surface */
11503 {136, 60, 144, 68}, /* left > surface */
11504 {60, 136, 68, 144}, /* top > surface */
11506 static const struct
11508 DWORD caps, caps2;
11509 const char *name;
11510 BOOL allowed;
11511 HRESULT hr;
11513 resources[] =
11515 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", TRUE, DDERR_INVALIDPARAMS},
11516 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", TRUE, DDERR_INVALIDPARAMS},
11517 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", TRUE, DDERR_INVALIDPARAMS},
11518 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", TRUE, DDERR_INVALIDPARAMS},
11519 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", TRUE, DDERR_INVALIDPARAMS},
11521 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_WRITEONLY, 0, "sysmem offscreenplain writeonly", FALSE, DDERR_INVALIDPARAMS},
11522 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_WRITEONLY, 0, "vidmem offscreenplain writeonly", FALSE, DDERR_INVALIDPARAMS},
11523 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_WRITEONLY, 0, "sysmem texture writeonly", FALSE, DDERR_INVALIDPARAMS},
11524 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_WRITEONLY, 0, "vidmem texture writeonly", FALSE, DDERR_INVALIDPARAMS},
11525 {DDSCAPS_TEXTURE | DDSCAPS_WRITEONLY, DDSCAPS2_TEXTUREMANAGE, "managed texture writeonly", TRUE, DDERR_INVALIDPARAMS},
11528 window = create_window();
11529 ddraw = create_ddraw();
11530 ok(!!ddraw, "Failed to create a ddraw object.\n");
11531 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11532 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11534 memset(&hal_caps, 0, sizeof(hal_caps));
11535 hal_caps.dwSize = sizeof(hal_caps);
11536 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
11537 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
11538 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
11539 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
11541 skip("Required surface types not supported, skipping test.\n");
11542 goto done;
11545 for (r = 0; r < ARRAY_SIZE(resources); ++r)
11547 memset(&surface_desc, 0, sizeof(surface_desc));
11548 surface_desc.dwSize = sizeof(surface_desc);
11549 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11550 surface_desc.ddsCaps.dwCaps = resources[r].caps;
11551 surface_desc.ddsCaps.dwCaps2 = resources[r].caps2;
11552 surface_desc.dwWidth = 128;
11553 surface_desc.dwHeight = 128;
11554 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11555 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11556 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
11557 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xff0000;
11558 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x00ff00;
11559 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000ff;
11561 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11562 if (!resources[r].allowed)
11564 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
11565 continue;
11567 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, resources[r].name);
11569 hr = IDirectDrawSurface4_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
11570 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
11572 for (i = 0; i < ARRAY_SIZE(valid); ++i)
11574 RECT *rect = &valid[i];
11576 memset(&surface_desc, 0, sizeof(surface_desc));
11577 surface_desc.dwSize = sizeof(surface_desc);
11579 hr = IDirectDrawSurface4_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
11580 ok(SUCCEEDED(hr), "Lock failed (%#x) for rect %s, type %s.\n",
11581 hr, wine_dbgstr_rect(rect), resources[r].name);
11583 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11584 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11587 for (i = 0; i < ARRAY_SIZE(invalid); ++i)
11589 RECT *rect = &invalid[i];
11591 memset(&surface_desc, 1, sizeof(surface_desc));
11592 surface_desc.dwSize = sizeof(surface_desc);
11594 hr = IDirectDrawSurface4_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
11595 ok(hr == resources[r].hr, "Lock returned %#x for rect %s, type %s.\n",
11596 hr, wine_dbgstr_rect(rect), resources[r].name);
11597 if (SUCCEEDED(hr))
11599 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11600 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11602 else
11603 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
11606 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
11607 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#x, type %s.\n",
11608 hr, resources[r].name);
11609 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
11610 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#x, type %s.\n",
11611 hr, resources[r].name);
11612 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11613 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11615 hr = IDirectDrawSurface4_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
11616 ok(SUCCEEDED(hr), "Lock(rect = %s) failed (%#x).\n", wine_dbgstr_rect(&valid[0]), hr);
11617 hr = IDirectDrawSurface4_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
11618 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = %s) failed (%#x).\n",
11619 wine_dbgstr_rect(&valid[0]), hr);
11621 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
11622 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
11624 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11625 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11627 IDirectDrawSurface4_Release(surface);
11630 done:
11631 IDirectDraw4_Release(ddraw);
11632 DestroyWindow(window);
11635 static void test_yv12_overlay(void)
11637 IDirectDrawSurface4 *src_surface, *dst_surface;
11638 RECT rect = {13, 17, 14, 18};
11639 unsigned int offset, y;
11640 DDSURFACEDESC2 desc;
11641 unsigned char *base;
11642 IDirectDraw4 *ddraw;
11643 HWND window;
11644 HRESULT hr;
11646 window = create_window();
11647 ddraw = create_ddraw();
11648 ok(!!ddraw, "Failed to create a ddraw object.\n");
11649 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11650 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11652 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
11654 skip("Failed to create a YV12 overlay, skipping test.\n");
11655 goto done;
11658 memset(&desc, 0, sizeof(desc));
11659 desc.dwSize = sizeof(desc);
11660 hr = IDirectDrawSurface4_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
11661 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11663 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
11664 "Got unexpected flags %#x.\n", desc.dwFlags);
11665 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
11666 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
11667 "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps);
11668 ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth);
11669 ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight);
11670 /* The overlay pitch seems to have 256 byte alignment. */
11671 ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch);
11673 /* Fill the surface with some data for the blit test. */
11674 base = desc.lpSurface;
11675 /* Luminance */
11676 for (y = 0; y < desc.dwHeight; ++y)
11678 memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth);
11680 /* V */
11681 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
11683 memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth);
11685 /* U */
11686 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
11688 memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth);
11691 hr = IDirectDrawSurface4_Unlock(src_surface, NULL);
11692 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11694 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
11695 * other block-based formats like DXT the entire Y channel is stored in
11696 * one big chunk of memory, followed by the chroma channels. So partial
11697 * locks do not really make sense. Show that they are allowed nevertheless
11698 * and the offset points into the luminance data. */
11699 hr = IDirectDrawSurface4_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
11700 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11701 offset = ((const unsigned char *)desc.lpSurface - base);
11702 ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n",
11703 offset, rect.top * U1(desc).lPitch + rect.left);
11704 hr = IDirectDrawSurface4_Unlock(src_surface, NULL);
11705 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11707 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
11709 /* Windows XP with a Radeon X1600 GPU refuses to create a second
11710 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
11711 skip("Failed to create a second YV12 surface, skipping blit test.\n");
11712 IDirectDrawSurface4_Release(src_surface);
11713 goto done;
11716 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
11717 /* VMware rejects YV12 blits. This behavior has not been seen on real
11718 * hardware yet, so mark it broken. */
11719 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr);
11721 if (SUCCEEDED(hr))
11723 memset(&desc, 0, sizeof(desc));
11724 desc.dwSize = sizeof(desc);
11725 hr = IDirectDrawSurface4_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
11726 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11728 base = desc.lpSurface;
11729 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
11730 base += desc.dwHeight * U1(desc).lPitch;
11731 todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
11732 base += desc.dwHeight / 4 * U1(desc).lPitch;
11733 todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
11735 hr = IDirectDrawSurface4_Unlock(dst_surface, NULL);
11736 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11739 IDirectDrawSurface4_Release(dst_surface);
11740 IDirectDrawSurface4_Release(src_surface);
11741 done:
11742 IDirectDraw4_Release(ddraw);
11743 DestroyWindow(window);
11746 static BOOL dwm_enabled(void)
11748 BOOL ret = FALSE;
11750 if (!strcmp(winetest_platform, "wine"))
11751 return FALSE;
11752 if (!pDwmIsCompositionEnabled)
11753 return FALSE;
11754 if (FAILED(pDwmIsCompositionEnabled(&ret)))
11755 return FALSE;
11756 return ret;
11759 static void test_offscreen_overlay(void)
11761 IDirectDrawSurface4 *overlay, *offscreen, *primary;
11762 DDSURFACEDESC2 surface_desc;
11763 IDirectDraw4 *ddraw;
11764 HWND window;
11765 HRESULT hr;
11766 HDC dc;
11768 window = create_window();
11769 ddraw = create_ddraw();
11770 ok(!!ddraw, "Failed to create a ddraw object.\n");
11771 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11772 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11774 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
11776 skip("Failed to create a UYVY overlay, skipping test.\n");
11777 goto done;
11780 memset(&surface_desc, 0, sizeof(surface_desc));
11781 surface_desc.dwSize = sizeof(surface_desc);
11782 surface_desc.dwFlags = DDSD_CAPS;
11783 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
11784 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
11785 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
11787 /* On Windows 7, and probably Vista, UpdateOverlay() will return
11788 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
11789 * surface prevents this by disabling the dwm. */
11790 hr = IDirectDrawSurface4_GetDC(primary, &dc);
11791 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
11792 hr = IDirectDrawSurface4_ReleaseDC(primary, dc);
11793 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
11795 /* Try to overlay a NULL surface. */
11796 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
11797 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11798 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
11799 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11801 /* Try to overlay an offscreen surface. */
11802 memset(&surface_desc, 0, sizeof(surface_desc));
11803 surface_desc.dwSize = sizeof(surface_desc);
11804 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
11805 surface_desc.dwWidth = 64;
11806 surface_desc.dwHeight = 64;
11807 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11808 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11809 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11810 U4(surface_desc).ddpfPixelFormat.dwFourCC = 0;
11811 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
11812 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
11813 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
11814 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
11815 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
11816 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
11818 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
11819 ok(SUCCEEDED(hr) || broken(hr == DDERR_OUTOFCAPS && dwm_enabled())
11820 || broken(hr == E_NOTIMPL && ddraw_is_vmware(ddraw)),
11821 "Failed to update overlay, hr %#x.\n", hr);
11823 /* Try to overlay the primary with a non-overlay surface. */
11824 hr = IDirectDrawSurface4_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
11825 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
11826 hr = IDirectDrawSurface4_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_HIDE, NULL);
11827 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
11829 IDirectDrawSurface4_Release(offscreen);
11830 IDirectDrawSurface4_Release(primary);
11831 IDirectDrawSurface4_Release(overlay);
11832 done:
11833 IDirectDraw4_Release(ddraw);
11834 DestroyWindow(window);
11837 static void test_overlay_rect(void)
11839 IDirectDrawSurface4 *overlay, *primary = NULL;
11840 DDSURFACEDESC2 surface_desc;
11841 RECT rect = {0, 0, 64, 64};
11842 IDirectDraw4 *ddraw;
11843 LONG pos_x, pos_y;
11844 HRESULT hr, hr2;
11845 HWND window;
11846 HDC dc;
11848 window = create_window();
11849 ddraw = create_ddraw();
11850 ok(!!ddraw, "Failed to create a ddraw object.\n");
11851 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11852 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11854 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
11856 skip("Failed to create a UYVY overlay, skipping test.\n");
11857 goto done;
11860 memset(&surface_desc, 0, sizeof(surface_desc));
11861 surface_desc.dwSize = sizeof(surface_desc);
11862 surface_desc.dwFlags = DDSD_CAPS;
11863 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
11864 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
11865 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
11867 /* On Windows 7, and probably Vista, UpdateOverlay() will return
11868 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
11869 * surface prevents this by disabling the dwm. */
11870 hr = IDirectDrawSurface4_GetDC(primary, &dc);
11871 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
11872 hr = IDirectDrawSurface4_ReleaseDC(primary, dc);
11873 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
11875 /* On Windows 8 and newer DWM can't be turned off, making overlays unusable. */
11876 if (dwm_enabled())
11878 win_skip("Cannot disable DWM, skipping overlay test.\n");
11879 goto done;
11882 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is
11883 * used. This is not true in Windows Vista and earlier, but changed in
11884 * Windows 7. */
11885 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
11886 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11887 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
11888 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11889 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
11890 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11892 /* Show that the overlay position is the (top, left) coordinate of the
11893 * destination rectangle. */
11894 OffsetRect(&rect, 32, 16);
11895 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
11896 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11897 pos_x = -1; pos_y = -1;
11898 hr = IDirectDrawSurface4_GetOverlayPosition(overlay, &pos_x, &pos_y);
11899 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
11900 ok(pos_x == rect.left, "Got unexpected pos_x %d, expected %d.\n", pos_x, rect.left);
11901 ok(pos_y == rect.top, "Got unexpected pos_y %d, expected %d.\n", pos_y, rect.top);
11903 /* Passing a NULL dest rect sets the position to 0/0. Visually it can be
11904 * seen that the overlay overlays the whole primary(==screen). */
11905 hr2 = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
11906 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS || hr2 == DDERR_OUTOFCAPS, "Got unexpected hr %#x.\n", hr2);
11907 hr = IDirectDrawSurface4_GetOverlayPosition(overlay, &pos_x, &pos_y);
11908 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
11909 if (SUCCEEDED(hr2))
11911 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
11912 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
11914 else
11916 ok(pos_x == 32, "Got unexpected pos_x %d.\n", pos_x);
11917 ok(pos_y == 16, "Got unexpected pos_y %d.\n", pos_y);
11920 /* The position cannot be retrieved when the overlay is not shown. */
11921 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
11922 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11923 pos_x = -1; pos_y = -1;
11924 hr = IDirectDrawSurface4_GetOverlayPosition(overlay, &pos_x, &pos_y);
11925 ok(hr == DDERR_OVERLAYNOTVISIBLE, "Got unexpected hr %#x.\n", hr);
11926 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
11927 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
11929 IDirectDrawSurface4_Release(overlay);
11930 done:
11931 if (primary)
11932 IDirectDrawSurface4_Release(primary);
11933 IDirectDraw4_Release(ddraw);
11934 DestroyWindow(window);
11937 static void test_blt(void)
11939 IDirectDrawSurface4 *surface, *rt;
11940 DDSURFACEDESC2 surface_desc;
11941 IDirect3DDevice3 *device;
11942 IDirectDraw4 *ddraw;
11943 IDirect3D3 *d3d;
11944 unsigned int i;
11945 ULONG refcount;
11946 HWND window;
11947 HRESULT hr;
11949 static struct
11951 RECT src_rect;
11952 RECT dst_rect;
11953 HRESULT hr;
11955 test_data[] =
11957 {{160, 0, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit. */
11958 {{160, 480, 640, 0}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, flipped source. */
11959 {{640, 0, 160, 480}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, mirrored source. */
11960 {{160, 0, 480, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched x. */
11961 {{160, 160, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched y. */
11962 {{ 0, 0, 640, 480}, { 0, 0, 640, 480}, DD_OK}, /* Full surface blit. */
11963 {{ 0, 0, 640, 480}, { 0, 480, 640, 0}, DDERR_INVALIDRECT}, /* Full surface, flipped destination. */
11964 {{ 0, 0, 640, 480}, {640, 0, 0, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored destination. */
11965 {{ 0, 480, 640, 0}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, flipped source. */
11966 {{640, 0, 0, 480}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored source. */
11969 window = create_window();
11970 if (!(device = create_device(window, DDSCL_NORMAL)))
11972 skip("Failed to create a 3D device, skipping test.\n");
11973 DestroyWindow(window);
11974 return;
11977 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
11978 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
11979 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
11980 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
11981 IDirect3D3_Release(d3d);
11982 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
11983 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11985 memset(&surface_desc, 0, sizeof(surface_desc));
11986 surface_desc.dwSize = sizeof(surface_desc);
11987 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
11988 surface_desc.dwWidth = 640;
11989 surface_desc.dwHeight = 480;
11990 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11991 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11992 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11994 hr = IDirectDrawSurface4_Blt(surface, NULL, surface, NULL, 0, NULL);
11995 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
11997 hr = IDirectDrawSurface4_Blt(surface, NULL, rt, NULL, 0, NULL);
11998 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12000 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
12002 hr = IDirectDrawSurface4_Blt(surface, &test_data[i].dst_rect,
12003 surface, &test_data[i].src_rect, DDBLT_WAIT, NULL);
12004 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
12006 hr = IDirectDrawSurface4_Blt(surface, &test_data[i].dst_rect,
12007 rt, &test_data[i].src_rect, DDBLT_WAIT, NULL);
12008 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
12010 hr = IDirectDrawSurface4_Blt(surface, &test_data[i].dst_rect,
12011 NULL, &test_data[i].src_rect, DDBLT_WAIT, NULL);
12012 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
12014 hr = IDirectDrawSurface4_Blt(surface, &test_data[i].dst_rect, NULL, NULL, DDBLT_WAIT, NULL);
12015 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
12018 IDirectDrawSurface4_Release(surface);
12019 IDirectDrawSurface4_Release(rt);
12020 IDirectDraw4_Release(ddraw);
12021 refcount = IDirect3DDevice3_Release(device);
12022 ok(!refcount, "Device has %u references left.\n", refcount);
12023 DestroyWindow(window);
12026 static void test_blt_z_alpha(void)
12028 DWORD blt_flags[] =
12030 /* 0 */
12031 DDBLT_ALPHADEST,
12032 DDBLT_ALPHADESTCONSTOVERRIDE,
12033 DDBLT_ALPHADESTNEG,
12034 DDBLT_ALPHADESTSURFACEOVERRIDE,
12035 DDBLT_ALPHAEDGEBLEND,
12036 /* 5 */
12037 DDBLT_ALPHASRC,
12038 DDBLT_ALPHASRCCONSTOVERRIDE,
12039 DDBLT_ALPHASRCNEG,
12040 DDBLT_ALPHASRCSURFACEOVERRIDE,
12041 DDBLT_ZBUFFER,
12042 /* 10 */
12043 DDBLT_ZBUFFERDESTCONSTOVERRIDE,
12044 DDBLT_ZBUFFERDESTOVERRIDE,
12045 DDBLT_ZBUFFERSRCCONSTOVERRIDE,
12046 DDBLT_ZBUFFERSRCOVERRIDE,
12048 IDirectDrawSurface4 *src_surface, *dst_surface;
12049 DDSURFACEDESC2 surface_desc;
12050 IDirectDraw4 *ddraw;
12051 DDPIXELFORMAT pf;
12052 ULONG refcount;
12053 unsigned int i;
12054 D3DCOLOR color;
12055 HWND window;
12056 HRESULT hr;
12057 DDBLTFX fx;
12059 window = create_window();
12060 ddraw = create_ddraw();
12061 ok(!!ddraw, "Failed to create a ddraw object.\n");
12062 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12063 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12065 memset(&pf, 0, sizeof(pf));
12066 pf.dwSize = sizeof(pf);
12067 pf.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
12068 U1(pf).dwRGBBitCount = 32;
12069 U2(pf).dwRBitMask = 0x00ff0000;
12070 U3(pf).dwGBitMask = 0x0000ff00;
12071 U4(pf).dwBBitMask = 0x000000ff;
12072 U5(pf).dwRGBAlphaBitMask = 0xff000000;
12074 memset(&surface_desc, 0, sizeof(surface_desc));
12075 surface_desc.dwSize = sizeof(surface_desc);
12076 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
12077 surface_desc.dwWidth = 64;
12078 surface_desc.dwHeight = 64;
12079 U4(surface_desc).ddpfPixelFormat = pf;
12080 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12082 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
12083 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
12084 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
12085 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
12087 memset(&fx, 0, sizeof(fx));
12088 fx.dwSize = sizeof(fx);
12089 fx.dwZBufferOpCode = D3DCMP_NEVER;
12090 fx.dwZDestConstBitDepth = 32;
12091 U1(fx).dwZDestConst = 0x11111111;
12092 fx.dwZSrcConstBitDepth = 32;
12093 U2(fx).dwZSrcConst = 0xeeeeeeee;
12094 fx.dwAlphaEdgeBlendBitDepth = 8;
12095 fx.dwAlphaEdgeBlend = 0x7f;
12096 fx.dwAlphaDestConstBitDepth = 8;
12097 U3(fx).dwAlphaDestConst = 0xdd;
12098 fx.dwAlphaSrcConstBitDepth = 8;
12099 U4(fx).dwAlphaSrcConst = 0x22;
12101 for (i = 0; i < ARRAY_SIZE(blt_flags); ++i)
12103 U5(fx).dwFillColor = 0x3300ff00;
12104 hr = IDirectDrawSurface4_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12105 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
12107 U5(fx).dwFillColor = 0xccff0000;
12108 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12109 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
12111 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, src_surface, NULL, blt_flags[i] | DDBLT_WAIT, &fx);
12112 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
12114 color = get_surface_color(dst_surface, 32, 32);
12115 ok(compare_color(color, 0x0000ff00, 0), "Test %u: Got unexpected color 0x%08x.\n", i, color);
12118 IDirectDrawSurface4_Release(dst_surface);
12119 IDirectDrawSurface4_Release(src_surface);
12120 refcount = IDirectDraw4_Release(ddraw);
12121 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
12122 DestroyWindow(window);
12125 static void test_cross_device_blt(void)
12127 IDirectDrawSurface4 *surface, *surface2, *sysmem_surface;
12128 IDirect3DDevice3 *device, *device2;
12129 IDirectDraw4 *ddraw, *ddraw2;
12130 DDSURFACEDESC2 surface_desc;
12131 HWND window, window2;
12132 IDirect3D3 *d3d;
12133 ULONG refcount;
12134 D3DCOLOR color;
12135 DDBLTFX fx;
12136 HRESULT hr;
12138 window = create_window();
12139 if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
12141 skip("Failed to create a 3D device.\n");
12142 DestroyWindow(window);
12143 return;
12146 window2 = create_window();
12147 if (!(device2 = create_device(window2, DDSCL_NORMAL)))
12149 skip("Failed to create a 3D device.\n");
12150 IDirect3DDevice3_Release(device);
12151 DestroyWindow(window);
12152 DestroyWindow(window2);
12153 return;
12156 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
12157 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
12158 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
12159 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
12160 IDirect3D3_Release(d3d);
12162 hr = IDirect3DDevice3_GetDirect3D(device2, &d3d);
12163 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
12164 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw2);
12165 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
12166 IDirect3D3_Release(d3d);
12168 memset(&surface_desc, 0, sizeof(surface_desc));
12169 surface_desc.dwSize = sizeof(surface_desc);
12170 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
12171 surface_desc.dwWidth = 640;
12172 surface_desc.dwHeight = 480;
12173 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
12174 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
12175 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12177 memset(&surface_desc, 0, sizeof(surface_desc));
12178 surface_desc.dwSize = sizeof(surface_desc);
12179 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
12180 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_VIDEOMEMORY;
12181 U5(surface_desc).dwBackBufferCount = 2;
12182 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12183 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12185 memset(&surface_desc, 0, sizeof(surface_desc));
12186 surface_desc.dwSize = sizeof(surface_desc);
12187 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
12188 surface_desc.dwWidth = 640;
12189 surface_desc.dwHeight = 480;
12190 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
12191 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
12192 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
12193 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
12194 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00007c00;
12195 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x000003e0;
12196 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000001f;
12197 hr = IDirectDraw4_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
12198 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12200 memset(&fx, 0, sizeof(fx));
12201 fx.dwSize = sizeof(fx);
12202 U5(fx).dwFillColor = 0xff0000ff;
12203 hr = IDirectDrawSurface4_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12204 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
12206 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
12207 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
12208 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
12209 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12210 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
12211 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
12212 color = get_surface_color(surface, 320, 240);
12213 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
12215 hr = IDirectDrawSurface4_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
12216 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
12217 color = get_surface_color(sysmem_surface, 320, 240);
12218 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
12220 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12221 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12222 hr = IDirectDrawSurface4_IsLost(sysmem_surface);
12223 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
12225 hr = IDirectDrawSurface4_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
12226 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
12227 color = get_surface_color(sysmem_surface, 320, 240);
12228 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
12230 IDirectDrawSurface4_Release(surface2);
12231 memset(&surface_desc, 0, sizeof(surface_desc));
12232 surface_desc.dwSize = sizeof(surface_desc);
12233 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
12234 surface_desc.dwWidth = 640;
12235 surface_desc.dwHeight = 480;
12236 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
12237 hr = IDirectDraw4_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
12238 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12239 hr = IDirectDrawSurface4_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12240 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
12242 hr = IDirectDrawSurface4_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
12243 todo_wine ok(hr == D3D_OK, "Failed to blit, hr %#x.\n", hr);
12244 color = get_surface_color(sysmem_surface, 320, 240);
12245 todo_wine ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12247 IDirectDrawSurface4_Release(surface);
12248 IDirectDrawSurface4_Release(surface2);
12249 IDirectDrawSurface4_Release(sysmem_surface);
12250 IDirectDraw4_Release(ddraw);
12251 IDirectDraw4_Release(ddraw2);
12252 refcount = IDirect3DDevice3_Release(device);
12253 ok(!refcount, "Device has %u references left.\n", refcount);
12254 refcount = IDirect3DDevice3_Release(device2);
12255 ok(!refcount, "Device has %u references left.\n", refcount);
12256 DestroyWindow(window);
12257 DestroyWindow(window2);
12260 static void test_color_clamping(void)
12262 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
12263 static D3DMATRIX mat =
12265 1.0f, 0.0f, 0.0f, 0.0f,
12266 0.0f, 1.0f, 0.0f, 0.0f,
12267 0.0f, 0.0f, 1.0f, 0.0f,
12268 0.0f, 0.0f, 0.0f, 1.0f,
12270 static struct vec3 quad[] =
12272 {-1.0f, -1.0f, 0.1f},
12273 {-1.0f, 1.0f, 0.1f},
12274 { 1.0f, -1.0f, 0.1f},
12275 { 1.0f, 1.0f, 0.1f},
12277 IDirect3DViewport3 *viewport;
12278 IDirect3DDevice3 *device;
12279 IDirectDrawSurface4 *rt;
12280 ULONG refcount;
12281 D3DCOLOR color;
12282 HWND window;
12283 HRESULT hr;
12285 window = create_window();
12286 if (!(device = create_device(window, DDSCL_NORMAL)))
12288 skip("Failed to create a 3D device, skipping test.\n");
12289 DestroyWindow(window);
12290 return;
12293 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
12294 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
12296 viewport = create_viewport(device, 0, 0, 640, 480);
12297 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
12298 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
12300 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
12301 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12302 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
12303 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
12304 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
12305 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
12306 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
12307 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
12308 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
12309 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
12310 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
12311 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
12312 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
12313 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
12315 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0xff404040);
12316 ok(SUCCEEDED(hr), "Failed to set texture factor, hr %#x.\n", hr);
12317 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_ADD);
12318 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
12319 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
12320 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12321 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_SPECULAR);
12322 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12323 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_MODULATE);
12324 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
12325 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TFACTOR);
12326 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12327 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
12328 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12330 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
12331 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12333 hr = IDirect3DDevice3_BeginScene(device);
12334 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12336 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
12337 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12339 hr = IDirect3DDevice3_EndScene(device);
12340 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12342 color = get_surface_color(rt, 320, 240);
12343 ok(compare_color(color, 0x00404040, 1), "Got unexpected color 0x%08x.\n", color);
12345 destroy_viewport(device, viewport);
12346 IDirectDrawSurface4_Release(rt);
12347 refcount = IDirect3DDevice3_Release(device);
12348 ok(!refcount, "Device has %u references left.\n", refcount);
12349 DestroyWindow(window);
12352 static void test_getdc(void)
12354 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
12355 IDirectDrawSurface4 *surface, *surface2, *tmp;
12356 DDSURFACEDESC2 surface_desc, map_desc;
12357 IDirectDraw4 *ddraw;
12358 unsigned int i;
12359 HWND window;
12360 HDC dc, dc2;
12361 HRESULT hr;
12363 static const struct
12365 const char *name;
12366 DDPIXELFORMAT format;
12367 BOOL getdc_supported;
12368 HRESULT alt_result;
12370 test_data[] =
12372 {"D3DFMT_A8R8G8B8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
12373 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}}, TRUE},
12374 {"D3DFMT_X8R8G8B8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
12375 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}}, TRUE},
12376 {"D3DFMT_R5G6B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
12377 {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}}, TRUE},
12378 {"D3DFMT_X1R5G5B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
12379 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}}, TRUE},
12380 {"D3DFMT_A1R5G5B5", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
12381 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}}, TRUE},
12382 {"D3DFMT_A4R4G4B4", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
12383 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
12384 {"D3DFMT_X4R4G4B4", {sizeof(test_data->format), DDPF_RGB, 0, {16},
12385 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
12386 {"D3DFMT_A2R10G10B10", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
12387 {0xc0000000}, {0x3ff00000}, {0x000ffc00}, {0x000003ff}}, TRUE},
12388 {"D3DFMT_A8B8G8R8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
12389 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
12390 {"D3DFMT_X8B8G8R8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
12391 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
12392 {"D3DFMT_R3G3B2", {sizeof(test_data->format), DDPF_RGB, 0, {8},
12393 {0x000000e0}, {0x0000001c}, {0x00000003}, {0x00000000}}, FALSE},
12394 /* GetDC() on a P8 surface fails unless the display mode is 8 bpp.
12395 * This is not implemented in wine yet, so disable the test for now.
12396 * Succeeding P8 GetDC() calls are tested in the ddraw:visual test.
12397 {"D3DFMT_P8", {sizeof(test_data->format), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0, {8 },
12398 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12400 {"D3DFMT_L8", {sizeof(test_data->format), DDPF_LUMINANCE, 0, {8},
12401 {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12402 {"D3DFMT_A8L8", {sizeof(test_data->format), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0, {16},
12403 {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}}, FALSE},
12404 {"D3DFMT_DXT1", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'), {0},
12405 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12406 {"D3DFMT_DXT2", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'), {0},
12407 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12408 {"D3DFMT_DXT3", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'), {0},
12409 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12410 {"D3DFMT_DXT4", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'), {0},
12411 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12412 {"D3DFMT_DXT5", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'), {0},
12413 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12416 window = create_window();
12417 ddraw = create_ddraw();
12418 ok(!!ddraw, "Failed to create a ddraw object.\n");
12419 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12420 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12422 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
12424 memset(&surface_desc, 0, sizeof(surface_desc));
12425 surface_desc.dwSize = sizeof(surface_desc);
12426 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12427 surface_desc.dwWidth = 64;
12428 surface_desc.dwHeight = 64;
12429 U4(surface_desc).ddpfPixelFormat = test_data[i].format;
12430 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12432 if (FAILED(IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
12434 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
12435 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
12436 if (FAILED(hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
12438 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
12439 continue;
12443 dc = (void *)0x1234;
12444 hr = IDirectDrawSurface4_GetDC(surface, &dc);
12445 if (test_data[i].getdc_supported)
12446 ok(SUCCEEDED(hr) || broken(hr == test_data[i].alt_result),
12447 "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12448 else
12449 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12451 if (SUCCEEDED(hr))
12453 unsigned int width_bytes;
12454 DIBSECTION dib;
12455 HBITMAP bitmap;
12456 DWORD type;
12457 int size;
12459 type = GetObjectType(dc);
12460 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
12461 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
12462 type = GetObjectType(bitmap);
12463 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
12465 size = GetObjectA(bitmap, sizeof(dib), &dib);
12466 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, test_data[i].name);
12467 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
12468 dib.dsBm.bmType, test_data[i].name);
12469 ok(dib.dsBm.bmWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
12470 dib.dsBm.bmWidth, test_data[i].name);
12471 ok(dib.dsBm.bmHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
12472 dib.dsBm.bmHeight, test_data[i].name);
12473 width_bytes = ((dib.dsBm.bmWidth * U1(test_data[i].format).dwRGBBitCount + 31) >> 3) & ~3;
12474 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
12475 dib.dsBm.bmWidthBytes, test_data[i].name);
12476 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
12477 dib.dsBm.bmPlanes, test_data[i].name);
12478 ok(dib.dsBm.bmBitsPixel == U1(test_data[i].format).dwRGBBitCount,
12479 "Got unexpected bit count %d for format %s.\n",
12480 dib.dsBm.bmBitsPixel, test_data[i].name);
12481 ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n",
12482 dib.dsBm.bmBits, test_data[i].name);
12484 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
12485 dib.dsBmih.biSize, test_data[i].name);
12486 ok(dib.dsBmih.biWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
12487 dib.dsBmih.biHeight, test_data[i].name);
12488 ok(dib.dsBmih.biHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
12489 dib.dsBmih.biHeight, test_data[i].name);
12490 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
12491 dib.dsBmih.biPlanes, test_data[i].name);
12492 ok(dib.dsBmih.biBitCount == U1(test_data[i].format).dwRGBBitCount,
12493 "Got unexpected bit count %u for format %s.\n",
12494 dib.dsBmih.biBitCount, test_data[i].name);
12495 ok(dib.dsBmih.biCompression == (U1(test_data[i].format).dwRGBBitCount == 16 ? BI_BITFIELDS : BI_RGB)
12496 || broken(U1(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
12497 "Got unexpected compression %#x for format %s.\n",
12498 dib.dsBmih.biCompression, test_data[i].name);
12499 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
12500 dib.dsBmih.biSizeImage, test_data[i].name);
12501 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
12502 dib.dsBmih.biXPelsPerMeter, test_data[i].name);
12503 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
12504 dib.dsBmih.biYPelsPerMeter, test_data[i].name);
12505 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
12506 dib.dsBmih.biClrUsed, test_data[i].name);
12507 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
12508 dib.dsBmih.biClrImportant, test_data[i].name);
12510 if (dib.dsBmih.biCompression == BI_BITFIELDS)
12512 ok((dib.dsBitfields[0] == U2(test_data[i].format).dwRBitMask
12513 && dib.dsBitfields[1] == U3(test_data[i].format).dwGBitMask
12514 && dib.dsBitfields[2] == U4(test_data[i].format).dwBBitMask)
12515 || broken(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2]),
12516 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
12517 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
12519 else
12521 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
12522 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
12523 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
12525 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, test_data[i].name);
12526 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, test_data[i].name);
12528 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
12529 ok(hr == DD_OK, "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12531 else
12533 ok(!dc, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
12536 IDirectDrawSurface4_Release(surface);
12538 if (FAILED(hr))
12539 continue;
12541 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
12542 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
12543 if (FAILED(hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
12545 skip("Failed to create mip-mapped texture for format %s (hr %#x), skipping tests.\n",
12546 test_data[i].name, hr);
12547 continue;
12550 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &tmp);
12551 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
12552 hr = IDirectDrawSurface4_GetAttachedSurface(tmp, &caps, &surface2);
12553 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
12554 IDirectDrawSurface4_Release(tmp);
12556 hr = IDirectDrawSurface4_GetDC(surface, &dc);
12557 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12558 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
12559 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12560 hr = IDirectDrawSurface4_GetDC(surface2, &dc);
12561 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12562 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc);
12563 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12565 hr = IDirectDrawSurface4_GetDC(surface, &dc);
12566 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12567 dc2 = (void *)0x1234;
12568 hr = IDirectDrawSurface4_GetDC(surface, &dc2);
12569 ok(hr == DDERR_DCALREADYCREATED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12570 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
12571 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
12572 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12573 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
12574 ok(hr == DDERR_NODC, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12576 map_desc.dwSize = sizeof(map_desc);
12577 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12578 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12579 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12580 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12581 hr = IDirectDrawSurface4_Unlock(surface, NULL);
12582 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12583 hr = IDirectDrawSurface4_Unlock(surface, NULL);
12584 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12586 hr = IDirectDrawSurface4_GetDC(surface, &dc);
12587 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12588 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12589 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12590 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
12591 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12593 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12594 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12595 hr = IDirectDrawSurface4_GetDC(surface, &dc);
12596 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12597 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
12598 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12599 hr = IDirectDrawSurface4_Unlock(surface, NULL);
12600 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12602 hr = IDirectDrawSurface4_GetDC(surface, &dc);
12603 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12604 hr = IDirectDrawSurface4_GetDC(surface2, &dc2);
12605 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12606 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc2);
12607 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12608 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
12609 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12611 hr = IDirectDrawSurface4_GetDC(surface2, &dc);
12612 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12613 hr = IDirectDrawSurface4_GetDC(surface, &dc2);
12614 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12615 hr = IDirectDrawSurface4_ReleaseDC(surface, dc2);
12616 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12617 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc);
12618 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12620 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12621 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12622 hr = IDirectDrawSurface4_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12623 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12624 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
12625 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12626 hr = IDirectDrawSurface4_Unlock(surface, NULL);
12627 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12629 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12630 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12631 hr = IDirectDrawSurface4_GetDC(surface, &dc);
12632 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12633 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
12634 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12635 hr = IDirectDrawSurface4_Unlock(surface, NULL);
12636 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12638 hr = IDirectDrawSurface4_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12639 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12640 hr = IDirectDrawSurface4_GetDC(surface, &dc);
12641 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12642 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
12643 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12644 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
12645 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12647 hr = IDirectDrawSurface4_GetDC(surface, &dc);
12648 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12649 hr = IDirectDrawSurface4_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12650 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12651 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
12652 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12653 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
12654 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12656 hr = IDirectDrawSurface4_GetDC(surface2, &dc);
12657 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12658 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12659 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12660 hr = IDirectDrawSurface4_Unlock(surface, NULL);
12661 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12662 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc);
12663 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12665 hr = IDirectDrawSurface4_Unlock(surface, NULL);
12666 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12667 hr = IDirectDrawSurface4_GetDC(surface2, &dc);
12668 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12669 hr = IDirectDrawSurface4_Unlock(surface, NULL);
12670 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12671 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc);
12672 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12673 hr = IDirectDrawSurface4_Unlock(surface, NULL);
12674 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12676 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
12677 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12678 hr = IDirectDrawSurface4_GetDC(surface, &dc);
12679 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12680 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
12681 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12682 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
12683 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12684 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
12685 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12687 IDirectDrawSurface4_Release(surface2);
12688 IDirectDrawSurface4_Release(surface);
12691 IDirectDraw4_Release(ddraw);
12692 DestroyWindow(window);
12695 static void test_draw_primitive(void)
12697 static WORD indices[] = {0, 1, 2, 3};
12698 static struct vec3 quad[] =
12700 {-1.0f, -1.0f, 0.0f},
12701 {-1.0f, 1.0f, 0.0f},
12702 { 1.0f, -1.0f, 0.0f},
12703 { 1.0f, 1.0f, 0.0f},
12705 D3DDRAWPRIMITIVESTRIDEDDATA strided;
12706 IDirect3DViewport3 *viewport;
12707 D3DVERTEXBUFFERDESC vb_desc;
12708 IDirect3DVertexBuffer *vb;
12709 IDirect3DDevice3 *device;
12710 IDirect3D3 *d3d;
12711 ULONG refcount;
12712 HWND window;
12713 HRESULT hr;
12714 void *data;
12716 window = create_window();
12717 if (!(device = create_device(window, DDSCL_NORMAL)))
12719 skip("Failed to create a 3D device, skipping test.\n");
12720 DestroyWindow(window);
12721 return;
12724 viewport = create_viewport(device, 0, 0, 640, 480);
12725 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
12726 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
12728 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
12729 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
12731 memset(&vb_desc, 0, sizeof(vb_desc));
12732 vb_desc.dwSize = sizeof(vb_desc);
12733 vb_desc.dwFVF = D3DFVF_XYZ;
12734 vb_desc.dwNumVertices = 4;
12735 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &vb, 0, NULL);
12736 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
12738 IDirect3D3_Release(d3d);
12740 memset(&strided, 0, sizeof(strided));
12742 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, NULL, 0, 0);
12743 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12744 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device,
12745 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, NULL, 0, 0);
12746 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12747 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, NULL, 0, 0);
12748 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12749 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, 0);
12750 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12751 hr = IDirect3DDevice3_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, 0);
12752 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12753 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, 0);
12754 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12756 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, indices, 4, 0);
12757 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12758 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device,
12759 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, indices, 4, 0);
12760 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12761 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, indices, 4, 0);
12762 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12764 strided.position.lpvData = quad;
12765 strided.position.dwStride = sizeof(*quad);
12766 hr = IDirect3DVertexBuffer_Lock(vb, 0, &data, NULL);
12767 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
12768 memcpy(data, quad, sizeof(quad));
12769 hr = IDirect3DVertexBuffer_Unlock(vb);
12770 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
12772 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, NULL, 0, 0);
12773 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12774 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device,
12775 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, NULL, 0, 0);
12776 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12777 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, NULL, 0, 0);
12778 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12779 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
12780 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12781 hr = IDirect3DDevice3_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, 0);
12782 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12783 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
12784 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12785 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, indices, 4, 0);
12786 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12787 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device,
12788 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, indices, 4, 0);
12789 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12790 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, indices, 4, 0);
12791 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12793 IDirect3DVertexBuffer_Release(vb);
12794 destroy_viewport(device, viewport);
12795 refcount = IDirect3DDevice3_Release(device);
12796 ok(!refcount, "Device has %u references left.\n", refcount);
12797 DestroyWindow(window);
12800 static void test_edge_antialiasing_blending(void)
12802 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
12803 IDirectDrawSurface4 *offscreen, *ds;
12804 D3DDEVICEDESC hal_desc, hel_desc;
12805 IDirect3DViewport3 *viewport;
12806 DDSURFACEDESC2 surface_desc;
12807 IDirect3DDevice3 *device;
12808 IDirectDraw4 *ddraw;
12809 IDirect3D3 *d3d;
12810 ULONG refcount;
12811 D3DCOLOR color;
12812 HWND window;
12813 HRESULT hr;
12815 static D3DMATRIX mat =
12817 1.0f, 0.0f, 0.0f, 0.0f,
12818 0.0f, 1.0f, 0.0f, 0.0f,
12819 0.0f, 0.0f, 1.0f, 0.0f,
12820 0.0f, 0.0f, 0.0f, 1.0f,
12822 static struct
12824 struct vec3 position;
12825 DWORD diffuse;
12827 green_quad[] =
12829 {{-1.0f, -1.0f, 0.1f}, 0x7f00ff00},
12830 {{-1.0f, 1.0f, 0.1f}, 0x7f00ff00},
12831 {{ 1.0f, -1.0f, 0.1f}, 0x7f00ff00},
12832 {{ 1.0f, 1.0f, 0.1f}, 0x7f00ff00},
12834 static struct
12836 struct vec3 position;
12837 DWORD diffuse;
12839 red_quad[] =
12841 {{-1.0f, -1.0f, 0.1f}, 0xccff0000},
12842 {{-1.0f, 1.0f, 0.1f}, 0xccff0000},
12843 {{ 1.0f, -1.0f, 0.1f}, 0xccff0000},
12844 {{ 1.0f, 1.0f, 0.1f}, 0xccff0000},
12847 window = create_window();
12848 if (!(device = create_device(window, DDSCL_NORMAL)))
12850 skip("Failed to create a 3D device.\n");
12851 DestroyWindow(window);
12852 return;
12855 memset(&hal_desc, 0, sizeof(hal_desc));
12856 hal_desc.dwSize = sizeof(hal_desc);
12857 memset(&hel_desc, 0, sizeof(hel_desc));
12858 hel_desc.dwSize = sizeof(hel_desc);
12859 hr = IDirect3DDevice3_GetCaps(device, &hal_desc, &hel_desc);
12860 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
12861 trace("HAL line edge antialiasing support: %#x.\n",
12862 hal_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12863 trace("HAL triangle edge antialiasing support: %#x.\n",
12864 hal_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12865 trace("HEL line edge antialiasing support: %#x.\n",
12866 hel_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12867 trace("HEL triangle edge antialiasing support: %#x.\n",
12868 hel_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12870 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
12871 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
12872 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
12873 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
12874 IDirect3D3_Release(d3d);
12876 memset(&surface_desc, 0, sizeof(surface_desc));
12877 surface_desc.dwSize = sizeof(surface_desc);
12878 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
12879 surface_desc.dwWidth = 640;
12880 surface_desc.dwHeight = 480;
12881 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
12882 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
12883 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
12884 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
12885 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
12886 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
12887 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
12888 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
12889 ok(hr == D3D_OK, "Creating the offscreen render target failed, hr %#x.\n", hr);
12891 ds = get_depth_stencil(device);
12892 hr = IDirectDrawSurface4_AddAttachedSurface(offscreen, ds);
12893 todo_wine ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
12894 IDirectDrawSurface4_Release(ds);
12896 hr = IDirect3DDevice3_SetRenderTarget(device, offscreen, 0);
12897 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
12899 viewport = create_viewport(device, 0, 0, 640, 480);
12900 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
12901 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
12903 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
12904 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12905 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
12906 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
12907 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
12908 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
12909 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
12910 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
12911 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
12912 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
12913 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
12914 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
12915 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
12916 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
12918 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
12919 ok(SUCCEEDED(hr), "Failed to enable blending, hr %#x.\n", hr);
12920 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
12921 ok(SUCCEEDED(hr), "Failed to set src blend, hr %#x.\n", hr);
12922 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
12923 ok(SUCCEEDED(hr), "Failed to set dest blend, hr %#x.\n", hr);
12925 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
12926 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
12927 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
12928 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12929 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
12930 ok(SUCCEEDED(hr), "Failed to set alpha op, hr %#x.\n", hr);
12931 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
12932 ok(SUCCEEDED(hr), "Failed to set alpha arg, hr %#x.\n", hr);
12934 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
12935 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12936 hr = IDirect3DDevice3_BeginScene(device);
12937 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12938 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12939 green_quad, 4, 0);
12940 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12941 hr = IDirect3DDevice3_EndScene(device);
12942 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12943 color = get_surface_color(offscreen, 320, 240);
12944 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
12946 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
12947 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12948 hr = IDirect3DDevice3_BeginScene(device);
12949 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12950 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12951 red_quad, 4, 0);
12952 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12953 hr = IDirect3DDevice3_EndScene(device);
12954 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12955 color = get_surface_color(offscreen, 320, 240);
12956 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
12958 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
12959 ok(SUCCEEDED(hr), "Failed to disable blending, hr %#x.\n", hr);
12961 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
12962 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12963 hr = IDirect3DDevice3_BeginScene(device);
12964 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12965 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12966 green_quad, 4, 0);
12967 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12968 hr = IDirect3DDevice3_EndScene(device);
12969 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12970 color = get_surface_color(offscreen, 320, 240);
12971 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12973 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
12974 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12975 hr = IDirect3DDevice3_BeginScene(device);
12976 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12977 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12978 red_quad, 4, 0);
12979 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12980 hr = IDirect3DDevice3_EndScene(device);
12981 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12982 color = get_surface_color(offscreen, 320, 240);
12983 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12985 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_EDGEANTIALIAS, TRUE);
12986 ok(SUCCEEDED(hr), "Failed to enable edge antialiasing, hr %#x.\n", hr);
12988 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
12989 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12990 hr = IDirect3DDevice3_BeginScene(device);
12991 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12992 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12993 green_quad, 4, 0);
12994 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12995 hr = IDirect3DDevice3_EndScene(device);
12996 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12997 color = get_surface_color(offscreen, 320, 240);
12998 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
13000 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
13001 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
13002 hr = IDirect3DDevice3_BeginScene(device);
13003 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13004 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
13005 red_quad, 4, 0);
13006 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13007 hr = IDirect3DDevice3_EndScene(device);
13008 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13009 color = get_surface_color(offscreen, 320, 240);
13010 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
13012 IDirectDrawSurface4_Release(offscreen);
13013 IDirectDraw4_Release(ddraw);
13014 destroy_viewport(device, viewport);
13015 refcount = IDirect3DDevice3_Release(device);
13016 ok(!refcount, "Device has %u references left.\n", refcount);
13017 DestroyWindow(window);
13020 /* TransformVertices always writes 32 bytes regardless of the input / output stride.
13021 * The stride is honored for navigating to the next vertex. 3 floats input position
13022 * are read, and 16 bytes extra vertex data are copied around. */
13023 struct transform_input
13025 float x, y, z, unused1; /* Position data, transformed. */
13026 DWORD v1, v2, v3, v4; /* Extra data, e.g. color and texture coords, copied. */
13027 DWORD unused2;
13030 struct transform_output
13032 float x, y, z, w;
13033 DWORD v1, v2, v3, v4;
13034 DWORD unused3, unused4;
13037 static void test_transform_vertices(void)
13039 IDirect3DDevice3 *device;
13040 IDirectDrawSurface4 *rt;
13041 ULONG refcount;
13042 HWND window;
13043 HRESULT hr;
13044 D3DCOLOR color;
13045 IDirect3DViewport3 *viewport;
13046 static struct transform_input position_tests[] =
13048 { 0.0f, 0.0f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
13049 { 1.0f, 1.0f, 1.0f, 8.0f, 6, 7, 8, 9, 10},
13050 {-1.0f, -1.0f, -1.0f, 4.0f, 11, 12, 13, 14, 15},
13051 { 0.5f, 0.5f, 0.5f, 2.0f, 16, 17, 18, 19, 20},
13052 {-0.5f, -0.5f, -0.5f, 1.0f, ~1U, ~2U, ~3U, ~4U, ~5U},
13053 {-0.5f, -0.5f, 0.0f, 0.0f, ~6U, ~7U, ~8U, ~9U, ~0U},
13055 static struct transform_input cliptest[] =
13057 { 25.59f, 25.59f, 1.0f, 0.0f, 1, 2, 3, 4, 5},
13058 { 25.61f, 25.61f, 1.01f, 0.0f, 1, 2, 3, 4, 5},
13059 {-25.59f, -25.59f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
13060 {-25.61f, -25.61f, -0.01f, 0.0f, 1, 2, 3, 4, 5},
13062 static struct transform_input offscreentest[] =
13064 {128.1f, 0.0f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
13066 struct transform_output out[ARRAY_SIZE(position_tests)];
13067 D3DHVERTEX out_h[ARRAY_SIZE(position_tests)];
13068 D3DTRANSFORMDATA transformdata;
13069 static const D3DVIEWPORT vp_template =
13071 sizeof(vp_template), 0, 0, 256, 256, 5.0f, 5.0f, 256.0f, 256.0f, -25.0f, 60.0f
13073 D3DVIEWPORT vp_data =
13075 sizeof(vp_data), 0, 0, 256, 256, 1.0f, 1.0f, 256.0f, 256.0f, 0.0f, 1.0f
13077 D3DVIEWPORT2 vp2_data;
13078 unsigned int i;
13079 DWORD offscreen;
13080 static D3DMATRIX mat_scale =
13082 2.0f, 0.0f, 0.0f, 0.0f,
13083 0.0f, 2.0f, 0.0f, 0.0f,
13084 0.0f, 0.0f, 2.0f, 0.0f,
13085 0.0f, 0.0f, 0.0f, 1.0f,
13087 mat_translate1 =
13089 1.0f, 0.0f, 0.0f, 0.0f,
13090 0.0f, 1.0f, 0.0f, 0.0f,
13091 0.0f, 0.0f, 1.0f, 0.0f,
13092 1.0f, 0.0f, 0.0f, 1.0f,
13094 mat_translate2 =
13096 1.0f, 0.0f, 0.0f, 0.0f,
13097 0.0f, 1.0f, 0.0f, 0.0f,
13098 0.0f, 0.0f, 1.0f, 0.0f,
13099 0.0f, 1.0f, 0.0f, 1.0f,
13101 mat_transform3 =
13103 1.0f, 0.0f, 0.0f, 0.0f,
13104 0.0f, 1.0f, 0.0f, 0.0f,
13105 0.0f, 0.0f, 1.0f, 0.0f,
13106 0.0f, 19.2f, 0.0f, 2.0f,
13108 mat_identity =
13110 1.0f, 0.0f, 0.0f, 0.0f,
13111 0.0f, 1.0f, 0.0f, 0.0f,
13112 0.0f, 0.0f, 1.0f, 0.0f,
13113 0.0f, 0.0f, 0.0f, 1.0f,
13115 static struct
13117 struct vec3 position;
13118 DWORD color;
13120 quad[] =
13122 {{-0.75f, -0.5f , 0.0f}, 0xffff0000},
13123 {{-0.75f, 0.25f, 0.0f}, 0xffff0000},
13124 {{ 0.5f, -0.5f , 0.0f}, 0xffff0000},
13125 {{ 0.5f, 0.25f, 0.0f}, 0xffff0000},
13127 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
13129 for (i = 0; i < ARRAY_SIZE(out); ++i)
13131 out[i].unused3 = 0xdeadbeef;
13132 out[i].unused4 = 0xcafecafe;
13135 window = create_window();
13136 if (!(device = create_device(window, DDSCL_NORMAL)))
13138 skip("Failed to create a 3D device.\n");
13139 DestroyWindow(window);
13140 return;
13142 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
13143 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
13145 viewport = create_viewport(device, 0, 0, 256, 256);
13146 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
13147 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
13149 memset(&transformdata, 0, sizeof(transformdata));
13150 transformdata.dwSize = sizeof(transformdata);
13151 transformdata.lpIn = position_tests;
13152 transformdata.dwInSize = sizeof(position_tests[0]);
13153 transformdata.lpOut = out;
13154 transformdata.dwOutSize = sizeof(out[0]);
13155 transformdata.lpHOut = NULL;
13157 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
13158 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
13159 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13160 ok(!offscreen, "Offscreen is %x.\n", offscreen);
13162 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
13164 static const struct vec4 cmp[] =
13166 {128.0f, 128.0f, 0.0f, 1.0f}, {129.0f, 127.0f, 1.0f, 1.0f}, {127.0f, 129.0f, -1.0f, 1.0f},
13167 {128.5f, 127.5f, 0.5f, 1.0f}, {127.5f, 128.5f, -0.5f, 1.0f}, {127.5f, 128.5f, 0.0f, 1.0f}
13170 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
13171 "Vertex %u differs. Got %f %f %f %f.\n", i,
13172 out[i].x, out[i].y, out[i].z, out[i].w);
13173 ok(out[i].v1 == position_tests[i].v1 && out[i].v2 == position_tests[i].v2
13174 && out[i].v3 == position_tests[i].v3 && out[i].v4 == position_tests[i].v4,
13175 "Vertex %u payload is %u %u %u %u.\n", i, out[i].v1, out[i].v2, out[i].v3, out[i].v4);
13176 ok(out[i].unused3 == 0xdeadbeef && out[i].unused4 == 0xcafecafe,
13177 "Vertex %u unused data is %#x, %#x.\n", i, out[i].unused3, out[i].unused4);
13180 vp_data = vp_template;
13181 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
13182 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
13183 offscreen = 0xdeadbeef;
13184 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
13185 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
13186 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13187 ok(!offscreen, "Offscreen is %x.\n", offscreen);
13189 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
13191 static const struct vec4 cmp[] =
13193 {128.0f, 128.0f, 0.0f, 1.0f}, {133.0f, 123.0f, 1.0f, 1.0f}, {123.0f, 133.0f, -1.0f, 1.0f},
13194 {130.5f, 125.5f, 0.5f, 1.0f}, {125.5f, 130.5f, -0.5f, 1.0f}, {125.5f, 130.5f, 0.0f, 1.0f}
13196 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
13197 "Vertex %u differs. Got %f %f %f %f.\n", i,
13198 out[i].x, out[i].y, out[i].z, out[i].w);
13201 vp_data.dwX = 10;
13202 vp_data.dwY = 20;
13203 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
13204 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
13205 offscreen = 0xdeadbeef;
13206 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
13207 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
13208 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13209 ok(!offscreen, "Offscreen is %x.\n", offscreen);
13210 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
13212 static const struct vec4 cmp[] =
13214 {138.0f, 148.0f, 0.0f, 1.0f}, {143.0f, 143.0f, 1.0f, 1.0f}, {133.0f, 153.0f, -1.0f, 1.0f},
13215 {140.5f, 145.5f, 0.5f, 1.0f}, {135.5f, 150.5f, -0.5f, 1.0f}, {135.5f, 150.5f, 0.0f, 1.0f}
13217 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
13218 "Vertex %u differs. Got %f %f %f %f.\n", i,
13219 out[i].x, out[i].y, out[i].z, out[i].w);
13222 transformdata.lpHOut = out_h;
13223 offscreen = 0xdeadbeef;
13224 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
13225 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
13226 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13227 ok(!offscreen, "Offscreen is %x.\n", offscreen);
13228 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
13230 static const D3DHVERTEX cmp_h[] =
13232 {0, { 0.0f}, { 0.0f}, { 0.0f}}, {0, { 1.0f}, { 1.0f}, {1.0f}},
13233 {D3DCLIP_FRONT, {-1.0f}, {-1.0f}, {-1.0f}}, {0, { 0.5f}, { 0.5f}, {0.5f}},
13234 {D3DCLIP_FRONT, {-0.5f}, {-0.5f}, {-0.5f}}, {0, {-0.5f}, {-0.5f}, {0.0f}}
13236 ok(compare_float(U1(cmp_h[i]).hx, U1(out_h[i]).hx, 4096)
13237 && compare_float(U2(cmp_h[i]).hy, U2(out_h[i]).hy, 4096)
13238 && compare_float(U3(cmp_h[i]).hz, U3(out_h[i]).hz, 4096)
13239 && cmp_h[i].dwFlags == out_h[i].dwFlags,
13240 "HVertex %u differs. Got %#x %f %f %f.\n", i,
13241 out_h[i].dwFlags, U1(out_h[i]).hx, U2(out_h[i]).hy, U3(out_h[i]).hz);
13243 /* No scheme has been found behind those return values. It seems to be
13244 * whatever data windows has when throwing the vertex away. Modify the
13245 * input test vertices to test this more. Depending on the input data
13246 * it can happen that the z coord gets written into y, or similar things. */
13247 if (0)
13249 static const struct vec4 cmp[] =
13251 {138.0f, 148.0f, 0.0f, 1.0f}, {143.0f, 143.0f, 1.0f, 1.0f}, { -1.0f, -1.0f, 0.5f, 1.0f},
13252 {140.5f, 145.5f, 0.5f, 1.0f}, { -0.5f, -0.5f, -0.5f, 1.0f}, {135.5f, 150.5f, 0.0f, 1.0f}
13254 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
13255 "Vertex %u differs. Got %f %f %f %f.\n", i,
13256 out[i].x, out[i].y, out[i].z, out[i].w);
13260 transformdata.lpIn = cliptest;
13261 transformdata.dwInSize = sizeof(cliptest[0]);
13262 offscreen = 0xdeadbeef;
13263 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
13264 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
13265 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13266 ok(!offscreen, "Offscreen is %x.\n", offscreen);
13267 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
13269 static const DWORD flags[] =
13272 D3DCLIP_RIGHT | D3DCLIP_BACK | D3DCLIP_TOP,
13274 D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
13276 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
13279 vp_data = vp_template;
13280 vp_data.dwWidth = 10;
13281 vp_data.dwHeight = 480;
13282 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
13283 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
13284 offscreen = 0xdeadbeef;
13285 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
13286 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
13287 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13288 ok(!offscreen, "Offscreen is %x.\n", offscreen);
13289 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
13291 static const DWORD flags[] =
13293 D3DCLIP_RIGHT,
13294 D3DCLIP_RIGHT | D3DCLIP_BACK,
13295 D3DCLIP_LEFT,
13296 D3DCLIP_LEFT | D3DCLIP_FRONT,
13298 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
13301 vp_data = vp_template;
13302 vp_data.dwWidth = 256;
13303 vp_data.dwHeight = 256;
13304 vp_data.dvScaleX = 1;
13305 vp_data.dvScaleY = 1;
13306 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
13307 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
13308 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
13309 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
13310 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13311 ok(!offscreen, "Offscreen is %x.\n", offscreen);
13312 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
13314 static const DWORD flags[] =
13317 D3DCLIP_BACK,
13319 D3DCLIP_FRONT,
13321 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
13324 /* Finally try to figure out how the DWORD dwOffscreen works.
13325 * It is a logical AND of the vertices' dwFlags members. */
13326 vp_data = vp_template;
13327 vp_data.dwWidth = 5;
13328 vp_data.dwHeight = 5;
13329 vp_data.dvScaleX = 10000.0f;
13330 vp_data.dvScaleY = 10000.0f;
13331 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
13332 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
13333 transformdata.lpIn = cliptest;
13334 offscreen = 0xdeadbeef;
13335 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
13336 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
13337 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13338 ok(!offscreen, "Offscreen is %x.\n", offscreen);
13340 offscreen = 0xdeadbeef;
13341 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
13342 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
13343 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13344 ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
13345 offscreen = 0xdeadbeef;
13346 hr = IDirect3DViewport2_TransformVertices(viewport, 2,
13347 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
13348 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13349 ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
13350 hr = IDirect3DViewport2_TransformVertices(viewport, 3,
13351 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
13352 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13353 ok(!offscreen, "Offscreen is %x.\n", offscreen);
13355 transformdata.lpIn = cliptest + 1;
13356 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
13357 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
13358 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13359 ok(offscreen == (D3DCLIP_BACK | D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
13361 transformdata.lpIn = cliptest + 2;
13362 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
13363 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
13364 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13365 ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
13366 offscreen = 0xdeadbeef;
13367 hr = IDirect3DViewport2_TransformVertices(viewport, 2,
13368 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
13369 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13370 ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
13372 transformdata.lpIn = cliptest + 3;
13373 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
13374 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
13375 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13376 ok(offscreen == (D3DCLIP_FRONT | D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
13378 transformdata.lpIn = offscreentest;
13379 transformdata.dwInSize = sizeof(offscreentest[0]);
13380 vp_data = vp_template;
13381 vp_data.dwWidth = 257;
13382 vp_data.dwHeight = 257;
13383 vp_data.dvScaleX = 1.0f;
13384 vp_data.dvScaleY = 1.0f;
13385 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
13386 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
13387 offscreen = 0xdeadbeef;
13388 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
13389 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
13390 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13391 ok(!offscreen, "Offscreen is %x.\n", offscreen);
13393 vp_data.dwWidth = 256;
13394 vp_data.dwHeight = 256;
13395 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
13396 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
13397 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
13398 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
13399 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13400 ok(offscreen == D3DCLIP_RIGHT, "Offscreen is %x.\n", offscreen);
13402 /* Test the effect of Matrices.
13404 * Basically the x coordinate ends up as ((x + 1) * 2 + 0) * 5 and
13405 * y as ((y + 0) * 2 + 1) * 5. The 5 comes from dvScaleX/Y, 2 from
13406 * the view matrix and the +1's from the world and projection matrix. */
13407 vp_data.dwX = 0;
13408 vp_data.dwY = 0;
13409 vp_data.dwWidth = 256;
13410 vp_data.dwHeight = 256;
13411 vp_data.dvScaleX = 5.0f;
13412 vp_data.dvScaleY = 5.0f;
13413 vp_data.dvMinZ = 0.0f;
13414 vp_data.dvMaxZ = 1.0f;
13415 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
13416 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
13418 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat_translate1);
13419 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
13420 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat_scale);
13421 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
13422 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat_translate2);
13423 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
13425 transformdata.lpIn = position_tests;
13426 transformdata.dwInSize = sizeof(position_tests[0]);
13427 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
13428 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
13429 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13431 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
13433 static const struct vec4 cmp[] =
13435 {138.0f, 123.0f, 0.0f, 1.0f}, {148.0f, 113.0f, 2.0f, 1.0f}, {128.0f, 133.0f, -2.0f, 1.0f},
13436 {143.0f, 118.0f, 1.0f, 1.0f}, {133.0f, 128.0f, -1.0f, 1.0f}, {133.0f, 128.0f, 0.0f, 1.0f}
13439 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
13440 "Vertex %u differs. Got %f %f %f %f.\n", i,
13441 out[i].x, out[i].y, out[i].z, out[i].w);
13444 /* Invalid flags. */
13445 offscreen = 0xdeadbeef;
13446 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
13447 &transformdata, 0, &offscreen);
13448 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
13449 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
13451 /* NULL transform data. */
13452 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
13453 NULL, D3DTRANSFORM_UNCLIPPED, &offscreen);
13454 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
13455 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
13456 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
13457 NULL, D3DTRANSFORM_UNCLIPPED, &offscreen);
13458 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
13459 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
13461 /* NULL transform data and NULL dwOffscreen.
13463 * Valid transform data + NULL dwOffscreen -> crash. */
13464 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
13465 NULL, D3DTRANSFORM_UNCLIPPED, NULL);
13466 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
13468 /* No vertices. */
13469 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
13470 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
13471 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13472 ok(!offscreen, "Offscreen is %x.\n", offscreen);
13473 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
13474 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
13475 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13476 ok(offscreen == ~0U, "Offscreen is %x.\n", offscreen);
13478 /* Invalid sizes. */
13479 offscreen = 0xdeadbeef;
13480 transformdata.dwSize = sizeof(transformdata) - 1;
13481 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
13482 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
13483 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
13484 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
13485 transformdata.dwSize = sizeof(transformdata) + 1;
13486 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
13487 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
13488 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
13489 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
13491 /* NULL lpIn or lpOut -> crash, except when transforming 0 vertices. */
13492 transformdata.dwSize = sizeof(transformdata);
13493 transformdata.lpIn = NULL;
13494 transformdata.lpOut = NULL;
13495 offscreen = 0xdeadbeef;
13496 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
13497 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
13498 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13499 ok(offscreen == ~0U, "Offscreen is %x.\n", offscreen);
13501 /* Test how vertices are transformed during draws. */
13502 vp_data.dwX = 20;
13503 vp_data.dwY = 20;
13504 vp_data.dwWidth = 200;
13505 vp_data.dwHeight = 400;
13506 vp_data.dvScaleX = 20.0f;
13507 vp_data.dvScaleY = 50.0f;
13508 vp_data.dvMinZ = 0.0f;
13509 vp_data.dvMaxZ = 1.0f;
13510 hr = IDirect3DViewport3_SetViewport(viewport, &vp_data);
13511 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
13512 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
13513 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
13515 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
13516 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
13518 hr = IDirect3DDevice3_BeginScene(device);
13519 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13520 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
13521 quad, 4, 0);
13522 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13523 hr = IDirect3DDevice3_EndScene(device);
13524 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13526 color = get_surface_color(rt, 128, 143);
13527 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
13528 color = get_surface_color(rt, 132, 143);
13529 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
13530 color = get_surface_color(rt, 128, 147);
13531 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
13532 color = get_surface_color(rt, 132, 147);
13533 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
13535 color = get_surface_color(rt, 177, 217);
13536 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
13537 color = get_surface_color(rt, 181, 217);
13538 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
13539 color = get_surface_color(rt, 177, 221);
13540 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
13541 color = get_surface_color(rt, 181, 221);
13542 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
13544 /* Test D3DVIEWPORT2 behavior. */
13545 vp2_data.dwSize = sizeof(vp2_data);
13546 vp2_data.dwX = 20;
13547 vp2_data.dwY = 20;
13548 vp2_data.dwWidth = 200;
13549 vp2_data.dwHeight = 400;
13550 vp2_data.dvClipX = -0.5f;
13551 vp2_data.dvClipY = 4.0f;
13552 vp2_data.dvClipWidth = 5.0f;
13553 vp2_data.dvClipHeight = 10.0f;
13554 vp2_data.dvMinZ = 0.0f;
13555 vp2_data.dvMaxZ = 2.0f;
13556 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2_data);
13557 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
13558 transformdata.lpIn = position_tests;
13559 transformdata.lpOut = out;
13560 hr = IDirect3DViewport3_TransformVertices(viewport, ARRAY_SIZE(position_tests),
13561 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
13562 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13563 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
13565 static const struct vec4 cmp[] =
13567 {120.0f, 140.0f, 0.0f, 1.0f}, {200.0f, 60.0f, 1.0f, 1.0f}, {40.0f, 220.0f, -1.0f, 1.0f},
13568 {160.0f, 100.0f, 0.5f, 1.0f}, { 80.0f, 180.0f, -0.5f, 1.0f}, {80.0f, 180.0f, 0.0f, 1.0f}
13571 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
13572 "Vertex %u differs. Got %f %f %f %f.\n", i,
13573 out[i].x, out[i].y, out[i].z, out[i].w);
13576 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x0000ff00, 0.0f, 0);
13577 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
13579 hr = IDirect3DDevice3_BeginScene(device);
13580 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13581 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
13582 quad, 4, 0);
13583 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13584 hr = IDirect3DDevice3_EndScene(device);
13585 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13587 color = get_surface_color(rt, 58, 118);
13588 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
13589 color = get_surface_color(rt, 62, 118);
13590 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
13591 color = get_surface_color(rt, 58, 122);
13592 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
13593 color = get_surface_color(rt, 62, 122);
13594 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
13596 color = get_surface_color(rt, 157, 177);
13597 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
13598 color = get_surface_color(rt, 161, 177);
13599 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
13600 color = get_surface_color(rt, 157, 181);
13601 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
13602 color = get_surface_color(rt, 161, 181);
13603 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
13605 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat_identity);
13606 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
13607 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat_identity);
13608 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
13609 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat_transform3);
13610 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
13612 vp2_data.dwX = 0.0;
13613 vp2_data.dwY = 0.0;
13614 vp2_data.dwWidth = 1;
13615 vp2_data.dwHeight = 1;
13616 vp2_data.dvClipX = -12.8f;
13617 vp2_data.dvClipY = 12.8f + mat_transform3._42 / mat_transform3._44;
13618 vp2_data.dvClipWidth = 25.6f;
13619 vp2_data.dvClipHeight = 25.6f;
13620 vp2_data.dvMinZ = 0.0f;
13621 vp2_data.dvMaxZ = 0.5f;
13622 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2_data);
13623 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
13624 transformdata.lpIn = cliptest;
13625 transformdata.dwInSize = sizeof(cliptest[0]);
13626 offscreen = 0xdeadbeef;
13627 hr = IDirect3DViewport3_TransformVertices(viewport, ARRAY_SIZE(cliptest),
13628 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
13629 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
13630 ok(!offscreen, "Offscreen is %x.\n", offscreen);
13631 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
13633 static const D3DHVERTEX cmp_h[] =
13635 {0, { 25.59f}, { 44.79f}, { 1.0f }},
13636 {D3DCLIP_RIGHT | D3DCLIP_TOP | D3DCLIP_BACK, { 25.61f}, { 44.81f}, { 1.01f}},
13637 {0, {-25.59f}, {-6.39f }, { 0.0f }},
13638 {D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,{-25.61f}, {-6.41f }, {-0.01f}},
13640 ok(compare_float(U1(cmp_h[i]).hx, U1(out_h[i]).hx, 4096)
13641 && compare_float(U2(cmp_h[i]).hy, U2(out_h[i]).hy, 4096)
13642 && compare_float(U3(cmp_h[i]).hz, U3(out_h[i]).hz, 4096)
13643 && cmp_h[i].dwFlags == out_h[i].dwFlags,
13644 "HVertex %u differs. Got %#x %f %f %f.\n", i,
13645 out_h[i].dwFlags, U1(out_h[i]).hx, U2(out_h[i]).hy, U3(out_h[i]).hz);
13648 destroy_viewport(device, viewport);
13649 IDirectDrawSurface4_Release(rt);
13650 refcount = IDirect3DDevice3_Release(device);
13651 ok(!refcount, "Device has %u references left.\n", refcount);
13652 DestroyWindow(window);
13655 static void test_display_mode_surface_pixel_format(void)
13657 unsigned int width, height, bpp;
13658 IDirectDrawSurface4 *surface;
13659 DDSURFACEDESC2 surface_desc;
13660 IDirectDraw4 *ddraw;
13661 ULONG refcount;
13662 HWND window;
13663 HRESULT hr;
13665 if (!(ddraw = create_ddraw()))
13667 skip("Failed to create ddraw.\n");
13668 return;
13671 surface_desc.dwSize = sizeof(surface_desc);
13672 hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc);
13673 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
13674 width = surface_desc.dwWidth;
13675 height = surface_desc.dwHeight;
13677 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
13678 0, 0, width, height, NULL, NULL, NULL, NULL);
13679 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
13680 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13682 bpp = 0;
13683 if (SUCCEEDED(IDirectDraw4_SetDisplayMode(ddraw, width, height, 16, 0, 0)))
13684 bpp = 16;
13685 if (SUCCEEDED(IDirectDraw4_SetDisplayMode(ddraw, width, height, 24, 0, 0)))
13686 bpp = 24;
13687 if (SUCCEEDED(IDirectDraw4_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
13688 bpp = 32;
13689 ok(bpp, "Set display mode failed.\n");
13691 surface_desc.dwSize = sizeof(surface_desc);
13692 hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc);
13693 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
13694 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
13695 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
13696 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
13697 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
13699 memset(&surface_desc, 0, sizeof(surface_desc));
13700 surface_desc.dwSize = sizeof(surface_desc);
13701 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
13702 U5(surface_desc).dwBackBufferCount = 1;
13703 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE;
13704 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13705 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
13706 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
13707 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
13708 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
13709 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
13710 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
13711 U4(surface_desc).ddpfPixelFormat.dwFlags);
13712 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
13713 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
13714 IDirectDrawSurface4_Release(surface);
13716 memset(&surface_desc, 0, sizeof(surface_desc));
13717 surface_desc.dwSize = sizeof(surface_desc);
13718 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
13719 surface_desc.dwWidth = width;
13720 surface_desc.dwHeight = height;
13721 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13722 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13723 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
13724 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
13725 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
13726 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
13727 U4(surface_desc).ddpfPixelFormat.dwFlags);
13728 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
13729 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
13730 IDirectDrawSurface4_Release(surface);
13732 refcount = IDirectDraw4_Release(ddraw);
13733 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13734 DestroyWindow(window);
13737 static void test_surface_desc_size(void)
13739 union
13741 DWORD dwSize;
13742 DDSURFACEDESC desc1;
13743 DDSURFACEDESC2 desc2;
13744 BYTE blob[1024];
13745 } desc;
13746 IDirectDrawSurface4 *surface4;
13747 IDirectDrawSurface3 *surface3;
13748 IDirectDrawSurface *surface;
13749 DDSURFACEDESC2 surface_desc;
13750 HRESULT expected_hr, hr;
13751 IDirectDraw4 *ddraw;
13752 unsigned int i, j;
13753 ULONG refcount;
13755 static const struct
13757 unsigned int caps;
13758 const char *name;
13760 surface_caps[] =
13762 {DDSCAPS_OFFSCREENPLAIN, "offscreenplain"},
13763 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "systemmemory texture"},
13764 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "videomemory texture"},
13766 static const unsigned int desc_sizes[] =
13768 sizeof(DDSURFACEDESC),
13769 sizeof(DDSURFACEDESC2),
13770 sizeof(DDSURFACEDESC) + 1,
13771 sizeof(DDSURFACEDESC2) + 1,
13772 2 * sizeof(DDSURFACEDESC),
13773 2 * sizeof(DDSURFACEDESC2),
13774 sizeof(DDSURFACEDESC) - 1,
13775 sizeof(DDSURFACEDESC2) - 1,
13776 sizeof(DDSURFACEDESC) / 2,
13777 sizeof(DDSURFACEDESC2) / 2,
13781 sizeof(desc) / 2,
13782 sizeof(desc) - 100,
13785 if (!(ddraw = create_ddraw()))
13787 skip("Failed to create ddraw.\n");
13788 return;
13790 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
13791 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13793 for (i = 0; i < ARRAY_SIZE(surface_caps); ++i)
13795 memset(&surface_desc, 0, sizeof(surface_desc));
13796 surface_desc.dwSize = sizeof(surface_desc);
13797 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
13798 surface_desc.ddsCaps.dwCaps = surface_caps[i].caps;
13799 surface_desc.dwHeight = 128;
13800 surface_desc.dwWidth = 128;
13801 if (FAILED(IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL)))
13803 skip("Failed to create surface, type %s.\n", surface_caps[i].name);
13804 continue;
13806 hr = IDirectDrawSurface_QueryInterface(surface4, &IID_IDirectDrawSurface, (void **)&surface);
13807 ok(hr == DD_OK, "Failed to query IDirectDrawSurface, hr %#x, type %s.\n", hr, surface_caps[i].name);
13808 hr = IDirectDrawSurface_QueryInterface(surface4, &IID_IDirectDrawSurface3, (void **)&surface3);
13809 ok(hr == DD_OK, "Failed to query IDirectDrawSurface3, hr %#x, type %s.\n", hr, surface_caps[i].name);
13811 /* GetSurfaceDesc() */
13812 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13814 memset(&desc, 0, sizeof(desc));
13815 desc.dwSize = desc_sizes[j];
13816 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
13817 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc.desc1);
13818 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13819 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13821 memset(&desc, 0, sizeof(desc));
13822 desc.dwSize = desc_sizes[j];
13823 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
13824 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &desc.desc1);
13825 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13826 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13828 memset(&desc, 0, sizeof(desc));
13829 desc.dwSize = desc_sizes[j];
13830 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC2) ? DD_OK : DDERR_INVALIDPARAMS;
13831 hr = IDirectDrawSurface4_GetSurfaceDesc(surface4, &desc.desc2);
13832 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13833 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13836 /* Lock() */
13837 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13839 const BOOL valid_size = desc_sizes[j] == sizeof(DDSURFACEDESC)
13840 || desc_sizes[j] == sizeof(DDSURFACEDESC2);
13841 DWORD expected_texture_stage;
13843 memset(&desc, 0, sizeof(desc));
13844 desc.dwSize = desc_sizes[j];
13845 desc.desc2.dwTextureStage = 0xdeadbeef;
13846 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13847 hr = IDirectDrawSurface_Lock(surface, NULL, &desc.desc1, 0, 0);
13848 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13849 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13850 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13851 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
13852 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13853 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
13854 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13855 if (SUCCEEDED(hr))
13857 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
13858 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
13859 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
13860 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
13861 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13862 todo_wine_if(!expected_texture_stage)
13863 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13864 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
13865 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13866 IDirectDrawSurface_Unlock(surface, NULL);
13869 memset(&desc, 0, sizeof(desc));
13870 desc.dwSize = desc_sizes[j];
13871 desc.desc2.dwTextureStage = 0xdeadbeef;
13872 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13873 hr = IDirectDrawSurface3_Lock(surface3, NULL, &desc.desc1, 0, 0);
13874 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13875 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13876 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13877 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
13878 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13879 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
13880 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13881 if (SUCCEEDED(hr))
13883 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
13884 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
13885 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
13886 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
13887 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13888 todo_wine_if(!expected_texture_stage)
13889 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13890 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
13891 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13892 IDirectDrawSurface3_Unlock(surface3, NULL);
13895 memset(&desc, 0, sizeof(desc));
13896 desc.dwSize = desc_sizes[j];
13897 desc.desc2.dwTextureStage = 0xdeadbeef;
13898 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13899 hr = IDirectDrawSurface4_Lock(surface4, NULL, &desc.desc2, 0, 0);
13900 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13901 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13902 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13903 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
13904 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13905 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
13906 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13907 if (SUCCEEDED(hr))
13909 ok(desc.desc2.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
13910 desc.desc2.dwWidth, desc_sizes[j], surface_caps[i].name);
13911 ok(desc.desc2.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
13912 desc.desc2.dwHeight, desc_sizes[j], surface_caps[i].name);
13913 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13914 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13915 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
13916 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13917 IDirectDrawSurface4_Unlock(surface4, NULL);
13921 IDirectDrawSurface4_Release(surface4);
13922 IDirectDrawSurface3_Release(surface3);
13923 IDirectDrawSurface_Release(surface);
13926 /* GetDisplayMode() */
13927 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13929 memset(&desc, 0xcc, sizeof(desc));
13930 desc.dwSize = desc_sizes[j];
13931 expected_hr = (desc.dwSize == sizeof(DDSURFACEDESC) || desc.dwSize == sizeof(DDSURFACEDESC2))
13932 ? DD_OK : DDERR_INVALIDPARAMS;
13933 hr = IDirectDraw4_GetDisplayMode(ddraw, &desc.desc2);
13934 ok(hr == expected_hr, "Got hr %#x, expected %#x, size %u.\n", hr, expected_hr, desc_sizes[j]);
13935 if (SUCCEEDED(hr))
13937 ok(desc.dwSize == sizeof(DDSURFACEDESC2), "Wrong size %u for %u.\n", desc.dwSize, desc_sizes[j]);
13938 ok(desc.blob[desc_sizes[j]] == 0xcc, "Overflow for size %u.\n", desc_sizes[j]);
13939 ok(desc.blob[desc_sizes[j] - 1] != 0xcc, "Struct not cleared for size %u.\n", desc_sizes[j]);
13943 refcount = IDirectDraw4_Release(ddraw);
13944 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13947 static void test_get_surface_from_dc(void)
13949 IDirectDrawSurface *surface1, *tmp;
13950 IDirectDrawSurface4 *surface;
13951 DDSURFACEDESC2 surface_desc;
13952 IDirectDraw4 *ddraw;
13953 HDC dc, device_dc;
13954 ULONG refcount;
13955 HWND window;
13956 HRESULT hr;
13957 DWORD ret;
13959 window = create_window();
13960 ddraw = create_ddraw();
13961 ok(!!ddraw, "Failed to create a ddraw object.\n");
13962 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13963 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13965 memset(&surface_desc, 0, sizeof(surface_desc));
13966 surface_desc.dwSize = sizeof(surface_desc);
13967 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
13968 surface_desc.dwWidth = 64;
13969 surface_desc.dwHeight = 64;
13970 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13972 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13973 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13974 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirectDrawSurface, (void **)&surface1);
13975 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
13977 refcount = get_refcount((IUnknown *)surface1);
13978 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13979 refcount = get_refcount((IUnknown *)surface);
13980 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13982 hr = IDirectDrawSurface4_GetDC(surface, &dc);
13983 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
13985 tmp = (void *)0xdeadbeef;
13986 device_dc = (void *)0xdeadbeef;
13987 hr = GetSurfaceFromDC(NULL, &tmp, &device_dc);
13988 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13989 ok(!tmp, "Got unexpected surface %p.\n", tmp);
13990 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
13992 device_dc = (void *)0xdeadbeef;
13993 hr = GetSurfaceFromDC(dc, NULL, &device_dc);
13994 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
13995 ok(device_dc == (void *)0xdeadbeef, "Got unexpected device_dc %p.\n", device_dc);
13997 tmp = (void *)0xdeadbeef;
13998 hr = GetSurfaceFromDC(dc, &tmp, NULL);
13999 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
14000 ok(!tmp, "Got unexpected surface %p.\n", tmp);
14002 hr = GetSurfaceFromDC(dc, &tmp, &device_dc);
14003 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
14004 ok(tmp == surface1, "Got unexpected surface %p, expected %p.\n", tmp, surface1);
14005 IDirectDrawSurface_Release(tmp);
14007 ret = GetObjectType(device_dc);
14008 todo_wine ok(ret == OBJ_DC, "Got unexpected object type %#x.\n", ret);
14009 ret = GetDeviceCaps(device_dc, TECHNOLOGY);
14010 todo_wine ok(ret == DT_RASDISPLAY, "Got unexpected technology %#x.\n", ret);
14012 hr = IDirectDraw4_GetSurfaceFromDC(ddraw, dc, NULL);
14013 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
14015 hr = IDirectDraw4_GetSurfaceFromDC(ddraw, dc, (IDirectDrawSurface4 **)&tmp);
14016 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
14017 ok(tmp == surface1, "Got unexpected surface %p, expected %p.\n", tmp, surface1);
14019 refcount = get_refcount((IUnknown *)surface1);
14020 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
14021 refcount = get_refcount((IUnknown *)surface);
14022 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
14024 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
14025 ok(SUCCEEDED(hr), "ReleaseDC failed, hr %#x.\n", hr);
14027 IDirectDrawSurface_Release(tmp);
14029 dc = CreateCompatibleDC(NULL);
14030 ok(!!dc, "CreateCompatibleDC failed.\n");
14032 tmp = (void *)0xdeadbeef;
14033 device_dc = (void *)0xdeadbeef;
14034 hr = GetSurfaceFromDC(dc, &tmp, &device_dc);
14035 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
14036 ok(!tmp, "Got unexpected surface %p.\n", tmp);
14037 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
14039 tmp = (void *)0xdeadbeef;
14040 hr = IDirectDraw4_GetSurfaceFromDC(ddraw, dc, (IDirectDrawSurface4 **)&tmp);
14041 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
14042 ok(!tmp, "Got unexpected surface %p.\n", tmp);
14044 ok(DeleteDC(dc), "DeleteDC failed.\n");
14046 tmp = (void *)0xdeadbeef;
14047 hr = IDirectDraw4_GetSurfaceFromDC(ddraw, NULL, (IDirectDrawSurface4 **)&tmp);
14048 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
14049 ok(!tmp, "Got unexpected surface %p.\n", tmp);
14051 IDirectDrawSurface4_Release(surface);
14052 IDirectDrawSurface_Release(surface1);
14053 IDirectDraw4_Release(ddraw);
14054 DestroyWindow(window);
14057 static void test_ck_operation(void)
14059 IDirectDrawSurface4 *src, *dst;
14060 IDirectDrawSurface *src1, *dst1;
14061 DDSURFACEDESC2 surface_desc;
14062 IDirectDraw4 *ddraw;
14063 ULONG refcount;
14064 HWND window;
14065 HRESULT hr;
14066 D3DCOLOR *color;
14067 unsigned int i;
14068 DDCOLORKEY ckey;
14069 DDBLTFX fx;
14071 window = create_window();
14072 ddraw = create_ddraw();
14073 ok(!!ddraw, "Failed to create a ddraw object.\n");
14074 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
14075 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
14077 memset(&surface_desc, 0, sizeof(surface_desc));
14078 surface_desc.dwSize = sizeof(surface_desc);
14079 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
14080 surface_desc.dwWidth = 4;
14081 surface_desc.dwHeight = 1;
14082 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
14083 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
14084 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
14085 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
14086 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
14087 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
14088 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL);
14089 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
14091 surface_desc.dwFlags |= DDSD_CKSRCBLT;
14092 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff00ff;
14093 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff00ff;
14094 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL);
14095 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
14097 hr = IDirectDrawSurface4_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14098 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14099 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
14100 color = surface_desc.lpSurface;
14101 color[0] = 0x77010203;
14102 color[1] = 0x00010203;
14103 color[2] = 0x77ff00ff;
14104 color[3] = 0x00ff00ff;
14105 hr = IDirectDrawSurface4_Unlock(src, NULL);
14106 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14108 for (i = 0; i < 2; ++i)
14110 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14111 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14112 color = surface_desc.lpSurface;
14113 color[0] = 0xcccccccc;
14114 color[1] = 0xcccccccc;
14115 color[2] = 0xcccccccc;
14116 color[3] = 0xcccccccc;
14117 hr = IDirectDrawSurface4_Unlock(dst, NULL);
14118 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14120 if (i)
14122 hr = IDirectDrawSurface4_BltFast(dst, 0, 0, src, NULL, DDBLTFAST_SRCCOLORKEY);
14123 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14125 else
14127 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, NULL);
14128 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14131 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT | DDLOCK_READONLY, NULL);
14132 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14133 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
14134 color = surface_desc.lpSurface;
14135 /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
14136 * color keying, but copy it to the destination surface. Others (sysmem surfaces) apply it for
14137 * color keying, but do not copy it into the destination surface. Nvidia neither uses it for
14138 * color keying nor copies it. */
14139 ok((color[0] == 0x77010203 && color[1] == 0x00010203
14140 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* AMD, Wine */
14141 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
14142 && color[2] == 0x00ff00ff && color[3] == 0xcccccccc) /* Sysmem surfaces? */
14143 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
14144 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Nvidia */
14145 || broken(color[0] == 0xff010203 && color[1] == 0xff010203
14146 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Testbot */,
14147 "Destination data after blitting is %08x %08x %08x %08x, i=%u.\n",
14148 color[0], color[1], color[2], color[3], i);
14149 hr = IDirectDrawSurface4_Unlock(dst, NULL);
14150 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14153 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
14154 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
14155 ok(ckey.dwColorSpaceLowValue == 0x00ff00ff && ckey.dwColorSpaceHighValue == 0x00ff00ff,
14156 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
14158 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
14159 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
14160 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14162 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
14163 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
14164 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
14165 ok(ckey.dwColorSpaceLowValue == 0x0000ff00 && ckey.dwColorSpaceHighValue == 0x0000ff00,
14166 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
14168 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0;
14169 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0;
14170 hr = IDirectDrawSurface4_GetSurfaceDesc(src, &surface_desc);
14171 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
14172 ok(surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0x0000ff00
14173 && surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0x0000ff00,
14174 "Got unexpected color key low=%08x high=%08x.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue,
14175 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue);
14177 /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */
14178 ckey.dwColorSpaceLowValue = 0x000000ff;
14179 ckey.dwColorSpaceHighValue = 0x00000000;
14180 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
14181 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14183 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
14184 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
14185 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
14186 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
14187 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
14189 ckey.dwColorSpaceLowValue = 0x000000ff;
14190 ckey.dwColorSpaceHighValue = 0x00000001;
14191 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
14192 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14194 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
14195 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
14196 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
14197 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
14198 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
14200 ckey.dwColorSpaceLowValue = 0x000000fe;
14201 ckey.dwColorSpaceHighValue = 0x000000fd;
14202 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
14203 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14205 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
14206 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
14207 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
14208 ok(ckey.dwColorSpaceLowValue == 0x000000fe && ckey.dwColorSpaceHighValue == 0x000000fe,
14209 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
14211 IDirectDrawSurface4_Release(src);
14212 IDirectDrawSurface4_Release(dst);
14214 /* Test source and destination keys and where they are read from. Use a surface with alpha
14215 * to avoid driver-dependent content in the X channel. */
14216 memset(&surface_desc, 0, sizeof(surface_desc));
14217 surface_desc.dwSize = sizeof(surface_desc);
14218 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
14219 surface_desc.dwWidth = 6;
14220 surface_desc.dwHeight = 1;
14221 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
14222 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
14223 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
14224 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
14225 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
14226 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
14227 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
14228 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL);
14229 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
14230 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL);
14231 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
14233 ckey.dwColorSpaceLowValue = 0x0000ff00;
14234 ckey.dwColorSpaceHighValue = 0x0000ff00;
14235 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
14236 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14237 ckey.dwColorSpaceLowValue = 0x00ff0000;
14238 ckey.dwColorSpaceHighValue = 0x00ff0000;
14239 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_DESTBLT, &ckey);
14240 ok(SUCCEEDED(hr) || hr == DDERR_NOCOLORKEYHW, "Failed to set color key, hr %#x.\n", hr);
14241 if (FAILED(hr))
14243 /* Nvidia reject dest keys, AMD allows them. This applies to vidmem and sysmem surfaces. */
14244 skip("Failed to set destination color key, skipping related tests.\n");
14245 goto done;
14248 ckey.dwColorSpaceLowValue = 0x000000ff;
14249 ckey.dwColorSpaceHighValue = 0x000000ff;
14250 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
14251 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14252 ckey.dwColorSpaceLowValue = 0x000000aa;
14253 ckey.dwColorSpaceHighValue = 0x000000aa;
14254 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_DESTBLT, &ckey);
14255 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14257 memset(&fx, 0, sizeof(fx));
14258 fx.dwSize = sizeof(fx);
14259 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x00110000;
14260 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x00110000;
14261 fx.ddckDestColorkey.dwColorSpaceHighValue = 0x00001100;
14262 fx.ddckDestColorkey.dwColorSpaceLowValue = 0x00001100;
14264 hr = IDirectDrawSurface4_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14265 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14266 color = surface_desc.lpSurface;
14267 color[0] = 0x000000ff; /* Applies to src blt key in src surface. */
14268 color[1] = 0x000000aa; /* Applies to dst blt key in src surface. */
14269 color[2] = 0x00ff0000; /* Dst color key in dst surface. */
14270 color[3] = 0x0000ff00; /* Src color key in dst surface. */
14271 color[4] = 0x00001100; /* Src color key in ddbltfx. */
14272 color[5] = 0x00110000; /* Dst color key in ddbltfx. */
14273 hr = IDirectDrawSurface4_Unlock(src, NULL);
14274 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14276 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14277 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14278 color = surface_desc.lpSurface;
14279 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
14280 hr = IDirectDrawSurface4_Unlock(dst, NULL);
14281 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14283 /* Test a blit without keying. */
14284 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, 0, &fx);
14285 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14287 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14288 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14289 color = surface_desc.lpSurface;
14290 /* Should have copied src data unmodified to dst. */
14291 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
14292 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
14293 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14294 color[0], color[1], color[2], color[3], color[4], color[5]);
14296 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
14297 hr = IDirectDrawSurface4_Unlock(dst, NULL);
14298 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14300 /* Src key. */
14301 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
14302 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14304 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14305 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14306 color = surface_desc.lpSurface;
14307 /* Src key applied to color[0]. It is unmodified, the others are copied. */
14308 ok(color[0] == 0x55555555 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
14309 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
14310 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14311 color[0], color[1], color[2], color[3], color[4], color[5]);
14313 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
14314 hr = IDirectDrawSurface4_Unlock(dst, NULL);
14315 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14317 /* Src override. */
14318 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
14319 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14321 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14322 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14323 color = surface_desc.lpSurface;
14324 /* Override key applied to color[5]. It is unmodified, the others are copied. */
14325 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
14326 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x55555555,
14327 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14328 color[0], color[1], color[2], color[3], color[4], color[5]);
14330 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
14331 hr = IDirectDrawSurface4_Unlock(dst, NULL);
14332 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14334 /* Src override AND src key. That is not supposed to work. */
14335 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx);
14336 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14338 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14339 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14340 color = surface_desc.lpSurface;
14341 /* Ensure the destination was not changed. */
14342 ok(color[0] == 0x55555555 && color[1] == 0x55555555 && color[2] == 0x55555555 &&
14343 color[3] == 0x55555555 && color[4] == 0x55555555 && color[5] == 0x55555555,
14344 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14345 color[0], color[1], color[2], color[3], color[4], color[5]);
14347 /* Use different dst colors for the dst key test. */
14348 color[0] = 0x00ff0000; /* Dest key in dst surface. */
14349 color[1] = 0x00ff0000; /* Dest key in dst surface. */
14350 color[2] = 0x00001100; /* Dest key in override. */
14351 color[3] = 0x00001100; /* Dest key in override. */
14352 color[4] = 0x000000aa; /* Dest key in src surface. */
14353 color[5] = 0x000000aa; /* Dest key in src surface. */
14354 hr = IDirectDrawSurface4_Unlock(dst, NULL);
14355 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14357 /* Dest key blit. The key is taken from the DESTINATION surface in v4! */
14358 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
14359 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14361 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14362 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14363 color = surface_desc.lpSurface;
14364 /* Dst key applied to color[0,1], they are the only changed pixels. */
14365 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
14366 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
14367 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14368 color[0], color[1], color[2], color[3], color[4], color[5]);
14370 color[0] = 0x00ff0000; /* Dest key in dst surface. */
14371 color[1] = 0x00ff0000; /* Dest key in dst surface. */
14372 color[2] = 0x00001100; /* Dest key in override. */
14373 color[3] = 0x00001100; /* Dest key in override. */
14374 color[4] = 0x000000aa; /* Dest key in src surface. */
14375 color[5] = 0x000000aa; /* Dest key in src surface. */
14376 hr = IDirectDrawSurface4_Unlock(dst, NULL);
14377 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14379 /* What happens with a QI'd older version of the interface? It takes the key
14380 * from the source surface. */
14381 hr = IDirectDrawSurface4_QueryInterface(src, &IID_IDirectDrawSurface, (void **)&src1);
14382 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
14383 hr = IDirectDrawSurface4_QueryInterface(dst, &IID_IDirectDrawSurface, (void **)&dst1);
14384 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
14386 hr = IDirectDrawSurface_Blt(dst1, NULL, src1, NULL, DDBLT_KEYDEST, &fx);
14387 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14389 IDirectDrawSurface_Release(dst1);
14390 IDirectDrawSurface_Release(src1);
14392 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14393 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14394 color = surface_desc.lpSurface;
14395 /* Dst key applied to color[4,5], they are the only changed pixels. */
14396 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
14397 color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000,
14398 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14399 color[0], color[1], color[2], color[3], color[4], color[5]);
14401 color[0] = 0x00ff0000; /* Dest key in dst surface. */
14402 color[1] = 0x00ff0000; /* Dest key in dst surface. */
14403 color[2] = 0x00001100; /* Dest key in override. */
14404 color[3] = 0x00001100; /* Dest key in override. */
14405 color[4] = 0x000000aa; /* Dest key in src surface. */
14406 color[5] = 0x000000aa; /* Dest key in src surface. */
14407 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14408 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14410 /* Dest override key blit. */
14411 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
14412 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14414 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14415 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14416 color = surface_desc.lpSurface;
14417 /* Dst key applied to color[2,3], they are the only changed pixels. */
14418 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00ff0000 &&
14419 color[3] == 0x0000ff00 && color[4] == 0x000000aa && color[5] == 0x000000aa,
14420 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14421 color[0], color[1], color[2], color[3], color[4], color[5]);
14423 color[0] = 0x00ff0000; /* Dest key in dst surface. */
14424 color[1] = 0x00ff0000; /* Dest key in dst surface. */
14425 color[2] = 0x00001100; /* Dest key in override. */
14426 color[3] = 0x00001100; /* Dest key in override. */
14427 color[4] = 0x000000aa; /* Dest key in src surface. */
14428 color[5] = 0x000000aa; /* Dest key in src surface. */
14429 hr = IDirectDrawSurface4_Unlock(dst, NULL);
14430 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14432 /* Dest override together with surface key. Supposed to fail. */
14433 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx);
14434 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14436 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14437 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14438 color = surface_desc.lpSurface;
14439 /* Destination is unchanged. */
14440 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
14441 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
14442 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14443 color[0], color[1], color[2], color[3], color[4], color[5]);
14444 hr = IDirectDrawSurface4_Unlock(dst, NULL);
14445 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14447 /* Source and destination key. This is driver dependent. New HW treats it like
14448 * DDBLT_KEYSRC. Older HW and some software renderers apply both keys. */
14449 if (0)
14451 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx);
14452 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14454 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14455 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14456 color = surface_desc.lpSurface;
14457 /* Color[0] is filtered by the src key, 2-5 are filtered by the dst key, if
14458 * the driver applies it. */
14459 ok(color[0] == 0x00ff0000 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
14460 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
14461 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14462 color[0], color[1], color[2], color[3], color[4], color[5]);
14464 color[0] = 0x00ff0000; /* Dest key in dst surface. */
14465 color[1] = 0x00ff0000; /* Dest key in dst surface. */
14466 color[2] = 0x00001100; /* Dest key in override. */
14467 color[3] = 0x00001100; /* Dest key in override. */
14468 color[4] = 0x000000aa; /* Dest key in src surface. */
14469 color[5] = 0x000000aa; /* Dest key in src surface. */
14470 hr = IDirectDrawSurface4_Unlock(dst, NULL);
14471 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14474 /* Override keys without ddbltfx parameter fail */
14475 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, NULL);
14476 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14477 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, NULL);
14478 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14480 /* Try blitting without keys in the source surface. */
14481 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, NULL);
14482 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14483 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_DESTBLT, NULL);
14484 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14486 /* That fails now. Do not bother to check that the data is unmodified. */
14487 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
14488 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14490 /* Dest key blit still works, the destination surface key is used in v4. */
14491 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
14492 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14494 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14495 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14496 color = surface_desc.lpSurface;
14497 /* Dst key applied to color[0,1], they are the only changed pixels. */
14498 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
14499 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
14500 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14501 color[0], color[1], color[2], color[3], color[4], color[5]);
14502 hr = IDirectDrawSurface4_Unlock(dst, NULL);
14503 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14505 /* Try blitting without keys in the destination surface. */
14506 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_SRCBLT, NULL);
14507 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14508 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_DESTBLT, NULL);
14509 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14511 /* This fails, as sanity would dictate. */
14512 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
14513 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14515 done:
14516 IDirectDrawSurface4_Release(src);
14517 IDirectDrawSurface4_Release(dst);
14518 refcount = IDirectDraw4_Release(ddraw);
14519 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
14520 DestroyWindow(window);
14523 static void test_vb_refcount(void)
14525 ULONG prev_d3d_refcount, prev_device_refcount;
14526 ULONG cur_d3d_refcount, cur_device_refcount;
14527 IDirect3DVertexBuffer *vb, *vb1;
14528 IDirect3DVertexBuffer7 *vb7;
14529 D3DVERTEXBUFFERDESC vb_desc;
14530 IDirect3DDevice3 *device;
14531 IDirect3D3 *d3d;
14532 ULONG refcount;
14533 IUnknown *unk;
14534 HWND window;
14535 HRESULT hr;
14537 window = create_window();
14538 if (!(device = create_device(window, DDSCL_NORMAL)))
14540 skip("Failed to create a 3D device, skipping test.\n");
14541 DestroyWindow(window);
14542 return;
14545 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
14546 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
14548 prev_d3d_refcount = get_refcount((IUnknown *)d3d);
14549 prev_device_refcount = get_refcount((IUnknown *)device);
14551 memset(&vb_desc, 0, sizeof(vb_desc));
14552 vb_desc.dwSize = sizeof(vb_desc);
14553 vb_desc.dwFVF = D3DFVF_XYZ;
14554 vb_desc.dwNumVertices = 4;
14555 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &vb, 0, NULL);
14556 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
14558 cur_d3d_refcount = get_refcount((IUnknown *)d3d);
14559 cur_device_refcount = get_refcount((IUnknown *)device);
14560 ok(cur_d3d_refcount == prev_d3d_refcount, "D3D object refcount changed from %u to %u.\n",
14561 prev_d3d_refcount, cur_d3d_refcount);
14562 ok(cur_device_refcount == prev_device_refcount, "Device refcount changed from %u to %u.\n",
14563 prev_device_refcount, cur_device_refcount);
14565 hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IDirect3DVertexBuffer, (void **)&vb1);
14566 ok(hr == DD_OK, "Failed to query IDirect3DVertexBuffer, hr %#x.\n", hr);
14567 IDirect3DVertexBuffer_Release(vb1);
14569 hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IDirect3DVertexBuffer7, (void **)&vb7);
14570 ok(hr == E_NOINTERFACE, "Querying IDirect3DVertexBuffer7 returned unexpected hr %#x.\n", hr);
14572 hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IUnknown, (void **)&unk);
14573 ok(hr == DD_OK, "Failed to query IUnknown, hr %#x.\n", hr);
14574 ok((IUnknown *)vb == unk,
14575 "IDirect3DVertexBuffer and IUnknown interface pointers don't match, %p != %p.\n", vb, unk);
14576 IUnknown_Release(unk);
14578 refcount = IDirect3DVertexBuffer_Release(vb);
14579 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
14580 IDirect3D3_Release(d3d);
14581 refcount = IDirect3DDevice3_Release(device);
14582 ok(!refcount, "Device has %u references left.\n", refcount);
14583 DestroyWindow(window);
14586 static void test_compute_sphere_visibility(void)
14588 static D3DMATRIX proj_1 =
14590 1.810660f, 0.000000f, 0.000000f, 0.000000f,
14591 0.000000f, 2.414213f, 0.000000f, 0.000000f,
14592 0.000000f, 0.000000f, 1.020408f, 1.000000f,
14593 0.000000f, 0.000000f, -0.102041f, 0.000000f,
14595 static D3DMATRIX proj_2 =
14597 10.0f, 0.0f, 0.0f, 0.0f,
14598 0.0f, 10.0f, 0.0f, 0.0f,
14599 0.0f, 0.0f, 10.0f, 0.0f,
14600 0.0f, 0.0f, 0.0f, 1.0f,
14602 static D3DMATRIX view_1 =
14604 1.000000f, 0.000000f, 0.000000f, 0.000000f,
14605 0.000000f, 0.768221f, -0.640185f, 0.000000f,
14606 -0.000000f, 0.640185f, 0.768221f, 0.000000f,
14607 -14.852037f, 9.857489f, 11.600972f, 1.000000f,
14609 static D3DMATRIX identity =
14611 1.0f, 0.0f, 0.0f, 0.0f,
14612 0.0f, 1.0f, 0.0f, 0.0f,
14613 0.0f, 0.0f, 1.0f, 0.0f,
14614 0.0f, 0.0f, 0.0f, 1.0f,
14616 static struct
14618 D3DMATRIX *view, *proj;
14619 unsigned int sphere_count;
14620 D3DVECTOR center[3];
14621 D3DVALUE radius[3];
14622 const DWORD expected[3];
14623 BOOL todo;
14625 tests[] =
14627 {&view_1, &proj_1, 1, {{{11.461533f}, {-4.761727f}, {-1.171646f}}}, {38.252632f}, {0x1555}},
14628 {&view_1, &proj_1, 3, {{{-3.515620f}, {-1.560661f}, {-12.464638f}},
14629 {{14.290396f}, {-2.981143f}, {-24.311312f}},
14630 {{1.461626f}, {-6.093709f}, {-13.901010f}}},
14631 {4.354097f, 12.500704f, 17.251318f}, {0x154a, 0x1555, 0x1555}},
14632 {&identity, &proj_2, 1, {{{0.0f}, {0.0f}, {0.05f}}}, {0.04f}, {0x1555}, TRUE},
14633 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.5f}}}, {0.5f}, {0x1401}},
14634 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {0.0f}, {0x401}},
14635 {&identity, &identity, 1, {{{-1.0f}, {-1.0f}, {0.5f}}}, {0.25f}, {0x1505}, TRUE}, /* 5 */
14636 {&identity, &identity, 1, {{{-20.0f}, {0.0f}, {0.5f}}}, {3.0f}, {0x154a}},
14637 {&identity, &identity, 1, {{{20.0f}, {0.0f}, {0.5f}}}, {3.0f}, {0x1562}},
14638 {&identity, &identity, 1, {{{0.0f}, {-20.0f}, {0.5f}}}, {3.0f}, {0x1616}},
14639 {&identity, &identity, 1, {{{0.0f}, {20.0f}, {0.5f}}}, {3.0f}, {0x1496}},
14640 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {-20.0f}}}, {3.0f}, {0x956}}, /* 10 */
14641 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {20.0f}}}, {3.0f}, {0x2156}},
14643 IDirect3DViewport3 *viewport;
14644 IDirect3DDevice3 *device;
14645 unsigned int i, j;
14646 DWORD result[3];
14647 ULONG refcount;
14648 HWND window;
14649 HRESULT hr;
14651 window = create_window();
14652 if (!(device = create_device(window, DDSCL_NORMAL)))
14654 skip("Failed to create a 3D device, skipping test.\n");
14655 DestroyWindow(window);
14656 return;
14659 viewport = create_viewport(device, 0, 0, 640, 480);
14660 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
14661 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
14663 IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
14665 for (i = 0; i < ARRAY_SIZE(tests); ++i)
14667 IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, tests[i].view);
14668 IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].proj);
14670 hr = IDirect3DDevice3_ComputeSphereVisibility(device, tests[i].center, tests[i].radius,
14671 tests[i].sphere_count, 0, result);
14672 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14674 for (j = 0; j < tests[i].sphere_count; ++j)
14675 todo_wine_if(tests[i].todo)
14676 ok(result[j] == tests[i].expected[j], "Test %u sphere %u: expected %#x, got %#x.\n",
14677 i, j, tests[i].expected[j], result[j]);
14680 destroy_viewport(device, viewport);
14681 refcount = IDirect3DDevice3_Release(device);
14682 ok(!refcount, "Device has %u references left.\n", refcount);
14683 DestroyWindow(window);
14686 static void test_texture_stages_limits(void)
14688 IDirectDrawSurface4 *surface;
14689 DDSURFACEDESC2 surface_desc;
14690 IDirect3DTexture2 *texture;
14691 IDirect3DDevice3 *device;
14692 IDirectDraw4 *ddraw;
14693 IDirect3D3 *d3d;
14694 unsigned int i;
14695 ULONG refcount;
14696 HWND window;
14697 HRESULT hr;
14699 window = create_window();
14700 if (!(device = create_device(window, DDSCL_NORMAL)))
14702 skip("Failed to create 3D device.\n");
14703 DestroyWindow(window);
14704 return;
14706 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
14707 ok(SUCCEEDED(hr), "Failed to get Direct3D interface, hr %#x.\n", hr);
14708 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
14709 ok(SUCCEEDED(hr), "Failed to get DirectDraw interface, hr %#x.\n", hr);
14710 IDirect3D3_Release(d3d);
14712 memset(&surface_desc, 0, sizeof(surface_desc));
14713 surface_desc.dwSize = sizeof(surface_desc);
14714 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
14715 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
14716 surface_desc.dwWidth = 16;
14717 surface_desc.dwHeight = 16;
14718 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
14719 ok(hr == DD_OK, "Failed to create surface, hr %#x.\n", hr);
14720 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
14721 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
14722 IDirectDrawSurface4_Release(surface);
14724 for (i = 0; i < 8; ++i)
14726 hr = IDirect3DDevice3_SetTexture(device, i, texture);
14727 ok(hr == D3D_OK, "Failed to set texture %u, hr %#x.\n", i, hr);
14728 hr = IDirect3DDevice3_SetTexture(device, i, NULL);
14729 ok(hr == D3D_OK, "Failed to set texture %u, hr %#x.\n", i, hr);
14730 hr = IDirect3DDevice3_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
14731 ok(hr == D3D_OK, "Failed to set texture stage state %u, hr %#x.\n", i, hr);
14734 IDirectDraw4_Release(ddraw);
14735 IDirect3DTexture2_Release(texture);
14736 refcount = IDirect3DDevice3_Release(device);
14737 ok(!refcount, "Device has %u references left.\n", refcount);
14738 DestroyWindow(window);
14741 static void test_set_render_state(void)
14743 IDirect3DDevice3 *device;
14744 ULONG refcount;
14745 HWND window;
14746 DWORD state;
14747 HRESULT hr;
14749 window = create_window();
14750 if (!(device = create_device(window, DDSCL_NORMAL)))
14752 skip("Failed to create 3D device.\n");
14753 DestroyWindow(window);
14754 return;
14757 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, TRUE);
14758 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14759 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, FALSE);
14760 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14762 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
14763 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14764 state = 0xdeadbeef;
14765 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, &state);
14766 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14767 ok(!state, "Got unexpected render state %#x.\n", state);
14768 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
14769 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14770 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, &state);
14771 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14772 ok(state == D3DTBLEND_MODULATE, "Got unexpected render state %#x.\n", state);
14774 refcount = IDirect3DDevice3_Release(device);
14775 ok(!refcount, "Device has %u references left.\n", refcount);
14776 DestroyWindow(window);
14779 static void test_map_synchronisation(void)
14781 LARGE_INTEGER frequency, diff, ts[3];
14782 IDirect3DVertexBuffer *buffer;
14783 IDirect3DViewport3 *viewport;
14784 unsigned int i, j, tri_count;
14785 D3DVERTEXBUFFERDESC vb_desc;
14786 IDirect3DDevice3 *device;
14787 BOOL unsynchronised, ret;
14788 IDirectDrawSurface4 *rt;
14789 IDirect3D3 *d3d;
14790 D3DCOLOR colour;
14791 ULONG refcount;
14792 HWND window;
14793 HRESULT hr;
14795 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
14797 /* DDLOCK_DISCARDCONTENTS and DDLOCK_NOOVERWRITE were introduced with
14798 * ddraw7 and are ignored in earlier versions. */
14799 static const struct
14801 unsigned int flags;
14802 BOOL unsynchronised;
14804 tests[] =
14806 {0, FALSE},
14807 {DDLOCK_NOOVERWRITE, FALSE},
14808 {DDLOCK_DISCARDCONTENTS, FALSE},
14809 {DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS, FALSE},
14812 static const struct quad
14814 struct
14816 struct vec3 position;
14817 DWORD diffuse;
14818 } strip[4];
14820 quad1 =
14823 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
14824 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
14825 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
14826 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
14829 quad2 =
14832 {{-1.0f, -1.0f, 0.0f}, 0xffffff00},
14833 {{-1.0f, 1.0f, 0.0f}, 0xffffff00},
14834 {{ 1.0f, -1.0f, 0.0f}, 0xffffff00},
14835 {{ 1.0f, 1.0f, 0.0f}, 0xffffff00},
14838 struct quad *quads;
14840 window = create_window();
14841 ok(!!window, "Failed to create a window.\n");
14843 if (!(device = create_device(window, DDSCL_NORMAL)))
14845 skip("Failed to create a D3D device, skipping tests.\n");
14846 DestroyWindow(window);
14847 return;
14850 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
14851 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
14853 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
14854 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
14855 viewport = create_viewport(device, 0, 0, 640, 480);
14856 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
14857 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
14859 tri_count = 0x1000;
14861 ret = QueryPerformanceFrequency(&frequency);
14862 ok(ret, "Failed to get performance counter frequency.\n");
14864 vb_desc.dwSize = sizeof(vb_desc);
14865 vb_desc.dwCaps = D3DVBCAPS_WRITEONLY;
14866 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
14867 vb_desc.dwNumVertices = tri_count + 2;
14868 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &buffer, 0, NULL);
14869 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
14870 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&quads, NULL);
14871 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
14872 for (j = 0; j < vb_desc.dwNumVertices / 4; ++j)
14874 quads[j] = quad1;
14876 hr = IDirect3DVertexBuffer_Unlock(buffer);
14877 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
14879 /* Initial draw to initialise states, compile shaders, etc. */
14880 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14881 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14882 hr = IDirect3DDevice3_BeginScene(device);
14883 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14884 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
14885 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14886 hr = IDirect3DDevice3_EndScene(device);
14887 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14888 /* Read the result to ensure the GPU has finished drawing. */
14889 colour = get_surface_color(rt, 320, 240);
14891 /* Time drawing tri_count triangles. */
14892 ret = QueryPerformanceCounter(&ts[0]);
14893 ok(ret, "Failed to read performance counter.\n");
14894 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14895 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14896 hr = IDirect3DDevice3_BeginScene(device);
14897 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14898 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
14899 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14900 hr = IDirect3DDevice3_EndScene(device);
14901 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14902 colour = get_surface_color(rt, 320, 240);
14903 /* Time drawing a single triangle. */
14904 ret = QueryPerformanceCounter(&ts[1]);
14905 ok(ret, "Failed to read performance counter.\n");
14906 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14907 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14908 hr = IDirect3DDevice3_BeginScene(device);
14909 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14910 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 3, 0);
14911 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14912 hr = IDirect3DDevice3_EndScene(device);
14913 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14914 colour = get_surface_color(rt, 320, 240);
14915 ret = QueryPerformanceCounter(&ts[2]);
14916 ok(ret, "Failed to read performance counter.\n");
14918 IDirect3DVertexBuffer_Release(buffer);
14920 /* Estimate the number of triangles we can draw in 100ms. */
14921 diff.QuadPart = ts[1].QuadPart - ts[0].QuadPart + ts[1].QuadPart - ts[2].QuadPart;
14922 tri_count = (tri_count * frequency.QuadPart) / (diff.QuadPart * 10);
14923 tri_count = ((tri_count + 2 + 3) & ~3) - 2;
14924 vb_desc.dwNumVertices = tri_count + 2;
14926 for (i = 0; i < ARRAY_SIZE(tests); ++i)
14928 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &buffer, 0, NULL);
14929 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
14930 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&quads, NULL);
14931 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
14932 for (j = 0; j < vb_desc.dwNumVertices / 4; ++j)
14934 quads[j] = quad1;
14936 hr = IDirect3DVertexBuffer_Unlock(buffer);
14937 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
14939 /* Start a draw operation. */
14940 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14941 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14942 hr = IDirect3DDevice3_BeginScene(device);
14943 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14944 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
14945 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14946 hr = IDirect3DDevice3_EndScene(device);
14947 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14949 /* Map the last quad while the draw is in progress. */
14950 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_WAIT | tests[i].flags, (void **)&quads, NULL);
14951 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
14952 quads[(vb_desc.dwNumVertices / 4) - 1] = quad2;
14953 hr = IDirect3DVertexBuffer_Unlock(buffer);
14954 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
14956 colour = get_surface_color(rt, 320, 240);
14957 unsynchronised = compare_color(colour, 0x00ffff00, 1);
14958 ok(tests[i].unsynchronised == unsynchronised, "Expected %s map for flags %#x.\n",
14959 tests[i].unsynchronised ? "unsynchronised" : "synchronised", tests[i].flags);
14961 IDirect3DVertexBuffer_Release(buffer);
14964 destroy_viewport(device, viewport);
14965 IDirectDrawSurface4_Release(rt);
14966 IDirect3D3_Release(d3d);
14967 refcount = IDirect3DDevice3_Release(device);
14968 ok(!refcount, "Device has %u references left.\n", refcount);
14969 DestroyWindow(window);
14972 static void test_depth_readback(void)
14974 DWORD depth, expected_depth, max_diff, passed_fmts = 0;
14975 IDirectDrawSurface4 *rt, *ds;
14976 IDirect3DViewport3 *viewport;
14977 DDSURFACEDESC2 surface_desc;
14978 IDirect3DDevice3 *device;
14979 unsigned int i, x, y;
14980 IDirectDraw4 *ddraw;
14981 IDirect3D3 *d3d;
14982 ULONG refcount;
14983 HWND window;
14984 HRESULT hr;
14985 RECT r;
14986 BOOL all_pass;
14988 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
14989 static struct
14991 struct vec3 position;
14992 DWORD diffuse;
14994 quad[] =
14996 {{-1.0f, -1.0f, 0.1f}, 0xff00ff00},
14997 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
14998 {{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
14999 {{ 1.0f, 1.0f, 0.9f}, 0xff00ff00},
15002 static const struct
15004 unsigned int z_depth, s_depth, z_mask, s_mask;
15005 BOOL todo;
15007 tests[] =
15009 {16, 0, 0x0000ffff, 0x00000000},
15010 {24, 0, 0x00ffffff, 0x00000000},
15011 {32, 0, 0x00ffffff, 0x00000000},
15012 {32, 8, 0x00ffffff, 0xff000000, TRUE},
15013 {32, 0, 0xffffffff, 0x00000000},
15016 window = create_window();
15017 ok(!!window, "Failed to create a window.\n");
15019 if (!(device = create_device(window, DDSCL_NORMAL)))
15021 skip("Failed to create a D3D device, skipping tests.\n");
15022 DestroyWindow(window);
15023 return;
15026 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
15027 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
15028 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
15029 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
15031 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
15032 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
15033 viewport = create_viewport(device, 0, 0, 640, 480);
15034 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
15035 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
15037 ds = get_depth_stencil(device);
15038 hr = IDirectDrawSurface4_DeleteAttachedSurface(rt, 0, ds);
15039 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
15040 IDirectDrawSurface4_Release(ds);
15042 for (i = 0; i < ARRAY_SIZE(tests); ++i)
15044 memset(&surface_desc, 0, sizeof(surface_desc));
15045 surface_desc.dwSize = sizeof(surface_desc);
15046 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
15047 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
15048 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
15049 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
15050 if (tests[i].s_depth)
15051 U4(surface_desc).ddpfPixelFormat.dwFlags |= DDPF_STENCILBUFFER;
15052 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = tests[i].z_depth;
15053 U2(U4(surface_desc).ddpfPixelFormat).dwStencilBitDepth = tests[i].s_depth;
15054 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = tests[i].z_mask;
15055 U4(U4(surface_desc).ddpfPixelFormat).dwStencilBitMask = tests[i].s_mask;
15056 surface_desc.dwWidth = 640;
15057 surface_desc.dwHeight = 480;
15058 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &ds, NULL);
15059 if (FAILED(hr))
15061 skip("Format %u not supported, skipping test.\n", i);
15062 continue;
15065 hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
15066 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
15067 hr = IDirect3DDevice3_SetRenderTarget(device, rt, 0);
15068 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
15070 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect,
15071 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
15072 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15073 hr = IDirect3DDevice3_BeginScene(device);
15074 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
15075 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0);
15076 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
15077 hr = IDirect3DDevice3_EndScene(device);
15078 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
15080 all_pass = TRUE;
15081 for (y = 60; y < 480; y += 120)
15083 for (x = 80; x < 640; x += 160)
15085 SetRect(&r, x, y, x + 1, y + 1);
15086 memset(&surface_desc, 0, sizeof(surface_desc));
15087 surface_desc.dwSize = sizeof(surface_desc);
15088 hr = IDirectDrawSurface4_Lock(ds, &r, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
15089 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
15091 depth = *((DWORD *)surface_desc.lpSurface) & tests[i].z_mask;
15092 expected_depth = (x * (0.9 / 640.0) + y * (0.1 / 480.0)) * tests[i].z_mask;
15093 max_diff = ((0.5f * 0.9f) / 640.0f) * tests[i].z_mask;
15094 /* The ddraw4 version of this test behaves similarly to the ddraw7 version on Nvidia GPUs,
15095 * except that Geforce 7 also returns garbage data in D24S8, whereas the ddraw7 version
15096 * returns 0 for that format. Give up on pre-filtering formats, accept Nvidia as generally
15097 * broken here, but still expect at least one format (D16 or D24X8 in practise) to pass. */
15098 todo_wine_if(tests[i].todo)
15099 ok(abs(expected_depth - depth) <= max_diff || ddraw_is_nvidia(ddraw),
15100 "Test %u: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n",
15101 i, depth, expected_depth - depth, expected_depth, max_diff, x, y);
15102 if (abs(expected_depth - depth) > max_diff)
15103 all_pass = FALSE;
15105 hr = IDirectDrawSurface4_Unlock(ds, &r);
15106 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
15110 if (all_pass)
15111 passed_fmts++;
15113 hr = IDirectDrawSurface4_DeleteAttachedSurface(rt, 0, ds);
15114 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
15115 IDirectDrawSurface4_Release(ds);
15118 ok(passed_fmts, "Not a single format passed the tests, this is bad even by Nvidia's standards.\n");
15120 destroy_viewport(device, viewport);
15121 IDirectDrawSurface4_Release(rt);
15122 IDirectDraw4_Release(ddraw);
15123 IDirect3D3_Release(d3d);
15124 refcount = IDirect3DDevice3_Release(device);
15125 ok(!refcount, "Device has %u references left.\n", refcount);
15126 DestroyWindow(window);
15129 static void test_clear(void)
15131 D3DRECT rect_negneg, rect_full = {{0}, {0}, {640}, {480}};
15132 IDirect3DViewport3 *viewport, *viewport2, *viewport3;
15133 IDirect3DDevice3 *device;
15134 IDirectDrawSurface4 *rt;
15135 IDirectDraw4 *ddraw;
15136 IDirect3D3 *d3d;
15137 D3DRECT rect[2];
15138 D3DCOLOR color;
15139 ULONG refcount;
15140 HWND window;
15141 HRESULT hr;
15143 window = create_window();
15144 if (!(device = create_device(window, DDSCL_NORMAL)))
15146 skip("Failed to create 3D device.\n");
15147 DestroyWindow(window);
15148 return;
15151 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
15152 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
15153 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
15154 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
15156 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
15157 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
15159 viewport = create_viewport(device, 0, 0, 640, 480);
15160 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
15161 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
15163 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
15164 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15166 /* Positive x, negative y. */
15167 U1(rect[0]).x1 = 0;
15168 U2(rect[0]).y1 = 480;
15169 U3(rect[0]).x2 = 320;
15170 U4(rect[0]).y2 = 240;
15172 /* Positive x, positive y. */
15173 U1(rect[1]).x1 = 0;
15174 U2(rect[1]).y1 = 0;
15175 U3(rect[1]).x2 = 320;
15176 U4(rect[1]).y2 = 240;
15178 /* Clear 2 rectangles with one call. Unlike d3d8/9, the refrast does not
15179 * refuse negative rectangles, but it will not clear them either. */
15180 hr = IDirect3DViewport3_Clear2(viewport, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
15181 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15183 color = get_surface_color(rt, 160, 360);
15184 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 3 (pos, neg) has color 0x%08x.\n", color);
15185 color = get_surface_color(rt, 160, 120);
15186 ok(compare_color(color, 0x00ff0000, 0), "Clear rectangle 1 (pos, pos) has color 0x%08x.\n", color);
15187 color = get_surface_color(rt, 480, 360);
15188 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (NULL) has color 0x%08x.\n", color);
15189 color = get_surface_color(rt, 480, 120);
15190 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (neg, neg) has color 0x%08x.\n", color);
15192 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
15193 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15194 /* negative x, negative y.
15195 * Also ignored, except on WARP, which clears the entire screen. */
15196 U1(rect_negneg).x1 = 640;
15197 U2(rect_negneg).y1 = 240;
15198 U3(rect_negneg).x2 = 320;
15199 U4(rect_negneg).y2 = 0;
15200 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
15201 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15203 color = get_surface_color(rt, 160, 360);
15204 ok(compare_color(color, 0x00ffffff, 0)
15205 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
15206 "Got unexpected color 0x%08x.\n", color);
15207 color = get_surface_color(rt, 160, 120);
15208 ok(compare_color(color, 0x00ffffff, 0)
15209 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
15210 "Got unexpected color 0x%08x.\n", color);
15211 color = get_surface_color(rt, 480, 360);
15212 ok(compare_color(color, 0x00ffffff, 0)
15213 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
15214 "Got unexpected color 0x%08x.\n", color);
15215 color = get_surface_color(rt, 480, 120);
15216 ok(compare_color(color, 0x00ffffff, 0)
15217 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
15218 "Got unexpected color 0x%08x.\n", color);
15220 /* Test how the viewport affects clears. */
15221 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
15222 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15224 viewport2 = create_viewport(device, 160, 120, 160, 120);
15225 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport2);
15226 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
15228 hr = IDirect3DViewport3_Clear2(viewport2, 1, &rect_full, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
15229 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15231 viewport3 = create_viewport(device, 320, 240, 320, 240);
15232 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport3);
15233 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
15235 U1(rect[0]).x1 = 160;
15236 U2(rect[0]).y1 = 120;
15237 U3(rect[0]).x2 = 480;
15238 U4(rect[0]).y2 = 360;
15239 hr = IDirect3DViewport3_Clear2(viewport3, 1, &rect[0], D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
15240 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15242 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
15243 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
15245 color = get_surface_color(rt, 158, 118);
15246 ok(compare_color(color, 0x00ffffff, 0), "(158, 118) has color 0x%08x.\n", color);
15247 color = get_surface_color(rt, 162, 118);
15248 ok(compare_color(color, 0x00ffffff, 0), "(162, 118) has color 0x%08x.\n", color);
15249 color = get_surface_color(rt, 158, 122);
15250 ok(compare_color(color, 0x00ffffff, 0), "(158, 122) has color 0x%08x.\n", color);
15251 color = get_surface_color(rt, 162, 122);
15252 ok(compare_color(color, 0x000000ff, 0), "(162, 122) has color 0x%08x.\n", color);
15254 color = get_surface_color(rt, 318, 238);
15255 ok(compare_color(color, 0x000000ff, 0), "(318, 238) has color 0x%08x.\n", color);
15256 color = get_surface_color(rt, 322, 238);
15257 ok(compare_color(color, 0x00ffffff, 0), "(322, 328) has color 0x%08x.\n", color);
15258 color = get_surface_color(rt, 318, 242);
15259 ok(compare_color(color, 0x00ffffff, 0), "(318, 242) has color 0x%08x.\n", color);
15260 color = get_surface_color(rt, 322, 242);
15261 ok(compare_color(color, 0x0000ff00, 0), "(322, 242) has color 0x%08x.\n", color);
15263 color = get_surface_color(rt, 478, 358);
15264 ok(compare_color(color, 0x0000ff00, 0), "(478, 358) has color 0x%08x.\n", color);
15265 color = get_surface_color(rt, 482, 358);
15266 ok(compare_color(color, 0x00ffffff, 0), "(482, 358) has color 0x%08x.\n", color);
15267 color = get_surface_color(rt, 478, 362);
15268 ok(compare_color(color, 0x00ffffff, 0), "(478, 362) has color 0x%08x.\n", color);
15269 color = get_surface_color(rt, 482, 362);
15270 ok(compare_color(color, 0x00ffffff, 0), "(482, 362) has color 0x%08x.\n", color);
15272 /* The clear rectangle is rendertarget absolute, not relative to the
15273 * viewport. */
15274 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
15275 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15276 U1(rect[0]).x1 = 330;
15277 U2(rect[0]).y1 = 250;
15278 U3(rect[0]).x2 = 340;
15279 U4(rect[0]).y2 = 260;
15280 hr = IDirect3DViewport3_Clear2(viewport3, 1, &rect[0], D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
15281 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15283 color = get_surface_color(rt, 328, 248);
15284 ok(compare_color(color, 0x00ffffff, 0), "(328, 248) has color 0x%08x.\n", color);
15285 color = get_surface_color(rt, 332, 248);
15286 ok(compare_color(color, 0x00ffffff, 0), "(332, 248) has color 0x%08x.\n", color);
15287 color = get_surface_color(rt, 328, 252);
15288 ok(compare_color(color, 0x00ffffff, 0), "(328, 252) has color 0x%08x.\n", color);
15289 color = get_surface_color(rt, 332, 252);
15290 ok(compare_color(color, 0x0000ff00, 0), "(332, 252) has color 0x%08x.\n", color);
15292 color = get_surface_color(rt, 338, 248);
15293 ok(compare_color(color, 0x00ffffff, 0), "(338, 248) has color 0x%08x.\n", color);
15294 color = get_surface_color(rt, 342, 248);
15295 ok(compare_color(color, 0x00ffffff, 0), "(342, 248) has color 0x%08x.\n", color);
15296 color = get_surface_color(rt, 338, 252);
15297 ok(compare_color(color, 0x0000ff00, 0), "(338, 252) has color 0x%08x.\n", color);
15298 color = get_surface_color(rt, 342, 252);
15299 ok(compare_color(color, 0x00ffffff, 0), "(342, 252) has color 0x%08x.\n", color);
15301 color = get_surface_color(rt, 328, 258);
15302 ok(compare_color(color, 0x00ffffff, 0), "(328, 258) has color 0x%08x.\n", color);
15303 color = get_surface_color(rt, 332, 258);
15304 ok(compare_color(color, 0x0000ff00, 0), "(332, 258) has color 0x%08x.\n", color);
15305 color = get_surface_color(rt, 328, 262);
15306 ok(compare_color(color, 0x00ffffff, 0), "(328, 262) has color 0x%08x.\n", color);
15307 color = get_surface_color(rt, 332, 262);
15308 ok(compare_color(color, 0x00ffffff, 0), "(332, 262) has color 0x%08x.\n", color);
15310 color = get_surface_color(rt, 338, 258);
15311 ok(compare_color(color, 0x0000ff00, 0), "(338, 258) has color 0x%08x.\n", color);
15312 color = get_surface_color(rt, 342, 258);
15313 ok(compare_color(color, 0x00ffffff, 0), "(342, 258) has color 0x%08x.\n", color);
15314 color = get_surface_color(rt, 338, 262);
15315 ok(compare_color(color, 0x00ffffff, 0), "(338, 262) has color 0x%08x.\n", color);
15316 color = get_surface_color(rt, 342, 262);
15317 ok(compare_color(color, 0x00ffffff, 0), "(342, 262) has color 0x%08x.\n", color);
15319 /* COLORWRITEENABLE, SRGBWRITEENABLE and scissor rectangles do not exist
15320 * in d3d3. */
15322 IDirect3DViewport3_Release(viewport3);
15323 IDirect3DViewport3_Release(viewport2);
15324 IDirect3DViewport3_Release(viewport);
15325 IDirectDrawSurface4_Release(rt);
15326 IDirectDraw4_Release(ddraw);
15327 IDirect3D3_Release(d3d);
15328 refcount = IDirect3DDevice3_Release(device);
15329 ok(!refcount, "Device has %u references left.\n", refcount);
15330 DestroyWindow(window);
15333 struct enum_surfaces_param
15335 IDirectDrawSurface4 *surfaces[8];
15336 unsigned int count;
15339 static HRESULT WINAPI enum_surfaces_cb(IDirectDrawSurface4 *surface, DDSURFACEDESC2 *desc, void *context)
15341 struct enum_surfaces_param *param = context;
15342 BOOL found = FALSE;
15343 unsigned int i;
15345 for (i = 0; i < ARRAY_SIZE(param->surfaces); ++i)
15347 if (param->surfaces[i] == surface)
15349 found = TRUE;
15350 break;
15354 ok(found, "Unexpected surface %p enumerated.\n", surface);
15355 IDirectDrawSurface4_Release(surface);
15356 ++param->count;
15358 return DDENUMRET_OK;
15361 static void test_enum_surfaces(void)
15363 struct enum_surfaces_param param = {{0}};
15364 DDSURFACEDESC2 desc;
15365 IDirectDraw4 *ddraw;
15366 HRESULT hr;
15368 ddraw = create_ddraw();
15369 ok(!!ddraw, "Failed to create a ddraw object.\n");
15371 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
15372 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
15374 memset(&desc, 0, sizeof(desc));
15375 desc.dwSize = sizeof(desc);
15376 desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
15377 desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
15378 U2(desc).dwMipMapCount = 3;
15379 desc.dwWidth = 32;
15380 desc.dwHeight = 32;
15381 hr = IDirectDraw4_CreateSurface(ddraw, &desc, &param.surfaces[0], NULL);
15382 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
15384 hr = IDirectDrawSurface4_GetAttachedSurface(param.surfaces[0], &desc.ddsCaps, &param.surfaces[1]);
15385 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
15386 hr = IDirectDrawSurface4_GetAttachedSurface(param.surfaces[1], &desc.ddsCaps, &param.surfaces[2]);
15387 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
15388 hr = IDirectDrawSurface4_GetAttachedSurface(param.surfaces[2], &desc.ddsCaps, &param.surfaces[3]);
15389 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
15390 ok(!param.surfaces[3], "Got unexpected pointer %p.\n", param.surfaces[3]);
15392 hr = IDirectDraw4_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
15393 &desc, &param, enum_surfaces_cb);
15394 ok(SUCCEEDED(hr), "Failed to enumerate surfaces, hr %#x.\n", hr);
15395 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
15397 param.count = 0;
15398 hr = IDirectDraw4_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
15399 NULL, &param, enum_surfaces_cb);
15400 ok(SUCCEEDED(hr), "Failed to enumerate surfaces, hr %#x.\n", hr);
15401 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
15403 IDirectDrawSurface4_Release(param.surfaces[2]);
15404 IDirectDrawSurface4_Release(param.surfaces[1]);
15405 IDirectDrawSurface4_Release(param.surfaces[0]);
15406 IDirectDraw4_Release(ddraw);
15409 static void test_viewport(void)
15411 static struct
15413 D3DVIEWPORT7 vp;
15414 RECT expected_rect;
15415 const char *message;
15417 tests[] =
15419 {{ 0, 0, 640, 480}, { 0, 120, 479, 359}, "Viewport (0, 0) - (640, 480)"},
15420 {{ 0, 0, 320, 240}, { 0, 60, 239, 179}, "Viewport (0, 0) - (320, 240)"},
15421 {{ 0, 0, 1280, 960}, { 0, 240, 639, 479}, "Viewport (0, 0) - (1280, 960)"},
15422 {{ 0, 0, 2000, 1600}, { 0, 400, 639, 479}, "Viewport (0, 0) - (2000, 1600)"},
15423 {{100, 100, 640, 480}, {100, 220, 579, 459}, "Viewport (100, 100) - (640, 480)"},
15424 {{ 0, 0, 8192, 8192}, {-10, -10, -10, -10}, "Viewport (0, 0) - (8192, 8192)"},
15426 static const struct vec2 rt_sizes[] =
15428 {640, 480}, {1280, 960}, {320, 240}, {800, 600},
15430 static D3DMATRIX mat =
15432 1.0f, 0.0f, 0.0f, 0.0f,
15433 0.0f, 1.0f, 0.0f, 0.0f,
15434 0.0f, 0.0f, 1.0f, 0.0f,
15435 0.0f, 0.0f, 0.0f, 1.0f,
15437 static struct vec3 quad[] =
15439 {-1.5f, -0.5f, 0.1f},
15440 {-1.5f, 0.5f, 0.1f},
15441 { 0.5f, -0.5f, 0.1f},
15442 { 0.5f, 0.5f, 0.1f},
15444 IDirect3DViewport3 *viewport, *full_viewport;
15445 IDirectDrawSurface4 *rt, *ds;
15446 DDSURFACEDESC2 surface_desc;
15447 IDirect3DDevice3 *device;
15448 BOOL expected_failure;
15449 IDirectDraw4 *ddraw;
15450 DDPIXELFORMAT z_fmt;
15451 D3DRECT clear_rect;
15452 unsigned int i, j;
15453 IDirect3D3 *d3d;
15454 D3DVIEWPORT2 vp;
15455 ULONG refcount;
15456 HWND window;
15457 HRESULT hr;
15459 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
15460 0, 0, 640, 480, 0, 0, 0, 0);
15461 if (!(device = create_device(window, DDSCL_NORMAL)))
15463 skip("Failed to create a 3D device, skipping test.\n");
15464 DestroyWindow(window);
15465 return;
15468 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
15469 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
15470 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
15471 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
15473 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
15474 ok(SUCCEEDED(hr), "Failed to disable depth test, hr %#x.\n", hr);
15475 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
15476 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
15478 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
15479 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
15480 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
15481 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
15482 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
15483 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
15485 ds = get_depth_stencil(device);
15486 memset(&surface_desc, 0, sizeof(surface_desc));
15487 surface_desc.dwSize = sizeof(surface_desc);
15488 hr = IDirectDrawSurface4_GetSurfaceDesc(ds, &surface_desc);
15489 z_fmt = U4(surface_desc).ddpfPixelFormat;
15491 for (i = 0; i < ARRAY_SIZE(rt_sizes); ++i)
15493 if (i)
15495 memset(&surface_desc, 0, sizeof(surface_desc));
15496 surface_desc.dwSize = sizeof(surface_desc);
15497 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
15498 surface_desc.dwWidth = rt_sizes[i].x;
15499 surface_desc.dwHeight = rt_sizes[i].y;
15500 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
15501 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &rt, NULL);
15502 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x (i %u).\n", hr, i);
15504 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
15505 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
15506 U4(surface_desc).ddpfPixelFormat = z_fmt;
15507 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &ds, NULL);
15508 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x (i %u).\n", hr, i);
15509 hr = IDirectDrawSurface4_AddAttachedSurface(rt, ds);
15510 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x (i %u).\n", hr, i);
15512 hr = IDirect3DDevice3_SetRenderTarget(device, rt, 0);
15513 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
15515 else
15517 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
15518 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
15521 full_viewport = create_viewport(device, 0, 0, rt_sizes[i].x, rt_sizes[i].y);
15523 U1(clear_rect).x1 = U2(clear_rect).y1 = 0;
15524 U3(clear_rect).x2 = rt_sizes[i].x;
15525 U4(clear_rect).y2 = rt_sizes[i].y;
15527 for (j = 0; j < ARRAY_SIZE(tests); ++j)
15529 expected_failure = tests[j].vp.dwX + tests[j].vp.dwWidth > rt_sizes[i].x
15530 || tests[j].vp.dwY + tests[j].vp.dwHeight > rt_sizes[i].y;
15532 hr = IDirect3DViewport3_Clear2(full_viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff000000, 0.0f, 0);
15533 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x (i %u, j %u).\n", hr, i, j);
15535 hr = IDirect3D3_CreateViewport(d3d, &viewport, NULL);
15536 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x (i %u, j %u).\n", hr, i, j);
15537 hr = IDirect3DViewport3_SetViewport2(viewport, NULL);
15538 ok(hr == E_INVALIDARG, "Setting NULL viewport data returned unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15539 memset(&vp, 0, sizeof(vp));
15540 vp.dwSize = sizeof(vp);
15541 vp.dwX = tests[j].vp.dwX;
15542 vp.dwY = tests[j].vp.dwY;
15543 vp.dwWidth = tests[j].vp.dwWidth;
15544 vp.dwHeight = tests[j].vp.dwHeight;
15545 vp.dvClipX = -1.0f;
15546 vp.dvClipY = 1.0f;
15547 vp.dvClipWidth = 2.0f;
15548 vp.dvClipHeight = 2.0f;
15549 vp.dvMinZ = 0.0f;
15550 vp.dvMaxZ = 1.0f;
15551 hr = IDirect3DViewport3_SetViewport2(viewport, &vp);
15552 ok(hr == D3DERR_VIEWPORTHASNODEVICE,
15553 "Setting viewport data returned unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15554 hr = IDirect3DDevice3_AddViewport(device, viewport);
15555 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x (i %u, j %u).\n", hr, i, j);
15556 hr = IDirect3DViewport3_SetViewport2(viewport, &vp);
15557 if (expected_failure)
15558 ok(hr == E_INVALIDARG,
15559 "Setting viewport data returned unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15560 else
15561 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x (i %u, j %u).\n", hr, i, j);
15563 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
15564 ok(SUCCEEDED(hr), "Failed to set the viewport, hr %#x (i %u, j %u).\n", hr, i, j);
15565 if (expected_failure)
15567 destroy_viewport(device, viewport);
15568 continue;
15571 hr = IDirect3DDevice3_BeginScene(device);
15572 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x (i %u, j %u).\n", hr, i, j);
15573 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
15574 ok(SUCCEEDED(hr), "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15575 hr = IDirect3DDevice3_EndScene(device);
15576 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x (i %u, j %u).\n", hr, i, j);
15578 check_rect(rt, tests[j].expected_rect, tests[j].message);
15580 destroy_viewport(device, viewport);
15583 destroy_viewport(device, full_viewport);
15585 hr = IDirectDrawSurface4_DeleteAttachedSurface(rt, 0, ds);
15586 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x (i %u).\n", hr, i);
15587 IDirectDrawSurface4_Release(ds);
15589 IDirectDrawSurface4_Release(rt);
15592 refcount = IDirect3DDevice3_Release(device);
15593 ok(!refcount, "Device has %u references left.\n", refcount);
15594 IDirect3D3_Release(d3d);
15595 IDirectDraw4_Release(ddraw);
15596 DestroyWindow(window);
15599 static void test_find_device(void)
15601 D3DFINDDEVICESEARCH search = {0};
15602 D3DFINDDEVICERESULT result = {0};
15603 IDirect3DDevice3 *device;
15604 IDirectDraw4 *ddraw;
15605 IDirect3D3 *d3d;
15606 unsigned int i;
15607 HWND window;
15608 HRESULT hr;
15610 struct
15612 DWORD size;
15613 GUID guid;
15614 D3DDEVICEDESC_V1 hw_desc;
15615 D3DDEVICEDESC_V1 sw_desc;
15616 } result_v1;
15618 struct
15620 DWORD size;
15621 GUID guid;
15622 D3DDEVICEDESC_V2 hw_desc;
15623 D3DDEVICEDESC_V2 sw_desc;
15624 } result_v2;
15626 static const struct
15628 const GUID *guid;
15629 HRESULT hr;
15631 tests[] =
15633 {&IID_IDirect3D, DDERR_NOTFOUND},
15634 {&IID_IDirect3DRampDevice, DDERR_NOTFOUND},
15635 {&IID_IDirect3DRGBDevice, D3D_OK},
15636 {&IID_IDirect3DMMXDevice, DDERR_NOTFOUND},
15637 {&IID_IDirect3DRefDevice, DDERR_NOTFOUND},
15638 {&IID_IDirect3DTnLHalDevice, DDERR_NOTFOUND},
15639 {&IID_IDirect3DNullDevice, DDERR_NOTFOUND},
15642 ddraw = create_ddraw();
15643 ok(!!ddraw, "Failed to create a ddraw object.\n");
15645 if (FAILED(IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
15647 skip("D3D interface is not available, skipping test.\n");
15648 IDirectDraw4_Release(ddraw);
15649 return;
15652 result.dwSize = sizeof(result);
15653 search.dwSize = sizeof(search);
15654 hr = IDirect3D3_FindDevice(d3d, NULL, NULL);
15655 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
15656 hr = IDirect3D3_FindDevice(d3d, NULL, &result);
15657 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
15658 hr = IDirect3D3_FindDevice(d3d, &search, NULL);
15659 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
15660 hr = IDirect3D3_FindDevice(d3d, &search, &result);
15661 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15662 ok(result.dwSize == sizeof(result), "Got unexpected result size %u.\n", result.dwSize);
15663 ok(result.ddHwDesc.dwSize == sizeof(result.ddHwDesc),
15664 "Got unexpected HW desc size %u.\n", result.ddHwDesc.dwSize);
15665 ok(result.ddSwDesc.dwSize == sizeof(result.ddSwDesc),
15666 "Got unexpected SW desc size %u.\n", result.ddSwDesc.dwSize);
15668 memset(&search, 0, sizeof(search));
15669 memset(&result, 0, sizeof(result));
15670 hr = IDirect3D3_FindDevice(d3d, &search, &result);
15671 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
15673 search.dwSize = sizeof(search) + 1;
15674 result.dwSize = sizeof(result) + 1;
15675 hr = IDirect3D3_FindDevice(d3d, &search, &result);
15676 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
15678 search.dwSize = sizeof(search);
15680 memset(&result_v1, 0, sizeof(result_v1));
15681 result_v1.size = sizeof(result_v1);
15682 hr = IDirect3D3_FindDevice(d3d, &search, (D3DFINDDEVICERESULT *)&result_v1);
15683 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15684 ok(result_v1.hw_desc.dwSize == sizeof(result.ddHwDesc),
15685 "Got unexpected HW desc size %u.\n", result_v1.hw_desc.dwSize);
15686 ok(result_v1.sw_desc.dwSize == sizeof(result.ddSwDesc),
15687 "Got unexpected SW desc size %u.\n", result_v1.sw_desc.dwSize);
15689 memset(&result_v2, 0, sizeof(result_v2));
15690 result_v2.size = sizeof(result_v2);
15691 hr = IDirect3D3_FindDevice(d3d, &search, (D3DFINDDEVICERESULT *)&result_v2);
15692 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15693 ok(result_v2.hw_desc.dwSize == sizeof(result.ddHwDesc),
15694 "Got unexpected HW desc size %u.\n", result_v2.hw_desc.dwSize);
15695 ok(result_v2.sw_desc.dwSize == sizeof(result.ddSwDesc),
15696 "Got unexpected SW desc size %u.\n", result_v2.sw_desc.dwSize);
15698 for (i = 0; i < ARRAY_SIZE(tests); ++i)
15700 memset(&search, 0, sizeof(search));
15701 search.dwSize = sizeof(search);
15702 search.dwFlags = D3DFDS_GUID;
15703 search.guid = *tests[i].guid;
15705 memset(&result, 0, sizeof(result));
15706 result.dwSize = sizeof(result);
15708 hr = IDirect3D3_FindDevice(d3d, &search, &result);
15709 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
15710 ok(result.dwSize == sizeof(result), "Test %u: Got unexpected result size %u.\n", i, result.dwSize);
15711 if (SUCCEEDED(hr))
15713 ok(result.ddHwDesc.dwSize == sizeof(result.ddHwDesc),
15714 "Test %u: Got unexpected HW desc size %u.\n", i, result.ddHwDesc.dwSize);
15715 ok(result.ddSwDesc.dwSize == sizeof(result.ddSwDesc),
15716 "Test %u: Got unexpected SW desc size %u.\n", i, result.ddSwDesc.dwSize);
15718 else
15720 ok(!result.ddHwDesc.dwSize,
15721 "Test %u: Got unexpected HW desc size %u.\n", i, result.ddHwDesc.dwSize);
15722 ok(!result.ddSwDesc.dwSize,
15723 "Test %u: Got unexpected SW desc size %u.\n", i, result.ddSwDesc.dwSize);
15727 /* The HAL device can only be enumerated if hardware acceleration is present. */
15728 search.dwSize = sizeof(search);
15729 search.dwFlags = D3DFDS_GUID;
15730 search.guid = IID_IDirect3DHALDevice;
15731 result.dwSize = sizeof(result);
15732 hr = IDirect3D3_FindDevice(d3d, &search, &result);
15734 window = create_window();
15735 device = create_device(window, DDSCL_NORMAL);
15736 if (hr == D3D_OK)
15737 ok(!!device, "Failed to create a 3D device.\n");
15738 else
15739 ok(!device, "Succeeded to create a 3D device.\n");
15740 if (device)
15741 IDirect3DDevice3_Release(device);
15742 DestroyWindow(window);
15744 /* Curiously the colour model criteria seem to be ignored. */
15745 search.dwSize = sizeof(search);
15746 search.dwFlags = D3DFDS_COLORMODEL;
15747 search.dcmColorModel = 0xdeadbeef;
15748 result.dwSize = sizeof(result);
15749 hr = IDirect3D3_FindDevice(d3d, &search, &result);
15750 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15752 IDirect3D3_Release(d3d);
15753 IDirectDraw4_Release(ddraw);
15756 static IDirectDraw4 *killfocus_ddraw;
15757 static IDirectDrawSurface4 *killfocus_surface;
15759 static LRESULT CALLBACK killfocus_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
15761 ULONG ref;
15763 if (message == WM_KILLFOCUS)
15765 ref = IDirectDrawSurface4_Release(killfocus_surface);
15766 ok(!ref, "Unexpected surface refcount %u.\n", ref);
15767 ref = IDirectDraw4_Release(killfocus_ddraw);
15768 ok(!ref, "Unexpected ddraw refcount %u.\n", ref);
15769 killfocus_ddraw = NULL;
15772 return DefWindowProcA(window, message, wparam, lparam);
15775 static void test_killfocus(void)
15777 DDSURFACEDESC2 surface_desc;
15778 HRESULT hr;
15779 HWND window;
15780 WNDCLASSA wc = {0};
15782 wc.lpfnWndProc = killfocus_proc;
15783 wc.lpszClassName = "ddraw_killfocus_wndproc_wc";
15784 ok(RegisterClassA(&wc), "Failed to register window class.\n");
15786 window = CreateWindowA("ddraw_killfocus_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW,
15787 0, 0, 640, 480, 0, 0, 0, 0);
15789 killfocus_ddraw = create_ddraw();
15790 ok(!!killfocus_ddraw, "Failed to create a ddraw object.\n");
15792 hr = IDirectDraw4_SetCooperativeLevel(killfocus_ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
15793 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
15795 memset(&surface_desc, 0, sizeof(surface_desc));
15796 surface_desc.dwSize = sizeof(surface_desc);
15797 surface_desc.dwFlags = DDSD_CAPS;
15798 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
15799 hr = IDirectDraw7_CreateSurface(killfocus_ddraw, &surface_desc, &killfocus_surface, NULL);
15800 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
15802 SetForegroundWindow(GetDesktopWindow());
15803 ok(!killfocus_ddraw, "WM_KILLFOCUS was not received.\n");
15805 DestroyWindow(window);
15806 UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL));
15809 static void test_sysmem_draw(void)
15811 D3DRECT rect_full = {{0}, {0}, {640}, {480}};
15812 IDirectDrawSurface4 *rt, *surface;
15813 IDirect3DViewport3 *viewport;
15814 DDSURFACEDESC2 surface_desc;
15815 D3DVERTEXBUFFERDESC vb_desc;
15816 IDirect3DTexture2 *texture;
15817 IDirect3DVertexBuffer *vb;
15818 IDirect3DDevice3 *device;
15819 IDirectDraw4 *ddraw;
15820 IDirect3D3 *d3d;
15821 D3DCOLOR color;
15822 ULONG refcount;
15823 HWND window;
15824 HRESULT hr;
15825 BYTE *data;
15827 static const struct
15829 struct vec3 position;
15830 DWORD diffuse;
15832 quad[] =
15834 {{ 0.0f, 0.0f, 0.0f}, 0x00000000},
15835 {{ 0.0f, 0.0f, 0.0f}, 0x00000000},
15836 {{ 0.0f, 0.0f, 0.0f}, 0x00000000},
15837 {{ 0.0f, 0.0f, 0.0f}, 0x00000000},
15838 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
15839 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
15840 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
15841 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
15843 static WORD indices[] = {4, 5, 6, 7};
15845 window = create_window();
15846 ok(!!window, "Failed to create a window.\n");
15848 if (!(device = create_device(window, DDSCL_NORMAL)))
15850 skip("Failed to create a 3D device, skipping test.\n");
15851 DestroyWindow(window);
15852 return;
15855 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
15856 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15857 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
15858 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15859 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
15860 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15862 viewport = create_viewport(device, 0, 0, 640, 480);
15863 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
15864 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15866 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
15867 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15869 vb_desc.dwSize = sizeof(vb_desc);
15870 vb_desc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
15871 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
15872 vb_desc.dwNumVertices = ARRAY_SIZE(quad);
15873 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &vb, 0, NULL);
15874 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15876 hr = IDirect3DVertexBuffer_Lock(vb, 0, (void **)&data, NULL);
15877 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15878 memcpy(data, quad, sizeof(quad));
15879 hr = IDirect3DVertexBuffer_Unlock(vb);
15880 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15882 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
15883 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15885 hr = IDirect3DDevice3_BeginScene(device);
15886 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15887 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 4, 4, 0);
15888 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15889 hr = IDirect3DDevice3_EndScene(device);
15890 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15892 color = get_surface_color(rt, 320, 240);
15893 ok(compare_color(color, 0x00007f7f, 1), "Got unexpected color 0x%08x.\n", color);
15895 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
15896 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15898 hr = IDirect3DDevice3_BeginScene(device);
15899 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15900 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, indices, 4, 0);
15901 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15902 hr = IDirect3DDevice3_EndScene(device);
15903 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15905 color = get_surface_color(rt, 320, 240);
15906 ok(compare_color(color, 0x00007f7f, 1), "Got unexpected color 0x%08x.\n", color);
15908 memset(&surface_desc, 0, sizeof(surface_desc));
15909 surface_desc.dwSize = sizeof(surface_desc);
15910 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
15911 surface_desc.dwHeight = 2;
15912 surface_desc.dwWidth = 2;
15913 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
15914 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
15915 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
15916 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
15917 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
15918 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
15919 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
15920 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
15921 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
15922 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15923 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
15924 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15925 IDirectDrawSurface4_Release(surface);
15926 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
15927 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15929 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
15930 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15932 hr = IDirect3DDevice3_BeginScene(device);
15933 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15934 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
15935 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15936 hr = IDirect3DDevice3_EndScene(device);
15937 ok(hr == D3D_OK || hr == D3DERR_SCENE_END_FAILED, "Got unexpected hr %#x.\n", hr);
15939 IDirect3DTexture2_Release(texture);
15940 IDirect3DVertexBuffer_Release(vb);
15941 IDirect3DViewport3_Release(viewport);
15942 IDirectDrawSurface4_Release(rt);
15943 IDirectDraw4_Release(ddraw);
15944 IDirect3D3_Release(d3d);
15945 refcount = IDirect3DDevice3_Release(device);
15946 ok(!refcount, "Device has %u references left.\n", refcount);
15947 DestroyWindow(window);
15950 static void test_gdi_surface(void)
15952 IDirectDrawSurface4 *primary, *backbuffer, *gdi_surface;
15953 DDSCAPS2 caps = {DDSCAPS_BACKBUFFER, 0, 0, {0}};
15954 DDSURFACEDESC2 surface_desc;
15955 IDirectDraw4 *ddraw;
15956 ULONG refcount;
15957 HWND window;
15958 HRESULT hr;
15960 window = create_window();
15961 ddraw = create_ddraw();
15962 ok(!!ddraw, "Failed to create a ddraw object.\n");
15963 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
15964 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15966 /* Retrieving the GDI surface requires a primary surface to exist. */
15967 gdi_surface = (void *)0xc0dec0de;
15968 hr = IDirectDraw4_GetGDISurface(ddraw, &gdi_surface);
15969 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
15970 ok(!gdi_surface, "Got unexpected surface %p.\n", gdi_surface);
15972 hr = IDirectDraw4_FlipToGDISurface(ddraw);
15973 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
15975 memset(&surface_desc, 0, sizeof(surface_desc));
15976 surface_desc.dwSize = sizeof(surface_desc);
15977 surface_desc.dwFlags = DDSD_CAPS;
15978 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
15979 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
15980 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15982 hr = IDirectDraw4_GetGDISurface(ddraw, &gdi_surface);
15983 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15984 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
15985 IDirectDrawSurface4_Release(gdi_surface);
15987 /* Flipping to the GDI surface requires the primary surface to be
15988 * flippable. */
15989 hr = IDirectDraw4_FlipToGDISurface(ddraw);
15990 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
15992 IDirectDrawSurface4_Release(primary);
15994 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
15995 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15997 memset(&surface_desc, 0, sizeof(surface_desc));
15998 surface_desc.dwSize = sizeof(surface_desc);
15999 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
16000 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
16001 U5(surface_desc).dwBackBufferCount = 1;
16002 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
16003 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16004 hr = IDirectDrawSurface4_GetAttachedSurface(primary, &caps, &backbuffer);
16005 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16006 ok(backbuffer != primary, "Got unexpected backbuffer %p.\n", backbuffer);
16008 hr = IDirectDraw4_GetGDISurface(ddraw, &gdi_surface);
16009 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16010 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
16011 IDirectDrawSurface4_Release(gdi_surface);
16013 hr = IDirectDrawSurface4_Flip(primary, NULL, DDFLIP_WAIT);
16014 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16015 hr = IDirectDraw4_GetGDISurface(ddraw, &gdi_surface);
16016 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16017 ok(gdi_surface == backbuffer || broken(gdi_surface == primary),
16018 "Got unexpected surface %p, expected %p.\n", gdi_surface, backbuffer);
16019 IDirectDrawSurface4_Release(gdi_surface);
16021 hr = IDirectDraw4_FlipToGDISurface(ddraw);
16022 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16024 hr = IDirectDraw4_GetGDISurface(ddraw, &gdi_surface);
16025 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16026 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
16027 IDirectDrawSurface4_Release(gdi_surface);
16029 hr = IDirectDraw4_FlipToGDISurface(ddraw);
16030 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16032 IDirectDrawSurface4_Release(backbuffer);
16033 IDirectDrawSurface4_Release(primary);
16035 refcount = IDirectDraw4_Release(ddraw);
16036 ok(!refcount, "%u references left.\n", refcount);
16037 DestroyWindow(window);
16040 static void test_alphatest(void)
16042 #define ALPHATEST_PASSED 0x0000ff00
16043 #define ALPHATEST_FAILED 0x00ff0000
16044 D3DRECT rect_full = {{0}, {0}, {640}, {480}};
16045 IDirect3DViewport3 *viewport;
16046 IDirect3DDevice3 *device;
16047 IDirectDrawSurface4 *rt;
16048 unsigned int i;
16049 D3DCOLOR color;
16050 ULONG refcount;
16051 HWND window;
16052 DWORD value;
16053 HRESULT hr;
16055 static const struct
16057 D3DCMPFUNC func;
16058 D3DCOLOR color_less;
16059 D3DCOLOR color_equal;
16060 D3DCOLOR color_greater;
16062 test_data[] =
16064 {D3DCMP_NEVER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_FAILED},
16065 {D3DCMP_LESS, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_FAILED},
16066 {D3DCMP_EQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_FAILED},
16067 {D3DCMP_LESSEQUAL, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_FAILED},
16068 {D3DCMP_GREATER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_PASSED},
16069 {D3DCMP_NOTEQUAL, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_PASSED},
16070 {D3DCMP_GREATEREQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_PASSED},
16071 {D3DCMP_ALWAYS, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED},
16073 static struct
16075 struct vec3 position;
16076 DWORD diffuse;
16078 quad[] =
16080 {{-1.0f, -1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
16081 {{-1.0f, 1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
16082 {{ 1.0f, -1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
16083 {{ 1.0f, 1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
16086 window = create_window();
16087 if (!(device = create_device(window, DDSCL_NORMAL)))
16089 skip("Failed to create a 3D device.\n");
16090 DestroyWindow(window);
16091 return;
16093 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
16094 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16096 viewport = create_viewport(device, 0, 0, 640, 480);
16097 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
16098 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16100 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
16101 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16102 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
16103 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16104 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
16105 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16106 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
16107 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16109 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
16111 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHAFUNC, test_data[i].func);
16112 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16114 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0f, 0);
16115 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16116 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHAREF, 0x70);
16117 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16118 hr = IDirect3DDevice3_BeginScene(device);
16119 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16120 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
16121 D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, ARRAY_SIZE(quad), 0);
16122 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16123 hr = IDirect3DDevice3_EndScene(device);
16124 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16125 color = get_surface_color(rt, 320, 240);
16126 ok(compare_color(color, test_data[i].color_greater, 0),
16127 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
16128 color, test_data[i].color_greater, test_data[i].func);
16130 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0f, 0);
16131 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16132 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHAREF, 0xff70);
16133 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16134 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHAREF, &value);
16135 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16136 ok(value == 0xff70, "Got unexpected value %#x.\n", value);
16137 hr = IDirect3DDevice3_BeginScene(device);
16138 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16139 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
16140 D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, ARRAY_SIZE(quad), 0);
16141 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16142 hr = IDirect3DDevice3_EndScene(device);
16143 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16144 color = get_surface_color(rt, 320, 240);
16145 ok(compare_color(color, test_data[i].color_greater, 0),
16146 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
16147 color, test_data[i].color_greater, test_data[i].func);
16150 destroy_viewport(device, viewport);
16151 IDirectDrawSurface4_Release(rt);
16152 refcount = IDirect3DDevice3_Release(device);
16153 ok(!refcount, "Device has %u references left.\n", refcount);
16154 DestroyWindow(window);
16157 static void test_clipper_refcount(void)
16159 IDirectDrawSurface4 *surface;
16160 IDirectDrawClipper *clipper, *clipper2;
16161 DDSURFACEDESC2 surface_desc;
16162 IDirectDraw4 *ddraw;
16163 IDirectDraw *ddraw1;
16164 ULONG refcount;
16165 HWND window;
16166 HRESULT hr;
16167 BOOL changed;
16168 const IDirectDrawClipperVtbl *orig_vtbl;
16170 window = create_window();
16171 ddraw = create_ddraw();
16172 ok(!!ddraw, "Failed to create a ddraw object.\n");
16173 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
16174 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16176 memset(&surface_desc, 0, sizeof(surface_desc));
16177 surface_desc.dwSize = sizeof(surface_desc);
16178 surface_desc.dwFlags = DDSD_CAPS;
16179 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
16180 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
16181 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16183 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL);
16184 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
16185 refcount = get_refcount((IUnknown *)clipper);
16186 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
16188 /* Show that clipper validation doesn't somehow happen through per-clipper vtable
16189 * pointers. */
16190 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper2, NULL);
16191 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
16192 ok(clipper->lpVtbl == clipper2->lpVtbl, "Got different clipper vtables %p and %p.\n",
16193 clipper->lpVtbl, clipper2->lpVtbl);
16194 orig_vtbl = clipper->lpVtbl;
16195 IDirectDrawClipper_Release(clipper2);
16197 /* Surfaces hold a reference to clippers. No surprises there. */
16198 hr = IDirectDrawSurface4_SetClipper(surface, clipper);
16199 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
16200 refcount = get_refcount((IUnknown *)clipper);
16201 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
16203 hr = IDirectDrawSurface4_GetClipper(surface, &clipper2);
16204 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#x.\n", hr);
16205 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
16206 refcount = IDirectDrawClipper_Release(clipper2);
16207 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
16209 hr = IDirectDrawSurface4_SetClipper(surface, NULL);
16210 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
16211 refcount = get_refcount((IUnknown *)clipper);
16212 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
16214 hr = IDirectDrawSurface4_SetClipper(surface, clipper);
16215 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
16216 refcount = get_refcount((IUnknown *)clipper);
16217 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
16219 refcount = IDirectDrawSurface4_Release(surface);
16220 ok(!refcount, "%u references left.\n", refcount);
16221 refcount = get_refcount((IUnknown *)clipper);
16222 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
16224 /* SetClipper with an invalid pointer crashes. */
16226 /* Clipper methods work with a broken vtable, with the exception of Release. */
16227 clipper->lpVtbl = (void *)0xdeadbeef;
16228 refcount = orig_vtbl->AddRef(clipper);
16229 todo_wine ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
16230 refcount = orig_vtbl->Release(clipper);
16231 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
16233 clipper->lpVtbl = orig_vtbl;
16234 refcount = orig_vtbl->Release(clipper);
16235 todo_wine ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
16237 /* Fix the refcount difference because Wine did not increase the ref in the
16238 * AddRef call above. */
16239 if (refcount)
16241 refcount = IDirectDrawClipper_Release(clipper);
16242 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
16245 /* Steal the reference and see what happens - releasing the surface works fine.
16246 * The clipper is destroyed and not kept alive by a hidden refcount - trying to
16247 * release it after the GetClipper call is likely to crash, and certain to crash
16248 * if we allocate and zero as much heap memory as we can get. */
16249 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
16250 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16251 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL);
16252 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
16253 hr = IDirectDrawSurface4_SetClipper(surface, clipper);
16254 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
16256 IDirectDrawClipper_Release(clipper);
16257 IDirectDrawClipper_Release(clipper);
16259 hr = IDirectDrawSurface4_GetClipper(surface, &clipper2);
16260 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#x.\n", hr);
16261 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
16263 /* Show that invoking the Release method does not crash, but don't get the
16264 * vtable through the clipper pointer because it is no longer pointing to
16265 * valid memory. */
16266 refcount = orig_vtbl->Release(clipper);
16267 ok(!refcount, "%u references left.\n", refcount);
16269 refcount = IDirectDrawSurface4_Release(surface);
16270 ok(!refcount, "%u references left.\n", refcount);
16272 /* It looks like the protection against invalid thispointers is part of
16273 * the IDirectDrawClipper method implementation, not IDirectDrawSurface. */
16274 clipper = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 0x1000);
16275 ok(!!clipper, "failed to allocate memory\n");
16277 /* Assigning the vtable to our fake clipper does NOT make a difference on
16278 * native - there is a different member of the clipper implementation struct
16279 * that is used to determine if a clipper is valid. */
16280 clipper->lpVtbl = orig_vtbl;
16282 refcount = orig_vtbl->AddRef(clipper);
16283 todo_wine ok(!refcount, "Got refcount %u.\n", refcount);
16284 refcount = orig_vtbl->AddRef((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef);
16285 ok(!refcount, "Got refcount %u.\n", refcount);
16287 changed = 0x1234;
16288 hr = orig_vtbl->IsClipListChanged(clipper, &changed);
16289 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
16290 todo_wine ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
16292 changed = 0x1234;
16293 hr = orig_vtbl->IsClipListChanged((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef, &changed);
16294 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
16295 ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
16297 /* Nope, we can't initialize our fake clipper. */
16298 hr = IDirectDraw4_QueryInterface(ddraw, &IID_IDirectDraw, (void **)&ddraw1);
16299 ok(SUCCEEDED(hr), "Failed to get ddraw1 interface, hr %#x.\n", hr);
16301 hr = orig_vtbl->Initialize(clipper, ddraw1, 0);
16302 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
16304 IDirectDraw_Release(ddraw1);
16306 HeapFree(GetProcessHeap(), 0, clipper);
16308 refcount = IDirectDraw4_Release(ddraw);
16309 ok(!refcount, "%u references left.\n", refcount);
16310 DestroyWindow(window);
16313 static void test_caps(void)
16315 DDCAPS hal_caps, hel_caps;
16316 IDirectDraw4 *ddraw;
16317 HRESULT hr;
16319 ddraw = create_ddraw();
16320 ok(!!ddraw, "Failed to create a ddraw object.\n");
16322 memset(&hal_caps, 0, sizeof(hal_caps));
16323 memset(&hel_caps, 0, sizeof(hel_caps));
16324 hal_caps.dwSize = sizeof(hal_caps);
16325 hel_caps.dwSize = sizeof(hel_caps);
16326 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, &hel_caps);
16327 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16328 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
16329 "Got unexpected caps %#x, expected %#x.\n",
16330 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
16331 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
16332 "Got unexpected caps %#x, expected %#x.\n",
16333 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
16335 IDirectDraw4_Release(ddraw);
16338 static void test_d32_support(void)
16340 IDirectDrawSurface4 *surface;
16341 DDSURFACEDESC2 surface_desc;
16342 IDirectDraw4 *ddraw;
16343 ULONG refcount;
16344 HWND window;
16345 HRESULT hr;
16347 window = create_window();
16348 ddraw = create_ddraw();
16349 ok(!!ddraw, "Failed to create a ddraw object.\n");
16350 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
16351 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16353 memset(&surface_desc, 0, sizeof(surface_desc));
16354 surface_desc.dwSize = sizeof(surface_desc);
16355 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
16356 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
16357 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
16358 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
16359 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 32;
16360 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0xffffffff;
16361 surface_desc.dwWidth = 64;
16362 surface_desc.dwHeight = 64;
16363 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
16364 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16366 memset(&surface_desc, 0, sizeof(surface_desc));
16367 surface_desc.dwSize = sizeof(surface_desc);
16368 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
16369 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16370 ok((surface_desc.dwFlags & DDSD_PIXELFORMAT), "Got unexpected flags %#x.\n", surface_desc.dwFlags);
16371 ok(U4(surface_desc).ddpfPixelFormat.dwFlags & DDPF_ZBUFFER,
16372 "Got unexpected format flags %#x.\n", U4(surface_desc).ddpfPixelFormat.dwFlags);
16373 ok(U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth == 32,
16374 "Got unexpected dwZBufferBitDepth %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth);
16375 ok(U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask == 0xffffffff,
16376 "Got unexpected Z mask 0x%08x.\n", U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask);
16377 ok(!(surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY),
16378 "Got unexpected surface caps %#x.\n", surface_desc.ddsCaps.dwCaps);
16379 IDirectDrawSurface4_Release(surface);
16381 refcount = IDirectDraw4_Release(ddraw);
16382 ok(!refcount, "%u references left.\n", refcount);
16383 DestroyWindow(window);
16386 START_TEST(ddraw4)
16388 DDDEVICEIDENTIFIER identifier;
16389 DEVMODEW current_mode;
16390 IDirectDraw4 *ddraw;
16391 HMODULE dwmapi;
16393 if (!(ddraw = create_ddraw()))
16395 skip("Failed to create a ddraw object, skipping tests.\n");
16396 return;
16399 if (ddraw_get_identifier(ddraw, &identifier))
16401 trace("Driver string: \"%s\"\n", identifier.szDriver);
16402 trace("Description string: \"%s\"\n", identifier.szDescription);
16403 trace("Driver version %d.%d.%d.%d\n",
16404 HIWORD(U(identifier.liDriverVersion).HighPart), LOWORD(U(identifier.liDriverVersion).HighPart),
16405 HIWORD(U(identifier.liDriverVersion).LowPart), LOWORD(U(identifier.liDriverVersion).LowPart));
16407 IDirectDraw4_Release(ddraw);
16409 memset(&current_mode, 0, sizeof(current_mode));
16410 current_mode.dmSize = sizeof(current_mode);
16411 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
16412 registry_mode.dmSize = sizeof(registry_mode);
16413 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
16414 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
16415 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
16417 skip("Current mode does not match registry mode, skipping test.\n");
16418 return;
16421 if ((dwmapi = LoadLibraryA("dwmapi.dll")))
16422 pDwmIsCompositionEnabled = (void *)GetProcAddress(dwmapi, "DwmIsCompositionEnabled");
16424 test_process_vertices();
16425 test_coop_level_create_device_window();
16426 test_clipper_blt();
16427 test_coop_level_d3d_state();
16428 test_surface_interface_mismatch();
16429 test_coop_level_threaded();
16430 test_depth_blit();
16431 test_texture_load_ckey();
16432 test_viewport_object();
16433 test_zenable();
16434 test_ck_rgba();
16435 test_ck_default();
16436 test_ck_complex();
16437 test_surface_qi();
16438 test_device_qi();
16439 test_wndproc();
16440 test_window_style();
16441 test_redundant_mode_set();
16442 test_coop_level_mode_set();
16443 test_coop_level_mode_set_multi();
16444 test_initialize();
16445 test_coop_level_surf_create();
16446 test_vb_discard();
16447 test_coop_level_multi_window();
16448 test_draw_strided();
16449 test_lighting();
16450 test_specular_lighting();
16451 test_clear_rect_count();
16452 test_coop_level_versions();
16453 test_lighting_interface_versions();
16454 test_coop_level_activateapp();
16455 test_texturemanage();
16456 test_block_formats_creation();
16457 test_unsupported_formats();
16458 test_rt_caps();
16459 test_primary_caps();
16460 test_surface_lock();
16461 test_surface_discard();
16462 test_flip();
16463 test_set_surface_desc();
16464 test_user_memory_getdc();
16465 test_sysmem_overlay();
16466 test_primary_palette();
16467 test_surface_attachment();
16468 test_private_data();
16469 test_pixel_format();
16470 test_create_surface_pitch();
16471 test_mipmap();
16472 test_palette_complex();
16473 test_p8_blit();
16474 test_material();
16475 test_palette_gdi();
16476 test_palette_alpha();
16477 test_vb_writeonly();
16478 test_lost_device();
16479 test_surface_desc_lock();
16480 test_texturemapblend();
16481 test_signed_formats();
16482 test_color_fill();
16483 test_texcoordindex();
16484 test_colorkey_precision();
16485 test_range_colorkey();
16486 test_shademode();
16487 test_lockrect_invalid();
16488 test_yv12_overlay();
16489 test_offscreen_overlay();
16490 test_overlay_rect();
16491 test_blt();
16492 test_blt_z_alpha();
16493 test_cross_device_blt();
16494 test_color_clamping();
16495 test_getdc();
16496 test_draw_primitive();
16497 test_edge_antialiasing_blending();
16498 test_transform_vertices();
16499 test_display_mode_surface_pixel_format();
16500 test_surface_desc_size();
16501 test_get_surface_from_dc();
16502 test_ck_operation();
16503 test_vb_refcount();
16504 test_compute_sphere_visibility();
16505 test_texture_stages_limits();
16506 test_set_render_state();
16507 test_map_synchronisation();
16508 test_depth_readback();
16509 test_clear();
16510 test_enum_surfaces();
16511 test_viewport();
16512 test_find_device();
16513 test_killfocus();
16514 test_sysmem_draw();
16515 test_gdi_surface();
16516 test_alphatest();
16517 test_clipper_refcount();
16518 test_caps();
16519 test_d32_support();