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

📄 dglcontext.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
    // Search for DGL context matching window handle
    for (i=0; i<DGL_MAX_CONTEXTS; i++) {
	    if (ctxlist[i].hWnd == hwnd) {
	        lpCtx = &ctxlist[i];
	        lpfnWndProc = lpCtx->lpfnWndProc;
		    break;
        }
    }
	// Not one of ours...
	if (!lpfnWndProc)
	    return DefWindowProc(hwnd, msg, wParam, lParam);

    // Intercept messages amd process *before* passing on to window
	switch (msg) {
#ifdef _USE_GLD3_WGL
	case WM_DISPLAYCHANGE:
		glb.bPixelformatsDirty = TRUE;
		break;
#endif
	case WM_ACTIVATEAPP:
		glb.bAppActive = (BOOL)wParam;
		ddlogPrintf(DDLOG_INFO, "Calling app has been %s", glb.bAppActive ? "activated" : "de-activated");
		break;
	case WM_ERASEBKGND:
		// Eat the GDI erase event for the GL window
        if (!lpCtx || !lpCtx->bHasBeenCurrent)
            break;
		lpCtx->bGDIEraseBkgnd = TRUE;
		return TRUE;
	case WM_PAINT:
		// Eat the invalidated update region if render scene is in progress
        if (!lpCtx || !lpCtx->bHasBeenCurrent)
            break;
		if (lpCtx->bFrameStarted) {
			if (GetUpdateRect(hwnd, &rect, FALSE)) {
				BeginPaint(hwnd, &ps);
				EndPaint(hwnd, &ps);
				ValidateRect(hwnd, &rect);
				return TRUE;
				}
			}
		break;
	}
	// Call the appropriate window message handler
	rc = CallWindowProc((WNDPROC)lpfnWndProc, hwnd, msg, wParam, lParam);

    // Intercept messages and process *after* passing on to window
	switch (msg) {
    case WM_QUIT:
	case WM_DESTROY:
        bQuit = TRUE;
		if (lpCtx && lpCtx->bAllocated) {
			ddlogPrintf(DDLOG_WARN, "WM_DESTROY detected for HWND=%X, HDC=%X, HGLRC=%d", hwnd, lpCtx->hDC, i+1);
			dglDeleteContext((HGLRC)(i+1));
		}
		break;
#if 0
	case WM_SIZE:
		// Resize surfaces to fit window but not viewport (in case app did not bother)
        if (!lpCtx || !lpCtx->bHasBeenCurrent)
            break;
		w = LOWORD(lParam);
		h = HIWORD(lParam);
		if (lpCtx->dwWidth < w || lpCtx->dwHeight < h) {
			if (!dglWglResizeBuffers(lpCtx->glCtx, TRUE))
                 dglWglResizeBuffers(lpCtx->glCtx, FALSE);
        }
		break;
#endif
    }

    // If the main window is quitting, then so should we...
    if (bMain && bQuit) {
		ddlogPrintf(DDLOG_SYSTEM, "shutting down after WM_DESTROY detected for main HWND=%X", hwnd);
        dglDeleteContextState();
        dglExitDriver();
    }

    return rc;
}

// ***********************************************************************

// Driver Window message handler
static LONG __stdcall GLD_EventWndProc(
	HWND hwnd,
	UINT msg,
	WPARAM wParam,
	LPARAM lParam)
{
	switch (msg) {
        // May be sent by splash screen dialog on exit
        case WM_ACTIVATE:
            if (LOWORD(wParam) == WA_ACTIVE && glb.hWndActive) {
                SetForegroundWindow(glb.hWndActive);
                return 0;
                }
            break;
	}
	return DefWindowProc(hwnd, msg, wParam, lParam);
}

// ***********************************************************************

