📄 dglcontext.c
字号:
// ***********************************************************************
HGLRC dglCreateContext(
HDC a,
const DGL_pixelFormat *lpPF)
{
int i;
HGLRC hGLRC;
DGL_ctx* lpCtx;
static BOOL bWarnOnce = TRUE;
DWORD dwThreadId = GetCurrentThreadId();
char szMsg[256];
HWND hWnd;
LONG lpfnWndProc;
// Validate license
if (!dglValidate())
return NULL;
// Is context state ready ?
if (!bContextReady)
return NULL;
ddlogPrintf(DDLOG_SYSTEM, "dglCreateContext for HDC=%X, ThreadId=%X", a, dwThreadId);
// Find next free context.
// Also ensure that only one Fullscreen context is created at any one time.
hGLRC = 0; // Default to Not Found
for (i=0; i<DGL_MAX_CONTEXTS; i++) {
if (ctxlist[i].bAllocated) {
if (/*glb.bFullscreen && */ctxlist[i].bFullscreen)
break;
} else {
hGLRC = (HGLRC)(i+1);
break;
}
}
// Bail if no GLRC was found
if (!hGLRC)
return NULL;
// Set the context pointer
lpCtx = dglGetContextAddress(hGLRC);
// Make sure that context is zeroed before we do anything.
// MFC and C++ apps call wglCreateContext() and wglDeleteContext() multiple times,
// even though only one context is ever used by the app, so keep it clean. (DaveM)
ZeroMemory(lpCtx, sizeof(DGL_ctx));
lpCtx->bAllocated = TRUE;
// Flag that buffers need creating on next wglMakeCurrent call.
lpCtx->bHasBeenCurrent = FALSE;
lpCtx->lpPF = (DGL_pixelFormat *)lpPF; // cache pixel format
lpCtx->bCanRender = FALSE;
// Create all the internal resources here, not in dglMakeCurrent().
// We do a re-size check in dglMakeCurrent in case of re-allocations. (DaveM)
// We now try context allocations twice, first with video memory,
// then again with system memory. This is similar to technique
// used for dglWglResizeBuffers(). (DaveM)
if (lpCtx->bHasBeenCurrent == FALSE) {
if (!dglCreateContextBuffers(a, lpCtx, FALSE)) {
if (glb.bMessageBoxWarnings && bWarnOnce && dwLogging) {
bWarnOnce = FALSE;
switch (nContextError) {
case GLDERR_DDRAW: strcpy(szMsg, szDDrawWarning); break;
case GLDERR_D3D: strcpy(szMsg, szD3DWarning); break;
case GLDERR_MEM: strcpy(szMsg, szResourceWarning); break;
case GLDERR_BPP: strcpy(szMsg, szBPPWarning); break;
default: strcpy(szMsg, "");
}
if (strlen(szMsg))
MessageBox(NULL, szMsg, "GLDirect", MB_OK | MB_ICONWARNING);
}
// Only need to try again if memory error
if (nContextError == GLDERR_MEM) {
ddlogPrintf(DDLOG_WARN, "dglCreateContext failed 1st time with video memory");
}
else {
ddlogPrintf(DDLOG_ERROR, "dglCreateContext failed");
return NULL;
}
}
}
// Now that we have a hWnd, we can intercept the WindowProc.
hWnd = lpCtx->hWnd;
if (hWnd) {
// Only hook individual window handler once if not hooked before.
lpfnWndProc = GetWindowLong(hWnd, GWL_WNDPROC);
if (lpfnWndProc != (LONG)dglWndProc) {
lpCtx->lpfnWndProc = lpfnWndProc;
SetWindowLong(hWnd, GWL_WNDPROC, (LONG)dglWndProc);
}
// Find the parent window of the app too.
if (glb.hWndActive == NULL) {
while (hWnd != NULL) {
glb.hWndActive = hWnd;
hWnd = GetParent(hWnd);
}
// Hook the parent window too.
lpfnWndProc = GetWindowLong(glb.hWndActive, GWL_WNDPROC);
if (glb.hWndActive == lpCtx->hWnd)
glb.lpfnWndProc = lpCtx->lpfnWndProc;
else if (lpfnWndProc != (LONG)dglWndProc)
glb.lpfnWndProc = lpfnWndProc;
if (glb.lpfnWndProc)
SetWindowLong(glb.hWndActive, GWL_WNDPROC, (LONG)dglWndProc);
}
}
ddlogPrintf(DDLOG_SYSTEM, "dglCreateContext succeeded for HGLRC=%d", (int)hGLRC);
return hGLRC;
}
// ***********************************************************************
// Make a DirectGL context current
// Used by wgl functions and dgl functions
BOOL dglMakeCurrent(
HDC a,
HGLRC b)
{
int context;
DGL_ctx* lpCtx;
HWND hWnd;
BOOL bNeedResize = FALSE;
BOOL bWindowChanged, bContextChanged;
LPDIRECTDRAWCLIPPER lpddClipper;
DWORD dwThreadId = GetCurrentThreadId();
LONG lpfnWndProc;
// Validate license
if (!dglValidate())
return FALSE;
// Is context state ready ?
if (!bContextReady)
return FALSE;
context = (int)b; // This is as a result of STRICT!
ddlogPrintf(DDLOG_SYSTEM, "dglMakeCurrent: HDC=%X, HGLRC=%d, ThreadId=%X", a, context, dwThreadId);
// If the HGLRC is NULL then make no context current;
// Ditto if the HDC is NULL either. (DaveM)
if (context == 0 || a == 0) {
// Corresponding Mesa operation
#ifdef _USE_GLD3_WGL
_mesa_make_current(NULL, NULL);
#else
(*mesaFuncs.gl_make_current)(NULL, NULL);
#endif
dglSetCurrentContext(0);
return TRUE;
}
// Make sure the HGLRC is in range
if ((context > DGL_MAX_CONTEXTS) || (context < 0)) {
ddlogMessage(DDLOG_ERROR, "dglMakeCurrent: HGLRC out of range\n");
return FALSE;
}
// Find address of context and make sure that it has been allocated
lpCtx = dglGetContextAddress(b);
if (!lpCtx->bAllocated) {
ddlogMessage(DDLOG_ERROR, "dglMakeCurrent: Context not allocated\n");
// return FALSE;
return TRUE; // HACK: Shuts up "WebLab Viewer Pro". KeithH
}
#ifdef GLD_THREADS
// Serialize access to DirectDraw or DDS operations
if (glb.bMultiThreaded)
EnterCriticalSection(&CriticalSection);
#endif
// Check if window has changed
hWnd = (a != lpCtx->hDC) ? WindowFromDC(a) : lpCtx->hWnd;
bWindowChanged = (hWnd != lpCtx->hWnd) ? TRUE : FALSE;
bContextChanged = (b != dglGetCurrentContext()) ? TRUE : FALSE;
// If the window has changed, make sure the clipper is updated. (DaveM)
if (glb.bDirectDrawPersistant && !lpCtx->bFullscreen && (bWindowChanged || bContextChanged)) {
lpCtx->hWnd = hWnd;
#ifndef _USE_GLD3_WGL
IDirectDrawSurface4_GetClipper(lpCtx->lpFront4, &lpddClipper);
IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
IDirectDrawClipper_Release(lpddClipper);
#endif // _USE_GLD3_WGL
}
// Make sure hDC and hWnd is current. (DaveM)
// Obtain the dimensions of the rendering window
lpCtx->hDC = a; // Cache DC
lpCtx->hWnd = hWnd;
hWndLastActive = hWnd;
// Check for non-window DC = memory DC ?
if (hWnd == NULL) {
if (GetClipBox(a, &lpCtx->rcScreenRect) == ERROR) {
ddlogMessage(DDLOG_WARN, "GetClipBox failed in dglMakeCurrent\n");
SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
}
}
else if (!GetClientRect(lpCtx->hWnd, &lpCtx->rcScreenRect)) {
ddlogMessage(DDLOG_WARN, "GetClientRect failed in dglMakeCurrent\n");
SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
}
// Check if buffers need to be re-sized;
// If so, wait until Mesa GL stuff is setup before re-sizing;
if (lpCtx->dwWidth != lpCtx->rcScreenRect.right - lpCtx->rcScreenRect.left ||
lpCtx->dwHeight != lpCtx->rcScreenRect.bottom - lpCtx->rcScreenRect.top)
bNeedResize = TRUE;
// Now we can update our globals
dglSetCurrentContext(b);
// Corresponding Mesa operation
#ifdef _USE_GLD3_WGL
_mesa_make_current(lpCtx->glCtx, lpCtx->glBuffer);
lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL);
if (bNeedResize) {
// Resize buffers (Note Mesa GL needs to be setup beforehand);
// Resize Mesa internal buffer too via glViewport() command,
// which subsequently calls dglWglResizeBuffers() too.
lpCtx->glCtx->Driver.Viewport(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
lpCtx->bHasBeenCurrent = TRUE;
}
#else
(*mesaFuncs.gl_make_current)(lpCtx->glCtx, lpCtx->glBuffer);
dglSetupDDPointers(lpCtx->glCtx);
// Insure DirectDraw surfaces fit current window DC
if (bNeedResize) {
// Resize buffers (Note Mesa GL needs to be setup beforehand);
// Resize Mesa internal buffer too via glViewport() command,
// which subsequently calls dglWglResizeBuffers() too.
(*mesaFuncs.gl_Viewport)(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
lpCtx->bHasBeenCurrent = TRUE;
}
#endif // _USE_GLD3_WGL
ddlogPrintf(DDLOG_SYSTEM, "dglMakeCurrent: width = %d, height = %d", lpCtx->dwWidth, lpCtx->dwHeight);
// We have to clear D3D back buffer and render state if emulated front buffering
// for different window (but not context) like in Solid Edge.
if (glb.bDirectDrawPersistant && glb.bPersistantBuffers
&& (bWindowChanged /* || bContextChanged */) && lpCtx->EmulateSingle) {
#ifdef _USE_GLD3_WGL
// IDirect3DDevice8_EndScene(lpCtx->pDev);
// lpCtx->bSceneStarted = FALSE;
lpCtx->glCtx->Driver.Clear(lpCtx->glCtx, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
GL_TRUE, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
#else
IDirect3DDevice3_EndScene(lpCtx->lpDev3);
lpCtx->bSceneStarted = FALSE;
dglClearD3D(lpCtx->glCtx, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
GL_TRUE, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
#endif // _USE_GLD3_WGL
}
// The first time we call MakeCurrent we set the initial viewport size
if (lpCtx->bHasBeenCurrent == FALSE)
#ifdef _USE_GLD3_WGL
lpCtx->glCtx->Driver.Viewport(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
#else
(*mesaFuncs.gl_Viewport)(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
#endif // _USE_GLD3_WGL
lpCtx->bHasBeenCurrent = TRUE;
#ifdef GLD_THREADS
// Release serialized access
if (glb.bMultiThreaded)
LeaveCriticalSection(&CriticalSection);
#endif
return TRUE;
}
// ***********************************************************************
BOOL dglDeleteContext(
HGLRC a)
{
DGL_ctx* lpCtx;
DWORD dwThreadId = GetCurrentThreadId();
char argstr[256];
#if 0 // We have enough trouble throwing exceptions as it is... (DaveM)
// Validate license
if (!dglValidate())
return FALSE;
#endif
// Is context state ready ?
if (!bContextReady)
return FALSE;
ddlogPrintf(DDLOG_SYSTEM, "dglDeleteContext: Deleting context HGLRC=%d, ThreadId=%X", (int)a, dwThreadId);
// Make sure the HGLRC is in range
if (((int) a> DGL_MAX_CONTEXTS) || ((int)a < 0)) {
ddlogMessage(DDLOG_ERROR, "dglDeleteCurrent: HGLRC out of range\n");
return FALSE;
}
// Make sure context is valid
lpCtx = dglGetContextAddress(a);
if (!lpCtx->bAllocated) {
ddlogPrintf(DDLOG_WARN, "Tried to delete unallocated context HGLRC=%d", (int)a);
// return FALSE;
return TRUE; // HACK: Shuts up "WebLab Viewer Pro". KeithH
}
// Make sure context is de-activated
if (a == dglGetCurrentContext()) {
ddlogPrintf(DDLOG_WARN, "dglDeleteContext: context HGLRC=%d still active", (int)a);
dglMakeCurrent(NULL, NULL);
}
#ifdef GLD_THREADS
// Serialize access to DirectDraw or DDS operations
if (glb.bMultiThreaded)
EnterCriticalSection(&CriticalSection);
#endif
// We are about to destroy all Direct3D objects.
// Therefore we must disable rendering
lpCtx->bCanRender = FALSE;
// This exception handler was installed to catch some
// particularly nasty apps. Console apps that call exit()
// fall into this catagory (i.e. Win32 Glut).
// VC cannot successfully implement multiple exception handlers
// if more than one exception occurs. Therefore reverting back to
// single exception handler as Keith originally had it. (DaveM)
#define WARN_MESSAGE(p) strcpy(argstr, (#p));
#define SAFE_RELEASE(p) WARN_MESSAGE(p); RELEASE(p);
__try {
#ifdef _USE_GLD3_WGL
WARN_MESSAGE(gl_destroy_framebuffer);
if (lpCtx->glBuffer)
_mesa_destroy_framebuffer(lpCtx->glBuffer);
WARN_MESSAGE(gl_destroy_context);
if (lpCtx->glCtx)
_mesa_destroy_context(lpCtx->glCtx);
WARN_MESSAGE(gl_destroy_visual);
if (lpCtx->glVis)
_mesa_destroy_visual(lpCtx->glVis);
_gldDriver.DestroyDrawable(lpCtx);
#else
// Destroy the Mesa context
WARN_MESSAGE(gl_destroy_framebuffer);
if (lpCtx->glBuffer)
(*mesaFuncs.gl_destroy_framebuffer)(lpCtx->glBuffer);
WARN_MESSAGE(gl_destroy_context);
if (lpCtx->glCtx)
(*mesaFuncs.gl_destroy_context)(lpCtx->glCtx);
WARN_MESSAGE(gl_destroy_visual);
if (lpCtx->glVis)
(*mesaFuncs.gl_destroy_visual)(lpCtx->glVis);
SAFE_RELEASE(lpCtx->m_pvbuf); // release D3D vertex buffer
SAFE_RELEASE(lpCtx->m_vbuf); // release D3D vertex buffer
// Delete the global palette
SAFE_RELEASE(lpCtx->lpGlobalPalette);
// Clean up.
if (lpCtx->lpViewport3) {
if (lpCtx->lpDev3) IDirect3DDevice3_DeleteViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
SAFE_RELEASE(lpCtx->lpViewport3);
lpCtx->lpViewport3 = NULL;
}
SAFE_RELEASE(lpCtx->lpDev3);
if (lpCtx->lpDepth4) {
if (lpCtx->lpBack4)
IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpBack4, 0L, lpCtx->lpDepth4);
else
IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpFront4, 0L, lpCtx->lpDepth4);
SAFE_RELEASE(lpCtx->lpDepth4);
lpCtx->lpDepth4 = NULL;
}
SAFE_RELEASE(lpCtx->lpBack4);
SAFE_RELEASE(lpCtx->lpFront4);
if (lpCtx->bFullscreen) {
IDirectDraw4_RestoreDisplayMode(lpCtx->lpDD4);
IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, NULL, DDSCL_NORMAL);
}
SAFE_RELEASE(lpCtx->lpD3D3);
SAFE_RELEASE(lpCtx->lpDD4);
SAFE_RELEASE(lpCtx->lpDD1);
#endif // _ULSE_GLD3_WGL
}
__except(EXCEPTION_EXECUTE_HANDLER) {
ddlogPr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -