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.

658 lines
18 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: makecur.c
  3. *
  4. * wglMakeCurrent implementation
  5. *
  6. * Created: 02-10-1997
  7. *
  8. * Copyright (c) 1993-1997 Microsoft Corporation
  9. \**************************************************************************/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. #include <context.h>
  13. #include <global.h>
  14. #include "metasup.h"
  15. #include "wgldef.h"
  16. /******************************Public*Routine******************************\
  17. *
  18. * __wglSetProcTable
  19. *
  20. * Callback function given to ICDs to set a proc table
  21. *
  22. \**************************************************************************/
  23. void APIENTRY
  24. __wglSetProcTable(PGLCLTPROCTABLE pglCltProcTable)
  25. {
  26. if (pglCltProcTable == (PGLCLTPROCTABLE) NULL)
  27. return;
  28. // It must have either 306 entries for version 1.0 or 336 entries for 1.1
  29. if (pglCltProcTable->cEntries != OPENGL_VERSION_100_ENTRIES &&
  30. pglCltProcTable->cEntries != OPENGL_VERSION_110_ENTRIES)
  31. {
  32. return;
  33. }
  34. // This function is called by client drivers which do not use
  35. // the EXT procs provided by opengl32. Use the null EXT proc
  36. // table to disable those stubs since they should never be
  37. // called anyway
  38. SetCltProcTable(pglCltProcTable, &glNullExtProcTable, TRUE);
  39. }
  40. /******************************Public*Routine******************************\
  41. *
  42. * CheckDeviceModes
  43. *
  44. * Ensures that the HDC doesn't have any disallowed state
  45. *
  46. * History:
  47. * Mon Aug 26 15:03:28 1996 -by- Drew Bliss [drewb]
  48. * Split from wglMakeCurrent
  49. *
  50. \**************************************************************************/
  51. BOOL CheckDeviceModes(HDC hdc)
  52. {
  53. SIZE szW, szV;
  54. XFORM xform;
  55. POINT pt;
  56. HRGN hrgnTmp;
  57. int iRgn;
  58. // For release 1, GDI transforms must be identity.
  59. // This is to allow GDI transform binding in future.
  60. switch (GetMapMode(hdc))
  61. {
  62. case MM_TEXT:
  63. break;
  64. case MM_ANISOTROPIC:
  65. if (!GetWindowExtEx(hdc, &szW)
  66. || !GetViewportExtEx(hdc, &szV)
  67. || szW.cx != szV.cx
  68. || szW.cy != szV.cy)
  69. goto wglMakeCurrent_xform_error;
  70. break;
  71. default:
  72. goto wglMakeCurrent_xform_error;
  73. }
  74. if (!GetViewportOrgEx(hdc, &pt) || pt.x != 0 || pt.y != 0)
  75. goto wglMakeCurrent_xform_error;
  76. if (!GetWindowOrgEx(hdc, &pt) || pt.x != 0 || pt.y != 0)
  77. goto wglMakeCurrent_xform_error;
  78. if (!GetWorldTransform(hdc, &xform))
  79. {
  80. // Win95 does not support GetWorldTransform.
  81. if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
  82. goto wglMakeCurrent_xform_error;
  83. }
  84. else if (xform.eDx != 0.0f || xform.eDy != 0.0f
  85. || xform.eM12 != 0.0f || xform.eM21 != 0.0f
  86. || xform.eM11 < 0.999f || xform.eM11 > 1.001f // allow rounding errors
  87. || xform.eM22 < 0.999f || xform.eM22 > 1.001f)
  88. {
  89. wglMakeCurrent_xform_error:
  90. DBGERROR("wglMakeCurrent: GDI transforms not identity\n");
  91. SetLastError(ERROR_TRANSFORM_NOT_SUPPORTED);
  92. return FALSE;
  93. }
  94. // For release 1, GDI clip region is not allowed.
  95. // This is to allow GDI clip region binding in future.
  96. if (!(hrgnTmp = CreateRectRgn(0, 0, 0, 0)))
  97. return FALSE;
  98. iRgn = GetClipRgn(hdc, hrgnTmp);
  99. if (!DeleteObject(hrgnTmp))
  100. ASSERTOPENGL(FALSE, "DeleteObject failed");
  101. switch (iRgn)
  102. {
  103. case -1: // error
  104. WARNING("wglMakeCurrent: GetClipRgn failed\n");
  105. return FALSE;
  106. case 0: // no initial clip region
  107. break;
  108. case 1: // has initial clip region
  109. DBGERROR("wglMakeCurrent: GDI clip region not allowed\n");
  110. SetLastError(ERROR_CLIPPING_NOT_SUPPORTED);
  111. return FALSE;
  112. }
  113. return TRUE;
  114. }
  115. /******************************Public*Routine******************************\
  116. *
  117. * MakeAnyCurrent
  118. *
  119. * Makes any type of context current
  120. *
  121. * History:
  122. * Mon Aug 26 15:00:44 1996 -by- Drew Bliss [drewb]
  123. * Created
  124. *
  125. \**************************************************************************/
  126. BOOL MakeAnyCurrent(HGLRC hrc, int ipfd, DWORD dwObjectType,
  127. GLWINDOWID *pgwid)
  128. {
  129. HGLRC hrcSrv;
  130. PLRC plrc;
  131. DWORD tidCurrent;
  132. ULONG irc;
  133. PLHE plheRC;
  134. PGLCLTPROCTABLE pglProcTable;
  135. PGLEXTPROCTABLE pglExtProcTable;
  136. POLYARRAY *pa;
  137. DBGENTRY("wglMakeCurrent\n");
  138. // If this is a new, uninitialized thread, try to initialize it
  139. if (CURRENT_GLTEBINFO() == NULL)
  140. {
  141. GLInitializeThread(DLL_THREAD_ATTACH);
  142. // If the teb was not set up at thread initialization, return failure.
  143. if (!CURRENT_GLTEBINFO())
  144. {
  145. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  146. return(FALSE);
  147. }
  148. }
  149. // There are four cases:
  150. //
  151. // 1. hrc is NULL and there is no current RC.
  152. // 2. hrc is NULL and there is a current RC.
  153. // 3. hrc is not NULL and there is a current RC.
  154. // 4. hrc is not NULL and there is no current RC.
  155. // Case 1: hrc is NULL and there is no current RC.
  156. // This is a noop, return success.
  157. if (hrc == (HGLRC) 0 && (GLTEB_CLTCURRENTRC() == (PLRC) NULL))
  158. return(TRUE);
  159. // Case 2: hrc is NULL and there is a current RC.
  160. // Make the current RC inactive.
  161. if (hrc == (HGLRC) 0 && (GLTEB_CLTCURRENTRC() != (PLRC) NULL))
  162. return(bMakeNoCurrent());
  163. // Get the current thread id.
  164. tidCurrent = GetCurrentThreadId();
  165. ASSERTOPENGL(tidCurrent != INVALID_THREAD_ID,
  166. "wglMakeCurrent: GetCurrentThreadId returned a bad value\n");
  167. // Validate the handles. hrc is not NULL here.
  168. ASSERTOPENGL(hrc != (HGLRC) NULL, "wglMakeCurrent: hrc is NULL\n");
  169. // Validate the RC.
  170. if (cLockHandle((ULONG_PTR)hrc) <= 0)
  171. {
  172. DBGLEVEL1(LEVEL_ERROR, "wglMakeCurrent: can't lock hrc 0x%lx\n", hrc);
  173. goto wglMakeCurrent_error_nolock;
  174. }
  175. irc = MASKINDEX(hrc);
  176. plheRC = pLocalTable + irc;
  177. plrc = (PLRC) plheRC->pv;
  178. hrcSrv = (HGLRC) plheRC->hgre;
  179. ASSERTOPENGL(plrc->ident == LRC_IDENTIFIER, "wglMakeCurrent: Bad plrc\n");
  180. #ifdef GL_METAFILE
  181. // Ensure that metafile RC's are made current only to
  182. // metafile DC's
  183. if (plrc->uiGlsCaptureContext != 0 && dwObjectType != OBJ_ENHMETADC)
  184. {
  185. DBGLEVEL(LEVEL_ERROR,
  186. "wglMakeCurrent: attempt to make meta RC current "
  187. "to non-meta DC\n");
  188. SetLastError(ERROR_INVALID_HANDLE);
  189. vUnlockHandle((ULONG_PTR)hrc);
  190. return FALSE;
  191. }
  192. // Ensure that non-metafile RC's are made current only to
  193. // non-metafile DC's
  194. if (plrc->uiGlsCaptureContext == 0 && dwObjectType == OBJ_ENHMETADC)
  195. {
  196. DBGLEVEL(LEVEL_ERROR,
  197. "wglMakeCurrent: attempt to make non-meta RC current "
  198. "to meta DC\n");
  199. SetLastError(ERROR_METAFILE_NOT_SUPPORTED);
  200. vUnlockHandle((ULONG_PTR)hrc);
  201. return FALSE;
  202. }
  203. #endif
  204. // If the RC is current, it must be current to this thread because
  205. // makecurrent locks down the handle.
  206. // If the given RC is already current to this thread, we will release it first,
  207. // then make it current again. This is to support DC/RC attribute bindings in
  208. // this function.
  209. ASSERTOPENGL(plrc->tidCurrent == INVALID_THREAD_ID ||
  210. plrc->tidCurrent == tidCurrent,
  211. "wglMakeCurrent: hrc is current to another thread\n");
  212. // Case 3: hrc is not NULL and there is a current RC.
  213. // This is case 2 followed by case 4.
  214. if (GLTEB_CLTCURRENTRC())
  215. {
  216. // First, make the current RC inactive.
  217. if (!bMakeNoCurrent())
  218. {
  219. DBGERROR("wglMakeCurrent: bMakeNoCurrent failed\n");
  220. vUnlockHandle((ULONG_PTR)hrc);
  221. return(FALSE);
  222. }
  223. // Second, make hrc current. Fall through to case 4.
  224. }
  225. // Case 4: hrc is not NULL and there is no current RC.
  226. ASSERTOPENGL(GLTEB_CLTCURRENTRC() == (PLRC) NULL,
  227. "wglMakeCurrent: There is a current RC!\n");
  228. // If the pixel format of the window or surface is different from that of
  229. // the RC, return error.
  230. if (ipfd != plrc->iPixelFormat)
  231. {
  232. DBGERROR("wglMakeCurrent: different hdc and hrc pixel formats\n");
  233. SetLastError(ERROR_INVALID_PIXEL_FORMAT);
  234. goto wglMakeCurrent_error;
  235. }
  236. // Since the client code manages the function table, we will make
  237. // either the server or the driver current.
  238. if (!plrc->dhrc)
  239. {
  240. // If this is a generic format, tell the server to make it current.
  241. #ifndef _CLIENTSIDE_
  242. // If the subbatch data has not been set up for this thread, set it up now.
  243. if (GLTEB_CLTSHAREDSECTIONINFO() == NULL)
  244. {
  245. if (!glsbCreateAndDuplicateSection(SHARED_SECTION_SIZE))
  246. {
  247. WARNING("wglMakeCurrent: unable to create section\n");
  248. goto wglMakeCurrent_error;
  249. }
  250. }
  251. #endif // !_CLIENTSIDE_
  252. if (!__wglMakeCurrent(pgwid, hrcSrv, plrc->uiGlsCaptureContext != 0))
  253. {
  254. DBGERROR("wglMakeCurrent: server failed\n");
  255. goto wglMakeCurrent_error;
  256. }
  257. // Get the generic function table or metafile function table
  258. #ifdef GL_METAFILE
  259. if (plrc->fCapturing)
  260. {
  261. MetaGlProcTables(&pglProcTable, &pglExtProcTable);
  262. }
  263. else
  264. #endif
  265. {
  266. // Use RGBA or CI proc table depending on the color mode.
  267. // The gc should be available by now.
  268. __GL_SETUP();
  269. if (gc->modes.colorIndexMode)
  270. pglProcTable = &glCltCIProcTable;
  271. else
  272. pglProcTable = &glCltRGBAProcTable;
  273. pglExtProcTable = &glExtProcTable;
  274. }
  275. }
  276. else
  277. {
  278. // If this is a device format, tell the driver to make it current.
  279. // Get the driver function table from the driver.
  280. // pfnDrvSetContext returns the address of the driver OpenGL function
  281. // table if successful; NULL otherwise.
  282. ASSERTOPENGL(plrc->pGLDriver, "wglMakeCurrent: No GLDriver\n");
  283. pglProcTable = plrc->pGLDriver->pfnDrvSetContext(pgwid->hdc,
  284. plrc->dhrc,
  285. __wglSetProcTable);
  286. if (pglProcTable == (PGLCLTPROCTABLE) NULL)
  287. {
  288. DBGERROR("wglMakeCurrent: pfnDrvSetContext failed\n");
  289. goto wglMakeCurrent_error;
  290. }
  291. // It must have either 306 entries for version 1.0 or 336 entries for 1.1
  292. if (pglProcTable->cEntries != OPENGL_VERSION_100_ENTRIES &&
  293. pglProcTable->cEntries != OPENGL_VERSION_110_ENTRIES)
  294. {
  295. DBGERROR("wglMakeCurrent: pfnDrvSetContext returned bad table\n");
  296. plrc->pGLDriver->pfnDrvReleaseContext(plrc->dhrc);
  297. SetLastError(ERROR_BAD_DRIVER);
  298. goto wglMakeCurrent_error;
  299. }
  300. DBGLEVEL1(LEVEL_INFO, "wglMakeCurrent: driver function table 0x%lx\n",
  301. pglProcTable);
  302. // Always use the null EXT proc table since client drivers don't
  303. // use opengl32's stubs for EXT procs
  304. pglExtProcTable = &glNullExtProcTable;
  305. }
  306. // Make hrc current.
  307. plrc->tidCurrent = tidCurrent;
  308. plrc->gwidCurrent = *pgwid;
  309. GLTEB_SET_CLTCURRENTRC(plrc);
  310. SetCltProcTable(pglProcTable, pglExtProcTable, TRUE);
  311. #ifdef GL_METAFILE
  312. // Set up metafile context if necessary
  313. if (plrc->fCapturing)
  314. {
  315. __GL_SETUP();
  316. ActivateMetaRc(plrc, pgwid->hdc);
  317. // Set the metafile's base dispatch table by resetting
  318. // the proc table. Since we know we're capturing, this
  319. // will cause the GLS capture exec table to be updated
  320. // with the RGBA or CI proc table, preparing the
  321. // GLS context for correct passthrough
  322. if (gc->modes.colorIndexMode)
  323. pglProcTable = &glCltCIProcTable;
  324. else
  325. pglProcTable = &glCltRGBAProcTable;
  326. pglExtProcTable = &glExtProcTable;
  327. SetCltProcTable(pglProcTable, pglExtProcTable, FALSE);
  328. }
  329. #endif
  330. // Initialize polyarray structure in the TEB.
  331. pa = GLTEB_CLTPOLYARRAY();
  332. pa->flags = 0; // not in begin mode
  333. if (!plrc->dhrc)
  334. {
  335. POLYMATERIAL *pm;
  336. __GL_SETUP();
  337. pa->pdBufferNext = &gc->vertex.pdBuf[0];
  338. pa->pdBuffer0 = &gc->vertex.pdBuf[0];
  339. pa->pdBufferMax = &gc->vertex.pdBuf[gc->vertex.pdBufSize - 1];
  340. // reset next DPA message offset
  341. pa->nextMsgOffset = PA_nextMsgOffset_RESET_VALUE;
  342. // Vertex buffer size may have changed. For example, a generic gc's
  343. // vertex buffer may be of a different size than a MCD vertex buffer.
  344. // If it has changed, free the polymaterial array and realloc it later.
  345. pm = GLTEB_CLTPOLYMATERIAL();
  346. if (pm)
  347. {
  348. if (pm->aMatSize !=
  349. gc->vertex.pdBufSize * 2 / POLYMATERIAL_ARRAY_SIZE + 1)
  350. FreePolyMaterial();
  351. }
  352. }
  353. // Keep the handle locked while it is current.
  354. return(TRUE);
  355. // An error has occured, release the current RC.
  356. wglMakeCurrent_error:
  357. vUnlockHandle((ULONG_PTR)hrc);
  358. wglMakeCurrent_error_nolock:
  359. if (GLTEB_CLTCURRENTRC() != (PLRC) NULL)
  360. (void) bMakeNoCurrent();
  361. return(FALSE);
  362. }
  363. /******************************Public*Routine******************************\
  364. *
  365. * WindowIdFromHdc
  366. *
  367. * Fills out a GLWINDOWID for an HDC
  368. *
  369. * History:
  370. * Wed Aug 28 18:33:19 1996 -by- Drew Bliss [drewb]
  371. * Created
  372. *
  373. \**************************************************************************/
  374. void APIENTRY WindowIdFromHdc(HDC hdc, GLWINDOWID *pgwid)
  375. {
  376. LPDIRECTDRAWSURFACE pdds;
  377. HDC hdcDriver;
  378. if (pfnGetSurfaceFromDC != NULL &&
  379. pfnGetSurfaceFromDC(hdc, &pdds, &hdcDriver) == DD_OK)
  380. {
  381. // Release reference on the surface since this surface value
  382. // is only used as an identifier.
  383. pdds->lpVtbl->Release(pdds);
  384. pgwid->iType = GLWID_DDRAW;
  385. pgwid->hwnd = NULL;
  386. pgwid->hdc = hdcDriver;
  387. pgwid->pdds = pdds;
  388. }
  389. else
  390. {
  391. pgwid->hdc = hdc;
  392. pgwid->hwnd = WindowFromDC(hdc);
  393. if (pgwid->hwnd == NULL)
  394. {
  395. pgwid->iType = GLWID_HDC;
  396. }
  397. else
  398. {
  399. pgwid->iType = GLWID_HWND;
  400. }
  401. pgwid->pdds = NULL;
  402. }
  403. }
  404. /******************************Public*Routine******************************\
  405. * wglMakeCurrent(HDC hdc, HGLRC hrc)
  406. *
  407. * Make the hrc current.
  408. * Both hrc and hdc must have the same pixel format.
  409. *
  410. * If an error occurs, the current RC, if any, is made not current!
  411. *
  412. * Arguments:
  413. * hdc - Device context.
  414. * hrc - Rendering context.
  415. *
  416. * History:
  417. * Tue Oct 26 10:25:26 1993 -by- Hock San Lee [hockl]
  418. * Wrote it.
  419. \**************************************************************************/
  420. BOOL WINAPI wglMakeCurrent(HDC hdc, HGLRC hrc)
  421. {
  422. int iPixelFormat;
  423. DWORD dwObjectType;
  424. GLWINDOWID gwid;
  425. DBGENTRY("wglMakeCurrent\n");
  426. if (GLTEB_CLTCURRENTRC() != NULL)
  427. {
  428. // Flush OpenGL calls.
  429. glFlush();
  430. // Avoid HDC validation for simple make-non-current cases
  431. if (hrc == NULL)
  432. {
  433. return bMakeNoCurrent();
  434. }
  435. }
  436. // Validate the DC.
  437. dwObjectType = wglObjectType(hdc);
  438. switch (dwObjectType)
  439. {
  440. case OBJ_DC:
  441. case OBJ_MEMDC:
  442. break;
  443. case OBJ_ENHMETADC:
  444. #ifdef GL_METAFILE
  445. if (pfnGdiAddGlsRecord == NULL)
  446. {
  447. DBGLEVEL1(LEVEL_ERROR, "wglMakeCurrent: metafile hdc: 0x%lx\n",
  448. hdc);
  449. SetLastError(ERROR_INVALID_HANDLE);
  450. return FALSE;
  451. }
  452. break;
  453. #else
  454. DBGLEVEL1(LEVEL_ERROR, "wglMakeCurrent: metafile hdc: 0x%lx\n", hdc);
  455. SetLastError(ERROR_INVALID_HANDLE);
  456. return FALSE;
  457. #endif
  458. case OBJ_METADC:
  459. default:
  460. // 16-bit metafiles are not supported
  461. DBGLEVEL1(LEVEL_ERROR, "wglMakeCurrent: bad hdc: 0x%lx\n", hdc);
  462. SetLastError(ERROR_INVALID_HANDLE);
  463. return FALSE;
  464. }
  465. if (!CheckDeviceModes(hdc))
  466. {
  467. return FALSE;
  468. }
  469. #ifdef GL_METAFILE
  470. // For metafile RC's, use the reference HDC rather than the
  471. // metafile DC
  472. // Skip pixel format checks
  473. if (dwObjectType == OBJ_ENHMETADC)
  474. {
  475. iPixelFormat = 0;
  476. goto NoPixelFormat;
  477. }
  478. #endif
  479. // Get the current pixel format of the window or surface.
  480. // If no pixel format has been set, return error.
  481. if (!(iPixelFormat = GetPixelFormat(hdc)))
  482. {
  483. WARNING("wglMakeCurrent: No pixel format set in hdc\n");
  484. return FALSE;
  485. }
  486. #ifdef GL_METAFILE
  487. NoPixelFormat:
  488. #endif
  489. WindowIdFromHdc(hdc, &gwid);
  490. return MakeAnyCurrent(hrc, iPixelFormat, dwObjectType, &gwid);
  491. }
  492. /******************************Public*Routine******************************\
  493. * bMakeNoCurrent
  494. *
  495. * Make the current RC inactive.
  496. *
  497. * History:
  498. * Tue Oct 26 10:25:26 1993 -by- Hock San Lee [hockl]
  499. * Wrote it.
  500. \**************************************************************************/
  501. BOOL bMakeNoCurrent(void)
  502. {
  503. BOOL bRet = FALSE; // assume error
  504. PLRC plrc = GLTEB_CLTCURRENTRC();
  505. DBGENTRY("bMakeNoCurrent\n");
  506. ASSERTOPENGL(plrc != (PLRC) NULL, "bMakeNoCurrent: No current RC!\n");
  507. ASSERTOPENGL(plrc->tidCurrent == GetCurrentThreadId(),
  508. "bMakeNoCurrent: Current RC does not belong to this thread!\n");
  509. ASSERTOPENGL(plrc->gwidCurrent.iType != GLWID_ERROR,
  510. "bMakeNoCurrent: Current surface is NULL!\n");
  511. if (!plrc->dhrc)
  512. {
  513. #ifdef GL_METAFILE
  514. // Reset metafile context if necessary
  515. if (plrc->uiGlsCaptureContext != 0)
  516. {
  517. DeactivateMetaRc(plrc);
  518. }
  519. #endif
  520. // If this is a generic format, tell the server to make the current RC inactive.
  521. bRet = __wglMakeCurrent(NULL, NULL, FALSE);
  522. if (!bRet)
  523. {
  524. DBGERROR("bMakeNoCurrent: server failed\n");
  525. }
  526. }
  527. else
  528. {
  529. // If this is a device format, tell the driver to make the current RC inactive.
  530. ASSERTOPENGL(plrc->pGLDriver, "wglMakeCurrent: No GLDriver\n");
  531. bRet = plrc->pGLDriver->pfnDrvReleaseContext(plrc->dhrc);
  532. if (!bRet)
  533. {
  534. DBGERROR("bMakeNoCurrent: pfnDrvReleaseContext failed\n");
  535. }
  536. }
  537. // Always make the current RC inactive.
  538. // The handle is also unlocked when the RC becomes inactive.
  539. plrc->tidCurrent = INVALID_THREAD_ID;
  540. plrc->gwidCurrent.iType = GLWID_ERROR;
  541. GLTEB_SET_CLTCURRENTRC(NULL);
  542. SetCltProcTable(&glNullCltProcTable, &glNullExtProcTable, TRUE);
  543. vUnlockHandle((ULONG_PTR)(plrc->hrc));
  544. return(bRet);
  545. }