// Intercepted Keyboard handler for detecting hot keys.
LRESULT CALLBACK dglKeyProc(
	int code,
	WPARAM wParam,
	LPARAM lParam)
{
	HWND hWnd, hWndFrame;
	HGLRC hGLRC = NULL;
	DGL_ctx* lpCtx = NULL;
	int cmd = 0, dx1 = 0, dx2 = 0, i;
	static BOOL bAltPressed = FALSE;
	static BOOL bCtrlPressed = FALSE;
	static BOOL bShiftPressed = FALSE;
    RECT r, rf, rc;
    POINT pt;
    BOOL bForceReshape = FALSE;

	return CallNextHookEx(hKeyHook, code, wParam, lParam);
}

// ***********************************************************************

HWND hWndMatch;

// Window handle enumeration procedure.
BOOL CALLBACK dglEnumChildProc(
    HWND hWnd,
    LPARAM lParam)
{
    RECT rect;

    // Find window handle with matching client rect.
    GetClientRect(hWnd, &rect);
    if (EqualRect(&rect, (RECT*)lParam)) {
        hWndMatch = hWnd;
        return FALSE;
        }
    // Continue with next child window.
    return TRUE;
}

// ***********************************************************************

// Find window handle with matching client rect.
HWND dglFindWindowRect(
    RECT* pRect)
{
    hWndMatch = NULL;
    EnumChildWindows(GetForegroundWindow(), dglEnumChildProc, (LPARAM)pRect);
    return hWndMatch;
}

// ***********************************************************************
#ifndef _USE_GLD3_WGL
void dglChooseDisplayMode(
	DGL_ctx *lpCtx)
{
	// Note: Choose an exact match if possible.

	int				i;
	DWORD			area;
	DWORD			bestarea;
	DDSURFACEDESC2	*lpDDSD		= NULL;	// Mode list pointer
	DDSURFACEDESC2	*lpBestDDSD = NULL;	// Pointer to best

	lpDDSD = glb.lpDisplayModes;
	for (i=0; i<glb.nDisplayModeCount; i++, lpDDSD++) {
		if ((lpDDSD->dwWidth == lpCtx->dwWidth) &&
			(lpDDSD->dwHeight == lpCtx->dwHeight))
			goto matched; // Mode has been exactly matched
		// Choose modes that are larger in both dimensions than
		// the window, but smaller in area than the current best.
		if ( (lpDDSD->dwWidth >= lpCtx->dwWidth) &&
			 (lpDDSD->dwHeight >= lpCtx->dwHeight))
		{
			if (lpBestDDSD == NULL) {
				lpBestDDSD = lpDDSD;
				bestarea = lpDDSD->dwWidth * lpDDSD->dwHeight;
				continue;
			}
			area = lpDDSD->dwWidth * lpDDSD->dwHeight;
			if (area < bestarea) {
				lpBestDDSD = lpDDSD;
				bestarea = area;
			}
		}
	}

	// Safety check
	if (lpBestDDSD == NULL) {
		ddlogMessage(DDLOG_CRITICAL, "dglChooseDisplayMode");
		return;
	}

	lpCtx->dwModeWidth = lpBestDDSD->dwWidth;
	lpCtx->dwModeHeight = lpBestDDSD->dwHeight;
matched:
	ddlogPrintf(DDLOG_INFO, "Matched (%ldx%ld) to (%ldx%ld)",
		lpCtx->dwWidth, lpCtx->dwHeight, lpCtx->dwModeWidth, lpCtx->dwModeHeight);
}
#endif // _USE_GLD3_WGL
// ***********************************************************************

static BOOL IsDevice(
	DWORD *lpDeviceIdList,
	DWORD dwDeviceId,
	int count)
{
	int i;

	for (i=0; i<count; i++)
		if (dwDeviceId == lpDeviceIdList[i])
			return TRUE;

	return FALSE;
}

// ***********************************************************************

