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