Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendglcontext.c
Go to the documentation of this file.
00001 /**************************************************************************** 00002 * 00003 * Mesa 3-D graphics library 00004 * Direct3D Driver Interface 00005 * 00006 * ======================================================================== 00007 * 00008 * Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. 00009 * 00010 * Permission is hereby granted, free of charge, to any person obtaining a 00011 * copy of this software and associated documentation files (the "Software"), 00012 * to deal in the Software without restriction, including without limitation 00013 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00014 * and/or sell copies of the Software, and to permit persons to whom the 00015 * Software is furnished to do so, subject to the following conditions: 00016 * 00017 * The above copyright notice and this permission notice shall be included 00018 * in all copies or substantial portions of the Software. 00019 * 00020 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00021 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00022 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00023 * SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 00024 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 00025 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00026 * SOFTWARE. 00027 * 00028 * ====================================================================== 00029 * 00030 * Language: ANSI C 00031 * Environment: Windows 9x (Win32) 00032 * 00033 * Description: Context handling. 00034 * 00035 ****************************************************************************/ 00036 00037 #include "dglcontext.h" 00038 00039 // Get compile errors without this. KeithH 00040 //#include "scitech.h" // ibool, etc. 00041 00042 #ifdef _USE_GLD3_WGL 00043 #include "gld_driver.h" 00044 00045 extern void _gld_mesa_warning(GLcontext *, char *); 00046 extern void _gld_mesa_fatal(GLcontext *, char *); 00047 #endif // _USE_GLD3_WGL 00048 00049 // TODO: Clean out old DX6-specific code from GLD 2.x CAD driver 00050 // if it is no longer being built as part of GLDirect. (DaveM) 00051 00052 // *********************************************************************** 00053 00054 #define GLDERR_NONE 0 00055 #define GLDERR_MEM 1 00056 #define GLDERR_DDRAW 2 00057 #define GLDERR_D3D 3 00058 #define GLDERR_BPP 4 00059 00060 char szResourceWarning[] = 00061 "GLDirect does not have enough video memory resources\n" 00062 "to support the requested OpenGL rendering context.\n\n" 00063 "You may have to reduce the current display resolution\n" 00064 "to obtain satisfactory OpenGL performance.\n"; 00065 00066 char szDDrawWarning[] = 00067 "GLDirect is unable to initialize DirectDraw for the\n" 00068 "requested OpenGL rendering context.\n\n" 00069 "You will have to check the DirectX control panel\n" 00070 "for further information.\n"; 00071 00072 char szD3DWarning[] = 00073 "GLDirect is unable to initialize Direct3D for the\n" 00074 "requested OpenGL rendering context.\n\n" 00075 "You may have to change the display mode resolution\n" 00076 "color depth or check the DirectX control panel for\n" 00077 "further information.\n"; 00078 00079 char szBPPWarning[] = 00080 "GLDirect is unable to use the selected color depth for\n" 00081 "the requested OpenGL rendering context.\n\n" 00082 "You will have to change the display mode resolution\n" 00083 "color depth with the Display Settings control panel.\n"; 00084 00085 int nContextError = GLDERR_NONE; 00086 00087 // *********************************************************************** 00088 00089 #define VENDORID_ATI 0x1002 00090 00091 static DWORD devATIRagePro[] = { 00092 0x4742, // 3D RAGE PRO BGA AGP 1X/2X 00093 0x4744, // 3D RAGE PRO BGA AGP 1X only 00094 0x4749, // 3D RAGE PRO BGA PCI 33 MHz 00095 0x4750, // 3D RAGE PRO PQFP PCI 33 MHz 00096 0x4751, // 3D RAGE PRO PQFP PCI 33 MHz limited 3D 00097 0x4C42, // 3D RAGE LT PRO BGA-312 AGP 133 MHz 00098 0x4C44, // 3D RAGE LT PRO BGA-312 AGP 66 MHz 00099 0x4C49, // 3D RAGE LT PRO BGA-312 PCI 33 MHz 00100 0x4C50, // 3D RAGE LT PRO BGA-256 PCI 33 MHz 00101 0x4C51, // 3D RAGE LT PRO BGA-256 PCI 33 MHz limited 3D 00102 }; 00103 00104 static DWORD devATIRageIIplus[] = { 00105 0x4755, // 3D RAGE II+ 00106 0x4756, // 3D RAGE IIC PQFP PCI 00107 0x4757, // 3D RAGE IIC BGA AGP 00108 0x475A, // 3D RAGE IIC PQFP AGP 00109 0x4C47, // 3D RAGE LT-G 00110 }; 00111 00112 // *********************************************************************** 00113 00114 #ifndef _USE_GLD3_WGL 00115 extern DGL_mesaFuncs mesaFuncs; 00116 #endif 00117 00118 extern DWORD dwLogging; 00119 00120 #ifdef GLD_THREADS 00121 #pragma message("compiling DGLCONTEXT.C vars for multi-threaded support") 00122 CRITICAL_SECTION CriticalSection; // for serialized access 00123 DWORD dwTLSCurrentContext = 0xFFFFFFFF; // TLS index for current context 00124 DWORD dwTLSPixelFormat = 0xFFFFFFFF; // TLS index for current pixel format 00125 #endif 00126 HGLRC iCurrentContext = 0; // Index of current context (static) 00127 BOOL bContextReady = FALSE; // Context state ready ? 00128 00129 DGL_ctx ctxlist[DGL_MAX_CONTEXTS]; // Context list 00130 00131 // *********************************************************************** 00132 00133 static BOOL bHaveWin95 = FALSE; 00134 static BOOL bHaveWinNT = FALSE; 00135 static BOOL bHaveWin2K = FALSE; 00136 00137 /**************************************************************************** 00138 REMARKS: 00139 Detect the installed OS type. 00140 ****************************************************************************/ 00141 static void DetectOS(void) 00142 { 00143 OSVERSIONINFO VersionInformation; 00144 LPOSVERSIONINFO lpVersionInformation = &VersionInformation; 00145 00146 VersionInformation.dwOSVersionInfoSize = sizeof(VersionInformation); 00147 00148 GetVersionEx(lpVersionInformation); 00149 00150 switch (VersionInformation.dwPlatformId) { 00151 case VER_PLATFORM_WIN32_WINDOWS: 00152 bHaveWin95 = TRUE; 00153 bHaveWinNT = FALSE; 00154 bHaveWin2K = FALSE; 00155 break; 00156 case VER_PLATFORM_WIN32_NT: 00157 bHaveWin95 = FALSE; 00158 if (VersionInformation.dwMajorVersion <= 4) { 00159 bHaveWinNT = TRUE; 00160 bHaveWin2K = FALSE; 00161 } 00162 else { 00163 bHaveWinNT = FALSE; 00164 bHaveWin2K = TRUE; 00165 } 00166 break; 00167 case VER_PLATFORM_WIN32s: 00168 bHaveWin95 = FALSE; 00169 bHaveWinNT = FALSE; 00170 bHaveWin2K = FALSE; 00171 break; 00172 } 00173 } 00174 00175 // *********************************************************************** 00176 00177 HWND hWndEvent = NULL; // event monitor window 00178 HWND hWndLastActive = NULL; // last active client window 00179 LONG __stdcall GLD_EventWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam); 00180 00181 // *********************************************************************** 00182 00183 // Checks if the HGLRC is valid in range of context list. 00184 BOOL dglIsValidContext( 00185 HGLRC a) 00186 { 00187 return ((int)a > 0 && (int)a <= DGL_MAX_CONTEXTS); 00188 } 00189 00190 // *********************************************************************** 00191 00192 // Convert a HGLRC to a pointer into the context list. 00193 DGL_ctx* dglGetContextAddress( 00194 const HGLRC a) 00195 { 00196 if (dglIsValidContext(a)) 00197 return &ctxlist[(int)a-1]; 00198 return NULL; 00199 } 00200 00201 // *********************************************************************** 00202 00203 // Return the current HGLRC (however it may be stored for multi-threading). 00204 HGLRC dglGetCurrentContext(void) 00205 { 00206 #ifdef GLD_THREADS 00207 HGLRC hGLRC; 00208 // load from thread-specific instance 00209 if (glb.bMultiThreaded) { 00210 // protect against calls from arbitrary threads 00211 __try { 00212 hGLRC = (HGLRC)TlsGetValue(dwTLSCurrentContext); 00213 } 00214 __except(EXCEPTION_EXECUTE_HANDLER) { 00215 hGLRC = iCurrentContext; 00216 } 00217 } 00218 // load from global static var 00219 else { 00220 hGLRC = iCurrentContext; 00221 } 00222 return hGLRC; 00223 #else 00224 return iCurrentContext; 00225 #endif 00226 } 00227 00228 // *********************************************************************** 00229 00230 // Set the current HGLRC (however it may be stored for multi-threading). 00231 void dglSetCurrentContext(HGLRC hGLRC) 00232 { 00233 #ifdef GLD_THREADS 00234 // store in thread-specific instance 00235 if (glb.bMultiThreaded) { 00236 // protect against calls from arbitrary threads 00237 __try { 00238 TlsSetValue(dwTLSCurrentContext, (LPVOID)hGLRC); 00239 } 00240 __except(EXCEPTION_EXECUTE_HANDLER) { 00241 iCurrentContext = hGLRC; 00242 } 00243 } 00244 // store in global static var 00245 else { 00246 iCurrentContext = hGLRC; 00247 } 00248 #else 00249 iCurrentContext = hGLRC; 00250 #endif 00251 } 00252 00253 // *********************************************************************** 00254 00255 // Return the current HDC only for a currently active HGLRC. 00256 HDC dglGetCurrentDC(void) 00257 { 00258 HGLRC hGLRC; 00259 DGL_ctx* lpCtx; 00260 00261 hGLRC = dglGetCurrentContext(); 00262 if (hGLRC) { 00263 lpCtx = dglGetContextAddress(hGLRC); 00264 return lpCtx->hDC; 00265 } 00266 return 0; 00267 } 00268 00269 // *********************************************************************** 00270 00271 void dglInitContextState() 00272 { 00273 int i; 00274 WNDCLASS wc; 00275 00276 #ifdef GLD_THREADS 00277 // Allocate thread local storage indexes for current context and pixel format 00278 dwTLSCurrentContext = TlsAlloc(); 00279 dwTLSPixelFormat = TlsAlloc(); 00280 #endif 00281 00282 dglSetCurrentContext(NULL); // No current rendering context 00283 00284 // Clear all context data 00285 ZeroMemory(ctxlist, sizeof(ctxlist[0]) * DGL_MAX_CONTEXTS); 00286 00287 for (i=0; i<DGL_MAX_CONTEXTS; i++) 00288 ctxlist[i].bAllocated = FALSE; // Flag context as unused 00289 00290 // This section of code crashes the dll in circumstances where the app 00291 // creates and destroys contexts. 00292 /* 00293 // Register the class for our event monitor window 00294 wc.style = 0; 00295 wc.lpfnWndProc = GLD_EventWndProc; 00296 wc.cbClsExtra = 0; 00297 wc.cbWndExtra = 0; 00298 wc.hInstance = GetModuleHandle(NULL); 00299 wc.hIcon = LoadIcon(GetModuleHandle(NULL), IDI_APPLICATION); 00300 wc.hCursor = LoadCursor(NULL, IDC_ARROW); 00301 wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); 00302 wc.lpszMenuName = NULL; 00303 wc.lpszClassName = "GLDIRECT"; 00304 RegisterClass(&wc); 00305 00306 // Create the non-visible window to monitor all broadcast messages 00307 hWndEvent = CreateWindowEx( 00308 WS_EX_TOOLWINDOW,"GLDIRECT","GLDIRECT",WS_POPUP, 00309 0,0,0,0, 00310 NULL,NULL,GetModuleHandle(NULL),NULL); 00311 */ 00312 00313 #ifdef GLD_THREADS 00314 // Create a critical section object for serializing access to 00315 // DirectDraw and DDStereo create/destroy functions in multiple threads 00316 if (glb.bMultiThreaded) 00317 InitializeCriticalSection(&CriticalSection); 00318 #endif 00319 00320 // Context state is now initialized and ready 00321 bContextReady = TRUE; 00322 } 00323 00324 // *********************************************************************** 00325 00326 void dglDeleteContextState() 00327 { 00328 int i; 00329 static BOOL bOnceIsEnough = FALSE; 00330 00331 // Only call once, from either DGL_exitDriver(), or DLL_PROCESS_DETACH 00332 if (bOnceIsEnough) 00333 return; 00334 bOnceIsEnough = TRUE; 00335 00336 for (i=0; i<DGL_MAX_CONTEXTS; i++) { 00337 if (ctxlist[i].bAllocated == TRUE) { 00338 ddlogPrintf(DDLOG_WARN, "** Context %i not deleted - cleaning up.", (i+1)); 00339 dglDeleteContext((HGLRC)(i+1)); 00340 } 00341 } 00342 00343 // Context state is no longer ready 00344 bContextReady = FALSE; 00345 00346 // If executed when DLL unloads, DDraw objects may be invalid. 00347 // So catch any page faults with this exception handler. 00348 __try { 00349 00350 // Release final DirectDraw interfaces 00351 if (glb.bDirectDrawPersistant) { 00352 // RELEASE(glb.lpGlobalPalette); 00353 // RELEASE(glb.lpDepth4); 00354 // RELEASE(glb.lpBack4); 00355 // RELEASE(glb.lpPrimary4); 00356 // RELEASE(glb.lpDD4); 00357 } 00358 } 00359 __except(EXCEPTION_EXECUTE_HANDLER) { 00360 ddlogPrintf(DDLOG_WARN, "Exception raised in dglDeleteContextState."); 00361 } 00362 00363 // Destroy our event monitor window 00364 if (hWndEvent) { 00365 DestroyWindow(hWndEvent); 00366 hWndEvent = hWndLastActive = NULL; 00367 } 00368 00369 #ifdef GLD_THREADS 00370 // Destroy the critical section object 00371 if (glb.bMultiThreaded) 00372 DeleteCriticalSection(&CriticalSection); 00373 00374 // Release thread local storage indexes for current HGLRC and pixel format 00375 TlsFree(dwTLSPixelFormat); 00376 TlsFree(dwTLSCurrentContext); 00377 #endif 00378 } 00379 00380 // *********************************************************************** 00381 00382 // Application Window message handler interception 00383 static LONG __stdcall dglWndProc( 00384 HWND hwnd, 00385 UINT msg, 00386 WPARAM wParam, 00387 LPARAM lParam) 00388 { 00389 DGL_ctx* lpCtx = NULL; 00390 LONG lpfnWndProc = 0L; 00391 int i; 00392 HGLRC hGLRC; 00393 RECT rect; 00394 PAINTSTRUCT ps; 00395 BOOL bQuit = FALSE; 00396 BOOL bMain = FALSE; 00397 LONG rc; 00398 00399 // Get the window's message handler *before* it is unhooked in WM_DESTROY 00400 00401 // Is this the main window? 00402 if (hwnd == glb.hWndActive) { 00403 bMain = TRUE; 00404 lpfnWndProc = glb.lpfnWndProc; 00405 } 00406 // Search for DGL context matching window handle 00407 for (i=0; i<DGL_MAX_CONTEXTS; i++) { 00408 if (ctxlist[i].hWnd == hwnd) { 00409 lpCtx = &ctxlist[i]; 00410 lpfnWndProc = lpCtx->lpfnWndProc; 00411 break; 00412 } 00413 } 00414 // Not one of ours... 00415 if (!lpfnWndProc) 00416 return DefWindowProc(hwnd, msg, wParam, lParam); 00417 00418 // Intercept messages amd process *before* passing on to window 00419 switch (msg) { 00420 #ifdef _USE_GLD3_WGL 00421 case WM_DISPLAYCHANGE: 00422 glb.bPixelformatsDirty = TRUE; 00423 break; 00424 #endif 00425 case WM_ACTIVATEAPP: 00426 glb.bAppActive = (BOOL)wParam; 00427 ddlogPrintf(DDLOG_INFO, "Calling app has been %s", glb.bAppActive ? "activated" : "de-activated"); 00428 break; 00429 case WM_ERASEBKGND: 00430 // Eat the GDI erase event for the GL window 00431 if (!lpCtx || !lpCtx->bHasBeenCurrent) 00432 break; 00433 lpCtx->bGDIEraseBkgnd = TRUE; 00434 return TRUE; 00435 case WM_PAINT: 00436 // Eat the invalidated update region if render scene is in progress 00437 if (!lpCtx || !lpCtx->bHasBeenCurrent) 00438 break; 00439 if (lpCtx->bFrameStarted) { 00440 if (GetUpdateRect(hwnd, &rect, FALSE)) { 00441 BeginPaint(hwnd, &ps); 00442 EndPaint(hwnd, &ps); 00443 ValidateRect(hwnd, &rect); 00444 return TRUE; 00445 } 00446 } 00447 break; 00448 } 00449 // Call the appropriate window message handler 00450 rc = CallWindowProc((WNDPROC)lpfnWndProc, hwnd, msg, wParam, lParam); 00451 00452 // Intercept messages and process *after* passing on to window 00453 switch (msg) { 00454 case WM_QUIT: 00455 case WM_DESTROY: 00456 bQuit = TRUE; 00457 if (lpCtx && lpCtx->bAllocated) { 00458 ddlogPrintf(DDLOG_WARN, "WM_DESTROY detected for HWND=%X, HDC=%X, HGLRC=%d", hwnd, lpCtx->hDC, i+1); 00459 dglDeleteContext((HGLRC)(i+1)); 00460 } 00461 break; 00462 #if 0 00463 case WM_SIZE: 00464 // Resize surfaces to fit window but not viewport (in case app did not bother) 00465 if (!lpCtx || !lpCtx->bHasBeenCurrent) 00466 break; 00467 w = LOWORD(lParam); 00468 h = HIWORD(lParam); 00469 if (lpCtx->dwWidth < w || lpCtx->dwHeight < h) { 00470 if (!dglWglResizeBuffers(lpCtx->glCtx, TRUE)) 00471 dglWglResizeBuffers(lpCtx->glCtx, FALSE); 00472 } 00473 break; 00474 #endif 00475 } 00476 00477 // If the main window is quitting, then so should we... 00478 if (bMain && bQuit) { 00479 ddlogPrintf(DDLOG_SYSTEM, "shutting down after WM_DESTROY detected for main HWND=%X", hwnd); 00480 dglDeleteContextState(); 00481 dglExitDriver(); 00482 } 00483 00484 return rc; 00485 } 00486 00487 // *********************************************************************** 00488 00489 // Driver Window message handler 00490 static LONG __stdcall GLD_EventWndProc( 00491 HWND hwnd, 00492 UINT msg, 00493 WPARAM wParam, 00494 LPARAM lParam) 00495 { 00496 switch (msg) { 00497 // May be sent by splash screen dialog on exit 00498 case WM_ACTIVATE: 00499 if (LOWORD(wParam) == WA_ACTIVE && glb.hWndActive) { 00500 SetForegroundWindow(glb.hWndActive); 00501 return 0; 00502 } 00503 break; 00504 } 00505 return DefWindowProc(hwnd, msg, wParam, lParam); 00506 } 00507 00508 // *********************************************************************** 00509 00510 // Intercepted Keyboard handler for detecting hot keys. 00511 LRESULT CALLBACK dglKeyProc( 00512 int code, 00513 WPARAM wParam, 00514 LPARAM lParam) 00515 { 00516 HWND hWnd, hWndFrame; 00517 HGLRC hGLRC = NULL; 00518 DGL_ctx* lpCtx = NULL; 00519 int cmd = 0, dx1 = 0, dx2 = 0, i; 00520 static BOOL bAltPressed = FALSE; 00521 static BOOL bCtrlPressed = FALSE; 00522 static BOOL bShiftPressed = FALSE; 00523 RECT r, rf, rc; 00524 POINT pt; 00525 BOOL bForceReshape = FALSE; 00526 00527 return CallNextHookEx(hKeyHook, code, wParam, lParam); 00528 } 00529 00530 // *********************************************************************** 00531 00532 HWND hWndMatch; 00533 00534 // Window handle enumeration procedure. 00535 BOOL CALLBACK dglEnumChildProc( 00536 HWND hWnd, 00537 LPARAM lParam) 00538 { 00539 RECT rect; 00540 00541 // Find window handle with matching client rect. 00542 GetClientRect(hWnd, &rect); 00543 if (EqualRect(&rect, (RECT*)lParam)) { 00544 hWndMatch = hWnd; 00545 return FALSE; 00546 } 00547 // Continue with next child window. 00548 return TRUE; 00549 } 00550 00551 // *********************************************************************** 00552 00553 // Find window handle with matching client rect. 00554 HWND dglFindWindowRect( 00555 RECT* pRect) 00556 { 00557 hWndMatch = NULL; 00558 EnumChildWindows(GetForegroundWindow(), dglEnumChildProc, (LPARAM)pRect); 00559 return hWndMatch; 00560 } 00561 00562 // *********************************************************************** 00563 #ifndef _USE_GLD3_WGL 00564 void dglChooseDisplayMode( 00565 DGL_ctx *lpCtx) 00566 { 00567 // Note: Choose an exact match if possible. 00568 00569 int i; 00570 DWORD area; 00571 DWORD bestarea; 00572 DDSURFACEDESC2 *lpDDSD = NULL; // Mode list pointer 00573 DDSURFACEDESC2 *lpBestDDSD = NULL; // Pointer to best 00574 00575 lpDDSD = glb.lpDisplayModes; 00576 for (i=0; i<glb.nDisplayModeCount; i++, lpDDSD++) { 00577 if ((lpDDSD->dwWidth == lpCtx->dwWidth) && 00578 (lpDDSD->dwHeight == lpCtx->dwHeight)) 00579 goto matched; // Mode has been exactly matched 00580 // Choose modes that are larger in both dimensions than 00581 // the window, but smaller in area than the current best. 00582 if ( (lpDDSD->dwWidth >= lpCtx->dwWidth) && 00583 (lpDDSD->dwHeight >= lpCtx->dwHeight)) 00584 { 00585 if (lpBestDDSD == NULL) { 00586 lpBestDDSD = lpDDSD; 00587 bestarea = lpDDSD->dwWidth * lpDDSD->dwHeight; 00588 continue; 00589 } 00590 area = lpDDSD->dwWidth * lpDDSD->dwHeight; 00591 if (area < bestarea) { 00592 lpBestDDSD = lpDDSD; 00593 bestarea = area; 00594 } 00595 } 00596 } 00597 00598 // Safety check 00599 if (lpBestDDSD == NULL) { 00600 ddlogMessage(DDLOG_CRITICAL, "dglChooseDisplayMode"); 00601 return; 00602 } 00603 00604 lpCtx->dwModeWidth = lpBestDDSD->dwWidth; 00605 lpCtx->dwModeHeight = lpBestDDSD->dwHeight; 00606 matched: 00607 ddlogPrintf(DDLOG_INFO, "Matched (%ldx%ld) to (%ldx%ld)", 00608 lpCtx->dwWidth, lpCtx->dwHeight, lpCtx->dwModeWidth, lpCtx->dwModeHeight); 00609 } 00610 #endif // _USE_GLD3_WGL 00611 // *********************************************************************** 00612 00613 static BOOL IsDevice( 00614 DWORD *lpDeviceIdList, 00615 DWORD dwDeviceId, 00616 int count) 00617 { 00618 int i; 00619 00620 for (i=0; i<count; i++) 00621 if (dwDeviceId == lpDeviceIdList[i]) 00622 return TRUE; 00623 00624 return FALSE; 00625 } 00626 00627 // *********************************************************************** 00628 00629 void dglTestForBrokenCards( 00630 DGL_ctx *lpCtx) 00631 { 00632 #ifndef _GLD3 00633 DDDEVICEIDENTIFIER dddi; // DX6 device identifier 00634 00635 // Sanity check. 00636 if (lpCtx == NULL) { 00637 // Testing for broken cards is sensitive area, so we don't want 00638 // anything saying "broken cards" in the error message. ;) 00639 ddlogMessage(DDLOG_ERROR, "Null context passed to TFBC\n"); 00640 return; 00641 } 00642 00643 if (lpCtx->lpDD4 == NULL) { 00644 // Testing for broken cards is sensitive area, so we don't want 00645 // anything saying "broken cards" in the error message. ;) 00646 ddlogMessage(DDLOG_ERROR, "Null DD4 passed to TFBC\n"); 00647 return; 00648 } 00649 00650 // Microsoft really fucked up with the GetDeviceIdentifier function 00651 // on Windows 2000, since it locks up on stock driers on the CD. Updated 00652 // drivers from vendors appear to work, but we can't identify the drivers 00653 // without this function!!! For now we skip these tests on Windows 2000. 00654 if ((GetVersion() & 0x80000000UL) == 0) 00655 return; 00656 00657 // Obtain device info 00658 if (FAILED(IDirectDraw4_GetDeviceIdentifier(lpCtx->lpDD4, &dddi, 0))) 00659 return; 00660 00661 // Useful info. Log it. 00662 ddlogPrintf(DDLOG_INFO, "DirectDraw: VendorId=0x%x, DeviceId=0x%x", dddi.dwVendorId, dddi.dwDeviceId); 00663 00664 // Vendor 1: ATI 00665 if (dddi.dwVendorId == VENDORID_ATI) { 00666 // Test A: ATI Rage PRO 00667 if (IsDevice(devATIRagePro, dddi.dwDeviceId, sizeof(devATIRagePro))) 00668 glb.bUseMipmaps = FALSE; 00669 // Test B: ATI Rage II+ 00670 if (IsDevice(devATIRageIIplus, dddi.dwDeviceId, sizeof(devATIRageIIplus))) 00671 glb.bEmulateAlphaTest = TRUE; 00672 } 00673 00674 // Vendor 2: Matrox 00675 if (dddi.dwVendorId == 0x102B) { 00676 // Test: Matrox G400 stencil buffer support does not work for AutoCAD 00677 if (dddi.dwDeviceId == 0x0525) { 00678 lpCtx->lpPF->pfd.cStencilBits = 0; 00679 if (lpCtx->lpPF->iZBufferPF != -1) { 00680 glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwStencilBitDepth = 0; 00681 glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwStencilBitMask = 0; 00682 glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwFlags &= ~DDPF_STENCILBUFFER; 00683 } 00684 } 00685 } 00686 #endif // _GLD3 00687 } 00688 00689 // *********************************************************************** 00690 00691 BOOL dglCreateContextBuffers( 00692 HDC a, 00693 DGL_ctx *lpCtx, 00694 BOOL bFallback) 00695 { 00696 HRESULT hResult; 00697 00698 int i; 00699 // HGLRC hGLRC; 00700 // DGL_ctx* lpCtx; 00701 00702 #ifndef _USE_GLD3_WGL 00703 DWORD dwFlags; 00704 DDSURFACEDESC2 ddsd2; 00705 DDSCAPS2 ddscaps2; 00706 LPDIRECTDRAWCLIPPER lpddClipper; 00707 D3DDEVICEDESC D3DHWDevDesc; // Direct3D Hardware description 00708 D3DDEVICEDESC D3DHELDevDesc; // Direct3D Hardware Emulation Layer 00709 #endif // _USE_GLD3_WGL 00710 00711 float inv_aspect; 00712 00713 GLenum bDoubleBuffer; // TRUE if double buffer required 00714 GLenum bDepthBuffer; // TRUE if depth buffer required 00715 00716 const PIXELFORMATDESCRIPTOR *lpPFD = &lpCtx->lpPF->pfd; 00717 00718 // Vars for Mesa visual 00719 DWORD dwDepthBits = 0; 00720 DWORD dwStencilBits = 0; 00721 DWORD dwAlphaBits = 0; 00722 DWORD bAlphaSW = GL_FALSE; 00723 DWORD bDouble = GL_FALSE; 00724 00725 DDSURFACEDESC2 ddsd2DisplayMode; 00726 BOOL bFullScrnWin = FALSE; // fullscreen-size window ? 00727 DDBLTFX ddbltfx; 00728 DWORD dwMemoryType = (bFallback) ? DDSCAPS_SYSTEMMEMORY : glb.dwMemoryType; 00729 BOOL bBogusWindow = FALSE; // non-drawable window ? 00730 DWORD dwColorRef = 0; // GDI background color 00731 RECT rcDst; // GDI window rect 00732 POINT pt; // GDI window point 00733 00734 // Palette used for creating default global palette 00735 PALETTEENTRY ppe[256]; 00736 00737 #ifndef _USE_GLD3_WGL 00738 // Vertex buffer description. Used for creation of vertex buffers 00739 D3DVERTEXBUFFERDESC vbufdesc; 00740 #endif // _USE_GLD3_WGL 00741 00742 #define DDLOG_CRITICAL_OR_WARN (bFallback ? DDLOG_CRITICAL : DDLOG_WARN) 00743 00744 ddlogPrintf(DDLOG_SYSTEM, "dglCreateContextBuffers for HDC=%X", a); 00745 nContextError = GLDERR_NONE; 00746 00747 #ifdef GLD_THREADS 00748 // Serialize access to DirectDraw object creation or DDS start 00749 if (glb.bMultiThreaded) 00750 EnterCriticalSection(&CriticalSection); 00751 #endif 00752 00753 // Check for back buffer 00754 bDoubleBuffer = GL_TRUE; //(lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE; 00755 // Since we always do back buffering, check if we emulate front buffering 00756 lpCtx->EmulateSingle = 00757 (lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? FALSE : TRUE; 00758 #if 0 // Don't have to mimic MS OpenGL behavior for front-buffering (DaveM) 00759 lpCtx->EmulateSingle |= 00760 (lpPFD->dwFlags & PFD_SUPPORT_GDI) ? TRUE : FALSE; 00761 #endif 00762 00763 // Check for depth buffer 00764 bDepthBuffer = (lpPFD->cDepthBits) ? GL_TRUE : GL_FALSE; 00765 00766 lpCtx->bDoubleBuffer = bDoubleBuffer; 00767 lpCtx->bDepthBuffer = bDepthBuffer; 00768 00769 // Set the Fullscreen flag for the context. 00770 // lpCtx->bFullscreen = glb.bFullscreen; 00771 00772 // Obtain the dimensions of the rendering window 00773 lpCtx->hDC = a; // Cache DC 00774 lpCtx->hWnd = WindowFromDC(lpCtx->hDC); 00775 // Check for non-window DC = memory DC ? 00776 if (lpCtx->hWnd == NULL) { 00777 // bitmap memory contexts are always single-buffered 00778 lpCtx->EmulateSingle = TRUE; 00779 bBogusWindow = TRUE; 00780 ddlogPrintf(DDLOG_INFO, "Non-Window Memory Device Context"); 00781 if (GetClipBox(lpCtx->hDC, &lpCtx->rcScreenRect) == ERROR) { 00782 ddlogMessage(DDLOG_WARN, "GetClipBox failed in dglCreateContext\n"); 00783 SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0); 00784 } 00785 } 00786 else if (!GetClientRect(lpCtx->hWnd, &lpCtx->rcScreenRect)) { 00787 bBogusWindow = TRUE; 00788 ddlogMessage(DDLOG_WARN, "GetClientRect failed in dglCreateContext\n"); 00789 SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0); 00790 } 00791 lpCtx->dwWidth = lpCtx->rcScreenRect.right - lpCtx->rcScreenRect.left; 00792 lpCtx->dwHeight = lpCtx->rcScreenRect.bottom - lpCtx->rcScreenRect.top; 00793 00794 ddlogPrintf(DDLOG_INFO, "Input window %X: w=%i, h=%i", 00795 lpCtx->hWnd, lpCtx->dwWidth, lpCtx->dwHeight); 00796 00797 // What if app only zeroes one dimension instead of both? (DaveM) 00798 if ( (lpCtx->dwWidth == 0) || (lpCtx->dwHeight == 0) ) { 00799 // Make the buffer size something sensible 00800 lpCtx->dwWidth = 8; 00801 lpCtx->dwHeight = 8; 00802 } 00803 00804 // Set defaults 00805 lpCtx->dwModeWidth = lpCtx->dwWidth; 00806 lpCtx->dwModeHeight = lpCtx->dwHeight; 00807 /* 00808 // Find best display mode for fullscreen 00809 if (glb.bFullscreen || !glb.bPrimary) { 00810 dglChooseDisplayMode(lpCtx); 00811 } 00812 */ 00813 // Misc initialisation 00814 lpCtx->bCanRender = FALSE; // No rendering allowed yet 00815 lpCtx->bSceneStarted = FALSE; 00816 lpCtx->bFrameStarted = FALSE; 00817 00818 // Detect OS (specifically 'Windows 2000' or 'Windows XP') 00819 DetectOS(); 00820 00821 // NOTE: WinNT not supported 00822 ddlogPrintf(DDLOG_INFO, "OS: %s", bHaveWin95 ? "Win9x" : (bHaveWin2K ? "Win2000/XP" : "Unsupported") ); 00823 00824 // Test for Fullscreen 00825 if (bHaveWin95) { // Problems with fullscreen on Win2K/XP 00826 if ((GetSystemMetrics(SM_CXSCREEN) == lpCtx->dwWidth) && 00827 (GetSystemMetrics(SM_CYSCREEN) == lpCtx->dwHeight)) 00828 { 00829 // Workaround for some apps that crash when going fullscreen. 00830 //lpCtx->bFullscreen = TRUE; 00831 } 00832 00833 } 00834 00835 #ifdef _USE_GLD3_WGL 00836 _gldDriver.CreateDrawable(lpCtx, glb.bDirectDrawPersistant, glb.bPersistantBuffers); 00837 #else 00838 // Check if DirectDraw has already been created by original GLRC (DaveM) 00839 if (glb.bDirectDrawPersistant && glb.bDirectDraw) { 00840 lpCtx->lpDD4 = glb.lpDD4; 00841 IDirectDraw4_AddRef(lpCtx->lpDD4); 00842 goto SkipDirectDrawCreate; 00843 } 00844 00845 // Create DirectDraw object 00846 if (glb.bPrimary) 00847 hResult = DirectDrawCreate(NULL, &lpCtx->lpDD1, NULL); 00848 else { 00849 // A non-primary device is to be used. 00850 // Force context to be Fullscreen, secondary adaptors can not 00851 // be used in a window. 00852 hResult = DirectDrawCreate(&glb.ddGuid, &lpCtx->lpDD1, NULL); 00853 lpCtx->bFullscreen = TRUE; 00854 } 00855 if (FAILED(hResult)) { 00856 MessageBox(NULL, "Unable to initialize DirectDraw", "GLDirect", MB_OK); 00857 ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create DirectDraw interface", hResult); 00858 nContextError = GLDERR_DDRAW; 00859 goto return_with_error; 00860 } 00861 00862 // Query for DX6 IDirectDraw4. 00863 hResult = IDirectDraw_QueryInterface(lpCtx->lpDD1, 00864 &IID_IDirectDraw4, 00865 (void**)&lpCtx->lpDD4); 00866 if (FAILED(hResult)) { 00867 MessageBox(NULL, "GLDirect requires DirectX 6.0 or above", "GLDirect", MB_OK); 00868 ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create DirectDraw4 interface", hResult); 00869 nContextError = GLDERR_DDRAW; 00870 goto return_with_error; 00871 } 00872 00873 // Cache DirectDraw interface for subsequent GLRCs 00874 if (glb.bDirectDrawPersistant && !glb.bDirectDraw) { 00875 glb.lpDD4 = lpCtx->lpDD4; 00876 IDirectDraw4_AddRef(glb.lpDD4); 00877 glb.bDirectDraw = TRUE; 00878 } 00879 SkipDirectDrawCreate: 00880 00881 // Now we have a DD4 interface we can check for broken cards 00882 dglTestForBrokenCards(lpCtx); 00883 00884 // Test if primary device can use flipping instead of blitting 00885 ZeroMemory(&ddsd2DisplayMode, sizeof(ddsd2DisplayMode)); 00886 ddsd2DisplayMode.dwSize = sizeof(ddsd2DisplayMode); 00887 hResult = IDirectDraw4_GetDisplayMode( 00888 lpCtx->lpDD4, 00889 &ddsd2DisplayMode); 00890 if (SUCCEEDED(hResult)) { 00891 if ( (lpCtx->dwWidth == ddsd2DisplayMode.dwWidth) && 00892 (lpCtx->dwHeight == ddsd2DisplayMode.dwHeight) ) { 00893 // We have a fullscreen-size window 00894 bFullScrnWin = TRUE; 00895 // OK to use DirectDraw fullscreen mode ? 00896 if (glb.bPrimary && !glb.bFullscreenBlit && !lpCtx->EmulateSingle && !glb.bDirectDrawPersistant) { 00897 lpCtx->bFullscreen = TRUE; 00898 ddlogMessage(DDLOG_INFO, "Primary upgraded to page flipping.\n"); 00899 } 00900 } 00901 // Cache the display mode dimensions 00902 lpCtx->dwModeWidth = ddsd2DisplayMode.dwWidth; 00903 lpCtx->dwModeHeight = ddsd2DisplayMode.dwHeight; 00904 } 00905 00906 // Clamp the effective window dimensions to primary surface. 00907 // We need to do this for D3D viewport dimensions even if wide 00908 // surfaces are supported. This also is a good idea for handling 00909 // whacked-out window dimensions passed for non-drawable windows 00910 // like Solid Edge. (DaveM) 00911 if (lpCtx->dwWidth > ddsd2DisplayMode.dwWidth) 00912 lpCtx->dwWidth = ddsd2DisplayMode.dwWidth; 00913 if (lpCtx->dwHeight > ddsd2DisplayMode.dwHeight) 00914 lpCtx->dwHeight = ddsd2DisplayMode.dwHeight; 00915 00916 // Check for non-RGB desktop resolution 00917 if (!lpCtx->bFullscreen && ddsd2DisplayMode.ddpfPixelFormat.dwRGBBitCount <= 8) { 00918 ddlogPrintf(DDLOG_CRITICAL_OR_WARN, "Desktop color depth %d bpp not supported", 00919 ddsd2DisplayMode.ddpfPixelFormat.dwRGBBitCount); 00920 nContextError = GLDERR_BPP; 00921 goto return_with_error; 00922 } 00923 #endif // _USE_GLD3_WGL 00924 00925 ddlogPrintf(DDLOG_INFO, "Window: w=%i, h=%i (%s)", 00926 lpCtx->dwWidth, 00927 lpCtx->dwHeight, 00928 lpCtx->bFullscreen ? "fullscreen" : "windowed"); 00929 00930 #ifndef _USE_GLD3_WGL 00931 // Obtain ddraw caps 00932 ZeroMemory(&lpCtx->ddCaps, sizeof(DDCAPS)); 00933 lpCtx->ddCaps.dwSize = sizeof(DDCAPS); 00934 if (glb.bHardware) { 00935 // Get HAL caps 00936 IDirectDraw4_GetCaps(lpCtx->lpDD4, &lpCtx->ddCaps, NULL); 00937 } else { 00938 // Get HEL caps 00939 IDirectDraw4_GetCaps(lpCtx->lpDD4, NULL, &lpCtx->ddCaps); 00940 } 00941 00942 // If this flag is present then we can't default to Mesa 00943 // SW rendering between BeginScene() and EndScene(). 00944 if (lpCtx->ddCaps.dwCaps2 & DDCAPS2_NO2DDURING3DSCENE) { 00945 ddlogMessage(DDLOG_INFO, 00946 "Warning : No 2D allowed during 3D scene.\n"); 00947 } 00948 00949 // Query for DX6 Direct3D3 interface 00950 hResult = IDirectDraw4_QueryInterface(lpCtx->lpDD4, 00951 &IID_IDirect3D3, 00952 (void**)&lpCtx->lpD3D3); 00953 if (FAILED(hResult)) { 00954 MessageBox(NULL, "Unable to initialize Direct3D", "GLDirect", MB_OK); 00955 ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D interface", hResult); 00956 nContextError = GLDERR_D3D; 00957 goto return_with_error; 00958 } 00959 00960 // Context creation 00961 if (lpCtx->bFullscreen) { 00962 // FULLSCREEN 00963 00964 // Disable warning popups when in fullscreen mode 00965 ddlogWarnOption(FALSE); 00966 00967 // Have to release persistant primary surface if fullscreen mode 00968 if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) { 00969 RELEASE(glb.lpPrimary4); 00970 glb.bDirectDrawPrimary = FALSE; 00971 } 00972 00973 dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT; 00974 if (glb.bFastFPU) 00975 dwFlags |= DDSCL_FPUSETUP; // fast FPU setup optional (DaveM) 00976 hResult = IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, lpCtx->hWnd, dwFlags); 00977 if (FAILED(hResult)) { 00978 ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to set Exclusive Fullscreen mode", hResult); 00979 goto return_with_error; 00980 } 00981 00982 hResult = IDirectDraw4_SetDisplayMode(lpCtx->lpDD4, 00983 lpCtx->dwModeWidth, 00984 lpCtx->dwModeHeight, 00985 lpPFD->cColorBits, 00986 0, 00987 0); 00988 if (FAILED(hResult)) { 00989 ddlogError(DDLOG_CRITICAL_OR_WARN, "SetDisplayMode failed", hResult); 00990 goto return_with_error; 00991 } 00992 00993 // ** The display mode has changed, so dont use MessageBox! ** 00994 00995 ZeroMemory(&ddsd2, sizeof(ddsd2)); 00996 ddsd2.dwSize = sizeof(ddsd2); 00997 00998 if (bDoubleBuffer) { 00999 // Double buffered 01000 // Primary surface 01001 ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; 01002 ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | 01003 DDSCAPS_FLIP | 01004 DDSCAPS_COMPLEX | 01005 DDSCAPS_3DDEVICE | 01006 dwMemoryType; 01007 ddsd2.dwBackBufferCount = 1; 01008 01009 hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL); 01010 if (FAILED(hResult)) { 01011 ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult); 01012 nContextError = GLDERR_MEM; 01013 goto return_with_error; 01014 } 01015 01016 // Render target surface 01017 ZeroMemory(&ddscaps2, sizeof(ddscaps2)); // Clear the entire struct. 01018 ddscaps2.dwCaps = DDSCAPS_BACKBUFFER; 01019 hResult = IDirectDrawSurface4_GetAttachedSurface(lpCtx->lpFront4, &ddscaps2, &lpCtx->lpBack4); 01020 if (FAILED(hResult)) { 01021 ddlogError(DDLOG_CRITICAL_OR_WARN, "GetAttachedSurface failed", hResult); 01022 nContextError = GLDERR_MEM; 01023 goto return_with_error; 01024 } 01025 } else { 01026 // Single buffered 01027 // Primary surface 01028 ddsd2.dwFlags = DDSD_CAPS; 01029 ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | 01030 //DDSCAPS_3DDEVICE | 01031 dwMemoryType; 01032 01033 hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL); 01034 if (FAILED(hResult)) { 01035 ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult); 01036 nContextError = GLDERR_MEM; 01037 goto return_with_error; 01038 } 01039 01040 lpCtx->lpBack4 = NULL; 01041 } 01042 } else { 01043 // WINDOWED 01044 01045 // OK to enable warning popups in windowed mode 01046 ddlogWarnOption(glb.bMessageBoxWarnings); 01047 01048 dwFlags = DDSCL_NORMAL; 01049 if (glb.bMultiThreaded) 01050 dwFlags |= DDSCL_MULTITHREADED; 01051 if (glb.bFastFPU) 01052 dwFlags |= DDSCL_FPUSETUP; // fast FPU setup optional (DaveM) 01053 hResult = IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, 01054 lpCtx->hWnd, 01055 dwFlags); 01056 if (FAILED(hResult)) { 01057 ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to set Normal coop level", hResult); 01058 goto return_with_error; 01059 } 01060 // Has Primary surface already been created for original GLRC ? 01061 // Note this can only be applicable for windowed modes 01062 if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) { 01063 lpCtx->lpFront4 = glb.lpPrimary4; 01064 IDirectDrawSurface4_AddRef(lpCtx->lpFront4); 01065 // Update the window on the default clipper 01066 IDirectDrawSurface4_GetClipper(lpCtx->lpFront4, &lpddClipper); 01067 IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd); 01068 IDirectDrawClipper_Release(lpddClipper); 01069 goto SkipPrimaryCreate; 01070 } 01071 01072 // Primary surface 01073 ZeroMemory(&ddsd2, sizeof(ddsd2)); 01074 ddsd2.dwSize = sizeof(ddsd2); 01075 ddsd2.dwFlags = DDSD_CAPS; 01076 ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; 01077 hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL); 01078 if (FAILED(hResult)) { 01079 ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult); 01080 nContextError = GLDERR_MEM; 01081 goto return_with_error; 01082 } 01083 01084 // Cache Primary surface for subsequent GLRCs 01085 // Note this can only be applicable to subsequent windowed modes 01086 if (glb.bDirectDrawPersistant && !glb.bDirectDrawPrimary) { 01087 glb.lpPrimary4 = lpCtx->lpFront4; 01088 IDirectDrawSurface4_AddRef(glb.lpPrimary4); 01089 glb.bDirectDrawPrimary = TRUE; 01090 } 01091 01092 // Clipper object 01093 hResult = DirectDrawCreateClipper(0, &lpddClipper, NULL); 01094 if (FAILED(hResult)) { 01095 ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateClipper failed", hResult); 01096 goto return_with_error; 01097 } 01098 hResult = IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd); 01099 if (FAILED(hResult)) { 01100 RELEASE(lpddClipper); 01101 ddlogError(DDLOG_CRITICAL_OR_WARN, "SetHWnd failed", hResult); 01102 goto return_with_error; 01103 } 01104 hResult = IDirectDrawSurface4_SetClipper(lpCtx->lpFront4, lpddClipper); 01105 RELEASE(lpddClipper); // We have finished with it. 01106 if (FAILED(hResult)) { 01107 ddlogError(DDLOG_CRITICAL_OR_WARN, "SetClipper failed", hResult); 01108 goto return_with_error; 01109 } 01110 SkipPrimaryCreate: 01111 01112 if (bDoubleBuffer) { 01113 // Render target surface 01114 ZeroMemory(&ddsd2, sizeof(ddsd2)); 01115 ddsd2.dwSize = sizeof(ddsd2); 01116 ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; 01117 ddsd2.dwWidth = lpCtx->dwWidth; 01118 ddsd2.dwHeight = lpCtx->dwHeight; 01119 ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | 01120 DDSCAPS_OFFSCREENPLAIN | 01121 dwMemoryType; 01122 01123 // Reserve the entire desktop size for persistant buffers option 01124 if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) { 01125 ddsd2.dwWidth = ddsd2DisplayMode.dwWidth; 01126 ddsd2.dwHeight = ddsd2DisplayMode.dwHeight; 01127 } 01128 // Re-use original back buffer if persistant buffers exist 01129 if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpBack4) 01130 hResult = IDirectDrawSurface4_AddRef(lpCtx->lpBack4 = glb.lpBack4); 01131 else 01132 hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpBack4, NULL); 01133 if (FAILED(hResult)) { 01134 ddlogError(DDLOG_CRITICAL_OR_WARN, "Create Backbuffer failed", hResult); 01135 nContextError = GLDERR_MEM; 01136 goto return_with_error; 01137 } 01138 if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpBack4) 01139 IDirectDrawSurface4_AddRef(glb.lpBack4 = lpCtx->lpBack4); 01140 } else { 01141 lpCtx->lpBack4 = NULL; 01142 } 01143 } 01144 01145 // 01146 // Now create the Z-buffer 01147 // 01148 lpCtx->bStencil = FALSE; // Default to no stencil buffer 01149 if (bDepthBuffer && (lpCtx->lpPF->iZBufferPF != -1)) { 01150 // Get z-buffer dimensions from the render target 01151 // Setup the surface desc for the z-buffer. 01152 ZeroMemory(&ddsd2, sizeof(ddsd2)); 01153 ddsd2.dwSize = sizeof(ddsd2); 01154 ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; 01155 ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | dwMemoryType; 01156 ddsd2.dwWidth = lpCtx->dwWidth; 01157 ddsd2.dwHeight = lpCtx->dwHeight; 01158 memcpy(&ddsd2.ddpfPixelFormat, 01159 &glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF], 01160 sizeof(DDPIXELFORMAT) ); 01161 01162 // Reserve the entire desktop size for persistant buffers option 01163 if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) { 01164 ddsd2.dwWidth = ddsd2DisplayMode.dwWidth; 01165 ddsd2.dwHeight = ddsd2DisplayMode.dwHeight; 01166 } 01167 01168 // Create a z-buffer 01169 if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpDepth4) 01170 hResult = IDirectDrawSurface4_AddRef(lpCtx->lpDepth4 = glb.lpDepth4); 01171 else 01172 hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpDepth4, NULL); 01173 if (FAILED(hResult)) { 01174 ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (ZBuffer) failed", hResult); 01175 nContextError = GLDERR_MEM; 01176 goto return_with_error; 01177 } 01178 if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpDepth4) 01179 IDirectDrawSurface4_AddRef(glb.lpDepth4 = lpCtx->lpDepth4); 01180 else if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpDepth4 && glb.lpBack4) 01181 IDirectDrawSurface4_DeleteAttachedSurface(glb.lpBack4, 0, glb.lpDepth4); 01182 01183 // Attach Zbuffer to render target 01184 TRY(IDirectDrawSurface4_AddAttachedSurface( 01185 bDoubleBuffer ? lpCtx->lpBack4 : lpCtx->lpFront4, 01186 lpCtx->lpDepth4), 01187 "dglCreateContext: Attach Zbuffer"); 01188 if (glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwFlags & DDPF_STENCILBUFFER) { 01189 lpCtx->bStencil = TRUE; 01190 ddlogMessage(DDLOG_INFO, "Depth buffer has stencil\n"); 01191 } 01192 } 01193 01194 // Clear all back buffers and Z-buffers in case of memory recycling. 01195 ZeroMemory(&ddbltfx, sizeof(ddbltfx)); 01196 ddbltfx.dwSize = sizeof(ddbltfx); 01197 IDirectDrawSurface4_Blt(lpCtx->lpBack4, NULL, NULL, NULL, 01198 DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); 01199 if (lpCtx->lpDepth4) 01200 IDirectDrawSurface4_Blt(lpCtx->lpDepth4, NULL, NULL, NULL, 01201 DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); 01202 01203 // Now that we have a Z-buffer we can create the 3D device 01204 hResult = IDirect3D3_CreateDevice(lpCtx->lpD3D3, 01205 &glb.d3dGuid, 01206 bDoubleBuffer ? lpCtx->lpBack4 : lpCtx->lpFront4, 01207 &lpCtx->lpDev3, 01208 NULL); 01209 if (FAILED(hResult)) { 01210 ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D device", hResult); 01211 nContextError = GLDERR_D3D; 01212 goto return_with_error; 01213 } 01214 01215 // We must do this as soon as the device is created 01216 dglInitStateCaches(lpCtx); 01217 01218 // Obtain the D3D Device Description 01219 D3DHWDevDesc.dwSize = D3DHELDevDesc.dwSize = sizeof(D3DDEVICEDESC); 01220 TRY(IDirect3DDevice3_GetCaps(lpCtx->lpDev3, 01221 &D3DHWDevDesc, 01222 &D3DHELDevDesc), 01223 "dglCreateContext: GetCaps failed"); 01224 01225 // Choose the relevant description and cache it in the context. 01226 // We will use this description later for caps checking 01227 memcpy( &lpCtx->D3DDevDesc, 01228 glb.bHardware ? &D3DHWDevDesc : &D3DHELDevDesc, 01229 sizeof(D3DDEVICEDESC)); 01230 01231 // Now we can examine the texture formats 01232 if (!dglBuildTextureFormatList(lpCtx->lpDev3)) { 01233 ddlogMessage(DDLOG_CRITICAL_OR_WARN, "dglBuildTextureFormatList failed\n"); 01234 goto return_with_error; 01235 } 01236 01237 // Get the pixel format of the back buffer 01238 lpCtx->ddpfRender.dwSize = sizeof(lpCtx->ddpfRender); 01239 if (bDoubleBuffer) 01240 hResult = IDirectDrawSurface4_GetPixelFormat( 01241 lpCtx->lpBack4, 01242 &lpCtx->ddpfRender); 01243 else 01244 hResult = IDirectDrawSurface4_GetPixelFormat( 01245 lpCtx->lpFront4, 01246 &lpCtx->ddpfRender); 01247 01248 if (FAILED(hResult)) { 01249 ddlogError(DDLOG_CRITICAL_OR_WARN, "GetPixelFormat failed", hResult); 01250 goto return_with_error; 01251 } 01252 // Find a pixel packing function suitable for this surface 01253 pxClassifyPixelFormat(&lpCtx->ddpfRender, 01254 &lpCtx->fnPackFunc, 01255 &lpCtx->fnUnpackFunc, 01256 &lpCtx->fnPackSpanFunc); 01257 01258 // Viewport 01259 hResult = IDirect3D3_CreateViewport(lpCtx->lpD3D3, &lpCtx->lpViewport3, NULL); 01260 if (FAILED(hResult)) { 01261 ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateViewport failed", hResult); 01262 goto return_with_error; 01263 } 01264 01265 hResult = IDirect3DDevice3_AddViewport(lpCtx->lpDev3, lpCtx->lpViewport3); 01266 if (FAILED(hResult)) { 01267 ddlogError(DDLOG_CRITICAL_OR_WARN, "AddViewport failed", hResult); 01268 goto return_with_error; 01269 } 01270 01271 // Initialise the viewport 01272 // Note screen coordinates are used for viewport clipping since D3D 01273 // transform operations are not used in the GLD CAD driver. (DaveM) 01274 inv_aspect = (float)lpCtx->dwHeight/(float)lpCtx->dwWidth; 01275 01276 lpCtx->d3dViewport.dwSize = sizeof(lpCtx->d3dViewport); 01277 lpCtx->d3dViewport.dwX = 0; 01278 lpCtx->d3dViewport.dwY = 0; 01279 lpCtx->d3dViewport.dwWidth = lpCtx->dwWidth; 01280 lpCtx->d3dViewport.dwHeight = lpCtx->dwHeight; 01281 lpCtx->d3dViewport.dvClipX = 0; // -1.0f; 01282 lpCtx->d3dViewport.dvClipY = 0; // inv_aspect; 01283 lpCtx->d3dViewport.dvClipWidth = lpCtx->dwWidth; // 2.0f; 01284 lpCtx->d3dViewport.dvClipHeight = lpCtx->dwHeight; // 2.0f * inv_aspect; 01285 lpCtx->d3dViewport.dvMinZ = 0.0f; 01286 lpCtx->d3dViewport.dvMaxZ = 1.0f; 01287 TRY(IDirect3DViewport3_SetViewport2(lpCtx->lpViewport3, &lpCtx->d3dViewport), "dglCreateContext: SetViewport2"); 01288 01289 hResult = IDirect3DDevice3_SetCurrentViewport(lpCtx->lpDev3, lpCtx->lpViewport3); 01290 if (FAILED(hResult)) { 01291 ddlogError(DDLOG_CRITICAL_OR_WARN, "SetCurrentViewport failed", hResult); 01292 goto return_with_error; 01293 } 01294 01295 lpCtx->dwBPP = lpPFD->cColorBits; 01296 lpCtx->iZBufferPF = lpCtx->lpPF->iZBufferPF; 01297 01298 // Set last texture to NULL 01299 for (i=0; i<MAX_TEXTURE_UNITS; i++) { 01300 lpCtx->ColorOp[i] = D3DTOP_DISABLE; 01301 lpCtx->AlphaOp[i] = D3DTOP_DISABLE; 01302 lpCtx->tObj[i] = NULL; 01303 } 01304 01305 // Default to perspective correct texture mapping 01306 dglSetRenderState(lpCtx, D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE, "TexturePersp"); 01307 01308 // Set the default culling mode 01309 lpCtx->cullmode = D3DCULL_NONE; 01310 dglSetRenderState(lpCtx, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE, "CullMode"); 01311 01312 // Disable specular 01313 dglSetRenderState(lpCtx, D3DRENDERSTATE_SPECULARENABLE, FALSE, "SpecularEnable"); 01314 // Disable subpixel correction 01315 // dglSetRenderState(lpCtx, D3DRENDERSTATE_SUBPIXEL, FALSE, "SubpixelEnable"); 01316 // Disable dithering 01317 dglSetRenderState(lpCtx, D3DRENDERSTATE_DITHERENABLE, FALSE, "DitherEnable"); 01318 01319 // Initialise the primitive caches 01320 // lpCtx->dwNextLineVert = 0; 01321 // lpCtx->dwNextTriVert = 0; 01322 01323 // Init the global texture palette 01324 lpCtx->lpGlobalPalette = NULL; 01325 01326 // Init the HW/SW usage counters 01327 // lpCtx->dwHWUsageCount = lpCtx->dwSWUsageCount = 0L; 01328 01329 // 01330 // Create two D3D vertex buffers. 01331 // One will hold the pre-transformed data with the other one 01332 // being used to hold the post-transformed & clipped verts. 01333 // 01334 #if 0 // never used (DaveM) 01335 vbufdesc.dwSize = sizeof(D3DVERTEXBUFFERDESC); 01336 vbufdesc.dwCaps = D3DVBCAPS_WRITEONLY; 01337 if (glb.bHardware == FALSE) 01338 vbufdesc.dwCaps = D3DVBCAPS_SYSTEMMEMORY; 01339 vbufdesc.dwNumVertices = 32768; // For the time being 01340 01341 // Source vertex buffer 01342 vbufdesc.dwFVF = DGL_LVERTEX; 01343 hResult = IDirect3D3_CreateVertexBuffer(lpCtx->lpD3D3, &vbufdesc, &lpCtx->m_vbuf, 0, NULL); 01344 if (FAILED(hResult)) { 01345 ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateVertexBuffer(src) failed", hResult); 01346 goto return_with_error; 01347 } 01348 01349 // Destination vertex buffer 01350 vbufdesc.dwFVF = (glb.bMultitexture == FALSE) ? D3DFVF_TLVERTEX : (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX2); 01351 hResult = IDirect3D3_CreateVertexBuffer(lpCtx->lpD3D3, &vbufdesc, &lpCtx->m_pvbuf, 0, NULL); 01352 if(FAILED(hResult)) { 01353 ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateVertexBuffer(dst) failed", hResult); 01354 goto return_with_error; 01355 } 01356 #endif 01357 01358 #endif _USE_GLD3_WGL 01359 01360 // 01361 // Now create the Mesa context 01362 // 01363 01364 // Create the Mesa visual 01365 if (lpPFD->cDepthBits) 01366 dwDepthBits = 16; 01367 if (lpPFD->cStencilBits) 01368 dwStencilBits = 8; 01369 if (lpPFD->cAlphaBits) { 01370 dwAlphaBits = 8; 01371 bAlphaSW = GL_TRUE; 01372 } 01373 if (lpPFD->dwFlags & PFD_DOUBLEBUFFER) 01374 bDouble = GL_TRUE; 01375 // lpCtx->EmulateSingle = 01376 // (lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? FALSE : TRUE; 01377 01378 #ifdef _USE_GLD3_WGL 01379 lpCtx->glVis = _mesa_create_visual( 01380 GL_TRUE, // RGB mode 01381 bDouble, /* double buffer */ 01382 GL_FALSE, // stereo 01383 lpPFD->cRedBits, 01384 lpPFD->cGreenBits, 01385 lpPFD->cBlueBits, 01386 dwAlphaBits, 01387 0, // index bits 01388 dwDepthBits, 01389 dwStencilBits, 01390 lpPFD->cAccumRedBits, // accum bits 01391 lpPFD->cAccumGreenBits, // accum bits 01392 lpPFD->cAccumBlueBits, // accum bits 01393 lpPFD->cAccumAlphaBits, // accum alpha bits 01394 1 // num samples 01395 ); 01396 #else // _USE_GLD3_WGL 01397 lpCtx->glVis = (*mesaFuncs.gl_create_visual)( 01398 GL_TRUE, // RGB mode 01399 bAlphaSW, // Is an alpha buffer required? 01400 bDouble, // Is an double-buffering required? 01401 GL_FALSE, // stereo 01402 dwDepthBits, // depth_size 01403 dwStencilBits, // stencil_size 01404 lpPFD->cAccumBits, // accum_size 01405 0, // colour-index bits 01406 lpPFD->cRedBits, // Red bit count 01407 lpPFD->cGreenBits, // Green bit count 01408 lpPFD->cBlueBits, // Blue bit count 01409 dwAlphaBits // Alpha bit count 01410 ); 01411 #endif // _USE_GLD3_WGL 01412 01413 if (lpCtx->glVis == NULL) { 01414 ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_visual failed\n"); 01415 goto return_with_error; 01416 } 01417 01418 #ifdef _USE_GLD3_WGL 01419 lpCtx->glCtx = _mesa_create_context(lpCtx->glVis, NULL, (void *)lpCtx, GL_TRUE); 01420 #else 01421 // Create the Mesa context 01422 lpCtx->glCtx = (*mesaFuncs.gl_create_context)( 01423 lpCtx->glVis, // Mesa visual 01424 NULL, // share list context 01425 (void *)lpCtx, // Pointer to our driver context 01426 GL_TRUE // Direct context flag 01427 ); 01428 #endif // _USE_GLD3_WGL 01429 01430 if (lpCtx->glCtx == NULL) { 01431 ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_context failed\n"); 01432 goto return_with_error; 01433 } 01434 01435 // Create the Mesa framebuffer 01436 #ifdef _USE_GLD3_WGL 01437 lpCtx->glBuffer = _mesa_create_framebuffer( 01438 lpCtx->glVis, 01439 lpCtx->glVis->depthBits > 0, 01440 lpCtx->glVis->stencilBits > 0, 01441 lpCtx->glVis->accumRedBits > 0, 01442 GL_FALSE //swalpha 01443 ); 01444 #else 01445 lpCtx->glBuffer = (*mesaFuncs.gl_create_framebuffer)(lpCtx->glVis); 01446 #endif // _USE_GLD3_WGL 01447 01448 if (lpCtx->glBuffer == NULL) { 01449 ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_framebuffer failed\n"); 01450 goto return_with_error; 01451 } 01452 01453 #ifdef _USE_GLD3_WGL 01454 // Init Mesa internals 01455 _swrast_CreateContext( lpCtx->glCtx ); 01456 _vbo_CreateContext( lpCtx->glCtx ); 01457 _tnl_CreateContext( lpCtx->glCtx ); 01458 _swsetup_CreateContext( lpCtx->glCtx ); 01459 01460 _gldDriver.InitialiseMesa(lpCtx); 01461 01462 lpCtx->glCtx->imports.warning = _gld_mesa_warning; 01463 lpCtx->glCtx->imports.fatal = _gld_mesa_fatal; 01464 01465 #else 01466 // Tell Mesa how many texture stages we have 01467 glb.wMaxSimultaneousTextures = lpCtx->D3DDevDesc.wMaxSimultaneousTextures; 01468 // Only use as many Units as the spec requires 01469 if (glb.wMaxSimultaneousTextures > MAX_TEXTURE_UNITS) 01470 glb.wMaxSimultaneousTextures = MAX_TEXTURE_UNITS; 01471 lpCtx->glCtx->Const.MaxTextureUnits = glb.wMaxSimultaneousTextures; 01472 ddlogPrintf(DDLOG_INFO, "Texture stages : %d", glb.wMaxSimultaneousTextures); 01473 01474 // Set the max texture size. 01475 // NOTE: clamped to a max of 1024 for extra performance! 01476 lpCtx->dwMaxTextureSize = (lpCtx->D3DDevDesc.dwMaxTextureWidth <= 1024) ? lpCtx->D3DDevDesc.dwMaxTextureWidth : 1024; 01477 01478 // Texture resize takes place elsewhere. KH 01479 // NOTE: This was added to workaround an issue with the Intel app. 01480 #if 0 01481 lpCtx->glCtx->Const.MaxTextureSize = lpCtx->dwMaxTextureSize; 01482 #else 01483 lpCtx->glCtx->Const.MaxTextureSize = 1024; 01484 #endif 01485 01486 // Setup the Display Driver pointers 01487 dglSetupDDPointers(lpCtx->glCtx); 01488 01489 // Initialise all the Direct3D renderstates 01490 dglInitStateD3D(lpCtx->glCtx); 01491 01492 #if 0 01493 // Signal a reload of texture state on next glBegin 01494 lpCtx->m_texHandleValid = FALSE; 01495 lpCtx->m_mtex = FALSE; 01496 lpCtx->m_texturing = FALSE; 01497 #else 01498 // Set default texture unit state 01499 // dglSetTexture(lpCtx, 0, NULL); 01500 // dglSetTexture(lpCtx, 1, NULL); 01501 #endif 01502 01503 // 01504 // Set the global texture palette to default values. 01505 // 01506 01507 // Clear the entire palette 01508 ZeroMemory(ppe, sizeof(PALETTEENTRY) * 256); 01509 01510 // Fill the palette with a default colour. 01511 // A garish colour is used to catch bugs. Here Magenta is used. 01512 for (i=0; i < 256; i++) { 01513 ppe[i].peRed = 255; 01514 ppe[i].peGreen = 0; 01515 ppe[i].peBlue = 255; 01516 } 01517 01518 RELEASE(lpCtx->lpGlobalPalette); 01519 01520 if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpGlobalPalette) 01521 hResult = IDirectDrawPalette_AddRef(lpCtx->lpGlobalPalette = glb.lpGlobalPalette); 01522 else 01523 hResult = IDirectDraw4_CreatePalette( 01524 lpCtx->lpDD4, 01525 DDPCAPS_INITIALIZE | DDPCAPS_8BIT | DDPCAPS_ALLOW256, 01526 ppe, 01527 &(lpCtx->lpGlobalPalette), 01528 NULL); 01529 if (FAILED(hResult)) { 01530 ddlogError(DDLOG_ERROR, "Default CreatePalette failed\n", hResult); 01531 lpCtx->lpGlobalPalette = NULL; 01532 goto return_with_error; 01533 } 01534 if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpGlobalPalette) 01535 IDirectDrawPalette_AddRef(glb.lpGlobalPalette = lpCtx->lpGlobalPalette); 01536 01537 #endif // _USE_GLD3_WGL 01538 01539 // ** If we have made it to here then we can enable rendering ** 01540 lpCtx->bCanRender = TRUE; 01541 01542 // ddlogMessage(DDLOG_SYSTEM, "dglCreateContextBuffers succeded\n"); 01543 01544 #ifdef GLD_THREADS 01545 // Release serialized access 01546 if (glb.bMultiThreaded) 01547 LeaveCriticalSection(&CriticalSection); 01548 #endif 01549 01550 return TRUE; 01551 01552 return_with_error: 01553 // Clean up before returning. 01554 // This is critical for secondary devices. 01555 01556 lpCtx->bCanRender = FALSE; 01557 01558 #ifdef _USE_GLD3_WGL 01559 // Destroy the Mesa context 01560 if (lpCtx->glBuffer) 01561 _mesa_destroy_framebuffer(lpCtx->glBuffer); 01562 if (lpCtx->glCtx) 01563 _mesa_destroy_context(lpCtx->glCtx); 01564 if (lpCtx->glVis) 01565 _mesa_destroy_visual(lpCtx->glVis); 01566 01567 // Destroy driver data 01568 _gldDriver.DestroyDrawable(lpCtx); 01569 #else 01570 // Destroy the Mesa context 01571 if (lpCtx->glBuffer) 01572 (*mesaFuncs.gl_destroy_framebuffer)(lpCtx->glBuffer); 01573 if (lpCtx->glCtx) 01574 (*mesaFuncs.gl_destroy_context)(lpCtx->glCtx); 01575 if (lpCtx->glVis) 01576 (*mesaFuncs.gl_destroy_visual)(lpCtx->glVis); 01577 01578 RELEASE(lpCtx->m_pvbuf); // Release D3D vertex buffer 01579 RELEASE(lpCtx->m_vbuf); // Release D3D vertex buffer 01580 01581 if (lpCtx->lpViewport3) { 01582 if (lpCtx->lpDev3) IDirect3DDevice3_DeleteViewport(lpCtx->lpDev3, lpCtx->lpViewport3); 01583 RELEASE(lpCtx->lpViewport3); 01584 lpCtx->lpViewport3 = NULL; 01585 } 01586 01587 RELEASE(lpCtx->lpDev3); 01588 if (lpCtx->lpDepth4) { 01589 if (lpCtx->lpBack4) 01590 IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpBack4, 0L, lpCtx->lpDepth4); 01591 else 01592 IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpFront4, 0L, lpCtx->lpDepth4); 01593 RELEASE(lpCtx->lpDepth4); 01594 lpCtx->lpDepth4 = NULL; 01595 } 01596 RELEASE(lpCtx->lpBack4); 01597 RELEASE(lpCtx->lpFront4); 01598 else 01599 if (lpCtx->bFullscreen) { 01600 IDirectDraw4_RestoreDisplayMode(lpCtx->lpDD4); 01601 IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, NULL, DDSCL_NORMAL); 01602 } 01603 RELEASE(lpCtx->lpD3D3); 01604 RELEASE(lpCtx->lpDD4); 01605 RELEASE(lpCtx->lpDD1); 01606 #endif // _USE_GLD3_WGL 01607 01608 lpCtx->bAllocated = FALSE; 01609 01610 #ifdef GLD_THREADS 01611 // Release serialized access 01612 if (glb.bMultiThreaded) 01613 LeaveCriticalSection(&CriticalSection); 01614 #endif 01615 01616 return FALSE; 01617 01618 #undef DDLOG_CRITICAL_OR_WARN 01619 } 01620 01621 // *********************************************************************** 01622 01623 HGLRC dglCreateContext( 01624 HDC a, 01625 const DGL_pixelFormat *lpPF) 01626 { 01627 int i; 01628 HGLRC hGLRC; 01629 DGL_ctx* lpCtx; 01630 static BOOL bWarnOnce = TRUE; 01631 DWORD dwThreadId = GetCurrentThreadId(); 01632 char szMsg[256]; 01633 HWND hWnd; 01634 LONG lpfnWndProc; 01635 01636 // Validate license 01637 if (!dglValidate()) 01638 return NULL; 01639 01640 // Is context state ready ? 01641 if (!bContextReady) 01642 return NULL; 01643 01644 ddlogPrintf(DDLOG_SYSTEM, "dglCreateContext for HDC=%X, ThreadId=%X", a, dwThreadId); 01645 01646 // Find next free context. 01647 // Also ensure that only one Fullscreen context is created at any one time. 01648 hGLRC = 0; // Default to Not Found 01649 for (i=0; i<DGL_MAX_CONTEXTS; i++) { 01650 if (ctxlist[i].bAllocated) { 01651 if (/*glb.bFullscreen && */ctxlist[i].bFullscreen) 01652 break; 01653 } else { 01654 hGLRC = (HGLRC)(i+1); 01655 break; 01656 } 01657 } 01658 01659 // Bail if no GLRC was found 01660 if (!hGLRC) 01661 return NULL; 01662 01663 // Set the context pointer 01664 lpCtx = dglGetContextAddress(hGLRC); 01665 // Make sure that context is zeroed before we do anything. 01666 // MFC and C++ apps call wglCreateContext() and wglDeleteContext() multiple times, 01667 // even though only one context is ever used by the app, so keep it clean. (DaveM) 01668 ZeroMemory(lpCtx, sizeof(DGL_ctx)); 01669 lpCtx->bAllocated = TRUE; 01670 // Flag that buffers need creating on next wglMakeCurrent call. 01671 lpCtx->bHasBeenCurrent = FALSE; 01672 lpCtx->lpPF = (DGL_pixelFormat *)lpPF; // cache pixel format 01673 lpCtx->bCanRender = FALSE; 01674 01675 // Create all the internal resources here, not in dglMakeCurrent(). 01676 // We do a re-size check in dglMakeCurrent in case of re-allocations. (DaveM) 01677 // We now try context allocations twice, first with video memory, 01678 // then again with system memory. This is similar to technique 01679 // used for dglWglResizeBuffers(). (DaveM) 01680 if (lpCtx->bHasBeenCurrent == FALSE) { 01681 if (!dglCreateContextBuffers(a, lpCtx, FALSE)) { 01682 if (glb.bMessageBoxWarnings && bWarnOnce && dwLogging) { 01683 bWarnOnce = FALSE; 01684 switch (nContextError) { 01685 case GLDERR_DDRAW: strcpy(szMsg, szDDrawWarning); break; 01686 case GLDERR_D3D: strcpy(szMsg, szD3DWarning); break; 01687 case GLDERR_MEM: strcpy(szMsg, szResourceWarning); break; 01688 case GLDERR_BPP: strcpy(szMsg, szBPPWarning); break; 01689 default: strcpy(szMsg, ""); 01690 } 01691 if (strlen(szMsg)) 01692 MessageBox(NULL, szMsg, "GLDirect", MB_OK | MB_ICONWARNING); 01693 } 01694 // Only need to try again if memory error 01695 if (nContextError == GLDERR_MEM) { 01696 ddlogPrintf(DDLOG_WARN, "dglCreateContext failed 1st time with video memory"); 01697 } 01698 else { 01699 ddlogPrintf(DDLOG_ERROR, "dglCreateContext failed"); 01700 return NULL; 01701 } 01702 } 01703 } 01704 01705 // Now that we have a hWnd, we can intercept the WindowProc. 01706 hWnd = lpCtx->hWnd; 01707 if (hWnd) { 01708 // Only hook individual window handler once if not hooked before. 01709 lpfnWndProc = GetWindowLong(hWnd, GWL_WNDPROC); 01710 if (lpfnWndProc != (LONG)dglWndProc) { 01711 lpCtx->lpfnWndProc = lpfnWndProc; 01712 SetWindowLong(hWnd, GWL_WNDPROC, (LONG)dglWndProc); 01713 } 01714 // Find the parent window of the app too. 01715 if (glb.hWndActive == NULL) { 01716 while (hWnd != NULL) { 01717 glb.hWndActive = hWnd; 01718 hWnd = GetParent(hWnd); 01719 } 01720 // Hook the parent window too. 01721 lpfnWndProc = GetWindowLong(glb.hWndActive, GWL_WNDPROC); 01722 if (glb.hWndActive == lpCtx->hWnd) 01723 glb.lpfnWndProc = lpCtx->lpfnWndProc; 01724 else if (lpfnWndProc != (LONG)dglWndProc) 01725 glb.lpfnWndProc = lpfnWndProc; 01726 if (glb.lpfnWndProc) 01727 SetWindowLong(glb.hWndActive, GWL_WNDPROC, (LONG)dglWndProc); 01728 } 01729 } 01730 01731 ddlogPrintf(DDLOG_SYSTEM, "dglCreateContext succeeded for HGLRC=%d", (int)hGLRC); 01732 01733 return hGLRC; 01734 } 01735 01736 // *********************************************************************** 01737 // Make a DirectGL context current 01738 // Used by wgl functions and dgl functions 01739 BOOL dglMakeCurrent( 01740 HDC a, 01741 HGLRC b) 01742 { 01743 int context; 01744 DGL_ctx* lpCtx; 01745 HWND hWnd; 01746 BOOL bNeedResize = FALSE; 01747 BOOL bWindowChanged, bContextChanged; 01748 LPDIRECTDRAWCLIPPER lpddClipper; 01749 DWORD dwThreadId = GetCurrentThreadId(); 01750 LONG lpfnWndProc; 01751 01752 // Validate license 01753 if (!dglValidate()) 01754 return FALSE; 01755 01756 // Is context state ready ? 01757 if (!bContextReady) 01758 return FALSE; 01759 01760 context = (int)b; // This is as a result of STRICT! 01761 ddlogPrintf(DDLOG_SYSTEM, "dglMakeCurrent: HDC=%X, HGLRC=%d, ThreadId=%X", a, context, dwThreadId); 01762 01763 // If the HGLRC is NULL then make no context current; 01764 // Ditto if the HDC is NULL either. (DaveM) 01765 if (context == 0 || a == 0) { 01766 // Corresponding Mesa operation 01767 #ifdef _USE_GLD3_WGL 01768 _mesa_make_current(NULL, NULL); 01769 #else 01770 (*mesaFuncs.gl_make_current)(NULL, NULL); 01771 #endif 01772 dglSetCurrentContext(0); 01773 return TRUE; 01774 } 01775 01776 // Make sure the HGLRC is in range 01777 if ((context > DGL_MAX_CONTEXTS) || (context < 0)) { 01778 ddlogMessage(DDLOG_ERROR, "dglMakeCurrent: HGLRC out of range\n"); 01779 return FALSE; 01780 } 01781 01782 // Find address of context and make sure that it has been allocated 01783 lpCtx = dglGetContextAddress(b); 01784 if (!lpCtx->bAllocated) { 01785 ddlogMessage(DDLOG_ERROR, "dglMakeCurrent: Context not allocated\n"); 01786 // return FALSE; 01787 return TRUE; // HACK: Shuts up "WebLab Viewer Pro". KeithH 01788 } 01789 01790 #ifdef GLD_THREADS 01791 // Serialize access to DirectDraw or DDS operations 01792 if (glb.bMultiThreaded) 01793 EnterCriticalSection(&CriticalSection); 01794 #endif 01795 01796 // Check if window has changed 01797 hWnd = (a != lpCtx->hDC) ? WindowFromDC(a) : lpCtx->hWnd; 01798 bWindowChanged = (hWnd != lpCtx->hWnd) ? TRUE : FALSE; 01799 bContextChanged = (b != dglGetCurrentContext()) ? TRUE : FALSE; 01800 01801 // If the window has changed, make sure the clipper is updated. (DaveM) 01802 if (glb.bDirectDrawPersistant && !lpCtx->bFullscreen && (bWindowChanged || bContextChanged)) { 01803 lpCtx->hWnd = hWnd; 01804 #ifndef _USE_GLD3_WGL 01805 IDirectDrawSurface4_GetClipper(lpCtx->lpFront4, &lpddClipper); 01806 IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd); 01807 IDirectDrawClipper_Release(lpddClipper); 01808 #endif // _USE_GLD3_WGL 01809 } 01810 01811 // Make sure hDC and hWnd is current. (DaveM) 01812 // Obtain the dimensions of the rendering window 01813 lpCtx->hDC = a; // Cache DC 01814 lpCtx->hWnd = hWnd; 01815 hWndLastActive = hWnd; 01816 01817 // Check for non-window DC = memory DC ? 01818 if (hWnd == NULL) { 01819 if (GetClipBox(a, &lpCtx->rcScreenRect) == ERROR) { 01820 ddlogMessage(DDLOG_WARN, "GetClipBox failed in dglMakeCurrent\n"); 01821 SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0); 01822 } 01823 } 01824 else if (!GetClientRect(lpCtx->hWnd, &lpCtx->rcScreenRect)) { 01825 ddlogMessage(DDLOG_WARN, "GetClientRect failed in dglMakeCurrent\n"); 01826 SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0); 01827 } 01828 // Check if buffers need to be re-sized; 01829 // If so, wait until Mesa GL stuff is setup before re-sizing; 01830 if (lpCtx->dwWidth != lpCtx->rcScreenRect.right - lpCtx->rcScreenRect.left || 01831 lpCtx->dwHeight != lpCtx->rcScreenRect.bottom - lpCtx->rcScreenRect.top) 01832 bNeedResize = TRUE; 01833 01834 // Now we can update our globals 01835 dglSetCurrentContext(b); 01836 01837 // Corresponding Mesa operation 01838 #ifdef _USE_GLD3_WGL 01839 _mesa_make_current(lpCtx->glCtx, lpCtx->glBuffer); 01840 lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL); 01841 if (bNeedResize) { 01842 // Resize buffers (Note Mesa GL needs to be setup beforehand); 01843 // Resize Mesa internal buffer too via glViewport() command, 01844 // which subsequently calls dglWglResizeBuffers() too. 01845 lpCtx->glCtx->Driver.Viewport(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight); 01846 lpCtx->bHasBeenCurrent = TRUE; 01847 } 01848 #else 01849 (*mesaFuncs.gl_make_current)(lpCtx->glCtx, lpCtx->glBuffer); 01850 01851 dglSetupDDPointers(lpCtx->glCtx); 01852 01853 // Insure DirectDraw surfaces fit current window DC 01854 if (bNeedResize) { 01855 // Resize buffers (Note Mesa GL needs to be setup beforehand); 01856 // Resize Mesa internal buffer too via glViewport() command, 01857 // which subsequently calls dglWglResizeBuffers() too. 01858 (*mesaFuncs.gl_Viewport)(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight); 01859 lpCtx->bHasBeenCurrent = TRUE; 01860 } 01861 #endif // _USE_GLD3_WGL 01862 ddlogPrintf(DDLOG_SYSTEM, "dglMakeCurrent: width = %d, height = %d", lpCtx->dwWidth, lpCtx->dwHeight); 01863 01864 // We have to clear D3D back buffer and render state if emulated front buffering 01865 // for different window (but not context) like in Solid Edge. 01866 if (glb.bDirectDrawPersistant && glb.bPersistantBuffers 01867 && (bWindowChanged /* || bContextChanged */) && lpCtx->EmulateSingle) { 01868 #ifdef _USE_GLD3_WGL 01869 // IDirect3DDevice8_EndScene(lpCtx->pDev); 01870 // lpCtx->bSceneStarted = FALSE; 01871 lpCtx->glCtx->Driver.Clear(lpCtx->glCtx, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, 01872 GL_TRUE, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight); 01873 #else 01874 IDirect3DDevice3_EndScene(lpCtx->lpDev3); 01875 lpCtx->bSceneStarted = FALSE; 01876 dglClearD3D(lpCtx->glCtx, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, 01877 GL_TRUE, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight); 01878 #endif // _USE_GLD3_WGL 01879 } 01880 01881 // The first time we call MakeCurrent we set the initial viewport size 01882 if (lpCtx->bHasBeenCurrent == FALSE) 01883 #ifdef _USE_GLD3_WGL 01884 lpCtx->glCtx->Driver.Viewport(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight); 01885 #else 01886 (*mesaFuncs.gl_Viewport)(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight); 01887 #endif // _USE_GLD3_WGL 01888 lpCtx->bHasBeenCurrent = TRUE; 01889 01890 #ifdef GLD_THREADS 01891 // Release serialized access 01892 if (glb.bMultiThreaded) 01893 LeaveCriticalSection(&CriticalSection); 01894 #endif 01895 01896 return TRUE; 01897 } 01898 01899 // *********************************************************************** 01900 01901 BOOL dglDeleteContext( 01902 HGLRC a) 01903 { 01904 DGL_ctx* lpCtx; 01905 DWORD dwThreadId = GetCurrentThreadId(); 01906 char argstr[256]; 01907 01908 #if 0 // We have enough trouble throwing exceptions as it is... (DaveM) 01909 // Validate license 01910 if (!dglValidate()) 01911 return FALSE; 01912 #endif 01913 01914 // Is context state ready ? 01915 if (!bContextReady) 01916 return FALSE; 01917 01918 ddlogPrintf(DDLOG_SYSTEM, "dglDeleteContext: Deleting context HGLRC=%d, ThreadId=%X", (int)a, dwThreadId); 01919 01920 // Make sure the HGLRC is in range 01921 if (((int) a> DGL_MAX_CONTEXTS) || ((int)a < 0)) { 01922 ddlogMessage(DDLOG_ERROR, "dglDeleteCurrent: HGLRC out of range\n"); 01923 return FALSE; 01924 } 01925 01926 // Make sure context is valid 01927 lpCtx = dglGetContextAddress(a); 01928 if (!lpCtx->bAllocated) { 01929 ddlogPrintf(DDLOG_WARN, "Tried to delete unallocated context HGLRC=%d", (int)a); 01930 // return FALSE; 01931 return TRUE; // HACK: Shuts up "WebLab Viewer Pro". KeithH 01932 } 01933 01934 // Make sure context is de-activated 01935 if (a == dglGetCurrentContext()) { 01936 ddlogPrintf(DDLOG_WARN, "dglDeleteContext: context HGLRC=%d still active", (int)a); 01937 dglMakeCurrent(NULL, NULL); 01938 } 01939 01940 #ifdef GLD_THREADS 01941 // Serialize access to DirectDraw or DDS operations 01942 if (glb.bMultiThreaded) 01943 EnterCriticalSection(&CriticalSection); 01944 #endif 01945 01946 // We are about to destroy all Direct3D objects. 01947 // Therefore we must disable rendering 01948 lpCtx->bCanRender = FALSE; 01949 01950 // This exception handler was installed to catch some 01951 // particularly nasty apps. Console apps that call exit() 01952 // fall into this catagory (i.e. Win32 Glut). 01953 01954 // VC cannot successfully implement multiple exception handlers 01955 // if more than one exception occurs. Therefore reverting back to 01956 // single exception handler as Keith originally had it. (DaveM) 01957 01958 #define WARN_MESSAGE(p) strcpy(argstr, (#p)); 01959 #define SAFE_RELEASE(p) WARN_MESSAGE(p); RELEASE(p); 01960 01961 __try { 01962 #ifdef _USE_GLD3_WGL 01963 WARN_MESSAGE(gl_destroy_framebuffer); 01964 if (lpCtx->glBuffer) 01965 _mesa_destroy_framebuffer(lpCtx->glBuffer); 01966 WARN_MESSAGE(gl_destroy_context); 01967 if (lpCtx->glCtx) 01968 _mesa_destroy_context(lpCtx->glCtx); 01969 WARN_MESSAGE(gl_destroy_visual); 01970 if (lpCtx->glVis) 01971 _mesa_destroy_visual(lpCtx->glVis); 01972 01973 _gldDriver.DestroyDrawable(lpCtx); 01974 #else 01975 // Destroy the Mesa context 01976 WARN_MESSAGE(gl_destroy_framebuffer); 01977 if (lpCtx->glBuffer) 01978 (*mesaFuncs.gl_destroy_framebuffer)(lpCtx->glBuffer); 01979 WARN_MESSAGE(gl_destroy_context); 01980 if (lpCtx->glCtx) 01981 (*mesaFuncs.gl_destroy_context)(lpCtx->glCtx); 01982 WARN_MESSAGE(gl_destroy_visual); 01983 if (lpCtx->glVis) 01984 (*mesaFuncs.gl_destroy_visual)(lpCtx->glVis); 01985 01986 SAFE_RELEASE(lpCtx->m_pvbuf); // release D3D vertex buffer 01987 SAFE_RELEASE(lpCtx->m_vbuf); // release D3D vertex buffer 01988 01989 // Delete the global palette 01990 SAFE_RELEASE(lpCtx->lpGlobalPalette); 01991 01992 // Clean up. 01993 if (lpCtx->lpViewport3) { 01994 if (lpCtx->lpDev3) IDirect3DDevice3_DeleteViewport(lpCtx->lpDev3, lpCtx->lpViewport3); 01995 SAFE_RELEASE(lpCtx->lpViewport3); 01996 lpCtx->lpViewport3 = NULL; 01997 } 01998 01999 SAFE_RELEASE(lpCtx->lpDev3); 02000 if (lpCtx->lpDepth4) { 02001 if (lpCtx->lpBack4) 02002 IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpBack4, 0L, lpCtx->lpDepth4); 02003 else 02004 IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpFront4, 0L, lpCtx->lpDepth4); 02005 SAFE_RELEASE(lpCtx->lpDepth4); 02006 lpCtx->lpDepth4 = NULL; 02007 } 02008 SAFE_RELEASE(lpCtx->lpBack4); 02009 SAFE_RELEASE(lpCtx->lpFront4); 02010 if (lpCtx->bFullscreen) { 02011 IDirectDraw4_RestoreDisplayMode(lpCtx->lpDD4); 02012 IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, NULL, DDSCL_NORMAL); 02013 } 02014 SAFE_RELEASE(lpCtx->lpD3D3); 02015 SAFE_RELEASE(lpCtx->lpDD4); 02016 SAFE_RELEASE(lpCtx->lpDD1); 02017 #endif // _ULSE_GLD3_WGL 02018 02019 } 02020 __except(EXCEPTION_EXECUTE_HANDLER) { 02021 ddlogPrintf(DDLOG_WARN, "Exception raised in dglDeleteContext: %s", argstr); 02022 } 02023 02024 // Restore the window message handler because this context may be used 02025 // again by another window with a *different* message handler. (DaveM) 02026 if (lpCtx->lpfnWndProc) { 02027 SetWindowLong(lpCtx->hWnd, GWL_WNDPROC, (LONG)lpCtx->lpfnWndProc); 02028 lpCtx->lpfnWndProc = (LONG)NULL; 02029 } 02030 02031 lpCtx->bAllocated = FALSE; // This context is now free for use 02032 02033 #ifdef GLD_THREADS 02034 // Release serialized access 02035 if (glb.bMultiThreaded) 02036 LeaveCriticalSection(&CriticalSection); 02037 #endif 02038 02039 return TRUE; 02040 } 02041 02042 // *********************************************************************** 02043 02044 BOOL dglSwapBuffers( 02045 HDC hDC) 02046 { 02047 RECT rSrcRect; // Source rectangle 02048 RECT rDstRect; // Destination rectangle 02049 POINT pt; 02050 HRESULT hResult; 02051 02052 DDBLTFX bltFX; 02053 DWORD dwBlitFlags; 02054 DDBLTFX *lpBltFX; 02055 02056 // DWORD dwThreadId = GetCurrentThreadId(); 02057 HGLRC hGLRC = dglGetCurrentContext(); 02058 DGL_ctx *lpCtx = dglGetContextAddress(hGLRC); 02059 HWND hWnd; 02060 02061 HDC hDCAux; // for memory DC 02062 int x,y,w,h; // for memory DC BitBlt 02063 02064 #if 0 // Perhaps not a good idea. Called too often. KH 02065 // Validate license 02066 if (!dglValidate()) 02067 return FALSE; 02068 #endif 02069 02070 if (!lpCtx) { 02071 return TRUE; //FALSE; // No current context 02072 } 02073 02074 if (!lpCtx->bCanRender) { 02075 // Don't return false else some apps will bail. 02076 return TRUE; 02077 } 02078 02079 hWnd = lpCtx->hWnd; 02080 if (hDC != lpCtx->hDC) { 02081 ddlogPrintf(DDLOG_WARN, "dglSwapBuffers: HDC=%X does not match HDC=%X for HGLRC=%d", hDC, lpCtx->hDC, hGLRC); 02082 hWnd = WindowFromDC(hDC); 02083 } 02084 02085 #ifndef _USE_GLD3_WGL 02086 // Ensure that the surfaces exist before we tell 02087 // the device to render to them. 02088 IDirectDraw4_RestoreAllSurfaces(lpCtx->lpDD4); 02089 02090 // Make sure that the vertex caches have been emptied 02091 // dglStateChange(lpCtx); 02092 02093 // Some OpenGL programs don't issue a glFinish - check for it here. 02094 if (lpCtx->bSceneStarted) { 02095 IDirect3DDevice3_EndScene(lpCtx->lpDev3); 02096 lpCtx->bSceneStarted = FALSE; 02097 } 02098 #endif 02099 02100 #if 0 02101 // If the calling app is not active then we don't need to Blit/Flip. 02102 // We can therefore simply return TRUE. 02103 if (!glb.bAppActive) 02104 return TRUE; 02105 // Addendum: This is WRONG! We should bail if the app is *minimized*, 02106 // not merely if the app is just plain 'not active'. 02107 // KeithH, 27/May/2000. 02108 #endif 02109 02110 // Check for non-window DC = memory DC ? 02111 if (hWnd == NULL) { 02112 if (GetClipBox(hDC, &rSrcRect) == ERROR) 02113 return TRUE; 02114 // Use GDI BitBlt instead from compatible DirectDraw DC 02115 x = rSrcRect.left; 02116 y = rSrcRect.top; 02117 w = rSrcRect.right - rSrcRect.left; 02118 h = rSrcRect.bottom - rSrcRect.top; 02119 02120 // Ack. DX8 does not have a GetDC() function... 02121 // TODO: Defer to DX7 or DX9 drivers... (DaveM) 02122 return TRUE; 02123 } 02124 02125 // Bail if window client region is not drawable, like in Solid Edge 02126 if (!IsWindow(hWnd) /* || !IsWindowVisible(hWnd) */ || !GetClientRect(hWnd, &rSrcRect)) 02127 return TRUE; 02128 02129 #ifdef GLD_THREADS 02130 // Serialize access to DirectDraw or DDS operations 02131 if (glb.bMultiThreaded) 02132 EnterCriticalSection(&CriticalSection); 02133 #endif 02134 02135 #ifdef _USE_GLD3_WGL 02136 // Notify Mesa of impending swap, so Mesa can flush internal buffers. 02137 _mesa_notifySwapBuffers(lpCtx->glCtx); 02138 // Now perform driver buffer swap 02139 _gldDriver.SwapBuffers(lpCtx, hDC, hWnd); 02140 #else 02141 if (lpCtx->bFullscreen) { 02142 // Sync with retrace if required 02143 if (glb.bWaitForRetrace) { 02144 IDirectDraw4_WaitForVerticalBlank( 02145 lpCtx->lpDD4, 02146 DDWAITVB_BLOCKBEGIN, 02147 0); 02148 } 02149 02150 // Perform the fullscreen flip 02151 TRY(IDirectDrawSurface4_Flip( 02152 lpCtx->lpFront4, 02153 NULL, 02154 DDFLIP_WAIT), 02155 "dglSwapBuffers: Flip"); 02156 } else { 02157 // Calculate current window position and size 02158 pt.x = pt.y = 0; 02159 ClientToScreen(hWnd, &pt); 02160 GetClientRect(hWnd, &rDstRect); 02161 if (rDstRect.right > lpCtx->dwModeWidth) 02162 rDstRect.right = lpCtx->dwModeWidth; 02163 if (rDstRect.bottom > lpCtx->dwModeHeight) 02164 rDstRect.bottom = lpCtx->dwModeHeight; 02165 OffsetRect(&rDstRect, pt.x, pt.y); 02166 rSrcRect.left = rSrcRect.top = 0; 02167 rSrcRect.right = lpCtx->dwWidth; 02168 rSrcRect.bottom = lpCtx->dwHeight; 02169 if (rSrcRect.right > lpCtx->dwModeWidth) 02170 rSrcRect.right = lpCtx->dwModeWidth; 02171 if (rSrcRect.bottom > lpCtx->dwModeHeight) 02172 rSrcRect.bottom = lpCtx->dwModeHeight; 02173 02174 if (glb.bWaitForRetrace) { 02175 // Sync the blit to the vertical retrace 02176 ZeroMemory(&bltFX, sizeof(bltFX)); 02177 bltFX.dwSize = sizeof(bltFX); 02178 bltFX.dwDDFX = DDBLTFX_NOTEARING; 02179 dwBlitFlags = DDBLT_WAIT | DDBLT_DDFX; 02180 lpBltFX = &bltFX; 02181 } else { 02182 dwBlitFlags = DDBLT_WAIT; 02183 lpBltFX = NULL; 02184 } 02185 02186 // Perform the actual blit 02187 TRY(IDirectDrawSurface4_Blt( 02188 lpCtx->lpFront4, 02189 &rDstRect, 02190 lpCtx->lpBack4, // Blit source 02191 &rSrcRect, 02192 dwBlitFlags, 02193 lpBltFX), 02194 "dglSwapBuffers: Blt"); 02195 } 02196 #endif // _USE_GLD3_WGL 02197 02198 #ifdef GLD_THREADS 02199 // Release serialized access 02200 if (glb.bMultiThreaded) 02201 LeaveCriticalSection(&CriticalSection); 02202 #endif 02203 02204 // TODO: Re-instate rendering bitmap snapshot feature??? (DaveM) 02205 02206 // Render frame is completed 02207 ValidateRect(hWnd, NULL); 02208 lpCtx->bFrameStarted = FALSE; 02209 02210 return TRUE; 02211 } 02212 02213 // *********************************************************************** Generated on Sat May 26 2012 04:18:44 for ReactOS by
1.7.6.1
|