[NTDLL]
[reactos.git] / base / applications / dxdiag / ddtest.c
1 /*
2 * PROJECT: ReactX Diagnosis Application
3 * LICENSE: LGPL - See COPYING in the top level directory
4 * FILE: base/applications/dxdiag/ddtest.c
5 * PURPOSE: ReactX DirectDraw tests
6 * COPYRIGHT: Copyright 2008 Kamil Hornicek
7 *
8 */
9
10 #include "precomp.h"
11
12 BOOL DDPrimarySurfaceTest(HWND hWnd);
13 BOOL DDOffscreenBufferTest(HWND hWnd, BOOL Fullscreen);
14 VOID DDRedrawFrame(LPDIRECTDRAWSURFACE lpDDSurface);
15 VOID DDUpdateFrame(LPDIRECTDRAWSURFACE lpDDPrimarySurface ,LPDIRECTDRAWSURFACE lpDDBackBuffer, BOOL Fullscreen, INT *posX, INT *posY, INT *gainX, INT *gainY, RECT *rectDD);
16 static LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
17
18 #define TEST_DURATION 10000
19 #define WIDTH 640
20 #define HEIGHT 480
21 #define DD_TEST_STEP 5
22 #define DD_SQUARE_SIZE 100
23 #define DD_SQUARE_STEP 2
24
25
26 BOOL StartDDTest(HWND hWnd, HINSTANCE hInstance, INT resTestDescription, INT resResult, INT TestNr)
27 {
28 WCHAR szTestDescription[256];
29 WCHAR szCaption[256];
30 WCHAR szResult[256];
31 WCHAR szError[256];
32 BOOL Result;
33
34 LoadStringW(hInstance, IDS_DDTEST_TITLE, szCaption, sizeof(szCaption) / sizeof(WCHAR));
35 LoadStringW(hInstance, IDS_DDTEST_ERROR, szError, sizeof(szError) / sizeof(WCHAR));
36 LoadStringW(hInstance, resTestDescription, szTestDescription, sizeof(szTestDescription) / sizeof(WCHAR));
37 LoadStringW(hInstance, resResult, szResult, sizeof(szResult) / sizeof(WCHAR));
38
39 if(MessageBox(NULL, szTestDescription, szCaption, MB_YESNO | MB_ICONQUESTION) == IDNO)
40 return FALSE;
41
42 ShowWindow(hWnd, SW_SHOW);
43
44 switch(TestNr){
45 case 1:
46 Result = DDPrimarySurfaceTest(hWnd);
47 break;
48 case 2:
49 Result = DDOffscreenBufferTest(hWnd, FALSE);
50 break;
51 case 3:
52 Result = DDOffscreenBufferTest(hWnd, TRUE);
53 break;
54 default:
55 Result = FALSE;
56 }
57
58 ShowWindow(hWnd, SW_HIDE);
59
60 if(!Result)
61 {
62 MessageBox(NULL, szError, szCaption, MB_OK | MB_ICONERROR);
63 return FALSE;
64 }
65
66 if(MessageBox(NULL, szResult, szCaption, MB_YESNO | MB_ICONQUESTION) == IDYES)
67 return TRUE;
68
69 return FALSE;
70 }
71
72 VOID DDTests()
73 {
74 WNDCLASSEX winClass;
75 HWND hWnd;
76 HINSTANCE hInstance = NULL;
77 WCHAR szDescription[256];
78 WCHAR szCaption[256];
79
80 winClass.cbSize = sizeof(WNDCLASSEX);
81 winClass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
82 winClass.lpfnWndProc = WindowProc;
83 winClass.cbClsExtra = 0;
84 winClass.cbWndExtra = 0;
85 winClass.hInstance = hInstance;
86 winClass.hIcon = 0;
87 winClass.hCursor = 0;
88 winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
89 winClass.lpszMenuName = NULL;
90 winClass.lpszClassName = L"ddtest";
91 winClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
92
93 if (!RegisterClassEx(&winClass))
94 return;
95
96 hWnd = CreateWindowEx(0, winClass.lpszClassName, NULL,WS_POPUP,
97 (GetSystemMetrics(SM_CXSCREEN) - WIDTH)/2,
98 (GetSystemMetrics(SM_CYSCREEN) - HEIGHT)/2,
99 WIDTH, HEIGHT, NULL, NULL, hInstance, NULL);
100
101 if (!hWnd){
102 return;
103 }
104
105 LoadStringW(hInstance, IDS_DDTEST_DESCRIPTION, szDescription, sizeof(szDescription) / sizeof(WCHAR));
106 LoadStringW(hInstance, IDS_DDTEST_DESCRIPTION, szCaption, sizeof(szCaption) / sizeof(WCHAR));
107 if(MessageBox(NULL, szDescription, szCaption, MB_YESNO | MB_ICONQUESTION) == IDNO)
108 return;
109
110 StartDDTest(hWnd, hInstance, IDS_DDPRIMARY_DESCRIPTION, IDS_DDPRIMARY_RESULT, 1);
111 StartDDTest(hWnd, hInstance, IDS_DDOFFSCREEN_DESCRIPTION, IDS_DDOFFSCREEN_RESULT, 2);
112 StartDDTest(hWnd, hInstance, IDS_DDFULLSCREEN_DESCRIPTION, IDS_DDFULLSCREEN_RESULT, 3);
113
114 DestroyWindow(hWnd);
115 UnregisterClass(winClass.lpszClassName, hInstance);
116 }
117
118 BOOL DDPrimarySurfaceTest(HWND hWnd){
119 UINT TimerID;
120 MSG msg;
121
122 LPDIRECTDRAW lpDD = NULL;
123 LPDIRECTDRAWSURFACE lpDDSurface = NULL;
124 DDSURFACEDESC DDSurfaceDesc;
125
126 if(DirectDrawCreate(NULL, &lpDD, NULL) != DD_OK)
127 return FALSE;
128
129 if(lpDD->lpVtbl->SetCooperativeLevel(lpDD, hWnd, DDSCL_NORMAL) != DD_OK)
130 {
131 lpDD->lpVtbl->Release(lpDD);
132 return FALSE;
133 }
134
135 /* create our primary surface */
136 ZeroMemory(&DDSurfaceDesc, sizeof(DDSurfaceDesc));
137 DDSurfaceDesc.dwSize = sizeof(DDSurfaceDesc);
138 DDSurfaceDesc.dwFlags = DDSD_CAPS;
139 DDSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
140 DDSurfaceDesc.dwBackBufferCount = 0;
141
142 if(lpDD->lpVtbl->CreateSurface(lpDD, &DDSurfaceDesc, &lpDDSurface, NULL) != DD_OK)
143 {
144 lpDD->lpVtbl->Release(lpDD);
145 return FALSE;
146 }
147
148 TimerID = SetTimer(hWnd, -1, (UINT)TEST_DURATION, NULL);
149
150 while (TRUE)
151 {
152 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
153 {
154 if (msg.message == WM_TIMER && TimerID == msg.wParam)
155 break;
156 TranslateMessage(&msg);
157 DispatchMessage(&msg);
158 if (msg.message == WM_PAINT)
159 DDRedrawFrame(lpDDSurface);
160 }
161 }
162 KillTimer(hWnd, TimerID);
163 lpDDSurface->lpVtbl->Release(lpDDSurface);
164 lpDD->lpVtbl->Release(lpDD);
165
166 return TRUE;
167 }
168
169 VOID DDRedrawFrame(LPDIRECTDRAWSURFACE lpDDSurface)
170 {
171 HDC hdc;
172
173 if (lpDDSurface->lpVtbl->GetDC(lpDDSurface, &hdc) == DD_OK)
174 {
175 RECT rct;
176 HBRUSH BlackBrush, WhiteBrush;
177 BOOL Colour = FALSE;
178
179 rct.left = (GetSystemMetrics(SM_CXSCREEN) - WIDTH)/2;
180 rct.right = (GetSystemMetrics(SM_CXSCREEN) - WIDTH)/2 + WIDTH;
181 rct.top = (GetSystemMetrics(SM_CYSCREEN) - HEIGHT)/2;
182 rct.bottom = (GetSystemMetrics(SM_CYSCREEN) - HEIGHT)/2 + HEIGHT;
183
184 BlackBrush = CreateSolidBrush(RGB(0,0,0));
185 WhiteBrush = CreateSolidBrush(RGB(255,255,255));
186
187 while((rct.bottom - rct.top) > DD_TEST_STEP){
188 (Colour)? FillRect(hdc, &rct, WhiteBrush) : FillRect(hdc, &rct, BlackBrush);
189 rct.top += DD_TEST_STEP;
190 rct.bottom -= DD_TEST_STEP;
191 rct.left += DD_TEST_STEP;
192 rct.right -= DD_TEST_STEP;
193 Colour = !Colour;
194 }
195 DeleteObject((HGDIOBJ)BlackBrush);
196 DeleteObject((HGDIOBJ)WhiteBrush);
197 lpDDSurface->lpVtbl->ReleaseDC(lpDDSurface, hdc);
198 }
199 }
200
201
202 BOOL DDOffscreenBufferTest(HWND hWnd, BOOL Fullscreen){
203 UINT TimerID, TimerIDUpdate;
204 LPDIRECTDRAW lpDD;
205 LPDIRECTDRAWSURFACE lpDDPrimarySurface;
206 LPDIRECTDRAWSURFACE lpDDBackBuffer;
207 DDSURFACEDESC DDSurfaceDesc;
208 DDSURFACEDESC DDBBSurfaceDesc;
209 DDSCAPS DDSCaps;
210 MSG msg;
211 RECT rectDD;
212 POINT wndPoint;
213 INT posX = 0, posY = 10, xGain = DD_SQUARE_STEP, yGain = DD_SQUARE_STEP;
214
215 if(DirectDrawCreate(NULL, &lpDD, NULL) != DD_OK)
216 return FALSE;
217
218 ZeroMemory(&DDSurfaceDesc, sizeof(DDSurfaceDesc));
219 DDSurfaceDesc.dwSize = sizeof(DDSurfaceDesc);
220
221 if(Fullscreen)
222 {
223 if(lpDD->lpVtbl->SetCooperativeLevel(lpDD, hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN) != DD_OK)
224 {
225 lpDD->lpVtbl->Release(lpDD);
226 return FALSE;
227 }
228 if(lpDD->lpVtbl->SetDisplayMode(lpDD, WIDTH, HEIGHT, 32) != DD_OK)
229 {
230 lpDD->lpVtbl->Release(lpDD);
231 return FALSE;
232 }
233 DDSurfaceDesc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
234 DDSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
235 DDSurfaceDesc.dwBackBufferCount = 1;
236 }
237 else
238 {
239 if(lpDD->lpVtbl->SetCooperativeLevel(lpDD, hWnd, DDSCL_NORMAL) != DD_OK)
240 {
241 lpDD->lpVtbl->Release(lpDD);
242 return FALSE;
243 }
244 DDSurfaceDesc.dwFlags = DDSD_CAPS;
245 DDSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
246 }
247
248
249 if(lpDD->lpVtbl->CreateSurface(lpDD, &DDSurfaceDesc, &lpDDPrimarySurface, NULL) != DD_OK)
250 {
251 lpDD->lpVtbl->Release(lpDD);
252 return FALSE;
253 }
254
255 if(Fullscreen)
256 {
257 DDSCaps.dwCaps = DDSCAPS_BACKBUFFER;
258 if (lpDDPrimarySurface->lpVtbl->GetAttachedSurface(lpDDPrimarySurface, &DDSCaps,&lpDDBackBuffer) != DD_OK)
259 {
260 lpDDPrimarySurface->lpVtbl->Release(lpDDPrimarySurface);
261 lpDD->lpVtbl->Release(lpDD);
262 return FALSE;
263 }
264 }
265 else
266 {
267 /* create our offscreen back buffer */
268 ZeroMemory(&DDBBSurfaceDesc,sizeof(DDBBSurfaceDesc));
269 DDBBSurfaceDesc.dwSize = sizeof(DDBBSurfaceDesc);
270 DDBBSurfaceDesc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
271 DDBBSurfaceDesc.dwHeight = HEIGHT;
272 DDBBSurfaceDesc.dwWidth = WIDTH;
273 DDBBSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
274
275 if(lpDD->lpVtbl->CreateSurface(lpDD, &DDBBSurfaceDesc, &lpDDBackBuffer, NULL) != DD_OK)
276 {
277 lpDD->lpVtbl->Release(lpDD);
278 lpDDPrimarySurface->lpVtbl->Release(lpDDPrimarySurface);
279 return FALSE;
280 }
281 wndPoint.x = 0;
282 wndPoint.y = 0;
283 ClientToScreen(hWnd, &wndPoint);
284 GetClientRect(hWnd, &rectDD);
285 OffsetRect(&rectDD, wndPoint.x, wndPoint.y);
286 }
287
288 /* set our timers, TimerID - for test timeout, TimerIDUpdate - for frame updating */
289 TimerID = SetTimer(hWnd, -1, (UINT)TEST_DURATION, NULL);
290 TimerIDUpdate = SetTimer(hWnd, 2, (UINT)10, NULL);
291
292 while (TRUE)
293 {
294 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
295 {
296 if (msg.message == WM_TIMER)
297 {
298 if(msg.wParam == TimerID)
299 {
300 break;
301 }
302 else
303 {
304 DDUpdateFrame(lpDDPrimarySurface,lpDDBackBuffer, Fullscreen,&posX, &posY, &xGain, &yGain, &rectDD);
305 }
306 }
307 TranslateMessage(&msg);
308 DispatchMessage(&msg);
309 }
310 }
311
312 lpDDPrimarySurface->lpVtbl->Release(lpDDPrimarySurface);
313 /* backbuffer is released automatically when in fullscreen */
314 if(!Fullscreen)
315 lpDDBackBuffer->lpVtbl->Release(lpDDBackBuffer);
316 lpDD->lpVtbl->Release(lpDD);
317
318 return TRUE;
319 }
320
321
322 VOID DDUpdateFrame(LPDIRECTDRAWSURFACE lpDDPrimarySurface ,LPDIRECTDRAWSURFACE lpDDBackBuffer, BOOL Fullscreen, INT *posX, INT *posY, INT *gainX, INT *gainY, RECT *rectDD)
323 {
324 HDC hdc;
325 DDBLTFX DDBlitFx;
326
327 /* clear back buffer and paint it black */
328 ZeroMemory(&DDBlitFx, sizeof(DDBlitFx));
329 DDBlitFx.dwSize = sizeof(DDBlitFx);
330 DDBlitFx.dwFillColor = 0;
331
332 lpDDBackBuffer->lpVtbl->Blt(lpDDBackBuffer, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &DDBlitFx);
333
334 if (lpDDBackBuffer->lpVtbl->GetDC(lpDDBackBuffer, &hdc) == DD_OK)
335 {
336 RECT rct;
337 HBRUSH WhiteBrush;
338
339 rct.left = *posX;
340 rct.right = *posX+DD_SQUARE_SIZE;
341 rct.top = *posY;
342 rct.bottom = *posY+DD_SQUARE_SIZE;
343
344 WhiteBrush = CreateSolidBrush(RGB(255,255,255));
345 FillRect(hdc, &rct, WhiteBrush);
346
347 if(*posX >= (WIDTH - DD_SQUARE_SIZE)) *gainX = -(*gainX);
348 if(*posY >= (HEIGHT - DD_SQUARE_SIZE)) *gainY = -(*gainY);
349 if(*posX < 0) *gainX = -1*(*gainX);
350 if(*posY < 0) *gainY = -1*(*gainY);
351
352 *posX += *gainX;
353 *posY += *gainY;
354
355 lpDDBackBuffer->lpVtbl->ReleaseDC(lpDDBackBuffer, hdc);
356
357 if(Fullscreen)
358 {
359 lpDDPrimarySurface->lpVtbl->Flip(lpDDPrimarySurface, NULL, DDFLIP_WAIT);
360 }
361 else
362 {
363 lpDDPrimarySurface->lpVtbl->Blt(lpDDPrimarySurface, rectDD, lpDDBackBuffer, NULL, DDBLT_WAIT, NULL);
364 }
365 }
366 }
367
368 static LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
369 {
370 return DefWindowProc(hWnd, msg, wParam, lParam);
371 }