ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dglcontext.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.