Leaked source code of windows server 2003
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.

1496 lines
44 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: wcreate.c
  3. *
  4. * wgl Context creation routines
  5. *
  6. * Created: 08-27-1996
  7. * Author: Drew Bliss [drewb]
  8. *
  9. * Copyright (c) 1996 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #include <ddrawpr.h>
  14. #include <glscreen.h>
  15. #include <glgenwin.h>
  16. #include <gencx.h>
  17. #include "metasup.h"
  18. #include "wgldef.h"
  19. // List of loaded GL drivers for the process.
  20. // A driver is loaded only once per process. Once it is loaded,
  21. // it will not be freed until the process quits.
  22. static PGLDRIVER pGLDriverList = (PGLDRIVER) NULL;
  23. /******************************Public*Routine******************************\
  24. * iAllocLRC
  25. *
  26. * Allocates a LRC and a handle. Initializes the LDC to have the default
  27. * attributes. Returns the handle index. On error returns INVALID_INDEX.
  28. *
  29. * History:
  30. * Tue Oct 26 10:25:26 1993 -by- Hock San Lee [hockl]
  31. * Wrote it.
  32. \**************************************************************************/
  33. static LRC lrcDefault =
  34. {
  35. 0, // dhrc
  36. 0, // hrc
  37. 0, // iPixelFormat
  38. LRC_IDENTIFIER, // ident
  39. INVALID_THREAD_ID, // tidCurrent
  40. NULL, // pGLDriver
  41. GLWID_ERROR, NULL, NULL, NULL, // gwidCurrent
  42. GLWID_ERROR, NULL, NULL, NULL, // gwidCreate
  43. #ifdef GL_METAFILE
  44. 0, // uiGlsCaptureContext
  45. 0, // uiGlsPlaybackContext
  46. FALSE, // fCapturing
  47. 0, 0, 0, 0, 0, // Metafile scaling constants
  48. 0, 0, 0, 0.0f, 0.0f,
  49. #endif
  50. NULL, // GLubyte *pszExtensions
  51. #ifdef GL_METAFILE
  52. {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, // XFORM xformMeta
  53. NULL, // LPRECTL prclGlsBounds
  54. #endif
  55. NULL, 0, // DDraw texture formats
  56. };
  57. static ULONG iAllocLRC(int iPixelFormat)
  58. {
  59. ULONG irc = INVALID_INDEX;
  60. PLRC plrc;
  61. // Allocate a local RC.
  62. plrc = (PLRC) ALLOC(sizeof(LRC));
  63. if (plrc == (PLRC) NULL)
  64. {
  65. DBGERROR("Alloc failed\n");
  66. return(irc);
  67. }
  68. // Initialize the local RC.
  69. *plrc = lrcDefault;
  70. plrc->iPixelFormat = iPixelFormat;
  71. // Allocate a local handle.
  72. irc = iAllocHandle(LO_RC, 0, (PVOID) plrc);
  73. if (irc == INVALID_INDEX)
  74. {
  75. vFreeLRC(plrc);
  76. return(irc);
  77. }
  78. return(irc);
  79. }
  80. /******************************Public*Routine******************************\
  81. * vFreeLRC
  82. *
  83. * Free a local side RC.
  84. *
  85. * History:
  86. * Tue Oct 26 10:25:26 1993 -by- Hock San Lee [hockl]
  87. * Copied from gdi client.
  88. \**************************************************************************/
  89. VOID vFreeLRC(PLRC plrc)
  90. {
  91. // The driver will not be unloaded here. It is loaded for the process forever.
  92. // Some assertions.
  93. ASSERTOPENGL(plrc->ident == LRC_IDENTIFIER,
  94. "vFreeLRC: Bad plrc\n");
  95. ASSERTOPENGL(plrc->dhrc == (DHGLRC) 0,
  96. "vFreeLRC: Driver RC is not freed!\n");
  97. ASSERTOPENGL(plrc->tidCurrent == INVALID_THREAD_ID,
  98. "vFreeLRC: RC is current!\n");
  99. ASSERTOPENGL(plrc->gwidCurrent.iType == GLWID_ERROR,
  100. "vFreeLRC: Current surface is not NULL!\n");
  101. #ifdef GL_METAFILE
  102. ASSERTOPENGL(plrc->uiGlsCaptureContext == 0,
  103. "vFreeLRC: GLS capture context not freed");
  104. ASSERTOPENGL(plrc->uiGlsPlaybackContext == 0,
  105. "vFreeLRC: GLS playback context not freed");
  106. ASSERTOPENGL(plrc->fCapturing == FALSE,
  107. "vFreeLRC: GLS still capturing");
  108. #endif
  109. // Smash the identifier.
  110. plrc->ident = 0;
  111. // Free the memory.
  112. if (plrc->pszExtensions)
  113. FREE(plrc->pszExtensions);
  114. if (plrc->pddsdTexFormats != NULL)
  115. {
  116. FREE(plrc->pddsdTexFormats);
  117. }
  118. FREE(plrc);
  119. }
  120. /******************************Public*Routine******************************\
  121. * vCleanupAllLRC
  122. *
  123. * Process cleanup -- make sure all HGLRCs are deleted. This is done by
  124. * scanning the local handle table for all currently allocated objects
  125. * of type LO_RC and deleting them.
  126. *
  127. * Called *ONLY* during DLL process detach.
  128. *
  129. * History:
  130. * 24-Jul-1995 -by- Gilman Wong [gilmanw]
  131. * Wrote it.
  132. \**************************************************************************/
  133. VOID vCleanupAllLRC()
  134. {
  135. UINT ii;
  136. if ( pLocalTable )
  137. {
  138. ENTERCRITICALSECTION(&semLocal);
  139. // Scan handle table for handles of type LO_RC. Make sure to always
  140. // read the commit value since we need to periodically release the
  141. // semaphore.
  142. for (ii = 0; ii < *((volatile ULONG *)&cLheCommitted); ii++)
  143. {
  144. if ( pLocalTable[ii].iType == LO_RC )
  145. {
  146. if ( !wglDeleteContext((HGLRC) ULongToPtr(LHANDLE(ii))) )
  147. {
  148. WARNING1("bCleanupAllLRC: failed to remove hrc = 0x%lx\n",
  149. LHANDLE(ii));
  150. }
  151. }
  152. }
  153. LEAVECRITICALSECTION(&semLocal);
  154. }
  155. }
  156. /******************************Public*Routine******************************\
  157. *
  158. * GetDrvRegInfo
  159. *
  160. * Looks up driver registry information by name.
  161. * An old-style ICD registry entry has a REG_SZ value under the given name.
  162. * A new-style ICD registry entry has a key of the given name with
  163. * various values.
  164. *
  165. * This routine checks first for a key and then will optionally
  166. * try the value. If a key is not found then extended driver information
  167. * is filled out with the defaults.
  168. *
  169. * History:
  170. * Tue Apr 01 17:33:12 1997 -by- Drew Bliss [drewb]
  171. * Created
  172. *
  173. \**************************************************************************/
  174. typedef struct _GLDRVINFO
  175. {
  176. DWORD dwFlags;
  177. TCHAR tszDllName[MAX_GLDRIVER_NAME+1];
  178. DWORD dwVersion;
  179. DWORD dwDriverVersion;
  180. } GLDRVINFO;
  181. #ifdef _WIN95_
  182. #define STR_OPENGL_DRIVER_LIST (PCSTR)"Software\\Microsoft\\Windows\\CurrentVersion\\OpenGLDrivers"
  183. #else
  184. #define STR_OPENGL_DRIVER_LIST (PCWSTR)L"Software\\Microsoft\\Windows NT\\CurrentVersion\\OpenGLDrivers"
  185. #endif
  186. BOOL GetDrvRegInfo(PTCHAR ptszName, GLDRVINFO *pgdi)
  187. {
  188. HKEY hkDriverList = NULL;
  189. HKEY hkDriverInfo;
  190. DWORD dwDataType;
  191. DWORD cjSize;
  192. BOOL bRet;
  193. bRet = FALSE;
  194. // Open the registry key for the list of OpenGL drivers.
  195. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, STR_OPENGL_DRIVER_LIST,
  196. 0, KEY_READ, &hkDriverList) != ERROR_SUCCESS)
  197. {
  198. WARNING("RegOpenKeyEx failed\n");
  199. return bRet;
  200. }
  201. // Force a terminator on the DLL name so that we can check for
  202. // valid DLL name data.
  203. pgdi->tszDllName[MAX_GLDRIVER_NAME] = 0;
  204. cjSize = sizeof(TCHAR) * MAX_GLDRIVER_NAME;
  205. // Attempt to open a key under the driver's name.
  206. if (RegOpenKeyEx(hkDriverList, ptszName, 0, KEY_READ,
  207. &hkDriverInfo) == ERROR_SUCCESS)
  208. {
  209. // New-style driver entry. Fetch information from values.
  210. bRet = TRUE;
  211. if (RegQueryValueEx(hkDriverInfo, __TEXT("DLL"), NULL, &dwDataType,
  212. (LPBYTE)pgdi->tszDllName,
  213. &cjSize) != ERROR_SUCCESS ||
  214. dwDataType != REG_SZ)
  215. {
  216. WARNING("Invalid DLL value in ICD key\n");
  217. bRet = FALSE;
  218. }
  219. cjSize = sizeof(DWORD);
  220. if (bRet &&
  221. (RegQueryValueEx(hkDriverInfo, __TEXT("Flags"), NULL, &dwDataType,
  222. (LPBYTE)&pgdi->dwFlags,
  223. &cjSize) != ERROR_SUCCESS ||
  224. dwDataType != REG_DWORD))
  225. {
  226. WARNING("Invalid Flags value in ICD key\n");
  227. bRet = FALSE;
  228. }
  229. if (bRet &&
  230. (RegQueryValueEx(hkDriverInfo, __TEXT("Version"), NULL,
  231. &dwDataType, (LPBYTE)&pgdi->dwVersion,
  232. &cjSize) != ERROR_SUCCESS ||
  233. dwDataType != REG_DWORD))
  234. {
  235. WARNING("Invalid Version value in ICD key\n");
  236. bRet = FALSE;
  237. }
  238. if (bRet &&
  239. (RegQueryValueEx(hkDriverInfo, __TEXT("DriverVersion"), NULL,
  240. &dwDataType, (LPBYTE)&pgdi->dwDriverVersion,
  241. &cjSize) != ERROR_SUCCESS ||
  242. dwDataType != REG_DWORD))
  243. {
  244. WARNING("Invalid DriverVersion value in ICD key\n");
  245. bRet = FALSE;
  246. }
  247. // Mark as having full information.
  248. pgdi->dwFlags |= GLDRIVER_FULL_REGISTRY;
  249. RegCloseKey(hkDriverInfo);
  250. }
  251. else
  252. {
  253. // Attempt to fetch value under driver's name.
  254. if (RegQueryValueEx(hkDriverList, ptszName, NULL, &dwDataType,
  255. (LPBYTE)pgdi->tszDllName,
  256. &cjSize) != ERROR_SUCCESS ||
  257. dwDataType != REG_SZ)
  258. {
  259. WARNING1("RegQueryValueEx failed, %d\n", GetLastError());
  260. }
  261. else
  262. {
  263. // We found old-style information which only provides the
  264. // DLL name. Fill in the rest with defaults.
  265. //
  266. // Version and DriverVersion are not set here under the
  267. // assumption that the display driver set them in the
  268. // OPENGL_GETINFO escape since the old-style path requires
  269. // the escape to occur before getting here.
  270. pgdi->dwFlags = 0;
  271. bRet = TRUE;
  272. }
  273. }
  274. RegCloseKey(hkDriverList);
  275. // Validate the driver name. It must have some characters and
  276. // it must be terminated.
  277. if (bRet &&
  278. (pgdi->tszDllName[0] == 0 ||
  279. pgdi->tszDllName[MAX_GLDRIVER_NAME] != 0))
  280. {
  281. WARNING("Invalid DLL name information for ICD\n");
  282. bRet = FALSE;
  283. }
  284. #ifdef _WIN95_
  285. // Force client-side buffer calls for Win95.
  286. pgdi->dwFlags |= GLDRIVER_CLIENT_BUFFER_CALLS;
  287. #endif
  288. return bRet;
  289. }
  290. /******************************Public*Routine******************************\
  291. * bGetDriverInfo
  292. *
  293. * The HDC is used to determine the display driver name. This name in turn
  294. * is used as a subkey to search the registry for a corresponding OpenGL
  295. * driver name.
  296. *
  297. * The OpenGL driver name is returned in the buffer pointed to by pwszDriver.
  298. * If the name is not found or does not fit in the buffer, an error is
  299. * returned.
  300. *
  301. * Returns:
  302. * TRUE if sucessful.
  303. * FALSE if the driver name does not fit in the buffer or if an error occurs.
  304. *
  305. * History:
  306. * 16-Jan-1994 -by- Gilman Wong [gilmanw]
  307. * Wrote it.
  308. \**************************************************************************/
  309. BOOL bGetDriverInfo(HDC hdc, GLDRVINFO *pgdi)
  310. {
  311. GLDRVNAME dn;
  312. GLDRVNAMERET dnRet;
  313. // Get display driver name.
  314. dn.oglget.ulSubEsc = OPENGL_GETINFO_DRVNAME;
  315. if ( ExtEscape(hdc, OPENGL_GETINFO, sizeof(GLDRVNAME), (LPCSTR) &dn,
  316. sizeof(GLDRVNAMERET), (LPSTR) &dnRet) <= 0 )
  317. {
  318. WARNING("ExtEscape(OPENGL_GETINFO, "
  319. "OPENGL_GETINFO_DRVNAME) failed\n");
  320. return FALSE;
  321. }
  322. pgdi->dwVersion = dnRet.ulVersion;
  323. pgdi->dwDriverVersion = dnRet.ulDriverVersion;
  324. if (GetDrvRegInfo((PTCHAR)dnRet.awch, pgdi))
  325. {
  326. // Verify that the client-side driver version information
  327. // matches the information returned from the display driver.
  328. // Is this too restrictive? Old scheme used
  329. // DrvValidateVersion to allow the client-side DLL to validate
  330. // the display driver's version however it felt like.
  331. // In the new scheme DrvValidateVersion is mostly useless because
  332. // of the below code.
  333. return pgdi->dwVersion == dnRet.ulVersion &&
  334. pgdi->dwDriverVersion == dnRet.ulDriverVersion;
  335. }
  336. else
  337. {
  338. return FALSE;
  339. }
  340. }
  341. /*****************************Private*Routine******************************\
  342. *
  343. * wglCbSetCurrentValue
  344. *
  345. * Sets a thread-local value for a client-side driver
  346. *
  347. * History:
  348. * Wed Dec 21 15:10:40 1994 -by- Drew Bliss [drewb]
  349. * Created
  350. *
  351. \**************************************************************************/
  352. void APIENTRY wglCbSetCurrentValue(VOID *pv)
  353. {
  354. GLTEB_SET_CLTDRIVERSLOT(pv);
  355. }
  356. /*****************************Private*Routine******************************\
  357. *
  358. * wglCbGetCurrentValue
  359. *
  360. * Gets a thread-local value for a client-side driver
  361. *
  362. * History:
  363. * Wed Dec 21 15:11:32 1994 -by- Drew Bliss [drewb]
  364. * Created
  365. *
  366. \**************************************************************************/
  367. PVOID APIENTRY wglCbGetCurrentValue(void)
  368. {
  369. return GLTEB_CLTDRIVERSLOT();
  370. }
  371. /******************************Public*Routine******************************\
  372. *
  373. * wglCbGetDhglrc
  374. *
  375. * Translates an HGLRC to a DHGLRC for a client-side driver
  376. *
  377. * History:
  378. * Mon Jan 16 17:03:38 1995 -by- Drew Bliss [drewb]
  379. * Created
  380. *
  381. \**************************************************************************/
  382. DHGLRC APIENTRY wglCbGetDhglrc(HGLRC hrc)
  383. {
  384. PLRC plrc;
  385. ULONG irc;
  386. PLHE plheRC;
  387. irc = MASKINDEX(hrc);
  388. plheRC = pLocalTable + irc;
  389. if ((irc >= cLheCommitted) ||
  390. (!MATCHUNIQ(plheRC, hrc)) ||
  391. ((plheRC->iType != LO_RC))
  392. )
  393. {
  394. DBGLEVEL1(LEVEL_ERROR, "wglCbGetDhglrc: invalid hrc 0x%lx\n", hrc);
  395. SetLastError(ERROR_INVALID_HANDLE);
  396. return 0;
  397. }
  398. plrc = (PLRC)plheRC->pv;
  399. ASSERTOPENGL(plrc->ident == LRC_IDENTIFIER,
  400. "wglCbGetDhglrc: Bad plrc\n");
  401. return plrc->dhrc;
  402. }
  403. /******************************Public*Routine******************************\
  404. *
  405. * wglCbGetDdHandle
  406. *
  407. * Callback to allow ICDs to extract kernel-mode handles for DDraw surfaces
  408. *
  409. * History:
  410. * Tue Feb 25 17:14:29 1997 -by- Drew Bliss [drewb]
  411. * Created
  412. *
  413. \**************************************************************************/
  414. HANDLE APIENTRY wglCbGetDdHandle(LPDIRECTDRAWSURFACE pdds)
  415. {
  416. return (HANDLE)(((LPDDRAWI_DDRAWSURFACE_INT)pdds)->lpLcl)->hDDSurface;
  417. }
  418. // wgl's default callback procedures
  419. #define CALLBACK_PROC_COUNT 4
  420. static PROC __wglCallbackProcs[CALLBACK_PROC_COUNT] =
  421. {
  422. (PROC)wglCbSetCurrentValue,
  423. (PROC)wglCbGetCurrentValue,
  424. (PROC)wglCbGetDhglrc,
  425. (PROC)wglCbGetDdHandle
  426. };
  427. static char *pszDriverEntryPoints[] =
  428. {
  429. "DrvCreateContext",
  430. "DrvDeleteContext",
  431. "DrvSetContext",
  432. "DrvReleaseContext",
  433. "DrvCopyContext",
  434. "DrvCreateLayerContext",
  435. "DrvShareLists",
  436. "DrvGetProcAddress",
  437. "DrvDescribeLayerPlane",
  438. "DrvSetLayerPaletteEntries",
  439. "DrvGetLayerPaletteEntries",
  440. "DrvRealizeLayerPalette",
  441. "DrvSwapLayerBuffers",
  442. "DrvCreateDirectDrawContext",
  443. "DrvEnumTextureFormats",
  444. "DrvBindDirectDrawTexture",
  445. "DrvSwapMultipleBuffers",
  446. "DrvDescribePixelFormat",
  447. "DrvSetPixelFormat",
  448. "DrvSwapBuffers"
  449. };
  450. #define DRIVER_ENTRY_POINTS (sizeof(pszDriverEntryPoints)/sizeof(char *))
  451. /******************************Public*Routine******************************\
  452. * pgldrvLoadInstalledDriver
  453. *
  454. * Loads the opengl driver for the given device. Once the driver is loaded,
  455. * it will not be freed until the process goes away! It is loaded only once
  456. * for each process that references it.
  457. *
  458. * Returns the GLDRIVER structure if the driver is loaded.
  459. * Returns NULL if no driver is found or an error occurs.
  460. *
  461. * History:
  462. * Tue Oct 26 10:25:26 1993 -by- Hock San Lee [hockl]
  463. * Rewrote it.
  464. \**************************************************************************/
  465. PGLDRIVER APIENTRY pgldrvLoadInstalledDriver(HDC hdc)
  466. {
  467. GLDRVINFO gdi;
  468. PGLDRIVER pGLDriverNext;
  469. PGLDRIVER pGLDriver = (PGLDRIVER) NULL; // needed by clean up
  470. PGLDRIVER pGLDriverRet = (PGLDRIVER) NULL; // return value, assume error
  471. PFN_DRVVALIDATEVERSION pfnDrvValidateVersion = (PFN_DRVVALIDATEVERSION) NULL;
  472. PFN_DRVSETCALLBACKPROCS pfnDrvSetCallbackProcs;
  473. DWORD dwEscape;
  474. int i;
  475. PROC *pproc;
  476. GLGENwindow *pwnd;
  477. GLWINDOWID gwid;
  478. DBGENTRY("pgldrvLoadInstalledDriver\n");
  479. // Try to grab the cached pgldrv from the GLGENwindow if it exists.
  480. // This only works for DCs that have a window with a device pixel format.
  481. WindowIdFromHdc(hdc, &gwid);
  482. pwnd = pwndGetFromID(&gwid);
  483. if (pwnd)
  484. {
  485. ULONG ulFlags;
  486. ulFlags = pwnd->ulFlags;
  487. pGLDriverRet = (PGLDRIVER) pwnd->pvDriver;
  488. pwndRelease(pwnd);
  489. if ( ulFlags & GLGENWIN_DRIVERSET )
  490. {
  491. return pGLDriverRet;
  492. }
  493. }
  494. // Do a quick check and see if this driver even understands OpenGL
  495. dwEscape = OPENGL_GETINFO;
  496. if (ExtEscape(hdc, QUERYESCSUPPORT, sizeof(dwEscape), (LPCSTR)&dwEscape,
  497. 0, NULL) <= 0)
  498. {
  499. // Don't output a message since this code path is traversed often
  500. // for the pixel format routines.
  501. #ifdef CHECK_DEFAULT_ICD
  502. // The display driver doesn't support a specific ICD. Check
  503. // for a default ICD. It must have full registry information.
  504. if (!GetDrvRegInfo(__TEXT("Default"), &gdi) ||
  505. (gdi.dwFlags & GLDRIVER_FULL_REGISTRY) == 0)
  506. {
  507. return NULL;
  508. }
  509. #else
  510. return NULL;
  511. #endif
  512. }
  513. // Determine driver info from hdc
  514. else if ( !bGetDriverInfo(hdc, &gdi) )
  515. {
  516. WARNING("bGetDriverInfo failed\n");
  517. return NULL;
  518. }
  519. // Load the driver only once per process.
  520. ENTERCRITICALSECTION(&semLocal);
  521. // Look for the OpenGL driver in the previously loaded driver list.
  522. for (pGLDriverNext = pGLDriverList;
  523. pGLDriverNext != (PGLDRIVER) NULL;
  524. pGLDriverNext = pGLDriverNext->pGLDriver)
  525. {
  526. PTCHAR ptszDllName1 = pGLDriverNext->tszDllName;
  527. PTCHAR ptszDllName2 = gdi.tszDllName;
  528. while (*ptszDllName1 == *ptszDllName2)
  529. {
  530. // If we find one, return that driver.
  531. if (*ptszDllName1 == 0)
  532. {
  533. DBGINFO("pgldrvLoadInstalledDriver: "
  534. "return previously loaded driver\n");
  535. pGLDriverRet = pGLDriverNext; // found one
  536. goto pgldrvLoadInstalledDriver_crit_exit;
  537. }
  538. ptszDllName1++;
  539. ptszDllName2++;
  540. }
  541. }
  542. // Load the driver for the first time.
  543. // Allocate the driver data.
  544. pGLDriver = (PGLDRIVER) ALLOC(sizeof(GLDRIVER));
  545. if (pGLDriver == (PGLDRIVER) NULL)
  546. {
  547. WARNING("Alloc failed\n");
  548. goto pgldrvLoadInstalledDriver_crit_exit; // error
  549. }
  550. // Load the driver.
  551. pGLDriver->hModule = LoadLibrary(gdi.tszDllName);
  552. if (pGLDriver->hModule == (HINSTANCE) NULL)
  553. {
  554. WARNING("pgldrvLoadInstalledDriver: LoadLibrary failed\n");
  555. goto pgldrvLoadInstalledDriver_crit_exit; // error
  556. }
  557. // Copy the driver info.
  558. memcpy
  559. (
  560. pGLDriver->tszDllName,
  561. gdi.tszDllName,
  562. (MAX_GLDRIVER_NAME + 1) * sizeof(TCHAR)
  563. );
  564. pGLDriver->dwFlags = gdi.dwFlags;
  565. // Get the proc addresses.
  566. // DrvGetProcAddress is optional. It must be provided if a driver supports
  567. // extensions.
  568. pfnDrvValidateVersion = (PFN_DRVVALIDATEVERSION)
  569. GetProcAddress(pGLDriver->hModule, "DrvValidateVersion");
  570. pfnDrvSetCallbackProcs = (PFN_DRVSETCALLBACKPROCS)
  571. GetProcAddress(pGLDriver->hModule, "DrvSetCallbackProcs");
  572. pproc = (PROC *)&pGLDriver->pfnDrvCreateContext;
  573. for (i = 0; i < DRIVER_ENTRY_POINTS; i++)
  574. {
  575. *pproc++ =
  576. GetProcAddress(pGLDriver->hModule, pszDriverEntryPoints[i]);
  577. }
  578. if ((pGLDriver->pfnDrvCreateContext == NULL &&
  579. pGLDriver->pfnDrvCreateLayerContext == NULL) ||
  580. pGLDriver->pfnDrvDeleteContext == NULL ||
  581. pGLDriver->pfnDrvSetContext == NULL ||
  582. pGLDriver->pfnDrvReleaseContext == NULL ||
  583. ((gdi.dwFlags & GLDRIVER_CLIENT_BUFFER_CALLS) &&
  584. (pGLDriver->pfnDrvDescribePixelFormat == NULL ||
  585. pGLDriver->pfnDrvSetPixelFormat == NULL ||
  586. pGLDriver->pfnDrvSwapBuffers == NULL)) ||
  587. pfnDrvValidateVersion == NULL)
  588. {
  589. WARNING("pgldrvLoadInstalledDriver: GetProcAddress failed\n");
  590. goto pgldrvLoadInstalledDriver_crit_exit; // error
  591. }
  592. // Validate the driver.
  593. //!!!XXX -- Need to define a manifest constant for the ulVersion number
  594. // in this release. Where should it go?
  595. if ( gdi.dwVersion != 2 || !pfnDrvValidateVersion(gdi.dwDriverVersion) )
  596. {
  597. WARNING2("pgldrvLoadInstalledDriver: bad driver version "
  598. "(0x%lx, 0x%lx)\n", gdi.dwVersion, gdi.dwDriverVersion);
  599. goto pgldrvLoadInstalledDriver_crit_exit; // error
  600. }
  601. // Everything is golden.
  602. // Add it to the driver list.
  603. pGLDriver->pGLDriver = pGLDriverList;
  604. pGLDriverList = pGLDriver;
  605. pGLDriverRet = pGLDriver; // set return value
  606. DBGINFO("pgldrvLoadInstalledDriver: Loaded an OpenGL driver\n");
  607. // Set the callback procs for the driver if the driver supports doing so
  608. if (pfnDrvSetCallbackProcs != NULL)
  609. {
  610. pfnDrvSetCallbackProcs(CALLBACK_PROC_COUNT, __wglCallbackProcs);
  611. }
  612. // Error clean up in the critical section.
  613. pgldrvLoadInstalledDriver_crit_exit:
  614. if (pGLDriverRet == (PGLDRIVER) NULL)
  615. {
  616. if (pGLDriver != (PGLDRIVER) NULL)
  617. {
  618. if (pGLDriver->hModule != (HINSTANCE) NULL)
  619. if (!FreeLibrary(pGLDriver->hModule))
  620. RIP("FreeLibrary failed\n");
  621. FREE(pGLDriver);
  622. }
  623. }
  624. LEAVECRITICALSECTION(&semLocal);
  625. return(pGLDriverRet);
  626. }
  627. /******************************Public*Routine******************************\
  628. *
  629. * CreateAnyContext
  630. *
  631. * Base worker function for creating all kinds of contexts
  632. *
  633. * History:
  634. * Mon Aug 26 14:41:31 1996 -by- Drew Bliss [drewb]
  635. * Created
  636. *
  637. \**************************************************************************/
  638. HGLRC CreateAnyContext(GLSURF *pgsurf)
  639. {
  640. PLHE plheRC;
  641. ULONG irc;
  642. HGLRC hrc;
  643. PLRC plrc;
  644. #ifndef _WIN95_
  645. // _OPENGL_NT_
  646. // On NT, client-side drivers can use special fast TEB access macros
  647. // which rely on glContext being at a fixed offset into the
  648. // TEB. Assert that the offset is where we think it is
  649. // to catch any TEB changes which could break client-side
  650. // drivers
  651. // This assert is here in wglCreateContext to ensure that it
  652. // is checked very early in OpenGL operation
  653. ASSERTOPENGL(FIELD_OFFSET(TEB, glContext) == TeglContext,
  654. "TEB.glContext at wrong offset\n");
  655. ASSERTOPENGL(FIELD_OFFSET(TEB, glDispatchTable) == TeglDispatchTable,
  656. "TEB.glDispatchTable at wrong offset\n");
  657. ASSERTOPENGL(FIELD_OFFSET(TEB, glReserved1) == TeglReserved1,
  658. "TEB.glReserved1 at wrong offset\n");
  659. #if !defined(_WIN64)
  660. ASSERTOPENGL(FIELD_OFFSET(TEB, glReserved1)+(18 * sizeof(ULONG_PTR)) == TeglPaTeb,
  661. "TEB.glPaTeb at wrong offset\n");
  662. #endif
  663. ASSERTOPENGL(FIELD_OFFSET(TEB, glReserved2) == TeglReserved2,
  664. "TEB.glReserved2 at wrong offset\n");
  665. ASSERTOPENGL(FIELD_OFFSET(TEB, glSectionInfo) == TeglSectionInfo,
  666. "TEB.glSectionInfo at wrong offset\n");
  667. ASSERTOPENGL(FIELD_OFFSET(TEB, glSection) == TeglSection,
  668. "TEB.glSection at wrong offset\n");
  669. ASSERTOPENGL(FIELD_OFFSET(TEB, glTable) == TeglTable,
  670. "TEB.glTable at wrong offset\n");
  671. ASSERTOPENGL(FIELD_OFFSET(TEB, glCurrentRC) == TeglCurrentRC,
  672. "TEB.glCurrentRC at wrong offset\n");
  673. #endif
  674. // Create the local RC.
  675. ENTERCRITICALSECTION(&semLocal);
  676. irc = iAllocLRC(pgsurf->ipfd);
  677. if (irc == INVALID_INDEX ||
  678. cLockHandle((ULONG_PTR)(hrc = (HGLRC) ULongToPtr(LHANDLE(irc)))) <= 0)
  679. {
  680. // cLockHandle should never fail or we will need to free the handle.
  681. ASSERTOPENGL(irc == INVALID_INDEX, "cLockHandle should not fail!\n");
  682. LEAVECRITICALSECTION(&semLocal);
  683. return((HGLRC) 0);
  684. }
  685. LEAVECRITICALSECTION(&semLocal);
  686. plheRC = &pLocalTable[irc];
  687. plrc = (PLRC) plheRC->pv;
  688. // Remember the creation DC. This needs to be done early because
  689. // it is referenced in some code paths.
  690. plrc->gwidCreate.hdc = pgsurf->hdc;
  691. if (pgsurf->dwFlags & GLSURF_HDC)
  692. {
  693. plrc->gwidCreate.hwnd = pgsurf->hwnd;
  694. if (plrc->gwidCreate.hwnd == NULL)
  695. {
  696. plrc->gwidCreate.iType = GLWID_HDC;
  697. }
  698. else
  699. {
  700. plrc->gwidCreate.iType = GLWID_HWND;
  701. }
  702. plrc->gwidCreate.pdds = NULL;
  703. }
  704. else
  705. {
  706. plrc->gwidCreate.iType = GLWID_DDRAW;
  707. plrc->gwidCreate.pdds = pgsurf->dd.gddsFront.pdds;
  708. plrc->gwidCreate.hwnd = NULL;
  709. }
  710. if (!(pgsurf->pfd.dwFlags & PFD_GENERIC_FORMAT) &&
  711. !(pgsurf->pfd.dwFlags & PFD_GENERIC_ACCELERATED))
  712. {
  713. // If it is a device format, load the installable OpenGL driver.
  714. // Find and load the OpenGL driver referenced by this DC.
  715. if (!(plrc->pGLDriver = pgldrvLoadInstalledDriver(pgsurf->hdc)))
  716. goto wglCreateContext_error;
  717. // Create a driver context.
  718. // If the surface is a DirectDraw surface use the DirectDraw
  719. // entry point
  720. if (pgsurf->dwFlags & GLSURF_DIRECTDRAW)
  721. {
  722. if (plrc->pGLDriver->pfnDrvCreateDirectDrawContext == NULL)
  723. {
  724. SetLastError(ERROR_INVALID_FUNCTION);
  725. goto wglCreateContext_error;
  726. }
  727. plrc->dhrc = plrc->pGLDriver->pfnDrvCreateDirectDrawContext(
  728. pgsurf->hdc, pgsurf->dd.gddsFront.pdds, pgsurf->ipfd);
  729. if (plrc->dhrc == 0)
  730. {
  731. WARNING("wglCreateContext: "
  732. "pfnDrvCreateDirectDrawContext failed\n");
  733. goto wglCreateContext_error;
  734. }
  735. }
  736. // If the driver supports layers then create a context for the
  737. // given layer. Otherwise reject all layers except for the
  738. // main plane and call the layer-less create
  739. else if (plrc->pGLDriver->pfnDrvCreateLayerContext != NULL)
  740. {
  741. if (!(plrc->dhrc =
  742. plrc->pGLDriver->pfnDrvCreateLayerContext(pgsurf->hdc,
  743. pgsurf->iLayer)))
  744. {
  745. WARNING("wglCreateContext: pfnDrvCreateLayerContext failed\n");
  746. goto wglCreateContext_error;
  747. }
  748. }
  749. else if (pgsurf->iLayer != 0)
  750. {
  751. WARNING("wglCreateContext: "
  752. "Layer given for driver without layer support\n");
  753. SetLastError(ERROR_INVALID_FUNCTION);
  754. goto wglCreateContext_error;
  755. }
  756. else if (!(plrc->dhrc =
  757. plrc->pGLDriver->pfnDrvCreateContext(pgsurf->hdc)))
  758. {
  759. WARNING("wglCreateContext: pfnDrvCreateContext failed\n");
  760. goto wglCreateContext_error;
  761. }
  762. }
  763. else
  764. {
  765. GLCLTPROCTABLE *pgcpt;
  766. GLEXTPROCTABLE *pgept;
  767. __GLcontext *gc;
  768. // Unless supported by MCD, the generic implementation doesn't
  769. // support layers
  770. if ((pgsurf->iLayer != 0) &&
  771. !(pgsurf->pfd.dwFlags & PFD_GENERIC_ACCELERATED))
  772. {
  773. WARNING("wglCreateContext: Layer given to generic\n");
  774. goto wglCreateContext_error;
  775. }
  776. #ifdef GL_METAFILE
  777. // Create a metafile context if necessary
  778. if (pgsurf->dwFlags & GLSURF_METAFILE)
  779. {
  780. if (!CreateMetaRc(pgsurf->hdc, plrc))
  781. {
  782. WARNING("wglCreateContext: CreateMetaRc failed\n");
  783. goto wglCreateContext_error;
  784. }
  785. }
  786. #endif
  787. // If it is a generic format, call the generic OpenGL server.
  788. // Create a server RC.
  789. plheRC->hgre = (ULONG_PTR) __wglCreateContext(&plrc->gwidCreate, pgsurf);
  790. if (plheRC->hgre == 0)
  791. goto wglCreateContext_error;
  792. // Set up the default dispatch tables for display list playback
  793. gc = (__GLcontext *)plheRC->hgre;
  794. if (gc->modes.colorIndexMode)
  795. pgcpt = &glCltCIProcTable;
  796. else
  797. pgcpt = &glCltRGBAProcTable;
  798. pgept = &glExtProcTable;
  799. memcpy(&gc->savedCltProcTable.glDispatchTable, &pgcpt->glDispatchTable,
  800. pgcpt->cEntries*sizeof(PROC));
  801. memcpy(&gc->savedExtProcTable.glDispatchTable, &pgept->glDispatchTable,
  802. pgept->cEntries*sizeof(PROC));
  803. }
  804. DBGLEVEL3(LEVEL_INFO,
  805. "wglCreateContext: plrc = 0x%lx, pGLDriver = 0x%lx, hgre = 0x%lx\n",
  806. plrc, plrc->pGLDriver, plheRC->hgre);
  807. // Success, return the result.
  808. plrc->hrc = hrc;
  809. vUnlockHandle((ULONG_PTR)hrc);
  810. return hrc;
  811. wglCreateContext_error:
  812. // Fail, clean up and return 0.
  813. #ifdef GL_METAFILE
  814. // Clean up metafile context if necessary
  815. if (plrc->uiGlsCaptureContext != 0)
  816. {
  817. DeleteMetaRc(plrc);
  818. }
  819. #endif
  820. DBGERROR("wglCreateContext failed\n");
  821. ASSERTOPENGL(plrc->dhrc == (DHGLRC) 0, "wglCreateContext: dhrc != 0\n");
  822. vFreeLRC(plrc);
  823. vFreeHandle(irc); // it unlocks handle too
  824. return NULL;
  825. }
  826. /******************************Public*Routine******************************\
  827. *
  828. * CreateMetafileSurf
  829. *
  830. * Fills out a GLSURF for a metafile DC
  831. *
  832. * History:
  833. * Tue Aug 27 11:41:35 1996 -by- Drew Bliss [drewb]
  834. * Created
  835. *
  836. \**************************************************************************/
  837. #ifdef GL_METAFILE
  838. void CreateMetafileSurf(HDC hdc, int iLayer, GLSURF *pgsurf)
  839. {
  840. pgsurf->dwFlags = GLSURF_HDC | GLSURF_METAFILE;
  841. pgsurf->iLayer = iLayer;
  842. // Metafile surfaces don't have a real pixel format
  843. pgsurf->ipfd = 0;
  844. // Create a fake format of 24-bit DIB with BGR
  845. memset(&pgsurf->pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
  846. pgsurf->pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
  847. pgsurf->pfd.nVersion = 1;
  848. pgsurf->pfd.dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL |
  849. PFD_GENERIC_FORMAT;
  850. pgsurf->pfd.iPixelType = PFD_TYPE_RGBA;
  851. pgsurf->pfd.cColorBits = 24;
  852. pgsurf->pfd.cStencilBits = 8;
  853. pgsurf->pfd.cRedBits = 8;
  854. pgsurf->pfd.cRedShift = 16;
  855. pgsurf->pfd.cGreenBits = 8;
  856. pgsurf->pfd.cGreenShift = 8;
  857. pgsurf->pfd.cBlueBits = 8;
  858. pgsurf->pfd.cBlueShift = 0;
  859. pgsurf->pfd.cDepthBits = 16;
  860. pgsurf->pfd.iLayerType = PFD_MAIN_PLANE;
  861. pgsurf->hdc = hdc;
  862. }
  863. #endif
  864. /******************************Public*Routine******************************\
  865. * wglSurfacePixelFormat
  866. *
  867. * wglDescribePixelFormat doesn't describe the format of the surface we want
  868. * to render into. Some fields need to be fixed up if the surface is RGB,
  869. * BGR, or BITFIELDS.
  870. *
  871. * Expects a Describe'd pixel format as input
  872. *
  873. \**************************************************************************/
  874. VOID APIENTRY wglSurfacePixelFormat(HDC hdc, PIXELFORMATDESCRIPTOR *ppfd)
  875. {
  876. HBITMAP hbm;
  877. BITMAP bm;
  878. ULONG cBitmapColorBits;
  879. hbm = CreateCompatibleBitmap(hdc, 1, 1);
  880. if ( hbm )
  881. {
  882. if ( GetObject(hbm, sizeof(bm), &bm) )
  883. {
  884. cBitmapColorBits = bm.bmPlanes * bm.bmBitsPixel;
  885. #if DBG
  886. // If dynamic color depth caused depth mismatch one of two
  887. // things will happen: 1) bitmap creation will fail because
  888. // we failed to fill in color format, or 2) drawing will
  889. // be incorrect. We will not crash.
  890. if (cBitmapColorBits != ppfd->cColorBits)
  891. WARNING("pixel format/surface color depth mismatch\n");
  892. #endif
  893. if ( cBitmapColorBits >= 16 )
  894. __wglGetBitfieldColorFormat(hdc, cBitmapColorBits, ppfd,
  895. TRUE);
  896. }
  897. else
  898. {
  899. WARNING("wglSurfacePixelFormat: GetObject failed\n");
  900. }
  901. DeleteObject(hbm);
  902. }
  903. else
  904. {
  905. WARNING("wglSurfacePixelFormat: Unable to create cbm\n");
  906. }
  907. }
  908. /******************************Public*Routine******************************\
  909. * bLayerPixelFormat
  910. *
  911. * Fake up a pixel format using the layer descriptor format.
  912. *
  913. * We use this to describe the layer plane in a format that the generic
  914. * context can understand.
  915. *
  916. * Expects a Describe'd pixel format as input for the flags
  917. *
  918. \**************************************************************************/
  919. BOOL FASTCALL bLayerPixelFormat(HDC hdc, PIXELFORMATDESCRIPTOR *ppfd,
  920. int ipfd, LONG iLayer)
  921. {
  922. LAYERPLANEDESCRIPTOR lpd;
  923. if (!wglDescribeLayerPlane(hdc, ipfd, iLayer, sizeof(lpd), &lpd))
  924. return FALSE;
  925. ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
  926. ppfd->nVersion = 1;
  927. ppfd->dwFlags = (ppfd->dwFlags & (PFD_GENERIC_FORMAT |
  928. PFD_GENERIC_ACCELERATED)) |
  929. (lpd.dwFlags & ~(LPD_SHARE_DEPTH | LPD_SHARE_STENCIL |
  930. LPD_SHARE_ACCUM | LPD_TRANSPARENT));
  931. ppfd->iPixelType = lpd.iPixelType;
  932. ppfd->cColorBits = lpd.cColorBits;
  933. ppfd->cRedBits = lpd.cRedBits ;
  934. ppfd->cRedShift = lpd.cRedShift ;
  935. ppfd->cGreenBits = lpd.cGreenBits ;
  936. ppfd->cGreenShift = lpd.cGreenShift;
  937. ppfd->cBlueBits = lpd.cBlueBits ;
  938. ppfd->cBlueShift = lpd.cBlueShift ;
  939. ppfd->cAlphaBits = lpd.cAlphaBits ;
  940. ppfd->cAlphaShift = lpd.cAlphaShift;
  941. if (!(lpd.dwFlags & LPD_SHARE_ACCUM))
  942. {
  943. ppfd->cAccumBits = 0;
  944. ppfd->cAccumRedBits = 0;
  945. ppfd->cAccumGreenBits = 0;
  946. ppfd->cAccumBlueBits = 0;
  947. ppfd->cAccumAlphaBits = 0;
  948. }
  949. if (!(lpd.dwFlags & LPD_SHARE_DEPTH))
  950. {
  951. ppfd->cDepthBits = 0;
  952. }
  953. if (!(lpd.dwFlags & LPD_SHARE_STENCIL))
  954. {
  955. ppfd->cStencilBits = 0;
  956. }
  957. ppfd->cAuxBuffers = 0;
  958. return TRUE;
  959. }
  960. /******************************Public*Routine******************************\
  961. *
  962. * IsDirectDrawDevice
  963. *
  964. * Returns surface associated with HDC if such an association exists
  965. *
  966. * History:
  967. * Wed Sep 25 13:18:02 1996 -by- Drew Bliss [drewb]
  968. * Created
  969. *
  970. \**************************************************************************/
  971. BOOL APIENTRY IsDirectDrawDevice(HDC hdc)
  972. {
  973. LPDIRECTDRAWSURFACE pdds;
  974. HDC hdcDevice;
  975. if (pfnGetSurfaceFromDC != NULL &&
  976. pfnGetSurfaceFromDC(hdc, &pdds, &hdcDevice) == DD_OK)
  977. {
  978. // The call gave us a reference on the surface so release it.
  979. pdds->lpVtbl->Release(pdds);
  980. return TRUE;
  981. }
  982. else
  983. {
  984. return FALSE;
  985. }
  986. }
  987. /******************************Public*Routine******************************\
  988. *
  989. * DdPixelDepth
  990. *
  991. * Determines the number of bits per pixel for a surface.
  992. *
  993. * History:
  994. * Wed Nov 20 16:57:07 1996 -by- Drew Bliss [drewb]
  995. * Created
  996. *
  997. \**************************************************************************/
  998. BYTE APIENTRY DdPixelDepth(DDSURFACEDESC *pddsd)
  999. {
  1000. if (pddsd->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4)
  1001. {
  1002. return 4;
  1003. }
  1004. else if (pddsd->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)
  1005. {
  1006. return 8;
  1007. }
  1008. else
  1009. {
  1010. return (BYTE)DdPixDepthToCount(pddsd->ddpfPixelFormat.dwRGBBitCount);
  1011. }
  1012. }
  1013. /******************************Public*Routine******************************\
  1014. *
  1015. * wglIsDirectDevice
  1016. *
  1017. * Checks to see whether the given DC is a screen DC on the
  1018. * surface for which we have direct screen access
  1019. *
  1020. * History:
  1021. * Fri Apr 19 15:17:30 1996 -by- Drew Bliss [drewb]
  1022. * Created
  1023. *
  1024. \**************************************************************************/
  1025. BOOL APIENTRY wglIsDirectDevice(HDC hdc)
  1026. {
  1027. if (wglObjectType(hdc) != OBJ_DC)
  1028. {
  1029. return FALSE;
  1030. }
  1031. // What about multiple displays?
  1032. return GetDeviceCaps(hdc, TECHNOLOGY) == DT_RASDISPLAY;
  1033. }
  1034. /******************************Public*Routine******************************\
  1035. *
  1036. * InitDeviceSurface
  1037. *
  1038. * Fills out a GLSURF for an HDC-based surface
  1039. *
  1040. * History:
  1041. * Tue Aug 27 19:22:38 1996 -by- Drew Bliss [drewb]
  1042. * Created
  1043. *
  1044. \**************************************************************************/
  1045. BOOL APIENTRY InitDeviceSurface(HDC hdc, int ipfd, int iLayer,
  1046. DWORD dwObjectType, BOOL bUpdatePfd,
  1047. GLSURF *pgsurf)
  1048. {
  1049. pgsurf->dwFlags = GLSURF_HDC;
  1050. pgsurf->iLayer = iLayer;
  1051. pgsurf->ipfd = ipfd;
  1052. pgsurf->hdc = hdc;
  1053. pgsurf->hwnd = NULL;
  1054. // Determine whether direct memory access is available for this surface
  1055. // or not. The two cases are:
  1056. // It's a screen surface and we have direct screen access
  1057. // It's a DIBSECTION memory surface
  1058. if (dwObjectType == OBJ_DC)
  1059. {
  1060. pgsurf->dwFlags |= GLSURF_DIRECTDC;
  1061. if (wglIsDirectDevice(hdc))
  1062. {
  1063. pgsurf->dwFlags |= GLSURF_SCREEN | GLSURF_VIDEO_MEMORY;
  1064. pgsurf->hwnd = WindowFromDC(hdc);
  1065. if (GLDIRECTSCREEN)
  1066. {
  1067. pgsurf->dwFlags |= GLSURF_DIRECT_ACCESS;
  1068. }
  1069. }
  1070. }
  1071. else if (dwObjectType == OBJ_MEMDC)
  1072. {
  1073. DIBSECTION ds;
  1074. if (GetObject(GetCurrentObject(hdc, OBJ_BITMAP), sizeof(ds), &ds) ==
  1075. sizeof(ds) && ds.dsBm.bmBits != NULL)
  1076. {
  1077. pgsurf->dwFlags |= GLSURF_DIRECT_ACCESS;
  1078. }
  1079. if (bUpdatePfd)
  1080. {
  1081. // Update pixel format with true surface information rather
  1082. // than device information
  1083. wglSurfacePixelFormat(hdc, &pgsurf->pfd);
  1084. }
  1085. }
  1086. if (bUpdatePfd &&
  1087. iLayer > 0 &&
  1088. !bLayerPixelFormat(hdc, &pgsurf->pfd, ipfd, iLayer))
  1089. {
  1090. return FALSE;
  1091. }
  1092. return TRUE;
  1093. }
  1094. /******************************Public*Routine******************************\
  1095. *
  1096. * InitDdSurface
  1097. *
  1098. * Completes a GLSURF for a DirectDraw-based surface.
  1099. * Pixel format information should already be filled in.
  1100. *
  1101. * History:
  1102. * Mon Aug 26 13:50:04 1996 -by- Drew Bliss [drewb]
  1103. * Created
  1104. *
  1105. \**************************************************************************/
  1106. BOOL InitDdSurface(LPDIRECTDRAWSURFACE pdds, HDC hdcDevice, GLSURF *pgsurf)
  1107. {
  1108. DDSCAPS ddscaps;
  1109. LPDIRECTDRAWSURFACE pddsZ;
  1110. DDSURFACEDESC *pddsd;
  1111. pgsurf->hdc = hdcDevice;
  1112. pgsurf->dd.gddsFront.ddsd.dwSize = sizeof(DDSURFACEDESC);
  1113. pgsurf->dd.gddsZ.ddsd.dwSize = sizeof(DDSURFACEDESC);
  1114. pddsd = &pgsurf->dd.gddsFront.ddsd;
  1115. if (pdds->lpVtbl->GetSurfaceDesc(pdds, pddsd) != DD_OK)
  1116. {
  1117. return FALSE;
  1118. }
  1119. pgsurf->dwFlags = GLSURF_DIRECTDRAW | GLSURF_DIRECT_ACCESS;
  1120. pgsurf->iLayer = 0;
  1121. // Check for an attached Z buffer
  1122. memset(&ddscaps, 0, sizeof(ddscaps));
  1123. ddscaps.dwCaps = DDSCAPS_ZBUFFER;
  1124. pddsd = &pgsurf->dd.gddsZ.ddsd;
  1125. if (pdds->lpVtbl->GetAttachedSurface(pdds, &ddscaps, &pddsZ) == DD_OK)
  1126. {
  1127. if (pddsZ->lpVtbl->GetSurfaceDesc(pddsZ, pddsd) != DD_OK)
  1128. {
  1129. pddsZ->lpVtbl->Release(pddsZ);
  1130. return FALSE;
  1131. }
  1132. }
  1133. else
  1134. {
  1135. memset(&pgsurf->dd.gddsZ, 0, sizeof(pgsurf->dd.gddsZ));
  1136. }
  1137. // If both the color buffer and the Z buffer are in video memory
  1138. // then hardware acceleration is possible
  1139. if ((pgsurf->dd.gddsFront.ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
  1140. (pddsZ == NULL ||
  1141. (pgsurf->dd.gddsZ.ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)))
  1142. {
  1143. pgsurf->dwFlags |= GLSURF_VIDEO_MEMORY;
  1144. }
  1145. pgsurf->dd.gddsFront.pdds = pdds;
  1146. pgsurf->dd.gddsFront.dwBitDepth =
  1147. DdPixDepthToCount(pgsurf->dd.gddsFront.
  1148. ddsd.ddpfPixelFormat.dwRGBBitCount);
  1149. // GetAttachedSurface gave us a reference to the Z buffer
  1150. pgsurf->dd.gddsZ.pdds = pddsZ;
  1151. pgsurf->dd.gddsZ.dwBitDepth =
  1152. DdPixDepthToCount(pgsurf->dd.gddsZ.
  1153. ddsd.ddpfPixelFormat.dwZBufferBitDepth);
  1154. return TRUE;
  1155. }
  1156. /******************************Public*Routine******************************\
  1157. * wglCreateLayerContext(HDC hdc, int iLayer)
  1158. *
  1159. * Create a rendering context for a specific layer
  1160. *
  1161. * Arguments:
  1162. * hdc - Device context.
  1163. * iLayer - Layer
  1164. *
  1165. * History:
  1166. * Tue Oct 26 10:25:26 1993 -by- Hock San Lee [hockl]
  1167. * Rewrote it.
  1168. \**************************************************************************/
  1169. HGLRC WINAPI wglCreateLayerContext(HDC hdc, int iLayer)
  1170. {
  1171. DWORD dwObjectType;
  1172. GLSURF gsurf;
  1173. LPDIRECTDRAWSURFACE pdds;
  1174. HDC hdcDevice;
  1175. HGLRC hrc;
  1176. DBGENTRY("wglCreateLayerContext\n");
  1177. // Flush OpenGL calls.
  1178. GLFLUSH();
  1179. // Validate the DC.
  1180. dwObjectType = wglObjectType(hdc);
  1181. switch (dwObjectType)
  1182. {
  1183. case OBJ_DC:
  1184. case OBJ_MEMDC:
  1185. break;
  1186. case OBJ_ENHMETADC:
  1187. #ifdef GL_METAFILE
  1188. if (pfnGdiAddGlsRecord == NULL)
  1189. {
  1190. DBGLEVEL1(LEVEL_ERROR, "wglCreateContext: metafile hdc: 0x%lx\n",
  1191. hdc);
  1192. SetLastError(ERROR_INVALID_HANDLE);
  1193. return((HGLRC) 0);
  1194. }
  1195. break;
  1196. #else
  1197. DBGLEVEL1(LEVEL_ERROR, "wglCreateContext: metafile hdc: 0x%lx\n", hdc);
  1198. SetLastError(ERROR_INVALID_HANDLE);
  1199. return((HGLRC) 0);
  1200. #endif
  1201. case OBJ_METADC:
  1202. default:
  1203. // 16-bit metafiles are not supported
  1204. DBGLEVEL1(LEVEL_ERROR, "wglCreateContext: bad hdc: 0x%lx\n", hdc);
  1205. SetLastError(ERROR_INVALID_HANDLE);
  1206. return((HGLRC) 0);
  1207. }
  1208. pdds = NULL;
  1209. hrc = NULL;
  1210. memset(&gsurf, 0, sizeof(gsurf));
  1211. gsurf.ipfd = GetPixelFormat(hdc);
  1212. #ifdef GL_METAFILE
  1213. // Skip pixel format checks for metafiles
  1214. if (dwObjectType == OBJ_ENHMETADC)
  1215. {
  1216. CreateMetafileSurf(hdc, iLayer, &gsurf);
  1217. goto NoPixelFormat;
  1218. }
  1219. #endif
  1220. // Get the current pixel format of the window or surface.
  1221. // If no pixel format has been set, return error.
  1222. if (gsurf.ipfd == 0)
  1223. {
  1224. WARNING("wglCreateContext: No pixel format set in hdc\n");
  1225. SetLastError(ERROR_INVALID_PIXEL_FORMAT);
  1226. return ((HGLRC) 0);
  1227. }
  1228. if (!DescribePixelFormat(hdc, gsurf.ipfd, sizeof(gsurf.pfd), &gsurf.pfd))
  1229. {
  1230. DBGERROR("wglCreateContext: DescribePixelFormat failed\n");
  1231. return ((HGLRC) 0);
  1232. }
  1233. // Check for a DirectDraw surface
  1234. if (pfnGetSurfaceFromDC != NULL &&
  1235. pfnGetSurfaceFromDC(hdc, &pdds, &hdcDevice) == DD_OK)
  1236. {
  1237. // Don't allow layers for DirectDraw surfaces since
  1238. // layering is done through DirectDraw itself.
  1239. if (iLayer != 0 ||
  1240. !InitDdSurface(pdds, hdcDevice, &gsurf))
  1241. {
  1242. goto Exit;
  1243. }
  1244. }
  1245. else if (!InitDeviceSurface(hdc, gsurf.ipfd, iLayer, dwObjectType,
  1246. TRUE, &gsurf))
  1247. {
  1248. goto Exit;
  1249. }
  1250. #ifdef GL_METAFILE
  1251. NoPixelFormat:
  1252. #endif
  1253. hrc = CreateAnyContext(&gsurf);
  1254. Exit:
  1255. if (hrc == NULL)
  1256. {
  1257. if (pdds != NULL)
  1258. {
  1259. pdds->lpVtbl->Release(pdds);
  1260. // Release reference on Z buffer if necessary
  1261. if (gsurf.dd.gddsZ.pdds != NULL)
  1262. {
  1263. gsurf.dd.gddsZ.pdds->lpVtbl->Release(gsurf.dd.gddsZ.pdds);
  1264. }
  1265. }
  1266. }
  1267. return hrc;
  1268. }
  1269. /******************************Public*Routine******************************\
  1270. * wglCreateContext(HDC hdc)
  1271. *
  1272. * Create a rendering context.
  1273. *
  1274. * Arguments:
  1275. * hdc - Device context.
  1276. *
  1277. * History:
  1278. * Tue Oct 26 10:25:26 1993 -by- Hock San Lee [hockl]
  1279. * Rewrote it.
  1280. \**************************************************************************/
  1281. HGLRC WINAPI wglCreateContext(HDC hdc)
  1282. {
  1283. return wglCreateLayerContext(hdc, 0);
  1284. }