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.

910 lines
21 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. #include <stdio.h>
  4. #include "glwinint.h"
  5. // Window class
  6. static char *pszClass = "glWindow";
  7. // Structure to pass window creation data
  8. #pragma pack(1)
  9. typedef struct _GLWINCREATESTRUCT
  10. {
  11. WORD wSize;
  12. GLWINDOW gw;
  13. } GLWINCREATESTRUCT;
  14. #pragma pack()
  15. /******************************Public*Routine******************************\
  16. *
  17. * glwinWndProc
  18. *
  19. * Window procedure for glwin windows
  20. *
  21. * History:
  22. * Fri Aug 30 13:00:23 1996 -by- Drew Bliss [drewb]
  23. * Created
  24. *
  25. \**************************************************************************/
  26. LRESULT glwinWndProc(HWND hwnd, UINT uiMsg, WPARAM wpm, LPARAM lpm)
  27. {
  28. PAINTSTRUCT ps;
  29. LRESULT lr;
  30. GLWINDOW gw;
  31. GLWINCREATESTRUCT *pgcs;
  32. // Set up the window-related data immediately on WM_CREATE so that
  33. // a callback can be made for it as well as after it
  34. if (uiMsg == WM_CREATE)
  35. {
  36. pgcs = (GLWINCREATESTRUCT *)((CREATESTRUCT *)lpm)->lpCreateParams;
  37. SetWindowLong(hwnd, GWL_USERDATA, (LONG)pgcs->gw);
  38. }
  39. gw = (GLWINDOW)GetWindowLong(hwnd, GWL_USERDATA);
  40. // Pass off window messages if requested
  41. if (gw != NULL && gw->cbMessage != NULL)
  42. {
  43. if (gw->cbMessage(gw, hwnd, uiMsg, wpm, lpm, &lr))
  44. {
  45. return lr;
  46. }
  47. }
  48. switch(uiMsg)
  49. {
  50. case WM_PAINT:
  51. // Validate paint region. The assumption is that the app will either
  52. // interpose and catch the WM_PAINT itself or it's dynamic so
  53. // the screen will be repainted shortly anyway. Either way,
  54. // there's nothing for the library to do.
  55. BeginPaint(hwnd, &ps);
  56. EndPaint(hwnd, &ps);
  57. break;
  58. case WM_CLOSE:
  59. gw->bClosing = TRUE;
  60. DestroyWindow(hwnd);
  61. break;
  62. case WM_DESTROY:
  63. if (gw->bClosing)
  64. {
  65. PostQuitMessage(1);
  66. }
  67. break;
  68. default:
  69. return DefWindowProc(hwnd, uiMsg, wpm, lpm);
  70. }
  71. return 0;
  72. }
  73. // Default palette entry flags
  74. #define PALETTE_FLAGS PC_NOCOLLAPSE
  75. // Maximum color distance with 8-bit components
  76. #define MAX_COL_DIST (3*256*256L)
  77. // Number of static colors
  78. #define STATIC_COLORS 20
  79. // Flags used when matching colors
  80. #define EXACT_MATCH 1
  81. #define COLOR_USED 1
  82. // Tables to convert color components between bit sizes
  83. // These tables are corrected for a gamma of 1.4
  84. static unsigned char abThreeToEight[8] =
  85. {
  86. 0, 63, 104, 139, 171, 200, 229, 255
  87. };
  88. static unsigned char abTwoToEight[4] =
  89. {
  90. 0, 116, 191, 255
  91. };
  92. static unsigned char abOneToEight[2] =
  93. {
  94. 0, 255
  95. };
  96. // Table which indicates which colors in a 3-3-2 palette should be
  97. // replaced with the system default colors
  98. static int aiDefaultOverride[STATIC_COLORS] =
  99. {
  100. 0, 3, 24, 27, 64, 67, 88, 173, 181, 236,
  101. 247, 164, 91, 7, 56, 63, 192, 199, 248, 255
  102. };
  103. /******************************Public*Routine******************************\
  104. *
  105. * glwinComponentFromIndex
  106. *
  107. * Converts a color index to a color component
  108. *
  109. * History:
  110. * Fri Aug 30 14:04:45 1996 -by- Drew Bliss [drewb]
  111. * Created
  112. *
  113. \**************************************************************************/
  114. unsigned char glwinComponentFromIndex(int i, int nbits, int shift)
  115. {
  116. unsigned char val;
  117. val = i >> shift;
  118. switch (nbits)
  119. {
  120. case 1:
  121. return abOneToEight[val & 1];
  122. case 2:
  123. return abTwoToEight[val & 3];
  124. case 3:
  125. return abThreeToEight[val & 7];
  126. }
  127. return 0;
  128. }
  129. // System default colors
  130. static PALETTEENTRY apeDefaultPalEntry[STATIC_COLORS] =
  131. {
  132. { 0, 0, 0, 0 },
  133. { 0x80,0, 0, 0 },
  134. { 0, 0x80,0, 0 },
  135. { 0x80,0x80,0, 0 },
  136. { 0, 0, 0x80, 0 },
  137. { 0x80,0, 0x80, 0 },
  138. { 0, 0x80,0x80, 0 },
  139. { 0xC0,0xC0,0xC0, 0 },
  140. { 192, 220, 192, 0 },
  141. { 166, 202, 240, 0 },
  142. { 255, 251, 240, 0 },
  143. { 160, 160, 164, 0 },
  144. { 0x80,0x80,0x80, 0 },
  145. { 0xFF,0, 0, 0 },
  146. { 0, 0xFF,0, 0 },
  147. { 0xFF,0xFF,0, 0 },
  148. { 0, 0, 0xFF, 0 },
  149. { 0xFF,0, 0xFF, 0 },
  150. { 0, 0xFF,0xFF, 0 },
  151. { 0xFF,0xFF,0xFF, 0 }
  152. };
  153. /******************************Public*Routine******************************\
  154. *
  155. * glwinUpdateStaticMapping
  156. *
  157. * Computes the best match between the current system static colors
  158. * and a 3-3-2 palette
  159. *
  160. * History:
  161. * Tue Aug 01 18:18:12 1995 -by- Drew Bliss [drewb]
  162. * Created
  163. *
  164. \**************************************************************************/
  165. void glwinUpdateStaticMapping(PALETTEENTRY *pe332Palette)
  166. {
  167. HPALETTE hpalStock;
  168. int iStatic, i332;
  169. int iMinDist, iDist;
  170. int iDelta;
  171. int iMinEntry;
  172. PALETTEENTRY *peStatic, *pe332;
  173. hpalStock = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  174. // Get the current static colors
  175. GetPaletteEntries(hpalStock, 0, STATIC_COLORS, apeDefaultPalEntry);
  176. // Zero the flags in the static colors because they are used later
  177. peStatic = apeDefaultPalEntry;
  178. for (iStatic = 0; iStatic < STATIC_COLORS; iStatic++)
  179. {
  180. peStatic->peFlags = 0;
  181. peStatic++;
  182. }
  183. // Zero the flags in the incoming palette because they are used later
  184. pe332 = pe332Palette;
  185. for (i332 = 0; i332 < 256; i332++)
  186. {
  187. pe332->peFlags = 0;
  188. pe332++;
  189. }
  190. // Try to match each static color exactly
  191. // This saves time by avoiding the least-squares match for each
  192. // exact match
  193. peStatic = apeDefaultPalEntry;
  194. for (iStatic = 0; iStatic < STATIC_COLORS; iStatic++)
  195. {
  196. pe332 = pe332Palette;
  197. for (i332 = 0; i332 < 256; i332++)
  198. {
  199. if (peStatic->peRed == pe332->peRed &&
  200. peStatic->peGreen == pe332->peGreen &&
  201. peStatic->peBlue == pe332->peBlue)
  202. {
  203. peStatic->peFlags = EXACT_MATCH;
  204. pe332->peFlags = COLOR_USED;
  205. aiDefaultOverride[iStatic] = i332;
  206. break;
  207. }
  208. pe332++;
  209. }
  210. peStatic++;
  211. }
  212. // Match each static color as closely as possible to an entry
  213. // in the 332 palette by minimized the square of the distance
  214. peStatic = apeDefaultPalEntry;
  215. for (iStatic = 0; iStatic < STATIC_COLORS; iStatic++)
  216. {
  217. // Skip colors already matched exactly
  218. if (peStatic->peFlags == EXACT_MATCH)
  219. {
  220. peStatic++;
  221. continue;
  222. }
  223. iMinDist = MAX_COL_DIST+1;
  224. #if DBG
  225. iMinEntry = -1;
  226. #endif
  227. pe332 = pe332Palette;
  228. for (i332 = 0; i332 < 256; i332++)
  229. {
  230. // Skip colors already used
  231. if (pe332->peFlags == COLOR_USED)
  232. {
  233. pe332++;
  234. continue;
  235. }
  236. // Compute Euclidean distance squared
  237. iDelta = pe332->peRed-peStatic->peRed;
  238. iDist = iDelta*iDelta;
  239. iDelta = pe332->peGreen-peStatic->peGreen;
  240. iDist += iDelta*iDelta;
  241. iDelta = pe332->peBlue-peStatic->peBlue;
  242. iDist += iDelta*iDelta;
  243. if (iDist < iMinDist)
  244. {
  245. iMinDist = iDist;
  246. iMinEntry = i332;
  247. }
  248. pe332++;
  249. }
  250. // Remember the best match
  251. aiDefaultOverride[iStatic] = iMinEntry;
  252. pe332Palette[iMinEntry].peFlags = COLOR_USED;
  253. peStatic++;
  254. }
  255. // Zero the flags in the static colors because they may have been
  256. // set. We want them to be zero so the colors can be remapped
  257. peStatic = apeDefaultPalEntry;
  258. for (iStatic = 0; iStatic < STATIC_COLORS; iStatic++)
  259. {
  260. peStatic->peFlags = 0;
  261. peStatic++;
  262. }
  263. // Reset the 332 flags because we may have set them
  264. pe332 = pe332Palette;
  265. for (i332 = 0; i332 < 256; i332++)
  266. {
  267. pe332->peFlags = PALETTE_FLAGS;
  268. pe332++;
  269. }
  270. }
  271. PALETTEENTRY *glwinFillRgbPaletteEntries(PIXELFORMATDESCRIPTOR *ppfd,
  272. PALETTEENTRY *ppeEntries,
  273. UINT cColors)
  274. {
  275. PALETTEENTRY *ppeEntry;
  276. UINT i;
  277. for (i = 0, ppeEntry = ppeEntries ; i < cColors ; i++, ppeEntry++)
  278. {
  279. ppeEntry->peRed = glwinComponentFromIndex(i, ppfd->cRedBits,
  280. ppfd->cRedShift);
  281. ppeEntry->peGreen = glwinComponentFromIndex(i, ppfd->cGreenBits,
  282. ppfd->cGreenShift);
  283. ppeEntry->peBlue = glwinComponentFromIndex(i, ppfd->cBlueBits,
  284. ppfd->cBlueShift);
  285. ppeEntry->peFlags = PALETTE_FLAGS;
  286. }
  287. if (cColors == 256)
  288. {
  289. // If app set static system color usage for fixed palette support,
  290. // setup to take over the static colors. Otherwise, fixup the
  291. // static system colors.
  292. // The defaultOverride array is computed assuming a 332
  293. // palette where red has zero shift, etc.
  294. if ( (3 == ppfd->cRedBits) && (0 == ppfd->cRedShift) &&
  295. (3 == ppfd->cGreenBits) && (3 == ppfd->cGreenShift) &&
  296. (2 == ppfd->cBlueBits) && (6 == ppfd->cBlueShift) )
  297. {
  298. glwinUpdateStaticMapping(ppeEntries);
  299. for ( i = 0 ; i < STATIC_COLORS ; i++)
  300. {
  301. ppeEntries[aiDefaultOverride[i]] = apeDefaultPalEntry[i];
  302. }
  303. }
  304. }
  305. return ppeEntries;
  306. }
  307. void glwinFlushPalette(HDC hdc, int cColors)
  308. {
  309. LOGPALETTE *plpal;
  310. HPALETTE hpal, hpalOld;
  311. int i;
  312. if (cColors == 256)
  313. {
  314. plpal = (LOGPALETTE *)calloc(1, sizeof(LOGPALETTE)+
  315. cColors*sizeof(PALETTEENTRY));
  316. if (plpal != NULL)
  317. {
  318. plpal->palVersion = 0x300;
  319. plpal->palNumEntries = cColors;
  320. // Mark everything PC_NOCOLLAPSE and PC_RESERVED to force
  321. // every thing into the palette. Colors are already black
  322. // because we zero initialized during memory allocation.
  323. for (i = 0; i < cColors; i++)
  324. {
  325. plpal->palPalEntry[i].peFlags = PC_NOCOLLAPSE | PC_RESERVED;
  326. }
  327. hpal = CreatePalette(plpal);
  328. free(plpal);
  329. hpalOld = SelectPalette(hdc, hpal, FALSE);
  330. RealizePalette(hdc);
  331. SelectPalette(hdc, hpalOld, FALSE);
  332. DeleteObject(hpal);
  333. }
  334. }
  335. }
  336. LONG glwinRealizePaletteNow(HDC hdc, HPALETTE hpal, BOOL bForceBackground)
  337. {
  338. LONG lRet = -1;
  339. BOOL bHaveSysPal = TRUE;
  340. if (SelectPalette(hdc, hpal, FALSE) != NULL)
  341. {
  342. lRet = RealizePalette(hdc);
  343. }
  344. return lRet;
  345. }
  346. BOOL glwinCreateRgbPalette(HDC hdc, PIXELFORMATDESCRIPTOR *ppfd,
  347. HPALETTE *phpal)
  348. {
  349. LOGPALETTE *plpal;
  350. UINT cColors;
  351. HPALETTE hpal = NULL;
  352. BOOL bRet = TRUE;
  353. if (ppfd->iPixelType == PFD_TYPE_RGBA &&
  354. (ppfd->dwFlags & PFD_NEED_PALETTE))
  355. {
  356. cColors = 1 << ppfd->cColorBits;
  357. plpal = (LOGPALETTE *)malloc(sizeof(LOGPALETTE)+
  358. cColors*sizeof(PALETTEENTRY));
  359. if (plpal != NULL)
  360. {
  361. plpal->palVersion = 0x300;
  362. plpal->palNumEntries = cColors;
  363. glwinFillRgbPaletteEntries(ppfd, &plpal->palPalEntry[0], cColors);
  364. hpal = CreatePalette(plpal);
  365. free(plpal);
  366. glwinFlushPalette(hdc, cColors);
  367. glwinRealizePaletteNow(hdc, hpal, FALSE);
  368. }
  369. else
  370. {
  371. bRet = FALSE;
  372. }
  373. }
  374. *phpal = hpal;
  375. return bRet;
  376. }
  377. /******************************Public*Routine******************************\
  378. *
  379. * glwinRegisterClass
  380. *
  381. * Register a window class if necessary
  382. *
  383. * History:
  384. * Fri Aug 30 14:37:49 1996 -by- Drew Bliss [drewb]
  385. * Created
  386. *
  387. \**************************************************************************/
  388. BOOL glwinRegisterClass(void)
  389. {
  390. static ATOM aClass = 0;
  391. WNDCLASS wc;
  392. if (aClass == 0)
  393. {
  394. wc.style = CS_HREDRAW | CS_VREDRAW;
  395. wc.lpfnWndProc = glwinWndProc;
  396. wc.cbClsExtra = 0;
  397. wc.cbWndExtra = 0;
  398. wc.hInstance = (HINSTANCE)GetModuleHandle(NULL);
  399. wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  400. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  401. wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  402. wc.lpszMenuName = NULL;
  403. wc.lpszClassName = pszClass;
  404. aClass = RegisterClass(&wc);
  405. if (aClass == 0)
  406. {
  407. return FALSE;
  408. }
  409. }
  410. return TRUE;
  411. }
  412. /******************************Public*Routine******************************\
  413. *
  414. * glwinCreateWindow
  415. *
  416. * Create a new rendering window
  417. *
  418. * History:
  419. * Fri Aug 30 14:38:49 1996 -by- Drew Bliss [drewb]
  420. * Created
  421. *
  422. \**************************************************************************/
  423. GLWINDOW glwinCreateWindow(HWND hwndParent,
  424. char *pszTitle, int x, int y,
  425. int iWidth, int iHeight,
  426. DWORD dwFlags)
  427. {
  428. GLWINDOW gw;
  429. RECT rct;
  430. PIXELFORMATDESCRIPTOR pfd;
  431. GLWINCREATESTRUCT gcs;
  432. int ipfd;
  433. DWORD dwStyle;
  434. if (!glwinRegisterClass())
  435. {
  436. return NULL;
  437. }
  438. gw = (GLWINDOW)malloc(sizeof(_GLWINDOW));
  439. if (gw == NULL)
  440. {
  441. return NULL;
  442. }
  443. memset(gw, 0, sizeof(*gw));
  444. if (hwndParent != NULL)
  445. {
  446. dwStyle = WS_CHILDWINDOW;
  447. }
  448. else
  449. {
  450. dwStyle = WS_OVERLAPPEDWINDOW;
  451. }
  452. dwStyle |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
  453. // Create base window
  454. rct.left = x;
  455. rct.top = y;
  456. rct.right = x+iWidth;
  457. rct.bottom = y+iHeight;
  458. AdjustWindowRect(&rct, dwStyle, FALSE);
  459. gcs.wSize = sizeof(gcs);
  460. gcs.gw = gw;
  461. gw->hwnd = CreateWindow(pszClass, pszTitle, dwStyle,
  462. rct.left, rct.top,
  463. rct.right-rct.left, rct.bottom-rct.top,
  464. hwndParent, NULL, GetModuleHandle(NULL), &gcs);
  465. if (gw->hwnd == NULL)
  466. {
  467. return NULL;
  468. }
  469. ShowWindow(gw->hwnd, SW_SHOWDEFAULT);
  470. UpdateWindow(gw->hwnd);
  471. gw->hdc = GetDC(gw->hwnd);
  472. if (gw->hdc == NULL)
  473. {
  474. goto DestroyWin;
  475. }
  476. // Create an OpenGL rendering context
  477. memset(&pfd, 0, sizeof(pfd));
  478. pfd.nSize = sizeof(pfd);
  479. pfd.nVersion = 1;
  480. pfd.dwFlags = PFD_GENERIC_FORMAT;
  481. if (dwFlags & GLWIN_GENERIC_ACCELERATED)
  482. {
  483. pfd.dwFlags |= PFD_GENERIC_ACCELERATED;
  484. }
  485. if (dwFlags & GLWIN_BACK_BUFFER)
  486. {
  487. pfd.dwFlags |= PFD_DOUBLEBUFFER;
  488. }
  489. pfd.iPixelType = PFD_TYPE_RGBA;
  490. if (dwFlags & GLWIN_ACCUM_BUFFER)
  491. {
  492. pfd.cAccumBits = 64;
  493. }
  494. if (dwFlags & GLWIN_STENCIL_BUFFER)
  495. {
  496. pfd.cStencilBits = 8;
  497. }
  498. if (dwFlags & GLWIN_Z_BUFFER_16)
  499. {
  500. pfd.cDepthBits = 16;
  501. }
  502. else if (dwFlags & GLWIN_Z_BUFFER_32)
  503. {
  504. pfd.cDepthBits = 32;
  505. }
  506. ipfd = ChoosePixelFormat(gw->hdc, &pfd);
  507. if (ipfd <= 0)
  508. {
  509. goto DestroyWin;
  510. }
  511. if (DescribePixelFormat(gw->hdc, ipfd, sizeof(pfd), &pfd) <= 0)
  512. {
  513. goto DestroyWin;
  514. }
  515. if (!SetPixelFormat(gw->hdc, ipfd, &pfd))
  516. {
  517. goto DestroyWin;
  518. }
  519. if (!glwinCreateRgbPalette(gw->hdc, &pfd, &gw->hpal))
  520. {
  521. goto DestroyWin;
  522. }
  523. gw->hrc = wglCreateContext(gw->hdc);
  524. if (gw->hrc == NULL)
  525. {
  526. goto DestroyWin;
  527. }
  528. gw->iWidth = iWidth;
  529. gw->iHeight = iHeight;
  530. gw->dwFlags = dwFlags;
  531. return gw;
  532. DestroyWin:
  533. glwinDestroyWindow(gw);
  534. return NULL;
  535. }
  536. /******************************Public*Routine******************************\
  537. *
  538. * glwinDestroyWindow
  539. *
  540. * Clean up a rendering window
  541. *
  542. * History:
  543. * Fri Aug 30 14:39:20 1996 -by- Drew Bliss [drewb]
  544. * Created
  545. *
  546. \**************************************************************************/
  547. void glwinDestroyWindow(GLWINDOW gw)
  548. {
  549. if (gw->hrc != NULL)
  550. {
  551. if (wglGetCurrentContext() == gw->hrc)
  552. {
  553. wglMakeCurrent(NULL, NULL);
  554. }
  555. wglDeleteContext(gw->hrc);
  556. }
  557. if (gw->hdc != NULL)
  558. {
  559. ReleaseDC(gw->hwnd, gw->hdc);
  560. }
  561. if (gw->hpal != NULL)
  562. {
  563. DeleteObject(gw->hpal);
  564. }
  565. if (gw->hwnd != NULL)
  566. {
  567. DestroyWindow(gw->hwnd);
  568. }
  569. }
  570. /******************************Public*Routine******************************\
  571. *
  572. * glwinGetGlrc
  573. *
  574. * Return a rendering window's OpenGL rendering context
  575. *
  576. * History:
  577. * Fri Aug 30 14:39:29 1996 -by- Drew Bliss [drewb]
  578. * Created
  579. *
  580. \**************************************************************************/
  581. HGLRC glwinGetGlrc(GLWINDOW gw)
  582. {
  583. return gw->hrc;
  584. }
  585. /******************************Public*Routine******************************\
  586. *
  587. * glwinGetHwnd
  588. *
  589. * Returns a rendering window's window system window
  590. *
  591. * History:
  592. * Mon Oct 21 18:10:23 1996 -by- Drew Bliss [drewb]
  593. * Created
  594. *
  595. \**************************************************************************/
  596. HWND glwinGetHwnd(GLWINDOW gw)
  597. {
  598. return gw->hwnd;
  599. }
  600. /******************************Public*Routine******************************\
  601. *
  602. * glwinGetHdc
  603. *
  604. * Returns a renderin window's HDC
  605. *
  606. * History:
  607. * Tue Oct 22 11:01:35 1996 -by- Drew Bliss [drewb]
  608. * Created
  609. *
  610. \**************************************************************************/
  611. HDC glwinGetHdc(GLWINDOW gw)
  612. {
  613. return gw->hdc;
  614. }
  615. /******************************Public*Routine******************************\
  616. *
  617. * glwinGetFlags
  618. *
  619. * Returns creation flags
  620. *
  621. * History:
  622. * Mon Oct 21 18:28:24 1996 -by- Drew Bliss [drewb]
  623. * Created
  624. *
  625. \**************************************************************************/
  626. DWORD glwinGetFlags(GLWINDOW gw)
  627. {
  628. return gw->dwFlags;
  629. }
  630. /******************************Public*Routine******************************\
  631. *
  632. * glwinGetLastError
  633. *
  634. * Returns the last error recorded by the library
  635. *
  636. * History:
  637. * Fri Aug 30 14:39:39 1996 -by- Drew Bliss [drewb]
  638. * Created
  639. *
  640. \**************************************************************************/
  641. LONG glwinGetLastError(void)
  642. {
  643. #if DBG
  644. char pszMsg[80];
  645. if (GetLastError() != ERROR_SUCCESS)
  646. {
  647. sprintf(pszMsg, "glwinGetLastError returning %d (0x%08lX)\n",
  648. GetLastError(), GetLastError());
  649. OutputDebugString(pszMsg);
  650. }
  651. #endif
  652. return GetLastError();
  653. }
  654. /******************************Public*Routine******************************\
  655. *
  656. * glwinMakeCurrent
  657. *
  658. * Makes the given rendering window's OpenGL rendering context current
  659. *
  660. * History:
  661. * Fri Aug 30 14:39:47 1996 -by- Drew Bliss [drewb]
  662. * Created
  663. *
  664. \**************************************************************************/
  665. BOOL glwinMakeCurrent(GLWINDOW gw)
  666. {
  667. return wglMakeCurrent(gw->hdc, gw->hrc);
  668. }
  669. /******************************Public*Routine******************************\
  670. *
  671. * glwinSwapBuffers
  672. *
  673. * Performs double-buffer swapping through blt or flip
  674. *
  675. * History:
  676. * Fri Aug 30 14:40:49 1996 -by- Drew Bliss [drewb]
  677. * Created
  678. *
  679. \**************************************************************************/
  680. BOOL glwinSwapBuffers(GLWINDOW gw)
  681. {
  682. return SwapBuffers(gw->hdc);
  683. }
  684. /******************************Public*Routine******************************\
  685. *
  686. * glwinIdleCallback
  687. *
  688. * Set the idle-time callback
  689. *
  690. * History:
  691. * Fri Aug 30 14:41:28 1996 -by- Drew Bliss [drewb]
  692. * Created
  693. *
  694. \**************************************************************************/
  695. void glwinIdleCallback(GLWINDOW gw, GLWINIDLECALLBACK cb)
  696. {
  697. gw->cbIdle = cb;
  698. }
  699. /******************************Public*Routine******************************\
  700. *
  701. * glwinMessageCallback
  702. *
  703. * Set the message interposition callback
  704. *
  705. * History:
  706. * Fri Aug 30 14:41:40 1996 -by- Drew Bliss [drewb]
  707. * Created
  708. *
  709. \**************************************************************************/
  710. void glwinMessageCallback(GLWINDOW gw, GLWINMESSAGECALLBACK cb)
  711. {
  712. gw->cbMessage = cb;
  713. }
  714. /******************************Public*Routine******************************\
  715. *
  716. * glwinRunWindow
  717. *
  718. * Run the message loop for a single window
  719. *
  720. * History:
  721. * Fri Aug 30 14:41:58 1996 -by- Drew Bliss [drewb]
  722. * Created
  723. *
  724. \**************************************************************************/
  725. void glwinRunWindow(GLWINDOW gw)
  726. {
  727. MSG msg;
  728. BOOL bQuit;
  729. bQuit = FALSE;
  730. while (!bQuit)
  731. {
  732. while (!bQuit && PeekMessage(&msg, gw->hwnd, 0, 0, PM_NOREMOVE))
  733. {
  734. if (GetMessage(&msg, gw->hwnd, 0, 0))
  735. {
  736. TranslateMessage(&msg);
  737. DispatchMessage(&msg);
  738. }
  739. else
  740. {
  741. bQuit = TRUE;
  742. }
  743. }
  744. // Call the idle callback if one exists
  745. if (gw->cbIdle != NULL)
  746. {
  747. gw->cbIdle(gw);
  748. }
  749. }
  750. }
  751. /******************************Public*Routine******************************\
  752. *
  753. * glwinRun
  754. *
  755. * Run a message loop for all windows
  756. *
  757. * History:
  758. * Tue Oct 22 11:13:48 1996 -by- Drew Bliss [drewb]
  759. * Created
  760. *
  761. \**************************************************************************/
  762. void glwinRun(GLWINIDLECALLBACK cb)
  763. {
  764. MSG msg;
  765. BOOL bQuit;
  766. bQuit = FALSE;
  767. while (!bQuit)
  768. {
  769. while (!bQuit && PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
  770. {
  771. if (GetMessage(&msg, NULL, 0, 0))
  772. {
  773. TranslateMessage(&msg);
  774. DispatchMessage(&msg);
  775. }
  776. else
  777. {
  778. bQuit = TRUE;
  779. }
  780. }
  781. // Call the idle callback if one exists
  782. if (cb != NULL)
  783. {
  784. cb(NULL);
  785. }
  786. }
  787. }