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.

3303 lines
94 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: pixelfmt.c
  3. *
  4. * This contains the pixel format functions.
  5. *
  6. * Created: 15-Dec-1994 00:28:39
  7. * Author: Gilman Wong [gilmanw] -- ported from gdi\gre\pixelfmt.cxx
  8. *
  9. * Copyright (c) 1994 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. //#define DBG_WINDOW
  14. //#define DBG_REFCOUNTS
  15. #ifdef _CLIENTSIDE_
  16. // Need for glsbAttention declaration
  17. #include "glsbcltu.h"
  18. #include "glscreen.h"
  19. #endif
  20. #ifdef _MCD_
  21. #include "mcd.h"
  22. #endif
  23. #define SAVE_ERROR_CODE(x) SetLastError((x))
  24. // Number of generic pixel formats. There are 5 pixel depths (4,8,16,24,32).
  25. // This is to convert BMF constants into # bits per pel
  26. #define BMF_COUNT (BMF_32BPP+1)
  27. ULONG gaulConvert[BMF_COUNT] =
  28. {
  29. 0,
  30. 1,
  31. 4,
  32. 8,
  33. 16,
  34. 24,
  35. 32
  36. };
  37. #define MIN_GENERIC_PFD 1
  38. #define MAX_GENERIC_PFD 36
  39. LRESULT CALLBACK
  40. wglWndProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);
  41. #define PALETTE_WATCHER_CLASS __TEXT("Palette Watcher")
  42. static ATOM aPaletteWatcherClass = 0;
  43. DWORD tidPaletteWatcherThread = 0;
  44. ULONG ulPaletteWatcherCount = 0;
  45. HANDLE hPaletteWatcherThread = 0;
  46. HWND hwndPaletteWatcher = 0;
  47. LONG lPaletteWatcherUsers = 0;
  48. /******************************Public*Routine******************************\
  49. * pwndNew
  50. *
  51. * Allocate a new GLGENwindow, initialize it (from input structure), and
  52. * insert it into the global linked list.
  53. *
  54. * Returns:
  55. * Pointer to structure if successful, NULL otherwise.
  56. *
  57. * History:
  58. * 01-Nov-1994 -by- Gilman Wong [gilmanw]
  59. * Wrote it.
  60. \**************************************************************************/
  61. GLGENwindow * APIENTRY pwndNew(GLGENwindow *pwndInit)
  62. {
  63. GLGENwindow *pwndRet = (GLGENwindow *) NULL;
  64. BOOL bDirectScreen = GLDIRECTSCREEN && pwndInit->gwid.hwnd;
  65. LPDIRECTDRAWCLIPPER pddClip = (LPDIRECTDRAWCLIPPER) NULL;
  66. // If using direct access, retrieve or create a clipper object to track
  67. // vis rgn changes.
  68. if (pwndInit->gwid.iType == GLWID_DDRAW)
  69. {
  70. HRESULT hr;
  71. hr = pwndInit->gwid.pdds->lpVtbl->
  72. GetClipper(pwndInit->gwid.pdds, &pddClip);
  73. if (hr != DD_OK && hr != DDERR_NOCLIPPERATTACHED)
  74. {
  75. return NULL;
  76. }
  77. }
  78. if ( !bDirectScreen ||
  79. pwndInit->gwid.iType == GLWID_DDRAW ||
  80. (GLSCREENINFO->pdd->lpVtbl->
  81. CreateClipper(GLSCREENINFO->pdd, 0, &pddClip, NULL) == DD_OK &&
  82. pddClip->lpVtbl->SetHWnd(pddClip, 0, pwndInit->gwid.hwnd) == DD_OK) )
  83. {
  84. pwndInit->pddClip = pddClip;
  85. // Allocate a new GLGENwindow.
  86. pwndRet = (GLGENwindow *)ALLOC(sizeof(GLGENwindow));
  87. if (pwndRet)
  88. {
  89. // Initialize from input structure.
  90. *pwndRet = *pwndInit;
  91. // Initialize per-window semaphore.
  92. __try
  93. {
  94. InitializeCriticalSection(&pwndRet->sem);
  95. }
  96. __except(EXCEPTION_EXECUTE_HANDLER)
  97. {
  98. FREE(pwndRet);
  99. pwndRet = NULL;
  100. }
  101. if (pwndRet)
  102. {
  103. // Set initial usage count to one
  104. pwndRet->lUsers = 1;
  105. // Insert into linked list.
  106. EnterCriticalSection(&gwndHeader.sem);
  107. {
  108. pwndRet->pNext = gwndHeader.pNext;
  109. gwndHeader.pNext = pwndRet;
  110. }
  111. LeaveCriticalSection(&gwndHeader.sem);
  112. }
  113. }
  114. }
  115. else
  116. {
  117. WARNING("pwndNew: Clipper setup failed\n");
  118. if (pddClip != NULL)
  119. {
  120. pddClip->lpVtbl->Release(pddClip);
  121. }
  122. }
  123. #ifdef DBG_WINDOW
  124. if (pwndRet != NULL)
  125. {
  126. DbgPrint("Alloc window %p, type %d, hdc %p, hwnd %p, pdds %p\n",
  127. pwndRet, pwndRet->gwid.iType, pwndRet->gwid.hdc,
  128. pwndRet->gwid.hwnd, pwndRet->gwid.pdds);
  129. }
  130. #endif
  131. return pwndRet;
  132. }
  133. /******************************Public*Routine******************************\
  134. *
  135. * pwndUnsubclass
  136. *
  137. * Removes OpenGL's subclassing set when windows are created
  138. *
  139. * History:
  140. * Mon May 20 14:05:23 1996 -by- Drew Bliss [drewb]
  141. * Created
  142. *
  143. \**************************************************************************/
  144. void pwndUnsubclass(GLGENwindow *pwnd, BOOL bProcessExit)
  145. {
  146. WNDPROC wpCur;
  147. // We only restore the original WNDPROC if the current WNDPROC
  148. // is one of ours. This prevents us from stomping on the WNDPROC
  149. // pointer if somebody else has changed it.
  150. if ((pwnd->ulFlags & GLGENWIN_OTHERPROCESS) == 0)
  151. {
  152. wpCur = (WNDPROC)GetWindowLongPtr(pwnd->gwid.hwnd, GWLP_WNDPROC);
  153. if (wpCur == wglWndProc)
  154. {
  155. SetWindowLongPtr(pwnd->gwid.hwnd, GWLP_WNDPROC,
  156. (LONG_PTR) pwnd->pfnOldWndProc);
  157. }
  158. }
  159. else
  160. {
  161. // Clean up the palette watcher window if this is the last user.
  162. EnterCriticalSection(&gcsPaletteWatcher);
  163. ASSERTOPENGL(lPaletteWatcherUsers > 0,
  164. "lPaletteWatcherUsers too low\n");
  165. if (--lPaletteWatcherUsers == 0)
  166. {
  167. if( PostMessage(hwndPaletteWatcher, WM_CLOSE, 0, 0) == FALSE)
  168. {
  169. DbgPrint( "PostMessage to hwnd: %08x failed with error: %08x\n",
  170. hwndPaletteWatcher, GetLastError() );
  171. // Check if the thread is still alive
  172. if( WaitForSingleObject( hPaletteWatcherThread, 100 ) !=
  173. WAIT_OBJECT_0 )
  174. {
  175. // This means that the thread is still alive and
  176. // somehow the window is invalid.
  177. // Kill this thread or else GL will keep waiting.
  178. TerminateThread( hPaletteWatcherThread, 0 );
  179. }
  180. // Should be safe to do. If the thread is alive, it
  181. // was killed above else, someone else killed it
  182. tidPaletteWatcherThread = 0;
  183. }
  184. CloseHandle( hPaletteWatcherThread );
  185. // We don't want to zero the palette watcher's thread ID
  186. // at process exit because we use it to wait for the
  187. // thread to die.
  188. if (!bProcessExit)
  189. {
  190. tidPaletteWatcherThread = 0;
  191. }
  192. }
  193. LeaveCriticalSection(&gcsPaletteWatcher);
  194. }
  195. }
  196. /******************************Public*Routine******************************\
  197. * pwndFree
  198. *
  199. * Frees the specified GLGENwindow.
  200. *
  201. * Returns:
  202. * NULL if successful, pointer to structure otherwise
  203. *
  204. * History:
  205. * 07-Nov-1994 -by- Gilman Wong [gilmanw]
  206. * Wrote it.
  207. \**************************************************************************/
  208. GLGENwindow * APIENTRY pwndFree(GLGENwindow *pwndVictim, BOOL bProcessExit)
  209. {
  210. BOOL bDirectScreen = GLDIRECTSCREEN && pwndVictim->gwid.hwnd;
  211. #ifdef DBG_WINDOW
  212. DbgPrint("Free window %p\n", pwndVictim);
  213. #endif
  214. // Check for a stray screen lock and release if necessary.
  215. if (pwndVictim->ulFlags & GLGENWIN_DIRECTSCREEN)
  216. EndDirectScreenAccess(pwndVictim);
  217. // Free clipper object.
  218. if (bDirectScreen)
  219. {
  220. pwndVictim->pddClip->lpVtbl->Release(pwndVictim->pddClip);
  221. }
  222. // Cleanup visible region caches if they exist.
  223. if ( pwndVictim->prgndat )
  224. FREE(pwndVictim->prgndat);
  225. if ( pwndVictim->pscandat )
  226. FREE(pwndVictim->pscandat);
  227. // Restore original WNDPROC in window.
  228. if (pwndVictim->gwid.hwnd != NULL)
  229. pwndUnsubclass(pwndVictim, bProcessExit);
  230. // Cleanup GLGENlayers.
  231. if (pwndVictim->plyr)
  232. {
  233. int i;
  234. for (i = 0; i < 15; i++)
  235. {
  236. if (pwndVictim->plyr->overlayInfo[i])
  237. FREE(pwndVictim->plyr->overlayInfo[i]);
  238. if (pwndVictim->plyr->underlayInfo[i])
  239. FREE(pwndVictim->plyr->underlayInfo[i]);
  240. }
  241. FREE(pwndVictim->plyr);
  242. }
  243. // Notify MCD that this window has gone away
  244. if (pwndVictim->dwMcdWindow != 0)
  245. {
  246. GenMcdDestroyWindow(pwndVictim);
  247. }
  248. // Delete victim.
  249. DeleteCriticalSection(&pwndVictim->sem);
  250. FREE(pwndVictim);
  251. return NULL;
  252. }
  253. /******************************Public*Routine******************************\
  254. *
  255. * pwndCleanup
  256. *
  257. * Does all cleanup necessary for window destruction
  258. *
  259. * History:
  260. * Mon Mar 18 17:30:49 1996 -by- Drew Bliss [drewb]
  261. * Created
  262. *
  263. \**************************************************************************/
  264. void APIENTRY pwndCleanup(GLGENwindow *pwndVictim)
  265. {
  266. GLGENwindow *pwnd, *pwndPrev;
  267. #if DBG
  268. ULONG ulLoops;
  269. #endif
  270. #ifdef DBG_WINDOW
  271. DbgPrint("Clean window %p\n", pwndVictim);
  272. #endif
  273. EnterCriticalSection(&gwndHeader.sem);
  274. // Search for victim. Maintain a prev pointer so we can do
  275. // removal from linked list.
  276. for (
  277. pwndPrev = &gwndHeader, pwnd = pwndPrev->pNext;
  278. pwnd != &gwndHeader;
  279. pwndPrev = pwnd, pwnd = pwndPrev->pNext
  280. )
  281. {
  282. if (pwnd == pwndVictim)
  283. break;
  284. }
  285. // If victim was found, take it out.
  286. if (pwnd == pwndVictim)
  287. {
  288. // Excise victim from linked list.
  289. pwndPrev->pNext = pwnd->pNext;
  290. }
  291. LeaveCriticalSection(&gwndHeader.sem);
  292. if (pwnd == NULL)
  293. {
  294. WARNING("pwndFree: pwndVictim not found in list\n");
  295. return;
  296. }
  297. // If victim was found, it's out of the list so nobody
  298. // new can get access to it.
  299. // Wait for all current accessors to go away before cleaning up
  300. // the window
  301. #if DBG
  302. ulLoops = 0;
  303. #endif
  304. for (;;)
  305. {
  306. if (pwndVictim->lUsers == 1)
  307. {
  308. break;
  309. }
  310. #if DBG
  311. if (++ulLoops == 1000)
  312. {
  313. DbgPrint("Spinning on window %p\n", pwndVictim);
  314. #ifdef DBG_WINDOW
  315. DebugBreak();
  316. #endif
  317. }
  318. #endif
  319. // Wait on the critical section as a delay
  320. // Acquiring it doesn't guarantee that we're the last
  321. // accessor, but it does kill time in the case where
  322. // another accessor is already holding it
  323. EnterCriticalSection(&pwndVictim->sem);
  324. LeaveCriticalSection(&pwndVictim->sem);
  325. // Allow other threads time to run so we don't starve
  326. // anybody while we're waiting
  327. Sleep(0);
  328. }
  329. if (pwndVictim->buffers != NULL)
  330. {
  331. __glGenFreeBuffers(pwndVictim->buffers);
  332. wglCleanupWindow(pwndVictim);
  333. }
  334. if (pwndFree(pwndVictim, FALSE))
  335. WARNING("window deletion failed\n");
  336. }
  337. /******************************Public*Routine******************************\
  338. * vCleanupWnd
  339. *
  340. * Removes and deletes all GLGENwindow structures from the linked list.
  341. * Must *ONLY* be called from process detach (GLUnInitializeProcess).
  342. *
  343. * History:
  344. * 25-Jul-1995 -by- Gilman Wong [gilmanw]
  345. * Wrote it.
  346. \**************************************************************************/
  347. VOID APIENTRY vCleanupWnd()
  348. {
  349. GLGENwindow *pwndNext;
  350. EnterCriticalSection(&gwndHeader.sem);
  351. while ( gwndHeader.pNext != &gwndHeader )
  352. {
  353. pwndNext = gwndHeader.pNext->pNext;
  354. pwndFree(gwndHeader.pNext, TRUE);
  355. gwndHeader.pNext = pwndNext;
  356. }
  357. LeaveCriticalSection(&gwndHeader.sem);
  358. // Wait for the palette watcher thread to die. This ensures
  359. // that the palette watcher critical section can be deleted
  360. // safely in process detach.
  361. // We don't use a critical section at this point because of
  362. // the special critsec rules during DLL detach processing.
  363. while (tidPaletteWatcherThread != 0)
  364. {
  365. Sleep(50);
  366. }
  367. // Give the palette watcher thread some time to exit after
  368. // clearing the thread ID.
  369. Sleep(50);
  370. }
  371. /******************************Public*Routine******************************\
  372. * pwndGetFromHWND
  373. *
  374. * Finds the corresponding GLGENwindow for the given window handle.
  375. *
  376. * Returns:
  377. * Pointer to GLGENwindow if sucessful; NULL otherwise.
  378. *
  379. * History:
  380. * 19-Oct-1994 -by- Gilman Wong [gilmanw]
  381. * Wrote it.
  382. \**************************************************************************/
  383. GLGENwindow * APIENTRY pwndGetFromHWND(HWND hwnd)
  384. {
  385. GLGENwindow *pwndRet = (GLGENwindow *) NULL;
  386. GLGENwindow *pwnd = (GLGENwindow *) NULL;
  387. EnterCriticalSection(&gwndHeader.sem);
  388. {
  389. for (pwnd = gwndHeader.pNext; pwnd != &gwndHeader; pwnd = pwnd->pNext)
  390. if (pwnd->gwid.hwnd == hwnd)
  391. {
  392. pwndRet = pwnd;
  393. InterlockedIncrement(&pwnd->lUsers);
  394. break;
  395. }
  396. }
  397. LeaveCriticalSection(&gwndHeader.sem);
  398. #ifdef DBG_REFCOUNTS
  399. if (pwndRet != 0)
  400. {
  401. DbgPrint("GetHWND %p to %d\n", pwndRet, pwndRet->lUsers);
  402. }
  403. #endif
  404. return pwndRet;
  405. }
  406. /******************************Public*Routine******************************\
  407. * pwndGetFromMemDC
  408. *
  409. * Finds the corresponding GLGENwindow for the given mem DC handle.
  410. *
  411. * Returns:
  412. * Pointer to GLGENwindow if sucessful; NULL otherwise.
  413. *
  414. * History:
  415. * 21-Jan-1995 -by- Gilman Wong [gilmanw]
  416. * Wrote it.
  417. \**************************************************************************/
  418. GLGENwindow * APIENTRY pwndGetFromMemDC(HDC hdcMem)
  419. {
  420. GLGENwindow *pwndRet = (GLGENwindow *) NULL;
  421. GLGENwindow *pwnd = (GLGENwindow *) NULL;
  422. EnterCriticalSection(&gwndHeader.sem);
  423. {
  424. for (pwnd = gwndHeader.pNext; pwnd != &gwndHeader; pwnd = pwnd->pNext)
  425. {
  426. // If the pwnd has an HWND then the DC used at its
  427. // creation was associated with a window. If we're
  428. // in this routine, though, that means hdcMem is
  429. // not associated with a window, so there's been
  430. // a reuse of the HDC handle and even though
  431. // we match DCs we can't return the pwnd.
  432. if (pwnd->gwid.hdc == hdcMem && pwnd->gwid.hwnd == NULL)
  433. {
  434. pwndRet = pwnd;
  435. InterlockedIncrement(&pwndRet->lUsers);
  436. break;
  437. }
  438. }
  439. }
  440. LeaveCriticalSection(&gwndHeader.sem);
  441. #ifdef DBG_REFCOUNTS
  442. if (pwndRet != 0)
  443. {
  444. DbgPrint("GetDC %p to %d\n", pwndRet, pwndRet->lUsers);
  445. }
  446. #endif
  447. return pwndRet;
  448. }
  449. /******************************Public*Routine******************************\
  450. *
  451. * pwndGetFromDdraw
  452. *
  453. * Looks up a window by its DirectDraw surface
  454. *
  455. * History:
  456. * Wed Aug 28 18:15:40 1996 -by- Drew Bliss [drewb]
  457. * Created
  458. *
  459. \**************************************************************************/
  460. GLGENwindow *pwndGetFromDdraw(LPDIRECTDRAWSURFACE pdds)
  461. {
  462. GLGENwindow *pwndRet = (GLGENwindow *) NULL;
  463. GLGENwindow *pwnd = (GLGENwindow *) NULL;
  464. EnterCriticalSection(&gwndHeader.sem);
  465. {
  466. for (pwnd = gwndHeader.pNext; pwnd != &gwndHeader; pwnd = pwnd->pNext)
  467. if (pwnd->gwid.pdds == pdds)
  468. {
  469. pwndRet = pwnd;
  470. InterlockedIncrement(&pwndRet->lUsers);
  471. break;
  472. }
  473. }
  474. LeaveCriticalSection(&gwndHeader.sem);
  475. #ifdef DBG_REFCOUNTS
  476. if (pwndRet != 0)
  477. {
  478. DbgPrint("GetDD %p to %d\n", pwndRet, pwndRet->lUsers);
  479. }
  480. #endif
  481. return pwndRet;
  482. }
  483. /******************************Public*Routine******************************\
  484. * pwndGetFromID
  485. *
  486. * Finds the corresponding GLGENwindow for the given window ID.
  487. *
  488. * Returns:
  489. * Pointer to GLGENwindow if sucessful; NULL otherwise.
  490. *
  491. * History:
  492. * 19-Oct-1994 -by- Gilman Wong [gilmanw]
  493. * Wrote it.
  494. \**************************************************************************/
  495. GLGENwindow * APIENTRY pwndGetFromID(GLWINDOWID *pgwid)
  496. {
  497. GLGENwindow *pwndRet = (GLGENwindow *) NULL;
  498. switch (pgwid->iType)
  499. {
  500. case GLWID_HWND:
  501. pwndRet = pwndGetFromHWND(pgwid->hwnd);
  502. break;
  503. case GLWID_HDC:
  504. pwndRet = pwndGetFromMemDC(pgwid->hdc);
  505. break;
  506. case GLWID_DDRAW:
  507. pwndRet = pwndGetFromDdraw(pgwid->pdds);
  508. break;
  509. }
  510. return pwndRet;
  511. }
  512. /******************************Public*Routine******************************\
  513. *
  514. * pwndRelease
  515. *
  516. * Decrements the user count of a window
  517. *
  518. * History:
  519. * Mon Mar 18 19:35:28 1996 -by- Drew Bliss [drewb]
  520. * Created
  521. *
  522. \**************************************************************************/
  523. #if DBG
  524. void APIENTRY pwndRelease(GLGENwindow *pwnd)
  525. {
  526. ASSERTOPENGL(pwnd->lUsers > 0, "Decrement lUsers below zero\n");
  527. InterlockedDecrement(&pwnd->lUsers);
  528. #ifdef DBG_REFCOUNTS
  529. DbgPrint("Release %p to %d\n", pwnd, pwnd->lUsers);
  530. #endif
  531. }
  532. #endif
  533. /******************************Public*Routine******************************\
  534. *
  535. * pwndUnlock
  536. *
  537. * Releases an owner of a window
  538. *
  539. * History:
  540. * Mon Mar 18 17:25:56 1996 -by- Drew Bliss [drewb]
  541. * Created
  542. *
  543. \**************************************************************************/
  544. void APIENTRY pwndUnlock(GLGENwindow *pwnd, __GLGENcontext *gengc)
  545. {
  546. ASSERTOPENGL(pwnd != NULL, "Unlocking NULL window\n");
  547. LEAVE_WINCRIT_GC(pwnd, gengc);
  548. pwndRelease(pwnd);
  549. }
  550. /******************************Public*Routine******************************\
  551. *
  552. * ENTER_WINCRIT_GC
  553. * LEAVE_WINCRIT_GC
  554. *
  555. * Window lock tracking routines. The pwnd and gengc are validated
  556. * and updated to reflect current locks.
  557. *
  558. * If the gengc is non-NULL then recursion is not allowed. This is
  559. * to prevent difficulties with maintaining gengc->pwndLocked correctly
  560. * during recursion. Recursing with gengc == NULL is not a problem.
  561. *
  562. * No ASSERTOPENGL usage so these can be enabled on free builds.
  563. *
  564. * History:
  565. * Wed Jul 02 12:57:26 1997 -by- Drew Bliss [drewb]
  566. *
  567. \**************************************************************************/
  568. void ENTER_WINCRIT_GC(GLGENwindow *pwnd, __GLGENcontext *gengc)
  569. {
  570. EnterCriticalSection(&pwnd->sem);
  571. if (pwnd->owningThread == 0)
  572. {
  573. #if DBG || defined(TRACK_WINCRIT)
  574. if (pwnd->lockRecursion != 0)
  575. {
  576. DbgPrint("Unowned window 0x%08lX has recursion count %d\n",
  577. pwnd, pwnd->lockRecursion);
  578. DebugBreak();
  579. }
  580. if (pwnd->gengc != NULL)
  581. {
  582. DbgPrint("Unowned window 0x%08lX has gengc 0x%08lX\n",
  583. pwnd, pwnd->gengc);
  584. DebugBreak();
  585. }
  586. if (gengc != NULL && gengc->pwndLocked != NULL)
  587. {
  588. DbgPrint("gengc 0x%08lX has pwnd 0x%08lX while locking 0x%08lX\n",
  589. gengc, gengc->pwndLocked, pwnd);
  590. DebugBreak();
  591. }
  592. #endif
  593. pwnd->owningThread = GetCurrentThreadId();
  594. if (gengc != NULL)
  595. {
  596. gengc->pwndLocked = pwnd;
  597. pwnd->gengc = gengc;
  598. }
  599. }
  600. else
  601. {
  602. // Make sure this thread is really the one holding the lock.
  603. ASSERT_WINCRIT(pwnd);
  604. #if DBG || defined(TRACK_WINCRIT)
  605. // Recursion is only allowed with gengc == NULL.
  606. if (gengc != NULL)
  607. {
  608. DbgPrint("Window 0x%08lX recursing with gengc 0x%08lX\n",
  609. pwnd, gengc);
  610. DebugBreak();
  611. }
  612. #endif
  613. }
  614. pwnd->lockRecursion++;
  615. }
  616. void LEAVE_WINCRIT_GC(GLGENwindow *pwnd, __GLGENcontext *gengc)
  617. {
  618. ASSERT_WINCRIT(pwnd);
  619. #if 0
  620. // Currently turned off because of difference in RTL_CRITICAL_SECTION
  621. // RecursionCount between x86 and Alpha
  622. #if !defined(_WIN95_) && (DBG || defined(TRACK_WINCRIT))
  623. // Check and make sure that our tracking information is following
  624. // what the system thinks.
  625. if (pwnd->sem.OwningThread != (HANDLE)pwnd->owningThread ||
  626. (DWORD)pwnd->sem.RecursionCount != pwnd->lockRecursion)
  627. {
  628. DbgPrint("pwnd 0x%08lX critsec information mismatch\n", pwnd);
  629. DebugBreak();
  630. }
  631. #endif
  632. #endif
  633. #if DBG || defined(TRACK_WINCRIT)
  634. if (gengc != NULL)
  635. {
  636. if (pwnd->gengc != gengc || gengc->pwndLocked != pwnd)
  637. {
  638. DbgPrint("pwnd 0x%08lX:%08lX mismatch with gengc 0x%08lX:%08lX\n",
  639. pwnd, pwnd->gengc, gengc, gengc->pwndLocked);
  640. DebugBreak();
  641. }
  642. if (pwnd->lockRecursion != 1)
  643. {
  644. DbgPrint("gengc 0x%08lX leaving window 0x%08lX with "
  645. "recursion count of %d\n",
  646. gengc, pwnd, pwnd->lockRecursion);
  647. DebugBreak();
  648. }
  649. }
  650. #endif
  651. if (--pwnd->lockRecursion == 0)
  652. {
  653. if (gengc != NULL)
  654. {
  655. gengc->pwndLocked = NULL;
  656. }
  657. pwnd->gengc = NULL;
  658. pwnd->owningThread = 0;
  659. }
  660. LeaveCriticalSection(&pwnd->sem);
  661. }
  662. /******************************Public*Routine******************************\
  663. *
  664. * wglValidateWindows
  665. *
  666. * Walks the window list and prunes away any DC-based windows with
  667. * invalid DCs. This is necessary because, unlike window-based
  668. * windows, we usually aren't notified when a memory DC goes away
  669. * so if it has a window it just hangs around
  670. *
  671. * History:
  672. * Thu May 02 17:44:23 1996 -by- Drew Bliss [drewb]
  673. * Created
  674. *
  675. \**************************************************************************/
  676. void APIENTRY wglValidateWindows(void)
  677. {
  678. GLGENwindow *pwnd, *pwndNext;
  679. BOOL bValid;
  680. EnterCriticalSection(&gwndHeader.sem);
  681. for (pwnd = gwndHeader.pNext; pwnd != &gwndHeader; pwnd = pwndNext)
  682. {
  683. pwndNext = pwnd->pNext;
  684. switch(pwnd->gwid.iType)
  685. {
  686. case GLWID_HDC:
  687. bValid = GetObjectType(pwnd->gwid.hdc) != 0;
  688. break;
  689. case GLWID_DDRAW:
  690. // Better validation? Not really necessary since properly
  691. // behaved apps will have the genwin cleaned up on
  692. // context destruction.
  693. bValid = !IsBadReadPtr(pwnd->gwid.pdds, sizeof(void *)) &&
  694. *(void **)pwnd->gwid.pdds == pwnd->pvSurfaceVtbl;
  695. break;
  696. default:
  697. // No validation for HWNDs necessary
  698. bValid = TRUE;
  699. break;
  700. }
  701. if (!bValid)
  702. {
  703. // Increment so users count is one
  704. InterlockedIncrement(&pwnd->lUsers);
  705. pwndCleanup(pwnd);
  706. }
  707. }
  708. LeaveCriticalSection(&gwndHeader.sem);
  709. }
  710. /******************************Public*Routine******************************\
  711. * plyriGet
  712. *
  713. * Returns the GLGENlayerInfo for the specified layer plane from the pwnd.
  714. * If it doesn't yet exist, the GLGENlayer and/or GLGENlayerInfo structure(s)
  715. * are allocated.
  716. *
  717. * Returns:
  718. * A non-NULL pointer if successful; NULL otherwise.
  719. *
  720. * History:
  721. * 16-May-1996 -by- Gilman Wong [gilmanw]
  722. * Wrote it.
  723. \**************************************************************************/
  724. GLGENlayerInfo * APIENTRY plyriGet(GLGENwindow *pwnd, HDC hdc, int iLayer)
  725. {
  726. GLGENlayerInfo *plyriRet = (GLGENlayerInfo * ) NULL;
  727. GLGENlayerInfo **pplyri;
  728. ASSERTOPENGL(pwnd, "plyriGet: bad pwnd\n");
  729. // Allocate plyr if needed.
  730. if (!pwnd->plyr)
  731. {
  732. pwnd->plyr = (GLGENlayers *) ALLOCZ(sizeof(GLGENlayers));
  733. if (!pwnd->plyr)
  734. {
  735. WARNING("plyriGet: alloc failed (GLGENlayers)\n");
  736. goto plyriGet_exit;
  737. }
  738. }
  739. // Get info for the specified layer (positive values are overlay planes,
  740. // negative values are underlay planes).
  741. if (iLayer > 0)
  742. pplyri = &pwnd->plyr->overlayInfo[iLayer - 1];
  743. else if (iLayer < 1)
  744. pplyri = &pwnd->plyr->underlayInfo[(-iLayer) - 1];
  745. else
  746. {
  747. WARNING("plyriGet: no layer plane info for main plane!\n");
  748. goto plyriGet_exit;
  749. }
  750. // Allocate plyri if needed.
  751. if (!(*pplyri))
  752. {
  753. LAYERPLANEDESCRIPTOR lpd;
  754. if (!wglDescribeLayerPlane(hdc, pwnd->ipfd, iLayer, sizeof(lpd), &lpd))
  755. {
  756. WARNING("plyriGet: wglDescribeLayerPlane failed\n");
  757. goto plyriGet_exit;
  758. }
  759. *pplyri = (GLGENlayerInfo *)
  760. ALLOC((sizeof(COLORREF) * (1 << lpd.cColorBits))
  761. + sizeof(GLGENlayerInfo));
  762. if (*pplyri)
  763. {
  764. int i;
  765. // Initialize the new GLGENlayerInfo.
  766. // Note that the palette is initialized with all white colors.
  767. (*pplyri)->cPalEntries = 1 << lpd.cColorBits;
  768. for (i = 0; i < (*pplyri)->cPalEntries; i++)
  769. (*pplyri)->pPalEntries[i] = RGB(255, 255, 255);
  770. }
  771. else
  772. {
  773. WARNING("plyriGet: alloc failed (GLGENlayerInfo)\n");
  774. goto plyriGet_exit;
  775. }
  776. }
  777. // Success.
  778. plyriRet = *pplyri;
  779. plyriGet_exit:
  780. return plyriRet;
  781. }
  782. /******************************Public*Routine******************************\
  783. * GetScreenRect
  784. *
  785. * Get the screen rectangle by accessing the virtual screen metrics.
  786. *
  787. * If the system does not understand multimon, such as old Win95 or NT,
  788. * just use the device caps. This code technically isn't necessary but
  789. * it's useful.
  790. *
  791. \**************************************************************************/
  792. static void GetScreenRect( HDC hdc, LPRECTL pRect )
  793. {
  794. // If SM_CMONITORS is not understood the system returns zero,
  795. // so this if test works for both old and new systems.
  796. if (GetSystemMetrics(SM_CMONITORS) > 1)
  797. {
  798. pRect->left = GetSystemMetrics( SM_XVIRTUALSCREEN );
  799. pRect->top = GetSystemMetrics( SM_YVIRTUALSCREEN );
  800. pRect->right = pRect->left + GetSystemMetrics( SM_CXVIRTUALSCREEN );
  801. pRect->bottom = pRect->top + GetSystemMetrics( SM_CYVIRTUALSCREEN );
  802. }
  803. else
  804. {
  805. pRect->left = 0;
  806. pRect->top = 0;
  807. pRect->right = GetDeviceCaps(hdc, HORZRES);
  808. pRect->bottom = GetDeviceCaps(hdc, VERTRES);
  809. }
  810. }
  811. /******************************Public*Routine******************************\
  812. * bClipToScreen(prclDst, prclSrc)
  813. *
  814. * Clip source rectangle to screen bounds and store in destination rectangle.
  815. *
  816. * Returns:
  817. * TRUE if resultant prclDst == prclSrc; FALSE otherwise.
  818. *
  819. \**************************************************************************/
  820. BOOL bClipToScreen(RECTL *prclDst, RECTL *prclSrc)
  821. {
  822. BOOL bRet;
  823. HDC hdc;
  824. if (hdc = GetDC(NULL))
  825. {
  826. RECTL rclScreen;
  827. GetScreenRect( hdc, &rclScreen );
  828. prclDst->left = max(prclSrc->left , rclScreen.left );
  829. prclDst->top = max(prclSrc->top , rclScreen.top );
  830. prclDst->right = min(prclSrc->right , rclScreen.right );
  831. prclDst->bottom = min(prclSrc->bottom, rclScreen.bottom);
  832. if ((prclDst->left >= prclDst->right) ||
  833. (prclDst->top >= prclDst->bottom))
  834. {
  835. prclDst->left = 0;
  836. prclDst->top = 0;
  837. prclDst->right = 0;
  838. prclDst->bottom = 0;
  839. }
  840. ReleaseDC(NULL, hdc);
  841. }
  842. else
  843. {
  844. prclDst->left = 0;
  845. prclDst->top = 0;
  846. prclDst->right = 0;
  847. prclDst->bottom = 0;
  848. }
  849. if ((prclDst->left == prclSrc->left ) &&
  850. (prclDst->top == prclSrc->top ) &&
  851. (prclDst->right == prclSrc->right ) &&
  852. (prclDst->bottom == prclSrc->bottom))
  853. bRet = TRUE;
  854. else
  855. bRet = FALSE;
  856. return bRet;
  857. }
  858. /******************************Public*Routine******************************\
  859. *
  860. * PaletteWatcherProc
  861. *
  862. * Window proc for the palette watcher
  863. *
  864. * History:
  865. * Mon Oct 14 15:29:10 1996 -by- Drew Bliss [drewb]
  866. * Created
  867. *
  868. \**************************************************************************/
  869. LRESULT WINAPI PaletteWatcherProc(HWND hwnd, UINT uiMsg,
  870. WPARAM wpm, LPARAM lpm)
  871. {
  872. switch(uiMsg)
  873. {
  874. case WM_PALETTECHANGED:
  875. InterlockedIncrement((LONG *)&ulPaletteWatcherCount);
  876. return 0;
  877. default:
  878. return DefWindowProc(hwnd, uiMsg, wpm, lpm);
  879. }
  880. }
  881. /******************************Public*Routine******************************\
  882. *
  883. * PaletteWatcher
  884. *
  885. * Thread routine for the palette change monitor. Creates a hidden
  886. * top level window and looks for WM_PALETTECHANGED.
  887. *
  888. * History:
  889. * Mon Oct 14 15:16:02 1996 -by- Drew Bliss [drewb]
  890. * Created
  891. *
  892. \**************************************************************************/
  893. DWORD WINAPI PaletteWatcher(LPVOID pvArg)
  894. {
  895. HWND hwnd;
  896. hwnd = CreateWindow(PALETTE_WATCHER_CLASS,
  897. PALETTE_WATCHER_CLASS,
  898. WS_OVERLAPPED,
  899. 0, 0, 1, 1,
  900. NULL,
  901. NULL,
  902. (HINSTANCE)GetModuleHandle(NULL),
  903. NULL);
  904. if (hwnd != NULL)
  905. {
  906. HDC hdc;
  907. HPALETTE hpal;
  908. // Select a palette into the window DC. This is necessary
  909. // to get around an optimization introduced into NT5 where
  910. // WM_PALETTECHANGED is only sent to windows that have selected
  911. // a palette.
  912. hpal = NULL;
  913. hdc = GetDC(hwnd);
  914. if (hdc != NULL)
  915. {
  916. hpal = SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), FALSE);
  917. ReleaseDC(hwnd, hdc);
  918. }
  919. if (hpal == NULL)
  920. {
  921. goto EH_Exit;
  922. }
  923. hwndPaletteWatcher = hwnd;
  924. for (;;)
  925. {
  926. MSG msg;
  927. if (GetMessage(&msg, hwnd, 0, 0) > 0)
  928. {
  929. TranslateMessage(&msg);
  930. DispatchMessage(&msg);
  931. }
  932. else
  933. {
  934. break;
  935. }
  936. }
  937. EH_Exit:
  938. DestroyWindow(hwnd);
  939. hwndPaletteWatcher = 0;
  940. }
  941. EnterCriticalSection(&gcsPaletteWatcher);
  942. // Some kind of problem occurred or this thread is dying.
  943. // Indicate that this thread is going away and that a
  944. // new watcher needs to be created.
  945. if (tidPaletteWatcherThread == GetCurrentThreadId())
  946. {
  947. tidPaletteWatcherThread = 0;
  948. }
  949. LeaveCriticalSection(&gcsPaletteWatcher);
  950. return 0;
  951. }
  952. /******************************Public*Routine******************************\
  953. *
  954. * StartPaletteWatcher
  955. *
  956. * Spins up a thread to watch for palette change events
  957. *
  958. * History:
  959. * Mon Oct 14 15:11:35 1996 -by- Drew Bliss [drewb]
  960. * Created
  961. *
  962. \**************************************************************************/
  963. BOOL StartPaletteWatcher(void)
  964. {
  965. BOOL bRet;
  966. EnterCriticalSection(&gcsPaletteWatcher);
  967. bRet = FALSE;
  968. if (tidPaletteWatcherThread == 0)
  969. {
  970. HANDLE h;
  971. if (aPaletteWatcherClass == 0)
  972. {
  973. WNDCLASS wc;
  974. wc.style = 0;
  975. wc.lpfnWndProc = PaletteWatcherProc;
  976. wc.cbClsExtra = 0;
  977. wc.cbWndExtra = 0;
  978. wc.hInstance = (HINSTANCE)GetModuleHandle(NULL);
  979. wc.hIcon = NULL;
  980. wc.hCursor = NULL;
  981. wc.hbrBackground = NULL;
  982. wc.lpszMenuName = NULL;
  983. wc.lpszClassName = PALETTE_WATCHER_CLASS;
  984. aPaletteWatcherClass = RegisterClass(&wc);
  985. }
  986. if (aPaletteWatcherClass != 0)
  987. {
  988. h = CreateThread(NULL, 4096, PaletteWatcher,
  989. NULL, 0, &tidPaletteWatcherThread);
  990. if (h != NULL)
  991. {
  992. hPaletteWatcherThread = h;
  993. bRet = TRUE;
  994. }
  995. }
  996. }
  997. else
  998. {
  999. bRet = TRUE;
  1000. }
  1001. if (bRet)
  1002. {
  1003. lPaletteWatcherUsers++;
  1004. }
  1005. LeaveCriticalSection(&gcsPaletteWatcher);
  1006. // Make sure that the Palette watcher window is created.
  1007. // Dont need to be in the CritSec for this.
  1008. while( (hwndPaletteWatcher == 0) &&
  1009. (tidPaletteWatcherThread != 0) ) Sleep( 100 );
  1010. return bRet;
  1011. }
  1012. /******************************Public*Routine******************************\
  1013. * wglWndProc
  1014. *
  1015. * Handle window events for keeping GLGENwindows current
  1016. *
  1017. * History:
  1018. * 19-Oct-1994 -by- Gilman Wong [gilmanw]
  1019. * Wrote it.
  1020. \**************************************************************************/
  1021. LRESULT CALLBACK
  1022. wglWndProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
  1023. {
  1024. GLGENwindow *pwnd;
  1025. LRESULT lRet = 0;
  1026. WORD width, height;
  1027. __GLGENcontext *gengc;
  1028. pwnd = pwndGetFromHWND(hwnd);
  1029. if (pwnd)
  1030. {
  1031. __GLGENbuffers *buffers = (__GLGENbuffers *) NULL;
  1032. // Cache old WNDPROC because we may delete pwnd
  1033. WNDPROC pfnWndProc = pwnd->pfnOldWndProc;
  1034. // If WM_NCDESTROY, do OpenGL housekeeping after
  1035. // calling original WndProc.
  1036. // NOTE - We shouldn't really need this special case.
  1037. // It's present in order to allow apps to do things like
  1038. // wglDeleteContext in NCDESTROY which wouldn't work if
  1039. // we cleaned up the window before we passed on the message
  1040. // This used to be done in WM_DESTROY where apps do work,
  1041. // but now that it's on NCDESTROY it's much less likely that
  1042. // an app is doing anything. We preserved the old behavior
  1043. // for safety, though.
  1044. if (uiMsg == WM_NCDESTROY)
  1045. {
  1046. // Subclassing is supposed to be removed during NCDESTROY
  1047. // processing and order is important. Remove our
  1048. // subclassing before passing on the message.
  1049. pwndUnsubclass(pwnd, FALSE);
  1050. if (pfnWndProc)
  1051. {
  1052. lRet = CallWindowProc(pfnWndProc, hwnd,
  1053. uiMsg, wParam, lParam);
  1054. }
  1055. }
  1056. // OpenGL housekeeping in response to windowing system messages.
  1057. switch (uiMsg)
  1058. {
  1059. case WM_SIZE:
  1060. width = LOWORD(lParam);
  1061. height = HIWORD(lParam);
  1062. gengc = (__GLGENcontext *)GLTEB_SRVCONTEXT();
  1063. // Use the non-gc enter to allow recursion.
  1064. ENTER_WINCRIT(pwnd);
  1065. {
  1066. POINT pt;
  1067. // Convert client coordinates to screen coordinates
  1068. // as genwin information is always in screen coordinates.
  1069. // The given lParam information may be parent-relative
  1070. // for child windows so it can't be used directly.
  1071. pt.x = 0;
  1072. pt.y = 0;
  1073. ClientToScreen(hwnd, &pt);
  1074. pwnd->rclClient.left = pt.x;
  1075. pwnd->rclClient.right = pt.x + width;
  1076. pwnd->rclClient.top = pt.y;
  1077. pwnd->rclClient.bottom = pt.y + height;
  1078. #if 0
  1079. DbgPrint("size %d,%d - %d,%d\n",
  1080. pwnd->rclClient.left,
  1081. pwnd->rclClient.top,
  1082. pwnd->rclClient.right,
  1083. pwnd->rclClient.bottom);
  1084. #endif
  1085. // At least clip to screen.
  1086. if (bClipToScreen(&pwnd->rclBounds,
  1087. &pwnd->rclClient))
  1088. pwnd->clipComplexity = CLC_TRIVIAL;
  1089. else
  1090. pwnd->clipComplexity = CLC_RECT;
  1091. buffers = pwnd->buffers;
  1092. if (buffers)
  1093. {
  1094. buffers->WndUniq++;
  1095. buffers->WndSizeUniq++;
  1096. // Don't let it hit -1. -1 is special and is used by
  1097. // MakeCurrent to signal that an update is required
  1098. if (buffers->WndUniq == -1)
  1099. buffers->WndUniq = 0;
  1100. if (buffers->WndSizeUniq == -1)
  1101. buffers->WndSizeUniq = 0;
  1102. if ((gengc != NULL) && (pwnd == gengc->pwndLocked))
  1103. UpdateWindowInfo(gengc);
  1104. }
  1105. }
  1106. LEAVE_WINCRIT(pwnd);
  1107. break;
  1108. case WM_MOVE:
  1109. gengc = (__GLGENcontext *)GLTEB_SRVCONTEXT();
  1110. // Use the non-gc enter to allow recursion.
  1111. ENTER_WINCRIT(pwnd);
  1112. {
  1113. POINT pt;
  1114. // Convert client coordinates to screen coordinates
  1115. // as genwin information is always in screen coordinates.
  1116. // The given lParam information may be parent-relative
  1117. // for child windows so it can't be used directly.
  1118. pt.x = 0;
  1119. pt.y = 0;
  1120. ClientToScreen(hwnd, &pt);
  1121. width = (WORD) (pwnd->rclClient.right -
  1122. pwnd->rclClient.left);
  1123. height = (WORD) (pwnd->rclClient.bottom -
  1124. pwnd->rclClient.top);
  1125. ASSERTOPENGL(
  1126. (pwnd->rclClient.right -
  1127. pwnd->rclClient.left) <= 0x0FFFF &&
  1128. (pwnd->rclClient.bottom -
  1129. pwnd->rclClient.top) <= 0x0FFFF,
  1130. "wglWndProc(): WM_MOVE - width/height overflow\n"
  1131. );
  1132. pwnd->rclClient.left = pt.x;
  1133. pwnd->rclClient.right = pt.x + width;
  1134. pwnd->rclClient.top = pt.y;
  1135. pwnd->rclClient.bottom = pt.y + height;
  1136. #if 0
  1137. DbgPrint("move %d,%d - %d,%d\n",
  1138. pwnd->rclClient.left,
  1139. pwnd->rclClient.top,
  1140. pwnd->rclClient.right,
  1141. pwnd->rclClient.bottom);
  1142. #endif
  1143. // At least clip to screen.
  1144. if (bClipToScreen(&pwnd->rclBounds,
  1145. &pwnd->rclClient))
  1146. pwnd->clipComplexity = CLC_TRIVIAL;
  1147. else
  1148. pwnd->clipComplexity = CLC_RECT;
  1149. buffers = pwnd->buffers;
  1150. if (buffers)
  1151. {
  1152. buffers->WndUniq++;
  1153. // Don't let it hit -1. -1 is special and is used by
  1154. // MakeCurrent to signal that an update is required
  1155. if (buffers->WndUniq == -1)
  1156. buffers->WndUniq = 0;
  1157. if ((gengc != NULL) && (pwnd == gengc->pwndLocked))
  1158. UpdateWindowInfo(gengc);
  1159. }
  1160. }
  1161. LEAVE_WINCRIT(pwnd);
  1162. break;
  1163. case WM_PALETTECHANGED:
  1164. gengc = (__GLGENcontext *)GLTEB_SRVCONTEXT();
  1165. // Use the non-gc enter to allow recursion.
  1166. ENTER_WINCRIT(pwnd);
  1167. {
  1168. pwnd->ulPaletteUniq++;
  1169. if ((gengc != NULL) && (pwnd == gengc->pwndLocked))
  1170. HandlePaletteChanges(gengc, pwnd);
  1171. }
  1172. LEAVE_WINCRIT(pwnd);
  1173. break;
  1174. case WM_NCDESTROY:
  1175. pwndCleanup(pwnd);
  1176. // WM_NCDESTROY (and WM_DESTROY) are sent after the window has
  1177. // been removed from the screen. The window area is invalid
  1178. // but there is no API that allows us to dertermine that. This
  1179. // allows multithreaded drawing to draw on the screen area
  1180. // formerly occupied by the window. On Win95, DirectDraw does
  1181. // not force a repaint of the system when a window is destroyed.
  1182. // Therefore, if we are running multiple threads on Win95,
  1183. // we force a repaint of the desktop. Note that multithreaded
  1184. // does not mean that we are doing multithreaded drawing, but
  1185. // its a reasonable approximation.
  1186. if (WIN95_PLATFORM && (lThreadsAttached > 1))
  1187. {
  1188. InvalidateRect(NULL, NULL, FALSE);
  1189. }
  1190. return lRet;
  1191. default:
  1192. break;
  1193. }
  1194. // If !WM_NCDESTROY, do OpenGL housekeeping before calling original
  1195. // WndProc.
  1196. ASSERTOPENGL(uiMsg != WM_NCDESTROY,
  1197. "WM_NCDESTROY processing didn't terminate\n");
  1198. pwndRelease(pwnd);
  1199. if (pfnWndProc)
  1200. lRet = CallWindowProc(pfnWndProc, hwnd,
  1201. uiMsg, wParam, lParam);
  1202. }
  1203. return lRet;
  1204. }
  1205. /******************************Public*Routine******************************\
  1206. *
  1207. * CreatePwnd
  1208. *
  1209. * Creates a window for the given surface
  1210. *
  1211. * History:
  1212. * Thu Aug 29 10:33:59 1996 -by- Drew Bliss [drewb]
  1213. * Created
  1214. *
  1215. \**************************************************************************/
  1216. GLGENwindow * APIENTRY CreatePwnd(GLWINDOWID *pgwid, int ipfd, int ipfdDevMax,
  1217. DWORD dwObjectType, RECTL *prcl, BOOL *pbNew)
  1218. {
  1219. GLGENwindow *pwnd;
  1220. GLGENwindow wndInit;
  1221. pwnd = pwndGetFromID(pgwid);
  1222. if ( !pwnd )
  1223. {
  1224. memset(&wndInit, 0, sizeof(wndInit));
  1225. wndInit.gwid = *pgwid;
  1226. wndInit.ipfd = ipfd;
  1227. wndInit.ipfdDevMax = ipfdDevMax;
  1228. //!!!client driver
  1229. //!!!dbug -- Move SetWindowLong call to pwndNew?!? Maybe move
  1230. //!!!dbug everything from this if.. clause to pwndNew?!?
  1231. if ( wndInit.gwid.hwnd )
  1232. {
  1233. DWORD dwPid;
  1234. if (GetWindowThreadProcessId(wndInit.gwid.hwnd,
  1235. &dwPid) == 0xffffffff)
  1236. {
  1237. return NULL;
  1238. }
  1239. if (dwPid == GetCurrentProcessId())
  1240. {
  1241. wndInit.pfnOldWndProc =
  1242. (WNDPROC) SetWindowLongPtr(wndInit.gwid.hwnd,
  1243. GWLP_WNDPROC, (LONG_PTR) wglWndProc);
  1244. }
  1245. else
  1246. {
  1247. wndInit.ulFlags |= GLGENWIN_OTHERPROCESS;
  1248. // Start a thread to watch for palette changes
  1249. if (!StartPaletteWatcher())
  1250. {
  1251. return NULL;
  1252. }
  1253. }
  1254. // Get *SCREEN* coordinates of client rectangle.
  1255. GetClientRect(wndInit.gwid.hwnd, (LPRECT) &wndInit.rclClient);
  1256. ClientToScreen(wndInit.gwid.hwnd, (LPPOINT) &wndInit.rclClient);
  1257. wndInit.rclClient.right += wndInit.rclClient.left;
  1258. wndInit.rclClient.bottom += wndInit.rclClient.top;
  1259. }
  1260. else if (dwObjectType == OBJ_DC)
  1261. {
  1262. // A direct DC without a window is treated like a DFB
  1263. GetScreenRect( pgwid->hdc, &wndInit.rclClient );
  1264. }
  1265. else if (dwObjectType == OBJ_MEMDC)
  1266. {
  1267. DIBSECTION bmi;
  1268. // Get bitmap dimensions.
  1269. if ( !GetObject(GetCurrentObject(pgwid->hdc, OBJ_BITMAP),
  1270. sizeof(DIBSECTION), (LPVOID) &bmi) )
  1271. {
  1272. WARNING("wglSetPixelFormat(): GetObject failed\n");
  1273. return NULL;
  1274. }
  1275. wndInit.rclClient.left = 0;
  1276. wndInit.rclClient.top = 0;
  1277. wndInit.rclClient.right = bmi.dsBm.bmWidth;
  1278. wndInit.rclClient.bottom = abs(bmi.dsBm.bmHeight);
  1279. }
  1280. else if (dwObjectType == OBJ_DDRAW)
  1281. {
  1282. // DirectDraw surface, use passed in rectangle
  1283. ASSERTOPENGL(prcl != NULL, "NULL rect for DDraw surface\n");
  1284. wndInit.rclClient = *prcl;
  1285. // Record the surface vtbl pointer for later validation
  1286. wndInit.pvSurfaceVtbl = *(void **)pgwid->pdds;
  1287. }
  1288. else
  1289. {
  1290. ASSERTOPENGL(dwObjectType == OBJ_ENHMETADC,
  1291. "Bad dwType in SetPixelFormat\n");
  1292. // Initialize metafile DC's to have no size so all output
  1293. // is clipped. This is good because there's no surface
  1294. // to draw on
  1295. wndInit.rclClient.left = 0;
  1296. wndInit.rclClient.top = 0;
  1297. wndInit.rclClient.right = 0;
  1298. wndInit.rclClient.bottom = 0;
  1299. }
  1300. if (wndInit.gwid.hwnd)
  1301. {
  1302. // To be safe, at least clip bounds to screen.
  1303. if (bClipToScreen(&wndInit.rclBounds,
  1304. &wndInit.rclClient))
  1305. wndInit.clipComplexity = CLC_TRIVIAL;
  1306. else
  1307. wndInit.clipComplexity = CLC_RECT;
  1308. }
  1309. else
  1310. {
  1311. // Make bounds the same as client.
  1312. wndInit.rclBounds = wndInit.rclClient;
  1313. wndInit.clipComplexity = CLC_TRIVIAL;
  1314. }
  1315. pwnd = pwndNew(&wndInit);
  1316. if (pwnd == NULL)
  1317. {
  1318. WARNING("wglSetPixelFormat: Unable to allocate new window\n");
  1319. if ( wndInit.gwid.hwnd )
  1320. {
  1321. pwndUnsubclass(&wndInit, FALSE);
  1322. }
  1323. }
  1324. *pbNew = TRUE;
  1325. }
  1326. else
  1327. {
  1328. // If the given pixel format is the same as the previous one, return
  1329. // success. Otherwise, as the pixel format can be set only once,
  1330. // return error.
  1331. if ( pwnd->ipfd != ipfd )
  1332. {
  1333. WARNING("wglSetPixelFormat: Attempt to set pixel format twice\n");
  1334. SAVE_ERROR_CODE(ERROR_INVALID_PIXEL_FORMAT);
  1335. pwndRelease(pwnd);
  1336. pwnd = NULL;
  1337. }
  1338. *pbNew = FALSE;
  1339. }
  1340. return pwnd;
  1341. }
  1342. /******************************Public*Routine******************************\
  1343. * wglGetPixelFormat
  1344. *
  1345. * Get the pixel format for the window or surface associated with the given
  1346. * DC.
  1347. *
  1348. * Returns:
  1349. * 0 if error or no pixel format was previously set in the window or
  1350. * surface; current pixel format index otherwise
  1351. *
  1352. * History:
  1353. * 19-Oct-1994 -by- Gilman Wong [gilmanw]
  1354. * Wrote it.
  1355. \**************************************************************************/
  1356. int WINAPI wglGetPixelFormat(HDC hdc)
  1357. {
  1358. GLGENwindow *pwnd;
  1359. int iRet = 0;
  1360. GLWINDOWID gwid;
  1361. WindowIdFromHdc(hdc, &gwid);
  1362. pwnd = pwndGetFromID(&gwid);
  1363. if (pwnd)
  1364. {
  1365. iRet = pwnd->ipfd;
  1366. pwndRelease(pwnd);
  1367. }
  1368. else
  1369. {
  1370. #if 0
  1371. // Too noisy for normal operation
  1372. WARNING("wglGetPixelFormat: No window for DC\n");
  1373. #endif
  1374. SAVE_ERROR_CODE(ERROR_INVALID_PIXEL_FORMAT);
  1375. }
  1376. return iRet;
  1377. }
  1378. /*****************************Private*Routine******************************\
  1379. *
  1380. * EnterPixelFormatSection
  1381. *
  1382. * Enters pixel format exclusive code
  1383. *
  1384. * NOTE - Pixel format information is maintained in the client process
  1385. * so it is not synchronized between processes. This means that two
  1386. * processes could successfully set the pixel format for a window.
  1387. * If the list becomes global, this synchronization code should also become
  1388. * cross-process aware.
  1389. *
  1390. * History:
  1391. * Mon Jun 26 17:49:04 1995 -by- Drew Bliss [drewb]
  1392. * Created
  1393. *
  1394. \**************************************************************************/
  1395. #define EnterPixelFormatSection() \
  1396. (EnterCriticalSection(&gcsPixelFormat), TRUE)
  1397. /*****************************Private*Routine******************************\
  1398. *
  1399. * LeavePixelFormatSection
  1400. *
  1401. * Leaves pixel format exclusive code
  1402. *
  1403. * History:
  1404. * Mon Jun 26 17:55:20 1995 -by- Drew Bliss [drewb]
  1405. * Created
  1406. *
  1407. \**************************************************************************/
  1408. #define LeavePixelFormatSection() \
  1409. LeaveCriticalSection(&gcsPixelFormat)
  1410. /******************************Public*Routine******************************\
  1411. * wglNumHardwareFormats
  1412. *
  1413. * Returns the number of hardware formats (ICD and MCD), supported on the
  1414. * specified hdc.
  1415. *
  1416. * History:
  1417. * 17-Apr-1996 -by- Gilman Wong [gilmanw]
  1418. * Wrote it.
  1419. \**************************************************************************/
  1420. VOID APIENTRY wglNumHardwareFormats(HDC hdc, DWORD dwType,
  1421. int *piMcd, int *piIcd)
  1422. {
  1423. // It is assumed that the caller has already validated the DC.
  1424. ASSERTOPENGL((dwType == OBJ_DC) ||
  1425. (dwType == OBJ_MEMDC) ||
  1426. (dwType == OBJ_ENHMETADC) ||
  1427. (dwType == OBJ_DDRAW),
  1428. "wglNumHardwareFormats: bad hdc\n");
  1429. // Do not call MCD or ICD for enhanced metafile DCs. In such a
  1430. // case, the code in ntgdi\client\output.c will return a non-zero value
  1431. // even if there are no ICD or MCD pixelformats.
  1432. #if _WIN32_WINNT >= 0x0501
  1433. {
  1434. BOOL wow64Process;
  1435. if (IsWow64Process(GetCurrentProcess(), &wow64Process) && wow64Process)
  1436. dwType = OBJ_ENHMETADC;
  1437. }
  1438. #endif
  1439. if ( dwType == OBJ_ENHMETADC )
  1440. {
  1441. // It's a metafile DC. Therefore it cannot support MCD or ICD
  1442. // (current OpenGL metafiling support would have to be modified
  1443. // to allow this).
  1444. *piIcd = 0;
  1445. *piMcd = 0;
  1446. }
  1447. else
  1448. {
  1449. // Get ICD pixelformat count.
  1450. *piIcd = __DrvDescribePixelFormat(hdc, 1, 0, NULL);
  1451. // Get MCD pixelformat count.
  1452. #ifdef _MCD_
  1453. if ( gpMcdTable || bInitMcd(hdc) )
  1454. *piMcd = (gpMcdTable->pMCDDescribePixelFormat)(hdc, 1, NULL);
  1455. else
  1456. *piMcd = 0;
  1457. #else
  1458. *piMcd = 0;
  1459. #endif
  1460. }
  1461. }
  1462. /******************************Public*Routine******************************\
  1463. *
  1464. * GetCompatibleDevice
  1465. *
  1466. * Returns an HDC appropriate for making escape calls on.
  1467. * In the memdc case it returns a DC for the screen.
  1468. *
  1469. * History:
  1470. * Wed Nov 20 17:48:57 1996 -by- Drew Bliss [drewb]
  1471. * Created
  1472. *
  1473. \**************************************************************************/
  1474. HDC GetCompatibleDevice(HDC hdc, DWORD dwObjectType)
  1475. {
  1476. HDC hdcDriver;
  1477. int iTech;
  1478. hdcDriver = hdc;
  1479. iTech = GetDeviceCaps(hdc, TECHNOLOGY);
  1480. if ((dwObjectType == OBJ_MEMDC) && (iTech != DT_PLOTTER) &&
  1481. (iTech != DT_RASPRINTER))
  1482. {
  1483. hdcDriver = GetDC(NULL);
  1484. }
  1485. return hdcDriver;
  1486. }
  1487. /******************************Public*Routine******************************\
  1488. * wglSetPixelFormat
  1489. *
  1490. * Set the pixel format for the window or surface associated with the given
  1491. * DC.
  1492. *
  1493. * Note:
  1494. * Since the pixel format is per-window data (per-DC for non-display DCs), a
  1495. * side effect of this call is to create a GLGENwindow structure.
  1496. *
  1497. * Note:
  1498. * For an installable client driver, a GLGENwindow structure is still created
  1499. * to track the pixel format and the driver structure (GLDRIVER).
  1500. *
  1501. * History:
  1502. * 19-Oct-1994 -by- Gilman Wong [gilmanw]
  1503. * Wrote it.
  1504. \**************************************************************************/
  1505. BOOL WINAPI wglSetPixelFormat(HDC hdc, int ipfd,
  1506. CONST PIXELFORMATDESCRIPTOR *ppfd)
  1507. {
  1508. GLGENwindow *pwnd = NULL;
  1509. int ipfdDevMax, ipfdMcdMax;
  1510. DWORD dwObjectType;
  1511. BOOL bRet = FALSE;
  1512. GLWINDOWID gwid;
  1513. BOOL bNew;
  1514. HDC hdcDriver;
  1515. LPDIRECTDRAWSURFACE pdds;
  1516. RECTL rcl, *prcl;
  1517. DDSURFACEDESC ddsd;
  1518. //DBGPRINT1("wglSetPixelFormat: ipfd = %ld\n", ipfd);
  1519. // Validate DC.
  1520. switch (dwObjectType = wglObjectType(hdc))
  1521. {
  1522. case OBJ_DC:
  1523. case OBJ_MEMDC:
  1524. case OBJ_ENHMETADC:
  1525. break;
  1526. default:
  1527. WARNING1("wglSetPixelFormat: Attempt to set format of %d type DC\n",
  1528. dwObjectType);
  1529. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  1530. return(FALSE);
  1531. }
  1532. // Take the pixel format mutex
  1533. if (!EnterPixelFormatSection())
  1534. {
  1535. WARNING("wglSetPixelFormat: Unable to take pixel format mutex\n");
  1536. return FALSE;
  1537. }
  1538. // Get the number of hardware supported formats.
  1539. if (pfnGetSurfaceFromDC != NULL &&
  1540. pfnGetSurfaceFromDC(hdc, &pdds, &hdcDriver) == DD_OK)
  1541. {
  1542. // Get the surface dimensions
  1543. memset(&ddsd, 0, sizeof(ddsd));
  1544. ddsd.dwSize = sizeof(ddsd);
  1545. if (pdds->lpVtbl->GetSurfaceDesc(pdds, &ddsd) != DD_OK)
  1546. {
  1547. goto LeaveSection;
  1548. }
  1549. rcl.left = 0;
  1550. rcl.top = 0;
  1551. rcl.right = ddsd.dwWidth;
  1552. rcl.bottom = ddsd.dwHeight;
  1553. prcl = &rcl;
  1554. // Switch object type to identify this as a DirectDraw surface
  1555. dwObjectType = OBJ_DDRAW;
  1556. }
  1557. else
  1558. {
  1559. pdds = NULL;
  1560. prcl = NULL;
  1561. hdcDriver = GetCompatibleDevice(hdc, dwObjectType);
  1562. if (hdcDriver == NULL)
  1563. {
  1564. goto LeaveSection;
  1565. }
  1566. }
  1567. wglNumHardwareFormats(hdcDriver, dwObjectType,
  1568. &ipfdMcdMax, &ipfdDevMax);
  1569. // Filter out invalid (out of range) pixel format indices.
  1570. if ( (ipfd < 1) || (ipfd > (ipfdDevMax + ipfdMcdMax + MAX_GENERIC_PFD)) )
  1571. {
  1572. WARNING1("wglSetPixelFormat: ipfd %d out of range\n", ipfd);
  1573. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1574. goto LeaveSection;
  1575. }
  1576. // If it exists, grab pwnd. Otherwise, create one.
  1577. WindowIdFromHdc(hdc, &gwid);
  1578. pwnd = CreatePwnd(&gwid, ipfd, ipfdDevMax, dwObjectType, prcl, &bNew);
  1579. if (pwnd == NULL)
  1580. {
  1581. goto LeaveSection;
  1582. }
  1583. if (bNew)
  1584. {
  1585. // Dispatch driver formats.
  1586. // Driver is responsible for doing its own validation of the pixelformat.
  1587. // For generic formats, we call wglValidPixelFormat to validate.
  1588. // We do not send DirectDraw pixel format calls to the driver
  1589. // so that we avoid having new pixel format calls.
  1590. if (dwObjectType != OBJ_DDRAW && ipfd <= ipfdDevMax)
  1591. {
  1592. bRet = __DrvSetPixelFormat(hdc, ipfd, (PVOID) pwnd);
  1593. #if DBG
  1594. if (!bRet)
  1595. {
  1596. WARNING("__DrvSetPixelFormat failed\n");
  1597. }
  1598. #endif
  1599. }
  1600. else
  1601. {
  1602. bRet = wglValidPixelFormat(hdc, ipfd, dwObjectType,
  1603. pdds, &ddsd);
  1604. #if DBG
  1605. if (!bRet)
  1606. {
  1607. WARNING("wglValidPixelFormat failed\n");
  1608. }
  1609. #endif
  1610. }
  1611. // If the pixel format is not valid or could not be set in the driver,
  1612. // cleanup and return error.
  1613. if (!bRet)
  1614. {
  1615. goto FreeWnd;
  1616. }
  1617. }
  1618. else
  1619. {
  1620. bRet = TRUE;
  1621. }
  1622. pwndRelease(pwnd);
  1623. LeaveSection:
  1624. LeavePixelFormatSection();
  1625. if (pdds != NULL)
  1626. {
  1627. pdds->lpVtbl->Release(pdds);
  1628. }
  1629. else if (hdcDriver != hdc)
  1630. {
  1631. ReleaseDC((HWND) NULL, hdcDriver);
  1632. }
  1633. return bRet;
  1634. FreeWnd:
  1635. pwndCleanup(pwnd);
  1636. goto LeaveSection;
  1637. }
  1638. /******************************Public*Routine******************************\
  1639. * wglChoosePixelFormat
  1640. *
  1641. * Choose the pixel format.
  1642. *
  1643. * Returns: 0 if error; best matching pixel format index otherwise
  1644. *
  1645. * History:
  1646. *
  1647. * Sat Feb 10 11:55:22 1996 -by- Hock San Lee [hockl]
  1648. * Chose generic 16-bit depth buffer over 32-bit depth buffer.
  1649. * Added PFD_DEPTH_DONTCARE flag.
  1650. *
  1651. * 19-Oct-1994 Gilman Wong [gilmanw]
  1652. * Taken from GreChoosePixelFormat (gdi\gre\pixelfmt.cxx).
  1653. *
  1654. * History for gdi\gre\pixelfmt.cxx:
  1655. * Tue Sep 21 14:25:04 1993 -by- Hock San Lee [hockl]
  1656. * Wrote it.
  1657. \**************************************************************************/
  1658. // Reserve some PFD_SUPPORT flags for other potential graphics systems
  1659. // such as PEX, HOOPS, Renderman etc.
  1660. #define PFD_SUPPORT_OTHER1 0x01000000
  1661. #define PFD_SUPPORT_OTHER2 0x02000000
  1662. #define PFD_SUPPORT_OTHER3 0x04000000
  1663. #define PFD_SUPPORT_OTHER4 0x08000000
  1664. // Scores for matching pixel formats
  1665. #define PFD_DRAW_TO_WINDOW_SCORE 0x10000 /* must match */
  1666. #define PFD_DRAW_TO_BITMAP_SCORE 0x01000
  1667. #define PFD_PIXEL_TYPE_SCORE 0x01000
  1668. #define PFD_SUPPORT_SCORE 0x01000
  1669. #define PFD_DOUBLEBUFFER_SCORE1 0x01000
  1670. #define PFD_DOUBLEBUFFER_SCORE2 0x00001
  1671. #define PFD_STEREO_SCORE1 0x01000
  1672. #define PFD_STEREO_SCORE2 0x00001
  1673. #define PFD_BUFFER_SCORE1 0x01010
  1674. #define PFD_BUFFER_SCORE2 0x01001
  1675. #define PFD_BUFFER_SCORE3 0x01000
  1676. // #define PFD_LAYER_TYPE_SCORE 0x01000
  1677. #define PFD_DEVICE_FORMAT_SCORE 0x00100
  1678. #define PFD_ACCEL_FORMAT_SCORE 0x00010
  1679. #define PFD_SUPPORT_DDRAW_SCORE 0x10000 /* must match */
  1680. //!!! Add code to choose overlays?
  1681. int WINAPI wglChoosePixelFormat(HDC hdc, CONST PIXELFORMATDESCRIPTOR *ppfd)
  1682. {
  1683. PIXELFORMATDESCRIPTOR pfdIn = *ppfd;
  1684. PIXELFORMATDESCRIPTOR pfdCurrent;
  1685. // Enumerate and find the best match.
  1686. int ipfdBest = 1; // assume the default is the best
  1687. int iScoreBest = -1;
  1688. int ipfdMax;
  1689. int ipfd = 1;
  1690. do
  1691. {
  1692. int iScore = 0;
  1693. ipfdMax = wglDescribePixelFormat(hdc,ipfd,sizeof(PIXELFORMATDESCRIPTOR),&pfdCurrent);
  1694. if (ipfdMax == 0)
  1695. return(0); // something went wrong
  1696. if (pfdIn.iPixelType == pfdCurrent.iPixelType)
  1697. iScore += PFD_PIXEL_TYPE_SCORE;
  1698. if ((pfdIn.cColorBits == 0)
  1699. || (pfdIn.cColorBits == pfdCurrent.cColorBits))
  1700. iScore += PFD_BUFFER_SCORE1;
  1701. else if (pfdIn.cColorBits < pfdCurrent.cColorBits)
  1702. iScore += PFD_BUFFER_SCORE2;
  1703. else if (pfdCurrent.cColorBits != 0)
  1704. iScore += PFD_BUFFER_SCORE3;
  1705. if (!(pfdIn.dwFlags & PFD_DRAW_TO_WINDOW)
  1706. || (pfdCurrent.dwFlags & PFD_DRAW_TO_WINDOW))
  1707. iScore += PFD_DRAW_TO_WINDOW_SCORE;
  1708. if (!(pfdIn.dwFlags & PFD_DRAW_TO_BITMAP)
  1709. || (pfdCurrent.dwFlags & PFD_DRAW_TO_BITMAP))
  1710. iScore += PFD_DRAW_TO_BITMAP_SCORE;
  1711. if (!(pfdIn.dwFlags & PFD_SUPPORT_GDI)
  1712. || (pfdCurrent.dwFlags & PFD_SUPPORT_GDI))
  1713. iScore += PFD_SUPPORT_SCORE;
  1714. if (!(pfdIn.dwFlags & PFD_SUPPORT_OPENGL)
  1715. || (pfdCurrent.dwFlags & PFD_SUPPORT_OPENGL))
  1716. iScore += PFD_SUPPORT_SCORE;
  1717. if ((pfdIn.dwFlags & PFD_SUPPORT_DIRECTDRAW) == 0 ||
  1718. (pfdCurrent.dwFlags & PFD_SUPPORT_DIRECTDRAW))
  1719. {
  1720. iScore += PFD_SUPPORT_DDRAW_SCORE;
  1721. }
  1722. if (!(pfdIn.dwFlags & PFD_SUPPORT_OTHER1)
  1723. || (pfdCurrent.dwFlags & PFD_SUPPORT_OTHER1))
  1724. iScore += PFD_SUPPORT_SCORE;
  1725. if (!(pfdIn.dwFlags & PFD_SUPPORT_OTHER2)
  1726. || (pfdCurrent.dwFlags & PFD_SUPPORT_OTHER2))
  1727. iScore += PFD_SUPPORT_SCORE;
  1728. if (!(pfdIn.dwFlags & PFD_SUPPORT_OTHER3)
  1729. || (pfdCurrent.dwFlags & PFD_SUPPORT_OTHER3))
  1730. iScore += PFD_SUPPORT_SCORE;
  1731. if (!(pfdIn.dwFlags & PFD_SUPPORT_OTHER4)
  1732. || (pfdCurrent.dwFlags & PFD_SUPPORT_OTHER4))
  1733. iScore += PFD_SUPPORT_SCORE;
  1734. if (pfdCurrent.dwFlags & PFD_GENERIC_ACCELERATED)
  1735. iScore += PFD_ACCEL_FORMAT_SCORE;
  1736. else if (!(pfdCurrent.dwFlags & PFD_GENERIC_FORMAT))
  1737. iScore += PFD_DEVICE_FORMAT_SCORE;
  1738. if ((pfdIn.dwFlags & PFD_DOUBLEBUFFER_DONTCARE)
  1739. || ((pfdIn.dwFlags & PFD_DOUBLEBUFFER)
  1740. == (pfdCurrent.dwFlags & PFD_DOUBLEBUFFER)))
  1741. iScore += PFD_DOUBLEBUFFER_SCORE1;
  1742. else if (pfdCurrent.dwFlags & PFD_DOUBLEBUFFER)
  1743. iScore += PFD_DOUBLEBUFFER_SCORE2;
  1744. if ((pfdIn.dwFlags & PFD_STEREO_DONTCARE)
  1745. || ((pfdIn.dwFlags & PFD_STEREO)
  1746. == (pfdCurrent.dwFlags & PFD_STEREO)))
  1747. iScore += PFD_STEREO_SCORE1;
  1748. else if (pfdCurrent.dwFlags & PFD_STEREO)
  1749. iScore += PFD_STEREO_SCORE2;
  1750. if ((pfdIn.cAlphaBits == 0)
  1751. || (pfdIn.cAlphaBits == pfdCurrent.cAlphaBits))
  1752. iScore += PFD_BUFFER_SCORE1;
  1753. else if (pfdIn.cAlphaBits < pfdCurrent.cAlphaBits)
  1754. iScore += PFD_BUFFER_SCORE2;
  1755. else if (pfdCurrent.cAlphaBits != 0)
  1756. iScore += PFD_BUFFER_SCORE3;
  1757. if ((pfdIn.cAccumBits == 0)
  1758. || (pfdIn.cAccumBits == pfdCurrent.cAccumBits))
  1759. iScore += PFD_BUFFER_SCORE1;
  1760. else if (pfdIn.cAccumBits < pfdCurrent.cAccumBits)
  1761. iScore += PFD_BUFFER_SCORE2;
  1762. else if (pfdCurrent.cAccumBits != 0)
  1763. iScore += PFD_BUFFER_SCORE3;
  1764. // Some applications (e.g. GLview browser) specifies a 0-bit depth buffer
  1765. // but expect this function to return a pixel format with a depth buffer.
  1766. // This works in NT 3.51 since all pixel formats have a depth buffer.
  1767. // When pixel formats with no depth buffer were added in NT 4.0, these
  1768. // applications stopped working. The flag PFD_DEPTH_DONTCARE is added to
  1769. // indicate that no depth buffer is required. If this flags is not given,
  1770. // this function will attempt to select a pixel format with a depth buffer.
  1771. if (pfdIn.dwFlags & PFD_DEPTH_DONTCARE)
  1772. {
  1773. if (pfdCurrent.cDepthBits == 0)
  1774. iScore += PFD_BUFFER_SCORE1;
  1775. else
  1776. iScore += PFD_BUFFER_SCORE2;
  1777. }
  1778. else if (pfdCurrent.cDepthBits != 0)
  1779. {
  1780. if ((pfdIn.cDepthBits == 0)
  1781. || (pfdIn.cDepthBits == pfdCurrent.cDepthBits))
  1782. iScore += PFD_BUFFER_SCORE1;
  1783. else if (pfdIn.cDepthBits < pfdCurrent.cDepthBits)
  1784. iScore += PFD_BUFFER_SCORE2;
  1785. else if (pfdCurrent.cDepthBits != 0)
  1786. iScore += PFD_BUFFER_SCORE3;
  1787. }
  1788. if ((pfdIn.cStencilBits == 0)
  1789. || (pfdIn.cStencilBits == pfdCurrent.cStencilBits))
  1790. iScore += PFD_BUFFER_SCORE1;
  1791. else if (pfdIn.cStencilBits < pfdCurrent.cStencilBits)
  1792. iScore += PFD_BUFFER_SCORE2;
  1793. else if (pfdCurrent.cStencilBits != 0)
  1794. iScore += PFD_BUFFER_SCORE3;
  1795. if ((pfdIn.cAuxBuffers == 0)
  1796. || (pfdIn.cAuxBuffers == pfdCurrent.cAuxBuffers))
  1797. iScore += PFD_BUFFER_SCORE1;
  1798. else if (pfdIn.cAuxBuffers < pfdCurrent.cAuxBuffers)
  1799. iScore += PFD_BUFFER_SCORE2;
  1800. else if (pfdCurrent.cAuxBuffers != 0)
  1801. iScore += PFD_BUFFER_SCORE3;
  1802. #if 0
  1803. DbgPrint("%2d: score is %8X, best %8X (%2d)\n",
  1804. ipfd, iScore, iScoreBest, ipfdBest);
  1805. #endif
  1806. if (iScore > iScoreBest)
  1807. {
  1808. iScoreBest = iScore;
  1809. ipfdBest = ipfd;
  1810. }
  1811. else if (iScore == iScoreBest)
  1812. {
  1813. // When everything is equal, we should choose the pixel format with a
  1814. // smaller depth size for better performance, provided that the smaller
  1815. // depth buffer satisfies the request. The best way to do this is to
  1816. // order pixel formats such that one with smaller depth buffer comes
  1817. // first. In NT 3.51, however, the generic pixel format was not ordered
  1818. // this way. As a result, pixel formats with 32-bit depth buffer are
  1819. // choosen by default. To maintain compatibility, we modify the selection
  1820. // here without reordering generic pixel formats.
  1821. if ((pfdCurrent.dwFlags & PFD_GENERIC_FORMAT) &&
  1822. #ifdef _MCD_
  1823. !(pfdCurrent.dwFlags & PFD_GENERIC_ACCELERATED) &&
  1824. #endif
  1825. (pfdIn.cDepthBits < 16 || pfdIn.dwFlags & PFD_DEPTH_DONTCARE) &&
  1826. (pfdCurrent.cDepthBits == 16) &&
  1827. (ipfd == ipfdBest + 1))
  1828. {
  1829. ipfdBest = ipfd;
  1830. }
  1831. }
  1832. ipfd++;
  1833. } while (ipfd <= ipfdMax);
  1834. return(ipfdBest);
  1835. }
  1836. /******************************Public*Routine******************************\
  1837. *
  1838. * MaskToBitsAndShift
  1839. *
  1840. * Counts bits in a mask and determines shift
  1841. * Set bits must be contiguous
  1842. *
  1843. * History:
  1844. * Mon Aug 26 14:16:28 1996 -by- Drew Bliss [drewb]
  1845. * Created
  1846. *
  1847. \**************************************************************************/
  1848. void APIENTRY MaskToBitsAndShift(DWORD dwMask, BYTE *pbBits, BYTE *pbShift)
  1849. {
  1850. DWORD dwBit;
  1851. *pbBits = 0;
  1852. *pbShift = 0;
  1853. /* Determine first set bit and accumulate shift count */
  1854. dwBit = 0x1;
  1855. while ((dwMask & dwBit) == 0)
  1856. {
  1857. dwBit <<= 1;
  1858. (*pbShift)++;
  1859. }
  1860. /* Count set bits */
  1861. while ((dwMask & dwBit) != 0)
  1862. {
  1863. dwBit <<= 1;
  1864. (*pbBits)++;
  1865. }
  1866. /* No other bits in the mask can be set */
  1867. ASSERTOPENGL(((*pbBits+*pbShift) == (sizeof(dwMask)*8)) ||
  1868. ((dwMask >> (*pbBits+*pbShift)) == 0),
  1869. "Invalid mask\n");
  1870. }
  1871. /*****************************Private*Routine******************************\
  1872. *
  1873. * ComputeBitsFromMasks
  1874. *
  1875. * Determines the values for c*Bits and c*Shift from BI_BITFIELD
  1876. * channel masks
  1877. *
  1878. * History:
  1879. * Tue Feb 14 10:50:10 1995 -by- Drew Bliss [drewb]
  1880. * Created by pulling out duplicated code
  1881. *
  1882. \**************************************************************************/
  1883. static void ComputeBitsFromMasks(PIXELFORMATDESCRIPTOR *ppfd,
  1884. DWORD dwRedMask, DWORD dwGreenMask,
  1885. DWORD dwBlueMask)
  1886. {
  1887. /* Masks can't be zero and they can't overlap */
  1888. ASSERTOPENGL(dwRedMask != 0 &&
  1889. dwGreenMask != 0 &&
  1890. dwBlueMask != 0,
  1891. "Bitfield mask is zero");
  1892. ASSERTOPENGL((dwRedMask & dwGreenMask) == 0 &&
  1893. (dwRedMask & dwBlueMask) == 0 &&
  1894. (dwGreenMask & dwBlueMask) == 0,
  1895. "Bitfield masks overlap");
  1896. MaskToBitsAndShift(dwRedMask, &ppfd->cRedBits, &ppfd->cRedShift);
  1897. MaskToBitsAndShift(dwGreenMask, &ppfd->cGreenBits, &ppfd->cGreenShift);
  1898. MaskToBitsAndShift(dwBlueMask, &ppfd->cBlueBits, &ppfd->cBlueShift);
  1899. }
  1900. /******************************Public*Routine******************************\
  1901. * __wglGetDdFormat
  1902. *
  1903. * Special case of __wglGetBitfieldColorFormat to support DirectDraw
  1904. * surfaces. Fills in the cRedBits, cRedShift, cGreenBits, etc. fields
  1905. * of the PIXELFORMATDESCRIPTOR for 16, 24, and 32bpp direct surfaces.
  1906. *
  1907. * This is done by interpreting the given surface information
  1908. *
  1909. * History:
  1910. * 07-Jun-1995 -by- Gilman Wong [gilmanw]
  1911. * Wrote it.
  1912. \**************************************************************************/
  1913. void __wglGetDdFormat(DDSURFACEDESC *pddsd,
  1914. PIXELFORMATDESCRIPTOR *ppfd)
  1915. {
  1916. // This routine should only be called for bitfield formats, but
  1917. // random mode changes in the middle of certain calls could cause
  1918. // it to be called with non-bitfield formats.
  1919. //
  1920. // When such a mode change occurs OpenGL should not crash but
  1921. // does not necessarily have to produce correct output
  1922. if ((pddsd->ddpfPixelFormat.dwFlags & DDPF_RGB) == 0 ||
  1923. (pddsd->ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 |
  1924. DDPF_PALETTEINDEXED2 |
  1925. DDPF_PALETTEINDEXED4 |
  1926. DDPF_PALETTEINDEXED8)))
  1927. {
  1928. WARNING1("__wglGetDdFormat called with 0x%08lX ddpf flags\n",
  1929. pddsd->ddpfPixelFormat.dwFlags);
  1930. ppfd->cRedBits = 8;
  1931. ppfd->cRedShift = 0;
  1932. ppfd->cGreenBits = 8;
  1933. ppfd->cGreenShift = 0;
  1934. ppfd->cBlueBits = 8;
  1935. ppfd->cBlueShift = 0;
  1936. }
  1937. else
  1938. {
  1939. ComputeBitsFromMasks(ppfd,
  1940. pddsd->ddpfPixelFormat.dwRBitMask,
  1941. pddsd->ddpfPixelFormat.dwGBitMask,
  1942. pddsd->ddpfPixelFormat.dwBBitMask);
  1943. }
  1944. }
  1945. /******************************Public*Routine******************************\
  1946. * __wglGetBitfieldColorFormat
  1947. *
  1948. * Fills in the cRedBits, cRedShift, cGreenBits, etc. fields of the
  1949. * PIXELFORMATDESCRIPTOR for 16, 24, and 32bpp surfaces (either device
  1950. * or bitmap surfaces).
  1951. *
  1952. * This is done by creating a compatible bitmap and calling GetDIBits
  1953. * to return the color masks. This is done with two calls. The first
  1954. * call passes in biBitCount = 0 to GetDIBits which will fill in the
  1955. * base BITMAPINFOHEADER data. The second call to GetDIBits (passing
  1956. * in the BITMAPINFO filled in by the first call) will return the color
  1957. * table or bitmasks, as appropriate.
  1958. *
  1959. * This function is used to describe the color format for both the underlying
  1960. * surface and for the device. This is the same thing if the DC is a
  1961. * display DC. However, for a memory DC, the surface and the device may have
  1962. * different formats. The bDescribeSurf flag indicates whether the caller
  1963. * wants the decription of the device (FALSE) or the surface (TRUE).
  1964. *
  1965. * Returns:
  1966. * TRUE if successful, FALSE otherwise.
  1967. *
  1968. * History:
  1969. * 07-Jun-1995 -by- Gilman Wong [gilmanw]
  1970. * Wrote it.
  1971. \**************************************************************************/
  1972. BOOL APIENTRY
  1973. __wglGetBitfieldColorFormat(HDC hdc, UINT cColorBits, PIXELFORMATDESCRIPTOR *ppfd,
  1974. BOOL bDescribeSurf)
  1975. {
  1976. HBITMAP hbm = (HBITMAP) NULL;
  1977. BOOL bRet = FALSE;
  1978. HDC hdcDriver;
  1979. #if DBG
  1980. // Dynamic color depth changes can cause this. It will not cause us to crash,
  1981. // but drawing (color) may be incorrect.
  1982. if ((GetObjectType(hdc) == OBJ_DC) &&
  1983. (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE))
  1984. {
  1985. WARNING("Palette managed device that is greater than 8 bits\n");
  1986. }
  1987. if (cColorBits < 16)
  1988. {
  1989. WARNING("__wglGetBitfieldColorFormat with cColorBits < 16\n");
  1990. }
  1991. #endif
  1992. // Handle direct case.
  1993. if ( GLDIRECTSCREEN && wglIsDirectDevice(hdc) )
  1994. {
  1995. __wglGetDdFormat(&GLSCREENINFO->gdds.ddsd, ppfd);
  1996. return TRUE;
  1997. }
  1998. // Create a dummy bitmap from which we can query color format info.
  1999. //
  2000. // If we want a device format AND its a MEM_DC AND NOT a printer or plotter,
  2001. // then we need to create a compatible bitmap from a display DC (not the mem
  2002. // DC passed into this function).
  2003. //
  2004. // Otherwise, the format of the surface (whether bitmap or device) associated
  2005. // with the DC passed in will suffice.
  2006. //
  2007. // WinNT does not care, but the Win95 GetDIBits call might
  2008. // fail if we use a memory DC. Specifically, if the memory
  2009. // DC contains a surface that does not match the display
  2010. // (remember, the new bitmap is compatible with the display)
  2011. // the Win95 GetDIBits call will fail.
  2012. //
  2013. // So use the display DC. It works on both platforms.
  2014. if (!bDescribeSurf)
  2015. {
  2016. hdcDriver = GetCompatibleDevice(hdc, GetObjectType(hdc));
  2017. if (hdcDriver == NULL)
  2018. {
  2019. return FALSE;
  2020. }
  2021. }
  2022. else
  2023. {
  2024. hdcDriver = hdc;
  2025. }
  2026. hbm = CreateCompatibleBitmap(hdcDriver, 1, 1);
  2027. if ( !hbm )
  2028. {
  2029. WARNING("__wglGetBitfieldColorFormat: "
  2030. "CreateCompatibleBitmap failed\n");
  2031. }
  2032. // Get the color format by calling GetDIBits.
  2033. else
  2034. {
  2035. BYTE ajBitmapInfo[sizeof(BITMAPINFO) + 3*sizeof(DWORD)];
  2036. BITMAPINFO *pbmi = (BITMAPINFO *) ajBitmapInfo;
  2037. int iRet;
  2038. //!!!dbug -- Init masks to zero so we can
  2039. // tell if they are set by GetDIBits.
  2040. memset(pbmi, 0, sizeof(ajBitmapInfo));
  2041. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  2042. // Call first time to fill in BITMAPINFO header.
  2043. iRet = GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS);
  2044. #if DBG
  2045. if (pbmi->bmiHeader.biBitCount != cColorBits)
  2046. WARNING2("__wglGetBitfieldColorFormat: bit count != BITSPIXEL "
  2047. " (%ld, %ld)\n", pbmi->bmiHeader.biBitCount, cColorBits);
  2048. #endif
  2049. switch ( pbmi->bmiHeader.biCompression )
  2050. {
  2051. case BI_RGB:
  2052. #if DBG
  2053. // Dynamic color depth changes can cause this. It will not cause
  2054. // us to crash, but drawing (color) may be incorrect.
  2055. if (pbmi->bmiHeader.biBitCount != cColorBits)
  2056. {
  2057. WARNING("__wglGetBitfieldColorFormat(): bit count mismatch\n");
  2058. }
  2059. #endif
  2060. // Default DIB format. Color masks are implicit for each bit depth.
  2061. switch ( pbmi->bmiHeader.biBitCount )
  2062. {
  2063. case 16:
  2064. // 16bpp default is 555 BGR-ordering
  2065. ppfd->cRedBits = 5; ppfd->cRedShift = 10;
  2066. ppfd->cGreenBits = 5; ppfd->cGreenShift = 5;
  2067. ppfd->cBlueBits = 5; ppfd->cBlueShift = 0;
  2068. bRet = TRUE;
  2069. break;
  2070. case 24:
  2071. case 32:
  2072. // 24 and 32bpp default is 888 BGR-ordering
  2073. ppfd->cRedBits = 8; ppfd->cRedShift = 16;
  2074. ppfd->cGreenBits = 8; ppfd->cGreenShift = 8;
  2075. ppfd->cBlueBits = 8; ppfd->cBlueShift = 0;
  2076. bRet = TRUE;
  2077. break;
  2078. default:
  2079. break;
  2080. }
  2081. break;
  2082. case BI_BITFIELDS:
  2083. // Some drivers seem to return bitfields for everything that's
  2084. // not paletted. They return correct BGR bitfields so we
  2085. // operate correctly, so remove this assert
  2086. #ifdef STRICT_BITFIELD_CHECK
  2087. ASSERTOPENGL(
  2088. cColorBits == 16 || cColorBits == 32,
  2089. "__wglGetBitfieldColorFormat(): "
  2090. "BI_BITFIELDS surface not 16 or 32bpp\n"
  2091. );
  2092. #endif
  2093. // Call a second time to get the color masks.
  2094. // It's a GetDIBits Win32 "feature".
  2095. iRet = GetDIBits(hdc, hbm, 0, pbmi->bmiHeader.biHeight, NULL,
  2096. pbmi, DIB_RGB_COLORS);
  2097. ComputeBitsFromMasks(ppfd,
  2098. *(DWORD *)&pbmi->bmiColors[0],
  2099. *(DWORD *)&pbmi->bmiColors[1],
  2100. *(DWORD *)&pbmi->bmiColors[2]);
  2101. bRet = TRUE;
  2102. break;
  2103. default:
  2104. RIP("__wglGetBitfieldColorFormat(): bad biCompression\n");
  2105. break;
  2106. }
  2107. DeleteObject(hbm);
  2108. }
  2109. if ( hdcDriver != hdc )
  2110. {
  2111. ReleaseDC((HWND) NULL, hdcDriver);
  2112. }
  2113. return bRet;
  2114. }
  2115. /******************************Public*Routine******************************\
  2116. *
  2117. * wglGetDeviceDepth
  2118. *
  2119. * Returns the depth of the given HDC
  2120. * Primarily used to workaround potential problems with printers
  2121. * that lie about their depth in GetDeviceCaps
  2122. *
  2123. * History:
  2124. * Tue Apr 09 16:52:47 1996 -by- Drew Bliss [drewb]
  2125. * Created
  2126. *
  2127. \**************************************************************************/
  2128. int wglGetDeviceDepth(HDC hdc)
  2129. {
  2130. int iTech;
  2131. // If this is an enhanced metafile it should return the technology
  2132. // of the reference device
  2133. iTech = GetDeviceCaps(hdc, TECHNOLOGY);
  2134. if (iTech == DT_PLOTTER || iTech == DT_RASPRINTER)
  2135. {
  2136. HBITMAP hbm;
  2137. BYTE ajBitmapInfo[sizeof(BITMAPINFO) + 3*sizeof(DWORD)];
  2138. BITMAPINFO *pbmi = (BITMAPINFO *) ajBitmapInfo;
  2139. int iRet;
  2140. // We're dealing with a printer or a metafile that has a printer
  2141. // as a reference device
  2142. // Find out the true depth by creating a compatible
  2143. // bitmap and querying its format
  2144. if ( (hbm = CreateCompatibleBitmap(hdc, 1, 1)) != NULL )
  2145. {
  2146. memset(pbmi, 0, sizeof(ajBitmapInfo));
  2147. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  2148. iRet = GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS);
  2149. DeleteObject(hbm);
  2150. return iRet != 0 ? pbmi->bmiHeader.biBitCount : -1;
  2151. }
  2152. // Failure
  2153. return -1;
  2154. }
  2155. else
  2156. {
  2157. // We're dealing with a well-behaved DC so just return
  2158. // the normal depth
  2159. return GetDeviceCaps(hdc, BITSPIXEL)*GetDeviceCaps(hdc, PLANES);
  2160. }
  2161. }
  2162. /******************************Public*Routine******************************\
  2163. * wglDescribePixelFormat
  2164. *
  2165. * Describe the pixel format.
  2166. * If cjpfd is 0, just return the maximum pixel format index.
  2167. *
  2168. * Returns: 0 if error; maximum pixel format index otherwise
  2169. *
  2170. * History:
  2171. * 19-Oct-1994 Gilman Wong [gilmanw]
  2172. * Adapted from GreDescribePixelFormat (gdi\gre\pixelfmt.cxx).
  2173. *
  2174. * History for gdi\gre\pixelfmt.cxx:
  2175. * Mon Apr 25 15:34:32 1994 -by- Hock San Lee [hockl]
  2176. * Added 16-bit Z buffer formats and removed double buffered formats for bitmaps.
  2177. * Tue Sep 21 14:25:04 1993 -by- Hock San Lee [hockl]
  2178. * Wrote it.
  2179. \**************************************************************************/
  2180. // Here are the generic formats that we enumerate. ChoosePixelFormat code
  2181. // assumes that generic pixel formats with z32 comes before z16 as given below:
  2182. //
  2183. // I. Native formats:
  2184. //
  2185. // 1. rgb.sb.z32.a0
  2186. // 2. rgb.sb.z16.a0
  2187. // 3. rgb.db.z32.a0
  2188. // 4. rgb.db.z16.a0
  2189. // 5. rgb.sb.z32.a8
  2190. // 6. rgb.sb.z16.a8
  2191. // 7. rgb.db.z32.a8
  2192. // 8. rgb.db.z16.a8
  2193. // 9. ci.sb.z32
  2194. // 10. ci.sb.z16
  2195. // 11. ci.db.z32
  2196. // 12. ci.db.z16
  2197. //
  2198. // II. Other formats:
  2199. //
  2200. // 1. rgb.sb.z32.a0
  2201. // 2. rgb.sb.z16.a0
  2202. // 3. rgb.sb.z32.a8
  2203. // 4. rgb.sb.z16.a8
  2204. // 5. ci.sb.z32
  2205. // 6. ci.sb.z16
  2206. //
  2207. // We always enumerate the native formats first followed by other formats
  2208. // in the BPP order {24, 32, 16, 8, 4} for a total of 1 * 12 + 4 * 6 = 36
  2209. // pixel formats.
  2210. // Highest native format generic pixel format index.
  2211. #define MAX_NATIVE_GENERIC_PFD 12
  2212. // Number of non-native formats in a non-native group.
  2213. #define NON_NATIVE_PFD_GROUP 6
  2214. static BYTE aabPixelBits[BMF_COUNT][4] =
  2215. {
  2216. {24, 32, 16, 8}, // error
  2217. {24, 32, 16, 8}, // 1 bpp
  2218. {24, 32, 16, 8}, // 4 bpp
  2219. {24, 32, 16, 4}, // 8 bpp
  2220. {24, 32, 8, 4}, // 16 bpp
  2221. {32, 16, 8, 4}, // 24 bpp
  2222. {24, 16, 8, 4} // 32 bpp
  2223. };
  2224. static BYTE abPixelType[MAX_GENERIC_PFD] =
  2225. {
  2226. PFD_TYPE_RGBA, PFD_TYPE_RGBA, PFD_TYPE_RGBA, PFD_TYPE_RGBA,
  2227. PFD_TYPE_RGBA, PFD_TYPE_RGBA, PFD_TYPE_RGBA, PFD_TYPE_RGBA,
  2228. PFD_TYPE_COLORINDEX,PFD_TYPE_COLORINDEX, PFD_TYPE_COLORINDEX,PFD_TYPE_COLORINDEX,
  2229. PFD_TYPE_RGBA, PFD_TYPE_RGBA, PFD_TYPE_RGBA, PFD_TYPE_RGBA,
  2230. PFD_TYPE_COLORINDEX, PFD_TYPE_COLORINDEX,
  2231. PFD_TYPE_RGBA, PFD_TYPE_RGBA, PFD_TYPE_RGBA, PFD_TYPE_RGBA,
  2232. PFD_TYPE_COLORINDEX, PFD_TYPE_COLORINDEX,
  2233. PFD_TYPE_RGBA, PFD_TYPE_RGBA, PFD_TYPE_RGBA, PFD_TYPE_RGBA,
  2234. PFD_TYPE_COLORINDEX, PFD_TYPE_COLORINDEX,
  2235. PFD_TYPE_RGBA, PFD_TYPE_RGBA, PFD_TYPE_RGBA, PFD_TYPE_RGBA,
  2236. PFD_TYPE_COLORINDEX, PFD_TYPE_COLORINDEX
  2237. };
  2238. int WINAPI InternalDescribePixelFormat(HDC hdc, HDC hdcDriver,
  2239. int ipfd, UINT cjpfd,
  2240. LPPIXELFORMATDESCRIPTOR ppfd,
  2241. int ipfdDevMax, int ipfdMcdMax,
  2242. LPDIRECTDRAWSURFACE pdds,
  2243. DDSURFACEDESC *pddsd)
  2244. {
  2245. int iRet = 0;
  2246. int ipfdGen;
  2247. UINT iDitherFormat;
  2248. BYTE cColorBitsNative;
  2249. // If cjpfd is 0, just return the maximum pixel format index.
  2250. if (cjpfd == 0 || ppfd == NULL)
  2251. {
  2252. iRet = MAX_GENERIC_PFD + ipfdDevMax + ipfdMcdMax;
  2253. goto wglDescribePixelFormat_cleanup;
  2254. }
  2255. // Validate the size of the pixel format descriptor.
  2256. if (cjpfd < sizeof(PIXELFORMATDESCRIPTOR))
  2257. {
  2258. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  2259. goto wglDescribePixelFormat_cleanup;
  2260. }
  2261. // Validate pixel format index.
  2262. // If a driver support device pixel formats 1..ipfdDevMax, the generic
  2263. // pixel formats will be (ipfdDevMax+1)..(ipfdDevMax+MAX_GENERIC_PFD).
  2264. // Otherwise, ipfdDevMax is 0 and the generic pixel formats are
  2265. // 1..MAX_GENERIC_PFD.
  2266. if ((ipfd < 1) || (ipfd > ipfdDevMax + ipfdMcdMax + MAX_GENERIC_PFD))
  2267. {
  2268. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  2269. goto wglDescribePixelFormat_cleanup;
  2270. }
  2271. // Dispatch ICD driver formats.
  2272. if (ipfd <= ipfdDevMax)
  2273. {
  2274. int iDrvRet = __DrvDescribePixelFormat(hdcDriver,ipfd,cjpfd,ppfd);
  2275. if (iDrvRet)
  2276. {
  2277. ASSERTOPENGL(iDrvRet == ipfdDevMax,
  2278. "wglDescribePixelFornat: Bad ipfdDevMax");
  2279. iRet = MAX_GENERIC_PFD + ipfdDevMax + ipfdMcdMax;
  2280. }
  2281. goto wglDescribePixelFormat_cleanup;
  2282. }
  2283. #ifdef _MCD_
  2284. // Dispatch MCD driver formats.
  2285. ipfdGen = ipfd - ipfdDevMax;
  2286. if (ipfdGen <= ipfdMcdMax)
  2287. {
  2288. int iMcdRet;
  2289. // Note: don't need to check if gpMcdTable is valid because we can't get
  2290. // here unless ipfdDevMax is non-zero and that can't happen unless the
  2291. // the table is valid.
  2292. ASSERTOPENGL(gpMcdTable, "wglDescribePixelFormat: bad MCD table\n");
  2293. iMcdRet = (gpMcdTable->pMCDDescribePixelFormat)(hdcDriver, ipfdGen,
  2294. ppfd);
  2295. if (iMcdRet)
  2296. {
  2297. ASSERTOPENGL(iMcdRet == ipfdMcdMax,
  2298. "wglDescribePixelFornat: Bad ipfdMcdMax");
  2299. iRet = MAX_GENERIC_PFD + ipfdDevMax + ipfdMcdMax;
  2300. }
  2301. goto wglDescribePixelFormat_cleanup;
  2302. }
  2303. // Generic implementation.
  2304. // Normalize the generic pixel format index to 0..(MAX_GENERIC_PFD-1).
  2305. ipfdGen = ipfdGen - ipfdMcdMax - 1;
  2306. #else
  2307. // Generic implementation.
  2308. // Normalize the generic pixel format index to 0..(MAX_GENERIC_PFD-1).
  2309. ipfdGen = ipfd - ipfdDevMax - 1;
  2310. #endif
  2311. // Get the native BPP format.
  2312. if (pdds != NULL)
  2313. {
  2314. cColorBitsNative = DdPixelDepth(pddsd);
  2315. }
  2316. else
  2317. {
  2318. cColorBitsNative = (BYTE)wglGetDeviceDepth(hdc);
  2319. }
  2320. if (cColorBitsNative < 1)
  2321. {
  2322. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  2323. goto wglDescribePixelFormat_cleanup;
  2324. }
  2325. if (cColorBitsNative <= 1)
  2326. {
  2327. cColorBitsNative = 1;
  2328. iDitherFormat = BMF_1BPP;
  2329. }
  2330. else if (cColorBitsNative <= 4)
  2331. {
  2332. cColorBitsNative = 4;
  2333. iDitherFormat = BMF_4BPP;
  2334. }
  2335. else if (cColorBitsNative <= 8)
  2336. {
  2337. cColorBitsNative = 8;
  2338. iDitherFormat = BMF_8BPP;
  2339. }
  2340. else if (cColorBitsNative <= 16)
  2341. {
  2342. cColorBitsNative = 16;
  2343. iDitherFormat = BMF_16BPP;
  2344. }
  2345. else if (cColorBitsNative <= 24)
  2346. {
  2347. cColorBitsNative = 24;
  2348. iDitherFormat = BMF_24BPP;
  2349. }
  2350. else
  2351. {
  2352. cColorBitsNative = 32;
  2353. iDitherFormat = BMF_32BPP;
  2354. }
  2355. // Fill in the pixel format descriptor.
  2356. ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
  2357. ppfd->nVersion = 1;
  2358. ppfd->iPixelType = abPixelType[ipfdGen];
  2359. if (ipfdGen < MAX_NATIVE_GENERIC_PFD)
  2360. {
  2361. ppfd->cColorBits = max(cColorBitsNative, 4); // 1 bpp not supported
  2362. }
  2363. else
  2364. {
  2365. ppfd->cColorBits = aabPixelBits[iDitherFormat]
  2366. [(ipfdGen - MAX_NATIVE_GENERIC_PFD) / NON_NATIVE_PFD_GROUP];
  2367. }
  2368. // If the color format is compatible to that of the device and the
  2369. // color bits is 16 or greater, use the device description.
  2370. // Otherwise, use the generic format.
  2371. if (ipfdGen < MAX_NATIVE_GENERIC_PFD && cColorBitsNative >= 16)
  2372. {
  2373. // Handle compatible formats that are greater than 16-bits.
  2374. if (pdds != NULL)
  2375. {
  2376. __wglGetDdFormat(pddsd, ppfd);
  2377. }
  2378. else if ( !__wglGetBitfieldColorFormat(hdc, cColorBitsNative,
  2379. ppfd, FALSE) )
  2380. {
  2381. // Don't know how to deal with this device!
  2382. WARNING("Unknown device format");
  2383. SAVE_ERROR_CODE(ERROR_NOT_SUPPORTED);
  2384. goto wglDescribePixelFormat_cleanup;
  2385. }
  2386. }
  2387. else
  2388. {
  2389. // Handle generic formats.
  2390. switch (ppfd->cColorBits)
  2391. {
  2392. case 4:
  2393. ppfd->cRedBits = 1; ppfd->cRedShift = 0;
  2394. ppfd->cGreenBits = 1; ppfd->cGreenShift = 1;
  2395. ppfd->cBlueBits = 1; ppfd->cBlueShift = 2;
  2396. break;
  2397. case 8:
  2398. ppfd->cRedBits = 3; ppfd->cRedShift = 0;
  2399. ppfd->cGreenBits = 3; ppfd->cGreenShift = 3;
  2400. ppfd->cBlueBits = 2; ppfd->cBlueShift = 6;
  2401. break;
  2402. case 16:
  2403. /*
  2404. ** Even though Win95 allows arbitrary bitfield definitions
  2405. ** for 16bpp DIBs, only 555BGR is usable by Win95's GDI.
  2406. */
  2407. ppfd->cRedBits = 5; ppfd->cRedShift = 10; // 555BGR
  2408. ppfd->cGreenBits = 5; ppfd->cGreenShift = 5;
  2409. ppfd->cBlueBits = 5; ppfd->cBlueShift = 0;
  2410. break;
  2411. case 24:
  2412. case 32:
  2413. /*
  2414. ** Even though Win95 allows arbitrary bitfield definitions
  2415. ** for 32bpp, only 888BGR is usable by Win95's GDI. Similarly,
  2416. ** NT has the concept of a RGB 24bpp DIB, but Win95 does not.
  2417. */
  2418. ppfd->cRedBits = 8; ppfd->cRedShift = 16; // 888BGR
  2419. ppfd->cGreenBits = 8; ppfd->cGreenShift = 8;
  2420. ppfd->cBlueBits = 8; ppfd->cBlueShift = 0;
  2421. break;
  2422. default:
  2423. ASSERTOPENGL(FALSE, "wglDescribePixelFornat: Unknown format");
  2424. break;
  2425. }
  2426. }
  2427. ppfd->cAlphaBits = 0;
  2428. ppfd->cAlphaShift = 0;
  2429. if ( ipfdGen < MAX_NATIVE_GENERIC_PFD)
  2430. {
  2431. // Only report alpha bits if the DirectDraw surface has them.
  2432. if (pdds != NULL)
  2433. {
  2434. if (pddsd->ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS)
  2435. {
  2436. ASSERTOPENGL(pddsd->dwFlags & DDSD_ALPHABITDEPTH,
  2437. "Surface with alpha but no bit depth set\n");
  2438. ppfd->cAlphaBits = (BYTE)pddsd->dwAlphaBitDepth;
  2439. }
  2440. }
  2441. else if ( (ipfdGen > 3) && (ipfdGen < 8) )
  2442. {
  2443. ppfd->cAlphaBits = 8;
  2444. }
  2445. }
  2446. else
  2447. {
  2448. int ipfd = (ipfdGen - MAX_NATIVE_GENERIC_PFD) % NON_NATIVE_PFD_GROUP;
  2449. if ( (ipfd == 2) || (ipfd == 3) )
  2450. {
  2451. ppfd->cAlphaBits = 8;
  2452. }
  2453. }
  2454. if (ppfd->iPixelType == PFD_TYPE_RGBA)
  2455. {
  2456. if (ppfd->cColorBits <= 16)
  2457. {
  2458. if (ppfd->cColorBits < 8)
  2459. {
  2460. // !!! Internally now, we will actually be using a 32-bit accum
  2461. // buffer, but the user will think it's 16 (This is for
  2462. // backwards compatibility).
  2463. ppfd->cAccumBits = 16;
  2464. if( ppfd->cAlphaBits )
  2465. {
  2466. ppfd->cAccumRedBits = 4;
  2467. ppfd->cAccumGreenBits = 4;
  2468. ppfd->cAccumBlueBits = 4;
  2469. ppfd->cAccumAlphaBits = 4;
  2470. }
  2471. else
  2472. {
  2473. ppfd->cAccumRedBits = 5;
  2474. ppfd->cAccumGreenBits = 6;
  2475. ppfd->cAccumBlueBits = 5;
  2476. ppfd->cAccumAlphaBits = 0;
  2477. }
  2478. }
  2479. else
  2480. {
  2481. ppfd->cAccumBits = 32;
  2482. if( ppfd->cAlphaBits )
  2483. {
  2484. ppfd->cAccumRedBits = 8;
  2485. ppfd->cAccumGreenBits = 8;
  2486. ppfd->cAccumBlueBits = 8;
  2487. ppfd->cAccumAlphaBits = 8;
  2488. }
  2489. else
  2490. {
  2491. ppfd->cAccumRedBits = 11;
  2492. ppfd->cAccumGreenBits = 11;
  2493. ppfd->cAccumBlueBits = 10;
  2494. ppfd->cAccumAlphaBits = 0;
  2495. }
  2496. }
  2497. }
  2498. else
  2499. {
  2500. ppfd->cAccumBits = 64;
  2501. if( ppfd->cAlphaBits )
  2502. {
  2503. ppfd->cAccumRedBits = 16;
  2504. ppfd->cAccumGreenBits = 16;
  2505. ppfd->cAccumBlueBits = 16;
  2506. ppfd->cAccumAlphaBits = 16;
  2507. }
  2508. else
  2509. {
  2510. ppfd->cAccumRedBits = 16;
  2511. ppfd->cAccumGreenBits = 16;
  2512. ppfd->cAccumBlueBits = 16;
  2513. ppfd->cAccumAlphaBits = 0;
  2514. }
  2515. }
  2516. }
  2517. else
  2518. {
  2519. ppfd->cAccumBits = 0;
  2520. ppfd->cAccumRedBits = 0;
  2521. ppfd->cAccumGreenBits = 0;
  2522. ppfd->cAccumBlueBits = 0;
  2523. ppfd->cAccumAlphaBits = 0;
  2524. }
  2525. // Generic formats alternate between 16- and 32-bit depth buffer. Evens
  2526. // are 32-bit, odds are 16-bit.
  2527. // DirectDraw surfaces always report the depth of the attached Z buffer
  2528. // for the native format indices.
  2529. if (pdds != NULL && ipfdGen < MAX_NATIVE_GENERIC_PFD)
  2530. {
  2531. DDSCAPS ddscaps;
  2532. LPDIRECTDRAWSURFACE pddsZ;
  2533. // DDraw surfaces may not have attached Z buffers, in which case
  2534. // we should not report depth bits. If one is attached, its
  2535. // depth should be reported.
  2536. // We only do this processing for native pixel formats.
  2537. memset(&ddscaps, 0, sizeof(ddscaps));
  2538. ddscaps.dwCaps = DDSCAPS_ZBUFFER;
  2539. if (pdds->lpVtbl->
  2540. GetAttachedSurface(pdds, &ddscaps, &pddsZ) == DD_OK)
  2541. {
  2542. HRESULT hr;
  2543. DDSURFACEDESC ddsdZ;
  2544. memset(&ddsdZ, 0, sizeof(ddsdZ));
  2545. ddsdZ.dwSize = sizeof(ddsdZ);
  2546. hr = pddsZ->lpVtbl->GetSurfaceDesc(pddsZ, &ddsdZ);
  2547. pddsZ->lpVtbl->Release(pddsZ);
  2548. if (hr != DD_OK)
  2549. {
  2550. goto wglDescribePixelFormat_cleanup;
  2551. }
  2552. ppfd->cDepthBits =
  2553. (BYTE)DdPixDepthToCount(ddsdZ.ddpfPixelFormat.
  2554. dwZBufferBitDepth);
  2555. }
  2556. else
  2557. {
  2558. ppfd->cDepthBits = 0;
  2559. }
  2560. }
  2561. else if (ipfdGen & 0x1)
  2562. {
  2563. ppfd->cDepthBits = 16;
  2564. }
  2565. else
  2566. {
  2567. ppfd->cDepthBits = 32;
  2568. }
  2569. ppfd->cStencilBits = 8;
  2570. ppfd->cAuxBuffers = 0;
  2571. ppfd->iLayerType = PFD_MAIN_PLANE;
  2572. ppfd->bReserved = 0;
  2573. ppfd->dwLayerMask = 0;
  2574. ppfd->dwVisibleMask = 0;
  2575. ppfd->dwDamageMask = 0;
  2576. // Compute the buffer flags.
  2577. // Support OpenGL in all generic formats.
  2578. ppfd->dwFlags = PFD_SUPPORT_OPENGL | PFD_GENERIC_FORMAT;
  2579. // Indicate DirectDraw support on native pixel formats for DD surfaces.
  2580. if (pdds != NULL && ipfdGen < MAX_NATIVE_GENERIC_PFD)
  2581. {
  2582. ppfd->dwFlags |= PFD_SUPPORT_DIRECTDRAW;
  2583. }
  2584. // Bitmaps and GDI drawing are available in single buffered mode only.
  2585. if (pdds == NULL &&
  2586. (ipfdGen == 2 || ipfdGen == 3 || ipfdGen == 6 || ipfdGen == 7 ||
  2587. ipfdGen == 10 || ipfdGen == 11))
  2588. {
  2589. ppfd->dwFlags |= PFD_DOUBLEBUFFER | PFD_SWAP_COPY;
  2590. }
  2591. else
  2592. {
  2593. ppfd->dwFlags |= PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI;
  2594. }
  2595. // Draw to window or device surface only if the format is compatible.
  2596. if (ipfdGen < MAX_NATIVE_GENERIC_PFD)
  2597. {
  2598. ppfd->dwFlags |= PFD_DRAW_TO_WINDOW;
  2599. // Need a palette if it is a RGBA pixel type on a palette managed device.
  2600. if (ppfd->cColorBits == 8 && ppfd->iPixelType == PFD_TYPE_RGBA)
  2601. {
  2602. ppfd->dwFlags |= PFD_NEED_PALETTE;
  2603. }
  2604. }
  2605. // If this is a 1 bpp surface, we don't support drawing to window and
  2606. // double buffered mode. Re-set the buffer flags.
  2607. if (cColorBitsNative < 4)
  2608. {
  2609. #ifndef GL_METAFILE
  2610. ASSERTOPENGL(ppfd->cColorBits == 4,
  2611. "wglDescribePixelFormat: bad cColorBits for 1 bpp surface\n");
  2612. #endif
  2613. ppfd->dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI |
  2614. PFD_SUPPORT_OPENGL | PFD_GENERIC_FORMAT;
  2615. }
  2616. // To support other potential graphics systems, we reserve the following
  2617. // flags in the pixel format descriptor. For example, PEX may use
  2618. // PFD_SUPPORT_OTHER1 on the system that supports PEX. Since we don't
  2619. // support these other systems in the generic implementation, they belong
  2620. // to the device pixel format descriptor.
  2621. ASSERTOPENGL(!(ppfd->dwFlags & (PFD_SUPPORT_OTHER1 | PFD_SUPPORT_OTHER2 |
  2622. PFD_SUPPORT_OTHER3 | PFD_SUPPORT_OTHER4)),
  2623. "dwFlags reserved for device formats\n");
  2624. iRet = MAX_GENERIC_PFD + ipfdDevMax + ipfdMcdMax;
  2625. wglDescribePixelFormat_cleanup:
  2626. return iRet;
  2627. }
  2628. int WINAPI wglDescribePixelFormat(HDC hdc, int ipfd, UINT cjpfd,
  2629. LPPIXELFORMATDESCRIPTOR ppfd)
  2630. {
  2631. int iRet = 0;
  2632. int ipfdDevMax, ipfdMcdMax;
  2633. DWORD dwObjectType;
  2634. HDC hdcDriver = NULL;
  2635. LPDIRECTDRAWSURFACE pdds;
  2636. DDSURFACEDESC ddsd;
  2637. // Validate DC.
  2638. switch (dwObjectType = wglObjectType(hdc))
  2639. {
  2640. case OBJ_DC:
  2641. case OBJ_MEMDC:
  2642. case OBJ_ENHMETADC:
  2643. break;
  2644. default:
  2645. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  2646. return(0);
  2647. }
  2648. // Check to see if this is a DirectDraw DC. If it is, use the
  2649. // device DC returned from DirectDraw.
  2650. if (pfnGetSurfaceFromDC != NULL &&
  2651. pfnGetSurfaceFromDC(hdc, &pdds, &hdcDriver) == DD_OK)
  2652. {
  2653. // pdds reference must be released before exiting this function.
  2654. // Retrieve surface description for later use.
  2655. memset(&ddsd, 0, sizeof(ddsd));
  2656. ddsd.dwSize = sizeof(ddsd);
  2657. if (pdds->lpVtbl->GetSurfaceDesc(pdds, &ddsd) != DD_OK)
  2658. {
  2659. goto wglDescribePixelFormat_cleanup;
  2660. }
  2661. }
  2662. else
  2663. {
  2664. pdds = NULL;
  2665. hdcDriver = GetCompatibleDevice(hdc, dwObjectType);
  2666. if (hdcDriver == NULL)
  2667. {
  2668. goto wglDescribePixelFormat_cleanup;
  2669. }
  2670. // NOTE: From this point on, all exit cases must cleanup hdcDriver
  2671. }
  2672. // Get the number of hardware supported formats.
  2673. wglNumHardwareFormats(hdcDriver, dwObjectType, &ipfdMcdMax, &ipfdDevMax);
  2674. iRet = InternalDescribePixelFormat(hdc, hdcDriver, ipfd, cjpfd, ppfd,
  2675. ipfdDevMax, ipfdMcdMax,
  2676. pdds, &ddsd);
  2677. wglDescribePixelFormat_cleanup:
  2678. if (pdds != NULL)
  2679. {
  2680. pdds->lpVtbl->Release(pdds);
  2681. }
  2682. else if (hdcDriver != hdc)
  2683. {
  2684. ReleaseDC((HWND) NULL, hdcDriver);
  2685. }
  2686. return iRet;
  2687. }
  2688. #ifdef _MCD_
  2689. /******************************Public*Routine******************************\
  2690. * GenMcdGenericCompatibleFormat
  2691. *
  2692. * Determines if pixelformat in gengc can be supported by generic code.
  2693. *
  2694. * Note:
  2695. * The implication of not being compatible is that generic cannot be
  2696. * used for driver kickbacks and MCD contexts cannot be converted.
  2697. *
  2698. * Returns:
  2699. * TRUE if compatible, FALSE otherwise.
  2700. *
  2701. * History:
  2702. * 04-Jun-1996 -by- Gilman Wong [gilmanw]
  2703. * Wrote it.
  2704. \**************************************************************************/
  2705. BOOL FASTCALL GenMcdGenericCompatibleFormat(__GLGENcontext *gengc)
  2706. {
  2707. PIXELFORMATDESCRIPTOR *ppfd;
  2708. // Software-only formats are definitely supported.
  2709. ppfd = &gengc->gsurf.pfd;
  2710. if ((ppfd->dwFlags & (PFD_GENERIC_FORMAT|PFD_GENERIC_ACCELERATED))
  2711. == PFD_GENERIC_FORMAT)
  2712. return TRUE;
  2713. // Layer planes are not supported.
  2714. if (gengc->iLayerPlane)
  2715. return FALSE;
  2716. // Generic is PFD_SWAP_COPY only. There can't be many apps that rely
  2717. // on PFD_SWAP_EXCHANGE behavior (usually they look for PFD_SWAP_COPY
  2718. // so the back buffer can be used as backing store), but for now I think
  2719. // we should be conservative.
  2720. //
  2721. // Note: most MGA cards will set PFD_SWAP_COPY or neither (i.e., either
  2722. // style might be used depending on window size).
  2723. if (ppfd->dwFlags & PFD_SWAP_EXCHANGE)
  2724. return FALSE;
  2725. // Can only support 8bpp stencils.
  2726. if ((ppfd->cStencilBits != 0) && (ppfd->cStencilBits != 8))
  2727. return FALSE;
  2728. // Passed all the checks, we're compatible.
  2729. return TRUE;
  2730. }
  2731. #endif
  2732. /******************************Public*Routine******************************\
  2733. * wglSwapBuffers
  2734. *
  2735. \**************************************************************************/
  2736. BOOL WINAPI wglSwapBuffers(HDC hdc)
  2737. {
  2738. int ipfd;
  2739. BOOL bRet = FALSE;
  2740. GLGENwindow *pwnd;
  2741. GLWINDOWID gwid;
  2742. // Validate the DC.
  2743. if (IsDirectDrawDevice(hdc))
  2744. {
  2745. SetLastError(ERROR_INVALID_FUNCTION);
  2746. return FALSE;
  2747. }
  2748. switch ( wglObjectType(hdc) )
  2749. {
  2750. case OBJ_DC:
  2751. break;
  2752. case OBJ_MEMDC:
  2753. return(TRUE); // early out -- nothing to do if memory DC
  2754. default:
  2755. WARNING("wglSwapBuffers(): invalid hdc\n");
  2756. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  2757. return(FALSE);
  2758. }
  2759. // Validate pixel format.
  2760. WindowIdFromHdc(hdc, &gwid);
  2761. pwnd = pwndGetFromID(&gwid);
  2762. if ( pwnd )
  2763. {
  2764. if (pwnd->ipfd > 0)
  2765. {
  2766. // Dispatch to driver or generic. Which one can be determined by
  2767. // the pixel format.
  2768. if ( pwnd->ipfd <= pwnd->ipfdDevMax )
  2769. {
  2770. // Some ICDs do not need glFinish synchronization so
  2771. // we don't do it here. __DrvSwapBuffers will call
  2772. // it if necessary.
  2773. bRet = __DrvSwapBuffers(hdc, TRUE);
  2774. }
  2775. else
  2776. {
  2777. // Finish OpenGL calls in this thread before doing the swap.
  2778. // We use glFinish instead of glFlush to ensure that all
  2779. // OpenGL operations are completed.
  2780. glFinish();
  2781. ENTER_WINCRIT(pwnd);
  2782. // Can't rely on the pwnd's HDC because it may have
  2783. // been released since SetPixelFormat. Always use
  2784. // the DC passed in as the target.
  2785. bRet = glsrvSwapBuffers(hdc, pwnd);
  2786. LEAVE_WINCRIT(pwnd);
  2787. }
  2788. }
  2789. pwndRelease(pwnd);
  2790. }
  2791. else
  2792. {
  2793. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  2794. }
  2795. return bRet;
  2796. }