void dglTestForBrokenCards(
	DGL_ctx *lpCtx)
{
#ifndef _GLD3
	DDDEVICEIDENTIFIER	dddi; // DX6 device identifier

	// Sanity check.
	if (lpCtx == NULL) {
		// Testing for broken cards is sensitive area, so we don't want
		// anything saying "broken cards" in the error message. ;)
		ddlogMessage(DDLOG_ERROR, "Null context passed to TFBC\n");
		return;
	}

	if (lpCtx->lpDD4 == NULL) {
		// Testing for broken cards is sensitive area, so we don't want
		// anything saying "broken cards" in the error message. ;)
		ddlogMessage(DDLOG_ERROR, "Null DD4 passed to TFBC\n");
		return;
	}

	// Microsoft really fucked up with the GetDeviceIdentifier function
	// on Windows 2000, since it locks up on stock driers on the CD. Updated
	// drivers from vendors appear to work, but we can't identify the drivers
	// without this function!!! For now we skip these tests on Windows 2000.
	if ((GetVersion() & 0x80000000UL) == 0)
		return;

	// Obtain device info
	if (FAILED(IDirectDraw4_GetDeviceIdentifier(lpCtx->lpDD4, &dddi, 0)))
		return;

	// Useful info. Log it.
	ddlogPrintf(DDLOG_INFO, "DirectDraw: VendorId=0x%x, DeviceId=0x%x", dddi.dwVendorId, dddi.dwDeviceId);

	// Vendor 1: ATI
	if (dddi.dwVendorId == VENDORID_ATI) {
		// Test A: ATI Rage PRO
		if (IsDevice(devATIRagePro, dddi.dwDeviceId, sizeof(devATIRagePro)))
			glb.bUseMipmaps = FALSE;
		// Test B: ATI Rage II+
		if (IsDevice(devATIRageIIplus, dddi.dwDeviceId, sizeof(devATIRageIIplus)))
			glb.bEmulateAlphaTest = TRUE;
	}

	// Vendor 2: Matrox
	if (dddi.dwVendorId == 0x102B) {
		// Test: Matrox G400 stencil buffer support does not work for AutoCAD
		if (dddi.dwDeviceId == 0x0525) {
			lpCtx->lpPF->pfd.cStencilBits = 0;
			if (lpCtx->lpPF->iZBufferPF != -1) {
				glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwStencilBitDepth = 0;
				glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwStencilBitMask = 0;
				glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwFlags &= ~DDPF_STENCILBUFFER;
			}
		}
	}
#endif // _GLD3
}

// ***********************************************************************

