xref: /reactos/base/applications/dxdiag/ddtest.c (revision 84344399)
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 
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 
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 
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 
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 
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 
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