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
= (HBRUSH
) 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 */
122 if(lpddsd
->dwFlags
& DDSD_REFRESHRATE
)
124 ok(U2(*lpddsd
).dwRefreshRate
!= 0, "EnumDisplayModes callback with bad refresh rate\n");
127 adddisplaymode(lpddsd
);
132 static void enumdisplaymodes(void)
137 ZeroMemory(&ddsd
, sizeof(DDSURFACEDESC
));
138 ddsd
.dwSize
= sizeof(DDSURFACEDESC
);
139 ddsd
.dwFlags
= DDSD_CAPS
;
140 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_PRIMARYSURFACE
;
142 rc
= IDirectDraw_EnumDisplayModes(lpDD
,
143 DDEDM_STANDARDVGAMODES
, &ddsd
, 0, enummodescallback
);
144 ok(rc
==DD_OK
|| rc
==E_INVALIDARG
,"EnumDisplayModes returned: %x\n",rc
);
147 static void setdisplaymode(int i
)
151 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
152 hwnd
, DDSCL_ALLOWMODEX
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
153 ok(rc
==DD_OK
,"SetCooperativeLevel returned: %x\n",rc
);
154 if (modes
[i
].dwFlags
& DDSD_PIXELFORMAT
)
156 if (modes
[i
].ddpfPixelFormat
.dwFlags
& DDPF_RGB
)
158 rc
= IDirectDraw_SetDisplayMode(lpDD
,
159 modes
[i
].dwWidth
, modes
[i
].dwHeight
,
160 U1(modes
[i
].ddpfPixelFormat
).dwRGBBitCount
);
161 ok(DD_OK
==rc
|| DDERR_UNSUPPORTED
==rc
,"SetDisplayMode returned: %x\n",rc
);
166 SetRect(&virt
, 0, 0, GetSystemMetrics(SM_CXVIRTUALSCREEN
), GetSystemMetrics(SM_CYVIRTUALSCREEN
));
167 OffsetRect(&virt
, GetSystemMetrics(SM_XVIRTUALSCREEN
), GetSystemMetrics(SM_YVIRTUALSCREEN
));
168 SetRect(&scrn
, 0, 0, GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
));
169 trace("Mode (%dx%d) [%dx%d] (%d %d)x(%d %d)\n", modes
[i
].dwWidth
, modes
[i
].dwHeight
,
170 scrn
.right
, scrn
.bottom
, virt
.left
, virt
.top
, virt
.right
, virt
.bottom
);
172 ok(GetClipCursor(&r
), "GetClipCursor() failed\n");
173 /* ddraw sets clip rect here to the screen size, even for
175 ok(EqualRect(&r
, &scrn
), "Invalid clip rect: (%d %d) x (%d %d)\n",
176 r
.left
, r
.top
, r
.right
, r
.bottom
);
178 ok(ClipCursor(NULL
), "ClipCursor() failed\n");
179 ok(GetClipCursor(&r
), "GetClipCursor() failed\n");
180 ok(EqualRect(&r
, &virt
), "Invalid clip rect: (%d %d) x (%d %d)\n",
181 r
.left
, r
.top
, r
.right
, r
.bottom
);
183 rc
= IDirectDraw_RestoreDisplayMode(lpDD
);
184 ok(DD_OK
==rc
,"RestoreDisplayMode returned: %x\n",rc
);
190 static void createsurface(void)
196 ddsd
.dwSize
= sizeof(ddsd
);
197 ddsd
.dwFlags
= DDSD_CAPS
| DDSD_BACKBUFFERCOUNT
;
198 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_PRIMARYSURFACE
|
201 ddsd
.dwBackBufferCount
= 1;
202 rc
= IDirectDraw_CreateSurface(lpDD
, &ddsd
, &lpDDSPrimary
, NULL
);
203 ok(rc
==DD_OK
,"CreateSurface returned: %x\n",rc
);
204 ddscaps
.dwCaps
= DDSCAPS_BACKBUFFER
;
205 rc
= IDirectDrawSurface_GetAttachedSurface(lpDDSPrimary
, &ddscaps
, &lpDDSBack
);
206 ok(rc
==DD_OK
,"GetAttachedSurface returned: %x\n",rc
);
209 static void destroysurface(void)
211 if( lpDDSPrimary
!= NULL
)
213 IDirectDrawSurface_Release(lpDDSPrimary
);
218 static void testsurface(void)
220 const char* testMsg
= "ddraw device context test";
224 rc
= IDirectDrawSurface_GetDC(lpDDSBack
, &hdc
);
225 ok(rc
==DD_OK
, "IDirectDrawSurface_GetDC returned: %x\n",rc
);
226 SetBkColor(hdc
, RGB(0, 0, 255));
227 SetTextColor(hdc
, RGB(255, 255, 0));
228 TextOut(hdc
, 0, 0, testMsg
, lstrlen(testMsg
));
229 IDirectDrawSurface_ReleaseDC(lpDDSBack
, hdc
);
230 ok(rc
==DD_OK
, "IDirectDrawSurface_ReleaseDC returned: %x\n",rc
);
234 rc
= IDirectDrawSurface_Flip(lpDDSPrimary
, NULL
, DDFLIP_WAIT
);
235 ok(rc
==DD_OK
|| rc
==DDERR_SURFACELOST
, "IDirectDrawSurface_BltFast returned: %x\n",rc
);
241 else if (rc
== DDERR_SURFACELOST
)
243 rc
= IDirectDrawSurface_Restore(lpDDSPrimary
);
244 ok(rc
==DD_OK
, "IDirectDrawSurface_Restore returned: %x\n",rc
);
249 static void testdisplaymodes(void)
253 for (i
= 0; i
< modes_cnt
; ++i
)
262 static void testcooperativelevels_normal(void)
265 DDSURFACEDESC surfacedesc
;
266 IDirectDrawSurface
*surface
= (IDirectDrawSurface
*) 0xdeadbeef;
268 memset(&surfacedesc
, 0, sizeof(surfacedesc
));
269 surfacedesc
.dwSize
= sizeof(surfacedesc
);
270 surfacedesc
.ddpfPixelFormat
.dwSize
= sizeof(surfacedesc
.ddpfPixelFormat
);
271 surfacedesc
.dwFlags
= DDSD_CAPS
| DDSD_BACKBUFFERCOUNT
;
272 surfacedesc
.dwBackBufferCount
= 1;
273 surfacedesc
.ddsCaps
.dwCaps
= DDSCAPS_PRIMARYSURFACE
| DDSCAPS_COMPLEX
| DDSCAPS_FLIP
;
275 /* Do some tests with DDSCL_NORMAL mode */
277 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
279 ok(rc
==DD_OK
,"SetCooperativeLevel(DDSCL_NORMAL) returned: %x\n",rc
);
281 /* Try creating a double buffered primary in normal mode */
282 rc
= IDirectDraw_CreateSurface(lpDD
, &surfacedesc
, &surface
, NULL
);
283 ok(rc
== DDERR_NOEXCLUSIVEMODE
, "IDirectDraw_CreateSurface returned %08x\n", rc
);
284 ok(surface
== NULL
, "Returned surface pointer is %p\n", surface
);
285 if(surface
) IDirectDrawSurface_Release(surface
);
287 /* Set the focus window */
288 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
289 hwnd
, DDSCL_SETFOCUSWINDOW
);
290 ok(rc
==DD_OK
,"SetCooperativeLevel(DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
292 /* Set the focus window a second time*/
293 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
294 hwnd
, DDSCL_SETFOCUSWINDOW
);
295 ok(rc
==DD_OK
,"SetCooperativeLevel(DDSCL_SETFOCUSWINDOW) the second time returned: %x\n",rc
);
297 /* Test DDSCL_SETFOCUSWINDOW with the other flags. They should all fail, except of DDSCL_NOWINDOWCHANGES */
298 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
299 hwnd
, DDSCL_NORMAL
| DDSCL_SETFOCUSWINDOW
);
300 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_NORMAL | DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
302 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
303 hwnd
, DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
| DDSCL_SETFOCUSWINDOW
);
304 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
306 /* This one succeeds */
307 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
308 hwnd
, DDSCL_NOWINDOWCHANGES
| DDSCL_SETFOCUSWINDOW
);
309 ok(rc
==DD_OK
,"SetCooperativeLevel(DDSCL_NOWINDOWCHANGES | DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
311 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
312 hwnd
, DDSCL_MULTITHREADED
| DDSCL_SETFOCUSWINDOW
);
313 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_MULTITHREADED | DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
315 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
316 hwnd
, DDSCL_FPUSETUP
| DDSCL_SETFOCUSWINDOW
);
317 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_FPUSETUP | DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
319 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
320 hwnd
, DDSCL_FPUPRESERVE
| DDSCL_SETFOCUSWINDOW
);
321 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_FPUPRESERVE | DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
323 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
324 hwnd
, DDSCL_ALLOWREBOOT
| DDSCL_SETFOCUSWINDOW
);
325 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_ALLOWREBOOT | DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
327 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
328 hwnd
, DDSCL_ALLOWMODEX
| DDSCL_SETFOCUSWINDOW
);
329 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_ALLOWMODEX | DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
331 /* Set the device window without any other flags. Should give an error */
332 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
333 hwnd
, DDSCL_SETDEVICEWINDOW
);
334 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_SETDEVICEWINDOW) returned: %x\n",rc
);
336 /* Set device window with DDSCL_NORMAL */
337 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
338 hwnd
, DDSCL_NORMAL
| DDSCL_SETDEVICEWINDOW
);
339 ok(rc
==DD_OK
,"SetCooperativeLevel(DDSCL_NORMAL | DDSCL_SETDEVICEWINDOW) returned: %x\n",rc
);
341 /* Also set the focus window. Should give an error */
342 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
343 hwnd
, DDSCL_ALLOWMODEX
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
| DDSCL_SETDEVICEWINDOW
| DDSCL_SETFOCUSWINDOW
);
344 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_NORMAL | DDSCL_SETDEVICEWINDOW | DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
349 static void testcooperativelevels_exclusive(void)
353 /* Do some tests with DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN mode */
355 /* Try to set exclusive mode only */
356 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
357 hwnd
, DDSCL_EXCLUSIVE
);
358 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_EXCLUSIVE) returned: %x\n",rc
);
360 /* Full screen mode only */
361 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
362 hwnd
, DDSCL_FULLSCREEN
);
363 ok(rc
==DDERR_INVALIDPARAMS
,"SetCooperativeLevel(DDSCL_FULLSCREEN) returned: %x\n",rc
);
365 /* Full screen mode + exclusive mode */
366 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
367 hwnd
, DDSCL_FULLSCREEN
| DDSCL_EXCLUSIVE
);
368 ok(rc
==DD_OK
,"SetCooperativeLevel(DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN) returned: %x\n",rc
);
370 /* Set the focus window. Should fail */
371 rc
= IDirectDraw_SetCooperativeLevel(lpDD
,
372 hwnd
, DDSCL_SETFOCUSWINDOW
);
373 ok(rc
==DDERR_HWNDALREADYSET
,"SetCooperativeLevel(DDSCL_SETFOCUSWINDOW) returned: %x\n",rc
);
379 START_TEST(ddrawmodes
)
382 if (!createdirectdraw())
385 if (winetest_interactive
)
391 testcooperativelevels_normal();
395 testcooperativelevels_exclusive();