⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dglcontext.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
// ***********************************************************************

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 + -