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.

798 lines
22 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: dllinit.c
  3. *
  4. * (Brief description)
  5. *
  6. * Created: 18-Oct-1993 14:13:21
  7. * Author: Gilman Wong [gilmanw]
  8. *
  9. * Copyright (c) 1993 Microsoft Corporation
  10. *
  11. \**************************************************************************/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include "batchinf.h"
  15. #include "glteb.h"
  16. #include "glapi.h"
  17. #include "glsbcltu.h"
  18. #ifdef _CLIENTSIDE_
  19. #include "glscreen.h"
  20. #include "glgenwin.h"
  21. #endif //_CLIENTSIDE_
  22. #include "context.h"
  23. #include "global.h"
  24. #include "parray.h"
  25. #include "gencx.h"
  26. #include "cpu.h"
  27. #include "fixed.h"
  28. #ifdef _CLIENTSIDE_
  29. // Global screen access info. This is NULL if screen access is not available.
  30. SCREENINFO *gpScreenInfo = NULL;
  31. extern GLubyte *dBufFill;
  32. extern GLubyte *dBufTopLeft;
  33. //
  34. // This global multiply-lookup table helps with pixel-related functions.
  35. //
  36. BYTE gbMulTable[256*256+4];
  37. BYTE gbSatTable[256+256];
  38. //
  39. // This global inverse-lookup table helps with rasterization setup
  40. //
  41. #define INV_TABLE_SIZE (1 << __GL_VERTEX_FRAC_BITS) * (__GL_MAX_INV_TABLE + 1)
  42. __GLfloat invTable[INV_TABLE_SIZE];
  43. // Global thread local storage index. Allocated at process attach.
  44. // This is the slot reserved in thread local storage for per-thread
  45. // GLTLSINFO structures.
  46. static DWORD dwTlsIndex = 0xFFFFFFFF;
  47. static BOOL bProcessInitialized = FALSE;
  48. // Offset into the TEB where dwTlsIndex is
  49. // This enables us to directly access our TLS data in the TEB
  50. #if defined(_WIN64)
  51. #define NT_TLS_OFFSET 5248
  52. #else
  53. #define NT_TLS_OFFSET 3600
  54. #endif
  55. #define WIN95_TLS_OFFSET 136
  56. DWORD dwTlsOffset;
  57. // Platform indicator for conditional code
  58. DWORD dwPlatformId;
  59. // Thread count
  60. LONG lThreadsAttached = 0;
  61. // Global header node for the linked list of GLGENwindow structures.
  62. // The semaphore in the header node is used as the list access semaphore.
  63. GLGENwindow gwndHeader;
  64. // Synchronization object for pixel formats
  65. CRITICAL_SECTION gcsPixelFormat;
  66. // Protection for palette watcher
  67. CRITICAL_SECTION gcsPaletteWatcher;
  68. #ifdef GL_METAFILE
  69. BOOL (APIENTRY *pfnGdiAddGlsRecord)(HDC hdc, DWORD cb, BYTE *pb,
  70. LPRECTL prclBounds);
  71. BOOL (APIENTRY *pfnGdiAddGlsBounds)(HDC hdc, LPRECTL prclBounds);
  72. BOOL (APIENTRY *pfnGdiIsMetaPrintDC)(HDC hdc);
  73. #endif
  74. #endif //_CLIENTSIDE_
  75. // OpenGL client debug flag
  76. #if DBG
  77. long glDebugLevel;
  78. ULONG glDebugFlags;
  79. #endif
  80. BOOL bDirectScreen = FALSE;
  81. PFN_GETSURFACEFROMDC pfnGetSurfaceFromDC = NULL;
  82. /******************************Public*Routine******************************\
  83. *
  84. * DdbdToCount
  85. *
  86. * Converts a DDBD constant to its equivalent number
  87. *
  88. * History:
  89. * Mon Aug 26 14:11:34 1996 -by- Drew Bliss [drewb]
  90. * Created
  91. *
  92. \**************************************************************************/
  93. DWORD APIENTRY DdbdToCount(DWORD ddbd)
  94. {
  95. switch(ddbd)
  96. {
  97. case DDBD_1:
  98. return 1;
  99. case DDBD_2:
  100. return 2;
  101. case DDBD_4:
  102. return 4;
  103. case DDBD_8:
  104. return 8;
  105. case DDBD_16:
  106. return 16;
  107. case DDBD_24:
  108. return 24;
  109. case DDBD_32:
  110. return 32;
  111. }
  112. ASSERTOPENGL(FALSE, "DdbdToCount: Invalid ddbd\n");
  113. return 0;
  114. }
  115. /******************************Public*Routine******************************\
  116. * GLInitializeProcess
  117. *
  118. * Called from OPENGL32.DLL entry point for PROCESS_ATTACH.
  119. *
  120. * History:
  121. * 01-Nov-1994 -by- Gilman Wong [gilmanw]
  122. * Wrote it.
  123. \**************************************************************************/
  124. BOOL GLInitializeProcess()
  125. {
  126. PVOID pv;
  127. #ifdef _CLIENTSIDE_
  128. OSVERSIONINFO osvi;
  129. #endif
  130. // Attempt to locate GDI exports for metafiling support
  131. {
  132. HMODULE hdll;
  133. hdll = GetModuleHandleA("gdi32");
  134. ASSERTOPENGL(hdll != NULL, "Unable to get gdi32 handle\n");
  135. *(PROC *)&pfnGdiAddGlsRecord = GetProcAddress(hdll, "GdiAddGlsRecord");
  136. *(PROC *)&pfnGdiAddGlsBounds = GetProcAddress(hdll, "GdiAddGlsBounds");
  137. *(PROC *)&pfnGdiIsMetaPrintDC = GetProcAddress(hdll,
  138. "GdiIsMetaPrintDC");
  139. #ifdef ALLOW_DDRAW_SURFACES
  140. hdll = GetModuleHandleA("ddraw");
  141. ASSERTOPENGL(hdll != NULL, "Unable to get ddraw handle\n");
  142. pfnGetSurfaceFromDC = (PFN_GETSURFACEFROMDC)
  143. GetProcAddress(hdll, "GetSurfaceFromDC");
  144. #endif
  145. }
  146. #if DBG
  147. #define STR_OPENGL_DEBUG (PCSTR)"Software\\Microsoft\\Windows\\CurrentVersion\\DebugOpenGL"
  148. {
  149. HKEY hkDebug;
  150. // Initialize debugging level and flags.
  151. glDebugLevel = LEVEL_ERROR;
  152. glDebugFlags = 0;
  153. if ( RegOpenKeyExA(HKEY_LOCAL_MACHINE,
  154. STR_OPENGL_DEBUG,
  155. 0,
  156. KEY_QUERY_VALUE,
  157. &hkDebug) == ERROR_SUCCESS )
  158. {
  159. DWORD dwDataType;
  160. DWORD cjSize;
  161. long lTmp;
  162. cjSize = sizeof(long);
  163. if ( (RegQueryValueExA(hkDebug,
  164. (LPSTR) "glDebugLevel",
  165. (LPDWORD) NULL,
  166. &dwDataType,
  167. (LPBYTE) &lTmp,
  168. &cjSize) == ERROR_SUCCESS) )
  169. {
  170. glDebugLevel = lTmp;
  171. }
  172. cjSize = sizeof(long);
  173. if ( (RegQueryValueExA(hkDebug,
  174. (LPSTR) "glDebugFlags",
  175. (LPDWORD) NULL,
  176. &dwDataType,
  177. (LPBYTE) &lTmp,
  178. &cjSize) == ERROR_SUCCESS) )
  179. {
  180. glDebugFlags = (ULONG) lTmp;
  181. }
  182. RegCloseKey(hkDebug);
  183. }
  184. }
  185. #endif
  186. #ifdef _CLIENTSIDE_
  187. // Determine which platform we're running on and remember it
  188. osvi.dwOSVersionInfoSize = sizeof(osvi);
  189. if (!GetVersionEx(&osvi))
  190. {
  191. WARNING1("GetVersionEx failed with %d\n", GetLastError());
  192. goto EH_Fail;
  193. }
  194. dwPlatformId = osvi.dwPlatformId;
  195. if (!(
  196. (dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) ||
  197. (dwPlatformId == VER_PLATFORM_WIN32_NT
  198. && !(osvi.dwMajorVersion == 3 && osvi.dwMinorVersion <= 51)
  199. )
  200. )
  201. )
  202. {
  203. WARNING("DLL must be run on NT 4.0 or Win95");
  204. goto EH_Fail;
  205. }
  206. // Allocate a thread local storage slot.
  207. if ( (dwTlsIndex = TlsAlloc()) == 0xFFFFFFFF )
  208. {
  209. WARNING("DllInitialize: TlsAlloc failed\n");
  210. goto EH_Fail;
  211. }
  212. // Set up the offset to the TLS slot, OS-specific
  213. if (dwPlatformId == VER_PLATFORM_WIN32_NT)
  214. {
  215. ASSERTOPENGL(FIELD_OFFSET(TEB, TlsSlots) == NT_TLS_OFFSET,
  216. "NT TLS offset not at expected location");
  217. dwTlsOffset = dwTlsIndex*sizeof(DWORD_PTR)+NT_TLS_OFFSET;
  218. }
  219. #if !defined(_WIN64)
  220. else
  221. {
  222. // We don't have Win95's TIB type available so the assert is
  223. // slightly different
  224. ASSERTOPENGL(((ULONG_PTR)(NtCurrentTeb()->ThreadLocalStoragePointer)-
  225. (ULONG_PTR)NtCurrentTeb()) == WIN95_TLS_OFFSET,
  226. "Win95 TLS offset not at expected location");
  227. dwTlsOffset = dwTlsIndex*sizeof(DWORD)+WIN95_TLS_OFFSET;
  228. }
  229. #endif
  230. #endif
  231. // Reserve memory for the local handle table.
  232. if ( (pLocalTable = (PLHE) VirtualAlloc (
  233. (LPVOID) NULL, // let base locate it
  234. MAX_HANDLES*sizeof(LHE),
  235. MEM_RESERVE | MEM_TOP_DOWN,
  236. PAGE_READWRITE
  237. )) == (PLHE) NULL )
  238. {
  239. WARNING("DllInitialize: VirtualAlloc failed\n");
  240. goto EH_TlsIndex;
  241. }
  242. // Initialize the local handle manager semaphore.
  243. __try
  244. {
  245. INITIALIZECRITICALSECTION(&semLocal);
  246. }
  247. __except(EXCEPTION_EXECUTE_HANDLER)
  248. {
  249. goto EH_LocalTable;
  250. }
  251. #ifdef _CLIENTSIDE_
  252. // Initialize the GLGENwindow list semaphore.
  253. __try
  254. {
  255. INITIALIZECRITICALSECTION(&gwndHeader.sem);
  256. }
  257. __except(EXCEPTION_EXECUTE_HANDLER)
  258. {
  259. goto EH_semLocal;
  260. }
  261. gwndHeader.pNext = &gwndHeader;
  262. // Initialize the pixel format critical section
  263. __try
  264. {
  265. INITIALIZECRITICALSECTION(&gcsPixelFormat);
  266. }
  267. __except(EXCEPTION_EXECUTE_HANDLER)
  268. {
  269. goto EH_gwndHeader;
  270. }
  271. // Initialize the palette watcher critical section.
  272. __try
  273. {
  274. INITIALIZECRITICALSECTION(&gcsPaletteWatcher);
  275. }
  276. __except(EXCEPTION_EXECUTE_HANDLER)
  277. {
  278. goto EH_PixelFormat;
  279. }
  280. // Initialize direct screen access.
  281. if (GetSystemMetrics(SM_CMONITORS) > 1)
  282. {
  283. gpScreenInfo = NULL;
  284. }
  285. else
  286. {
  287. #if _WIN32_WINNT >= 0x0501
  288. BOOL wow64Process;
  289. if (IsWow64Process(GetCurrentProcess(), &wow64Process) && wow64Process)
  290. gpScreenInfo = NULL;
  291. else
  292. #endif
  293. gpScreenInfo = (SCREENINFO *)ALLOCZ(sizeof(SCREENINFO));
  294. }
  295. if ( gpScreenInfo )
  296. {
  297. UINT uiOldErrorMode;
  298. HRESULT hr;
  299. // We want to ensure that DDraw doesn't pop up any message
  300. // boxes on failure when we call DirectDrawCreate. DDraw
  301. // does errors on a different thread which it creates just
  302. // for the error. It waits for the error to complete before
  303. // returning. This function is running inside the loader
  304. // DllInitialize critical section, though, so other threads
  305. // do not get to run, causing a deadlock.
  306. // Force the error mode to get around this.
  307. uiOldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  308. hr = DirectDrawCreate(NULL, &gpScreenInfo->pdd, NULL);
  309. SetErrorMode(uiOldErrorMode);
  310. if (hr == DD_OK)
  311. {
  312. hr = gpScreenInfo->pdd->lpVtbl->
  313. SetCooperativeLevel(gpScreenInfo->pdd, NULL, DDSCL_NORMAL);
  314. if (hr == DD_OK)
  315. {
  316. gpScreenInfo->gdds.ddsd.dwSize = sizeof(DDSURFACEDESC);
  317. gpScreenInfo->gdds.ddsd.dwFlags = DDSD_CAPS;
  318. gpScreenInfo->gdds.ddsd.ddsCaps.dwCaps =
  319. DDSCAPS_PRIMARYSURFACE;
  320. hr = gpScreenInfo->pdd->lpVtbl->
  321. CreateSurface(gpScreenInfo->pdd, &gpScreenInfo->gdds.ddsd,
  322. &gpScreenInfo->gdds.pdds, NULL);
  323. }
  324. if (hr == DD_OK)
  325. {
  326. #if DBG
  327. #define LEVEL_SCREEN LEVEL_INFO
  328. gpScreenInfo->gdds.pdds->lpVtbl->
  329. GetSurfaceDesc(gpScreenInfo->gdds.pdds,
  330. &gpScreenInfo->gdds.ddsd);
  331. DBGLEVEL (LEVEL_SCREEN, "=============================\n");
  332. DBGLEVEL (LEVEL_SCREEN, "Direct screen access enabled for OpenGL\n\n");
  333. DBGLEVEL (LEVEL_SCREEN, "Surface info:\n");
  334. DBGLEVEL1(LEVEL_SCREEN, "\tdwSize = 0x%lx\n",
  335. gpScreenInfo->gdds.ddsd.dwSize);
  336. DBGLEVEL1(LEVEL_SCREEN, "\tdwWidth = %ld\n",
  337. gpScreenInfo->gdds.ddsd.dwWidth);
  338. DBGLEVEL1(LEVEL_SCREEN, "\tdwHeight = %ld\n",
  339. gpScreenInfo->gdds.ddsd.dwHeight);
  340. DBGLEVEL1(LEVEL_SCREEN, "\tlStride = 0x%lx\n",
  341. gpScreenInfo->gdds.ddsd.lPitch);
  342. DBGLEVEL1(LEVEL_SCREEN, "\tdwBitCount = %ld\n",
  343. gpScreenInfo->gdds.ddsd.ddpfPixelFormat.dwRGBBitCount);
  344. gpScreenInfo->gdds.pdds->lpVtbl->
  345. Lock(gpScreenInfo->gdds.pdds,
  346. NULL, &gpScreenInfo->gdds.ddsd,
  347. DDLOCK_SURFACEMEMORYPTR, NULL);
  348. DBGLEVEL1(LEVEL_SCREEN, "\tdwOffSurface = 0x%lx\n",
  349. gpScreenInfo->gdds.ddsd.lpSurface);
  350. gpScreenInfo->gdds.pdds->lpVtbl->
  351. Unlock(gpScreenInfo->gdds.pdds, gpScreenInfo->gdds.ddsd.lpSurface);
  352. DBGLEVEL (LEVEL_SCREEN, "=============================\n");
  353. #endif
  354. // Verify screen access
  355. if (gpScreenInfo->gdds.pdds->lpVtbl->
  356. GetSurfaceDesc(gpScreenInfo->gdds.pdds,
  357. &gpScreenInfo->gdds.ddsd) != DD_OK ||
  358. gpScreenInfo->gdds.pdds->lpVtbl->
  359. Lock(gpScreenInfo->gdds.pdds,
  360. NULL, &gpScreenInfo->gdds.ddsd,
  361. DDLOCK_SURFACEMEMORYPTR, NULL) != DD_OK)
  362. {
  363. DBGLEVEL(LEVEL_SCREEN,
  364. "Direct screen access failure : disabling\n");
  365. }
  366. else
  367. {
  368. gpScreenInfo->gdds.dwBitDepth =
  369. DdPixDepthToCount(gpScreenInfo->gdds.ddsd.
  370. ddpfPixelFormat.dwRGBBitCount);
  371. gpScreenInfo->gdds.pdds->lpVtbl->
  372. Unlock(gpScreenInfo->gdds.pdds,
  373. gpScreenInfo->gdds.ddsd.lpSurface);
  374. bDirectScreen = TRUE;
  375. }
  376. }
  377. #if DBG
  378. else
  379. {
  380. DBGLEVEL (LEVEL_SCREEN, "=============================\n");
  381. DBGLEVEL2(LEVEL_SCREEN,
  382. "Screen access failed code 0x%08lX (%s)\n",
  383. hr, (hr == DDERR_NOTFOUND) ? "DDERR_NOTFOUND" :
  384. "unknown");
  385. DBGLEVEL (LEVEL_SCREEN, "=============================\n");
  386. }
  387. #endif
  388. }
  389. else
  390. {
  391. DBGLEVEL(LEVEL_SCREEN, "DirectDrawCreate failed\n");
  392. }
  393. }
  394. if (!bDirectScreen)
  395. {
  396. if (gpScreenInfo)
  397. {
  398. if (gpScreenInfo->gdds.pdds)
  399. {
  400. gpScreenInfo->gdds.pdds->lpVtbl->
  401. Release(gpScreenInfo->gdds.pdds);
  402. }
  403. if (gpScreenInfo->pdd)
  404. {
  405. gpScreenInfo->pdd->lpVtbl->Release(gpScreenInfo->pdd);
  406. }
  407. FREE(gpScreenInfo);
  408. gpScreenInfo = NULL;
  409. }
  410. }
  411. #endif
  412. // Set up our multiplication table:
  413. {
  414. BYTE *pMulTable = gbMulTable;
  415. ULONG i, j;
  416. for (i = 0; i < 256; i++) {
  417. ULONG tmp = 0;
  418. for (j = 0; j < 256; j++, tmp += i) {
  419. *pMulTable++ = (BYTE)(tmp >> 8);
  420. }
  421. }
  422. }
  423. // Set up our saturation table:
  424. {
  425. ULONG i;
  426. for (i = 0; i < 256; i++)
  427. gbSatTable[i] = (BYTE)i;
  428. for (; i < (256+256); i++)
  429. gbSatTable[i] = 255;
  430. }
  431. // Set up inverse-lookup table:
  432. {
  433. __GLfloat accum = (__GLfloat)(1.0 / (__GLfloat)__GL_VERTEX_FRAC_ONE);
  434. GLint i;
  435. invTable[0] = (__GLfloat)0.0;
  436. for (i = 1; i < INV_TABLE_SIZE; i++) {
  437. invTable[i] = __glOne / accum;
  438. accum += (__GLfloat)(1.0 / (__GLfloat)__GL_VERTEX_FRAC_ONE);
  439. }
  440. }
  441. bProcessInitialized = TRUE;
  442. return TRUE;
  443. EH_PixelFormat:
  444. DELETECRITICALSECTION(&gcsPixelFormat);
  445. EH_gwndHeader:
  446. DELETECRITICALSECTION(&gwndHeader.sem);
  447. EH_semLocal:
  448. DELETECRITICALSECTION(&semLocal);
  449. EH_LocalTable:
  450. VirtualFree(pLocalTable, 0, MEM_RELEASE);
  451. EH_TlsIndex:
  452. TlsFree(dwTlsIndex);
  453. dwTlsIndex = 0xFFFFFFFF;
  454. EH_Fail:
  455. return FALSE;
  456. }
  457. /******************************Public*Routine******************************\
  458. * GLUnInitializeProcess
  459. *
  460. * Called from OPENGL32.DLL entry point for PROCESS_DETACH.
  461. *
  462. * History:
  463. * 01-Nov-1994 -by- Gilman Wong [gilmanw]
  464. * Wrote it.
  465. \**************************************************************************/
  466. void GLUnInitializeProcess()
  467. {
  468. // If we never finished process initialization, quit now.
  469. if (!bProcessInitialized)
  470. return;
  471. // Cleanup stray HGLRCs that the app may have forgotten to delete.
  472. {
  473. static GLTEBINFO gltebInfoTmp;
  474. // Need a temporary GLTEBINFO for this thread in order to do the
  475. // cleanup processing.
  476. ASSERTOPENGL(!CURRENT_GLTEBINFO(),
  477. "GLUnInitializeProcess: GLTEBINFO not NULL!\n");
  478. // made static and no longer need memset
  479. // memset(&gltebInfoTmp, 0, sizeof(gltebInfoTmp));
  480. SET_CURRENT_GLTEBINFO(&gltebInfoTmp);
  481. vCleanupAllLRC();
  482. SET_CURRENT_GLTEBINFO((PGLTEBINFO) NULL);
  483. }
  484. // Cleanup window tracking structures (GLGENwindow structs).
  485. vCleanupWnd();
  486. // Cleanup evaluator arrays
  487. if (dBufFill)
  488. FREE(dBufFill);
  489. if (dBufTopLeft)
  490. FREE(dBufTopLeft);
  491. // Screen access shutdown.
  492. if (gpScreenInfo)
  493. {
  494. if (gpScreenInfo->gdds.pdds)
  495. {
  496. gpScreenInfo->gdds.pdds->lpVtbl->Release(gpScreenInfo->gdds.pdds);
  497. }
  498. if (gpScreenInfo->pdd)
  499. {
  500. gpScreenInfo->pdd->lpVtbl->Release(gpScreenInfo->pdd);
  501. }
  502. FREE(gpScreenInfo);
  503. }
  504. // Free the TLS slot.
  505. if (dwTlsIndex != 0xFFFFFFFF)
  506. if (!TlsFree(dwTlsIndex))
  507. RIP("DllInitialize: TlsFree failed\n");
  508. // Free the global semaphores.
  509. DELETECRITICALSECTION(&gcsPaletteWatcher);
  510. DELETECRITICALSECTION(&gcsPixelFormat);
  511. DELETECRITICALSECTION(&gwndHeader.sem);
  512. DELETECRITICALSECTION(&semLocal);
  513. // Free the local handle table.
  514. if ( pLocalTable )
  515. VirtualFree(pLocalTable, 0, MEM_RELEASE);
  516. }
  517. /******************************Public*Routine******************************\
  518. * GLInitializeThread
  519. *
  520. * Called from OPENGL32.DLL entry point for THREAD_ATTACH. May assume that
  521. * GLInitializeProcess has succeeded.
  522. *
  523. \**************************************************************************/
  524. VOID GLInitializeThread(ULONG ulReason)
  525. {
  526. GLTEBINFO *pglti;
  527. GLMSGBATCHINFO *pMsgBatchInfo;
  528. POLYARRAY *pa;
  529. #if !defined(_WIN95_) && defined(_X86_)
  530. {
  531. TEB *pteb;
  532. pteb = NtCurrentTeb();
  533. // Set up linear pointers to TEB regions in the TEB
  534. // this saves an addition when referencing these values
  535. // This must occur early so that these pointers are available
  536. // for the rest of thread initialization
  537. ((POLYARRAY *)pteb->glReserved1)->paTeb =
  538. (POLYARRAY *)pteb->glReserved1;
  539. pteb->glTable = pteb->glDispatchTable;
  540. }
  541. #endif
  542. pglti = (GLTEBINFO *)ALLOCZ(sizeof(GLTEBINFO));
  543. SET_CURRENT_GLTEBINFO(pglti);
  544. if (pglti)
  545. {
  546. pa = GLTEB_CLTPOLYARRAY();
  547. pa->flags = 0; // not in begin mode
  548. // Save shared section pointer in POLYARRAY for fast pointer access
  549. pa->pMsgBatchInfo = (PVOID) pglti->glMsgBatchInfo;
  550. pMsgBatchInfo = (GLMSGBATCHINFO *) pa->pMsgBatchInfo;
  551. pMsgBatchInfo->MaximumOffset
  552. = SHARED_SECTION_SIZE - GLMSG_ALIGN(sizeof(ULONG));
  553. pMsgBatchInfo->FirstOffset
  554. = GLMSG_ALIGN(sizeof(GLMSGBATCHINFO));
  555. pMsgBatchInfo->NextOffset
  556. = GLMSG_ALIGN(sizeof(GLMSGBATCHINFO));
  557. SetCltProcTable(&glNullCltProcTable, &glNullExtProcTable, TRUE);
  558. GLTEB_SET_CLTCURRENTRC(NULL);
  559. GLTEB_SET_CLTPOLYMATERIAL(NULL);
  560. GLTEB_SET_CLTDRIVERSLOT(NULL);
  561. #if !defined(_WIN95_)
  562. ASSERTOPENGL((ULONG_PTR) pMsgBatchInfo == GLMSG_ALIGNPTR(pMsgBatchInfo),
  563. "bad shared memory alignment!\n");
  564. #endif
  565. }
  566. else
  567. {
  568. // This can be made into a WARNING (debug builds only) later on.
  569. DbgPrint ("Memory alloc failed for TebInfo structure, thread may AV if GL calls are made without MakeCurrent\n");
  570. }
  571. }
  572. /******************************Public*Routine******************************\
  573. * GLUnInitializeThread
  574. *
  575. * Called from OPENGL32.DLL entry point for THREAD_DETACH.
  576. *
  577. * The server generic driver should cleanup on its own. Same for the
  578. * installable driver.
  579. *
  580. \**************************************************************************/
  581. VOID GLUnInitializeThread(VOID)
  582. {
  583. // If we never finished process initialization, quit now.
  584. if (!bProcessInitialized)
  585. return;
  586. if (!CURRENT_GLTEBINFO())
  587. {
  588. return;
  589. }
  590. if (GLTEB_CLTCURRENTRC() != NULL)
  591. {
  592. PLRC plrc = GLTEB_CLTCURRENTRC();
  593. // May be an application error
  594. DBGERROR("GLUnInitializeThread: RC is current when thread exits\n");
  595. // Release the RC
  596. plrc->tidCurrent = INVALID_THREAD_ID;
  597. plrc->gwidCurrent.iType = GLWID_ERROR;
  598. GLTEB_SET_CLTCURRENTRC(NULL);
  599. vUnlockHandle((ULONG_PTR)(plrc->hrc));
  600. }
  601. // GLTEB_SET_CLTPROCTABLE(&glNullCltProcTable,&glNullExtProcTable);
  602. if (GLTEB_CLTPOLYMATERIAL())
  603. FreePolyMaterial();
  604. FREE(CURRENT_GLTEBINFO());
  605. SET_CURRENT_GLTEBINFO(NULL);
  606. }
  607. /******************************Public*Routine******************************\
  608. * DllInitialize
  609. *
  610. * This is the entry point for OPENGL32.DLL, which is called each time
  611. * a process or thread that is linked to it is created or terminated.
  612. *
  613. \**************************************************************************/
  614. BOOL DllInitialize(HMODULE hModule, ULONG Reason, PVOID Reserved)
  615. {
  616. // Do the appropriate task for process and thread attach/detach.
  617. DBGLEVEL3(LEVEL_INFO, "DllInitialize: %s Pid %d, Tid %d\n",
  618. Reason == DLL_PROCESS_ATTACH ? "PROCESS_ATTACH" :
  619. Reason == DLL_PROCESS_DETACH ? "PROCESS_DETACH" :
  620. Reason == DLL_THREAD_ATTACH ? "THREAD_ATTACH" :
  621. Reason == DLL_THREAD_DETACH ? "THREAD_DETACH" :
  622. "Reason UNKNOWN!",
  623. GetCurrentProcessId(), GetCurrentThreadId());
  624. switch (Reason)
  625. {
  626. case DLL_THREAD_ATTACH:
  627. case DLL_PROCESS_ATTACH:
  628. if (Reason == DLL_PROCESS_ATTACH)
  629. {
  630. if (!GLInitializeProcess())
  631. return FALSE;
  632. }
  633. InterlockedIncrement(&lThreadsAttached);
  634. GLInitializeThread(Reason);
  635. break;
  636. case DLL_THREAD_DETACH:
  637. case DLL_PROCESS_DETACH:
  638. GLUnInitializeThread();
  639. InterlockedDecrement(&lThreadsAttached);
  640. if ( Reason == DLL_PROCESS_DETACH )
  641. {
  642. GLUnInitializeProcess();
  643. }
  644. break;
  645. default:
  646. RIP("DllInitialize: unknown reason!\n");
  647. break;
  648. }
  649. return(TRUE);
  650. }