Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

510 lines
15 KiB

  1. #include <stdlib.h>
  2. #include <stdio.h> // for debugging
  3. #include <windows.h>
  4. #include <commctrl.h>
  5. #include <sys/types.h>
  6. #include <sys/timeb.h>
  7. #include <time.h>
  8. #include <gl\gl.h>
  9. #include "macros.h"
  10. #include "prfl.h"
  11. #include "skeltest.h"
  12. #include "hugetest.h"
  13. #include "primtest.h"
  14. #include "teapot.h"
  15. // Window procedure, handles all messages for this program
  16. LRESULT CALLBACK prfl_WndProc(HWND, UINT msg, WPARAM, LPARAM);
  17. extern HINSTANCE hInstance;
  18. static LPCTSTR lpszClassName = "GL Profiler";
  19. static SkeletonTest *pst = NULL;
  20. static HINSTANCE hInst = NULL;
  21. static HWND hwndTest = NULL;
  22. static long lIdleCount = 0;
  23. static struct _timeb timeStart;
  24. static struct _timeb timeEnd;
  25. void_void *prfl_EndFunct = NULL;
  26. // Select the pixel format for a given device context
  27. void SetDCPixelFormat(HDC hDC)
  28. {
  29. int nPixelFormat;
  30. DWORD mode =
  31. PFD_DRAW_TO_WINDOW | // Draw to Window (not to bitmap)
  32. PFD_SUPPORT_OPENGL | // Support OpenGL calls in window
  33. (pst->td.swapbuffers ? PFD_DOUBLEBUFFER : 0); // Double buffered mode?
  34. static PIXELFORMATDESCRIPTOR pfd = {
  35. sizeof(PIXELFORMATDESCRIPTOR), // Size of this structure
  36. 1, // Version of this structure
  37. -1,
  38. PFD_TYPE_RGBA, // RGBA Color mode
  39. -1,
  40. 0,0,0,0,0,0, // Not used to select mode
  41. 0,0, // Not used to select mode
  42. 0,0,0,0,0, // Not used to select mode
  43. -1,
  44. 0, // Not used to select mode
  45. 0, // Not used to select mode
  46. PFD_MAIN_PLANE, // Draw in main plane
  47. 0, // Not used to select mode
  48. 0,0,0 }; // Not used to select mode
  49. pfd.dwFlags = mode;
  50. pfd.cDepthBits = pst->bd.cDepthBits;
  51. pfd.cColorBits = GetDeviceCaps(hDC,BITSPIXEL)*GetDeviceCaps(hDC,PLANES);
  52. // Choose a pixel format that best matches that described in pfd
  53. nPixelFormat = ChoosePixelFormat(hDC, &pfd);
  54. // Set the pixel format for the device context
  55. SetPixelFormat(hDC, nPixelFormat, &pfd);
  56. }
  57. HWND prfl_InitWindow(LPCTSTR lpszWinName)
  58. {
  59. if (prfl_RegisterClass(NULL) == FALSE) {
  60. fprintf(stderr,"Can't register class for test window.\n");
  61. return NULL;
  62. }
  63. if (hwndTest != NULL)
  64. return NULL;
  65. hwndTest = CreateWindow(lpszClassName, lpszWinName,
  66. // OpenGL requires WS_CLIPCHILDREN and WS_CLIPSIBLINGS
  67. WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
  68. WS_VISIBLE | DS_SYSMODAL,
  69. // Window position and size
  70. pst->td.iX, pst->td.iY, pst->td.iW, pst->td.iH,
  71. NULL, NULL, hInst, NULL);
  72. if (!hwndTest) {
  73. fprintf(stderr,"Couldn't create test window.\n");
  74. return NULL;
  75. }
  76. SetWindowPos(hwndTest, HWND_TOPMOST, 0, 0, 0, 0,
  77. SWP_NOMOVE|SWP_NOSIZE|SWP_NOSENDCHANGING);
  78. return hwndTest;
  79. }
  80. // If necessary, creates a 3-3-2 palette for the device context listed.
  81. HPALETTE GetOpenGLPalette(HDC hDC)
  82. {
  83. HPALETTE hRetPal = NULL; // Handle to palette to be created
  84. PIXELFORMATDESCRIPTOR pfd; // Pixel Format Descriptor
  85. LOGPALETTE *pPal; // Pointer to memory for logical palette
  86. int nPixelFormat; // Pixel format index
  87. int nColors; // Number of entries in palette
  88. int i; // Counting variable
  89. BYTE RedRange,GreenRange,BlueRange;
  90. // Range for each color entry (7,7,and 3)
  91. // Get the pixel format index and retrieve the pixel format description
  92. nPixelFormat = GetPixelFormat(hDC);
  93. DescribePixelFormat(hDC, nPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
  94. // Does this pixel format require a palette? If not, do not create a
  95. // palette and just return NULL
  96. if(!(pfd.dwFlags & PFD_NEED_PALETTE))
  97. return NULL;
  98. // Number of entries in palette. 8 bits yeilds 256 entries
  99. nColors = 1 << pfd.cColorBits;
  100. // Allocate space for a logical palette structure
  101. // plus all the palette entries
  102. pPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE)+nColors*sizeof(PALETTEENTRY));
  103. // Fill in palette header
  104. pPal->palVersion = 0x300; // Windows 3.0
  105. pPal->palNumEntries = nColors; // table size
  106. // Build mask of all 1's. This creates a number represented by having
  107. // the low order x bits set, where x = pfd.cRedBits, pfd.cGreenBits, and
  108. // pfd.cBlueBits.
  109. RedRange = (1 << pfd.cRedBits) - 1;
  110. GreenRange = (1 << pfd.cGreenBits) - 1;
  111. BlueRange = (1 << pfd.cBlueBits) - 1;
  112. // Loop through all the palette entries
  113. for(i = 0; i < nColors; i++) {
  114. // Fill in the 8-bit equivalents for each component
  115. pPal->palPalEntry[i].peRed = (i >> pfd.cRedShift) & RedRange;
  116. pPal->palPalEntry[i].peRed =
  117. (unsigned char)((double) pPal->palPalEntry[i].peRed
  118. * 255.0 / RedRange);
  119. pPal->palPalEntry[i].peGreen = (i >> pfd.cGreenShift) & GreenRange;
  120. pPal->palPalEntry[i].peGreen =
  121. (unsigned char)((double)pPal->palPalEntry[i].peGreen
  122. * 255.0 / GreenRange);
  123. pPal->palPalEntry[i].peBlue = (i >> pfd.cBlueShift) & BlueRange;
  124. pPal->palPalEntry[i].peBlue =
  125. (unsigned char)((double)pPal->palPalEntry[i].peBlue
  126. * 255.0 / BlueRange);
  127. pPal->palPalEntry[i].peFlags = (unsigned char) NULL;
  128. }
  129. // Create the palette
  130. hRetPal = CreatePalette(pPal);
  131. // Go ahead and select and realize the palette for this device context
  132. SelectPalette(hDC, hRetPal, FALSE);
  133. RealizePalette(hDC);
  134. // Free the memory used for the logical palette structure
  135. free(pPal);
  136. // Return the handle to the new palette
  137. return hRetPal;
  138. }
  139. // Window procedure, handles all messages for this program
  140. LRESULT CALLBACK prfl_WndProc(HWND hWnd, UINT msg,WPARAM wParam, LPARAM lParam)
  141. {
  142. static HGLRC hRC; // Permenant Rendering context
  143. static HDC hDC; // Private GDI Device context
  144. static HPALETTE hPalette = NULL;
  145. //!!! Debug
  146. static BOOL bStartOnce = TRUE;
  147. switch (msg)
  148. {
  149. case WM_CREATE:
  150. // Window creation, setup for OpenGL
  151. // Store the device context
  152. hDC = GetDC(hWnd);
  153. // Select the pixel format
  154. SetDCPixelFormat(hDC);
  155. // Create the rendering context and make it current
  156. hRC = wglCreateContext(hDC);
  157. wglMakeCurrent(hDC, hRC);
  158. // Create the palette
  159. hPalette = GetOpenGLPalette(hDC);
  160. // New window, restart timer state
  161. bStartOnce = TRUE;
  162. break;
  163. case WM_SIZE:
  164. if (bStartOnce) {
  165. // do any initialization
  166. if (pst)
  167. pst->initfunct(LOWORD(lParam), HIWORD(lParam));
  168. glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  169. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT
  170. | GL_STENCIL_BUFFER_BIT | GL_ACCUM_BUFFER_BIT);
  171. glFlush();
  172. if (pst && pst->td.swapbuffers) {
  173. SwapBuffers(hDC);
  174. glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  175. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT
  176. | GL_STENCIL_BUFFER_BIT | GL_ACCUM_BUFFER_BIT);
  177. glFlush();
  178. }
  179. ValidateRect(hWnd,NULL);
  180. lIdleCount = 0;
  181. // Create a timer that fires every millisecond
  182. SetTimer(hWnd,101,1,NULL);
  183. // Only run for X seconds
  184. SetTimer(hWnd,102,pst->td.iDuration,NULL);
  185. _ftime(&timeStart);
  186. // Only once!
  187. bStartOnce = FALSE;
  188. }
  189. break;
  190. case WM_DESTROY:
  191. _ftime(&timeEnd);
  192. // Kill the timers that we created
  193. KillTimer(hWnd,101);
  194. KillTimer(hWnd,102);
  195. // do any test-specific cleaning up
  196. if (pst)
  197. pst->destfunct();
  198. // Deselect the current rendering context and delete it
  199. wglMakeCurrent(hDC,NULL);
  200. wglDeleteContext(hRC);
  201. // Delete the palette
  202. if(hPalette != NULL)
  203. DeleteObject(hPalette);
  204. hwndTest = NULL;
  205. break;
  206. case WM_TIMER:
  207. // Call the idle function, if it exists, then force a repaint
  208. if (wParam == 101) {
  209. if (pst)
  210. pst->idlefunct();
  211. lIdleCount++;
  212. InvalidateRect(hWnd,NULL,FALSE);
  213. } else if (wParam == 102) {
  214. DestroyWindow(hWnd);
  215. // alert the caller of the test that it's over.
  216. if (prfl_EndFunct)
  217. prfl_EndFunct();
  218. }
  219. break;
  220. case WM_PAINT:
  221. // Call OpenGL drawing code
  222. if (pst)
  223. pst->rendfunct();
  224. // Call function to swap the buffers
  225. if (pst && pst->td.swapbuffers)
  226. SwapBuffers(hDC);
  227. // Validate the newly painted client area
  228. ValidateRect(hWnd,NULL);
  229. break;
  230. case WM_QUERYNEWPALETTE:
  231. // Windows is telling the application that it may modify
  232. // the system palette. This message in essance asks the
  233. // application for a new palette.
  234. //
  235. // If the palette was created.
  236. if(hPalette) {
  237. int nRet;
  238. // Selects the palette into the current device context
  239. SelectPalette(hDC, hPalette, FALSE);
  240. // Map entries from the currently selected palette to
  241. // the system palette. The return value is the number
  242. // of palette entries modified.
  243. nRet = RealizePalette(hDC);
  244. // Repaint, forces remap of palette in current window
  245. InvalidateRect(hWnd,NULL,FALSE);
  246. return TRUE; // nRet
  247. }
  248. break;
  249. case WM_PALETTECHANGED:
  250. // This window may set the palette, even though it is not the
  251. // currently active window.
  252. //
  253. // Don't do anything if the palette does not exist, or if
  254. // this is the window that changed the palette.
  255. if((hPalette != NULL) && ((HWND)wParam != hWnd)) {
  256. // Select the palette into the device context
  257. SelectPalette(hDC,hPalette,FALSE);
  258. // Map entries to system palette
  259. RealizePalette(hDC);
  260. // Remap the current colors to the newly realized palette
  261. UpdateColors(hDC);
  262. return TRUE; // 0
  263. }
  264. break;
  265. default: // Passes it on if unproccessed
  266. return (DefWindowProc(hWnd, msg, wParam, lParam));
  267. // return FALSE;
  268. }
  269. // return TRUE;
  270. return (0L);
  271. }
  272. // Above are internal functions
  273. // Below are public functions
  274. void *prfl_AutoLoad(const char *szFileName, int *piError)
  275. {
  276. static char szErrorMsg[120];
  277. static SkeletonTest st;
  278. SkeletonTest *pst = NULL;
  279. HANDLE hFile;
  280. int i;
  281. char *szType;
  282. DWORD dwPointer;
  283. if (!piError || !szFileName)
  284. return NULL;
  285. *piError = PRFL_NO_ERROR;
  286. hFile = CreateFile(szFileName, GENERIC_READ, 0, NULL,
  287. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  288. if (hFile == INVALID_HANDLE_VALUE) {
  289. sprintf(szErrorMsg, "Error opening file: %d\n", GetLastError());
  290. *piError = PRFL_ERROR_OPENFILE;
  291. return szErrorMsg;
  292. }
  293. i = st.Load(hFile);
  294. if (i < 0) {
  295. CloseHandle(hFile);
  296. sprintf(szErrorMsg, "Error number %d while reading file", i);
  297. *piError = PRFL_ERROR_LOADFILE;
  298. return szErrorMsg;
  299. }
  300. dwPointer = SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
  301. if (dwPointer == 0xFFFFFFFF) {
  302. sprintf(szErrorMsg, "Error rewinding file: %d\n", GetLastError());
  303. *piError = PRFL_ERROR_FILESEEK;
  304. CloseHandle(hFile); // hope for no errors
  305. return szErrorMsg;
  306. }
  307. szType = (char*) st.QueryType();
  308. pst = NULL;
  309. switch(szType[0])
  310. {
  311. case 's':
  312. case 'S':
  313. if (!strcasecmp(szType, "skeleton"))
  314. pst = new(SkeletonTest);
  315. break;
  316. case 'h':
  317. case 'H':
  318. if (!strcasecmp(szType, "huge"))
  319. pst = new(HugeTest);
  320. break;
  321. case 'p':
  322. case 'P':
  323. if (!strcasecmp(szType, "primative"))
  324. pst = new(PrimativeTest);
  325. break;
  326. case 't':
  327. case 'T':
  328. if (!strcasecmp(szType, "teapot"))
  329. pst = new(TeapotTest);
  330. break;
  331. default:
  332. sprintf(szErrorMsg, "Unknown test type: %s", szType);
  333. *piError = PRFL_ERROR_UNKNOWN_TYPE;
  334. return szErrorMsg;
  335. }
  336. i = pst->Load(hFile);
  337. if (i < 0) {
  338. CloseHandle(hFile);
  339. sprintf(szErrorMsg, "Error number %d while reading file", i);
  340. *piError = PRFL_ERROR_LOADFILE;
  341. return szErrorMsg;
  342. }
  343. if (!CloseHandle(hFile)) {
  344. sprintf(szErrorMsg, "Error closing file: %d\n", GetLastError());
  345. *piError = PRFL_ERROR_CLOSEFILE;
  346. return szErrorMsg;
  347. }
  348. return pst;
  349. }
  350. BOOL prfl_RegisterClass(HINSTANCE hInstance)
  351. {
  352. static BOOL fRet = FALSE;
  353. WNDCLASS wc; // Windows class structure
  354. if ((fRet == TRUE) || (!hInstance))
  355. return fRet;
  356. fRet = TRUE;
  357. hInst = hInstance;
  358. // Register Window style
  359. wc.style = CS_HREDRAW | CS_VREDRAW;
  360. wc.lpfnWndProc = (WNDPROC) prfl_WndProc;
  361. wc.cbClsExtra = 0;
  362. wc.cbWndExtra = 0;
  363. wc.hInstance = hInstance;
  364. wc.hIcon = NULL;
  365. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  366. // No need for background brush for OpenGL window
  367. wc.hbrBackground = NULL;
  368. wc.lpszMenuName = NULL;
  369. wc.lpszClassName = lpszClassName;
  370. // Register the window class
  371. if(RegisterClass(&wc) == 0)
  372. fRet = FALSE;
  373. return fRet;
  374. }
  375. BOOL prfl_StartTest(SkeletonTest *ptest, LPCTSTR lpzWinName, void_void EndFn)
  376. {
  377. prfl_EndFunct = EndFn;
  378. if (hwndTest) {
  379. fprintf(stderr,"Error: Test is already running.\n");
  380. return FALSE;
  381. }
  382. if (ptest)
  383. pst = ptest;
  384. else
  385. return FALSE;
  386. if (NULL == prfl_InitWindow(lpzWinName)) {
  387. return FALSE;
  388. }
  389. return TRUE;
  390. }
  391. BOOL prfl_StopTest(void)
  392. {
  393. if (hwndTest == NULL)
  394. return TRUE;
  395. DestroyWindow(hwndTest);
  396. hwndTest = NULL;
  397. return TRUE;
  398. }
  399. BOOL prfl_TestRunning()
  400. {
  401. return (BOOL) hwndTest;
  402. }
  403. double prfl_GetDuration()
  404. {
  405. long lSecDiff;
  406. long lMilDiff;
  407. double dRet;
  408. lSecDiff = (timeEnd.time - timeStart.time);
  409. lMilDiff = (timeEnd.millitm - timeStart.millitm);
  410. dRet = 1000*(lSecDiff + ((double) lMilDiff/1000));
  411. return dRet;
  412. }
  413. double prfl_GetCount()
  414. {
  415. return (double) lIdleCount;
  416. }
  417. double prfl_GetResult()
  418. {
  419. if (!pst)
  420. return -1.0;
  421. return (pst->td.dResult * lIdleCount);
  422. }