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.

1068 lines
33 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: wgl.c
  3. *
  4. * Routines to integrate Windows NT and OpenGL.
  5. *
  6. * Created: 10-26-1993
  7. * Author: Hock San Lee [hockl]
  8. *
  9. * Copyright (c) 1993 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #include <ntcsrdll.h>
  14. #include <ntpsapi.h>
  15. #include <wingdip.h>
  16. #include <glscreen.h>
  17. #include <glgenwin.h>
  18. #include "batchinf.h"
  19. #include "glapi.h"
  20. #include "glsbcltu.h"
  21. #include "wgldef.h"
  22. #include "metasup.h"
  23. #include "glclt.h"
  24. #include "gencx.h"
  25. #include "context.h"
  26. #include "global.h"
  27. #include "mcdcx.h"
  28. // Static functions prototypes
  29. static PROC pfnGenGlExtProc(LPCSTR lpszProc);
  30. static PROC pfnSimGlExtProc(LPCSTR lpszProc);
  31. /******************************Public*Routine******************************\
  32. *
  33. * wglObjectType
  34. *
  35. * Returns GetObjectType result with the exception that
  36. * metafile-spooled printer DC's come back as metafile objects
  37. *
  38. * History:
  39. * Fri Jun 16 12:10:07 1995 -by- Drew Bliss [drewb]
  40. * Created
  41. *
  42. \**************************************************************************/
  43. DWORD APIENTRY wglObjectType(HDC hdc)
  44. {
  45. DWORD dwObjectType;
  46. dwObjectType = GetObjectType(hdc);
  47. #ifdef GL_METAFILE
  48. if (dwObjectType == OBJ_DC &&
  49. pfnGdiIsMetaPrintDC != NULL &&
  50. GlGdiIsMetaPrintDC(hdc))
  51. {
  52. dwObjectType = OBJ_ENHMETADC;
  53. }
  54. #endif
  55. // OBJ_DDRAW is reserved as a special identifier. Make sure
  56. // we aren't returning it from here.
  57. ASSERTOPENGL(dwObjectType != OBJ_DDRAW,
  58. "Unexpected object type\n");
  59. return dwObjectType;
  60. }
  61. /******************************Public*Routine******************************\
  62. * wglDeleteContext(HGLRC hrc)
  63. *
  64. * Delete the rendering context
  65. *
  66. * Arguments:
  67. * hrc - Rendering context.
  68. *
  69. * History:
  70. * Tue Oct 26 10:25:26 1993 -by- Hock San Lee [hockl]
  71. * Rewrote it.
  72. \**************************************************************************/
  73. BOOL WINAPI wglDeleteContext(HGLRC hrc)
  74. {
  75. PLHE plheRC;
  76. ULONG irc;
  77. PLRC plrc;
  78. BOOL bRet = FALSE;
  79. DBGENTRY("wglDeleteContext\n");
  80. // Flush OpenGL calls.
  81. GLFLUSH();
  82. // Validate the RC.
  83. if (cLockHandle((ULONG_PTR)hrc) <= 0)
  84. {
  85. DBGLEVEL1(LEVEL_ERROR, "wglDeleteContext: can't lock hrc 0x%lx\n", hrc);
  86. return(bRet);
  87. }
  88. irc = MASKINDEX(hrc);
  89. plheRC = pLocalTable + irc;
  90. plrc = (PLRC) plheRC->pv;
  91. ASSERTOPENGL(plrc->ident == LRC_IDENTIFIER, "wglDeleteContext: Bad plrc\n");
  92. DBGLEVEL2(LEVEL_INFO, "wglDeleteContext: hrc: 0x%lx, plrc: 0x%lx\n", hrc, plrc);
  93. if (plrc->tidCurrent != INVALID_THREAD_ID)
  94. {
  95. // The RC must be current to this thread because makecurrent locks
  96. // down the handle.
  97. ASSERTOPENGL(plrc->tidCurrent == GetCurrentThreadId(),
  98. "wglDeleteCurrent: hrc is current to another thread\n");
  99. // Make the RC inactive first.
  100. if (!bMakeNoCurrent())
  101. {
  102. DBGERROR("wglDeleteCurrent: bMakeNoCurrent failed\n");
  103. }
  104. }
  105. if (plrc->dhrc)
  106. {
  107. // If it is a device format, call the driver to delete its context.
  108. bRet = plrc->pGLDriver->pfnDrvDeleteContext(plrc->dhrc);
  109. plrc->dhrc = (DHGLRC) 0;
  110. }
  111. else
  112. {
  113. #ifdef GL_METAFILE
  114. // If we have metafile state, clean it up
  115. if (plrc->uiGlsCaptureContext != 0 ||
  116. plrc->uiGlsPlaybackContext != 0)
  117. {
  118. DeleteMetaRc(plrc);
  119. }
  120. #endif
  121. // If it is a generic format, call the server to delete its context.
  122. bRet = __wglDeleteContext((HANDLE) plheRC->hgre);
  123. }
  124. // Always clean up local objects.
  125. vFreeLRC(plrc);
  126. vFreeHandle(irc); // it unlocks handle too
  127. if (!bRet)
  128. DBGERROR("wglDeleteContext failed\n");
  129. return(bRet);
  130. }
  131. /******************************Public*Routine******************************\
  132. * wglGetCurrentContext(VOID)
  133. *
  134. * Return the current rendering context
  135. *
  136. * Arguments:
  137. * None
  138. *
  139. * Returns:
  140. * hrc - Rendering context.
  141. *
  142. * History:
  143. * Tue Oct 26 10:25:26 1993 -by- Hock San Lee [hockl]
  144. * Wrote it.
  145. \**************************************************************************/
  146. HGLRC WINAPI wglGetCurrentContext(VOID)
  147. {
  148. DBGENTRY("wglGetCurrentContext\n");
  149. if (GLTEB_CLTCURRENTRC())
  150. return(GLTEB_CLTCURRENTRC()->hrc);
  151. else
  152. return((HGLRC) 0);
  153. }
  154. /******************************Public*Routine******************************\
  155. * wglGetCurrentDC(VOID)
  156. *
  157. * Return the device context that is associated with the current rendering
  158. * context
  159. *
  160. * Arguments:
  161. * None
  162. *
  163. * Returns:
  164. * hdc - device context.
  165. *
  166. * History:
  167. * Mon Jan 31 12:15:12 1994 -by- Hock San Lee [hockl]
  168. * Wrote it.
  169. \**************************************************************************/
  170. HDC WINAPI wglGetCurrentDC(VOID)
  171. {
  172. PLRC plrc;
  173. DBGENTRY("wglGetCurrentDC\n");
  174. plrc = GLTEB_CLTCURRENTRC();
  175. if (plrc != NULL)
  176. {
  177. return plrc->gwidCurrent.hdc;
  178. }
  179. else
  180. {
  181. return((HDC) 0);
  182. }
  183. }
  184. /******************************Public*Routine******************************\
  185. * wglUseFontBitmapsA
  186. * wglUseFontBitmapsW
  187. *
  188. * Stubs that call wglUseFontBitmapsAW with the bUnicode flag set
  189. * appropriately.
  190. *
  191. * History:
  192. * 11-Mar-1994 gilmanw
  193. * Changed to call wglUseFontBitmapsAW.
  194. *
  195. * 17-Dec-1993 -by- Gilman Wong [gilmanw]
  196. * Wrote it.
  197. \**************************************************************************/
  198. BOOL WINAPI wglUseFontBitmapsAW(HDC hdc, DWORD first, DWORD count,
  199. DWORD listBase, BOOL bUnicode);
  200. BOOL WINAPI
  201. wglUseFontBitmapsA(HDC hdc, DWORD first, DWORD count, DWORD listBase)
  202. {
  203. return wglUseFontBitmapsAW(hdc, first, count, listBase, FALSE);
  204. }
  205. BOOL WINAPI
  206. wglUseFontBitmapsW(HDC hdc, DWORD first, DWORD count, DWORD listBase)
  207. {
  208. return wglUseFontBitmapsAW(hdc, first, count, listBase, TRUE);
  209. }
  210. /******************************Public*Routine******************************\
  211. * wglUseFontBitmapsAW
  212. *
  213. * Uses the current font in the specified DC to generate a series of OpenGL
  214. * display lists, each of which consists of a glyph bitmap.
  215. *
  216. * Each glyph bitmap is generated by calling ExtTextOut to draw the glyph
  217. * into a memory DC. The contents of the memory DC are then copied into
  218. * a buffer by GetDIBits and then put into the OpenGL display list.
  219. *
  220. * ABC spacing is used (if GetCharABCWidth() is supported by the font) to
  221. * determine proper placement of the glyph origin and character advance width.
  222. * Otherwise, A = C = 0 spacing is assumed and GetCharWidth() is used for the
  223. * advance widths.
  224. *
  225. * Returns:
  226. *
  227. * TRUE if successful, FALSE otherwise.
  228. *
  229. * History:
  230. * 17-Dec-1993 -by- Gilman Wong [gilmanw]
  231. * Wrote it.
  232. \**************************************************************************/
  233. BOOL WINAPI
  234. wglUseFontBitmapsAW(
  235. HDC hdc, // use HFONT from this DC
  236. DWORD first, // generate glyphs starting with this Unicode codepoint
  237. DWORD count, // range is this long [first, first+count-1]
  238. DWORD listBase, // starting display list number
  239. BOOL bUnicode // TRUE for if in Unicode mode, FALSE if in Ansi mode
  240. )
  241. {
  242. BOOL bRet = FALSE; // return value
  243. HDC hdcMem; // render glyphs to this memory DC
  244. HBITMAP hbm; // monochrome bitmap for memory DC
  245. LPABC pabc, pabcTmp, pabcEnd; // array of ABC spacing
  246. LPINT piWidth, piTmp, piWidthEnd; // array of char adv. widths
  247. WCHAR wc; // current Unicode char to render
  248. RECT rc; // background rectangle to clear
  249. TEXTMETRICA tm; // metrics of the font
  250. BOOL bTrueType; // TrueType supports ABC spacing
  251. int iMaxWidth = 1; // maximum glyph width
  252. int iBitmapWidth; // DWORD aligned bitmap width
  253. BYTE ajBmi[sizeof(BITMAPINFO) + sizeof(RGBQUAD)];
  254. BITMAPINFO *pbmi = (BITMAPINFO *)ajBmi;// bitmap info for GetDIBits
  255. GLint iUnpackRowLength; // save GL_UNPACK_ROW_LENGTH
  256. GLint iUnpackAlign; // save GL_UNPACK_ALIGNMENT
  257. PVOID pv; // pointer to glyph bitmap buffer
  258. // Return error if there is no current RC.
  259. if (!GLTEB_CLTCURRENTRC())
  260. {
  261. WARNING("wglUseFontBitmapsAW: no current RC\n");
  262. SetLastError(ERROR_INVALID_HANDLE);
  263. return bRet;
  264. }
  265. // Get TEXTMETRIC. The only fields used are those that are invariant with
  266. // respect to Unicode vs. ANSI. Therefore, we can call GetTextMetricsA for
  267. // both cases.
  268. if ( !GetTextMetricsA(hdc, &tm) )
  269. {
  270. WARNING("wglUseFontBitmapsAW: GetTextMetricsA failed\n");
  271. return bRet;
  272. }
  273. // If its a TrueType font, we can get ABC spacing.
  274. if ( bTrueType = (tm.tmPitchAndFamily & TMPF_TRUETYPE) )
  275. {
  276. // Allocate memory for array of ABC data.
  277. if ( (pabc = (LPABC) ALLOC(sizeof(ABC) * count)) == (LPABC) NULL )
  278. {
  279. WARNING("wglUseFontBitmapsAW: Alloc of pabc failed\n");
  280. return bRet;
  281. }
  282. // Get ABC metrics.
  283. if ( bUnicode )
  284. {
  285. if ( !GetCharABCWidthsW(hdc, first, first + count - 1, pabc) )
  286. {
  287. WARNING("wglUseFontBitmapsAW: GetCharABCWidthsW failed\n");
  288. FREE(pabc);
  289. return bRet;
  290. }
  291. }
  292. else
  293. {
  294. if ( !GetCharABCWidthsA(hdc, first, first + count - 1, pabc) )
  295. {
  296. WARNING("wglUseFontBitmapsAW: GetCharABCWidthsA failed\n");
  297. FREE(pabc);
  298. return bRet;
  299. }
  300. }
  301. // Find max glyph width.
  302. for (pabcTmp = pabc, pabcEnd = pabc + count;
  303. pabcTmp < pabcEnd;
  304. pabcTmp++)
  305. {
  306. if (iMaxWidth < (int) pabcTmp->abcB)
  307. iMaxWidth = pabcTmp->abcB;
  308. }
  309. }
  310. // Otherwise we will have to use just the advance width and assume
  311. // A = C = 0.
  312. else
  313. {
  314. // Allocate memory for array of ABC data.
  315. if ( (piWidth = (LPINT) ALLOC(sizeof(INT) * count)) == (LPINT) NULL )
  316. {
  317. WARNING("wglUseFontBitmapsAW: Alloc of pabc failed\n");
  318. return bRet;
  319. }
  320. // Get char widths.
  321. if ( bUnicode )
  322. {
  323. if ( !GetCharWidthW(hdc, first, first + count - 1, piWidth) )
  324. {
  325. WARNING("wglUseFontBitmapsAW: GetCharWidthW failed\n");
  326. FREE(piWidth);
  327. return bRet;
  328. }
  329. }
  330. else
  331. {
  332. if ( !GetCharWidthA(hdc, first, first + count - 1, piWidth) )
  333. {
  334. WARNING("wglUseFontBitmapsAW: GetCharWidthA failed\n");
  335. FREE(piWidth);
  336. return bRet;
  337. }
  338. }
  339. // Find max glyph width.
  340. for (piTmp = piWidth, piWidthEnd = piWidth + count;
  341. piTmp < piWidthEnd;
  342. piTmp++)
  343. {
  344. if (iMaxWidth < *piTmp)
  345. iMaxWidth = *piTmp;
  346. }
  347. }
  348. // Compute the dword aligned width. Bitmap scanlines must be aligned.
  349. iBitmapWidth = (iMaxWidth + 31) & -32;
  350. // Allocate memory for the DIB.
  351. if ( (pv = (PVOID)
  352. ALLOC((iBitmapWidth / 8) * tm.tmHeight)) == (PVOID) NULL )
  353. {
  354. WARNING("wglUseFontBitmapsAW: Alloc of pv failed\n");
  355. (bTrueType) ? FREE(pabc) : FREE(piWidth);
  356. return bRet;
  357. }
  358. // Create compatible DC/bitmap big enough to accomodate the biggest glyph
  359. // in the range requested.
  360. //!!!XXX -- Future optimization: use CreateDIBSection so that we
  361. //!!!XXX don't need to do a GetDIBits for each glyph. Saves
  362. //!!!XXX lots of CSR overhead.
  363. hdcMem = CreateCompatibleDC(hdc);
  364. if ( (hbm = CreateBitmap(iBitmapWidth, tm.tmHeight, 1, 1, (VOID *) NULL)) == (HBITMAP) NULL )
  365. {
  366. WARNING("wglUseFontBitmapsAW: CreateBitmap failed\n");
  367. (bTrueType) ? FREE(pabc) : FREE(piWidth);
  368. FREE(pv);
  369. DeleteDC(hdcMem);
  370. return bRet;
  371. }
  372. SelectObject(hdcMem, hbm);
  373. SelectObject(hdcMem, GetCurrentObject(hdc, OBJ_FONT));
  374. SetMapMode(hdcMem, MM_TEXT);
  375. SetTextAlign(hdcMem, TA_TOP | TA_LEFT);
  376. SetBkColor(hdcMem, RGB(0, 0, 0));
  377. SetBkMode(hdcMem, OPAQUE);
  378. SetTextColor(hdcMem, RGB(255, 255, 255));
  379. // Setup bitmap info header to retrieve a DIB from the compatible bitmap.
  380. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  381. pbmi->bmiHeader.biWidth = iBitmapWidth;
  382. pbmi->bmiHeader.biHeight = tm.tmHeight;
  383. pbmi->bmiHeader.biPlanes = 1;
  384. pbmi->bmiHeader.biBitCount = 1;
  385. pbmi->bmiHeader.biCompression = BI_RGB;
  386. pbmi->bmiHeader.biSizeImage = 0;
  387. pbmi->bmiHeader.biXPelsPerMeter = 0;
  388. pbmi->bmiHeader.biYPelsPerMeter = 0;
  389. pbmi->bmiHeader.biClrUsed = 0;
  390. pbmi->bmiHeader.biClrImportant = 0;
  391. pbmi->bmiColors[0].rgbRed = 0;
  392. pbmi->bmiColors[0].rgbGreen = 0;
  393. pbmi->bmiColors[0].rgbBlue = 0;
  394. pbmi->bmiColors[1].rgbRed = 0xff;
  395. pbmi->bmiColors[1].rgbGreen = 0xff;
  396. pbmi->bmiColors[1].rgbBlue = 0xff;
  397. // Setup OpenGL to accept our bitmap format.
  398. glGetIntegerv(GL_UNPACK_ROW_LENGTH, &iUnpackRowLength);
  399. glGetIntegerv(GL_UNPACK_ALIGNMENT, &iUnpackAlign);
  400. if (glGetError() != GL_NO_ERROR)
  401. {
  402. //XXX too noisy on debug builds running stress with mode changes
  403. //WARNING("wglUseFontBitmapsAW: failed to get GL state\n");
  404. goto wglUseFontBitmapsAW_exit;
  405. }
  406. glPixelStorei(GL_UNPACK_ROW_LENGTH, iBitmapWidth);
  407. if (glGetError() != GL_NO_ERROR)
  408. {
  409. //XXX too noisy on debug builds running stress with mode changes
  410. //WARNING("wglUseFontBitmapsAW: failed to set GL state, row length\n");
  411. goto wglUseFontBitmapsAW_restore_state;
  412. }
  413. glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
  414. if (glGetError() != GL_NO_ERROR)
  415. {
  416. //XXX too noisy on debug builds running stress with mode changes
  417. //WARNING("wglUseFontBitmapsAW: failed to set GL state, alignment\n");
  418. goto wglUseFontBitmapsAW_restore_state;
  419. }
  420. // Get the glyphs. Each glyph is rendered one at a time into the the
  421. // memory DC with ExtTextOutW (notice that the optional rectangle is
  422. // used to clear the background). Each glyph is then copied out of the
  423. // memory DC's bitmap with GetDIBits into a buffer. This buffer is passed
  424. // to glBitmap as each display list is created.
  425. rc.left = 0;
  426. rc.top = 0;
  427. rc.right = iBitmapWidth;
  428. rc.bottom = tm.tmHeight;
  429. pabcTmp = pabc;
  430. piTmp = piWidth;
  431. for (wc = (WCHAR) first; wc < (WCHAR) (first + count); wc++, listBase++)
  432. {
  433. //!!!XXX -- Future optimization: grab all the glyphs with a single
  434. //!!!XXX call to ExtTextOutA and GetDIBits into a large bitmap.
  435. //!!!XXX This would save a lot of per glyph CSR and call overhead.
  436. //!!!XXX A tall, thin bitmap with the glyphs arranged vertically
  437. //!!!XXX would be convenient because then we wouldn't have to change
  438. //!!!XXX the OpenGL pixel store row length for each glyph (which
  439. //!!!XXX we would need to do if the glyphs were printed horizontal).
  440. if ( bUnicode )
  441. {
  442. if ( !ExtTextOutW(hdcMem, bTrueType ? -pabcTmp->abcA : 0, 0, ETO_OPAQUE, &rc, &wc, 1, (INT *) NULL) ||
  443. !GetDIBits(hdcMem, hbm, 0, tm.tmHeight, pv, pbmi, DIB_RGB_COLORS) )
  444. {
  445. WARNING("wglUseFontBitmapsAW: failed to render glyph\n");
  446. goto wglUseFontBitmapsAW_restore_state;
  447. }
  448. }
  449. else
  450. {
  451. if ( !ExtTextOutA(hdcMem, bTrueType ? -pabcTmp->abcA : 0, 0, ETO_OPAQUE, &rc, (LPCSTR) &wc, 1, (INT *) NULL) ||
  452. !GetDIBits(hdcMem, hbm, 0, tm.tmHeight, pv, pbmi, DIB_RGB_COLORS) )
  453. {
  454. WARNING("wglUseFontBitmapsAW: failed to render glyph\n");
  455. goto wglUseFontBitmapsAW_restore_state;
  456. }
  457. }
  458. glNewList(listBase, GL_COMPILE);
  459. glBitmap((GLsizei) iBitmapWidth,
  460. (GLsizei) tm.tmHeight,
  461. (GLfloat) (bTrueType ? -pabcTmp->abcA : 0),
  462. (GLfloat) tm.tmDescent,
  463. (GLfloat) (bTrueType ? (pabcTmp->abcA + pabcTmp->abcB + pabcTmp->abcC) : *piTmp),
  464. (GLfloat) 0.0,
  465. (GLubyte *) pv);
  466. glEndList();
  467. if (bTrueType)
  468. pabcTmp++;
  469. else
  470. piTmp++;
  471. }
  472. // We can finally return success.
  473. bRet = TRUE;
  474. // Free resources.
  475. wglUseFontBitmapsAW_restore_state:
  476. glPixelStorei(GL_UNPACK_ROW_LENGTH, iUnpackRowLength);
  477. glPixelStorei(GL_UNPACK_ALIGNMENT, iUnpackAlign);
  478. wglUseFontBitmapsAW_exit:
  479. (bTrueType) ? FREE(pabc) : FREE(piWidth);
  480. FREE(pv);
  481. DeleteDC(hdcMem);
  482. DeleteObject(hbm);
  483. return bRet;
  484. }
  485. /******************************Public*Routine******************************\
  486. *
  487. * wglShareLists
  488. *
  489. * Allows a rendering context to share the display lists of another RC
  490. *
  491. * Returns:
  492. * TRUE if successful, FALSE otherwise
  493. *
  494. * History:
  495. * Tue Dec 13 14:57:17 1994 -by- Drew Bliss [drewb]
  496. * Created
  497. *
  498. \**************************************************************************/
  499. BOOL WINAPI
  500. wglShareLists(HGLRC hrcSource, HGLRC hrcShare)
  501. {
  502. BOOL fRet;
  503. PLRC plrcSource, plrcShare;
  504. ULONG irc;
  505. PLHE plheRC;
  506. HANDLE hrcSrvSource, hrcSrvShare;
  507. GLFLUSH();
  508. fRet = FALSE;
  509. // Validate the contexts
  510. if (cLockHandle((ULONG_PTR)hrcSource) <= 0)
  511. {
  512. DBGLEVEL1(LEVEL_ERROR, "wglShareLists: can't lock hrcSource 0x%lx\n",
  513. hrcSource);
  514. goto wglShareListsEnd_nolock;
  515. }
  516. irc = MASKINDEX(hrcSource);
  517. plheRC = pLocalTable + irc;
  518. plrcSource = (PLRC)plheRC->pv;
  519. hrcSrvSource = (HANDLE) plheRC->hgre;
  520. ASSERTOPENGL(plrcSource->ident == LRC_IDENTIFIER,
  521. "wglShareLists: Bad plrc\n");
  522. if (cLockHandle((ULONG_PTR)hrcShare) <= 0)
  523. {
  524. DBGLEVEL1(LEVEL_ERROR, "wglShareLists: can't lock hrcShare 0x%lx\n",
  525. hrcShare);
  526. goto wglShareListsEnd_onelock;
  527. }
  528. irc = MASKINDEX(hrcShare);
  529. plheRC = pLocalTable + irc;
  530. plrcShare = (PLRC)plheRC->pv;
  531. hrcSrvShare = (HANDLE) plheRC->hgre;
  532. ASSERTOPENGL(plrcShare->ident == LRC_IDENTIFIER,
  533. "wglShareLists: Bad plrc\n");
  534. #ifdef GL_METAFILE
  535. // Metafile RC's can't share lists to ensure that metafiles are
  536. // completely self-sufficient
  537. if (plrcSource->uiGlsCaptureContext != 0 ||
  538. plrcShare->uiGlsCaptureContext != 0 ||
  539. plrcSource->uiGlsPlaybackContext != 0 ||
  540. plrcShare->uiGlsPlaybackContext != 0)
  541. {
  542. DBGLEVEL(LEVEL_ERROR,
  543. "wglShareLists: Attempt to share metafile RC\n");
  544. SetLastError(ERROR_INVALID_HANDLE);
  545. goto wglShareListsEnd;
  546. }
  547. #endif
  548. // Lists can only be shared between like implementations so make
  549. // sure that both contexts are either driver contexts or generic
  550. // contexts
  551. if ((plrcSource->dhrc != 0) != (plrcShare->dhrc != 0))
  552. {
  553. DBGLEVEL(LEVEL_ERROR, "wglShareLists: mismatched implementations\n");
  554. SetLastError(ERROR_INVALID_FUNCTION);
  555. goto wglShareListsEnd;
  556. }
  557. if (plrcSource->dhrc == 0)
  558. {
  559. PIXELFORMATDESCRIPTOR *ppfdShare, *ppfdSource;
  560. // Fail sharing unless color parameters match for the two contexts
  561. ppfdShare = &((__GLGENcontext *)hrcSrvShare)->gsurf.pfd;
  562. ppfdSource = &((__GLGENcontext *)hrcSrvSource)->gsurf.pfd;
  563. if (ppfdShare->iPixelType != ppfdSource->iPixelType ||
  564. ppfdShare->cColorBits != ppfdSource->cColorBits ||
  565. ppfdShare->cRedBits != ppfdSource->cRedBits ||
  566. ppfdShare->cRedShift != ppfdSource->cRedShift ||
  567. ppfdShare->cGreenBits != ppfdSource->cGreenBits ||
  568. ppfdShare->cGreenShift != ppfdSource->cGreenShift ||
  569. ppfdShare->cBlueBits != ppfdSource->cBlueBits ||
  570. ppfdShare->cBlueShift != ppfdSource->cBlueShift ||
  571. ppfdShare->cAlphaBits != ppfdSource->cAlphaBits ||
  572. ppfdShare->cAlphaShift != ppfdSource->cAlphaShift ||
  573. (ppfdShare->dwFlags & PFD_GENERIC_ACCELERATED) !=
  574. (ppfdSource->dwFlags & PFD_GENERIC_ACCELERATED))
  575. {
  576. SetLastError(ERROR_INVALID_PIXEL_FORMAT);
  577. goto wglShareListsEnd;
  578. }
  579. // For generic contexts, tell the server to share the lists
  580. fRet = __wglShareLists(hrcSrvShare, hrcSrvSource);
  581. if (!fRet)
  582. {
  583. DBGERROR("wglShareLists: server call failed\n");
  584. }
  585. }
  586. else
  587. {
  588. // For device contexts tell the server to share the lists
  589. // Ensure that both implementations are the same
  590. if (plrcSource->pGLDriver != plrcShare->pGLDriver)
  591. {
  592. DBGLEVEL(LEVEL_ERROR, "wglShareLists: mismatched "
  593. "implementations\n");
  594. SetLastError(ERROR_INVALID_FUNCTION);
  595. goto wglShareListsEnd;
  596. }
  597. ASSERTOPENGL(plrcSource->pGLDriver != NULL,
  598. "wglShareLists: No GLDriver\n");
  599. // Older drivers may not support this entry point, so
  600. // fail the call if they don't
  601. if (plrcSource->pGLDriver->pfnDrvShareLists == NULL)
  602. {
  603. WARNING("wglShareLists called on driver context "
  604. "without driver support\n");
  605. SetLastError(ERROR_NOT_SUPPORTED);
  606. }
  607. else
  608. {
  609. fRet = plrcSource->pGLDriver->pfnDrvShareLists(plrcSource->dhrc,
  610. plrcShare->dhrc);
  611. }
  612. }
  613. wglShareListsEnd:
  614. vUnlockHandle((ULONG_PTR)hrcShare);
  615. wglShareListsEnd_onelock:
  616. vUnlockHandle((ULONG_PTR)hrcSource);
  617. wglShareListsEnd_nolock:
  618. return fRet;
  619. }
  620. /******************************Public*Routine******************************\
  621. *
  622. * wglGetDefaultProcAddress
  623. *
  624. * Returns generic extension functions for metafiling
  625. *
  626. * History:
  627. * Tue Nov 28 16:40:35 1995 -by- Drew Bliss [drewb]
  628. * Created
  629. *
  630. \**************************************************************************/
  631. PROC WINAPI wglGetDefaultProcAddress(LPCSTR lpszProc)
  632. {
  633. return pfnGenGlExtProc(lpszProc);
  634. }
  635. /******************************Public*Routine******************************\
  636. * wglGetProcAddress
  637. *
  638. * The wglGetProcAddress function returns the address of an OpenGL extension
  639. * function to be used with the current OpenGL rendering context.
  640. *
  641. * Arguments:
  642. * lpszProc - Points to a null-terminated string containing the function
  643. * name. The function must be an extension supported by the
  644. * implementation.
  645. *
  646. * Returns:
  647. * If the function succeeds, the return value is the address of the extension
  648. * function. If no current context exists or the function fails, the return
  649. * value is NULL. To get extended error information, call GetLastError.
  650. *
  651. * History:
  652. * Thu Dec 01 13:50:22 1994 -by- Hock San Lee [hockl]
  653. * Wrote it.
  654. \**************************************************************************/
  655. PROC WINAPI wglGetProcAddress(LPCSTR lpszProc)
  656. {
  657. PLRC plrc = GLTEB_CLTCURRENTRC();
  658. DBGENTRY("wglGetProcAddress\n");
  659. // Flush OpenGL calls.
  660. GLFLUSH();
  661. // Return error if there is no current RC.
  662. if (!plrc)
  663. {
  664. WARNING("wglGetProcAddress: no current RC\n");
  665. SetLastError(ERROR_INVALID_HANDLE);
  666. return((PROC) NULL);
  667. }
  668. // Handle generic RC.
  669. // Return the generic extension function entry point
  670. if (!plrc->dhrc)
  671. return(pfnGenGlExtProc(lpszProc));
  672. // Handle driver RC.
  673. // There are 3 cases:
  674. // 1. New drivers that support DrvGetProcAddress.
  675. // 2. Old drivers that don't support DrvGetProcAddress but export the function
  676. // 3. If we fail to obtain a function address in 1 and 2, it may still be
  677. // simulated by the generic implemenation for the driver
  678. // (e.g. glDrawArraysEXT). Return the simulated entry point if found.
  679. if (plrc->pGLDriver->pfnDrvGetProcAddress)
  680. {
  681. // Case 1
  682. PROC pfn = plrc->pGLDriver->pfnDrvGetProcAddress(lpszProc);
  683. if (pfn)
  684. return(pfn);
  685. }
  686. #ifdef OBSOLETE
  687. else
  688. {
  689. // Case 2
  690. PROC pfn = GetProcAddress(plrc->pGLDriver->hModule, lpszProc);
  691. if (pfn)
  692. return(pfn);
  693. }
  694. #endif
  695. // Case 3
  696. return (pfnSimGlExtProc(lpszProc));
  697. }
  698. /******************************Public*Routine******************************\
  699. * pfnGenGlExtProc
  700. *
  701. * Return the generic implementation extension function address.
  702. *
  703. * Returns NULL if the function is not found.
  704. *
  705. * History:
  706. * Thu Dec 01 13:50:22 1994 -by- Hock San Lee [hockl]
  707. * Wrote it.
  708. \**************************************************************************/
  709. typedef struct _GLEXTPROC {
  710. LPCSTR szProc; // extension function name
  711. PROC Proc; // extension function address
  712. } GLEXTPROC, *PGLEXTPROC;
  713. // Extension functions supported by the generic implementation
  714. // See also genglExtProcsSim for simulations.
  715. // NOTE: remember to update GL_EXTENSIONS in glGetString.
  716. GLEXTPROC genglExtProcs[] =
  717. {
  718. { "glAddSwapHintRectWIN" , (PROC) glAddSwapHintRectWIN },
  719. { "glColorTableEXT" , (PROC) glColorTableEXT },
  720. { "glColorSubTableEXT" , (PROC) glColorSubTableEXT },
  721. { "glGetColorTableEXT" , (PROC) glGetColorTableEXT },
  722. { "glGetColorTableParameterivEXT", (PROC) glGetColorTableParameterivEXT},
  723. { "glGetColorTableParameterfvEXT", (PROC) glGetColorTableParameterfvEXT},
  724. { "glDrawRangeElementsWIN", (PROC) glDrawRangeElementsWIN},
  725. #ifdef GL_EXT_flat_paletted_lighting
  726. { "glColorTableParameterivEXT", (PROC) glColorTableParameterivEXT},
  727. { "glColorTableParameterfvEXT", (PROC) glColorTableParameterfvEXT},
  728. #endif // GL_EXT_flat_paletted_lighting
  729. #ifdef GL_WIN_multiple_textures
  730. { "glCurrentTextureIndexWIN", (PROC) glCurrentTextureIndexWIN },
  731. { "glMultiTexCoord1dWIN", (PROC) glMultiTexCoord1dWIN },
  732. { "glMultiTexCoord1dvWIN", (PROC) glMultiTexCoord1dvWIN },
  733. { "glMultiTexCoord1fWIN", (PROC) glMultiTexCoord1fWIN },
  734. { "glMultiTexCoord1fvWIN", (PROC) glMultiTexCoord1fvWIN },
  735. { "glMultiTexCoord1iWIN", (PROC) glMultiTexCoord1iWIN },
  736. { "glMultiTexCoord1ivWIN", (PROC) glMultiTexCoord1ivWIN },
  737. { "glMultiTexCoord1sWIN", (PROC) glMultiTexCoord1sWIN },
  738. { "glMultiTexCoord1svWIN", (PROC) glMultiTexCoord1svWIN },
  739. { "glMultiTexCoord2dWIN", (PROC) glMultiTexCoord2dWIN },
  740. { "glMultiTexCoord2dvWIN", (PROC) glMultiTexCoord2dvWIN },
  741. { "glMultiTexCoord2fWIN", (PROC) glMultiTexCoord2fWIN },
  742. { "glMultiTexCoord2fvWIN", (PROC) glMultiTexCoord2fvWIN },
  743. { "glMultiTexCoord2iWIN", (PROC) glMultiTexCoord2iWIN },
  744. { "glMultiTexCoord2ivWIN", (PROC) glMultiTexCoord2ivWIN },
  745. { "glMultiTexCoord2sWIN", (PROC) glMultiTexCoord2sWIN },
  746. { "glMultiTexCoord2svWIN", (PROC) glMultiTexCoord2svWIN },
  747. { "glMultiTexCoord3dWIN", (PROC) glMultiTexCoord3dWIN },
  748. { "glMultiTexCoord3dvWIN", (PROC) glMultiTexCoord3dvWIN },
  749. { "glMultiTexCoord3fWIN", (PROC) glMultiTexCoord3fWIN },
  750. { "glMultiTexCoord3fvWIN", (PROC) glMultiTexCoord3fvWIN },
  751. { "glMultiTexCoord3iWIN", (PROC) glMultiTexCoord3iWIN },
  752. { "glMultiTexCoord3ivWIN", (PROC) glMultiTexCoord3ivWIN },
  753. { "glMultiTexCoord3sWIN", (PROC) glMultiTexCoord3sWIN },
  754. { "glMultiTexCoord3svWIN", (PROC) glMultiTexCoord3svWIN },
  755. { "glMultiTexCoord4dWIN", (PROC) glMultiTexCoord4dWIN },
  756. { "glMultiTexCoord4dvWIN", (PROC) glMultiTexCoord4dvWIN },
  757. { "glMultiTexCoord4fWIN", (PROC) glMultiTexCoord4fWIN },
  758. { "glMultiTexCoord4fvWIN", (PROC) glMultiTexCoord4fvWIN },
  759. { "glMultiTexCoord4iWIN", (PROC) glMultiTexCoord4iWIN },
  760. { "glMultiTexCoord4ivWIN", (PROC) glMultiTexCoord4ivWIN },
  761. { "glMultiTexCoord4sWIN", (PROC) glMultiTexCoord4sWIN },
  762. { "glMultiTexCoord4svWIN", (PROC) glMultiTexCoord4svWIN },
  763. { "glBindNthTextureWIN", (PROC) glBindNthTextureWIN },
  764. { "glNthTexCombineFuncWIN", (PROC) glNthTexCombineFuncWIN },
  765. #endif // GL_WIN_multiple_textures
  766. };
  767. static PROC pfnGenGlExtProc(LPCSTR lpszProc)
  768. {
  769. CONST CHAR *pch1, *pch2;
  770. int i;
  771. DBGENTRY("pfnGenGlExtProc\n");
  772. // Return extension function address if it is found.
  773. for (i = 0; i < sizeof(genglExtProcs) / sizeof(genglExtProcs[0]); i++)
  774. {
  775. // Compare names.
  776. for (pch1 = lpszProc, pch2 = genglExtProcs[i].szProc;
  777. *pch1 == *pch2 && *pch1;
  778. pch1++, pch2++)
  779. ;
  780. // If found, return the address.
  781. if (*pch1 == *pch2 && !*pch1)
  782. return genglExtProcs[i].Proc;
  783. }
  784. // Extension is not supported by the generic implementation, return NULL.
  785. SetLastError(ERROR_PROC_NOT_FOUND);
  786. return((PROC) NULL);
  787. }
  788. /******************************Public*Routine******************************\
  789. * pfnSimGlExtProc
  790. *
  791. * Return the extension function address that is the generic implemenation's
  792. * simulation for the client drivers. The simulation is used only if the
  793. * driver does not support an extension that is desirable to apps.
  794. *
  795. * Returns NULL if the function is not found.
  796. *
  797. * History:
  798. * Thu Dec 01 13:50:22 1994 -by- Hock San Lee [hockl]
  799. * Wrote it.
  800. \**************************************************************************/
  801. // Extension functions simulated by the generic implementation for the client
  802. // drivers
  803. // NOTE: remember to update GL_EXTENSIONS in glGetString.
  804. static PROC pfnSimGlExtProc(LPCSTR lpszProc)
  805. {
  806. // Extension is not supported by the generic implementation, return NULL.
  807. SetLastError(ERROR_PROC_NOT_FOUND);
  808. return((PROC) NULL);
  809. }
  810. /******************************Public*Routine******************************\
  811. *
  812. * wglCopyContext
  813. *
  814. * Copies all of one context's state to another one
  815. *
  816. * Returns:
  817. * TRUE if successful, FALSE otherwise
  818. *
  819. * History:
  820. * Fri May 26 14:57:17 1995 -by- Drew Bliss [drewb]
  821. * Created
  822. *
  823. \**************************************************************************/
  824. BOOL WINAPI
  825. wglCopyContext(HGLRC hrcSource, HGLRC hrcDest, UINT fuMask)
  826. {
  827. BOOL fRet;
  828. PLRC plrcSource, plrcDest;
  829. ULONG irc;
  830. PLHE plheRC;
  831. HANDLE hrcSrvSource, hrcSrvDest;
  832. GLFLUSH();
  833. fRet = FALSE;
  834. // Validate the contexts
  835. if (cLockHandle((ULONG_PTR)hrcSource) <= 0)
  836. {
  837. DBGLEVEL1(LEVEL_ERROR, "wglCopyContext: can't lock hrcSource 0x%lx\n",
  838. hrcSource);
  839. goto wglCopyContextEnd_nolock;
  840. }
  841. irc = MASKINDEX(hrcSource);
  842. plheRC = pLocalTable + irc;
  843. plrcSource = (PLRC)plheRC->pv;
  844. hrcSrvSource = (HANDLE) plheRC->hgre;
  845. ASSERTOPENGL(plrcSource->ident == LRC_IDENTIFIER,
  846. "wglCopyContext: Bad plrc\n");
  847. if (cLockHandle((ULONG_PTR)hrcDest) <= 0)
  848. {
  849. DBGLEVEL1(LEVEL_ERROR, "wglCopyContext: can't lock hrcDest 0x%lx\n",
  850. hrcDest);
  851. goto wglCopyContextEnd_onelock;
  852. }
  853. irc = MASKINDEX(hrcDest);
  854. plheRC = pLocalTable + irc;
  855. plrcDest = (PLRC)plheRC->pv;
  856. hrcSrvDest = (HANDLE) plheRC->hgre;
  857. ASSERTOPENGL(plrcDest->ident == LRC_IDENTIFIER,
  858. "wglCopyContext: Bad plrc\n");
  859. // Context can only be copied between like implementations so make
  860. // sure that both contexts are either driver contexts or generic
  861. // contexts
  862. if ((plrcSource->dhrc != 0) != (plrcDest->dhrc != 0))
  863. {
  864. DBGLEVEL(LEVEL_ERROR, "wglCopyContext: mismatched implementations\n");
  865. SetLastError(ERROR_INVALID_FUNCTION);
  866. goto wglCopyContextEnd;
  867. }
  868. // The destination context cannot be current to a thread
  869. if (plrcDest->tidCurrent != INVALID_THREAD_ID)
  870. {
  871. DBGLEVEL(LEVEL_ERROR, "wglCopyContext: destination has tidCurrent\n");
  872. SetLastError(ERROR_INVALID_HANDLE);
  873. goto wglCopyContextEnd;
  874. }
  875. if (plrcSource->dhrc == 0)
  876. {
  877. // For generic contexts, tell the server to share the lists
  878. fRet = __wglCopyContext(hrcSrvSource, hrcSrvDest, fuMask);
  879. if (!fRet)
  880. {
  881. DBGERROR("wglCopyContext: server call failed\n");
  882. }
  883. }
  884. else
  885. {
  886. // For device contexts tell the driver to copy the context
  887. // Ensure that both implementations are the same
  888. if (plrcSource->pGLDriver != plrcDest->pGLDriver)
  889. {
  890. DBGLEVEL(LEVEL_ERROR, "wglCopyContext: mismatched "
  891. "implementations\n");
  892. SetLastError(ERROR_INVALID_FUNCTION);
  893. goto wglCopyContextEnd;
  894. }
  895. ASSERTOPENGL(plrcSource->pGLDriver != NULL,
  896. "wglCopyContext: No GLDriver\n");
  897. // Older drivers may not support this entry point, so
  898. // fail the call if they don't
  899. if (plrcSource->pGLDriver->pfnDrvCopyContext == NULL)
  900. {
  901. WARNING("wglCopyContext called on driver context "
  902. "without driver support\n");
  903. SetLastError(ERROR_NOT_SUPPORTED);
  904. }
  905. else
  906. {
  907. fRet = plrcSource->pGLDriver->pfnDrvCopyContext(plrcSource->dhrc,
  908. plrcDest->dhrc,
  909. fuMask);
  910. }
  911. }
  912. wglCopyContextEnd:
  913. vUnlockHandle((ULONG_PTR)hrcDest);
  914. wglCopyContextEnd_onelock:
  915. vUnlockHandle((ULONG_PTR)hrcSource);
  916. wglCopyContextEnd_nolock:
  917. return fRet;
  918. }