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