1 /****************************************************************************
3 * Mesa 3-D graphics library
4 * Direct3D Driver Interface
6 * ========================================================================
8 * Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
25 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 * ======================================================================
31 * Environment: Windows 9x (Win32)
33 * Description: Context handling.
35 ****************************************************************************/
37 #include "dglcontext.h"
39 // Get compile errors without this. KeithH
40 //#include "scitech.h" // ibool, etc.
43 #include "gld_driver.h"
45 extern void _gld_mesa_warning(GLcontext
*, char *);
46 extern void _gld_mesa_fatal(GLcontext
*, char *);
47 #endif // _USE_GLD3_WGL
49 // TODO: Clean out old DX6-specific code from GLD 2.x CAD driver
50 // if it is no longer being built as part of GLDirect. (DaveM)
52 // ***********************************************************************
56 #define GLDERR_DDRAW 2
60 char szResourceWarning
[] =
61 "GLDirect does not have enough video memory resources\n"
62 "to support the requested OpenGL rendering context.\n\n"
63 "You may have to reduce the current display resolution\n"
64 "to obtain satisfactory OpenGL performance.\n";
66 char szDDrawWarning
[] =
67 "GLDirect is unable to initialize DirectDraw for the\n"
68 "requested OpenGL rendering context.\n\n"
69 "You will have to check the DirectX control panel\n"
70 "for further information.\n";
73 "GLDirect is unable to initialize Direct3D for the\n"
74 "requested OpenGL rendering context.\n\n"
75 "You may have to change the display mode resolution\n"
76 "color depth or check the DirectX control panel for\n"
77 "further information.\n";
80 "GLDirect is unable to use the selected color depth for\n"
81 "the requested OpenGL rendering context.\n\n"
82 "You will have to change the display mode resolution\n"
83 "color depth with the Display Settings control panel.\n";
85 int nContextError
= GLDERR_NONE
;
87 // ***********************************************************************
89 #define VENDORID_ATI 0x1002
91 static DWORD devATIRagePro
[] = {
92 0x4742, // 3D RAGE PRO BGA AGP 1X/2X
93 0x4744, // 3D RAGE PRO BGA AGP 1X only
94 0x4749, // 3D RAGE PRO BGA PCI 33 MHz
95 0x4750, // 3D RAGE PRO PQFP PCI 33 MHz
96 0x4751, // 3D RAGE PRO PQFP PCI 33 MHz limited 3D
97 0x4C42, // 3D RAGE LT PRO BGA-312 AGP 133 MHz
98 0x4C44, // 3D RAGE LT PRO BGA-312 AGP 66 MHz
99 0x4C49, // 3D RAGE LT PRO BGA-312 PCI 33 MHz
100 0x4C50, // 3D RAGE LT PRO BGA-256 PCI 33 MHz
101 0x4C51, // 3D RAGE LT PRO BGA-256 PCI 33 MHz limited 3D
104 static DWORD devATIRageIIplus
[] = {
105 0x4755, // 3D RAGE II+
106 0x4756, // 3D RAGE IIC PQFP PCI
107 0x4757, // 3D RAGE IIC BGA AGP
108 0x475A, // 3D RAGE IIC PQFP AGP
109 0x4C47, // 3D RAGE LT-G
112 // ***********************************************************************
114 #ifndef _USE_GLD3_WGL
115 extern DGL_mesaFuncs mesaFuncs
;
118 extern DWORD dwLogging
;
121 #pragma message("compiling DGLCONTEXT.C vars for multi-threaded support")
122 CRITICAL_SECTION CriticalSection
; // for serialized access
123 DWORD dwTLSCurrentContext
= 0xFFFFFFFF; // TLS index for current context
124 DWORD dwTLSPixelFormat
= 0xFFFFFFFF; // TLS index for current pixel format
126 HGLRC iCurrentContext
= 0; // Index of current context (static)
127 BOOL bContextReady
= FALSE
; // Context state ready ?
129 DGL_ctx ctxlist
[DGL_MAX_CONTEXTS
]; // Context list
131 // ***********************************************************************
133 static BOOL bHaveWin95
= FALSE
;
134 static BOOL bHaveWinNT
= FALSE
;
135 static BOOL bHaveWin2K
= FALSE
;
137 /****************************************************************************
139 Detect the installed OS type.
140 ****************************************************************************/
141 static void DetectOS(void)
143 OSVERSIONINFO VersionInformation
;
144 LPOSVERSIONINFO lpVersionInformation
= &VersionInformation
;
146 VersionInformation
.dwOSVersionInfoSize
= sizeof(VersionInformation
);
148 GetVersionEx(lpVersionInformation
);
150 switch (VersionInformation
.dwPlatformId
) {
151 case VER_PLATFORM_WIN32_WINDOWS
:
156 case VER_PLATFORM_WIN32_NT
:
158 if (VersionInformation
.dwMajorVersion
<= 4) {
167 case VER_PLATFORM_WIN32s
:
175 // ***********************************************************************
177 HWND hWndEvent
= NULL
; // event monitor window
178 HWND hWndLastActive
= NULL
; // last active client window
179 LONG __stdcall
GLD_EventWndProc(HWND hwnd
,UINT msg
,WPARAM wParam
,LPARAM lParam
);
181 // ***********************************************************************
183 // Checks if the HGLRC is valid in range of context list.
184 BOOL
dglIsValidContext(
187 return ((int)a
> 0 && (int)a
<= DGL_MAX_CONTEXTS
);
190 // ***********************************************************************
192 // Convert a HGLRC to a pointer into the context list.
193 DGL_ctx
* dglGetContextAddress(
196 if (dglIsValidContext(a
))
197 return &ctxlist
[(int)a
-1];
201 // ***********************************************************************
203 // Return the current HGLRC (however it may be stored for multi-threading).
204 HGLRC
dglGetCurrentContext(void)
208 // load from thread-specific instance
209 if (glb
.bMultiThreaded
) {
210 // protect against calls from arbitrary threads
212 hGLRC
= (HGLRC
)TlsGetValue(dwTLSCurrentContext
);
214 __except(EXCEPTION_EXECUTE_HANDLER
) {
215 hGLRC
= iCurrentContext
;
218 // load from global static var
220 hGLRC
= iCurrentContext
;
224 return iCurrentContext
;
228 // ***********************************************************************
230 // Set the current HGLRC (however it may be stored for multi-threading).
231 void dglSetCurrentContext(HGLRC hGLRC
)
234 // store in thread-specific instance
235 if (glb
.bMultiThreaded
) {
236 // protect against calls from arbitrary threads
238 TlsSetValue(dwTLSCurrentContext
, (LPVOID
)hGLRC
);
240 __except(EXCEPTION_EXECUTE_HANDLER
) {
241 iCurrentContext
= hGLRC
;
244 // store in global static var
246 iCurrentContext
= hGLRC
;
249 iCurrentContext
= hGLRC
;
253 // ***********************************************************************
255 // Return the current HDC only for a currently active HGLRC.
256 HDC
dglGetCurrentDC(void)
261 hGLRC
= dglGetCurrentContext();
263 lpCtx
= dglGetContextAddress(hGLRC
);
269 // ***********************************************************************
271 void dglInitContextState()
277 // Allocate thread local storage indexes for current context and pixel format
278 dwTLSCurrentContext
= TlsAlloc();
279 dwTLSPixelFormat
= TlsAlloc();
282 dglSetCurrentContext(NULL
); // No current rendering context
284 // Clear all context data
285 ZeroMemory(ctxlist
, sizeof(ctxlist
[0]) * DGL_MAX_CONTEXTS
);
287 for (i
=0; i
<DGL_MAX_CONTEXTS
; i
++)
288 ctxlist
[i
].bAllocated
= FALSE
; // Flag context as unused
290 // This section of code crashes the dll in circumstances where the app
291 // creates and destroys contexts.
293 // Register the class for our event monitor window
295 wc.lpfnWndProc = GLD_EventWndProc;
298 wc.hInstance = GetModuleHandle(NULL);
299 wc.hIcon = LoadIcon(GetModuleHandle(NULL), IDI_APPLICATION);
300 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
301 wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
302 wc.lpszMenuName = NULL;
303 wc.lpszClassName = "GLDIRECT";
306 // Create the non-visible window to monitor all broadcast messages
307 hWndEvent = CreateWindowEx(
308 WS_EX_TOOLWINDOW,"GLDIRECT","GLDIRECT",WS_POPUP,
310 NULL,NULL,GetModuleHandle(NULL),NULL);
314 // Create a critical section object for serializing access to
315 // DirectDraw and DDStereo create/destroy functions in multiple threads
316 if (glb
.bMultiThreaded
)
317 InitializeCriticalSection(&CriticalSection
);
320 // Context state is now initialized and ready
321 bContextReady
= TRUE
;
324 // ***********************************************************************
326 void dglDeleteContextState()
329 static BOOL bOnceIsEnough
= FALSE
;
331 // Only call once, from either DGL_exitDriver(), or DLL_PROCESS_DETACH
334 bOnceIsEnough
= TRUE
;
336 for (i
=0; i
<DGL_MAX_CONTEXTS
; i
++) {
337 if (ctxlist
[i
].bAllocated
== TRUE
) {
338 ddlogPrintf(DDLOG_WARN
, "** Context %i not deleted - cleaning up.", (i
+1));
339 dglDeleteContext((HGLRC
)(i
+1));
343 // Context state is no longer ready
344 bContextReady
= FALSE
;
346 // If executed when DLL unloads, DDraw objects may be invalid.
347 // So catch any page faults with this exception handler.
350 // Release final DirectDraw interfaces
351 if (glb
.bDirectDrawPersistant
) {
352 // RELEASE(glb.lpGlobalPalette);
353 // RELEASE(glb.lpDepth4);
354 // RELEASE(glb.lpBack4);
355 // RELEASE(glb.lpPrimary4);
356 // RELEASE(glb.lpDD4);
359 __except(EXCEPTION_EXECUTE_HANDLER
) {
360 ddlogPrintf(DDLOG_WARN
, "Exception raised in dglDeleteContextState.");
363 // Destroy our event monitor window
365 DestroyWindow(hWndEvent
);
366 hWndEvent
= hWndLastActive
= NULL
;
370 // Destroy the critical section object
371 if (glb
.bMultiThreaded
)
372 DeleteCriticalSection(&CriticalSection
);
374 // Release thread local storage indexes for current HGLRC and pixel format
375 TlsFree(dwTLSPixelFormat
);
376 TlsFree(dwTLSCurrentContext
);
380 // ***********************************************************************
382 // Application Window message handler interception
383 static LONG __stdcall
dglWndProc(
389 DGL_ctx
* lpCtx
= NULL
;
390 LONG lpfnWndProc
= 0L;
399 // Get the window's message handler *before* it is unhooked in WM_DESTROY
401 // Is this the main window?
402 if (hwnd
== glb
.hWndActive
) {
404 lpfnWndProc
= glb
.lpfnWndProc
;
406 // Search for DGL context matching window handle
407 for (i
=0; i
<DGL_MAX_CONTEXTS
; i
++) {
408 if (ctxlist
[i
].hWnd
== hwnd
) {
410 lpfnWndProc
= lpCtx
->lpfnWndProc
;
414 // Not one of ours...
416 return DefWindowProc(hwnd
, msg
, wParam
, lParam
);
418 // Intercept messages amd process *before* passing on to window
421 case WM_DISPLAYCHANGE
:
422 glb
.bPixelformatsDirty
= TRUE
;
426 glb
.bAppActive
= (BOOL
)wParam
;
427 ddlogPrintf(DDLOG_INFO
, "Calling app has been %s", glb
.bAppActive
? "activated" : "de-activated");
430 // Eat the GDI erase event for the GL window
431 if (!lpCtx
|| !lpCtx
->bHasBeenCurrent
)
433 lpCtx
->bGDIEraseBkgnd
= TRUE
;
436 // Eat the invalidated update region if render scene is in progress
437 if (!lpCtx
|| !lpCtx
->bHasBeenCurrent
)
439 if (lpCtx
->bFrameStarted
) {
440 if (GetUpdateRect(hwnd
, &rect
, FALSE
)) {
441 BeginPaint(hwnd
, &ps
);
443 ValidateRect(hwnd
, &rect
);
449 // Call the appropriate window message handler
450 rc
= CallWindowProc((WNDPROC
)lpfnWndProc
, hwnd
, msg
, wParam
, lParam
);
452 // Intercept messages and process *after* passing on to window
457 if (lpCtx
&& lpCtx
->bAllocated
) {
458 ddlogPrintf(DDLOG_WARN
, "WM_DESTROY detected for HWND=%X, HDC=%X, HGLRC=%d", hwnd
, lpCtx
->hDC
, i
+1);
459 dglDeleteContext((HGLRC
)(i
+1));
464 // Resize surfaces to fit window but not viewport (in case app did not bother)
465 if (!lpCtx
|| !lpCtx
->bHasBeenCurrent
)
469 if (lpCtx
->dwWidth
< w
|| lpCtx
->dwHeight
< h
) {
470 if (!dglWglResizeBuffers(lpCtx
->glCtx
, TRUE
))
471 dglWglResizeBuffers(lpCtx
->glCtx
, FALSE
);
477 // If the main window is quitting, then so should we...
478 if (bMain
&& bQuit
) {
479 ddlogPrintf(DDLOG_SYSTEM
, "shutting down after WM_DESTROY detected for main HWND=%X", hwnd
);
480 dglDeleteContextState();
487 // ***********************************************************************
489 // Driver Window message handler
490 static LONG __stdcall
GLD_EventWndProc(
497 // May be sent by splash screen dialog on exit
499 if (LOWORD(wParam
) == WA_ACTIVE
&& glb
.hWndActive
) {
500 SetForegroundWindow(glb
.hWndActive
);
505 return DefWindowProc(hwnd
, msg
, wParam
, lParam
);
508 // ***********************************************************************
510 // Intercepted Keyboard handler for detecting hot keys.
511 LRESULT CALLBACK
dglKeyProc(
516 HWND hWnd
, hWndFrame
;
518 DGL_ctx
* lpCtx
= NULL
;
519 int cmd
= 0, dx1
= 0, dx2
= 0, i
;
520 static BOOL bAltPressed
= FALSE
;
521 static BOOL bCtrlPressed
= FALSE
;
522 static BOOL bShiftPressed
= FALSE
;
525 BOOL bForceReshape
= FALSE
;
527 return CallNextHookEx(hKeyHook
, code
, wParam
, lParam
);
530 // ***********************************************************************
534 // Window handle enumeration procedure.
535 BOOL CALLBACK
dglEnumChildProc(
541 // Find window handle with matching client rect.
542 GetClientRect(hWnd
, &rect
);
543 if (EqualRect(&rect
, (RECT
*)lParam
)) {
547 // Continue with next child window.
551 // ***********************************************************************
553 // Find window handle with matching client rect.
554 HWND
dglFindWindowRect(
558 EnumChildWindows(GetForegroundWindow(), dglEnumChildProc
, (LPARAM
)pRect
);
562 // ***********************************************************************
563 #ifndef _USE_GLD3_WGL
564 void dglChooseDisplayMode(
567 // Note: Choose an exact match if possible.
572 DDSURFACEDESC2
*lpDDSD
= NULL
; // Mode list pointer
573 DDSURFACEDESC2
*lpBestDDSD
= NULL
; // Pointer to best
575 lpDDSD
= glb
.lpDisplayModes
;
576 for (i
=0; i
<glb
.nDisplayModeCount
; i
++, lpDDSD
++) {
577 if ((lpDDSD
->dwWidth
== lpCtx
->dwWidth
) &&
578 (lpDDSD
->dwHeight
== lpCtx
->dwHeight
))
579 goto matched
; // Mode has been exactly matched
580 // Choose modes that are larger in both dimensions than
581 // the window, but smaller in area than the current best.
582 if ( (lpDDSD
->dwWidth
>= lpCtx
->dwWidth
) &&
583 (lpDDSD
->dwHeight
>= lpCtx
->dwHeight
))
585 if (lpBestDDSD
== NULL
) {
587 bestarea
= lpDDSD
->dwWidth
* lpDDSD
->dwHeight
;
590 area
= lpDDSD
->dwWidth
* lpDDSD
->dwHeight
;
591 if (area
< bestarea
) {
599 if (lpBestDDSD
== NULL
) {
600 ddlogMessage(DDLOG_CRITICAL
, "dglChooseDisplayMode");
604 lpCtx
->dwModeWidth
= lpBestDDSD
->dwWidth
;
605 lpCtx
->dwModeHeight
= lpBestDDSD
->dwHeight
;
607 ddlogPrintf(DDLOG_INFO
, "Matched (%ldx%ld) to (%ldx%ld)",
608 lpCtx
->dwWidth
, lpCtx
->dwHeight
, lpCtx
->dwModeWidth
, lpCtx
->dwModeHeight
);
610 #endif // _USE_GLD3_WGL
611 // ***********************************************************************
613 static BOOL
IsDevice(
614 DWORD
*lpDeviceIdList
,
620 for (i
=0; i
<count
; i
++)
621 if (dwDeviceId
== lpDeviceIdList
[i
])
627 // ***********************************************************************
629 void dglTestForBrokenCards(
633 DDDEVICEIDENTIFIER dddi
; // DX6 device identifier
637 // Testing for broken cards is sensitive area, so we don't want
638 // anything saying "broken cards" in the error message. ;)
639 ddlogMessage(DDLOG_ERROR
, "Null context passed to TFBC\n");
643 if (lpCtx
->lpDD4
== NULL
) {
644 // Testing for broken cards is sensitive area, so we don't want
645 // anything saying "broken cards" in the error message. ;)
646 ddlogMessage(DDLOG_ERROR
, "Null DD4 passed to TFBC\n");
650 // Microsoft really fucked up with the GetDeviceIdentifier function
651 // on Windows 2000, since it locks up on stock driers on the CD. Updated
652 // drivers from vendors appear to work, but we can't identify the drivers
653 // without this function!!! For now we skip these tests on Windows 2000.
654 if ((GetVersion() & 0x80000000UL
) == 0)
657 // Obtain device info
658 if (FAILED(IDirectDraw4_GetDeviceIdentifier(lpCtx
->lpDD4
, &dddi
, 0)))
661 // Useful info. Log it.
662 ddlogPrintf(DDLOG_INFO
, "DirectDraw: VendorId=0x%x, DeviceId=0x%x", dddi
.dwVendorId
, dddi
.dwDeviceId
);
665 if (dddi
.dwVendorId
== VENDORID_ATI
) {
666 // Test A: ATI Rage PRO
667 if (IsDevice(devATIRagePro
, dddi
.dwDeviceId
, sizeof(devATIRagePro
)))
668 glb
.bUseMipmaps
= FALSE
;
669 // Test B: ATI Rage II+
670 if (IsDevice(devATIRageIIplus
, dddi
.dwDeviceId
, sizeof(devATIRageIIplus
)))
671 glb
.bEmulateAlphaTest
= TRUE
;
675 if (dddi
.dwVendorId
== 0x102B) {
676 // Test: Matrox G400 stencil buffer support does not work for AutoCAD
677 if (dddi
.dwDeviceId
== 0x0525) {
678 lpCtx
->lpPF
->pfd
.cStencilBits
= 0;
679 if (lpCtx
->lpPF
->iZBufferPF
!= -1) {
680 glb
.lpZBufferPF
[lpCtx
->lpPF
->iZBufferPF
].dwStencilBitDepth
= 0;
681 glb
.lpZBufferPF
[lpCtx
->lpPF
->iZBufferPF
].dwStencilBitMask
= 0;
682 glb
.lpZBufferPF
[lpCtx
->lpPF
->iZBufferPF
].dwFlags
&= ~DDPF_STENCILBUFFER
;
689 // ***********************************************************************
691 BOOL
dglCreateContextBuffers(
702 #ifndef _USE_GLD3_WGL
704 DDSURFACEDESC2 ddsd2
;
706 LPDIRECTDRAWCLIPPER lpddClipper
;
707 D3DDEVICEDESC D3DHWDevDesc
; // Direct3D Hardware description
708 D3DDEVICEDESC D3DHELDevDesc
; // Direct3D Hardware Emulation Layer
709 #endif // _USE_GLD3_WGL
713 GLenum bDoubleBuffer
; // TRUE if double buffer required
714 GLenum bDepthBuffer
; // TRUE if depth buffer required
716 const PIXELFORMATDESCRIPTOR
*lpPFD
= &lpCtx
->lpPF
->pfd
;
718 // Vars for Mesa visual
719 DWORD dwDepthBits
= 0;
720 DWORD dwStencilBits
= 0;
721 DWORD dwAlphaBits
= 0;
722 DWORD bAlphaSW
= GL_FALSE
;
723 DWORD bDouble
= GL_FALSE
;
725 DDSURFACEDESC2 ddsd2DisplayMode
;
726 BOOL bFullScrnWin
= FALSE
; // fullscreen-size window ?
728 DWORD dwMemoryType
= (bFallback
) ? DDSCAPS_SYSTEMMEMORY
: glb
.dwMemoryType
;
729 BOOL bBogusWindow
= FALSE
; // non-drawable window ?
730 DWORD dwColorRef
= 0; // GDI background color
731 RECT rcDst
; // GDI window rect
732 POINT pt
; // GDI window point
734 // Palette used for creating default global palette
735 PALETTEENTRY ppe
[256];
737 #ifndef _USE_GLD3_WGL
738 // Vertex buffer description. Used for creation of vertex buffers
739 D3DVERTEXBUFFERDESC vbufdesc
;
740 #endif // _USE_GLD3_WGL
742 #define DDLOG_CRITICAL_OR_WARN (bFallback ? DDLOG_CRITICAL : DDLOG_WARN)
744 ddlogPrintf(DDLOG_SYSTEM
, "dglCreateContextBuffers for HDC=%X", a
);
745 nContextError
= GLDERR_NONE
;
748 // Serialize access to DirectDraw object creation or DDS start
749 if (glb
.bMultiThreaded
)
750 EnterCriticalSection(&CriticalSection
);
753 // Check for back buffer
754 bDoubleBuffer
= GL_TRUE
; //(lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE;
755 // Since we always do back buffering, check if we emulate front buffering
756 lpCtx
->EmulateSingle
=
757 (lpPFD
->dwFlags
& PFD_DOUBLEBUFFER
) ? FALSE
: TRUE
;
758 #if 0 // Don't have to mimic MS OpenGL behavior for front-buffering (DaveM)
759 lpCtx
->EmulateSingle
|=
760 (lpPFD
->dwFlags
& PFD_SUPPORT_GDI
) ? TRUE
: FALSE
;
763 // Check for depth buffer
764 bDepthBuffer
= (lpPFD
->cDepthBits
) ? GL_TRUE
: GL_FALSE
;
766 lpCtx
->bDoubleBuffer
= bDoubleBuffer
;
767 lpCtx
->bDepthBuffer
= bDepthBuffer
;
769 // Set the Fullscreen flag for the context.
770 // lpCtx->bFullscreen = glb.bFullscreen;
772 // Obtain the dimensions of the rendering window
773 lpCtx
->hDC
= a
; // Cache DC
774 lpCtx
->hWnd
= WindowFromDC(lpCtx
->hDC
);
775 // Check for non-window DC = memory DC ?
776 if (lpCtx
->hWnd
== NULL
) {
777 // bitmap memory contexts are always single-buffered
778 lpCtx
->EmulateSingle
= TRUE
;
780 ddlogPrintf(DDLOG_INFO
, "Non-Window Memory Device Context");
781 if (GetClipBox(lpCtx
->hDC
, &lpCtx
->rcScreenRect
) == ERROR
) {
782 ddlogMessage(DDLOG_WARN
, "GetClipBox failed in dglCreateContext\n");
783 SetRect(&lpCtx
->rcScreenRect
, 0, 0, 0, 0);
786 else if (!GetClientRect(lpCtx
->hWnd
, &lpCtx
->rcScreenRect
)) {
788 ddlogMessage(DDLOG_WARN
, "GetClientRect failed in dglCreateContext\n");
789 SetRect(&lpCtx
->rcScreenRect
, 0, 0, 0, 0);
791 lpCtx
->dwWidth
= lpCtx
->rcScreenRect
.right
- lpCtx
->rcScreenRect
.left
;
792 lpCtx
->dwHeight
= lpCtx
->rcScreenRect
.bottom
- lpCtx
->rcScreenRect
.top
;
794 ddlogPrintf(DDLOG_INFO
, "Input window %X: w=%i, h=%i",
795 lpCtx
->hWnd
, lpCtx
->dwWidth
, lpCtx
->dwHeight
);
797 // What if app only zeroes one dimension instead of both? (DaveM)
798 if ( (lpCtx
->dwWidth
== 0) || (lpCtx
->dwHeight
== 0) ) {
799 // Make the buffer size something sensible
805 lpCtx
->dwModeWidth
= lpCtx
->dwWidth
;
806 lpCtx
->dwModeHeight
= lpCtx
->dwHeight
;
808 // Find best display mode for fullscreen
809 if (glb.bFullscreen || !glb.bPrimary) {
810 dglChooseDisplayMode(lpCtx);
813 // Misc initialisation
814 lpCtx
->bCanRender
= FALSE
; // No rendering allowed yet
815 lpCtx
->bSceneStarted
= FALSE
;
816 lpCtx
->bFrameStarted
= FALSE
;
818 // Detect OS (specifically 'Windows 2000' or 'Windows XP')
821 // NOTE: WinNT not supported
822 ddlogPrintf(DDLOG_INFO
, "OS: %s", bHaveWin95
? "Win9x" : (bHaveWin2K
? "Win2000/XP" : "Unsupported") );
824 // Test for Fullscreen
825 if (bHaveWin95
) { // Problems with fullscreen on Win2K/XP
826 if ((GetSystemMetrics(SM_CXSCREEN
) == lpCtx
->dwWidth
) &&
827 (GetSystemMetrics(SM_CYSCREEN
) == lpCtx
->dwHeight
))
829 // Workaround for some apps that crash when going fullscreen.
830 //lpCtx->bFullscreen = TRUE;
836 _gldDriver
.CreateDrawable(lpCtx
, glb
.bDirectDrawPersistant
, glb
.bPersistantBuffers
);
838 // Check if DirectDraw has already been created by original GLRC (DaveM)
839 if (glb
.bDirectDrawPersistant
&& glb
.bDirectDraw
) {
840 lpCtx
->lpDD4
= glb
.lpDD4
;
841 IDirectDraw4_AddRef(lpCtx
->lpDD4
);
842 goto SkipDirectDrawCreate
;
845 // Create DirectDraw object
847 hResult
= DirectDrawCreate(NULL
, &lpCtx
->lpDD1
, NULL
);
849 // A non-primary device is to be used.
850 // Force context to be Fullscreen, secondary adaptors can not
851 // be used in a window.
852 hResult
= DirectDrawCreate(&glb
.ddGuid
, &lpCtx
->lpDD1
, NULL
);
853 lpCtx
->bFullscreen
= TRUE
;
855 if (FAILED(hResult
)) {
856 MessageBox(NULL
, "Unable to initialize DirectDraw", "GLDirect", MB_OK
);
857 ddlogError(DDLOG_CRITICAL_OR_WARN
, "Unable to create DirectDraw interface", hResult
);
858 nContextError
= GLDERR_DDRAW
;
859 goto return_with_error
;
862 // Query for DX6 IDirectDraw4.
863 hResult
= IDirectDraw_QueryInterface(lpCtx
->lpDD1
,
865 (void**)&lpCtx
->lpDD4
);
866 if (FAILED(hResult
)) {
867 MessageBox(NULL
, "GLDirect requires DirectX 6.0 or above", "GLDirect", MB_OK
);
868 ddlogError(DDLOG_CRITICAL_OR_WARN
, "Unable to create DirectDraw4 interface", hResult
);
869 nContextError
= GLDERR_DDRAW
;
870 goto return_with_error
;
873 // Cache DirectDraw interface for subsequent GLRCs
874 if (glb
.bDirectDrawPersistant
&& !glb
.bDirectDraw
) {
875 glb
.lpDD4
= lpCtx
->lpDD4
;
876 IDirectDraw4_AddRef(glb
.lpDD4
);
877 glb
.bDirectDraw
= TRUE
;
879 SkipDirectDrawCreate
:
881 // Now we have a DD4 interface we can check for broken cards
882 dglTestForBrokenCards(lpCtx
);
884 // Test if primary device can use flipping instead of blitting
885 ZeroMemory(&ddsd2DisplayMode
, sizeof(ddsd2DisplayMode
));
886 ddsd2DisplayMode
.dwSize
= sizeof(ddsd2DisplayMode
);
887 hResult
= IDirectDraw4_GetDisplayMode(
890 if (SUCCEEDED(hResult
)) {
891 if ( (lpCtx
->dwWidth
== ddsd2DisplayMode
.dwWidth
) &&
892 (lpCtx
->dwHeight
== ddsd2DisplayMode
.dwHeight
) ) {
893 // We have a fullscreen-size window
895 // OK to use DirectDraw fullscreen mode ?
896 if (glb
.bPrimary
&& !glb
.bFullscreenBlit
&& !lpCtx
->EmulateSingle
&& !glb
.bDirectDrawPersistant
) {
897 lpCtx
->bFullscreen
= TRUE
;
898 ddlogMessage(DDLOG_INFO
, "Primary upgraded to page flipping.\n");
901 // Cache the display mode dimensions
902 lpCtx
->dwModeWidth
= ddsd2DisplayMode
.dwWidth
;
903 lpCtx
->dwModeHeight
= ddsd2DisplayMode
.dwHeight
;
906 // Clamp the effective window dimensions to primary surface.
907 // We need to do this for D3D viewport dimensions even if wide
908 // surfaces are supported. This also is a good idea for handling
909 // whacked-out window dimensions passed for non-drawable windows
910 // like Solid Edge. (DaveM)
911 if (lpCtx
->dwWidth
> ddsd2DisplayMode
.dwWidth
)
912 lpCtx
->dwWidth
= ddsd2DisplayMode
.dwWidth
;
913 if (lpCtx
->dwHeight
> ddsd2DisplayMode
.dwHeight
)
914 lpCtx
->dwHeight
= ddsd2DisplayMode
.dwHeight
;
916 // Check for non-RGB desktop resolution
917 if (!lpCtx
->bFullscreen
&& ddsd2DisplayMode
.ddpfPixelFormat
.dwRGBBitCount
<= 8) {
918 ddlogPrintf(DDLOG_CRITICAL_OR_WARN
, "Desktop color depth %d bpp not supported",
919 ddsd2DisplayMode
.ddpfPixelFormat
.dwRGBBitCount
);
920 nContextError
= GLDERR_BPP
;
921 goto return_with_error
;
923 #endif // _USE_GLD3_WGL
925 ddlogPrintf(DDLOG_INFO
, "Window: w=%i, h=%i (%s)",
928 lpCtx
->bFullscreen
? "fullscreen" : "windowed");
930 #ifndef _USE_GLD3_WGL
932 ZeroMemory(&lpCtx
->ddCaps
, sizeof(DDCAPS
));
933 lpCtx
->ddCaps
.dwSize
= sizeof(DDCAPS
);
936 IDirectDraw4_GetCaps(lpCtx
->lpDD4
, &lpCtx
->ddCaps
, NULL
);
939 IDirectDraw4_GetCaps(lpCtx
->lpDD4
, NULL
, &lpCtx
->ddCaps
);
942 // If this flag is present then we can't default to Mesa
943 // SW rendering between BeginScene() and EndScene().
944 if (lpCtx
->ddCaps
.dwCaps2
& DDCAPS2_NO2DDURING3DSCENE
) {
945 ddlogMessage(DDLOG_INFO
,
946 "Warning : No 2D allowed during 3D scene.\n");
949 // Query for DX6 Direct3D3 interface
950 hResult
= IDirectDraw4_QueryInterface(lpCtx
->lpDD4
,
952 (void**)&lpCtx
->lpD3D3
);
953 if (FAILED(hResult
)) {
954 MessageBox(NULL
, "Unable to initialize Direct3D", "GLDirect", MB_OK
);
955 ddlogError(DDLOG_CRITICAL_OR_WARN
, "Unable to create Direct3D interface", hResult
);
956 nContextError
= GLDERR_D3D
;
957 goto return_with_error
;
961 if (lpCtx
->bFullscreen
) {
964 // Disable warning popups when in fullscreen mode
965 ddlogWarnOption(FALSE
);
967 // Have to release persistant primary surface if fullscreen mode
968 if (glb
.bDirectDrawPersistant
&& glb
.bDirectDrawPrimary
) {
969 RELEASE(glb
.lpPrimary4
);
970 glb
.bDirectDrawPrimary
= FALSE
;
973 dwFlags
= DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
| DDSCL_ALLOWREBOOT
;
975 dwFlags
|= DDSCL_FPUSETUP
; // fast FPU setup optional (DaveM)
976 hResult
= IDirectDraw4_SetCooperativeLevel(lpCtx
->lpDD4
, lpCtx
->hWnd
, dwFlags
);
977 if (FAILED(hResult
)) {
978 ddlogError(DDLOG_CRITICAL_OR_WARN
, "Unable to set Exclusive Fullscreen mode", hResult
);
979 goto return_with_error
;
982 hResult
= IDirectDraw4_SetDisplayMode(lpCtx
->lpDD4
,
988 if (FAILED(hResult
)) {
989 ddlogError(DDLOG_CRITICAL_OR_WARN
, "SetDisplayMode failed", hResult
);
990 goto return_with_error
;
993 // ** The display mode has changed, so dont use MessageBox! **
995 ZeroMemory(&ddsd2
, sizeof(ddsd2
));
996 ddsd2
.dwSize
= sizeof(ddsd2
);
1001 ddsd2
.dwFlags
= DDSD_CAPS
| DDSD_BACKBUFFERCOUNT
;
1002 ddsd2
.ddsCaps
.dwCaps
= DDSCAPS_PRIMARYSURFACE
|
1007 ddsd2
.dwBackBufferCount
= 1;
1009 hResult
= IDirectDraw4_CreateSurface(lpCtx
->lpDD4
, &ddsd2
, &lpCtx
->lpFront4
, NULL
);
1010 if (FAILED(hResult
)) {
1011 ddlogError(DDLOG_CRITICAL_OR_WARN
, "CreateSurface (primary) failed", hResult
);
1012 nContextError
= GLDERR_MEM
;
1013 goto return_with_error
;
1016 // Render target surface
1017 ZeroMemory(&ddscaps2
, sizeof(ddscaps2
)); // Clear the entire struct.
1018 ddscaps2
.dwCaps
= DDSCAPS_BACKBUFFER
;
1019 hResult
= IDirectDrawSurface4_GetAttachedSurface(lpCtx
->lpFront4
, &ddscaps2
, &lpCtx
->lpBack4
);
1020 if (FAILED(hResult
)) {
1021 ddlogError(DDLOG_CRITICAL_OR_WARN
, "GetAttachedSurface failed", hResult
);
1022 nContextError
= GLDERR_MEM
;
1023 goto return_with_error
;
1028 ddsd2
.dwFlags
= DDSD_CAPS
;
1029 ddsd2
.ddsCaps
.dwCaps
= DDSCAPS_PRIMARYSURFACE
|
1030 //DDSCAPS_3DDEVICE |
1033 hResult
= IDirectDraw4_CreateSurface(lpCtx
->lpDD4
, &ddsd2
, &lpCtx
->lpFront4
, NULL
);
1034 if (FAILED(hResult
)) {
1035 ddlogError(DDLOG_CRITICAL_OR_WARN
, "CreateSurface (primary) failed", hResult
);
1036 nContextError
= GLDERR_MEM
;
1037 goto return_with_error
;
1040 lpCtx
->lpBack4
= NULL
;
1045 // OK to enable warning popups in windowed mode
1046 ddlogWarnOption(glb
.bMessageBoxWarnings
);
1048 dwFlags
= DDSCL_NORMAL
;
1049 if (glb
.bMultiThreaded
)
1050 dwFlags
|= DDSCL_MULTITHREADED
;
1052 dwFlags
|= DDSCL_FPUSETUP
; // fast FPU setup optional (DaveM)
1053 hResult
= IDirectDraw4_SetCooperativeLevel(lpCtx
->lpDD4
,
1056 if (FAILED(hResult
)) {
1057 ddlogError(DDLOG_CRITICAL_OR_WARN
, "Unable to set Normal coop level", hResult
);
1058 goto return_with_error
;
1060 // Has Primary surface already been created for original GLRC ?
1061 // Note this can only be applicable for windowed modes
1062 if (glb
.bDirectDrawPersistant
&& glb
.bDirectDrawPrimary
) {
1063 lpCtx
->lpFront4
= glb
.lpPrimary4
;
1064 IDirectDrawSurface4_AddRef(lpCtx
->lpFront4
);
1065 // Update the window on the default clipper
1066 IDirectDrawSurface4_GetClipper(lpCtx
->lpFront4
, &lpddClipper
);
1067 IDirectDrawClipper_SetHWnd(lpddClipper
, 0, lpCtx
->hWnd
);
1068 IDirectDrawClipper_Release(lpddClipper
);
1069 goto SkipPrimaryCreate
;
1073 ZeroMemory(&ddsd2
, sizeof(ddsd2
));
1074 ddsd2
.dwSize
= sizeof(ddsd2
);
1075 ddsd2
.dwFlags
= DDSD_CAPS
;
1076 ddsd2
.ddsCaps
.dwCaps
= DDSCAPS_PRIMARYSURFACE
;
1077 hResult
= IDirectDraw4_CreateSurface(lpCtx
->lpDD4
, &ddsd2
, &lpCtx
->lpFront4
, NULL
);
1078 if (FAILED(hResult
)) {
1079 ddlogError(DDLOG_CRITICAL_OR_WARN
, "CreateSurface (primary) failed", hResult
);
1080 nContextError
= GLDERR_MEM
;
1081 goto return_with_error
;
1084 // Cache Primary surface for subsequent GLRCs
1085 // Note this can only be applicable to subsequent windowed modes
1086 if (glb
.bDirectDrawPersistant
&& !glb
.bDirectDrawPrimary
) {
1087 glb
.lpPrimary4
= lpCtx
->lpFront4
;
1088 IDirectDrawSurface4_AddRef(glb
.lpPrimary4
);
1089 glb
.bDirectDrawPrimary
= TRUE
;
1093 hResult
= DirectDrawCreateClipper(0, &lpddClipper
, NULL
);
1094 if (FAILED(hResult
)) {
1095 ddlogError(DDLOG_CRITICAL_OR_WARN
, "CreateClipper failed", hResult
);
1096 goto return_with_error
;
1098 hResult
= IDirectDrawClipper_SetHWnd(lpddClipper
, 0, lpCtx
->hWnd
);
1099 if (FAILED(hResult
)) {
1100 RELEASE(lpddClipper
);
1101 ddlogError(DDLOG_CRITICAL_OR_WARN
, "SetHWnd failed", hResult
);
1102 goto return_with_error
;
1104 hResult
= IDirectDrawSurface4_SetClipper(lpCtx
->lpFront4
, lpddClipper
);
1105 RELEASE(lpddClipper
); // We have finished with it.
1106 if (FAILED(hResult
)) {
1107 ddlogError(DDLOG_CRITICAL_OR_WARN
, "SetClipper failed", hResult
);
1108 goto return_with_error
;
1112 if (bDoubleBuffer
) {
1113 // Render target surface
1114 ZeroMemory(&ddsd2
, sizeof(ddsd2
));
1115 ddsd2
.dwSize
= sizeof(ddsd2
);
1116 ddsd2
.dwFlags
= DDSD_CAPS
| DDSD_WIDTH
| DDSD_HEIGHT
;
1117 ddsd2
.dwWidth
= lpCtx
->dwWidth
;
1118 ddsd2
.dwHeight
= lpCtx
->dwHeight
;
1119 ddsd2
.ddsCaps
.dwCaps
= DDSCAPS_3DDEVICE
|
1120 DDSCAPS_OFFSCREENPLAIN
|
1123 // Reserve the entire desktop size for persistant buffers option
1124 if (glb
.bDirectDrawPersistant
&& glb
.bPersistantBuffers
) {
1125 ddsd2
.dwWidth
= ddsd2DisplayMode
.dwWidth
;
1126 ddsd2
.dwHeight
= ddsd2DisplayMode
.dwHeight
;
1128 // Re-use original back buffer if persistant buffers exist
1129 if (glb
.bDirectDrawPersistant
&& glb
.bPersistantBuffers
&& glb
.lpBack4
)
1130 hResult
= IDirectDrawSurface4_AddRef(lpCtx
->lpBack4
= glb
.lpBack4
);
1132 hResult
= IDirectDraw4_CreateSurface(lpCtx
->lpDD4
, &ddsd2
, &lpCtx
->lpBack4
, NULL
);
1133 if (FAILED(hResult
)) {
1134 ddlogError(DDLOG_CRITICAL_OR_WARN
, "Create Backbuffer failed", hResult
);
1135 nContextError
= GLDERR_MEM
;
1136 goto return_with_error
;
1138 if (glb
.bDirectDrawPersistant
&& glb
.bPersistantBuffers
&& !glb
.lpBack4
)
1139 IDirectDrawSurface4_AddRef(glb
.lpBack4
= lpCtx
->lpBack4
);
1141 lpCtx
->lpBack4
= NULL
;
1146 // Now create the Z-buffer
1148 lpCtx
->bStencil
= FALSE
; // Default to no stencil buffer
1149 if (bDepthBuffer
&& (lpCtx
->lpPF
->iZBufferPF
!= -1)) {
1150 // Get z-buffer dimensions from the render target
1151 // Setup the surface desc for the z-buffer.
1152 ZeroMemory(&ddsd2
, sizeof(ddsd2
));
1153 ddsd2
.dwSize
= sizeof(ddsd2
);
1154 ddsd2
.dwFlags
= DDSD_CAPS
| DDSD_WIDTH
| DDSD_HEIGHT
| DDSD_PIXELFORMAT
;
1155 ddsd2
.ddsCaps
.dwCaps
= DDSCAPS_ZBUFFER
| dwMemoryType
;
1156 ddsd2
.dwWidth
= lpCtx
->dwWidth
;
1157 ddsd2
.dwHeight
= lpCtx
->dwHeight
;
1158 memcpy(&ddsd2
.ddpfPixelFormat
,
1159 &glb
.lpZBufferPF
[lpCtx
->lpPF
->iZBufferPF
],
1160 sizeof(DDPIXELFORMAT
) );
1162 // Reserve the entire desktop size for persistant buffers option
1163 if (glb
.bDirectDrawPersistant
&& glb
.bPersistantBuffers
) {
1164 ddsd2
.dwWidth
= ddsd2DisplayMode
.dwWidth
;
1165 ddsd2
.dwHeight
= ddsd2DisplayMode
.dwHeight
;
1168 // Create a z-buffer
1169 if (glb
.bDirectDrawPersistant
&& glb
.bPersistantBuffers
&& glb
.lpDepth4
)
1170 hResult
= IDirectDrawSurface4_AddRef(lpCtx
->lpDepth4
= glb
.lpDepth4
);
1172 hResult
= IDirectDraw4_CreateSurface(lpCtx
->lpDD4
, &ddsd2
, &lpCtx
->lpDepth4
, NULL
);
1173 if (FAILED(hResult
)) {
1174 ddlogError(DDLOG_CRITICAL_OR_WARN
, "CreateSurface (ZBuffer) failed", hResult
);
1175 nContextError
= GLDERR_MEM
;
1176 goto return_with_error
;
1178 if (glb
.bDirectDrawPersistant
&& glb
.bPersistantBuffers
&& !glb
.lpDepth4
)
1179 IDirectDrawSurface4_AddRef(glb
.lpDepth4
= lpCtx
->lpDepth4
);
1180 else if (glb
.bDirectDrawPersistant
&& glb
.bPersistantBuffers
&& glb
.lpDepth4
&& glb
.lpBack4
)
1181 IDirectDrawSurface4_DeleteAttachedSurface(glb
.lpBack4
, 0, glb
.lpDepth4
);
1183 // Attach Zbuffer to render target
1184 TRY(IDirectDrawSurface4_AddAttachedSurface(
1185 bDoubleBuffer
? lpCtx
->lpBack4
: lpCtx
->lpFront4
,
1187 "dglCreateContext: Attach Zbuffer");
1188 if (glb
.lpZBufferPF
[lpCtx
->lpPF
->iZBufferPF
].dwFlags
& DDPF_STENCILBUFFER
) {
1189 lpCtx
->bStencil
= TRUE
;
1190 ddlogMessage(DDLOG_INFO
, "Depth buffer has stencil\n");
1194 // Clear all back buffers and Z-buffers in case of memory recycling.
1195 ZeroMemory(&ddbltfx
, sizeof(ddbltfx
));
1196 ddbltfx
.dwSize
= sizeof(ddbltfx
);
1197 IDirectDrawSurface4_Blt(lpCtx
->lpBack4
, NULL
, NULL
, NULL
,
1198 DDBLT_COLORFILL
| DDBLT_WAIT
, &ddbltfx
);
1199 if (lpCtx
->lpDepth4
)
1200 IDirectDrawSurface4_Blt(lpCtx
->lpDepth4
, NULL
, NULL
, NULL
,
1201 DDBLT_COLORFILL
| DDBLT_WAIT
, &ddbltfx
);
1203 // Now that we have a Z-buffer we can create the 3D device
1204 hResult
= IDirect3D3_CreateDevice(lpCtx
->lpD3D3
,
1206 bDoubleBuffer
? lpCtx
->lpBack4
: lpCtx
->lpFront4
,
1209 if (FAILED(hResult
)) {
1210 ddlogError(DDLOG_CRITICAL_OR_WARN
, "Unable to create Direct3D device", hResult
);
1211 nContextError
= GLDERR_D3D
;
1212 goto return_with_error
;
1215 // We must do this as soon as the device is created
1216 dglInitStateCaches(lpCtx
);
1218 // Obtain the D3D Device Description
1219 D3DHWDevDesc
.dwSize
= D3DHELDevDesc
.dwSize
= sizeof(D3DDEVICEDESC
);
1220 TRY(IDirect3DDevice3_GetCaps(lpCtx
->lpDev3
,
1223 "dglCreateContext: GetCaps failed");
1225 // Choose the relevant description and cache it in the context.
1226 // We will use this description later for caps checking
1227 memcpy( &lpCtx
->D3DDevDesc
,
1228 glb
.bHardware
? &D3DHWDevDesc
: &D3DHELDevDesc
,
1229 sizeof(D3DDEVICEDESC
));
1231 // Now we can examine the texture formats
1232 if (!dglBuildTextureFormatList(lpCtx
->lpDev3
)) {
1233 ddlogMessage(DDLOG_CRITICAL_OR_WARN
, "dglBuildTextureFormatList failed\n");
1234 goto return_with_error
;
1237 // Get the pixel format of the back buffer
1238 lpCtx
->ddpfRender
.dwSize
= sizeof(lpCtx
->ddpfRender
);
1240 hResult
= IDirectDrawSurface4_GetPixelFormat(
1242 &lpCtx
->ddpfRender
);
1244 hResult
= IDirectDrawSurface4_GetPixelFormat(
1246 &lpCtx
->ddpfRender
);
1248 if (FAILED(hResult
)) {
1249 ddlogError(DDLOG_CRITICAL_OR_WARN
, "GetPixelFormat failed", hResult
);
1250 goto return_with_error
;
1252 // Find a pixel packing function suitable for this surface
1253 pxClassifyPixelFormat(&lpCtx
->ddpfRender
,
1255 &lpCtx
->fnUnpackFunc
,
1256 &lpCtx
->fnPackSpanFunc
);
1259 hResult
= IDirect3D3_CreateViewport(lpCtx
->lpD3D3
, &lpCtx
->lpViewport3
, NULL
);
1260 if (FAILED(hResult
)) {
1261 ddlogError(DDLOG_CRITICAL_OR_WARN
, "CreateViewport failed", hResult
);
1262 goto return_with_error
;
1265 hResult
= IDirect3DDevice3_AddViewport(lpCtx
->lpDev3
, lpCtx
->lpViewport3
);
1266 if (FAILED(hResult
)) {
1267 ddlogError(DDLOG_CRITICAL_OR_WARN
, "AddViewport failed", hResult
);
1268 goto return_with_error
;
1271 // Initialise the viewport
1272 // Note screen coordinates are used for viewport clipping since D3D
1273 // transform operations are not used in the GLD CAD driver. (DaveM)
1274 inv_aspect
= (float)lpCtx
->dwHeight
/(float)lpCtx
->dwWidth
;
1276 lpCtx
->d3dViewport
.dwSize
= sizeof(lpCtx
->d3dViewport
);
1277 lpCtx
->d3dViewport
.dwX
= 0;
1278 lpCtx
->d3dViewport
.dwY
= 0;
1279 lpCtx
->d3dViewport
.dwWidth
= lpCtx
->dwWidth
;
1280 lpCtx
->d3dViewport
.dwHeight
= lpCtx
->dwHeight
;
1281 lpCtx
->d3dViewport
.dvClipX
= 0; // -1.0f;
1282 lpCtx
->d3dViewport
.dvClipY
= 0; // inv_aspect;
1283 lpCtx
->d3dViewport
.dvClipWidth
= lpCtx
->dwWidth
; // 2.0f;
1284 lpCtx
->d3dViewport
.dvClipHeight
= lpCtx
->dwHeight
; // 2.0f * inv_aspect;
1285 lpCtx
->d3dViewport
.dvMinZ
= 0.0f
;
1286 lpCtx
->d3dViewport
.dvMaxZ
= 1.0f
;
1287 TRY(IDirect3DViewport3_SetViewport2(lpCtx
->lpViewport3
, &lpCtx
->d3dViewport
), "dglCreateContext: SetViewport2");
1289 hResult
= IDirect3DDevice3_SetCurrentViewport(lpCtx
->lpDev3
, lpCtx
->lpViewport3
);
1290 if (FAILED(hResult
)) {
1291 ddlogError(DDLOG_CRITICAL_OR_WARN
, "SetCurrentViewport failed", hResult
);
1292 goto return_with_error
;
1295 lpCtx
->dwBPP
= lpPFD
->cColorBits
;
1296 lpCtx
->iZBufferPF
= lpCtx
->lpPF
->iZBufferPF
;
1298 // Set last texture to NULL
1299 for (i
=0; i
<MAX_TEXTURE_UNITS
; i
++) {
1300 lpCtx
->ColorOp
[i
] = D3DTOP_DISABLE
;
1301 lpCtx
->AlphaOp
[i
] = D3DTOP_DISABLE
;
1302 lpCtx
->tObj
[i
] = NULL
;
1305 // Default to perspective correct texture mapping
1306 dglSetRenderState(lpCtx
, D3DRENDERSTATE_TEXTUREPERSPECTIVE
, TRUE
, "TexturePersp");
1308 // Set the default culling mode
1309 lpCtx
->cullmode
= D3DCULL_NONE
;
1310 dglSetRenderState(lpCtx
, D3DRENDERSTATE_CULLMODE
, D3DCULL_NONE
, "CullMode");
1313 dglSetRenderState(lpCtx
, D3DRENDERSTATE_SPECULARENABLE
, FALSE
, "SpecularEnable");
1314 // Disable subpixel correction
1315 // dglSetRenderState(lpCtx, D3DRENDERSTATE_SUBPIXEL, FALSE, "SubpixelEnable");
1316 // Disable dithering
1317 dglSetRenderState(lpCtx
, D3DRENDERSTATE_DITHERENABLE
, FALSE
, "DitherEnable");
1319 // Initialise the primitive caches
1320 // lpCtx->dwNextLineVert = 0;
1321 // lpCtx->dwNextTriVert = 0;
1323 // Init the global texture palette
1324 lpCtx
->lpGlobalPalette
= NULL
;
1326 // Init the HW/SW usage counters
1327 // lpCtx->dwHWUsageCount = lpCtx->dwSWUsageCount = 0L;
1330 // Create two D3D vertex buffers.
1331 // One will hold the pre-transformed data with the other one
1332 // being used to hold the post-transformed & clipped verts.
1334 #if 0 // never used (DaveM)
1335 vbufdesc
.dwSize
= sizeof(D3DVERTEXBUFFERDESC
);
1336 vbufdesc
.dwCaps
= D3DVBCAPS_WRITEONLY
;
1337 if (glb
.bHardware
== FALSE
)
1338 vbufdesc
.dwCaps
= D3DVBCAPS_SYSTEMMEMORY
;
1339 vbufdesc
.dwNumVertices
= 32768; // For the time being
1341 // Source vertex buffer
1342 vbufdesc
.dwFVF
= DGL_LVERTEX
;
1343 hResult
= IDirect3D3_CreateVertexBuffer(lpCtx
->lpD3D3
, &vbufdesc
, &lpCtx
->m_vbuf
, 0, NULL
);
1344 if (FAILED(hResult
)) {
1345 ddlogError(DDLOG_CRITICAL_OR_WARN
, "CreateVertexBuffer(src) failed", hResult
);
1346 goto return_with_error
;
1349 // Destination vertex buffer
1350 vbufdesc
.dwFVF
= (glb
.bMultitexture
== FALSE
) ? D3DFVF_TLVERTEX
: (D3DFVF_XYZRHW
| D3DFVF_DIFFUSE
| D3DFVF_TEX2
);
1351 hResult
= IDirect3D3_CreateVertexBuffer(lpCtx
->lpD3D3
, &vbufdesc
, &lpCtx
->m_pvbuf
, 0, NULL
);
1352 if(FAILED(hResult
)) {
1353 ddlogError(DDLOG_CRITICAL_OR_WARN
, "CreateVertexBuffer(dst) failed", hResult
);
1354 goto return_with_error
;
1358 #endif _USE_GLD3_WGL
1361 // Now create the Mesa context
1364 // Create the Mesa visual
1365 if (lpPFD
->cDepthBits
)
1367 if (lpPFD
->cStencilBits
)
1369 if (lpPFD
->cAlphaBits
) {
1373 if (lpPFD
->dwFlags
& PFD_DOUBLEBUFFER
)
1375 // lpCtx->EmulateSingle =
1376 // (lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? FALSE : TRUE;
1378 #ifdef _USE_GLD3_WGL
1379 lpCtx
->glVis
= _mesa_create_visual(
1380 GL_TRUE
, // RGB mode
1381 bDouble
, /* double buffer */
1390 lpPFD
->cAccumRedBits
, // accum bits
1391 lpPFD
->cAccumGreenBits
, // accum bits
1392 lpPFD
->cAccumBlueBits
, // accum bits
1393 lpPFD
->cAccumAlphaBits
, // accum alpha bits
1396 #else // _USE_GLD3_WGL
1397 lpCtx
->glVis
= (*mesaFuncs
.gl_create_visual
)(
1398 GL_TRUE
, // RGB mode
1399 bAlphaSW
, // Is an alpha buffer required?
1400 bDouble
, // Is an double-buffering required?
1402 dwDepthBits
, // depth_size
1403 dwStencilBits
, // stencil_size
1404 lpPFD
->cAccumBits
, // accum_size
1405 0, // colour-index bits
1406 lpPFD
->cRedBits
, // Red bit count
1407 lpPFD
->cGreenBits
, // Green bit count
1408 lpPFD
->cBlueBits
, // Blue bit count
1409 dwAlphaBits
// Alpha bit count
1411 #endif // _USE_GLD3_WGL
1413 if (lpCtx
->glVis
== NULL
) {
1414 ddlogMessage(DDLOG_CRITICAL_OR_WARN
, "gl_create_visual failed\n");
1415 goto return_with_error
;
1418 #ifdef _USE_GLD3_WGL
1419 lpCtx
->glCtx
= _mesa_create_context(lpCtx
->glVis
, NULL
, (void *)lpCtx
, GL_TRUE
);
1421 // Create the Mesa context
1422 lpCtx
->glCtx
= (*mesaFuncs
.gl_create_context
)(
1423 lpCtx
->glVis
, // Mesa visual
1424 NULL
, // share list context
1425 (void *)lpCtx
, // Pointer to our driver context
1426 GL_TRUE
// Direct context flag
1428 #endif // _USE_GLD3_WGL
1430 if (lpCtx
->glCtx
== NULL
) {
1431 ddlogMessage(DDLOG_CRITICAL_OR_WARN
, "gl_create_context failed\n");
1432 goto return_with_error
;
1435 // Create the Mesa framebuffer
1436 #ifdef _USE_GLD3_WGL
1437 lpCtx
->glBuffer
= _mesa_create_framebuffer(
1439 lpCtx
->glVis
->depthBits
> 0,
1440 lpCtx
->glVis
->stencilBits
> 0,
1441 lpCtx
->glVis
->accumRedBits
> 0,
1445 lpCtx
->glBuffer
= (*mesaFuncs
.gl_create_framebuffer
)(lpCtx
->glVis
);
1446 #endif // _USE_GLD3_WGL
1448 if (lpCtx
->glBuffer
== NULL
) {
1449 ddlogMessage(DDLOG_CRITICAL_OR_WARN
, "gl_create_framebuffer failed\n");
1450 goto return_with_error
;
1453 #ifdef _USE_GLD3_WGL
1454 // Init Mesa internals
1455 _swrast_CreateContext( lpCtx
->glCtx
);
1456 _ac_CreateContext( lpCtx
->glCtx
);
1457 _tnl_CreateContext( lpCtx
->glCtx
);
1458 _swsetup_CreateContext( lpCtx
->glCtx
);
1460 _gldDriver
.InitialiseMesa(lpCtx
);
1462 lpCtx
->glCtx
->imports
.warning
= _gld_mesa_warning
;
1463 lpCtx
->glCtx
->imports
.fatal
= _gld_mesa_fatal
;
1466 // Tell Mesa how many texture stages we have
1467 glb
.wMaxSimultaneousTextures
= lpCtx
->D3DDevDesc
.wMaxSimultaneousTextures
;
1468 // Only use as many Units as the spec requires
1469 if (glb
.wMaxSimultaneousTextures
> MAX_TEXTURE_UNITS
)
1470 glb
.wMaxSimultaneousTextures
= MAX_TEXTURE_UNITS
;
1471 lpCtx
->glCtx
->Const
.MaxTextureUnits
= glb
.wMaxSimultaneousTextures
;
1472 ddlogPrintf(DDLOG_INFO
, "Texture stages : %d", glb
.wMaxSimultaneousTextures
);
1474 // Set the max texture size.
1475 // NOTE: clamped to a max of 1024 for extra performance!
1476 lpCtx
->dwMaxTextureSize
= (lpCtx
->D3DDevDesc
.dwMaxTextureWidth
<= 1024) ? lpCtx
->D3DDevDesc
.dwMaxTextureWidth
: 1024;
1478 // Texture resize takes place elsewhere. KH
1479 // NOTE: This was added to workaround an issue with the Intel app.
1481 lpCtx
->glCtx
->Const
.MaxTextureSize
= lpCtx
->dwMaxTextureSize
;
1483 lpCtx
->glCtx
->Const
.MaxTextureSize
= 1024;
1486 // Setup the Display Driver pointers
1487 dglSetupDDPointers(lpCtx
->glCtx
);
1489 // Initialise all the Direct3D renderstates
1490 dglInitStateD3D(lpCtx
->glCtx
);
1493 // Signal a reload of texture state on next glBegin
1494 lpCtx
->m_texHandleValid
= FALSE
;
1495 lpCtx
->m_mtex
= FALSE
;
1496 lpCtx
->m_texturing
= FALSE
;
1498 // Set default texture unit state
1499 // dglSetTexture(lpCtx, 0, NULL);
1500 // dglSetTexture(lpCtx, 1, NULL);
1504 // Set the global texture palette to default values.
1507 // Clear the entire palette
1508 ZeroMemory(ppe
, sizeof(PALETTEENTRY
) * 256);
1510 // Fill the palette with a default colour.
1511 // A garish colour is used to catch bugs. Here Magenta is used.
1512 for (i
=0; i
< 256; i
++) {
1515 ppe
[i
].peBlue
= 255;
1518 RELEASE(lpCtx
->lpGlobalPalette
);
1520 if (glb
.bDirectDrawPersistant
&& glb
.bPersistantBuffers
&& glb
.lpGlobalPalette
)
1521 hResult
= IDirectDrawPalette_AddRef(lpCtx
->lpGlobalPalette
= glb
.lpGlobalPalette
);
1523 hResult
= IDirectDraw4_CreatePalette(
1525 DDPCAPS_INITIALIZE
| DDPCAPS_8BIT
| DDPCAPS_ALLOW256
,
1527 &(lpCtx
->lpGlobalPalette
),
1529 if (FAILED(hResult
)) {
1530 ddlogError(DDLOG_ERROR
, "Default CreatePalette failed\n", hResult
);
1531 lpCtx
->lpGlobalPalette
= NULL
;
1532 goto return_with_error
;
1534 if (glb
.bDirectDrawPersistant
&& glb
.bPersistantBuffers
&& !glb
.lpGlobalPalette
)
1535 IDirectDrawPalette_AddRef(glb
.lpGlobalPalette
= lpCtx
->lpGlobalPalette
);
1537 #endif // _USE_GLD3_WGL
1539 // ** If we have made it to here then we can enable rendering **
1540 lpCtx
->bCanRender
= TRUE
;
1542 // ddlogMessage(DDLOG_SYSTEM, "dglCreateContextBuffers succeded\n");
1545 // Release serialized access
1546 if (glb
.bMultiThreaded
)
1547 LeaveCriticalSection(&CriticalSection
);
1553 // Clean up before returning.
1554 // This is critical for secondary devices.
1556 lpCtx
->bCanRender
= FALSE
;
1558 #ifdef _USE_GLD3_WGL
1559 // Destroy the Mesa context
1560 if (lpCtx
->glBuffer
)
1561 _mesa_destroy_framebuffer(lpCtx
->glBuffer
);
1563 _mesa_destroy_context(lpCtx
->glCtx
);
1565 _mesa_destroy_visual(lpCtx
->glVis
);
1567 // Destroy driver data
1568 _gldDriver
.DestroyDrawable(lpCtx
);
1570 // Destroy the Mesa context
1571 if (lpCtx
->glBuffer
)
1572 (*mesaFuncs
.gl_destroy_framebuffer
)(lpCtx
->glBuffer
);
1574 (*mesaFuncs
.gl_destroy_context
)(lpCtx
->glCtx
);
1576 (*mesaFuncs
.gl_destroy_visual
)(lpCtx
->glVis
);
1578 RELEASE(lpCtx
->m_pvbuf
); // Release D3D vertex buffer
1579 RELEASE(lpCtx
->m_vbuf
); // Release D3D vertex buffer
1581 if (lpCtx
->lpViewport3
) {
1582 if (lpCtx
->lpDev3
) IDirect3DDevice3_DeleteViewport(lpCtx
->lpDev3
, lpCtx
->lpViewport3
);
1583 RELEASE(lpCtx
->lpViewport3
);
1584 lpCtx
->lpViewport3
= NULL
;
1587 RELEASE(lpCtx
->lpDev3
);
1588 if (lpCtx
->lpDepth4
) {
1590 IDirectDrawSurface4_DeleteAttachedSurface(lpCtx
->lpBack4
, 0L, lpCtx
->lpDepth4
);
1592 IDirectDrawSurface4_DeleteAttachedSurface(lpCtx
->lpFront4
, 0L, lpCtx
->lpDepth4
);
1593 RELEASE(lpCtx
->lpDepth4
);
1594 lpCtx
->lpDepth4
= NULL
;
1596 RELEASE(lpCtx
->lpBack4
);
1597 RELEASE(lpCtx
->lpFront4
);
1599 if (lpCtx
->bFullscreen
) {
1600 IDirectDraw4_RestoreDisplayMode(lpCtx
->lpDD4
);
1601 IDirectDraw4_SetCooperativeLevel(lpCtx
->lpDD4
, NULL
, DDSCL_NORMAL
);
1603 RELEASE(lpCtx
->lpD3D3
);
1604 RELEASE(lpCtx
->lpDD4
);
1605 RELEASE(lpCtx
->lpDD1
);
1606 #endif // _USE_GLD3_WGL
1608 lpCtx
->bAllocated
= FALSE
;
1611 // Release serialized access
1612 if (glb
.bMultiThreaded
)
1613 LeaveCriticalSection(&CriticalSection
);
1618 #undef DDLOG_CRITICAL_OR_WARN
1621 // ***********************************************************************
1623 HGLRC
dglCreateContext(
1625 const DGL_pixelFormat
*lpPF
)
1630 static BOOL bWarnOnce
= TRUE
;
1631 DWORD dwThreadId
= GetCurrentThreadId();
1640 // Is context state ready ?
1644 ddlogPrintf(DDLOG_SYSTEM
, "dglCreateContext for HDC=%X, ThreadId=%X", a
, dwThreadId
);
1646 // Find next free context.
1647 // Also ensure that only one Fullscreen context is created at any one time.
1648 hGLRC
= 0; // Default to Not Found
1649 for (i
=0; i
<DGL_MAX_CONTEXTS
; i
++) {
1650 if (ctxlist
[i
].bAllocated
) {
1651 if (/*glb.bFullscreen && */ctxlist
[i
].bFullscreen
)
1654 hGLRC
= (HGLRC
)(i
+1);
1659 // Bail if no GLRC was found
1663 // Set the context pointer
1664 lpCtx
= dglGetContextAddress(hGLRC
);
1665 // Make sure that context is zeroed before we do anything.
1666 // MFC and C++ apps call wglCreateContext() and wglDeleteContext() multiple times,
1667 // even though only one context is ever used by the app, so keep it clean. (DaveM)
1668 ZeroMemory(lpCtx
, sizeof(DGL_ctx
));
1669 lpCtx
->bAllocated
= TRUE
;
1670 // Flag that buffers need creating on next wglMakeCurrent call.
1671 lpCtx
->bHasBeenCurrent
= FALSE
;
1672 lpCtx
->lpPF
= (DGL_pixelFormat
*)lpPF
; // cache pixel format
1673 lpCtx
->bCanRender
= FALSE
;
1675 // Create all the internal resources here, not in dglMakeCurrent().
1676 // We do a re-size check in dglMakeCurrent in case of re-allocations. (DaveM)
1677 // We now try context allocations twice, first with video memory,
1678 // then again with system memory. This is similar to technique
1679 // used for dglWglResizeBuffers(). (DaveM)
1680 if (lpCtx
->bHasBeenCurrent
== FALSE
) {
1681 if (!dglCreateContextBuffers(a
, lpCtx
, FALSE
)) {
1682 if (glb
.bMessageBoxWarnings
&& bWarnOnce
&& dwLogging
) {
1684 switch (nContextError
) {
1685 case GLDERR_DDRAW
: strcpy(szMsg
, szDDrawWarning
); break;
1686 case GLDERR_D3D
: strcpy(szMsg
, szD3DWarning
); break;
1687 case GLDERR_MEM
: strcpy(szMsg
, szResourceWarning
); break;
1688 case GLDERR_BPP
: strcpy(szMsg
, szBPPWarning
); break;
1689 default: strcpy(szMsg
, "");
1692 MessageBox(NULL
, szMsg
, "GLDirect", MB_OK
| MB_ICONWARNING
);
1694 // Only need to try again if memory error
1695 if (nContextError
== GLDERR_MEM
) {
1696 ddlogPrintf(DDLOG_WARN
, "dglCreateContext failed 1st time with video memory");
1699 ddlogPrintf(DDLOG_ERROR
, "dglCreateContext failed");
1705 // Now that we have a hWnd, we can intercept the WindowProc.
1708 // Only hook individual window handler once if not hooked before.
1709 lpfnWndProc
= GetWindowLong(hWnd
, GWL_WNDPROC
);
1710 if (lpfnWndProc
!= (LONG
)dglWndProc
) {
1711 lpCtx
->lpfnWndProc
= lpfnWndProc
;
1712 SetWindowLong(hWnd
, GWL_WNDPROC
, (LONG
)dglWndProc
);
1714 // Find the parent window of the app too.
1715 if (glb
.hWndActive
== NULL
) {
1716 while (hWnd
!= NULL
) {
1717 glb
.hWndActive
= hWnd
;
1718 hWnd
= GetParent(hWnd
);
1720 // Hook the parent window too.
1721 lpfnWndProc
= GetWindowLong(glb
.hWndActive
, GWL_WNDPROC
);
1722 if (glb
.hWndActive
== lpCtx
->hWnd
)
1723 glb
.lpfnWndProc
= lpCtx
->lpfnWndProc
;
1724 else if (lpfnWndProc
!= (LONG
)dglWndProc
)
1725 glb
.lpfnWndProc
= lpfnWndProc
;
1726 if (glb
.lpfnWndProc
)
1727 SetWindowLong(glb
.hWndActive
, GWL_WNDPROC
, (LONG
)dglWndProc
);
1731 ddlogPrintf(DDLOG_SYSTEM
, "dglCreateContext succeeded for HGLRC=%d", (int)hGLRC
);
1736 // ***********************************************************************
1737 // Make a DirectGL context current
1738 // Used by wgl functions and dgl functions
1739 BOOL
dglMakeCurrent(
1746 BOOL bNeedResize
= FALSE
;
1747 BOOL bWindowChanged
, bContextChanged
;
1748 LPDIRECTDRAWCLIPPER lpddClipper
;
1749 DWORD dwThreadId
= GetCurrentThreadId();
1756 // Is context state ready ?
1760 context
= (int)b
; // This is as a result of STRICT!
1761 ddlogPrintf(DDLOG_SYSTEM
, "dglMakeCurrent: HDC=%X, HGLRC=%d, ThreadId=%X", a
, context
, dwThreadId
);
1763 // If the HGLRC is NULL then make no context current;
1764 // Ditto if the HDC is NULL either. (DaveM)
1765 if (context
== 0 || a
== 0) {
1766 // Corresponding Mesa operation
1767 #ifdef _USE_GLD3_WGL
1768 _mesa_make_current(NULL
, NULL
);
1770 (*mesaFuncs
.gl_make_current
)(NULL
, NULL
);
1772 dglSetCurrentContext(0);
1776 // Make sure the HGLRC is in range
1777 if ((context
> DGL_MAX_CONTEXTS
) || (context
< 0)) {
1778 ddlogMessage(DDLOG_ERROR
, "dglMakeCurrent: HGLRC out of range\n");
1782 // Find address of context and make sure that it has been allocated
1783 lpCtx
= dglGetContextAddress(b
);
1784 if (!lpCtx
->bAllocated
) {
1785 ddlogMessage(DDLOG_ERROR
, "dglMakeCurrent: Context not allocated\n");
1787 return TRUE
; // HACK: Shuts up "WebLab Viewer Pro". KeithH
1791 // Serialize access to DirectDraw or DDS operations
1792 if (glb
.bMultiThreaded
)
1793 EnterCriticalSection(&CriticalSection
);
1796 // Check if window has changed
1797 hWnd
= (a
!= lpCtx
->hDC
) ? WindowFromDC(a
) : lpCtx
->hWnd
;
1798 bWindowChanged
= (hWnd
!= lpCtx
->hWnd
) ? TRUE
: FALSE
;
1799 bContextChanged
= (b
!= dglGetCurrentContext()) ? TRUE
: FALSE
;
1801 // If the window has changed, make sure the clipper is updated. (DaveM)
1802 if (glb
.bDirectDrawPersistant
&& !lpCtx
->bFullscreen
&& (bWindowChanged
|| bContextChanged
)) {
1804 #ifndef _USE_GLD3_WGL
1805 IDirectDrawSurface4_GetClipper(lpCtx
->lpFront4
, &lpddClipper
);
1806 IDirectDrawClipper_SetHWnd(lpddClipper
, 0, lpCtx
->hWnd
);
1807 IDirectDrawClipper_Release(lpddClipper
);
1808 #endif // _USE_GLD3_WGL
1811 // Make sure hDC and hWnd is current. (DaveM)
1812 // Obtain the dimensions of the rendering window
1813 lpCtx
->hDC
= a
; // Cache DC
1815 hWndLastActive
= hWnd
;
1817 // Check for non-window DC = memory DC ?
1819 if (GetClipBox(a
, &lpCtx
->rcScreenRect
) == ERROR
) {
1820 ddlogMessage(DDLOG_WARN
, "GetClipBox failed in dglMakeCurrent\n");
1821 SetRect(&lpCtx
->rcScreenRect
, 0, 0, 0, 0);
1824 else if (!GetClientRect(lpCtx
->hWnd
, &lpCtx
->rcScreenRect
)) {
1825 ddlogMessage(DDLOG_WARN
, "GetClientRect failed in dglMakeCurrent\n");
1826 SetRect(&lpCtx
->rcScreenRect
, 0, 0, 0, 0);
1828 // Check if buffers need to be re-sized;
1829 // If so, wait until Mesa GL stuff is setup before re-sizing;
1830 if (lpCtx
->dwWidth
!= lpCtx
->rcScreenRect
.right
- lpCtx
->rcScreenRect
.left
||
1831 lpCtx
->dwHeight
!= lpCtx
->rcScreenRect
.bottom
- lpCtx
->rcScreenRect
.top
)
1834 // Now we can update our globals
1835 dglSetCurrentContext(b
);
1837 // Corresponding Mesa operation
1838 #ifdef _USE_GLD3_WGL
1839 _mesa_make_current(lpCtx
->glCtx
, lpCtx
->glBuffer
);
1840 lpCtx
->glCtx
->Driver
.UpdateState(lpCtx
->glCtx
, _NEW_ALL
);
1842 // Resize buffers (Note Mesa GL needs to be setup beforehand);
1843 // Resize Mesa internal buffer too via glViewport() command,
1844 // which subsequently calls dglWglResizeBuffers() too.
1845 lpCtx
->glCtx
->Driver
.Viewport(lpCtx
->glCtx
, 0, 0, lpCtx
->dwWidth
, lpCtx
->dwHeight
);
1846 lpCtx
->bHasBeenCurrent
= TRUE
;
1849 (*mesaFuncs
.gl_make_current
)(lpCtx
->glCtx
, lpCtx
->glBuffer
);
1851 dglSetupDDPointers(lpCtx
->glCtx
);
1853 // Insure DirectDraw surfaces fit current window DC
1855 // Resize buffers (Note Mesa GL needs to be setup beforehand);
1856 // Resize Mesa internal buffer too via glViewport() command,
1857 // which subsequently calls dglWglResizeBuffers() too.
1858 (*mesaFuncs
.gl_Viewport
)(lpCtx
->glCtx
, 0, 0, lpCtx
->dwWidth
, lpCtx
->dwHeight
);
1859 lpCtx
->bHasBeenCurrent
= TRUE
;
1861 #endif // _USE_GLD3_WGL
1862 ddlogPrintf(DDLOG_SYSTEM
, "dglMakeCurrent: width = %d, height = %d", lpCtx
->dwWidth
, lpCtx
->dwHeight
);
1864 // We have to clear D3D back buffer and render state if emulated front buffering
1865 // for different window (but not context) like in Solid Edge.
1866 if (glb
.bDirectDrawPersistant
&& glb
.bPersistantBuffers
1867 && (bWindowChanged
/* || bContextChanged */) && lpCtx
->EmulateSingle
) {
1868 #ifdef _USE_GLD3_WGL
1869 // IDirect3DDevice8_EndScene(lpCtx->pDev);
1870 // lpCtx->bSceneStarted = FALSE;
1871 lpCtx
->glCtx
->Driver
.Clear(lpCtx
->glCtx
, GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
,
1872 GL_TRUE
, 0, 0, lpCtx
->dwWidth
, lpCtx
->dwHeight
);
1874 IDirect3DDevice3_EndScene(lpCtx
->lpDev3
);
1875 lpCtx
->bSceneStarted
= FALSE
;
1876 dglClearD3D(lpCtx
->glCtx
, GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
,
1877 GL_TRUE
, 0, 0, lpCtx
->dwWidth
, lpCtx
->dwHeight
);
1878 #endif // _USE_GLD3_WGL
1881 // The first time we call MakeCurrent we set the initial viewport size
1882 if (lpCtx
->bHasBeenCurrent
== FALSE
)
1883 #ifdef _USE_GLD3_WGL
1884 lpCtx
->glCtx
->Driver
.Viewport(lpCtx
->glCtx
, 0, 0, lpCtx
->dwWidth
, lpCtx
->dwHeight
);
1886 (*mesaFuncs
.gl_Viewport
)(lpCtx
->glCtx
, 0, 0, lpCtx
->dwWidth
, lpCtx
->dwHeight
);
1887 #endif // _USE_GLD3_WGL
1888 lpCtx
->bHasBeenCurrent
= TRUE
;
1891 // Release serialized access
1892 if (glb
.bMultiThreaded
)
1893 LeaveCriticalSection(&CriticalSection
);
1899 // ***********************************************************************
1901 BOOL
dglDeleteContext(
1905 DWORD dwThreadId
= GetCurrentThreadId();
1908 #if 0 // We have enough trouble throwing exceptions as it is... (DaveM)
1914 // Is context state ready ?
1918 ddlogPrintf(DDLOG_SYSTEM
, "dglDeleteContext: Deleting context HGLRC=%d, ThreadId=%X", (int)a
, dwThreadId
);
1920 // Make sure the HGLRC is in range
1921 if (((int) a
> DGL_MAX_CONTEXTS
) || ((int)a
< 0)) {
1922 ddlogMessage(DDLOG_ERROR
, "dglDeleteCurrent: HGLRC out of range\n");
1926 // Make sure context is valid
1927 lpCtx
= dglGetContextAddress(a
);
1928 if (!lpCtx
->bAllocated
) {
1929 ddlogPrintf(DDLOG_WARN
, "Tried to delete unallocated context HGLRC=%d", (int)a
);
1931 return TRUE
; // HACK: Shuts up "WebLab Viewer Pro". KeithH
1934 // Make sure context is de-activated
1935 if (a
== dglGetCurrentContext()) {
1936 ddlogPrintf(DDLOG_WARN
, "dglDeleteContext: context HGLRC=%d still active", (int)a
);
1937 dglMakeCurrent(NULL
, NULL
);
1941 // Serialize access to DirectDraw or DDS operations
1942 if (glb
.bMultiThreaded
)
1943 EnterCriticalSection(&CriticalSection
);
1946 // We are about to destroy all Direct3D objects.
1947 // Therefore we must disable rendering
1948 lpCtx
->bCanRender
= FALSE
;
1950 // This exception handler was installed to catch some
1951 // particularly nasty apps. Console apps that call exit()
1952 // fall into this catagory (i.e. Win32 Glut).
1954 // VC cannot successfully implement multiple exception handlers
1955 // if more than one exception occurs. Therefore reverting back to
1956 // single exception handler as Keith originally had it. (DaveM)
1958 #define WARN_MESSAGE(p) strcpy(argstr, (#p));
1959 #define SAFE_RELEASE(p) WARN_MESSAGE(p); RELEASE(p);
1962 #ifdef _USE_GLD3_WGL
1963 WARN_MESSAGE(gl_destroy_framebuffer
);
1964 if (lpCtx
->glBuffer
)
1965 _mesa_destroy_framebuffer(lpCtx
->glBuffer
);
1966 WARN_MESSAGE(gl_destroy_context
);
1968 _mesa_destroy_context(lpCtx
->glCtx
);
1969 WARN_MESSAGE(gl_destroy_visual
);
1971 _mesa_destroy_visual(lpCtx
->glVis
);
1973 _gldDriver
.DestroyDrawable(lpCtx
);
1975 // Destroy the Mesa context
1976 WARN_MESSAGE(gl_destroy_framebuffer
);
1977 if (lpCtx
->glBuffer
)
1978 (*mesaFuncs
.gl_destroy_framebuffer
)(lpCtx
->glBuffer
);
1979 WARN_MESSAGE(gl_destroy_context
);
1981 (*mesaFuncs
.gl_destroy_context
)(lpCtx
->glCtx
);
1982 WARN_MESSAGE(gl_destroy_visual
);
1984 (*mesaFuncs
.gl_destroy_visual
)(lpCtx
->glVis
);
1986 SAFE_RELEASE(lpCtx
->m_pvbuf
); // release D3D vertex buffer
1987 SAFE_RELEASE(lpCtx
->m_vbuf
); // release D3D vertex buffer
1989 // Delete the global palette
1990 SAFE_RELEASE(lpCtx
->lpGlobalPalette
);
1993 if (lpCtx
->lpViewport3
) {
1994 if (lpCtx
->lpDev3
) IDirect3DDevice3_DeleteViewport(lpCtx
->lpDev3
, lpCtx
->lpViewport3
);
1995 SAFE_RELEASE(lpCtx
->lpViewport3
);
1996 lpCtx
->lpViewport3
= NULL
;
1999 SAFE_RELEASE(lpCtx
->lpDev3
);
2000 if (lpCtx
->lpDepth4
) {
2002 IDirectDrawSurface4_DeleteAttachedSurface(lpCtx
->lpBack4
, 0L, lpCtx
->lpDepth4
);
2004 IDirectDrawSurface4_DeleteAttachedSurface(lpCtx
->lpFront4
, 0L, lpCtx
->lpDepth4
);
2005 SAFE_RELEASE(lpCtx
->lpDepth4
);
2006 lpCtx
->lpDepth4
= NULL
;
2008 SAFE_RELEASE(lpCtx
->lpBack4
);
2009 SAFE_RELEASE(lpCtx
->lpFront4
);
2010 if (lpCtx
->bFullscreen
) {
2011 IDirectDraw4_RestoreDisplayMode(lpCtx
->lpDD4
);
2012 IDirectDraw4_SetCooperativeLevel(lpCtx
->lpDD4
, NULL
, DDSCL_NORMAL
);
2014 SAFE_RELEASE(lpCtx
->lpD3D3
);
2015 SAFE_RELEASE(lpCtx
->lpDD4
);
2016 SAFE_RELEASE(lpCtx
->lpDD1
);
2017 #endif // _ULSE_GLD3_WGL
2020 __except(EXCEPTION_EXECUTE_HANDLER
) {
2021 ddlogPrintf(DDLOG_WARN
, "Exception raised in dglDeleteContext: %s", argstr
);
2024 // Restore the window message handler because this context may be used
2025 // again by another window with a *different* message handler. (DaveM)
2026 if (lpCtx
->lpfnWndProc
) {
2027 SetWindowLong(lpCtx
->hWnd
, GWL_WNDPROC
, (LONG
)lpCtx
->lpfnWndProc
);
2028 lpCtx
->lpfnWndProc
= (LONG
)NULL
;
2031 lpCtx
->bAllocated
= FALSE
; // This context is now free for use
2034 // Release serialized access
2035 if (glb
.bMultiThreaded
)
2036 LeaveCriticalSection(&CriticalSection
);
2042 // ***********************************************************************
2044 BOOL
dglSwapBuffers(
2047 RECT rSrcRect
; // Source rectangle
2048 RECT rDstRect
; // Destination rectangle
2056 // DWORD dwThreadId = GetCurrentThreadId();
2057 HGLRC hGLRC
= dglGetCurrentContext();
2058 DGL_ctx
*lpCtx
= dglGetContextAddress(hGLRC
);
2061 HDC hDCAux
; // for memory DC
2062 int x
,y
,w
,h
; // for memory DC BitBlt
2064 #if 0 // Perhaps not a good idea. Called too often. KH
2071 return TRUE
; //FALSE; // No current context
2074 if (!lpCtx
->bCanRender
) {
2075 // Don't return false else some apps will bail.
2080 if (hDC
!= lpCtx
->hDC
) {
2081 ddlogPrintf(DDLOG_WARN
, "dglSwapBuffers: HDC=%X does not match HDC=%X for HGLRC=%d", hDC
, lpCtx
->hDC
, hGLRC
);
2082 hWnd
= WindowFromDC(hDC
);
2085 #ifndef _USE_GLD3_WGL
2086 // Ensure that the surfaces exist before we tell
2087 // the device to render to them.
2088 IDirectDraw4_RestoreAllSurfaces(lpCtx
->lpDD4
);
2090 // Make sure that the vertex caches have been emptied
2091 // dglStateChange(lpCtx);
2093 // Some OpenGL programs don't issue a glFinish - check for it here.
2094 if (lpCtx
->bSceneStarted
) {
2095 IDirect3DDevice3_EndScene(lpCtx
->lpDev3
);
2096 lpCtx
->bSceneStarted
= FALSE
;
2101 // If the calling app is not active then we don't need to Blit/Flip.
2102 // We can therefore simply return TRUE.
2103 if (!glb
.bAppActive
)
2105 // Addendum: This is WRONG! We should bail if the app is *minimized*,
2106 // not merely if the app is just plain 'not active'.
2107 // KeithH, 27/May/2000.
2110 // Check for non-window DC = memory DC ?
2112 if (GetClipBox(hDC
, &rSrcRect
) == ERROR
)
2114 // Use GDI BitBlt instead from compatible DirectDraw DC
2117 w
= rSrcRect
.right
- rSrcRect
.left
;
2118 h
= rSrcRect
.bottom
- rSrcRect
.top
;
2120 // Ack. DX8 does not have a GetDC() function...
2121 // TODO: Defer to DX7 or DX9 drivers... (DaveM)
2125 // Bail if window client region is not drawable, like in Solid Edge
2126 if (!IsWindow(hWnd
) /* || !IsWindowVisible(hWnd) */ || !GetClientRect(hWnd
, &rSrcRect
))
2130 // Serialize access to DirectDraw or DDS operations
2131 if (glb
.bMultiThreaded
)
2132 EnterCriticalSection(&CriticalSection
);
2135 #ifdef _USE_GLD3_WGL
2136 // Notify Mesa of impending swap, so Mesa can flush internal buffers.
2137 _mesa_notifySwapBuffers(lpCtx
->glCtx
);
2138 // Now perform driver buffer swap
2139 _gldDriver
.SwapBuffers(lpCtx
, hDC
, hWnd
);
2141 if (lpCtx
->bFullscreen
) {
2142 // Sync with retrace if required
2143 if (glb
.bWaitForRetrace
) {
2144 IDirectDraw4_WaitForVerticalBlank(
2146 DDWAITVB_BLOCKBEGIN
,
2150 // Perform the fullscreen flip
2151 TRY(IDirectDrawSurface4_Flip(
2155 "dglSwapBuffers: Flip");
2157 // Calculate current window position and size
2159 ClientToScreen(hWnd
, &pt
);
2160 GetClientRect(hWnd
, &rDstRect
);
2161 if (rDstRect
.right
> lpCtx
->dwModeWidth
)
2162 rDstRect
.right
= lpCtx
->dwModeWidth
;
2163 if (rDstRect
.bottom
> lpCtx
->dwModeHeight
)
2164 rDstRect
.bottom
= lpCtx
->dwModeHeight
;
2165 OffsetRect(&rDstRect
, pt
.x
, pt
.y
);
2166 rSrcRect
.left
= rSrcRect
.top
= 0;
2167 rSrcRect
.right
= lpCtx
->dwWidth
;
2168 rSrcRect
.bottom
= lpCtx
->dwHeight
;
2169 if (rSrcRect
.right
> lpCtx
->dwModeWidth
)
2170 rSrcRect
.right
= lpCtx
->dwModeWidth
;
2171 if (rSrcRect
.bottom
> lpCtx
->dwModeHeight
)
2172 rSrcRect
.bottom
= lpCtx
->dwModeHeight
;
2174 if (glb
.bWaitForRetrace
) {
2175 // Sync the blit to the vertical retrace
2176 ZeroMemory(&bltFX
, sizeof(bltFX
));
2177 bltFX
.dwSize
= sizeof(bltFX
);
2178 bltFX
.dwDDFX
= DDBLTFX_NOTEARING
;
2179 dwBlitFlags
= DDBLT_WAIT
| DDBLT_DDFX
;
2182 dwBlitFlags
= DDBLT_WAIT
;
2186 // Perform the actual blit
2187 TRY(IDirectDrawSurface4_Blt(
2190 lpCtx
->lpBack4
, // Blit source
2194 "dglSwapBuffers: Blt");
2196 #endif // _USE_GLD3_WGL
2199 // Release serialized access
2200 if (glb
.bMultiThreaded
)
2201 LeaveCriticalSection(&CriticalSection
);
2204 // TODO: Re-instate rendering bitmap snapshot feature??? (DaveM)
2206 // Render frame is completed
2207 ValidateRect(hWnd
, NULL
);
2208 lpCtx
->bFrameStarted
= FALSE
;
2213 // ***********************************************************************