799 lines
22 KiB
C
799 lines
22 KiB
C
/******************************Module*Header*******************************\
|
|
* Module Name: dllinit.c
|
|
*
|
|
* (Brief description)
|
|
*
|
|
* Created: 18-Oct-1993 14:13:21
|
|
* Author: Gilman Wong [gilmanw]
|
|
*
|
|
* Copyright (c) 1993 Microsoft Corporation
|
|
*
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include "batchinf.h"
|
|
#include "glteb.h"
|
|
#include "glapi.h"
|
|
#include "glsbcltu.h"
|
|
#ifdef _CLIENTSIDE_
|
|
#include "glscreen.h"
|
|
#include "glgenwin.h"
|
|
#endif //_CLIENTSIDE_
|
|
#include "context.h"
|
|
#include "global.h"
|
|
#include "parray.h"
|
|
#include "gencx.h"
|
|
#include "cpu.h"
|
|
#include "fixed.h"
|
|
|
|
#ifdef _CLIENTSIDE_
|
|
// Global screen access info. This is NULL if screen access is not available.
|
|
|
|
SCREENINFO *gpScreenInfo = NULL;
|
|
|
|
extern GLubyte *dBufFill;
|
|
extern GLubyte *dBufTopLeft;
|
|
|
|
//
|
|
// This global multiply-lookup table helps with pixel-related functions.
|
|
//
|
|
|
|
BYTE gbMulTable[256*256+4];
|
|
BYTE gbSatTable[256+256];
|
|
|
|
//
|
|
// This global inverse-lookup table helps with rasterization setup
|
|
//
|
|
|
|
#define INV_TABLE_SIZE (1 << __GL_VERTEX_FRAC_BITS) * (__GL_MAX_INV_TABLE + 1)
|
|
|
|
__GLfloat invTable[INV_TABLE_SIZE];
|
|
|
|
// Global thread local storage index. Allocated at process attach.
|
|
// This is the slot reserved in thread local storage for per-thread
|
|
// GLTLSINFO structures.
|
|
|
|
static DWORD dwTlsIndex = 0xFFFFFFFF;
|
|
|
|
static BOOL bProcessInitialized = FALSE;
|
|
|
|
// Offset into the TEB where dwTlsIndex is
|
|
// This enables us to directly access our TLS data in the TEB
|
|
|
|
#if defined(_WIN64)
|
|
#define NT_TLS_OFFSET 5248
|
|
#else
|
|
#define NT_TLS_OFFSET 3600
|
|
#endif
|
|
|
|
#define WIN95_TLS_OFFSET 136
|
|
|
|
DWORD dwTlsOffset;
|
|
|
|
// Platform indicator for conditional code
|
|
DWORD dwPlatformId;
|
|
|
|
// Thread count
|
|
LONG lThreadsAttached = 0;
|
|
|
|
// Global header node for the linked list of GLGENwindow structures.
|
|
// The semaphore in the header node is used as the list access semaphore.
|
|
|
|
GLGENwindow gwndHeader;
|
|
|
|
// Synchronization object for pixel formats
|
|
CRITICAL_SECTION gcsPixelFormat;
|
|
|
|
// Protection for palette watcher
|
|
CRITICAL_SECTION gcsPaletteWatcher;
|
|
|
|
#ifdef GL_METAFILE
|
|
BOOL (APIENTRY *pfnGdiAddGlsRecord)(HDC hdc, DWORD cb, BYTE *pb,
|
|
LPRECTL prclBounds);
|
|
BOOL (APIENTRY *pfnGdiAddGlsBounds)(HDC hdc, LPRECTL prclBounds);
|
|
BOOL (APIENTRY *pfnGdiIsMetaPrintDC)(HDC hdc);
|
|
#endif
|
|
|
|
#endif //_CLIENTSIDE_
|
|
|
|
// OpenGL client debug flag
|
|
#if DBG
|
|
long glDebugLevel;
|
|
ULONG glDebugFlags;
|
|
#endif
|
|
|
|
BOOL bDirectScreen = FALSE;
|
|
|
|
PFN_GETSURFACEFROMDC pfnGetSurfaceFromDC = NULL;
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* DdbdToCount
|
|
*
|
|
* Converts a DDBD constant to its equivalent number
|
|
*
|
|
* History:
|
|
* Mon Aug 26 14:11:34 1996 -by- Drew Bliss [drewb]
|
|
* Created
|
|
*
|
|
\**************************************************************************/
|
|
|
|
DWORD APIENTRY DdbdToCount(DWORD ddbd)
|
|
{
|
|
switch(ddbd)
|
|
{
|
|
case DDBD_1:
|
|
return 1;
|
|
case DDBD_2:
|
|
return 2;
|
|
case DDBD_4:
|
|
return 4;
|
|
case DDBD_8:
|
|
return 8;
|
|
case DDBD_16:
|
|
return 16;
|
|
case DDBD_24:
|
|
return 24;
|
|
case DDBD_32:
|
|
return 32;
|
|
}
|
|
ASSERTOPENGL(FALSE, "DdbdToCount: Invalid ddbd\n");
|
|
return 0;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GLInitializeProcess
|
|
*
|
|
* Called from OPENGL32.DLL entry point for PROCESS_ATTACH.
|
|
*
|
|
* History:
|
|
* 01-Nov-1994 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL GLInitializeProcess()
|
|
{
|
|
PVOID pv;
|
|
#ifdef _CLIENTSIDE_
|
|
OSVERSIONINFO osvi;
|
|
#endif
|
|
|
|
// Attempt to locate GDI exports for metafiling support
|
|
{
|
|
HMODULE hdll;
|
|
|
|
hdll = GetModuleHandleA("gdi32");
|
|
ASSERTOPENGL(hdll != NULL, "Unable to get gdi32 handle\n");
|
|
*(PROC *)&pfnGdiAddGlsRecord = GetProcAddress(hdll, "GdiAddGlsRecord");
|
|
*(PROC *)&pfnGdiAddGlsBounds = GetProcAddress(hdll, "GdiAddGlsBounds");
|
|
*(PROC *)&pfnGdiIsMetaPrintDC = GetProcAddress(hdll,
|
|
"GdiIsMetaPrintDC");
|
|
|
|
#ifdef ALLOW_DDRAW_SURFACES
|
|
hdll = GetModuleHandleA("ddraw");
|
|
ASSERTOPENGL(hdll != NULL, "Unable to get ddraw handle\n");
|
|
pfnGetSurfaceFromDC = (PFN_GETSURFACEFROMDC)
|
|
GetProcAddress(hdll, "GetSurfaceFromDC");
|
|
#endif
|
|
}
|
|
|
|
#if DBG
|
|
#define STR_OPENGL_DEBUG (PCSTR)"Software\\Microsoft\\Windows\\CurrentVersion\\DebugOpenGL"
|
|
{
|
|
HKEY hkDebug;
|
|
|
|
// Initialize debugging level and flags.
|
|
|
|
glDebugLevel = LEVEL_ERROR;
|
|
glDebugFlags = 0;
|
|
if ( RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
|
STR_OPENGL_DEBUG,
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&hkDebug) == ERROR_SUCCESS )
|
|
{
|
|
DWORD dwDataType;
|
|
DWORD cjSize;
|
|
long lTmp;
|
|
|
|
cjSize = sizeof(long);
|
|
if ( (RegQueryValueExA(hkDebug,
|
|
(LPSTR) "glDebugLevel",
|
|
(LPDWORD) NULL,
|
|
&dwDataType,
|
|
(LPBYTE) &lTmp,
|
|
&cjSize) == ERROR_SUCCESS) )
|
|
{
|
|
glDebugLevel = lTmp;
|
|
}
|
|
|
|
cjSize = sizeof(long);
|
|
if ( (RegQueryValueExA(hkDebug,
|
|
(LPSTR) "glDebugFlags",
|
|
(LPDWORD) NULL,
|
|
&dwDataType,
|
|
(LPBYTE) &lTmp,
|
|
&cjSize) == ERROR_SUCCESS) )
|
|
{
|
|
glDebugFlags = (ULONG) lTmp;
|
|
}
|
|
|
|
RegCloseKey(hkDebug);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef _CLIENTSIDE_
|
|
// Determine which platform we're running on and remember it
|
|
|
|
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
|
if (!GetVersionEx(&osvi))
|
|
{
|
|
WARNING1("GetVersionEx failed with %d\n", GetLastError());
|
|
goto EH_Fail;
|
|
}
|
|
|
|
dwPlatformId = osvi.dwPlatformId;
|
|
|
|
if (!(
|
|
(dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) ||
|
|
(dwPlatformId == VER_PLATFORM_WIN32_NT
|
|
&& !(osvi.dwMajorVersion == 3 && osvi.dwMinorVersion <= 51)
|
|
)
|
|
)
|
|
)
|
|
{
|
|
WARNING("DLL must be run on NT 4.0 or Win95");
|
|
goto EH_Fail;
|
|
}
|
|
|
|
// Allocate a thread local storage slot.
|
|
|
|
if ( (dwTlsIndex = TlsAlloc()) == 0xFFFFFFFF )
|
|
{
|
|
WARNING("DllInitialize: TlsAlloc failed\n");
|
|
goto EH_Fail;
|
|
}
|
|
|
|
// Set up the offset to the TLS slot, OS-specific
|
|
|
|
if (dwPlatformId == VER_PLATFORM_WIN32_NT)
|
|
{
|
|
ASSERTOPENGL(FIELD_OFFSET(TEB, TlsSlots) == NT_TLS_OFFSET,
|
|
"NT TLS offset not at expected location");
|
|
|
|
dwTlsOffset = dwTlsIndex*sizeof(DWORD_PTR)+NT_TLS_OFFSET;
|
|
}
|
|
|
|
#if !defined(_WIN64)
|
|
|
|
else
|
|
{
|
|
// We don't have Win95's TIB type available so the assert is
|
|
// slightly different
|
|
ASSERTOPENGL(((ULONG_PTR)(NtCurrentTeb()->ThreadLocalStoragePointer)-
|
|
(ULONG_PTR)NtCurrentTeb()) == WIN95_TLS_OFFSET,
|
|
"Win95 TLS offset not at expected location");
|
|
|
|
dwTlsOffset = dwTlsIndex*sizeof(DWORD)+WIN95_TLS_OFFSET;
|
|
}
|
|
|
|
#endif
|
|
#endif
|
|
|
|
// Reserve memory for the local handle table.
|
|
|
|
if ( (pLocalTable = (PLHE) VirtualAlloc (
|
|
(LPVOID) NULL, // let base locate it
|
|
MAX_HANDLES*sizeof(LHE),
|
|
MEM_RESERVE | MEM_TOP_DOWN,
|
|
PAGE_READWRITE
|
|
)) == (PLHE) NULL )
|
|
{
|
|
WARNING("DllInitialize: VirtualAlloc failed\n");
|
|
goto EH_TlsIndex;
|
|
}
|
|
|
|
// Initialize the local handle manager semaphore.
|
|
__try
|
|
{
|
|
INITIALIZECRITICALSECTION(&semLocal);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
goto EH_LocalTable;
|
|
}
|
|
|
|
#ifdef _CLIENTSIDE_
|
|
// Initialize the GLGENwindow list semaphore.
|
|
__try
|
|
{
|
|
INITIALIZECRITICALSECTION(&gwndHeader.sem);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
goto EH_semLocal;
|
|
}
|
|
gwndHeader.pNext = &gwndHeader;
|
|
|
|
// Initialize the pixel format critical section
|
|
__try
|
|
{
|
|
INITIALIZECRITICALSECTION(&gcsPixelFormat);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
goto EH_gwndHeader;
|
|
}
|
|
|
|
// Initialize the palette watcher critical section.
|
|
__try
|
|
{
|
|
INITIALIZECRITICALSECTION(&gcsPaletteWatcher);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
goto EH_PixelFormat;
|
|
}
|
|
|
|
// Initialize direct screen access.
|
|
|
|
if (GetSystemMetrics(SM_CMONITORS) > 1)
|
|
{
|
|
gpScreenInfo = NULL;
|
|
}
|
|
else
|
|
{
|
|
#if _WIN32_WINNT >= 0x0501
|
|
BOOL wow64Process;
|
|
|
|
if (IsWow64Process(GetCurrentProcess(), &wow64Process) && wow64Process)
|
|
gpScreenInfo = NULL;
|
|
else
|
|
#endif
|
|
gpScreenInfo = (SCREENINFO *)ALLOCZ(sizeof(SCREENINFO));
|
|
}
|
|
|
|
if ( gpScreenInfo )
|
|
{
|
|
UINT uiOldErrorMode;
|
|
HRESULT hr;
|
|
|
|
// We want to ensure that DDraw doesn't pop up any message
|
|
// boxes on failure when we call DirectDrawCreate. DDraw
|
|
// does errors on a different thread which it creates just
|
|
// for the error. It waits for the error to complete before
|
|
// returning. This function is running inside the loader
|
|
// DllInitialize critical section, though, so other threads
|
|
// do not get to run, causing a deadlock.
|
|
// Force the error mode to get around this.
|
|
uiOldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
|
|
|
|
hr = DirectDrawCreate(NULL, &gpScreenInfo->pdd, NULL);
|
|
|
|
SetErrorMode(uiOldErrorMode);
|
|
|
|
if (hr == DD_OK)
|
|
{
|
|
hr = gpScreenInfo->pdd->lpVtbl->
|
|
SetCooperativeLevel(gpScreenInfo->pdd, NULL, DDSCL_NORMAL);
|
|
|
|
if (hr == DD_OK)
|
|
{
|
|
gpScreenInfo->gdds.ddsd.dwSize = sizeof(DDSURFACEDESC);
|
|
gpScreenInfo->gdds.ddsd.dwFlags = DDSD_CAPS;
|
|
gpScreenInfo->gdds.ddsd.ddsCaps.dwCaps =
|
|
DDSCAPS_PRIMARYSURFACE;
|
|
hr = gpScreenInfo->pdd->lpVtbl->
|
|
CreateSurface(gpScreenInfo->pdd, &gpScreenInfo->gdds.ddsd,
|
|
&gpScreenInfo->gdds.pdds, NULL);
|
|
}
|
|
|
|
if (hr == DD_OK)
|
|
{
|
|
#if DBG
|
|
|
|
#define LEVEL_SCREEN LEVEL_INFO
|
|
|
|
gpScreenInfo->gdds.pdds->lpVtbl->
|
|
GetSurfaceDesc(gpScreenInfo->gdds.pdds,
|
|
&gpScreenInfo->gdds.ddsd);
|
|
DBGLEVEL (LEVEL_SCREEN, "=============================\n");
|
|
DBGLEVEL (LEVEL_SCREEN, "Direct screen access enabled for OpenGL\n\n");
|
|
DBGLEVEL (LEVEL_SCREEN, "Surface info:\n");
|
|
DBGLEVEL1(LEVEL_SCREEN, "\tdwSize = 0x%lx\n",
|
|
gpScreenInfo->gdds.ddsd.dwSize);
|
|
DBGLEVEL1(LEVEL_SCREEN, "\tdwWidth = %ld\n",
|
|
gpScreenInfo->gdds.ddsd.dwWidth);
|
|
DBGLEVEL1(LEVEL_SCREEN, "\tdwHeight = %ld\n",
|
|
gpScreenInfo->gdds.ddsd.dwHeight);
|
|
DBGLEVEL1(LEVEL_SCREEN, "\tlStride = 0x%lx\n",
|
|
gpScreenInfo->gdds.ddsd.lPitch);
|
|
DBGLEVEL1(LEVEL_SCREEN, "\tdwBitCount = %ld\n",
|
|
gpScreenInfo->gdds.ddsd.ddpfPixelFormat.dwRGBBitCount);
|
|
|
|
gpScreenInfo->gdds.pdds->lpVtbl->
|
|
Lock(gpScreenInfo->gdds.pdds,
|
|
NULL, &gpScreenInfo->gdds.ddsd,
|
|
DDLOCK_SURFACEMEMORYPTR, NULL);
|
|
DBGLEVEL1(LEVEL_SCREEN, "\tdwOffSurface = 0x%lx\n",
|
|
gpScreenInfo->gdds.ddsd.lpSurface);
|
|
gpScreenInfo->gdds.pdds->lpVtbl->
|
|
Unlock(gpScreenInfo->gdds.pdds, gpScreenInfo->gdds.ddsd.lpSurface);
|
|
DBGLEVEL (LEVEL_SCREEN, "=============================\n");
|
|
#endif
|
|
|
|
// Verify screen access
|
|
|
|
if (gpScreenInfo->gdds.pdds->lpVtbl->
|
|
GetSurfaceDesc(gpScreenInfo->gdds.pdds,
|
|
&gpScreenInfo->gdds.ddsd) != DD_OK ||
|
|
gpScreenInfo->gdds.pdds->lpVtbl->
|
|
Lock(gpScreenInfo->gdds.pdds,
|
|
NULL, &gpScreenInfo->gdds.ddsd,
|
|
DDLOCK_SURFACEMEMORYPTR, NULL) != DD_OK)
|
|
{
|
|
DBGLEVEL(LEVEL_SCREEN,
|
|
"Direct screen access failure : disabling\n");
|
|
}
|
|
else
|
|
{
|
|
gpScreenInfo->gdds.dwBitDepth =
|
|
DdPixDepthToCount(gpScreenInfo->gdds.ddsd.
|
|
ddpfPixelFormat.dwRGBBitCount);
|
|
gpScreenInfo->gdds.pdds->lpVtbl->
|
|
Unlock(gpScreenInfo->gdds.pdds,
|
|
gpScreenInfo->gdds.ddsd.lpSurface);
|
|
|
|
bDirectScreen = TRUE;
|
|
}
|
|
}
|
|
#if DBG
|
|
else
|
|
{
|
|
DBGLEVEL (LEVEL_SCREEN, "=============================\n");
|
|
DBGLEVEL2(LEVEL_SCREEN,
|
|
"Screen access failed code 0x%08lX (%s)\n",
|
|
hr, (hr == DDERR_NOTFOUND) ? "DDERR_NOTFOUND" :
|
|
"unknown");
|
|
DBGLEVEL (LEVEL_SCREEN, "=============================\n");
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
DBGLEVEL(LEVEL_SCREEN, "DirectDrawCreate failed\n");
|
|
}
|
|
}
|
|
|
|
if (!bDirectScreen)
|
|
{
|
|
if (gpScreenInfo)
|
|
{
|
|
if (gpScreenInfo->gdds.pdds)
|
|
{
|
|
gpScreenInfo->gdds.pdds->lpVtbl->
|
|
Release(gpScreenInfo->gdds.pdds);
|
|
}
|
|
if (gpScreenInfo->pdd)
|
|
{
|
|
gpScreenInfo->pdd->lpVtbl->Release(gpScreenInfo->pdd);
|
|
}
|
|
FREE(gpScreenInfo);
|
|
gpScreenInfo = NULL;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
// Set up our multiplication table:
|
|
|
|
{
|
|
BYTE *pMulTable = gbMulTable;
|
|
ULONG i, j;
|
|
|
|
for (i = 0; i < 256; i++) {
|
|
ULONG tmp = 0;
|
|
|
|
for (j = 0; j < 256; j++, tmp += i) {
|
|
*pMulTable++ = (BYTE)(tmp >> 8);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set up our saturation table:
|
|
|
|
{
|
|
ULONG i;
|
|
|
|
for (i = 0; i < 256; i++)
|
|
gbSatTable[i] = (BYTE)i;
|
|
|
|
for (; i < (256+256); i++)
|
|
gbSatTable[i] = 255;
|
|
}
|
|
|
|
// Set up inverse-lookup table:
|
|
|
|
{
|
|
__GLfloat accum = (__GLfloat)(1.0 / (__GLfloat)__GL_VERTEX_FRAC_ONE);
|
|
GLint i;
|
|
|
|
invTable[0] = (__GLfloat)0.0;
|
|
|
|
for (i = 1; i < INV_TABLE_SIZE; i++) {
|
|
|
|
invTable[i] = __glOne / accum;
|
|
accum += (__GLfloat)(1.0 / (__GLfloat)__GL_VERTEX_FRAC_ONE);
|
|
}
|
|
}
|
|
|
|
bProcessInitialized = TRUE;
|
|
|
|
return TRUE;
|
|
|
|
EH_PixelFormat:
|
|
DELETECRITICALSECTION(&gcsPixelFormat);
|
|
EH_gwndHeader:
|
|
DELETECRITICALSECTION(&gwndHeader.sem);
|
|
EH_semLocal:
|
|
DELETECRITICALSECTION(&semLocal);
|
|
EH_LocalTable:
|
|
VirtualFree(pLocalTable, 0, MEM_RELEASE);
|
|
EH_TlsIndex:
|
|
TlsFree(dwTlsIndex);
|
|
dwTlsIndex = 0xFFFFFFFF;
|
|
EH_Fail:
|
|
return FALSE;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GLUnInitializeProcess
|
|
*
|
|
* Called from OPENGL32.DLL entry point for PROCESS_DETACH.
|
|
*
|
|
* History:
|
|
* 01-Nov-1994 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
void GLUnInitializeProcess()
|
|
{
|
|
// If we never finished process initialization, quit now.
|
|
|
|
if (!bProcessInitialized)
|
|
return;
|
|
|
|
// Cleanup stray HGLRCs that the app may have forgotten to delete.
|
|
{
|
|
static GLTEBINFO gltebInfoTmp;
|
|
|
|
// Need a temporary GLTEBINFO for this thread in order to do the
|
|
// cleanup processing.
|
|
|
|
ASSERTOPENGL(!CURRENT_GLTEBINFO(),
|
|
"GLUnInitializeProcess: GLTEBINFO not NULL!\n");
|
|
// made static and no longer need memset
|
|
// memset(&gltebInfoTmp, 0, sizeof(gltebInfoTmp));
|
|
SET_CURRENT_GLTEBINFO(&gltebInfoTmp);
|
|
|
|
vCleanupAllLRC();
|
|
|
|
SET_CURRENT_GLTEBINFO((PGLTEBINFO) NULL);
|
|
}
|
|
|
|
// Cleanup window tracking structures (GLGENwindow structs).
|
|
|
|
vCleanupWnd();
|
|
|
|
// Cleanup evaluator arrays
|
|
|
|
if (dBufFill)
|
|
FREE(dBufFill);
|
|
if (dBufTopLeft)
|
|
FREE(dBufTopLeft);
|
|
|
|
// Screen access shutdown.
|
|
|
|
if (gpScreenInfo)
|
|
{
|
|
if (gpScreenInfo->gdds.pdds)
|
|
{
|
|
gpScreenInfo->gdds.pdds->lpVtbl->Release(gpScreenInfo->gdds.pdds);
|
|
}
|
|
if (gpScreenInfo->pdd)
|
|
{
|
|
gpScreenInfo->pdd->lpVtbl->Release(gpScreenInfo->pdd);
|
|
}
|
|
FREE(gpScreenInfo);
|
|
}
|
|
|
|
// Free the TLS slot.
|
|
|
|
if (dwTlsIndex != 0xFFFFFFFF)
|
|
if (!TlsFree(dwTlsIndex))
|
|
RIP("DllInitialize: TlsFree failed\n");
|
|
|
|
// Free the global semaphores.
|
|
|
|
DELETECRITICALSECTION(&gcsPaletteWatcher);
|
|
DELETECRITICALSECTION(&gcsPixelFormat);
|
|
DELETECRITICALSECTION(&gwndHeader.sem);
|
|
DELETECRITICALSECTION(&semLocal);
|
|
|
|
// Free the local handle table.
|
|
|
|
if ( pLocalTable )
|
|
VirtualFree(pLocalTable, 0, MEM_RELEASE);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GLInitializeThread
|
|
*
|
|
* Called from OPENGL32.DLL entry point for THREAD_ATTACH. May assume that
|
|
* GLInitializeProcess has succeeded.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID GLInitializeThread(ULONG ulReason)
|
|
{
|
|
GLTEBINFO *pglti;
|
|
GLMSGBATCHINFO *pMsgBatchInfo;
|
|
POLYARRAY *pa;
|
|
|
|
#if !defined(_WIN95_) && defined(_X86_)
|
|
{
|
|
TEB *pteb;
|
|
|
|
pteb = NtCurrentTeb();
|
|
|
|
// Set up linear pointers to TEB regions in the TEB
|
|
// this saves an addition when referencing these values
|
|
// This must occur early so that these pointers are available
|
|
// for the rest of thread initialization
|
|
((POLYARRAY *)pteb->glReserved1)->paTeb =
|
|
(POLYARRAY *)pteb->glReserved1;
|
|
pteb->glTable = pteb->glDispatchTable;
|
|
}
|
|
#endif
|
|
|
|
pglti = (GLTEBINFO *)ALLOCZ(sizeof(GLTEBINFO));
|
|
SET_CURRENT_GLTEBINFO(pglti);
|
|
|
|
if (pglti)
|
|
{
|
|
pa = GLTEB_CLTPOLYARRAY();
|
|
pa->flags = 0; // not in begin mode
|
|
|
|
// Save shared section pointer in POLYARRAY for fast pointer access
|
|
pa->pMsgBatchInfo = (PVOID) pglti->glMsgBatchInfo;
|
|
|
|
pMsgBatchInfo = (GLMSGBATCHINFO *) pa->pMsgBatchInfo;
|
|
pMsgBatchInfo->MaximumOffset
|
|
= SHARED_SECTION_SIZE - GLMSG_ALIGN(sizeof(ULONG));
|
|
pMsgBatchInfo->FirstOffset
|
|
= GLMSG_ALIGN(sizeof(GLMSGBATCHINFO));
|
|
pMsgBatchInfo->NextOffset
|
|
= GLMSG_ALIGN(sizeof(GLMSGBATCHINFO));
|
|
SetCltProcTable(&glNullCltProcTable, &glNullExtProcTable, TRUE);
|
|
GLTEB_SET_CLTCURRENTRC(NULL);
|
|
GLTEB_SET_CLTPOLYMATERIAL(NULL);
|
|
GLTEB_SET_CLTDRIVERSLOT(NULL);
|
|
|
|
#if !defined(_WIN95_)
|
|
ASSERTOPENGL((ULONG_PTR) pMsgBatchInfo == GLMSG_ALIGNPTR(pMsgBatchInfo),
|
|
"bad shared memory alignment!\n");
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
// This can be made into a WARNING (debug builds only) later on.
|
|
DbgPrint ("Memory alloc failed for TebInfo structure, thread may AV if GL calls are made without MakeCurrent\n");
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GLUnInitializeThread
|
|
*
|
|
* Called from OPENGL32.DLL entry point for THREAD_DETACH.
|
|
*
|
|
* The server generic driver should cleanup on its own. Same for the
|
|
* installable driver.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID GLUnInitializeThread(VOID)
|
|
{
|
|
// If we never finished process initialization, quit now.
|
|
|
|
if (!bProcessInitialized)
|
|
return;
|
|
|
|
if (!CURRENT_GLTEBINFO())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (GLTEB_CLTCURRENTRC() != NULL)
|
|
{
|
|
PLRC plrc = GLTEB_CLTCURRENTRC();
|
|
|
|
// May be an application error
|
|
|
|
DBGERROR("GLUnInitializeThread: RC is current when thread exits\n");
|
|
|
|
// Release the RC
|
|
|
|
plrc->tidCurrent = INVALID_THREAD_ID;
|
|
plrc->gwidCurrent.iType = GLWID_ERROR;
|
|
GLTEB_SET_CLTCURRENTRC(NULL);
|
|
vUnlockHandle((ULONG_PTR)(plrc->hrc));
|
|
}
|
|
// GLTEB_SET_CLTPROCTABLE(&glNullCltProcTable,&glNullExtProcTable);
|
|
|
|
if (GLTEB_CLTPOLYMATERIAL())
|
|
FreePolyMaterial();
|
|
|
|
FREE(CURRENT_GLTEBINFO());
|
|
SET_CURRENT_GLTEBINFO(NULL);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* DllInitialize
|
|
*
|
|
* This is the entry point for OPENGL32.DLL, which is called each time
|
|
* a process or thread that is linked to it is created or terminated.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL DllInitialize(HMODULE hModule, ULONG Reason, PVOID Reserved)
|
|
{
|
|
// Do the appropriate task for process and thread attach/detach.
|
|
|
|
DBGLEVEL3(LEVEL_INFO, "DllInitialize: %s Pid %d, Tid %d\n",
|
|
Reason == DLL_PROCESS_ATTACH ? "PROCESS_ATTACH" :
|
|
Reason == DLL_PROCESS_DETACH ? "PROCESS_DETACH" :
|
|
Reason == DLL_THREAD_ATTACH ? "THREAD_ATTACH" :
|
|
Reason == DLL_THREAD_DETACH ? "THREAD_DETACH" :
|
|
"Reason UNKNOWN!",
|
|
GetCurrentProcessId(), GetCurrentThreadId());
|
|
|
|
switch (Reason)
|
|
{
|
|
case DLL_THREAD_ATTACH:
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
if (Reason == DLL_PROCESS_ATTACH)
|
|
{
|
|
if (!GLInitializeProcess())
|
|
return FALSE;
|
|
}
|
|
|
|
InterlockedIncrement(&lThreadsAttached);
|
|
GLInitializeThread(Reason);
|
|
|
|
break;
|
|
|
|
case DLL_THREAD_DETACH:
|
|
case DLL_PROCESS_DETACH:
|
|
|
|
GLUnInitializeThread();
|
|
InterlockedDecrement(&lThreadsAttached);
|
|
|
|
if ( Reason == DLL_PROCESS_DETACH )
|
|
{
|
|
GLUnInitializeProcess();
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
RIP("DllInitialize: unknown reason!\n");
|
|
break;
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|