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