/* * PROJECT: ReactX Diagnosis Application * LICENSE: LGPL - See COPYING in the top level directory * PURPOSE: ReactX DirectDraw tests * COPYRIGHT: Copyright 2008 Kamil Horníček * */ #include "precomp.h" BOOL DDPrimarySurfaceTest(HWND hWnd); BOOL DDOffscreenBufferTest(HWND hWnd, BOOL Fullscreen); VOID DDRedrawFrame(LPDIRECTDRAWSURFACE lpDDSurface); VOID DDUpdateFrame(LPDIRECTDRAWSURFACE lpDDPrimarySurface ,LPDIRECTDRAWSURFACE lpDDBackBuffer, BOOL Fullscreen, INT *posX, INT *posY, INT *gainX, INT *gainY, RECT *rectDD); #define TEST_DURATION 10000 #define DD_TEST_WIDTH 640 #define DD_TEST_HEIGHT 480 #define DD_TEST_STEP 5 #define DD_SQUARE_SIZE 100 #define DD_SQUARE_STEP 2 BOOL StartDDTest(HWND hWnd, HINSTANCE hInstance, INT resTestDescription, INT resResult, INT TestNr) { WCHAR szTestDescription[256]; WCHAR szCaption[256]; WCHAR szResult[256]; WCHAR szError[256]; BOOL Result; LoadStringW(hInstance, IDS_MAIN_DIALOG, szCaption, sizeof(szCaption) / sizeof(WCHAR)); LoadStringW(hInstance, IDS_DDTEST_ERROR, szError, sizeof(szError) / sizeof(WCHAR)); LoadStringW(hInstance, resTestDescription, szTestDescription, sizeof(szTestDescription) / sizeof(WCHAR)); LoadStringW(hInstance, resResult, szResult, sizeof(szResult) / sizeof(WCHAR)); if(MessageBox(NULL, szTestDescription, szCaption, MB_YESNO | MB_ICONQUESTION) == IDNO) return FALSE; ShowWindow(hWnd, SW_SHOW); switch(TestNr){ case 1: Result = DDPrimarySurfaceTest(hWnd); break; case 2: Result = DDOffscreenBufferTest(hWnd, FALSE); break; case 3: Result = DDOffscreenBufferTest(hWnd, TRUE); break; default: Result = FALSE; } ShowWindow(hWnd, SW_HIDE); if(!Result) { MessageBox(NULL, szError, szCaption, MB_OK | MB_ICONERROR); return FALSE; } if(MessageBox(NULL, szResult, szCaption, MB_YESNO | MB_ICONQUESTION) == IDYES) return TRUE; return FALSE; } VOID DDTests() { WNDCLASSEX winClass; HWND hWnd; HINSTANCE hInstance = NULL; WCHAR szDescription[256]; WCHAR szCaption[256]; winClass.cbSize = sizeof(WNDCLASSEX); winClass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW; winClass.lpfnWndProc = DefWindowProc; winClass.cbClsExtra = 0; winClass.cbWndExtra = 0; winClass.hInstance = hInstance; winClass.hIcon = 0; winClass.hCursor = 0; winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); winClass.lpszMenuName = NULL; winClass.lpszClassName = L"ddtest"; winClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if (!RegisterClassEx(&winClass)) return; hWnd = CreateWindowEx(0, winClass.lpszClassName, NULL,WS_POPUP, (GetSystemMetrics(SM_CXSCREEN) - DD_TEST_WIDTH)/2, (GetSystemMetrics(SM_CYSCREEN) - DD_TEST_HEIGHT)/2, DD_TEST_WIDTH, DD_TEST_HEIGHT, NULL, NULL, hInstance, NULL); if (!hWnd){ return; } LoadStringW(hInstance, IDS_DDTEST_DESCRIPTION, szDescription, sizeof(szDescription) / sizeof(WCHAR)); LoadStringW(hInstance, IDS_MAIN_DIALOG, szCaption, sizeof(szCaption) / sizeof(WCHAR)); if(MessageBox(NULL, szDescription, szCaption, MB_YESNO | MB_ICONQUESTION) == IDNO) return; StartDDTest(hWnd, hInstance, IDS_DDPRIMARY_DESCRIPTION, IDS_DDPRIMARY_RESULT, 1); StartDDTest(hWnd, hInstance, IDS_DDOFFSCREEN_DESCRIPTION, IDS_DDOFFSCREEN_RESULT, 2); StartDDTest(hWnd, hInstance, IDS_DDFULLSCREEN_DESCRIPTION, IDS_DDFULLSCREEN_RESULT, 3); DestroyWindow(hWnd); UnregisterClass(winClass.lpszClassName, hInstance); } BOOL DDPrimarySurfaceTest(HWND hWnd){ UINT TimerID; MSG msg; LPDIRECTDRAW lpDD = NULL; LPDIRECTDRAWSURFACE lpDDSurface = NULL; DDSURFACEDESC DDSurfaceDesc; if(DirectDrawCreate(NULL, &lpDD, NULL) != DD_OK) return FALSE; if(lpDD->lpVtbl->SetCooperativeLevel(lpDD, hWnd, DDSCL_NORMAL) != DD_OK) { lpDD->lpVtbl->Release(lpDD); return FALSE; } /* create our primary surface */ ZeroMemory(&DDSurfaceDesc, sizeof(DDSurfaceDesc)); DDSurfaceDesc.dwSize = sizeof(DDSurfaceDesc); DDSurfaceDesc.dwFlags = DDSD_CAPS; DDSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE; DDSurfaceDesc.dwBackBufferCount = 0; if(lpDD->lpVtbl->CreateSurface(lpDD, &DDSurfaceDesc, &lpDDSurface, NULL) != DD_OK) { lpDD->lpVtbl->Release(lpDD); return FALSE; } TimerID = SetTimer(hWnd, -1, (UINT)TEST_DURATION, NULL); while (TRUE) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_TIMER && TimerID == msg.wParam) break; TranslateMessage(&msg); DispatchMessage(&msg); if (msg.message == WM_PAINT) DDRedrawFrame(lpDDSurface); } } KillTimer(hWnd, TimerID); lpDDSurface->lpVtbl->Release(lpDDSurface); lpDD->lpVtbl->Release(lpDD); return TRUE; } VOID DDRedrawFrame(LPDIRECTDRAWSURFACE lpDDSurface) { HDC hdc; if (lpDDSurface->lpVtbl->GetDC(lpDDSurface, &hdc) == DD_OK) { RECT rct; HBRUSH BlackBrush, WhiteBrush; BOOL Colour = FALSE; rct.left = (GetSystemMetrics(SM_CXSCREEN) - DD_TEST_WIDTH)/2; rct.right = (GetSystemMetrics(SM_CXSCREEN) - DD_TEST_WIDTH)/2 + DD_TEST_WIDTH; rct.top = (GetSystemMetrics(SM_CYSCREEN) - DD_TEST_HEIGHT)/2; rct.bottom = (GetSystemMetrics(SM_CYSCREEN) - DD_TEST_HEIGHT)/2 + DD_TEST_HEIGHT; BlackBrush = CreateSolidBrush(RGB(0,0,0)); WhiteBrush = CreateSolidBrush(RGB(255,255,255)); while((rct.bottom - rct.top) > DD_TEST_STEP){ (Colour)? FillRect(hdc, &rct, WhiteBrush) : FillRect(hdc, &rct, BlackBrush); rct.top += DD_TEST_STEP; rct.bottom -= DD_TEST_STEP; rct.left += DD_TEST_STEP; rct.right -= DD_TEST_STEP; Colour = !Colour; } DeleteObject((HGDIOBJ)BlackBrush); DeleteObject((HGDIOBJ)WhiteBrush); lpDDSurface->lpVtbl->ReleaseDC(lpDDSurface, hdc); } } BOOL DDOffscreenBufferTest(HWND hWnd, BOOL Fullscreen){ UINT_PTR TimerID, TimerIDUpdate; LPDIRECTDRAW lpDD; LPDIRECTDRAWSURFACE lpDDPrimarySurface; LPDIRECTDRAWSURFACE lpDDBackBuffer; DDSURFACEDESC DDSurfaceDesc; DDSURFACEDESC DDBBSurfaceDesc; DDSCAPS DDSCaps; MSG msg; RECT rectDD; POINT wndPoint; INT posX = 0, posY = 10, xGain = DD_SQUARE_STEP, yGain = DD_SQUARE_STEP; if(DirectDrawCreate(NULL, &lpDD, NULL) != DD_OK) return FALSE; ZeroMemory(&DDSurfaceDesc, sizeof(DDSurfaceDesc)); DDSurfaceDesc.dwSize = sizeof(DDSurfaceDesc); if(Fullscreen) { if(lpDD->lpVtbl->SetCooperativeLevel(lpDD, hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN) != DD_OK) { lpDD->lpVtbl->Release(lpDD); return FALSE; } if(lpDD->lpVtbl->SetDisplayMode(lpDD, DD_TEST_WIDTH, DD_TEST_HEIGHT, 32) != DD_OK) { lpDD->lpVtbl->Release(lpDD); return FALSE; } DDSurfaceDesc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; DDSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; DDSurfaceDesc.dwBackBufferCount = 1; } else { if(lpDD->lpVtbl->SetCooperativeLevel(lpDD, hWnd, DDSCL_NORMAL) != DD_OK) { lpDD->lpVtbl->Release(lpDD); return FALSE; } DDSurfaceDesc.dwFlags = DDSD_CAPS; DDSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; } if(lpDD->lpVtbl->CreateSurface(lpDD, &DDSurfaceDesc, &lpDDPrimarySurface, NULL) != DD_OK) { lpDD->lpVtbl->Release(lpDD); return FALSE; } if(Fullscreen) { DDSCaps.dwCaps = DDSCAPS_BACKBUFFER; if (lpDDPrimarySurface->lpVtbl->GetAttachedSurface(lpDDPrimarySurface, &DDSCaps,&lpDDBackBuffer) != DD_OK) { lpDDPrimarySurface->lpVtbl->Release(lpDDPrimarySurface); lpDD->lpVtbl->Release(lpDD); return FALSE; } } else { /* create our offscreen back buffer */ ZeroMemory(&DDBBSurfaceDesc,sizeof(DDBBSurfaceDesc)); DDBBSurfaceDesc.dwSize = sizeof(DDBBSurfaceDesc); DDBBSurfaceDesc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; DDBBSurfaceDesc.dwHeight = DD_TEST_HEIGHT; DDBBSurfaceDesc.dwWidth = DD_TEST_WIDTH; DDBBSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; if(lpDD->lpVtbl->CreateSurface(lpDD, &DDBBSurfaceDesc, &lpDDBackBuffer, NULL) != DD_OK) { lpDD->lpVtbl->Release(lpDD); lpDDPrimarySurface->lpVtbl->Release(lpDDPrimarySurface); return FALSE; } wndPoint.x = 0; wndPoint.y = 0; ClientToScreen(hWnd, &wndPoint); GetClientRect(hWnd, &rectDD); OffsetRect(&rectDD, wndPoint.x, wndPoint.y); } /* set our timers, TimerID - for test timeout, TimerIDUpdate - for frame updating */ TimerID = SetTimer(hWnd, -1, (UINT)TEST_DURATION, NULL); TimerIDUpdate = SetTimer(hWnd, 2, (UINT)10, NULL); (void)TimerIDUpdate; while (TRUE) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_TIMER) { if(msg.wParam == TimerID) { break; } else { DDUpdateFrame(lpDDPrimarySurface,lpDDBackBuffer, Fullscreen,&posX, &posY, &xGain, &yGain, &rectDD); } } TranslateMessage(&msg); DispatchMessage(&msg); } } lpDDPrimarySurface->lpVtbl->Release(lpDDPrimarySurface); /* backbuffer is released automatically when in fullscreen */ if(!Fullscreen) lpDDBackBuffer->lpVtbl->Release(lpDDBackBuffer); lpDD->lpVtbl->Release(lpDD); return TRUE; } VOID DDUpdateFrame(LPDIRECTDRAWSURFACE lpDDPrimarySurface ,LPDIRECTDRAWSURFACE lpDDBackBuffer, BOOL Fullscreen, INT *posX, INT *posY, INT *gainX, INT *gainY, RECT *rectDD) { HDC hdc; DDBLTFX DDBlitFx; /* clear back buffer and paint it black */ ZeroMemory(&DDBlitFx, sizeof(DDBlitFx)); DDBlitFx.dwSize = sizeof(DDBlitFx); DDBlitFx.dwFillColor = 0; lpDDBackBuffer->lpVtbl->Blt(lpDDBackBuffer, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &DDBlitFx); if (lpDDBackBuffer->lpVtbl->GetDC(lpDDBackBuffer, &hdc) == DD_OK) { RECT rct; HBRUSH WhiteBrush; rct.left = *posX; rct.right = *posX+DD_SQUARE_SIZE; rct.top = *posY; rct.bottom = *posY+DD_SQUARE_SIZE; WhiteBrush = CreateSolidBrush(RGB(255,255,255)); FillRect(hdc, &rct, WhiteBrush); if(*posX >= (DD_TEST_WIDTH - DD_SQUARE_SIZE)) *gainX = -(*gainX); if(*posY >= (DD_TEST_HEIGHT - DD_SQUARE_SIZE)) *gainY = -(*gainY); if(*posX < 0) *gainX = -1*(*gainX); if(*posY < 0) *gainY = -1*(*gainY); *posX += *gainX; *posY += *gainY; lpDDBackBuffer->lpVtbl->ReleaseDC(lpDDBackBuffer, hdc); if(Fullscreen) { lpDDPrimarySurface->lpVtbl->Flip(lpDDPrimarySurface, NULL, DDFLIP_WAIT); } else { lpDDPrimarySurface->lpVtbl->Blt(lpDDPrimarySurface, rectDD, lpDDBackBuffer, NULL, DDBLT_WAIT, NULL); } } }