xref: /reactos/base/applications/dxdiag/ddtest.c (revision 05c39d8d)
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 
17 #define TEST_DURATION 10000
18 #define DD_TEST_WIDTH 640
19 #define DD_TEST_HEIGHT 480
20 #define DD_TEST_STEP 5
21 #define DD_SQUARE_SIZE 100
22 #define DD_SQUARE_STEP 2
23 
24 
25 BOOL StartDDTest(HWND hWnd, HINSTANCE hInstance, INT resTestDescription, INT resResult, INT TestNr)
26 {
27     WCHAR szTestDescription[256];
28     WCHAR szCaption[256];
29     WCHAR szResult[256];
30     WCHAR szError[256];
31     BOOL Result;
32 
33     LoadStringW(hInstance, IDS_MAIN_DIALOG, szCaption, sizeof(szCaption) / sizeof(WCHAR));
34     LoadStringW(hInstance, IDS_DDTEST_ERROR, szError, sizeof(szError) / sizeof(WCHAR));
35     LoadStringW(hInstance, resTestDescription, szTestDescription, sizeof(szTestDescription) / sizeof(WCHAR));
36     LoadStringW(hInstance, resResult, szResult, sizeof(szResult) / sizeof(WCHAR));
37 
38     if(MessageBox(NULL, szTestDescription, szCaption, MB_YESNO | MB_ICONQUESTION) == IDNO)
39         return FALSE;
40 
41     ShowWindow(hWnd, SW_SHOW);
42 
43     switch(TestNr){
44         case 1:
45             Result = DDPrimarySurfaceTest(hWnd);
46             break;
47         case 2:
48             Result = DDOffscreenBufferTest(hWnd, FALSE);
49             break;
50         case 3:
51             Result = DDOffscreenBufferTest(hWnd, TRUE);
52             break;
53         default:
54             Result = FALSE;
55     }
56 
57     ShowWindow(hWnd, SW_HIDE);
58 
59     if(!Result)
60     {
61         MessageBox(NULL, szError, szCaption, MB_OK | MB_ICONERROR);
62         return FALSE;
63     }
64 
65     if(MessageBox(NULL, szResult, szCaption, MB_YESNO | MB_ICONQUESTION) == IDYES)
66         return TRUE;
67 
68     return FALSE;
69 }
70 
71 VOID DDTests()
72 {
73     WNDCLASSEX winClass;
74     HWND hWnd;
75     HINSTANCE hInstance = NULL;
76     WCHAR szDescription[256];
77     WCHAR szCaption[256];
78 
79     winClass.cbSize = sizeof(WNDCLASSEX);
80     winClass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
81     winClass.lpfnWndProc = DefWindowProc;
82     winClass.cbClsExtra = 0;
83     winClass.cbWndExtra = 0;
84     winClass.hInstance = hInstance;
85     winClass.hIcon = 0;
86     winClass.hCursor = 0;
87     winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
88     winClass.lpszMenuName = NULL;
89     winClass.lpszClassName = L"ddtest";
90     winClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
91 
92     if (!RegisterClassEx(&winClass))
93         return;
94 
95     hWnd = CreateWindowEx(0, winClass.lpszClassName, NULL,WS_POPUP,
96                           (GetSystemMetrics(SM_CXSCREEN) - DD_TEST_WIDTH)/2,
97                           (GetSystemMetrics(SM_CYSCREEN) - DD_TEST_HEIGHT)/2,
98                           DD_TEST_WIDTH, DD_TEST_HEIGHT, NULL, NULL, hInstance, NULL);
99 
100     if (!hWnd){
101         return;
102     }
103 
104     LoadStringW(hInstance, IDS_DDTEST_DESCRIPTION, szDescription, sizeof(szDescription) / sizeof(WCHAR));
105     LoadStringW(hInstance, IDS_MAIN_DIALOG, szCaption, sizeof(szCaption) / sizeof(WCHAR));
106     if(MessageBox(NULL, szDescription, szCaption, MB_YESNO | MB_ICONQUESTION) == IDNO)
107         return;
108 
109     StartDDTest(hWnd, hInstance, IDS_DDPRIMARY_DESCRIPTION, IDS_DDPRIMARY_RESULT, 1);
110     StartDDTest(hWnd, hInstance, IDS_DDOFFSCREEN_DESCRIPTION, IDS_DDOFFSCREEN_RESULT, 2);
111     StartDDTest(hWnd, hInstance, IDS_DDFULLSCREEN_DESCRIPTION, IDS_DDFULLSCREEN_RESULT, 3);
112 
113     DestroyWindow(hWnd);
114     UnregisterClass(winClass.lpszClassName, hInstance);
115 }
116 
117 BOOL DDPrimarySurfaceTest(HWND hWnd){
118     UINT TimerID;
119     MSG msg;
120 
121     LPDIRECTDRAW lpDD = NULL;
122     LPDIRECTDRAWSURFACE lpDDSurface = NULL;
123     DDSURFACEDESC DDSurfaceDesc;
124 
125     if(DirectDrawCreate(NULL, &lpDD, NULL) != DD_OK)
126         return FALSE;
127 
128     if(lpDD->lpVtbl->SetCooperativeLevel(lpDD, hWnd, DDSCL_NORMAL) != DD_OK)
129     {
130         lpDD->lpVtbl->Release(lpDD);
131         return FALSE;
132     }
133 
134     /* create our primary surface */
135     ZeroMemory(&DDSurfaceDesc, sizeof(DDSurfaceDesc));
136     DDSurfaceDesc.dwSize = sizeof(DDSurfaceDesc);
137     DDSurfaceDesc.dwFlags = DDSD_CAPS;
138     DDSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
139     DDSurfaceDesc.dwBackBufferCount = 0;
140 
141     if(lpDD->lpVtbl->CreateSurface(lpDD, &DDSurfaceDesc, &lpDDSurface, NULL) != DD_OK)
142     {
143         lpDD->lpVtbl->Release(lpDD);
144         return FALSE;
145     }
146 
147     TimerID = SetTimer(hWnd, -1, (UINT)TEST_DURATION, NULL);
148 
149     while (TRUE)
150     {
151         if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
152         {
153             if (msg.message == WM_TIMER && TimerID == msg.wParam)
154                 break;
155             TranslateMessage(&msg);
156             DispatchMessage(&msg);
157             if (msg.message == WM_PAINT)
158                 DDRedrawFrame(lpDDSurface);
159         }
160     }
161     KillTimer(hWnd, TimerID);
162     lpDDSurface->lpVtbl->Release(lpDDSurface);
163     lpDD->lpVtbl->Release(lpDD);
164 
165 return TRUE;
166 }
167 
168 VOID DDRedrawFrame(LPDIRECTDRAWSURFACE lpDDSurface)
169 {
170     HDC hdc;
171 
172     if (lpDDSurface->lpVtbl->GetDC(lpDDSurface, &hdc) == DD_OK)
173     {
174         RECT rct;
175         HBRUSH BlackBrush, WhiteBrush;
176         BOOL Colour = FALSE;
177 
178         rct.left = (GetSystemMetrics(SM_CXSCREEN) - DD_TEST_WIDTH)/2;
179         rct.right = (GetSystemMetrics(SM_CXSCREEN) - DD_TEST_WIDTH)/2 + DD_TEST_WIDTH;
180         rct.top = (GetSystemMetrics(SM_CYSCREEN) - DD_TEST_HEIGHT)/2;
181         rct.bottom = (GetSystemMetrics(SM_CYSCREEN) - DD_TEST_HEIGHT)/2 + DD_TEST_HEIGHT;
182 
183         BlackBrush = CreateSolidBrush(RGB(0,0,0));
184         WhiteBrush = CreateSolidBrush(RGB(255,255,255));
185 
186         while((rct.bottom - rct.top) > DD_TEST_STEP){
187             (Colour)? FillRect(hdc, &rct, WhiteBrush) : FillRect(hdc, &rct, BlackBrush);
188             rct.top += DD_TEST_STEP;
189             rct.bottom -= DD_TEST_STEP;
190             rct.left += DD_TEST_STEP;
191             rct.right -= DD_TEST_STEP;
192             Colour = !Colour;
193         }
194         DeleteObject((HGDIOBJ)BlackBrush);
195         DeleteObject((HGDIOBJ)WhiteBrush);
196         lpDDSurface->lpVtbl->ReleaseDC(lpDDSurface, hdc);
197     }
198 }
199 
200 
201 BOOL DDOffscreenBufferTest(HWND hWnd, BOOL Fullscreen){
202     UINT_PTR TimerID, TimerIDUpdate;
203     LPDIRECTDRAW lpDD;
204     LPDIRECTDRAWSURFACE lpDDPrimarySurface;
205     LPDIRECTDRAWSURFACE lpDDBackBuffer;
206     DDSURFACEDESC DDSurfaceDesc;
207     DDSURFACEDESC DDBBSurfaceDesc;
208     DDSCAPS DDSCaps;
209     MSG msg;
210     RECT rectDD;
211     POINT wndPoint;
212     INT posX = 0, posY = 10, xGain = DD_SQUARE_STEP, yGain = DD_SQUARE_STEP;
213 
214     if(DirectDrawCreate(NULL, &lpDD, NULL) != DD_OK)
215         return FALSE;
216 
217     ZeroMemory(&DDSurfaceDesc, sizeof(DDSurfaceDesc));
218     DDSurfaceDesc.dwSize = sizeof(DDSurfaceDesc);
219 
220     if(Fullscreen)
221     {
222         if(lpDD->lpVtbl->SetCooperativeLevel(lpDD, hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN) != DD_OK)
223         {
224             lpDD->lpVtbl->Release(lpDD);
225             return FALSE;
226         }
227         if(lpDD->lpVtbl->SetDisplayMode(lpDD, DD_TEST_WIDTH, DD_TEST_HEIGHT, 32) != DD_OK)
228         {
229             lpDD->lpVtbl->Release(lpDD);
230             return FALSE;
231         }
232         DDSurfaceDesc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
233         DDSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE  | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
234         DDSurfaceDesc.dwBackBufferCount = 1;
235     }
236     else
237     {
238         if(lpDD->lpVtbl->SetCooperativeLevel(lpDD, hWnd, DDSCL_NORMAL) != DD_OK)
239         {
240             lpDD->lpVtbl->Release(lpDD);
241             return FALSE;
242         }
243         DDSurfaceDesc.dwFlags = DDSD_CAPS;
244         DDSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
245     }
246 
247 
248     if(lpDD->lpVtbl->CreateSurface(lpDD, &DDSurfaceDesc, &lpDDPrimarySurface, NULL) != DD_OK)
249     {
250         lpDD->lpVtbl->Release(lpDD);
251         return FALSE;
252     }
253 
254     if(Fullscreen)
255     {
256         DDSCaps.dwCaps = DDSCAPS_BACKBUFFER;
257         if (lpDDPrimarySurface->lpVtbl->GetAttachedSurface(lpDDPrimarySurface, &DDSCaps,&lpDDBackBuffer) != DD_OK)
258         {
259             lpDDPrimarySurface->lpVtbl->Release(lpDDPrimarySurface);
260             lpDD->lpVtbl->Release(lpDD);
261             return FALSE;
262         }
263     }
264     else
265     {
266         /* create our offscreen back buffer */
267         ZeroMemory(&DDBBSurfaceDesc,sizeof(DDBBSurfaceDesc));
268         DDBBSurfaceDesc.dwSize = sizeof(DDBBSurfaceDesc);
269         DDBBSurfaceDesc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
270         DDBBSurfaceDesc.dwHeight = DD_TEST_HEIGHT;
271         DDBBSurfaceDesc.dwWidth = DD_TEST_WIDTH;
272         DDBBSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
273 
274         if(lpDD->lpVtbl->CreateSurface(lpDD, &DDBBSurfaceDesc, &lpDDBackBuffer, NULL) != DD_OK)
275         {
276             lpDD->lpVtbl->Release(lpDD);
277             lpDDPrimarySurface->lpVtbl->Release(lpDDPrimarySurface);
278             return FALSE;
279         }
280         wndPoint.x = 0;
281         wndPoint.y = 0;
282         ClientToScreen(hWnd, &wndPoint);
283         GetClientRect(hWnd, &rectDD);
284         OffsetRect(&rectDD, wndPoint.x, wndPoint.y);
285     }
286 
287     /* set our timers, TimerID - for test timeout, TimerIDUpdate - for frame updating */
288     TimerID = SetTimer(hWnd, -1, (UINT)TEST_DURATION, NULL);
289     TimerIDUpdate = SetTimer(hWnd, 2, (UINT)10, NULL);
290     (void)TimerIDUpdate;
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 >= (DD_TEST_WIDTH - DD_SQUARE_SIZE)) *gainX = -(*gainX);
348         if(*posY >= (DD_TEST_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