📄 dglcontext.c
字号:
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 handlerstatic 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_WGLvoid 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); }*/ // Misc initialisation lpCtx->bCanRender = FALSE; // No rendering allowed yet lpCtx->bSceneStarted = FALSE; lpCtx->bFrameStarted = FALSE; // Detect OS (specifically 'Windows 2000' or 'Windows XP') DetectOS(); // NOTE: WinNT not supported ddlogPrintf(DDLOG_INFO, "OS: %s", bHaveWin95 ? "Win9x" : (bHaveWin2K ? "Win2000/XP" : "Unsupported") ); // Test for Fullscreen if (bHaveWin95) { // Problems with fullscreen on Win2K/XP if ((GetSystemMetrics(SM_CXSCREEN) == lpCtx->dwWidth) && (GetSystemMetrics(SM_CYSCREEN) == lpCtx->dwHeight)) { // Workaround for some apps that crash when going fullscreen. //lpCtx->bFullscreen = TRUE; } }#ifdef _USE_GLD3_WGL _gldDriver.CreateDrawable(lpCtx, glb.bDirectDrawPersistant, glb.bPersistantBuffers);#else // Check if DirectDraw has already been created by original GLRC (DaveM) if (glb.bDirectDrawPersistant && glb.bDirectDraw) { lpCtx->lpDD4 = glb.lpDD4; IDirectDraw4_AddRef(lpCtx->lpDD4); goto SkipDirectDrawCreate;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -