2 * Unit tests for ddraw functions
5 * Part of this test involves changing the screen resolution. But this is
6 * really disrupting if the user is doing something else and is not very nice
7 * to CRT screens. Plus, ideally it needs someone watching it to check that
8 * each mode displays correctly.
9 * So this is only done if the test is being run in interactive mode.
11 * Copyright (C) 2003 Sami Aario
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2.1 of the License, or (at your option) any later version.
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this library; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "wine/test.h"
32 static LPDIRECTDRAW lpDD
= NULL
;
33 static LPDIRECTDRAWSURFACE lpDDSPrimary
= NULL
;
34 static LPDIRECTDRAWSURFACE lpDDSBack
= NULL
;
38 static int modes_size
;
39 static LPDDSURFACEDESC modes
;
41 static void createwindow(void)
43 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
44 wc
.lpfnWndProc
= DefWindowProcA
;
47 wc
.hInstance
= GetModuleHandleA(0);
48 wc
.hIcon
= LoadIconA(wc
.hInstance
, IDI_APPLICATION
);
49 wc
.hCursor
= LoadCursorA(NULL
, IDC_ARROW
);
50 wc
.hbrBackground
= GetStockObject(BLACK_BRUSH
);
51 wc
.lpszMenuName
= NULL
;
52 wc
.lpszClassName
= "TestWindowClass";
53 if(!RegisterClassA(&wc
))
56 hwnd
= CreateWindowExA(0, "TestWindowClass", "TestWindowClass",
58 GetSystemMetrics(SM_CXSCREEN
),
59 GetSystemMetrics(SM_CYSCREEN
),
60 NULL
, NULL
, GetModuleHandleA(0), NULL
);
63 ShowWindow(hwnd
, SW_HIDE
);
69 static BOOL
createdirectdraw(void)
73 rc
= DirectDrawCreate(NULL
, &lpDD
, NULL
);
74 ok(rc
==DD_OK
|| rc
==DDERR_NODIRECTDRAWSUPPORT
, "DirectDrawCreateEx returned: %x\n", rc
);
76 trace("DirectDrawCreateEx() failed with an error %x\n", rc
);
83 static void releasedirectdraw(void)
87 IDirectDraw_Release(lpDD
);
92 static void adddisplaymode(LPDDSURFACEDESC lpddsd
)
95 modes
= malloc((modes_size
= 2) * sizeof(DDSURFACEDESC
));
96 if (modes_cnt
== modes_size
)
97 modes
= realloc(modes
, (modes_size
*= 2) * sizeof(DDSURFACEDESC
));
99 modes
[modes_cnt
++] = *lpddsd
;
102 static void flushdisplaymodes(void)
106 modes_cnt
= modes_size
= 0;
109 static HRESULT WINAPI
enummodescallback(LPDDSURFACEDESC lpddsd
, LPVOID lpContext
)
111 trace("Width = %i, Height = %i, Refresh Rate = %i, Pitch = %i, flags =%02X\r\n",
112 lpddsd
->dwWidth
, lpddsd
->dwHeight
,
113 U2(*lpddsd
).dwRefreshRate
, U1(*lpddsd
).lPitch
, lpddsd
->dwFlags
);
115 /* Check that the pitch is valid if applicable */
116 if(lpddsd
->dwFlags
& DDSD_PITCH
)
118 ok(U1(*lpddsd
).lPitch
!= 0, "EnumDisplayModes callback with bad pitch\n");
121 /* Check that frequency is valid if applicable
123 * This fails on some Windows drivers or Windows versions, so it isn't important
125 if(lpddsd->dwFlags & DDSD_REFRESHRATE)
127 ok(U2(*lpddsd).dwRefreshRate != 0, "EnumDisplayModes callback with bad refresh rate\n");
131 adddisplaymode(lpddsd
);
136 static void enumdisplaymodes(void)
141 ZeroMemory(&ddsd
, sizeof(DDSURFACEDESC
));
142 ddsd
.dwSize
= sizeof(DDSURFACEDESC
);
143 ddsd
.dwFlags
= DDSD_CAPS
;
144 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_PRIMARYSURFACE
;
146 rc
= IDirectDraw_EnumDisplayModes(lpDD
,
147 DDEDM_STANDARDVGAMODES
, &ddsd
, 0, enummodescallback
);
148 ok(rc
==DD_OK
|| rc
==E_INVALIDARG
,"EnumDisplayModes returned: %x\n",rc
);
151 static void setdisplaymode(int i
)
155 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
156 hwnd
, DDSCL_ALLOWMODEX
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
157 ok(rc
==DD_OK
,"SetCooperativeLevel returned: %x\n",rc
);
158 if (modes
[i
].dwFlags
& DDSD_PIXELFORMAT
)
160 if (modes
[i
].ddpfPixelFormat
.dwFlags
& DDPF_RGB
)
162 rc
= IDirectDraw_SetDisplayMode(lpDD
,
163 modes
[i
].dwWidth
, modes
[i
].dwHeight
,
164 U1(modes
[i
].ddpfPixelFormat
).dwRGBBitCount
);
165 ok(DD_OK
==rc
|| DDERR_UNSUPPORTED
==rc
,"SetDisplayMode returned: %x\n",rc
);
170 SetRect(&virt
, 0, 0, GetSystemMetrics(SM_CXVIRTUALSCREEN
), GetSystemMetrics(SM_CYVIRTUALSCREEN
));
171 OffsetRect(&virt
, GetSystemMetrics(SM_XVIRTUALSCREEN
), GetSystemMetrics(SM_YVIRTUALSCREEN
));
172 SetRect(&scrn
, 0, 0, GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
));
173 trace("Mode (%dx%d) [%dx%d] (%d %d)x(%d %d)\n", modes
[i
].dwWidth
, modes
[i
].dwHeight
,
174 scrn
.right
, scrn
.bottom
, virt
.left
, virt
.top
, virt
.right
, virt
.bottom
);
176 ok(GetClipCursor(&r
), "GetClipCursor() failed\n");
177 /* ddraw sets clip rect here to the screen size, even for
179 ok(EqualRect(&r
, &scrn
), "Invalid clip rect: (%d %d) x (%d %d)\n",
180 r
.left
, r
.top
, r
.right
, r
.bottom
);
182 ok(ClipCursor(NULL
), "ClipCursor() failed\n");
183 ok(GetClipCursor(&r
), "GetClipCursor() failed\n");
184 ok(EqualRect(&r
, &virt
), "Invalid clip rect: (%d %d) x (%d %d)\n",
185 r
.left
, r
.top
, r
.right
, r
.bottom
);
187 rc
= IDirectDraw_RestoreDisplayMode(lpDD
);
188 ok(DD_OK
==rc
,"RestoreDisplayMode returned: %x\n",rc
);
194 static void createsurface(void)
200 ddsd
.dwSize
= sizeof(ddsd
);
201 ddsd
.dwFlags
= DDSD_CAPS
| DDSD_BACKBUFFERCOUNT
;
202 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_PRIMARYSURFACE
|
205 ddsd
.dwBackBufferCount
= 1;
206 rc
= IDirectDraw_CreateSurface(lpDD
, &ddsd
, &lpDDSPrimary
, NULL
);
207 ok(rc
==DD_OK
,"CreateSurface returned: %x\n",rc
);
208 ddscaps
.dwCaps
= DDSCAPS_BACKBUFFER
;
209 rc
= IDirectDrawSurface_GetAttachedSurface(lpDDSPrimary
, &ddscaps
, &lpDDSBack
);
210 ok(rc
==DD_OK
,"GetAttachedSurface returned: %x\n",rc
);
213 static void destroysurface(void)
215 if( lpDDSPrimary
!= NULL
)
217 IDirectDrawSurface_Release(lpDDSPrimary
);
222 static void testsurface(void)
224 const char* testMsg
= "ddraw device context test";
228 rc
= IDirectDrawSurface_GetDC(lpDDSBack
, &hdc
);
229 ok(rc
==DD_OK
, "IDirectDrawSurface_GetDC returned: %x\n",rc
);
230 SetBkColor(hdc
, RGB(0, 0, 255));
231 SetTextColor(hdc
, RGB(255, 255, 0));
232 TextOut(hdc
, 0, 0, testMsg
, lstrlen(testMsg
));
233 IDirectDrawSurface_ReleaseDC(lpDDSBack
, hdc
);
234 ok(rc
==DD_OK
, "IDirectDrawSurface_ReleaseDC returned: %x\n",rc
);
238 rc
= IDirectDrawSurface_Flip(lpDDSPrimary
, NULL
, DDFLIP_WAIT
);
239 ok(rc
==DD_OK
|| rc
==DDERR_SURFACELOST
, "IDirectDrawSurface_BltFast returned: %x\n",rc
);
245 else if (rc
== DDERR_SURFACELOST
)
247 rc
= IDirectDrawSurface_Restore(lpDDSPrimary
);
248 ok(rc
==DD_OK
, "IDirectDrawSurface_Restore returned: %x\n",rc
);
253 static void testdisplaymodes(void)
257 for (i
= 0; i
< modes_cnt
; ++i
)
266 static void testcooperativelevels_normal(void)
269 DDSURFACEDESC surfacedesc
;
270 IDirectDrawSurface
*surface
= (IDirectDrawSurface
*) 0xdeadbeef;
272 memset(&surfacedesc
, 0, sizeof(surfacedesc
));
273 surfacedesc
.dwSize
= sizeof(surfacedesc
);
274 surfacedesc
.ddpfPixelFormat
.dwSize
= sizeof(surfacedesc
.ddpfPixelFormat
);
275 surfacedesc
.dwFlags
= DDSD_CAPS
| DDSD_BACKBUFFERCOUNT
;
276 surfacedesc
.dwBackBufferCount
= 1;
277 surfacedesc
.ddsCaps
.dwCaps
= DDSCAPS_PRIMARYSURFACE
| DDSCAPS_COMPLEX
| DDSCAPS_FLIP
;
279 /* Do some tests with DDSCL_NORMAL mode */
281 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
283 ok(rc
==DD_OK
,"SetCooperativeLevel(DDSCL_NORMAL) returned: %x\n",rc
);
285 /* Try creating a double buffered primary in normal mode */
286 rc
= IDirectDraw_CreateSurface(lpDD
, &surfacedesc
, &surface
, NULL
);
287 if (rc
== DDERR_UNSUPPORTEDMODE
)
288 skip("Unsupported mode\n");
291 ok(rc
== DDERR_NOEXCLUSIVEMODE
, "IDirectDraw_CreateSurface returned %08x\n", rc
);
292 ok(surface
== NULL
, "Returned surface pointer is %p\n", surface
);
294 if(surface
&& surface
!= (IDirectDrawSurface
*)0xdeadbeef) IDirectDrawSurface_Release(surface
);
296 /* Set the focus window */
297 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
298 hwnd
, DDSCL_SETFOCUSWINDOW
);
299 ok(rc
==DD_OK
,"SetCooperativeLevel(DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
301 /* Set the focus window a second time*/
302 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
303 hwnd
, DDSCL_SETFOCUSWINDOW
);
304 ok(rc
==DD_OK
,"SetCooperativeLevel(DDSCL_SETFOCUSWINDOW) the second time returned: %x\n",rc
);
306 /* Test DDSCL_SETFOCUSWINDOW with the other flags. They should all fail, except of DDSCL_NOWINDOWCHANGES */
307 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
308 hwnd
, DDSCL_NORMAL
| DDSCL_SETFOCUSWINDOW
);
309 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_NORMAL | DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
311 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
312 hwnd
, DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
| DDSCL_SETFOCUSWINDOW
);
313 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
315 /* This one succeeds */
316 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
317 hwnd
, DDSCL_NOWINDOWCHANGES
| DDSCL_SETFOCUSWINDOW
);
318 ok(rc
==DD_OK
,"SetCooperativeLevel(DDSCL_NOWINDOWCHANGES | DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
320 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
321 hwnd
, DDSCL_MULTITHREADED
| DDSCL_SETFOCUSWINDOW
);
322 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_MULTITHREADED | DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
324 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
325 hwnd
, DDSCL_FPUSETUP
| DDSCL_SETFOCUSWINDOW
);
326 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_FPUSETUP | DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
328 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
329 hwnd
, DDSCL_FPUPRESERVE
| DDSCL_SETFOCUSWINDOW
);
330 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_FPUPRESERVE | DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
332 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
333 hwnd
, DDSCL_ALLOWREBOOT
| DDSCL_SETFOCUSWINDOW
);
334 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_ALLOWREBOOT | DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
336 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
337 hwnd
, DDSCL_ALLOWMODEX
| DDSCL_SETFOCUSWINDOW
);
338 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_ALLOWMODEX | DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
340 /* Set the device window without any other flags. Should give an error */
341 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
342 hwnd
, DDSCL_SETDEVICEWINDOW
);
343 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_SETDEVICEWINDOW) returned: %x\n",rc
);
345 /* Set device window with DDSCL_NORMAL */
346 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
347 hwnd
, DDSCL_NORMAL
| DDSCL_SETDEVICEWINDOW
);
348 ok(rc
==DD_OK
,"SetCooperativeLevel(DDSCL_NORMAL | DDSCL_SETDEVICEWINDOW) returned: %x\n",rc
);
350 /* Also set the focus window. Should give an error */
351 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
352 hwnd
, DDSCL_ALLOWMODEX
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
| DDSCL_SETDEVICEWINDOW
| DDSCL_SETFOCUSWINDOW
);
353 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_NORMAL | DDSCL_SETDEVICEWINDOW | DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
358 static void testcooperativelevels_exclusive(void)
362 /* Do some tests with DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN mode */
364 /* Try to set exclusive mode only */
365 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
366 hwnd
, DDSCL_EXCLUSIVE
);
367 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_EXCLUSIVE) returned: %x\n",rc
);
369 /* Full screen mode only */
370 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
371 hwnd
, DDSCL_FULLSCREEN
);
372 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_FULLSCREEN) returned: %x\n",rc
);
374 /* Full screen mode + exclusive mode */
375 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
376 hwnd
, DDSCL_FULLSCREEN
| DDSCL_EXCLUSIVE
);
377 ok(rc
==DD_OK
,"SetCooperativeLevel(DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN) returned: %x\n",rc
);
379 /* Set the focus window. Should fail */
380 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
381 hwnd
, DDSCL_SETFOCUSWINDOW
);
382 ok(rc
==DDERR_HWNDALREADYSET
,"SetCooperativeLevel(DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
388 static void testddraw3(void)
390 const GUID My_IID_IDirectDraw3
= {
394 { 0x8f,0xcc,0x0,0xc0,0x4f,0xd9,0x18,0x9d }
398 hr
= IDirectDraw_QueryInterface(lpDD
, &My_IID_IDirectDraw3
, (void **) &dd3
);
399 ok(hr
== E_NOINTERFACE
, "QueryInterface for IID_IDirectDraw3 returned 0x%08x, expected E_NOINTERFACE\n", hr
);
400 if(SUCCEEDED(hr
) && dd3
) IDirectDraw3_Release(dd3
);
403 START_TEST(ddrawmodes
)
406 if (!createdirectdraw())
409 if (winetest_interactive
)
416 testcooperativelevels_normal();
420 testcooperativelevels_exclusive();