2
// This unit is part of the GLScene Engine https://github.com/glscene
5
Win32 specific Context.
8
11/09/11 - Yar - Added layers support (not tested because need Quadro or FireFX VGA)
9
18/07/11 - Yar - Added ability of creating OpenGL ES 2.0 profile context
10
03/12/10 - Yar - Fixed window tracking (thanks to Gabriel Corneanu)
11
04/11/10 - DaStr - Restored Delphi5 and Delphi6 compatibility
12
23/08/10 - Yar - Replaced OpenGL1x to OpenGLTokens. Improved context creation.
13
18/06/10 - Yar - Changed context sharing method for similarity to GLX
14
06/06/10 - Yar - Moved forward context creation to DoCreateContext
15
make outputDevice HWND type
16
19/05/10 - Yar - Added choice between hardware and software acceleration
17
06/05/10 - Yar - Added vLastVendor clearing when multithreading is enabled
18
06/04/10 - Yar - Added DoGetHandles to TGLWin32Context (thanks Rustam Asmandiarov aka Predator)
19
28/03/10 - Yar - Added 3.3 forward context creation and eliminate memory leaks when multithreading
20
06/03/10 - Yar - Added forward context creation in TGLWin32Context.DoActivate
21
20/02/10 - DanB - Allow double-buffered memory viewers, if you want single
22
buffered, or no swapping, then change buffer options instead.
23
Some changes from Cardinal to the appropriate HDC /HGLRC type.
24
15/01/10 - DaStr - Bugfixed TGLWin32Context.ChooseWGLFormat()
25
(BugtrackerID = 2933081) (thanks YarUndeoaker)
26
08/01/10 - DaStr - Added more AntiAliasing modes (thanks YarUndeoaker)
27
13/12/09 - DaStr - Modified for multithread support (thanks Controller)
28
30/08/09 - DanB - vIgnoreContextActivationFailures renamed to
29
vContextActivationFailureOccurred + check removed.
30
06/11/07 - mrqzzz - Ignore ContextActivation failure
31
if GLContext.vIgnoreContextActivationFailures=true
32
15/02/07 - DaStr - Integer -> Cardinal because $R- was removed in GLScene.pas
33
11/09/06 - NC - Added support for Multiple-Render-Target
34
03/10/04 - NC - Added float texture support
35
03/07/02 - EG - ChooseWGLFormat Kyro fix (Patrick Chevalley)
36
13/03/02 - EG - aaDefault now prefers non-AA when possible
37
03/03/02 - EG - Fixed aaNone mode (AA specifically off)
38
01/03/02 - EG - Fixed CurrentPixelFormatIsHardwareAccelerated
39
22/02/02 - EG - Unified ChooseWGLFormat for visual & non-visual
40
21/02/02 - EG - AntiAliasing support *experimental* (Chris N. Strahm)
41
05/02/02 - EG - Fixed UnTrackWindow
42
03/02/02 - EG - Added experimental Hook-based window tracking
43
29/01/02 - EG - Improved recovery for ICDs without pbuffer support
44
21/01/02 - EG - More graceful recovery for ICDs without pbuffer support
45
07/01/02 - EG - DoCreateMemoryContext now retrieved topDC when needed
46
15/12/01 - EG - Added support for AlphaBits
47
30/11/01 - EG - Hardware acceleration support now detected
48
20/11/01 - EG - New temp HWnd code for memory contexts (improved compat.)
49
04/09/01 - EG - Added ChangeIAttrib, support for 16bits depth buffer
50
25/08/01 - EG - Added pbuffer support and CreateMemoryContext interface
51
24/08/01 - EG - Fixed PropagateSharedContext
52
12/08/01 - EG - Handles management completed
53
22/07/01 - EG - Creation (glcontext.omm)
62
{$IFNDEF MSWINDOWS}{$MESSAGE Error 'Unit is Windows specific'}{$ENDIF}
83
WGL_SWAP_MAIN_PLANE = $00000001;
84
WGL_SWAP_OVERLAY1 = $00000002;
85
WGL_SWAP_OVERLAY2 = $00000004;
86
WGL_SWAP_OVERLAY3 = $00000008;
87
WGL_SWAP_OVERLAY4 = $00000010;
88
WGL_SWAP_OVERLAY5 = $00000020;
89
WGL_SWAP_OVERLAY6 = $00000040;
90
WGL_SWAP_OVERLAY7 = $00000080;
91
WGL_SWAP_OVERLAY8 = $00000100;
92
WGL_SWAP_OVERLAY9 = $00000200;
93
WGL_SWAP_OVERLAY10 = $00000400;
94
WGL_SWAP_OVERLAY11 = $00000800;
95
WGL_SWAP_OVERLAY12 = $00001000;
96
WGL_SWAP_OVERLAY13 = $00002000;
97
WGL_SWAP_OVERLAY14 = $00004000;
98
WGL_SWAP_OVERLAY15 = $00008000;
99
WGL_SWAP_UNDERLAY1 = $00010000;
100
WGL_SWAP_UNDERLAY2 = $00020000;
101
WGL_SWAP_UNDERLAY3 = $00040000;
102
WGL_SWAP_UNDERLAY4 = $00080000;
103
WGL_SWAP_UNDERLAY5 = $00100000;
104
WGL_SWAP_UNDERLAY6 = $00200000;
105
WGL_SWAP_UNDERLAY7 = $00400000;
106
WGL_SWAP_UNDERLAY8 = $00800000;
107
WGL_SWAP_UNDERLAY9 = $01000000;
108
WGL_SWAP_UNDERLAY10 = $02000000;
109
WGL_SWAP_UNDERLAY11 = $04000000;
110
WGL_SWAP_UNDERLAY12 = $08000000;
111
WGL_SWAP_UNDERLAY13 = $10000000;
112
WGL_SWAP_UNDERLAY14 = $20000000;
113
WGL_SWAP_UNDERLAY15 = $40000000;
120
{ A context driver for standard Windows OpenGL (via MS OpenGL). }
121
TGLWin32Context = class(TGLContext)
126
FShareContext: TGLWin32Context;
128
FiAttribs: packed array of Integer;
129
FfAttribs: packed array of Single;
130
FLegacyContextsOnly: Boolean;
131
FSwapBufferSupported: Boolean;
133
procedure SpawnLegacyContext(aDC: HDC); // used for WGL_pixel_format soup
134
procedure CreateOldContext(aDC: HDC); dynamic;
135
procedure CreateNewContext(aDC: HDC); dynamic;
137
procedure ClearIAttribs;
138
procedure AddIAttrib(attrib, value: Integer);
139
procedure ChangeIAttrib(attrib, newValue: Integer);
140
procedure DropIAttrib(attrib: Integer);
141
procedure ClearFAttribs;
142
procedure AddFAttrib(attrib, value: Single);
144
procedure DestructionEarlyWarning(sender: TObject);
146
procedure ChooseWGLFormat(DC: HDC; nMaxFormats: Cardinal; piFormats:
147
PInteger; var nNumFormats: Integer; BufferCount: integer = 1);
148
procedure DoCreateContext(ADeviceHandle: HDC); override;
149
procedure DoCreateMemoryContext(outputDevice: HWND; width, height:
150
Integer; BufferCount: integer); override;
151
function DoShareLists(aContext: TGLContext): Boolean; override;
152
procedure DoDestroyContext; override;
153
procedure DoActivate; override;
154
procedure DoDeactivate; override;
155
{ DoGetHandles must be implemented in child classes,
156
and return the display + window }
158
procedure DoGetHandles(outputDevice: HWND; out XWin: HDC); virtual; abstract;
162
constructor Create; override;
163
destructor Destroy; override;
165
function IsValid: Boolean; override;
166
procedure SwapBuffers; override;
168
function RenderOutputDevice: Pointer; override;
170
property DC: HDC read FDC;
171
property RC: HGLRC read FRC;
176
strForwardContextFailed = 'Can not create forward compatible context: #%X, %s';
177
strBackwardContextFailed = 'Can not create backward compatible context: #%X, %s';
178
strFailHWRC = 'Unable to create rendering context with hardware acceleration - down to software';
179
strTmpRC_Created = 'Temporary rendering context created';
180
strDriverNotSupportFRC = 'Driver not support creating of forward context';
181
strDriverNotSupportOESRC = 'Driver not support creating of OpenGL ES 2.0 context';
182
strDriverNotSupportDebugRC = 'Driver not support creating of debug context';
183
strOESvsForwardRC = 'OpenGL ES 2.0 context incompatible with Forward context - flag ignored';
184
strFRC_created = 'Forward core context seccussfuly created';
185
strOESRC_created = 'OpenGL ES 2.0 context seccussfuly created';
186
strPBufferRC_created = 'Backward compatible core PBuffer context successfully created';
188
function CreateTempWnd: HWND;
191
{ This boolean controls a hook-based tracking of top-level forms destruction,
192
with the purpose of being able to properly release OpenGL contexts before
193
they are (improperly) released by some drivers upon top-level form
195
vUseWindowTrackingHook: Boolean = True;
197
// ------------------------------------------------------------------
198
// ------------------------------------------------------------------
199
// ------------------------------------------------------------------
201
// ------------------------------------------------------------------
202
// ------------------------------------------------------------------
203
// ------------------------------------------------------------------
207
vTrackingCount: Integer;
208
vTrackedHwnd: array of HWND;
209
vTrackedEvents: array of TNotifyEvent;
210
vTrackingHook: HHOOK;
215
function TrackHookProc(nCode: Integer; wParam: wParam; lParam: LPARAM): Integer;
221
if nCode = HC_ACTION then
223
p := PCWPStruct(lParam);
224
// if (p.message=WM_DESTROY) or (p.message=WM_CLOSE) then begin // destroy & close variant
225
if p.message = WM_DESTROY then
227
// special care must be taken by this loop, items may go away unexpectedly
228
i := vTrackingCount - 1;
231
if IsChild(p.hwnd, vTrackedHwnd[i]) then
233
// got one, send notification
234
vTrackedEvents[i](nil);
237
while i >= vTrackingCount do
241
CallNextHookEx(vTrackingHook, nCode, wParam, lParam);
245
Result := CallNextHookEx(vTrackingHook, nCode, wParam, lParam);
251
procedure TrackWindow(h: HWND; notifyEvent: TNotifyEvent);
253
if not IsWindow(h) then
255
if vTrackingCount = 0 then
256
vTrackingHook := SetWindowsHookEx(WH_CALLWNDPROC, @TrackHookProc, 0,
259
SetLength(vTrackedHwnd, vTrackingCount);
260
vTrackedHwnd[vTrackingCount - 1] := h;
261
SetLength(vTrackedEvents, vTrackingCount);
262
vTrackedEvents[vTrackingCount - 1] := notifyEvent;
268
procedure UnTrackWindow(h: HWND);
272
if not IsWindow(h) then
274
if vTrackingCount = 0 then
277
for i := 0 to MinInteger(vTrackingCount, Length(vTrackedHwnd)) - 1 do
279
if vTrackedHwnd[i] <> h then
283
vTrackedHwnd[k] := vTrackedHwnd[i];
284
vTrackedEvents[k] := vTrackedEvents[i];
289
if(k >= vTrackingCount) then exit;
291
SetLength(vTrackedHwnd, vTrackingCount);
292
SetLength(vTrackedEvents, vTrackingCount);
293
if vTrackingCount = 0 then
294
UnhookWindowsHookEx(vTrackingHook);
298
vUtilWindowClass: TWndClass = (
300
lpfnWndProc: @DefWindowProc;
308
lpszClassName: 'GLSUtilWindow');
313
function CreateTempWnd: HWND;
315
classRegistered: Boolean;
316
tempClass: TWndClass;
318
vUtilWindowClass.hInstance := HInstance;
319
classRegistered := GetClassInfo(HInstance, vUtilWindowClass.lpszClassName,
321
if not classRegistered then
322
Windows.RegisterClass(vUtilWindowClass);
323
Result := CreateWindowEx(WS_EX_TOOLWINDOW, vUtilWindowClass.lpszClassName,
324
'', WS_POPUP, 0, 0, 0, 0, 0, 0, HInstance, nil);
328
// ------------------ TGLWin32Context ------------------
334
constructor TGLWin32Context.Create;
344
destructor TGLWin32Context.Destroy;
352
function SetupPalette(DC: HDC; PFD: TPixelFormatDescriptor): HPalette;
355
LogPalette: TMaxLogPalette;
356
RedMask, GreenMask, BlueMask: Byte;
358
nColors := 1 shl Pfd.cColorBits;
359
LogPalette.palVersion := $300;
360
LogPalette.palNumEntries := nColors;
361
RedMask := (1 shl Pfd.cRedBits) - 1;
362
GreenMask := (1 shl Pfd.cGreenBits) - 1;
363
BlueMask := (1 shl Pfd.cBlueBits) - 1;
364
with LogPalette, PFD do
365
for I := 0 to nColors - 1 do
367
palPalEntry[I].peRed := (((I shr cRedShift) and RedMask) * 255) div
369
palPalEntry[I].peGreen := (((I shr cGreenShift) and GreenMask) * 255) div
371
palPalEntry[I].peBlue := (((I shr cBlueShift) and BlueMask) * 255) div
373
palPalEntry[I].peFlags := 0;
376
Result := CreatePalette(PLogPalette(@LogPalette)^);
379
SelectPalette(DC, Result, False);
389
procedure TGLWin32Context.ClearIAttribs;
391
SetLength(FiAttribs, 1);
398
procedure TGLWin32Context.AddIAttrib(attrib, value: Integer);
402
n := Length(FiAttribs);
403
SetLength(FiAttribs, n + 2);
404
FiAttribs[n - 1] := attrib;
405
FiAttribs[n] := value;
406
FiAttribs[n + 1] := 0;
412
procedure TGLWin32Context.ChangeIAttrib(attrib, newValue: Integer);
417
while i < Length(FiAttribs) do
419
if FiAttribs[i] = attrib then
421
FiAttribs[i + 1] := newValue;
426
AddIAttrib(attrib, newValue);
432
procedure TGLWin32Context.DropIAttrib(attrib: Integer);
437
while i < Length(FiAttribs) do
439
if FiAttribs[i] = attrib then
442
while i < Length(FiAttribs) do
444
FiAttribs[i - 2] := FiAttribs[i];
447
SetLength(FiAttribs, Length(FiAttribs) - 2);
457
procedure TGLWin32Context.ClearFAttribs;
459
SetLength(FfAttribs, 1);
466
procedure TGLWin32Context.AddFAttrib(attrib, value: Single);
470
n := Length(FfAttribs);
471
SetLength(FfAttribs, n + 2);
472
FfAttribs[n - 1] := attrib;
473
FfAttribs[n] := value;
474
FfAttribs[n + 1] := 0;
477
// DestructionEarlyWarning
480
procedure TGLWin32Context.DestructionEarlyWarning(sender: TObject);
488
procedure TGLWin32Context.ChooseWGLFormat(DC: HDC; nMaxFormats: Cardinal; piFormats:
489
PInteger; var nNumFormats: Integer; BufferCount: integer);
491
cAAToSamples: array[aaNone..csa16xHQ] of Integer =
492
(1, 2, 2, 4, 4, 6, 8, 16, 8, 8, 16, 16);
493
cCSAAToSamples: array[csa8x..csa16xHQ] of Integer = (4, 8, 4, 8);
495
procedure ChoosePixelFormat;
497
if not FGL.WChoosePixelFormatARB(DC, @FiAttribs[0], @FfAttribs[0],
498
32, PGLint(piFormats), @nNumFormats) then
506
// request hardware acceleration
507
case FAcceleration of
508
chaUnknown: AddIAttrib(WGL_ACCELERATION_ARB, WGL_GENERIC_ACCELERATION_ARB);
509
chaHardware: AddIAttrib(WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB);
510
chaSoftware: AddIAttrib(WGL_ACCELERATION_ARB, WGL_NO_ACCELERATION_ARB);
513
float := (ColorBits = 64) or (ColorBits = 128); // float_type
517
if GL.W_ATI_pixel_format_float then
518
begin // NV40 uses ATI_float, with linear filtering
519
AddIAttrib(WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_FLOAT_ATI);
523
AddIAttrib(WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB);
524
AddIAttrib(WGL_FLOAT_COMPONENTS_NV, GL_TRUE);
528
if BufferCount > 1 then
529
// 1 front buffer + (BufferCount-1) aux buffers
530
AddIAttrib(WGL_AUX_BUFFERS_ARB, BufferCount - 1);
532
AddIAttrib(WGL_COLOR_BITS_ARB, ColorBits);
533
if AlphaBits > 0 then
534
AddIAttrib(WGL_ALPHA_BITS_ARB, AlphaBits);
535
AddIAttrib(WGL_DEPTH_BITS_ARB, DepthBits);
536
if StencilBits > 0 then
537
AddIAttrib(WGL_STENCIL_BITS_ARB, StencilBits);
538
if AccumBits > 0 then
539
AddIAttrib(WGL_ACCUM_BITS_ARB, AccumBits);
540
if AuxBuffers > 0 then
541
AddIAttrib(WGL_AUX_BUFFERS_ARB, AuxBuffers);
542
if (AntiAliasing <> aaDefault) and GL.W_ARB_multisample then
544
if AntiAliasing = aaNone then
545
AddIAttrib(WGL_SAMPLE_BUFFERS_ARB, GL_FALSE)
548
AddIAttrib(WGL_SAMPLE_BUFFERS_ARB, GL_TRUE);
549
AddIAttrib(WGL_SAMPLES_ARB, cAAToSamples[AntiAliasing]);
550
if (AntiAliasing >= csa8x) and (AntiAliasing <= csa16xHQ) then
551
AddIAttrib(WGL_COLOR_SAMPLES_NV, cCSAAToSamples[AntiAliasing]);
558
if (nNumFormats = 0) and (DepthBits >= 32) then
560
// couldn't find 32+ bits depth buffer, 24 bits one available?
561
ChangeIAttrib(WGL_DEPTH_BITS_ARB, 24);
564
if (nNumFormats = 0) and (DepthBits >= 24) then
566
// couldn't find 24+ bits depth buffer, 16 bits one available?
567
ChangeIAttrib(WGL_DEPTH_BITS_ARB, 16);
570
if (nNumFormats = 0) and (ColorBits >= 24) then
572
// couldn't find 24+ bits color buffer, 16 bits one available?
573
ChangeIAttrib(WGL_COLOR_BITS_ARB, 16);
576
if (nNumFormats = 0) and (AntiAliasing <> aaDefault) then
579
ChangeIAttrib(WGL_DEPTH_BITS_ARB, DepthBits);
580
if (AntiAliasing >= csa8x) and (AntiAliasing <= csa16xHQ) then
582
DropIAttrib(WGL_COLOR_SAMPLES_NV);
584
csa8x, csa8xHQ: AntiAliasing := aa8x;
585
csa16x, csa16xHQ: AntiAliasing := aa16x;
587
ChangeIAttrib(WGL_SAMPLES_ARB, cAAToSamples[AntiAliasing]);
591
if nNumFormats = 0 then
598
// couldn't find AA buffer, try without
599
DropIAttrib(WGL_SAMPLE_BUFFERS_ARB);
600
DropIAttrib(WGL_SAMPLES_ARB);
604
ChangeIAttrib(WGL_SAMPLES_ARB, cAAToSamples[aa]);
606
until nNumFormats <> 0;
610
// Check DepthBits again
611
if (nNumFormats = 0) and (DepthBits >= 32) then
613
// couldn't find 32+ bits depth buffer, 24 bits one available?
614
ChangeIAttrib(WGL_DEPTH_BITS_ARB, 24);
617
if (nNumFormats = 0) and (DepthBits >= 24) then
619
// couldn't find 24+ bits depth buffer, 16 bits one available?
620
ChangeIAttrib(WGL_DEPTH_BITS_ARB, 16);
623
if (nNumFormats = 0) and (ColorBits >= 24) then
625
// couldn't find 24+ bits color buffer, 16 bits one available?
626
ChangeIAttrib(WGL_COLOR_BITS_ARB, 16);
629
if nNumFormats = 0 then
631
// ok, last attempt: no AA, restored depth and color,
632
// relaxed hardware-acceleration request
633
ChangeIAttrib(WGL_COLOR_BITS_ARB, ColorBits);
634
ChangeIAttrib(WGL_DEPTH_BITS_ARB, DepthBits);
635
DropIAttrib(WGL_ACCELERATION_ARB);
640
procedure TGLWin32Context.CreateOldContext(aDC: HDC);
642
if not FLegacyContextsOnly then
645
clUnderlay2: FRC := wglCreateLayerContext(aDC, -2);
646
clUnderlay1: FRC := wglCreateLayerContext(aDC, -1);
647
clMainPlane: FRC := wglCreateContext(aDC);
648
clOverlay1: FRC := wglCreateLayerContext(aDC, 1);
649
clOverlay2: FRC := wglCreateLayerContext(aDC, 2);
653
FRC := wglCreateContext(aDC);
659
if not wglMakeCurrent(FDC, FRC) then
660
raise EGLContext.Create(Format(strContextActivationFailed,
661
[GetLastError, SysErrorMessage(GetLastError)]));
663
if not FLegacyContextsOnly then
665
if Assigned(FShareContext) and (FShareContext.RC <> 0) then
667
if not wglShareLists(FShareContext.RC, FRC) then
669
GLSLogger.LogWarning(strFailedToShare)
673
FSharedContexts.Add(FShareContext);
674
PropagateSharedContext;
677
FGL.DebugMode := False;
680
// If we are using AntiAliasing, adjust filtering hints
681
if AntiAliasing in [aa2xHQ, aa4xHQ, csa8xHQ, csa16xHQ] then
682
// Hint for nVidia HQ modes (Quincunx etc.)
683
GLStates.MultisampleFilterHint := hintNicest
685
GLStates.MultisampleFilterHint := hintDontCare;
687
if rcoDebug in Options then
688
GLSLogger.LogWarning(strDriverNotSupportDebugRC);
689
if rcoOGL_ES in Options then
690
GLSLogger.LogWarning(strDriverNotSupportOESRC);
691
if GLStates.ForwardContext then
692
GLSLogger.LogWarning(strDriverNotSupportFRC);
693
GLStates.ForwardContext := False;
696
GLSLogger.LogInfo(strTmpRC_Created);
699
procedure TGLWin32Context.CreateNewContext(aDC: HDC);
701
bSuccess, bOES: Boolean;
708
// Initialize forward context
709
if GLStates.ForwardContext then
711
if FGL.VERSION_4_2 then
713
AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 4);
714
AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 2);
716
else if FGL.VERSION_4_1 then
718
AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 4);
719
AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 1);
721
else if FGL.VERSION_4_0 then
723
AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 4);
724
AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 0);
726
else if FGL.VERSION_3_3 then
728
AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 3);
729
AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 3);
731
else if FGL.VERSION_3_2 then
733
AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 3);
734
AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 2);
736
else if FGL.VERSION_3_1 then
738
AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 3);
739
AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 1);
741
else if FGL.VERSION_3_0 then
743
AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 3);
744
AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 0);
748
AddIAttrib(WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
749
if rcoOGL_ES in Options then
750
GLSLogger.LogWarning(strOESvsForwardRC);
752
else if rcoOGL_ES in Options then
754
if FGL.W_EXT_create_context_es2_profile then
756
AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 2);
757
AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 0);
758
AddIAttrib(WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_ES2_PROFILE_BIT_EXT);
762
GLSLogger.LogError(strDriverNotSupportOESRC);
765
if rcoDebug in Options then
767
AddIAttrib(WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB);
768
FGL.DebugMode := True;
772
clUnderlay2: AddIAttrib(WGL_CONTEXT_LAYER_PLANE_ARB, -2);
773
clUnderlay1: AddIAttrib(WGL_CONTEXT_LAYER_PLANE_ARB, -1);
774
clOverlay1: AddIAttrib(WGL_CONTEXT_LAYER_PLANE_ARB, 1);
775
clOverlay2: AddIAttrib(WGL_CONTEXT_LAYER_PLANE_ARB, 2);
779
if Assigned(FShareContext) then
781
FRC := FGL.WCreateContextAttribsARB(aDC, FShareContext.RC, @FiAttribs[0]);
784
FSharedContexts.Add(FShareContext);
785
PropagateSharedContext;
788
GLSLogger.LogWarning(strFailedToShare)
793
FRC := FGL.WCreateContextAttribsARB(aDC, 0, @FiAttribs[0]);
796
if GLStates.ForwardContext then
797
GLSLogger.LogErrorFmt(strForwardContextFailed,
798
[GetLastError, SysErrorMessage(GetLastError)])
800
GLSLogger.LogErrorFmt(strBackwardContextFailed,
801
[GetLastError, SysErrorMessage(GetLastError)]);
808
if not wglMakeCurrent(FDC, FRC) then
810
GLSLogger.LogErrorFmt(strContextActivationFailed,
811
[GetLastError, SysErrorMessage(GetLastError)]);
817
// If we are using AntiAliasing, adjust filtering hints
818
if AntiAliasing in [aa2xHQ, aa4xHQ, csa8xHQ, csa16xHQ] then
819
// Hint for nVidia HQ modes (Quincunx etc.)
820
GLStates.MultisampleFilterHint := hintNicest
822
GLStates.MultisampleFilterHint := hintDontCare;
824
if GLStates.ForwardContext then
825
GLSLogger.LogInfo(strFRC_created);
827
GLSLogger.LogInfo(strOESRC_created);
830
GLStates.ForwardContext := GLStates.ForwardContext and bSuccess;
831
PipelineTransformation.LoadMatricesEnabled := not GLStates.ForwardContext;
838
procedure TGLWin32Context.DoCreateContext(ADeviceHandle: HDC);
840
cMemoryDCs = [OBJ_MEMDC, OBJ_METADC, OBJ_ENHMETADC];
841
cBoolToInt: array[False..True] of Integer = (GL_FALSE, GL_TRUE);
842
cLayerToSet: array[TGLContextLayer] of Byte = (32, 16, 0, 1, 2);
844
pfDescriptor: TPixelFormatDescriptor;
845
pixelFormat, nbFormats, softwarePixelFormat: Integer;
847
iFormats: array[0..31] of Integer;
852
sharedRC: TGLWin32Context;
854
function CurrentPixelFormatIsHardwareAccelerated: Boolean;
856
localPFD: TPixelFormatDescriptor;
859
if pixelFormat = 0 then
863
nSize := SizeOf(localPFD);
866
DescribePixelFormat(ADeviceHandle, pixelFormat, SizeOf(localPFD), localPFD);
867
Result := ((localPFD.dwFlags and PFD_GENERIC_FORMAT) = 0);
871
i, iAttrib, iValue: Integer;
874
DoGetHandles(HWND(ADeviceHandle), ADeviceHandle);
876
if vUseWindowTrackingHook and not FLegacyContextsOnly then
877
TrackWindow(WindowFromDC(ADeviceHandle), DestructionEarlyWarning);
879
// Just in case it didn't happen already.
880
if not InitOpenGL then
884
FillChar(pfDescriptor, SizeOf(pfDescriptor), 0);
887
nSize := SizeOf(PFDescriptor);
889
dwFlags := PFD_SUPPORT_OPENGL;
890
aType := GetObjectType(ADeviceHandle);
893
if aType in cMemoryDCs then
894
dwFlags := dwFlags or PFD_DRAW_TO_BITMAP
896
dwFlags := dwFlags or PFD_DRAW_TO_WINDOW;
897
if rcoDoubleBuffered in Options then
898
dwFlags := dwFlags or PFD_DOUBLEBUFFER;
899
if rcoStereo in Options then
900
dwFlags := dwFlags or PFD_STEREO;
901
iPixelType := PFD_TYPE_RGBA;
902
cColorBits := ColorBits;
903
cDepthBits := DepthBits;
904
cStencilBits := StencilBits;
905
cAccumBits := AccumBits;
906
cAlphaBits := AlphaBits;
907
cAuxBuffers := AuxBuffers;
909
clUnderlay2, clUnderlay1: iLayerType := Byte(PFD_UNDERLAY_PLANE);
910
clMainPlane: iLayerType := PFD_MAIN_PLANE;
911
clOverlay1, clOverlay2: iLayerType := PFD_OVERLAY_PLANE;
913
bReserved := cLayerToSet[Layer];
914
if Layer <> clMainPlane then
915
dwFlags := dwFlags or PFD_SWAP_LAYER_BUFFERS;
920
// WGL_ARB_pixel_format is used if available
922
if not (IsMesaGL or FLegacyContextsOnly or (aType in cMemoryDCs)) then
924
// the WGL mechanism is a little awkward: we first create a dummy context
925
// on the TOP-level DC (ie. screen), to retrieve our pixelformat, create
927
tempWnd := CreateTempWnd;
928
tempDC := GetDC(tempWnd);
932
SpawnLegacyContext(tempDC);
937
if FGL.W_ARB_pixel_format then
939
// New pixel format selection via wglChoosePixelFormatARB
941
AddIAttrib(WGL_DRAW_TO_WINDOW_ARB, GL_TRUE);
942
AddIAttrib(WGL_STEREO_ARB, cBoolToInt[rcoStereo in Options]);
943
AddIAttrib(WGL_DOUBLE_BUFFER_ARB, cBoolToInt[rcoDoubleBuffered in
946
ChooseWGLFormat(ADeviceHandle, 32, @iFormats, nbFormats);
947
if nbFormats > 0 then
949
if FGL.W_ARB_multisample and (AntiAliasing in [aaNone, aaDefault]) then
951
// Pick first non AntiAliased for aaDefault and aaNone modes
952
iAttrib := WGL_SAMPLE_BUFFERS_ARB;
953
for i := 0 to nbFormats - 1 do
955
pixelFormat := iFormats[i];
957
FGL.WGetPixelFormatAttribivARB(ADeviceHandle, pixelFormat, 0, 1,
959
if iValue = GL_FALSE then
964
pixelFormat := iFormats[0];
965
if GetPixelFormat(ADeviceHandle) <> pixelFormat then
967
if not SetPixelFormat(ADeviceHandle, pixelFormat, @PFDescriptor) then
976
sharedRC := FShareContext;
978
FShareContext := sharedRC;
979
GLSLogger.LogInfo('Temporary rendering context destroyed');
982
ReleaseDC(0, tempDC);
983
DestroyWindow(tempWnd);
989
if pixelFormat = 0 then
991
// Legacy pixel format selection
992
pixelFormat := ChoosePixelFormat(ADeviceHandle, @PFDescriptor);
993
if (not (aType in cMemoryDCs)) and (not
994
CurrentPixelFormatIsHardwareAccelerated) then
996
softwarePixelFormat := pixelFormat;
1000
softwarePixelFormat := 0;
1001
if pixelFormat = 0 then
1003
// Failed on default params, try with 16 bits depth buffer
1004
PFDescriptor.cDepthBits := 16;
1005
pixelFormat := ChoosePixelFormat(ADeviceHandle, @PFDescriptor);
1006
if not CurrentPixelFormatIsHardwareAccelerated then
1008
if pixelFormat = 0 then
1010
// Failed, try with 16 bits color buffer
1011
PFDescriptor.cColorBits := 16;
1012
pixelFormat := ChoosePixelFormat(ADeviceHandle, @PFDescriptor);
1014
if not CurrentPixelFormatIsHardwareAccelerated then
1016
// Fallback to original, should be supported by software
1017
pixelFormat := softwarePixelFormat;
1019
if pixelFormat = 0 then
1024
if GetPixelFormat(ADeviceHandle) <> pixelFormat then
1026
if not SetPixelFormat(ADeviceHandle, pixelFormat, @PFDescriptor) then
1030
// Check the properties we just set.
1031
DescribePixelFormat(ADeviceHandle, pixelFormat, SizeOf(PFDescriptor), PFDescriptor);
1032
with PFDescriptor do
1034
if (dwFlags and PFD_NEED_PALETTE) <> 0 then
1035
SetupPalette(ADeviceHandle, PFDescriptor);
1036
FSwapBufferSupported := (dwFlags and PFD_SWAP_LAYER_BUFFERS) <> 0;
1037
if bReserved = 0 then
1038
FLayer := clMainPlane;
1041
if not FLegacyContextsOnly then
1043
if ((pfDescriptor.dwFlags and PFD_GENERIC_FORMAT) > 0)
1044
and (FAcceleration = chaHardware) then
1046
FAcceleration := chaSoftware;
1047
GLSLogger.LogWarning(strFailHWRC);
1051
if not FLegacyContextsOnly
1052
and FGL.W_ARB_create_context
1053
and (FAcceleration = chaHardware) then
1054
CreateNewContext(ADeviceHandle)
1056
CreateOldContext(ADeviceHandle);
1058
if not FLegacyContextsOnly then
1060
// Share identifiers with other context if it deffined
1061
if (ServiceContext <> nil) and (Self <> ServiceContext) then
1063
if wglShareLists(TGLWin32Context(ServiceContext).FRC, FRC) then
1065
FSharedContexts.Add(ServiceContext);
1066
PropagateSharedContext;
1069
GLSLogger.LogWarning('DoCreateContext - Failed to share contexts with resource context');
1074
// SpawnLegacyContext
1077
procedure TGLWin32Context.SpawnLegacyContext(aDC: HDC);
1080
FLegacyContextsOnly := True;
1082
DoCreateContext(aDC);
1084
FLegacyContextsOnly := False;
1089
raise Exception.Create(strUnableToCreateLegacyContext + #13#10
1090
+ E.ClassName + ': ' + E.Message);
1095
// DoCreateMemoryContext
1098
procedure TGLWin32Context.DoCreateMemoryContext(outputDevice: HWND; width,
1099
height: Integer; BufferCount: integer);
1102
iFormats: array[0..31] of Integer;
1103
iPBufferAttribs: array[0..0] of Integer;
1104
localHPBuffer: Integer;
1106
localDC, tempDC: HDC;
1108
shareRC: TGLWin32Context;
1109
pfDescriptor: TPixelFormatDescriptor;
1116
// the WGL mechanism is a little awkward: we first create a dummy context
1117
// on the TOP-level DC (ie. screen), to retrieve our pixelformat, create
1119
tempWnd := CreateTempWnd;
1120
tempDC := GetDC(tempWnd);
1122
SpawnLegacyContext(tempDC);
1127
if FGL.W_ARB_pixel_format and FGL.W_ARB_pbuffer then
1130
AddIAttrib(WGL_DRAW_TO_PBUFFER_ARB, 1);
1131
ChooseWGLFormat(tempDC, 32, @iFormats, nbFormats, BufferCount);
1132
if nbFormats = 0 then
1134
EPBuffer.Create('Format not supported for pbuffer operation.');
1135
iPBufferAttribs[0] := 0;
1137
localHPBuffer := FGL.WCreatePbufferARB(tempDC, iFormats[0], width,
1139
@iPBufferAttribs[0]);
1140
if localHPBuffer = 0 then
1141
raise EPBuffer.Create('Unabled to create pbuffer.');
1143
localDC := FGL.WGetPbufferDCARB(localHPBuffer);
1145
raise EPBuffer.Create('Unabled to create pbuffer''s DC.');
1147
if FGL.W_ARB_create_context then
1149
// Modern creation style
1151
// Initialize forward context
1152
if GLStates.ForwardContext then
1154
if FGL.VERSION_4_2 then
1156
AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 4);
1157
AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 2);
1159
else if FGL.VERSION_4_1 then
1161
AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 4);
1162
AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 1);
1164
else if FGL.VERSION_4_0 then
1166
AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 4);
1167
AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 0);
1169
else if FGL.VERSION_3_3 then
1171
AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 3);
1172
AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 3);
1174
else if FGL.VERSION_3_2 then
1176
AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 3);
1177
AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 2);
1179
else if FGL.VERSION_3_1 then
1181
AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 3);
1182
AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 1);
1184
else if FGL.VERSION_3_0 then
1186
AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 3);
1187
AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 0);
1191
AddIAttrib(WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
1192
if rcoOGL_ES in Options then
1193
GLSLogger.LogWarning(strOESvsForwardRC);
1195
else if rcoOGL_ES in Options then
1197
if FGL.W_EXT_create_context_es2_profile then
1199
AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 2);
1200
AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 0);
1201
AddIAttrib(WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_ES2_PROFILE_BIT_EXT);
1204
GLSLogger.LogError(strDriverNotSupportOESRC);
1207
if rcoDebug in Options then
1209
AddIAttrib(WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB);
1210
FGL.DebugMode := True;
1214
clUnderlay2: AddIAttrib(WGL_CONTEXT_LAYER_PLANE_ARB, -2);
1215
clUnderlay1: AddIAttrib(WGL_CONTEXT_LAYER_PLANE_ARB, -1);
1216
clOverlay1: AddIAttrib(WGL_CONTEXT_LAYER_PLANE_ARB, 1);
1217
clOverlay2: AddIAttrib(WGL_CONTEXT_LAYER_PLANE_ARB, 2);
1220
localRC := FGL.WCreateContextAttribsARB(localDC, 0, @FiAttribs[0]);
1222
{$IFDEF GLS_LOGGING}
1224
if GLStates.ForwardContext then
1225
GLSLogger.LogErrorFmt(strForwardContextFailed,
1226
[GetLastError, SysErrorMessage(GetLastError)])
1228
GLSLogger.LogErrorFmt(strBackwardContextFailed,
1229
[GetLastError, SysErrorMessage(GetLastError)]);
1233
raise Exception.Create('Unabled to create pbuffer''s RC.');
1238
// Old creation style
1239
localRC := wglCreateContext(localDC);
1242
GLSLogger.LogErrorFmt(strBackwardContextFailed,
1243
[GetLastError, SysErrorMessage(GetLastError)]);
1249
FGL.WReleasePBufferDCARB(localHPBuffer, localDC);
1253
FGL.WDestroyPBufferARB(localHPBuffer);
1258
raise EPBuffer.Create('WGL_ARB_pbuffer support required.');
1264
shareRC := FShareContext;
1266
FShareContext := shareRC;
1269
ReleaseDC(0, tempDC);
1270
DestroyWindow(tempWnd);
1271
FHPBUFFER := localHPBuffer;
1276
DescribePixelFormat(FDC, GetPixelFormat(FDC), SizeOf(PFDescriptor), PFDescriptor);
1277
if ((PFDescriptor.dwFlags and PFD_GENERIC_FORMAT) > 0)
1278
and (FAcceleration = chaHardware) then
1280
FAcceleration := chaSoftware;
1281
GLSLogger.LogWarning(strFailHWRC);
1286
// If we are using AntiAliasing, adjust filtering hints
1287
if AntiAliasing in [aa2xHQ, aa4xHQ, csa8xHQ, csa16xHQ] then
1288
GLStates.MultisampleFilterHint := hintNicest
1289
else if AntiAliasing in [aa2x, aa4x, csa8x, csa16x] then
1290
GLStates.MultisampleFilterHint := hintFastest
1291
else GLStates.MultisampleFilterHint := hintDontCare;
1293
// Specific which color buffers are to be drawn into
1294
if BufferCount > 1 then
1295
FGL.DrawBuffers(BufferCount, @MRT_BUFFERS);
1297
if (ServiceContext <> nil) and (Self <> ServiceContext) then
1299
if wglShareLists(TGLWin32Context(ServiceContext).FRC, FRC) then
1301
FSharedContexts.Add(ServiceContext);
1302
PropagateSharedContext;
1305
GLSLogger.LogWarning('DoCreateContext - Failed to share contexts with resource context');
1308
if Assigned(FShareContext) and (FShareContext.RC <> 0) then
1310
if not wglShareLists(FShareContext.RC, FRC) then
1311
GLSLogger.LogWarning(strFailedToShare)
1314
FSharedContexts.Add(FShareContext);
1315
PropagateSharedContext;
1321
if GLStates.ForwardContext then
1322
GLSLogger.LogInfo('PBuffer ' + strFRC_created);
1324
GLSLogger.LogInfo('PBuffer ' + strOESRC_created);
1325
if not (GLStates.ForwardContext or bOES) then
1326
GLSLogger.LogInfo(strPBufferRC_created);
1332
function TGLWin32Context.DoShareLists(aContext: TGLContext): Boolean;
1334
if aContext is TGLWin32Context then
1336
FShareContext := TGLWin32Context(aContext);
1337
if FShareContext.RC <> 0 then
1338
Result := wglShareLists(FShareContext.RC, RC)
1343
raise Exception.Create(strIncompatibleContexts);
1349
procedure TGLWin32Context.DoDestroyContext;
1351
if vUseWindowTrackingHook then
1352
UnTrackWindow(WindowFromDC(FDC));
1354
if FHPBUFFER <> 0 then
1356
FGL.WReleasePbufferDCARB(FHPBuffer, FDC);
1357
FGL.WDestroyPbufferARB(FHPBUFFER);
1362
if not wglDeleteContext(FRC) then
1363
GLSLogger.LogErrorFmt(strDeleteContextFailed,
1364
[GetLastError, SysErrorMessage(GetLastError)]);
1368
FShareContext := nil;
1374
procedure TGLWin32Context.DoActivate;
1376
if not wglMakeCurrent(FDC, FRC) then
1378
GLSLogger.LogErrorFmt(strContextActivationFailed,
1379
[GetLastError, SysErrorMessage(GetLastError)]);
1383
if not FGL.IsInitialized then
1384
FGL.Initialize(CurrentGLContext = nil);
1390
procedure TGLWin32Context.DoDeactivate;
1392
if not wglMakeCurrent(0, 0) then
1394
GLSLogger.LogErrorFmt(strContextDeactivationFailed,
1395
[GetLastError, SysErrorMessage(GetLastError)]);
1403
function TGLWin32Context.IsValid: Boolean;
1405
Result := (FRC <> 0);
1411
procedure TGLWin32Context.SwapBuffers;
1413
if (FDC <> 0) and (rcoDoubleBuffered in Options) then
1414
if FSwapBufferSupported then
1417
clUnderlay2: wglSwapLayerBuffers(FDC, WGL_SWAP_UNDERLAY2);
1418
clUnderlay1: wglSwapLayerBuffers(FDC, WGL_SWAP_UNDERLAY1);
1419
clMainPlane: Windows.SwapBuffers(FDC);
1420
clOverlay1: wglSwapLayerBuffers(FDC, WGL_SWAP_OVERLAY1);
1421
clOverlay2: wglSwapLayerBuffers(FDC, WGL_SWAP_OVERLAY2);
1425
Windows.SwapBuffers(FDC);
1428
// RenderOutputDevice
1431
function TGLWin32Context.RenderOutputDevice: Pointer;
1433
Result := Pointer(FDC);
1436
// ------------------------------------------------------------------
1437
// ------------------------------------------------------------------
1438
// ------------------------------------------------------------------
1440
// ------------------------------------------------------------------
1441
// ------------------------------------------------------------------
1442
// ------------------------------------------------------------------