BOOL dglCreateContextBuffers(
	HDC a,
	DGL_ctx *lpCtx,
	BOOL bFallback)
{
	HRESULT				hResult;

	int					i;
//	HGLRC				hGLRC;
//	DGL_ctx*			lpCtx;

#ifndef _USE_GLD3_WGL
	DWORD				dwFlags;
	DDSURFACEDESC2		ddsd2;
	DDSCAPS2			ddscaps2;
	LPDIRECTDRAWCLIPPER	lpddClipper;
	D3DDEVICEDESC		D3DHWDevDesc;	// Direct3D Hardware description
	D3DDEVICEDESC		D3DHELDevDesc;	// Direct3D Hardware Emulation Layer
#endif // _USE_GLD3_WGL

	float				inv_aspect;

	GLenum				bDoubleBuffer;	// TRUE if double buffer required
	GLenum				bDepthBuffer;	// TRUE if depth buffer required

	const PIXELFORMATDESCRIPTOR	*lpPFD = &lpCtx->lpPF->pfd;

	// Vars for Mesa visual
	DWORD				dwDepthBits		= 0;
	DWORD				dwStencilBits	= 0;
	DWORD				dwAlphaBits		= 0;
	DWORD				bAlphaSW		= GL_FALSE;
	DWORD				bDouble			= GL_FALSE;

	DDSURFACEDESC2 		ddsd2DisplayMode;
	BOOL				bFullScrnWin	= FALSE;	// fullscreen-size window ?
	DDBLTFX 			ddbltfx;
	DWORD				dwMemoryType 	= (bFallback) ? DDSCAPS_SYSTEMMEMORY : glb.dwMemoryType;
	BOOL				bBogusWindow	= FALSE;	// non-drawable window ?
	DWORD               dwColorRef      = 0;        // GDI background color
	RECT				rcDst;						// GDI window rect
	POINT				pt;							// GDI window point

	// Palette used for creating default global palette
	PALETTEENTRY	ppe[256];

#ifndef _USE_GLD3_WGL
	// Vertex buffer description. Used for creation of vertex buffers
	D3DVERTEXBUFFERDESC vbufdesc;
#endif // _USE_GLD3_WGL

#define DDLOG_CRITICAL_OR_WARN	(bFallback ? DDLOG_CRITICAL : DDLOG_WARN)

	ddlogPrintf(DDLOG_SYSTEM, "dglCreateContextBuffers for HDC=%X", a);
    nContextError = GLDERR_NONE;

#ifdef GLD_THREADS
	// Serialize access to DirectDraw object creation or DDS start
	if (glb.bMultiThreaded)
		EnterCriticalSection(&CriticalSection);
#endif

	// Check for back buffer
	bDoubleBuffer = GL_TRUE; //(lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE;
	// Since we always do back buffering, check if we emulate front buffering
	lpCtx->EmulateSingle =
		(lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? FALSE : TRUE;
#if 0	// Don't have to mimic MS OpenGL behavior for front-buffering (DaveM)
	lpCtx->EmulateSingle |=
		(lpPFD->dwFlags & PFD_SUPPORT_GDI) ? TRUE : FALSE;
#endif

	// Check for depth buffer
	bDepthBuffer = (lpPFD->cDepthBits) ? GL_TRUE : GL_FALSE;

	lpCtx->bDoubleBuffer = bDoubleBuffer;
	lpCtx->bDepthBuffer = bDepthBuffer;

	// Set the Fullscreen flag for the context.
//	lpCtx->bFullscreen = glb.bFullscreen;

	// Obtain the dimensions of the rendering window
	lpCtx->hDC = a; // Cache DC
	lpCtx->hWnd = WindowFromDC(lpCtx->hDC);
	// Check for non-window DC = memory DC ?
	if (lpCtx->hWnd == NULL) {
        // bitmap memory contexts are always single-buffered
        lpCtx->EmulateSingle = TRUE;
		bBogusWindow = TRUE;
		ddlogPrintf(DDLOG_INFO, "Non-Window Memory Device Context");
		if (GetClipBox(lpCtx->hDC, &lpCtx->rcScreenRect) == ERROR) {
			ddlogMessage(DDLOG_WARN, "GetClipBox failed in dglCreateContext\n");
			SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
		}
	}
	else if (!GetClientRect(lpCtx->hWnd, &lpCtx->rcScreenRect)) {
		bBogusWindow = TRUE;
		ddlogMessage(DDLOG_WARN, "GetClientRect failed in dglCreateContext\n");
		SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
	}
	lpCtx->dwWidth = lpCtx->rcScreenRect.right - lpCtx->rcScreenRect.left;
	lpCtx->dwHeight = lpCtx->rcScreenRect.bottom - lpCtx->rcScreenRect.top;

	ddlogPrintf(DDLOG_INFO, "Input window %X: w=%i, h=%i",
							lpCtx->hWnd, lpCtx->dwWidth, lpCtx->dwHeight);

	// What if app only zeroes one dimension instead of both? (DaveM)
	if ( (lpCtx->dwWidth == 0) || (lpCtx->dwHeight == 0) ) {
		// Make the buffer size something sensible
		lpCtx->dwWidth = 8;
		lpCtx->dwHeight = 8;
	}

	// Set defaults
	lpCtx->dwModeWidth = lpCtx->dwWidth;
	lpCtx->dwModeHeight = lpCtx->dwHeight;
/*
	// Find best display mode for fullscreen
	if (glb.bFullscreen || !glb.bPrimary) {
		dglChooseDisplayMode(lpCtx);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -