LZScene

Форк
0
/
GLContext.pas 
4975 строк · 128.2 Кб
1
//
2
// This unit is part of the GLScene Engine https://github.com/glscene
3
//
4
{
5
   Prototypes and base implementation of TGLContext.
6

7
    History :  
8
       01/06/11 - Yar - Now number of rendering contexts is unlimited (by Gabriel Corneanu)  
9
       13/05/11 - Yar - Made indexing for context's handles to improve speed of operations
10
       24/03/11 - Yar - Added preparation arrangement to TGLContext, TGLContextHandle 
11
       24/11/10 - Yar - Added TGLBooleanOcclusionQueryHandle
12
       14/10/10 - Yar - Added ServiceContext in separate thread, procedure AddTaskForServiceContext
13
       16/09/10 - YP - Fixes param assertion to display missing attrib, uniform or varying by name
14
       23/08/10 - Yar - Added OpenGLTokens to uses, replaced OpenGL1x functions to OpenGLAdapter
15
                           Added to TGLContext property PipelineTransformation
16
                           Added feature of debug context creating
17
                           Improved TGLContextHandle destroying
18
                           Added TGLARBVertexProgramHandle, TGLARBFragmentProgramHandle, TGLARBGeometryProgramHandle
19
       02/08/10 - DaStr - Bugfixed TGLContextHandle.DestroyHandle()
20
       18/07/10 - Yar - Added TGLTessControlShaderHandle, TGLTessEvaluationShaderHandle, TGLSamplerHandle
21
       17/06/10 - Yar - Added IsDataNeedUpdate, NotifyDataUpdated, NotifyChangesOfData to TGLContextHandle
22
       02/05/10 - Yar - Fixes for Linux x64. Make outputDevice HWND type.
23
       02/05/10 - Yar - Handles are universal for contexts.
24
                           You can use one handle in different contexts, regardless of the compatibility of contexts.
25
       01/05/10 - Yar - Added buffer objects state cashing
26
       22/04/10 - Yar - Fixes after GLState revision
27
       18/03/10 - Yar - Added MapBufferRange, Flush to TGLBufferObjectHandle
28
       06/03/10 - Yar - Added to TGLProgramHandle BindFragDataLocation, GetUniformOffset, GetUniformBlockIndex
29
       05/03/10 - DanB - More state added to TGLStateCache
30
       22/02/10 - DanB - Added TGLContext.GLStates, to be used to cache
31
                            global per-context state. Removed BindedGLSLProgram
32
                            since it should be per-context state.
33
       21/02/10 - Yar - Added function BindedGLSLProgram
34
       08/01/10 - DaStr - Added TGLFramebufferHandle.AttachLayer()
35
                             Added more AntiAliasing modes (thanks YarUndeoaker)
36
       13/12/09 - DaStr - Modified for multithread support (thanks Controller)
37
       30/08/09 - DanB - renamed vIgnoreContextActivationFailures to vContextActivationFailureOccurred
38
                            + re-enabled it's original behaviour (fixes major memory leak).
39
       30/08/09 - DanB - Added TGLTransformFeedbackBufferHandle, TGLTextureBufferHandle,
40
                            TGLUniformBufferHandle, TGLVertexArrayHandle,
41
                            TGLFramebufferHandle, TGLRenderbufferHandle
42
       24/08/09 - DaStr - Added TGLProgramHandle.GetVaryingLocation(),
43
                              AddActiveVarying() (thanks YarUnderoaker)
44
       21/08/09 - DanB - TGLQueryHandle.GetTarget no longer a class function,
45
                            for earlier Delphi compatibility
46
       13/08/09 - DanB - Added timer & primitive queries.  Occlusion queries now
47
                            use OpenGL 1.5+ queries, instead of GL_NV_occlusion_query extension
48
       10/06/09 - DanB - removed OpenGL error handling code, it already exists in OpenGL1x.pas
49
       16/03/08 - DanB - moved MRT_BUFFERS into unit from opengl1x.pas rewrite,
50
                            and added some experimental geometry shader code
51
       15/03/08 - DaStr - Fixups for vIgnoreContextActivationFailures mode
52
                                                      (BugTracker ID = 1914782)
53
       06/11/07 - LC - moved vIgnoreContextActivationFailures to "Interface" section
54
       24/06/06 - LC - Refactored TGLVBOHandle, introduced TGLBufferObjectHandle
55
                          and TGLPackPBOHandle/TGLUnpackPBOHandle
56
       15/02/07 - DaStr - Added more parameters to TGLProgramHandle
57
                             TGLProgramHandle.Name is now a property
58
       15/02/07 - DaStr - Integer -> Cardinal because $R- was removed in GLScene.pas
59
       15/09/06 - NC - TGLContextHandle.handle as Integer -> Cardinal
60
       11/09/06 - NC - Added TGLProgramHandle.Name, TGLProgramHandle.Uniform2f,
61
                          SetUniform*, support for Multiple-Render-Target
62
       25/04/04 - EG - Added TGLOcclusionQueryHandle.Active
63
       25/09/03 - EG - Added TGLVBOHandle
64
       20/09/03 - EG - Added TGLOcclusionQueryHandle
65
       30/01/02 - EG - Added TGLVirtualHandle
66
       29/01/02 - EG - Improved recovery for context creation failures
67
       28/01/02 - EG - Activation failures always ignored
68
       21/01/02 - EG - Activation failures now ignored if application is
69
                          terminating (workaround for some weird ICDs)
70
       15/12/01 - EG - Added support for AlphaBits
71
       30/11/01 - EG - Added TGLContextAcceleration
72
       06/09/01 - EG - Win32Context moved to new GLWin32Context unit
73
       04/09/01 - EG - Added ChangeIAttrib, support for 16bits depth buffer
74
       25/08/01 - EG - Added pbuffer support and CreateMemoryContext interface
75
       24/08/01 - EG - Fixed PropagateSharedContext
76
       12/08/01 - EG - Handles management completed
77
       22/07/01 - EG - Creation (glcontext.omm)
78
    
79
}
80
unit GLContext;
81

82
interface
83

84
{$I GLScene.inc}
85

86
uses
87
  {$IFDEF MSWINDOWS}
88
  Windows,
89
  {$ENDIF}
90
  Classes, SysUtils, Types, Forms, Controls,
91

92
  LCLVersion, LCLType,
93

94
  SyncObjs,
95
{$IFDEF GLS_SERVICE_CONTEXT}
96
  GLSGenerics,
97
{$ENDIF}
98
  GLSLog,
99
  GLCrossPlatform, OpenGLTokens, OpenGLAdapter,  GLVectorGeometry, GLStrings,
100
  GLVectorTypes,  GLState,  GLPipelineTransformation,  GLTextureFormat;
101

102
// Buffer ID's for Multiple-Render-Targets (using GL_ATI_draw_buffers)
103
const
104
  MRT_BUFFERS: array[0..3] of GLenum = (GL_FRONT_LEFT, GL_AUX0, GL_AUX1, GL_AUX2);
105

106
type
107

108
  // TGLRCOptions
109
  //
110
  TGLRCOption = (rcoDoubleBuffered, rcoStereo, rcoDebug, rcoOGL_ES);
111
  TGLRCOptions = set of TGLRCOption;
112

113
  TGLContextLayer = (clUnderlay2, clUnderlay1, clMainPlane, clOverlay1, clOverlay2);
114

115
  TFinishTaskEvent = class(TEvent)
116
  public
117
    constructor Create; reintroduce;
118
  end;
119

120
  TTaskProcedure = procedure of object; stdcall;
121
  TServiceContextTask = record
122
    Task: TTaskProcedure;
123
    Event: TFinishTaskEvent;
124
  end;
125

126
{$IFDEF GLS_SERVICE_CONTEXT}
127
  TServiceContextTaskList = {$IFDEF GLS_GENERIC_PREFIX} specialize {$ENDIF}
128
    GThreadList < TServiceContextTask > ;
129
{$ENDIF GLS_SERVICE_CONTEXT}
130

131
  TGLContext = class;
132
  TGLContextManager = class;
133

134
  TAbstractMultitextureCoordinator = class(TObject)
135
  protected
136
    FOwner: TGLContext;
137
  public
138
    constructor Create(AOwner: TGLContext); virtual;
139
  end;
140

141
  TAbstractMultitextureCoordinatorClass = class of TAbstractMultitextureCoordinator;
142

143
  // TGLContextAcceleration
144
  //
145
  TGLContextAcceleration = (chaUnknown, chaHardware, chaSoftware);
146

147
  // TGLAntiAliasing
148
  //
149
  TGLAntiAliasing = (// Multisample Antialiasing
150
    aaDefault, aaNone, aa2x, aa2xHQ, aa4x, aa4xHQ,
151
    aa6x, aa8x, aa16x,
152
    // Coverage Sampling Antialiasing
153
    csa8x, csa8xHQ, csa16x, csa16xHQ);
154

155
  // TVSyncMode
156
  //
157
  TVSyncMode = (vsmSync, vsmNoSync);
158

159
  // TGLContext
160
  //
161
  { Wrapper around an OpenGL rendering context.
162
     The aim of this class is to offer platform-independant
163
     initialization, activation and management of OpenGL
164
     rendering context. The class also offers notifications
165
     event and error/problems detection. 
166
     This is a virtual abstract a class, and platform-specific
167
     subclasses must be used. 
168
     All rendering context share the same lists. }
169
  TGLContext = class
170
  private
171
     
172
    FColorBits, FAlphaBits: Integer;
173
    FDepthBits: Integer;
174
    FStencilBits: Integer;
175
    FAccumBits: Integer;
176
    FAuxBuffers: Integer;
177
    FAntiAliasing: TGLAntiAliasing;
178
    FOptions: TGLRCOptions;
179
    FOnDestroyContext: TNotifyEvent;
180
    FManager: TGLContextManager;
181
    FActivationCount: Integer;
182
    FOwnedHandlesCount: Integer;
183
    FIsPraparationNeed: Boolean;
184
    procedure SetColorBits(const aColorBits: Integer);
185
    procedure SetAlphaBits(const aAlphaBits: Integer);
186
    procedure SetDepthBits(const val: Integer);
187
    procedure SetStencilBits(const aStencilBits: Integer);
188
    procedure SetAccumBits(const aAccumBits: Integer);
189
    procedure SetAuxBuffers(const aAuxBuffers: Integer);
190
    procedure SetOptions(const aOptions: TGLRCOptions);
191
    procedure SetAntiAliasing(const val: TGLAntiAliasing);
192
    procedure SetAcceleration(const val: TGLContextAcceleration);
193
    function GetActive: Boolean;
194
    procedure SetActive(const aActive: Boolean);
195
    procedure SetLayer(const Value: TGLContextLayer);
196
  protected
197
     
198
    FGL: TGLExtensionsAndEntryPoints;
199
    FXGL: TAbstractMultitextureCoordinator;
200
    FGLStates: TGLStateCache;
201
    FTransformation: TGLTransformation;
202
    FAcceleration: TGLContextAcceleration;
203
    FLayer: TGLContextLayer;
204
{$IFNDEF GLS_MULTITHREAD}
205
    FSharedContexts: TList;
206
{$ELSE}
207
    FSharedContexts: TThreadList;
208
    FLock: TCriticalSection;
209
{$ENDIF}
210
    procedure PropagateSharedContext;
211

212
    procedure DoCreateContext(ADeviceHandle: HDC); virtual; abstract;
213
    procedure DoCreateMemoryContext(outputDevice: HWND; width, height:
214
      Integer; BufferCount: integer = 1); virtual; abstract;
215
    function DoShareLists(aContext: TGLContext): Boolean; virtual; abstract;
216
    procedure DoDestroyContext; virtual; abstract;
217
    procedure DoActivate; virtual; abstract;
218
    procedure DoDeactivate; virtual; abstract;
219
    class function ServiceContext: TGLContext;
220
    procedure MakeGLCurrent;
221
    function GetXGL: TAbstractMultitextureCoordinator;
222
  public
223
     
224
    constructor Create; virtual;
225
    destructor Destroy; override;
226

227
    { An application-side cache of global per-context OpenGL states
228
       and parameters }
229
    property GLStates: TGLStateCache read FGLStates;
230

231
    property PipelineTransformation: TGLTransformation read FTransformation;
232

233
    // Context manager reference
234
    property Manager: TGLContextManager read FManager;
235

236
    { Color bits for the rendering context }
237
    property ColorBits: Integer read FColorBits write SetColorBits;
238
    { Alpha bits for the rendering context }
239
    property AlphaBits: Integer read FAlphaBits write SetAlphaBits;
240
    { Depth bits for the rendering context }
241
    property DepthBits: Integer read FDepthBits write SetDepthBits;
242
    { Stencil bits for the rendering context }
243
    property StencilBits: Integer read FStencilBits write SetStencilBits;
244
    { Accumulation buffer bits for the rendering context }
245
    property AccumBits: Integer read FAccumBits write SetAccumBits;
246
    { Auxiliary buffers bits for the rendering context }
247
    property AuxBuffers: Integer read FAuxBuffers write SetAuxBuffers;
248
    { AntiAliasing option.
249
       Ignored if not hardware supported, currently based on ARB_multisample. }
250
    property AntiAliasing: TGLAntiAliasing read FAntiAliasing write
251
      SetAntiAliasing;
252
    { Specifies the layer plane that the rendering context is bound to. }
253
    property Layer: TGLContextLayer read FLayer write SetLayer;
254
    { Rendering context options. }
255
    property Options: TGLRCOptions read FOptions write SetOptions;
256
    { Allows reading and defining the activity for the context.
257
       The methods of this property are just wrappers around calls
258
       to Activate and Deactivate. }
259
    property Active: Boolean read GetActive write SetActive;
260
    { Indicates if the context is hardware-accelerated. }
261
    property Acceleration: TGLContextAcceleration read FAcceleration write SetAcceleration;
262
    { Triggered whenever the context is destroyed.
263
       This events happens *before* the context has been
264
       actually destroyed, OpenGL resource cleanup can
265
       still occur here. }
266
    property OnDestroyContext: TNotifyEvent read FOnDestroyContext write
267
      FOnDestroyContext;
268

269
    { Creates the context.
270
       This method must be invoked before the context can be used. }
271
    procedure CreateContext(ADeviceHandle: HDC); overload;
272
    { Creates an in-memory context.
273
       The function should fail if no hardware-accelerated memory context
274
       can be created (the CreateContext method can handle software OpenGL
275
       contexts). }
276
    procedure CreateMemoryContext(outputDevice: HWND; width, height:
277
      Integer; BufferCount: integer = 1);
278
    { Setup display list sharing between two rendering contexts.
279
       Both contexts must have the same pixel format. }
280
    procedure ShareLists(aContext: TGLContext);
281
    { Destroy the context.
282
       Will fail if no context has been created. 
283
       The method will first invoke the OnDestroyContext
284
       event, then attempts to deactivate the context
285
       (if it is active) before destroying it. }
286
    procedure DestroyContext;
287
    { Activates the context.
288
       A context can be activated multiple times (and must be
289
       deactivated the same number of times), but this function
290
       will fail if another context is already active. }
291
    procedure Activate;
292
    { Deactivates the context.
293
       Will fail if the context is not active or another
294
       context has been activated. }
295
    procedure Deactivate;
296
    { Call OnPrepare for all handles. }
297
    procedure PrepareHandlesData;
298
    { Returns true if the context is valid.
299
       A context is valid from the time it has been successfully
300
       created to the time of its destruction. }
301
    function IsValid: Boolean; virtual; abstract;
302
    { Request to swap front and back buffers if they were defined. }
303
    procedure SwapBuffers; virtual; abstract;
304

305
    { Returns the first compatible context that isn't self in the shares. }
306
    function FindCompatibleContext: TGLContext;
307
    procedure DestroyAllHandles;
308

309
    function RenderOutputDevice: Pointer; virtual; abstract;
310
    { Access to OpenGL command and extension. }
311
    property GL: TGLExtensionsAndEntryPoints read FGL;
312
    property MultitextureCoordinator: TAbstractMultitextureCoordinator read GetXGL;
313
    property IsPraparationNeed: Boolean read FIsPraparationNeed;
314
  end;
315

316
  TGLContextClass = class of TGLContext;
317

318
  // TGLScreenControlingContext
319
  //
320
  { A TGLContext with screen control property and methods.
321
     This variety of contexts is for drivers that access windows and OpenGL
322
     through an intermediate opaque cross-platform API.
323
     TGLSceneViewer won't use them, TGLMemoryViewer may be able to use them,
324
     but most of the time they will be accessed through a specific viewer
325
     class/subclass. }
326
  TGLScreenControlingContext = class(TGLContext)
327
  private
328
     
329
    FWidth, FHeight: Integer;
330
    FFullScreen: Boolean;
331

332
  protected
333
     
334

335
  public
336
     
337
    property Width: Integer read FWidth write FWidth;
338
    property Height: Integer read FHeight write FHeight;
339
    property FullScreen: Boolean read FFullScreen write FFullScreen;
340
  end;
341

342
  PGLRCHandle = ^TGLRCHandle;
343
  TGLRCHandle = record
344
    FRenderingContext: TGLContext;
345
    FHandle: TGLuint;
346
    FChanged: Boolean;
347
  end;
348

349
  TOnPrepareHandleData = procedure(AContext: TGLContext) of object;
350

351
  // TGLContextHandle
352
  //
353
  { Wrapper around an OpenGL context handle.
354
     This wrapper also takes care of context registrations and data releases
355
     related to context releases an cleanups. This is an abstract class,
356
     use the TGLListHandle and TGLTextureHandle subclasses. }
357
  TGLContextHandle = class
358
  private
359
     
360
    FHandles: TList;
361
    FLastHandle : PGLRCHandle;
362
    FOnPrepare: TOnPrepareHandleData;
363
    function GetHandle: TGLuint;
364
    function GetContext: TGLContext;
365
    function SearchRC(AContext: TGLContext): PGLRCHandle;
366
    function RCItem(AIndex: integer): PGLRCHandle; {$IFDEF GLS_INLINE}inline;{$ENDIF}
367
    procedure CheckCurrentRC;
368
  protected
369
     
370
    // Invoked by when there is no compatible context left for relocation
371
    procedure ContextDestroying;
372

373
    // Specifies if the handle can be transfered across shared contexts
374
    class function Transferable: Boolean; virtual;
375
    class function IsValid(const ID: GLuint): Boolean; virtual;
376

377
    function DoAllocateHandle: Cardinal; virtual; abstract;
378
    procedure DoDestroyHandle(var AHandle: TGLuint); virtual; abstract;
379

380
  public
381
     
382
    constructor Create; virtual;
383
    constructor CreateAndAllocate(failIfAllocationFailed: Boolean = True);
384
    destructor Destroy; override;
385

386
    { Return OpenGL identifier in current context. }
387
    property Handle: TGLuint read GetHandle;
388
    { Return current rendering context if handle is allocated in it
389
       or first context where handle is allocated. }
390
    property RenderingContext: TGLContext read GetContext;
391
    { Return True is data need update in current context. }
392
    function IsDataNeedUpdate: Boolean;
393
    { Return True if data updated in all contexts. }
394
    function IsDataComplitelyUpdated: Boolean;
395
    { Notify the data was updated in current context. }
396
    procedure NotifyDataUpdated;
397
    { Notify the data was changed through all context. }
398
    procedure NotifyChangesOfData;
399

400
    // Checks if required extensions / OpenGL version are met
401
    class function IsSupported: Boolean; virtual;
402
    function IsAllocatedForContext(AContext: TGLContext = nil): Boolean;
403
    function IsShared: Boolean;
404

405
    function  AllocateHandle: TGLuint;
406
    procedure DestroyHandle;
407

408
    property OnPrapare: TOnPrepareHandleData read FOnPrepare write FOnPrepare;
409
  end;
410

411
  TGLVirtualHandle = class;
412
  TGLVirtualHandleEvent = procedure(Sender: TGLVirtualHandle; var handle:
413
    TGLuint) of object;
414

415
  // TGLVirtualHandle
416
  //
417
  { A context handle with event-based handle allocation and destruction. }
418
  TGLVirtualHandle = class(TGLContextHandle)
419
  private
420
     
421
    FOnAllocate, FOnDestroy: TGLVirtualHandleEvent;
422
    FTag: Integer;
423
  protected
424
     
425
    function DoAllocateHandle: Cardinal; override;
426
    procedure DoDestroyHandle(var AHandle: TGLuint); override;
427
    class function Transferable: Boolean; override;
428
  public
429
     
430
    property OnAllocate: TGLVirtualHandleEvent read FOnAllocate write
431
      FOnAllocate;
432
    property OnDestroy: TGLVirtualHandleEvent read FOnDestroy write FOnDestroy;
433

434
    property Tag: Integer read FTag write FTag;
435
  end;
436

437
  // TGLVirtualHandleTransf
438
  //
439
  { Transferable virtual handle. }
440
  TGLVirtualHandleTransf = class(TGLVirtualHandle)
441
  protected
442
    class function Transferable: Boolean; override;
443
  end;
444

445
  // TGLListHandle
446
  //
447
  { Manages a handle to a display list. }
448
  TGLListHandle = class(TGLContextHandle)
449
  private
450
     
451

452
  protected
453
     
454
    function DoAllocateHandle: Cardinal; override;
455
    procedure DoDestroyHandle(var AHandle: TGLuint); override;
456
    class function IsValid(const ID: GLuint): Boolean; override;
457
  public
458
     
459
    procedure NewList(mode: Cardinal);
460
    procedure EndList;
461
    procedure CallList;
462
  end;
463

464
  // TGLTextureHandle
465
  //
466
  { Manages a handle to a texture. }
467
  TGLTextureHandle = class(TGLContextHandle)
468
  private
469
    FTarget: TGLTextureTarget;
470
    procedure SetTarget(ATarget: TGLTextureTarget);
471
  protected
472
     
473
    function DoAllocateHandle: Cardinal; override;
474
    procedure DoDestroyHandle(var AHandle: TGLuint); override;
475
    class function IsValid(const ID: GLuint): Boolean; override;
476
  public
477
     
478
    property Target: TGLTextureTarget read FTarget write SetTarget;
479
  end;
480

481
  // TGLSamplerHandle
482
  //
483
  { Manages a handle to a sampler. }
484
  TGLSamplerHandle = class(TGLContextHandle)
485
  protected
486
     
487
    function DoAllocateHandle: Cardinal; override;
488
    procedure DoDestroyHandle(var AHandle: TGLuint); override;
489
    class function IsValid(const ID: GLuint): Boolean; override;
490
  public
491
     
492
    class function IsSupported: Boolean; override;
493
  end;
494

495
  // TGLQueryHandle
496
  //
497
  { Manages a handle to a query. 
498
     Do not use this class directly, use one of its subclasses instead. }
499
  TGLQueryHandle = class(TGLContextHandle)
500
  private
501
     
502
    FActive: Boolean;
503
  protected
504
     
505
    class function Transferable: Boolean; override;
506
    function DoAllocateHandle: Cardinal; override;
507
    procedure DoDestroyHandle(var AHandle: TGLuint); override;
508
    function GetTarget: TGLuint; virtual; abstract;
509
    function GetQueryType: TQueryType; virtual; abstract;
510
    class function IsValid(const ID: GLuint): Boolean; override;
511
  public
512
     
513
    procedure BeginQuery;
514
    procedure EndQuery;
515

516
    // Check if result is available from the query.  Result may not be available
517
    // immediately after ending the query
518
    function IsResultAvailable: boolean;
519
    // Number of bits used to store the query result. eg. 32/64 bit
520
    function CounterBits: integer;
521
    // Retrieve query result, may cause a stall if the result is not available yet
522
    function QueryResultInt: TGLInt;
523
    function QueryResultUInt: TGLUInt;
524
    function QueryResultInt64: TGLint64EXT;
525
    function QueryResultUInt64: TGLuint64EXT;
526
    function QueryResultBool: TGLboolean;
527

528
    property Target: TGLuint read GetTarget;
529
    property QueryType: TQueryType read GetQueryType;
530

531
    { True if within a Begin/EndQuery. }
532
    property Active: Boolean read FActive;
533
  end;
534

535
  // TGLOcclusionQueryHandle
536
  //
537
  { Manages a handle to an occlusion query. 
538
     Requires OpenGL 1.5+ 
539
     Does *NOT* check for extension availability, this is assumed to have been
540
     checked by the user. }
541
  TGLOcclusionQueryHandle = class(TGLQueryHandle)
542
  protected
543
    function GetTarget: TGLuint; override;
544
    function GetQueryType: TQueryType; override;
545
  public
546
    class function IsSupported: Boolean; override;
547
    // Number of samples (pixels) drawn during the query, some pixels may
548
    // be drawn to several times in the same query
549
    function PixelCount: Integer;
550
  end;
551

552
  TGLBooleanOcclusionQueryHandle = class(TGLQueryHandle)
553
  protected
554
    function GetTarget: TGLuint; override;
555
    function GetQueryType: TQueryType; override;
556
  public
557
    class function IsSupported: Boolean; override;
558
  end;
559

560
  // TGLTimerQueryHandle
561
  //
562
  { Manages a handle to a timer query. 
563
     Requires GL_EXT_timer_query extension. 
564
     Does *NOT* check for extension availability, this is assumed to have been
565
     checked by the user. }
566
  TGLTimerQueryHandle = class(TGLQueryHandle)
567
  protected
568
    function GetTarget: TGLuint; override;
569
    function GetQueryType: TQueryType; override;
570
  public
571
    class function IsSupported: Boolean; override;
572
    // Time, in nanoseconds (1 ns = 10^-9 s) between starting + ending the query.
573
    // with 32 bit integer can measure up to approximately 4 seconds, use
574
    // QueryResultUInt64 if you may need longer
575
    function Time: Integer;
576
  end;
577

578
  // TGLPrimitiveQueryHandle
579
  //
580
  { Manages a handle to a primitive query. 
581
     Requires OpenGL 3.0+ 
582
     Does *NOT* check for extension availability, this is assumed to have been
583
     checked by the user. }
584
  TGLPrimitiveQueryHandle = class(TGLQueryHandle)
585
  protected
586
    function GetTarget: TGLuint; override;
587
    function GetQueryType: TQueryType; override;
588
  public
589
    class function IsSupported: Boolean; override;
590
    // Number of primitives (eg. Points, Triangles etc.) drawn whilst the
591
    // query was active
592
    function PrimitivesGenerated: Integer;
593
  end;
594

595
  // TGLBufferObjectHandle
596
  //
597
  { Manages a handle to a Buffer Object. 
598
     Does *NOT* check for extension availability, this is assumed to have been
599
     checked by the user.  }
600
  TGLBufferObjectHandle = class(TGLContextHandle)
601
  private
602
     
603
    FSize: Integer;
604
  protected
605
     
606
    function DoAllocateHandle: Cardinal; override;
607
    procedure DoDestroyHandle(var AHandle: TGLuint); override;
608

609
    function GetTarget: TGLuint; virtual; abstract;
610
    class function IsValid(const ID: GLuint): Boolean; override;
611
  public
612
     
613
    { Creates the buffer object buffer and initializes it. }
614
    constructor CreateFromData(p: Pointer; size: Integer; bufferUsage: TGLuint);
615

616
    procedure Bind; virtual; abstract;
617
    { Note that it is not necessary to UnBind before Binding another buffer. }
618
    procedure UnBind; virtual; abstract;
619

620
    { Bind a buffer object to an indexed target, used by transform feedback
621
       buffer objects and uniform buffer objects. (OpenGL 3.0+) }
622
    procedure BindRange(index: TGLuint; offset: TGLintptr; size: TGLsizeiptr);
623
      virtual;
624
    { Equivalent to calling BindRange with offset = 0, and size = the size of buffer.}
625
    procedure BindBase(index: TGLuint); virtual;
626
    procedure UnBindBase(index: TGLuint); virtual;
627

628
    { Specifies buffer content.
629
       Common bufferUsage values are GL_STATIC_DRAW_ARB for data that will
630
       change rarely, but be used often, GL_STREAM_DRAW_ARB for data specified
631
       once but used only a few times, and GL_DYNAMIC_DRAW_ARB for data
632
       that is re-specified very often.
633
       Valid only if the buffer has been bound. }
634
    procedure BufferData(p: Pointer; size: Integer; bufferUsage: TGLuint);
635
    // Invokes Bind then BufferData
636
    procedure BindBufferData(p: Pointer; size: Integer; bufferUsage: TGLuint);
637
    { Updates part of an already existing buffer.
638
       offset and size indicate which part of the data in the buffer is
639
       to bo modified and p where the data should be taken from. }
640
    procedure BufferSubData(offset, size: Integer; p: Pointer);
641
    { Map buffer content to memory.
642
       Values for access are GL_READ_ONLY_ARB, GL_WRITE_ONLY_ARB and
643
       GL_READ_WRITE_ARB.
644
       Valid only if the buffer has been bound, must be followed by
645
       an UnmapBuffer, only one buffer may be mapped at a time. }
646
    function MapBuffer(access: TGLuint): Pointer;
647
    function MapBufferRange(offset: TGLint; len: TGLsizei; access: TGLbitfield):
648
      Pointer;
649
    procedure Flush(offset: TGLint; len: TGLsizei);
650
    { Unmap buffer content from memory.
651
       Must follow a MapBuffer, and happen before the buffer is unbound. }
652
    function UnmapBuffer: Boolean;
653

654
    class function IsSupported: Boolean; override;
655

656
    property Target: TGLuint read GetTarget;
657
    property BufferSize: Integer read FSize;
658
  end;
659

660
  // TGLVBOHandle
661
  //
662
  { Manages a handle to an Vertex Buffer Object. 
663
     Does *NOT* check for extension availability, this is assumed to have been
664
     checked by the user. 
665
     Do not use this class directly, use one of its subclasses instead. }
666
  TGLVBOHandle = class(TGLBufferObjectHandle)
667
  private
668
     
669

670
    function GetVBOTarget: TGLuint;
671
  public
672

673
    property VBOTarget: TGLuint read GetVBOTarget;
674
  end;
675

676
  // TGLVBOArrayBufferHandle
677
  //
678
  { Manages a handle to VBO Array Buffer.
679
     Typically used to store vertices, normals, texcoords, etc. }
680
  TGLVBOArrayBufferHandle = class(TGLVBOHandle)
681
  protected
682
    function GetTarget: TGLuint; override;
683
  public
684
    procedure Bind; override;
685
    procedure UnBind; override;
686
  end;
687

688
  // TGLVBOElementArrayHandle
689
  //
690
  { Manages a handle to VBO Element Array Buffer.
691
     Typically used to store vertex indices. }
692
  TGLVBOElementArrayHandle = class(TGLVBOHandle)
693
  protected
694
    function GetTarget: TGLuint; override;
695
  public
696
    procedure Bind; override;
697
    procedure UnBind; override;
698
  end;
699

700
  // TGLPackPBOHandle
701
  //
702
  { Manages a handle to PBO Pixel Pack Buffer.
703
     When bound, commands such as ReadPixels write
704
     their data into a buffer object. }
705
  TGLPackPBOHandle = class(TGLBufferObjectHandle)
706
  protected
707
    function GetTarget: TGLuint; override;
708
  public
709
    procedure Bind; override;
710
    procedure UnBind; override;
711
    class function IsSupported: Boolean; override;
712
  end;
713

714
  // TGLUnpackPBOHandle
715
  //
716
  { Manages a handle to PBO Pixel Unpack Buffer.
717
     When bound, commands such as DrawPixels read
718
     their data from a buffer object. }
719
  TGLUnpackPBOHandle = class(TGLBufferObjectHandle)
720
  protected
721
    function GetTarget: TGLuint; override;
722
  public
723
    procedure Bind; override;
724
    procedure UnBind; override;
725
    class function IsSupported: Boolean; override;
726
  end;
727

728
  // TGLTransformFeedbackBufferHandle
729
  //
730
  { Manages a handle to a Transform Feedback Buffer Object.
731
     Transform feedback buffers can be used to capture vertex data from the
732
     vertex or geometry shader stage to perform further processing without
733
     going on to the fragment shader stage. }
734
  TGLTransformFeedbackBufferHandle = class(TGLBufferObjectHandle)
735
    //    FTransformFeedbackBufferBuffer: array[0..15] of TGLuint; // (0, 0, 0, ...)
736
    //    FTransformFeedbackBufferStart: array[0..15] of TGLuint64; // (0, 0, 0, ...)
737
    //    FTransformFeedbackBufferSize: array[0..15] of TGLuint64; // (0, 0, 0, ...)
738
  protected
739
    function GetTarget: TGLuint; override;
740
  public
741
    procedure Bind; override;
742
    procedure UnBind; override;
743
    procedure BeginTransformFeedback(primitiveMode: TGLenum);
744
    procedure EndTransformFeedback();
745
    procedure BindRange(index: TGLuint; offset: TGLintptr; size: TGLsizeiptr); override;
746
    procedure BindBase(index: TGLuint); override;
747
    procedure UnBindBase(index: TGLuint); override;
748

749
    class function IsSupported: Boolean; override;
750
  end;
751

752
  // TGLTextureBufferHandle
753
  //
754
  { Manages a handle to a Buffer Texture. (TBO) }
755
  TGLTextureBufferHandle = class(TGLBufferObjectHandle)
756
  protected
757
    function GetTarget: TGLuint; override;
758
  public
759
    procedure Bind; override;
760
    procedure UnBind; override;
761
    class function IsSupported: Boolean; override;
762
  end;
763

764
  // TGLUniformBufferHandle
765
  //
766
  { Manages a handle to a Uniform Buffer Object (UBO).
767
     Uniform buffer objects store "uniform blocks"; groups of uniforms
768
     that can be passed as a group into a GLSL program. }
769
  TGLUniformBufferHandle = class(TGLBufferObjectHandle)
770
    //    FUniformBufferBuffer: array[0..15] of TGLuint; // (0, 0, 0, ...)
771
    //    FUniformBufferStart: array[0..15] of TGLuint64; // (0, 0, 0, ...)
772
    //    FUniformBufferSize: array[0..15] of TGLuint64; // (0, 0, 0, ...)
773
  protected
774
    function GetTarget: TGLuint; override;
775
  public
776
    procedure Bind; override;
777
    procedure UnBind; override;
778
    procedure BindRange(index: TGLuint; offset: TGLintptr; size: TGLsizeiptr); override;
779
    procedure BindBase(index: TGLuint); override;
780
    procedure UnBindBase(index: TGLuint); override;
781
    class function IsSupported: Boolean; override;
782
  end;
783

784
  // TGLVertexArrayHandle
785
  //
786
  { Manages a handle to a Vertex Array Object (VAO).
787
     Vertex array objects are used to rapidly switch between large sets
788
     of array state. }
789
  TGLVertexArrayHandle = class(TGLContextHandle)
790
  protected
791
    class function Transferable: Boolean; override;
792
    function DoAllocateHandle: Cardinal; override;
793
    procedure DoDestroyHandle(var AHandle: TGLuint); override;
794
    class function IsValid(const ID: GLuint): Boolean; override;
795
  public
796
    procedure Bind;
797
    procedure UnBind;
798
    class function IsSupported: Boolean; override;
799
  end;
800

801
  TGLFramebufferStatus = (fsComplete, fsIncompleteAttachment,
802
    fsIncompleteMissingAttachment,
803
    fsIncompleteDuplicateAttachment, fsIncompleteDimensions,
804
    fsIncompleteFormats,
805
    fsIncompleteDrawBuffer, fsIncompleteReadBuffer, fsUnsupported,
806
    fsIncompleteMultisample,
807
    fsStatusError);
808

809
  // TGLFramebufferHandle
810
  //
811
  { Manages a handle to a Framebuffer Object (FBO).
812
     Framebuffer objects provide a way of drawing to rendering
813
     destinations other than the buffers provided to the GL by the
814
     window-system.  One or more "framebuffer-attachable images" can be attached
815
     to a Framebuffer for uses such as: offscreen rendering, "render to texture" +
816
     "multiple render targets" (MRT).
817
     There are several types of framebuffer-attachable images:
818
     - The image of a renderbuffer object, which is always 2D.
819
     - A single level of a 1D texture, which is treated as a 2D image with a height of one.
820
     - A single level of a 2D or rectangle texture.
821
     - A single face of a cube map texture level, which is treated as a 2D image.
822
     - A single layer of a 1D or 2D array texture or 3D texture, which is treated as a 2D image.
823
     Additionally, an entire level of a 3D texture, cube map texture,
824
     or 1D or 2D array texture can be attached to an attachment point.
825
     Such attachments are treated as an array of 2D images, arranged in
826
     layers, and the corresponding attachment point is considered to be layered. }
827
  TGLFramebufferHandle = class(TGLContextHandle)
828
  protected
829
    class function Transferable: Boolean; override;
830
    function DoAllocateHandle: Cardinal; override;
831
    procedure DoDestroyHandle(var AHandle: TGLuint); override;
832
    class function IsValid(const ID: GLuint): Boolean; override;
833
  public
834
    // Bind framebuffer for both drawing + reading
835
    procedure Bind;
836
    // Bind framebuffer for drawing
837
    procedure BindForDrawing;
838
    // Bind framebuffer for reading
839
    procedure BindForReading;
840
    { Note that it is not necessary to unbind before binding another framebuffer. }
841
    procedure UnBind;
842
    procedure UnBindForDrawing;
843
    procedure UnBindForReading;
844
    // target = GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER (attach to both READ + DRAW)
845
    // attachment = COLOR_ATTACHMENTi, DEPTH_ATTACHMENT, STENCIL_ATTACHMENT, DEPTH_STENCIL_ATTACHMENT
846
    procedure Attach1DTexture(target: TGLenum; attachment: TGLenum; textarget:
847
      TGLenum; texture: TGLuint; level: TGLint);
848
    procedure Attach2DTexture(target: TGLenum; attachment: TGLenum; textarget:
849
      TGLenum; texture: TGLuint; level: TGLint);
850
    procedure Attach3DTexture(target: TGLenum; attachment: TGLenum; textarget:
851
      TGLenum; texture: TGLuint; level: TGLint; layer: TGLint);
852
    procedure AttachLayer(target: TGLenum; attachment: TGLenum; texture:
853
      TGLuint; level: TGLint; layer: TGLint);
854
    procedure AttachRenderBuffer(target: TGLenum; attachment: TGLenum;
855
      renderbuffertarget: TGLenum; renderbuffer: TGLuint);
856
    // OpenGL 3.2+ only.
857
    // If texture is the name of a three-dimensional texture, cube map texture, one-or
858
    // two-dimensional array texture, or two-dimensional multisample array texture, the
859
    // texture level attached to the framebuffer attachment point is an array of images,
860
    // and the framebuffer attachment is considered layered.
861
    procedure AttachTexture(target: TGLenum; attachment: TGLenum; texture:
862
      TGLuint; level: TGLint);
863
    // OpenGL 3.2+ only
864
    procedure AttachTextureLayer(target: TGLenum; attachment: TGLenum; texture:
865
      TGLuint; level: TGLint; layer: TGLint);
866

867
    // copy rect from bound read framebuffer to bound draw framebuffer
868
    procedure Blit(srcX0: TGLint; srcY0: TGLint; srcX1: TGLint; srcY1: TGLint;
869
      dstX0: TGLint; dstY0: TGLint; dstX1: TGLint; dstY1: TGLint;
870
      mask: TGLbitfield; filter: TGLenum);
871
    // target = GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER (equivalent to GL_DRAW_FRAMEBUFFER)
872
    // If default framebuffer (0) is bound:
873
    // attachment = GL_FRONT_LEFT, GL_FRONT_RIGHT, GL_BACK_LEFT, or GL_BACK_RIGHT, GL_DEPTH, GL_STENCIL
874
    // if a framebuffer object is bound:
875
    // attachment = GL_COLOR_ATTACHMENTi, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT, GL_DEPTH_STENCIL_ATTACHMENT
876
    // param = GL_FRAMEBUFFER_ATTACHMENT_(OBJECT_TYPE, OBJECT_NAME,
877
    //       RED_SIZE, GREEN_SIZE, BLUE_SIZE, ALPHA_SIZE, DEPTH_SIZE, STENCIL_SIZE,
878
    //       COMPONENT_TYPE, COLOR_ENCODING, TEXTURE_LEVEL, LAYERED, TEXTURE_CUBE_MAP_FACE, TEXTURE_LAYER
879
    function GetAttachmentParameter(target: TGLenum; attachment: TGLenum; pname:
880
      TGLenum): TGLint;
881
    // Returns the type of object bound to attachment point:
882
    // GL_NONE, GL_FRAMEBUFFER_DEFAULT, GL_TEXTURE, or GL_RENDERBUFFER
883
    function GetAttachmentObjectType(target: TGLenum; attachment: TGLenum):
884
      TGLint;
885
    // Returns the name (ID) of the texture or renderbuffer attached to attachment point
886
    function GetAttachmentObjectName(target: TGLenum; attachment: TGLenum):
887
      TGLint;
888

889
    function GetStatus: TGLFramebufferStatus;
890
    function GetStringStatus(out clarification: string): TGLFramebufferStatus;
891

892
    class function IsSupported: Boolean; override;
893
  end;
894

895
  // TGLRenderbufferHandle
896
  //
897
  { Manages a handle to a Renderbuffer Object.
898
     A Renderbuffer is a "framebuffer-attachable image" for generalized offscreen
899
     rendering and it also provides a means to support rendering to GL logical
900
     buffer types which have no corresponding texture format (stencil, accum, etc). }
901
  TGLRenderbufferHandle = class(TGLContextHandle)
902
  protected
903
    function DoAllocateHandle: Cardinal; override;
904
    procedure DoDestroyHandle(var AHandle: TGLuint); override;
905
    class function IsValid(const ID: GLuint): Boolean; override;
906
  public
907
    procedure Bind;
908
    procedure UnBind;
909
    procedure SetStorage(internalformat: TGLenum; width, height: TGLsizei);
910
    procedure SetStorageMultisample(internalformat: TGLenum; samples: TGLsizei;
911
      width, height: TGLsizei);
912
    class function IsSupported: Boolean; override;
913
  end;
914

915
  TGLARBProgramHandle = class(TGLContextHandle)
916
  private
917
     
918
    FReady: Boolean;
919
    FInfoLog: string;
920
  protected
921
     
922
    function DoAllocateHandle: Cardinal; override;
923
    procedure DoDestroyHandle(var AHandle: TGLuint); override;
924
    class function IsValid(const ID: GLuint): Boolean; override;
925
    class function GetTarget: TGLenum; virtual; abstract;
926
  public
927
     
928
    procedure LoadARBProgram(AText: string);
929
    procedure Enable;
930
    procedure Disable;
931
    procedure Bind;
932
    property Ready: Boolean read FReady;
933
    property InfoLog: string read FInfoLog;
934
  end;
935

936
  TGLARBVertexProgramHandle = class(TGLARBProgramHandle)
937
  protected
938
     
939
    class function GetTarget: TGLenum; override;
940
  public
941
     
942
    class function IsSupported: Boolean; override;
943
  end;
944

945
  TGLARBFragmentProgramHandle = class(TGLARBProgramHandle)
946
  protected
947
     
948
    class function GetTarget: TGLenum; override;
949
  public
950
     
951
    class function IsSupported: Boolean; override;
952
  end;
953

954
  TGLARBGeometryProgramHandle = class(TGLARBProgramHandle)
955
  protected
956
     
957
    class function GetTarget: TGLenum; override;
958
  public
959
     
960
    class function IsSupported: Boolean; override;
961
  end;
962

963
  // TGLSLHandle
964
  //
965
  { Base class for GLSL handles (programs and shaders).
966
     Do not use this class directly, use one of its subclasses instead. }
967
  TGLSLHandle = class(TGLContextHandle)
968
  private
969
     
970

971
  protected
972
     
973
    procedure DoDestroyHandle(var AHandle: TGLuint); override;
974

975
  public
976
     
977
    function InfoLog: string;
978
    class function IsSupported: Boolean; override;
979
  end;
980

981
  // TGLShaderHandle
982
  //
983
  { Manages a handle to a Shader Object. 
984
     Does *NOT* check for extension availability, this is assumed to have been
985
     checked by the user. 
986
     Do not use this class directly, use one of its subclasses instead. }
987
  TGLShaderHandle = class(TGLSLHandle)
988
  private
989
     
990
    FShaderType: Cardinal;
991

992
  protected
993
     
994
    function DoAllocateHandle: Cardinal; override;
995
    class function IsValid(const ID: GLuint): Boolean; override;
996
  public
997
     
998
    procedure ShaderSource(const source: AnsiString); overload;
999
    // Returns True if compilation sucessful
1000
    function CompileShader: Boolean;
1001

1002
    property ShaderType: Cardinal read FShaderType;
1003
  end;
1004

1005
  TGLShaderHandleClass = class of TGLShaderHandle;
1006

1007
  // TGLVertexShaderHandle
1008
  //
1009
  { Manages a handle to a Vertex Shader Object. }
1010
  TGLVertexShaderHandle = class(TGLShaderHandle)
1011
  public
1012
     
1013
    constructor Create; override;
1014
    class function IsSupported: Boolean; override;
1015
  end;
1016

1017
  // TGLGeometryShaderHandle
1018
  //
1019
  { Manages a handle to a Geometry Shader Object. }
1020
  TGLGeometryShaderHandle = class(TGLShaderHandle)
1021
  public
1022
     
1023
    constructor Create; override;
1024
    class function IsSupported: Boolean; override;
1025
  end;
1026

1027
  // TGLFragmentShaderHandle
1028
  //
1029
  { Manages a handle to a Fragment Shader Object. }
1030
  TGLFragmentShaderHandle = class(TGLShaderHandle)
1031
  public
1032
     
1033
    constructor Create; override;
1034
    class function IsSupported: Boolean; override;
1035
  end;
1036

1037
  // TGLTessControlShaderHandle
1038
  //
1039
  { Manages a handle to a Tessellation Control Shader Object. }
1040
  TGLTessControlShaderHandle = class(TGLShaderHandle)
1041
  public
1042
     
1043
    constructor Create; override;
1044
    class function IsSupported: Boolean; override;
1045
  end;
1046

1047
  // TGLTessEvaluationShaderHandle
1048
  //
1049
  { Manages a handle to a Tessellation Evaluation Shader Object. }
1050
  TGLTessEvaluationShaderHandle = class(TGLShaderHandle)
1051
  public
1052
     
1053
    constructor Create; override;
1054
    class function IsSupported: Boolean; override;
1055
  end;
1056

1057
  // TGLProgramHandle
1058
  //
1059
  { Manages a GLSL Program Object. 
1060
     Does *NOT* check for extension availability, this is assumed to have been
1061
     checked by the user.  }
1062
  TGLProgramHandle = class(TGLSLHandle)
1063
  public
1064
    class function IsValid(const ID: GLuint): Boolean; override;
1065
  private
1066
     
1067
    FName: string;
1068
    function GetUniform1i(const index: string): Integer;
1069
    procedure SetUniform1i(const index: string; val: Integer);
1070
    function GetUniform2i(const index: string): TVector2i;
1071
    procedure SetUniform2i(const index: string; const Value: TVector2i);
1072
    function GetUniform3i(const index: string): TVector3i;
1073
    procedure SetUniform3i(const index: string; const Value: TVector3i);
1074
    function GetUniform4i(const index: string): TVector4i;
1075
    procedure SetUniform4i(const index: string; const Value: TVector4i);
1076

1077
    function GetUniform1f(const index: string): Single;
1078
    procedure SetUniform1f(const index: string; val: Single);
1079
    function GetUniform2f(const index: string): TVector2f;
1080
    procedure SetUniform2f(const index: string; const val: TVector2f);
1081
    function GetUniform3f(const index: string): TAffineVector;
1082
    procedure SetUniform3f(const index: string; const val: TAffineVector);
1083
    function GetUniform4f(const index: string): TVector;
1084
    procedure SetUniform4f(const index: string; const val: TVector);
1085

1086
    function GetUniformMatrix2fv(const index: string): TMatrix2f;
1087
    procedure SetUniformMatrix2fv(const index: string; const val: TMatrix2f);
1088
    function GetUniformMatrix3fv(const index: string): TMatrix3f;
1089
    procedure SetUniformMatrix3fv(const index: string; const val: TMatrix3f);
1090
    function GetUniformMatrix4fv(const index: string): TMatrix;
1091
    procedure SetUniformMatrix4fv(const index: string; const val: TMatrix);
1092

1093
    function GetUniformTextureHandle(const index: string;
1094
      const TextureIndex: Integer; const TextureTarget: TGLTextureTarget):
1095
      Cardinal;
1096
    procedure SetUniformTextureHandle(const index: string;
1097
      const TextureIndex: Integer; const TextureTarget: TGLTextureTarget;
1098
      const Value: Cardinal);
1099
    procedure SetUniformBuffer(const index: string;
1100
      Value: TGLUniformBufferHandle);
1101
  protected
1102
     
1103
    function DoAllocateHandle: cardinal; override;
1104

1105
  public
1106
     
1107
    property Name: string read FName write FName;
1108

1109
    constructor Create; override;
1110

1111
    { Compile and attach a new shader.
1112
       Raises an EGLShader exception in case of failure. }
1113
    procedure AddShader(shaderType: TGLShaderHandleClass; const shaderSource:
1114
      string;
1115
      treatWarningsAsErrors: Boolean = False);
1116

1117
    procedure AttachObject(shader: TGLShaderHandle);
1118
    procedure DetachAllObject;
1119
    procedure BindAttribLocation(index: Integer; const aName: string);
1120
    procedure BindFragDataLocation(index: Integer; const aName: string);
1121
    function LinkProgram: Boolean;
1122
    function ValidateProgram: Boolean;
1123
    function GetAttribLocation(const aName: string): Integer;
1124
    function GetUniformLocation(const aName: string): Integer;
1125
    function GetUniformOffset(const aName: string): PGLInt;
1126
    function GetUniformBlockIndex(const aName: string): Integer;
1127

1128
    function GetVaryingLocation(const aName: string): Integer;
1129
    // Currently, NVidia-specific.
1130
    procedure AddActiveVarying(const aName: string);
1131
    // Currently, NVidia-specific.
1132

1133
    function GetUniformBufferSize(const aName: string): Integer;
1134

1135
    procedure UseProgramObject;
1136
    procedure EndUseProgramObject;
1137

1138
    procedure SetUniformi(const index: string; const val: integer); overload;
1139
    procedure SetUniformi(const index: string; const val: TVector2i); overload;
1140
    procedure SetUniformi(const index: string; const val: TVector3i); overload;
1141
    procedure SetUniformi(const index: string; const val: TVector4i); overload;
1142

1143
    procedure SetUniformf(const index: string; const val: single); overload;
1144
    procedure SetUniformf(const index: string; const val: TVector2f); overload;
1145
    procedure SetUniformf(const index: string; const val: TVector3f); overload;
1146
    procedure SetUniformf(const index: string; const val: TVector4f); overload;
1147

1148
    { Shader parameters. }
1149
    property Uniform1i[const index: string]: Integer read GetUniform1i write
1150
    SetUniform1i;
1151
    property Uniform2i[const index: string]: TVector2i read GetUniform2i write
1152
    SetUniform2i;
1153
    property Uniform3i[const index: string]: TVector3i read GetUniform3i write
1154
    SetUniform3i;
1155
    property Uniform4i[const index: string]: TVector4i read GetUniform4i write
1156
    SetUniform4i;
1157

1158
    property Uniform1f[const index: string]: Single read GetUniform1f write
1159
    SetUniform1f;
1160
    property Uniform2f[const index: string]: TVector2f read GetUniform2f write
1161
    SetUniform2f;
1162
    property Uniform3f[const index: string]: TAffineVector read GetUniform3f
1163
    write SetUniform3f;
1164
    property Uniform4f[const index: string]: TVector read GetUniform4f write
1165
    SetUniform4f;
1166

1167
    property UniformMatrix2fv[const index: string]: TMatrix2f read
1168
    GetUniformMatrix2fv write SetUniformMatrix2fv;
1169
    property UniformMatrix3fv[const index: string]: TMatrix3f read
1170
    GetUniformMatrix3fv write SetUniformMatrix3fv;
1171
    property UniformMatrix4fv[const index: string]: TMatrix read
1172
    GetUniformMatrix4fv write SetUniformMatrix4fv;
1173

1174
    property UniformTextureHandle[const index: string; const TextureIndex:
1175
    Integer; const TextureTarget: TGLTextureTarget]: Cardinal read
1176
    GetUniformTextureHandle write SetUniformTextureHandle;
1177
    property UniformBuffer[const index: string]: TGLUniformBufferHandle write
1178
    SetUniformBuffer;
1179
  end;
1180

1181
  // TGLContextNotification
1182
  //
1183
  TGLContextNotification = record
1184
    obj: TObject;
1185
    event: TNotifyEvent;
1186
  end;
1187

1188
  // TGLContextManager
1189
  //
1190
  { Stores and manages all the TGLContext objects. }
1191
  TGLContextManager = class
1192
  private
1193
     
1194
    FList: TThreadList;
1195
    FTerminated: Boolean;
1196
    FNotifications: array of TGLContextNotification;
1197
    FCreatedRCCount: Integer;
1198

1199
{$IFNDEF GLS_MULTITHREAD}
1200
    FHandles: TList;
1201
{$ELSE}
1202
    FHandles: TThreadList;
1203
{$ENDIF GLS_MULTITHREAD}
1204

1205
{$IFDEF GLS_SERVICE_CONTEXT}
1206
    FThread: TThread;
1207
    FServiceStarter: TEvent;
1208
    FThreadTask: TServiceContextTaskList;
1209
{$ENDIF}
1210
    FServiceContext: TGLContext;
1211
  protected
1212
     
1213
    procedure Lock;
1214
    procedure UnLock;
1215

1216
    procedure RegisterContext(aContext: TGLContext);
1217
    procedure UnRegisterContext(aContext: TGLContext);
1218

1219
    procedure ContextCreatedBy(aContext: TGLContext);
1220
    procedure DestroyingContextBy(aContext: TGLContext);
1221

1222
{$IFDEF GLS_SERVICE_CONTEXT}
1223
    { Create a special service and resource-keeper context. }
1224
    procedure CreateServiceContext;
1225
    procedure QueueTaskDepleted; register;
1226
    property ServiceStarter: TEvent read FServiceStarter;
1227
{$ENDIF}
1228
    property ServiceContext: TGLContext read FServiceContext;
1229
  public
1230
     
1231
    constructor Create;
1232
    destructor Destroy; override;
1233

1234
    {: Returns an appropriate, ready-to use context.
1235
       The returned context should be freed by caller. }
1236
    function CreateContext(AClass: TGLContextClass = nil): TGLContext;
1237

1238
    {: Returns the number of TGLContext object.
1239
       This is *not* the number of OpenGL rendering contexts! }
1240
    function ContextCount: Integer;
1241
    { Registers a new object to notify when the last context is destroyed.
1242
       When the last rendering context is destroyed, the 'anEvent' will
1243
       be invoked with 'anObject' as parameter. 
1244
       Note that the registration is kept until the notification is triggered
1245
       or a RemoveNotification on 'anObject' is issued. }
1246
    procedure LastContextDestroyNotification(anObject: TObject; anEvent:
1247
      TNotifyEvent);
1248
    { Unregisters an object from the notification lists. }
1249
    procedure RemoveNotification(anObject: TObject);
1250

1251
    // Marks the context manager for termination
1252
    procedure Terminate;
1253

1254
    { Request all contexts to destroy all their handles. }
1255
    procedure DestroyAllHandles;
1256

1257
    { Notify all contexts about necessity of handles preparation. }
1258
    procedure NotifyPreparationNeed;
1259
  end;
1260

1261
  EGLContext = class(Exception);
1262

1263
  EPBuffer = class(Exception);
1264

1265
  EGLShader = class(EGLContext);
1266

1267
  { Drivers should register themselves via this function. }
1268
procedure RegisterGLContextClass(aGLContextClass: TGLContextClass);
1269
{ The TGLContext that is the currently active context, if any.
1270
   Returns nil if no context is active. }
1271
function CurrentGLContext: TGLContext;
1272
function SafeCurrentGLContext: TGLContext;
1273
function GL: TGLExtensionsAndEntryPoints;
1274
function IsMainThread: Boolean;
1275
function IsServiceContextAvaible: Boolean;
1276
function GetServiceWindow: TForm;
1277
{$IFDEF GLS_SERVICE_CONTEXT}
1278
procedure AddTaskForServiceContext(ATask: TTaskProcedure; FinishEvent: TFinishTaskEvent = nil);
1279
{$ENDIF}
1280

1281
resourcestring
1282
  cIncompatibleContexts = 'Incompatible contexts';
1283
  cDeleteContextFailed = 'Delete context failed';
1284
  cContextActivationFailed = 'Context activation failed: %X, %s';
1285
  cContextDeactivationFailed = 'Context deactivation failed';
1286
  cUnableToCreateLegacyContext = 'Unable to create legacy context';
1287
  cNoActiveRC = 'No active rendering context';
1288
  glsFailedToShare = 'DoCreateContext - Failed to share contexts';
1289

1290
var
1291
  GLContextManager: TGLContextManager;
1292
  vIgnoreOpenGLErrors: Boolean = False;
1293
  vContextActivationFailureOccurred: Boolean = false;
1294
  vMultitextureCoordinatorClass: TAbstractMultitextureCoordinatorClass;
1295

1296
  // ------------------------------------------------------------------
1297
  // ------------------------------------------------------------------
1298
  // ------------------------------------------------------------------
1299
implementation
1300
// ------------------------------------------------------------------
1301
// ------------------------------------------------------------------
1302
// ------------------------------------------------------------------
1303

1304
resourcestring
1305
  cCannotAlterAnActiveContext = 'Cannot alter an active context';
1306
  cInvalidContextRegistration = 'Invalid context registration';
1307
  cInvalidNotificationRemoval = 'Invalid notification removal';
1308
  cContextAlreadyCreated = 'Context already created';
1309
  cContextNotCreated = 'Context not created';
1310
  cUnbalancedContexActivations = 'Unbalanced context activations';
1311

1312
{$IFDEF GLS_SERVICE_CONTEXT}
1313
type
1314
  // TServiceContextThread
1315
  //
1316
  TServiceContextThread = class(TThread)
1317
  private
1318
    FDC: HDC;
1319
    FWindow: TForm;
1320
    FLastTaskStartTime: Double;
1321
    FReported: Boolean;
1322
  protected
1323
    procedure Execute; override;
1324
    procedure DoCreateServiceContext; stdcall;
1325
  public
1326
    constructor Create;
1327
    destructor Destroy; override;
1328
  end;
1329
{$ENDIF}
1330

1331
var
1332
  vContextClasses: TList;
1333
  GLwithoutContext: TGLExtensionsAndEntryPoints;
1334
  vServiceWindow: TForm;
1335
{$IFDEF GLS_SERVICE_CONTEXT}
1336
  OldInitProc: Pointer;
1337
{$ENDIF}
1338

1339
{$IFNDEF GLS_MULTITHREAD}
1340
var
1341
{$ELSE}
1342
threadvar
1343
{$ENDIF}
1344
  vGL: TGLExtensionsAndEntryPoints;
1345
  vCurrentGLContext: TGLContext;
1346
  vMainThread: Boolean;
1347

1348
  // CurrentGLContext
1349
  //
1350

1351
function CurrentGLContext: TGLContext;
1352
begin
1353
  Result := vCurrentGLContext;
1354
end;
1355

1356
function SafeCurrentGLContext: TGLContext;
1357
begin
1358
  Result := CurrentGLContext;
1359
  if not Assigned(Result) then
1360
  begin
1361
   {$IFDEF GLS_LOGGING}
1362
    GLSLogger.LogError(cNoActiveRC);
1363
   {$ENDIF}
1364
    Abort;
1365
  end;
1366
end;
1367

1368
function GL: TGLExtensionsAndEntryPoints;
1369
begin
1370
  Result := vGL;
1371
end;
1372

1373
function IsMainThread: Boolean;
1374
begin
1375
  Result := vMainThread;
1376
end;
1377

1378
function IsServiceContextAvaible: Boolean;
1379
begin
1380
  Result := GLContextManager.ServiceContext <> nil;
1381
end;
1382

1383
function GetServiceWindow: TForm;
1384
begin
1385
  Result := vServiceWindow;
1386
end;
1387

1388

1389
// RegisterGLContextClass
1390
//
1391

1392
procedure RegisterGLContextClass(aGLContextClass: TGLContextClass);
1393
begin
1394
  if not Assigned(vContextClasses) then
1395
    vContextClasses := TList.Create;
1396
  vContextClasses.Add(aGLContextClass);
1397
end;
1398

1399
constructor TAbstractMultitextureCoordinator.Create(AOwner: TGLContext);
1400
begin
1401
  FOwner := AOwner;
1402
end;
1403

1404
// ------------------
1405
// ------------------ TGLContext ------------------
1406
// ------------------
1407

1408
// Create
1409
//
1410

1411
constructor TGLContext.Create;
1412
begin
1413
  inherited Create;
1414
{$IFDEF GLS_MULTITHREAD}
1415
  FLock := TCriticalSection.Create;
1416
{$ENDIF}
1417
  FColorBits := 32;
1418
  FStencilBits := 0;
1419
  FAccumBits := 0;
1420
  FAuxBuffers := 0;
1421
  FLayer := clMainPlane;
1422
  FOptions := [];
1423
{$IFNDEF GLS_MULTITHREAD}
1424
  FSharedContexts := TList.Create;
1425
{$ELSE}
1426
  FSharedContexts := TThreadList.Create;
1427
{$ENDIF}
1428
  FSharedContexts.Add(Self);
1429
  FAcceleration := chaUnknown;
1430
  FGLStates := TGLStateCache.Create;
1431
  FGL := TGLExtensionsAndEntryPoints.Create;
1432
  FTransformation := TGLTransformation.Create;
1433
  FTransformation.LoadMatricesEnabled := True;
1434
  GLContextManager.RegisterContext(Self);
1435
  FIsPraparationNeed := True;
1436
end;
1437

1438
// Destroy
1439
//
1440

1441
destructor TGLContext.Destroy;
1442
begin
1443
  if IsValid then
1444
    DestroyContext;
1445
  GLContextManager.UnRegisterContext(Self);
1446
  FGLStates.Free;
1447
  FGL.Free;
1448
  FXGL.Free;
1449
  FTransformation.Free;
1450
  FSharedContexts.Free;
1451
{$IFDEF GLS_MULTITHREAD}
1452
  FLock.Free;
1453
{$ENDIF}
1454
  inherited Destroy;
1455
end;
1456

1457
// SetColorBits
1458
//
1459

1460
procedure TGLContext.SetColorBits(const aColorBits: Integer);
1461
begin
1462
  if Active then
1463
    raise EGLContext.Create(cCannotAlterAnActiveContext)
1464
  else
1465
    FColorBits := aColorBits;
1466
end;
1467

1468
// SetAlphaBits
1469
//
1470

1471
procedure TGLContext.SetAlphaBits(const aAlphaBits: Integer);
1472
begin
1473
  if Active then
1474
    raise EGLContext.Create(cCannotAlterAnActiveContext)
1475
  else
1476
    FAlphaBits := aAlphaBits;
1477
end;
1478

1479
// SetDepthBits
1480
//
1481

1482
procedure TGLContext.SetDepthBits(const val: Integer);
1483
begin
1484
  if Active then
1485
    raise EGLContext.Create(cCannotAlterAnActiveContext)
1486
  else
1487
    FDepthBits := val;
1488
end;
1489

1490
procedure TGLContext.SetLayer(const Value: TGLContextLayer);
1491
begin
1492
  if Active then
1493
    raise EGLContext.Create(cCannotAlterAnActiveContext)
1494
  else
1495
    FLayer := Value;
1496
end;
1497

1498
// SetStencilBits
1499
//
1500

1501
procedure TGLContext.SetStencilBits(const aStencilBits: Integer);
1502
begin
1503
  if Active then
1504
    raise EGLContext.Create(cCannotAlterAnActiveContext)
1505
  else
1506
    FStencilBits := aStencilBits;
1507
end;
1508

1509
// SetAccumBits
1510
//
1511

1512
procedure TGLContext.SetAccumBits(const aAccumBits: Integer);
1513
begin
1514
  if Active then
1515
    raise EGLContext.Create(cCannotAlterAnActiveContext)
1516
  else
1517
    FAccumBits := aAccumBits;
1518
end;
1519

1520
// SetAuxBuffers
1521
//
1522

1523
procedure TGLContext.SetAuxBuffers(const aAuxBuffers: Integer);
1524
begin
1525
  if Active then
1526
    raise EGLContext.Create(cCannotAlterAnActiveContext)
1527
  else
1528
    FAuxBuffers := aAuxBuffers;
1529
end;
1530

1531
// SetOptions
1532
//
1533

1534
procedure TGLContext.SetOptions(const aOptions: TGLRCOptions);
1535
begin
1536
  if Active then
1537
    raise EGLContext.Create(cCannotAlterAnActiveContext)
1538
  else
1539
    FOptions := aOptions;
1540
end;
1541

1542
// SetAntiAliasing
1543
//
1544

1545
procedure TGLContext.SetAntiAliasing(const val: TGLAntiAliasing);
1546
begin
1547
  if Active then
1548
    raise EGLContext.Create(cCannotAlterAnActiveContext)
1549
  else
1550
    FAntiAliasing := val;
1551
end;
1552

1553
// SetAcceleration
1554
//
1555

1556
procedure TGLContext.SetAcceleration(const val: TGLContextAcceleration);
1557
begin
1558
  if Active then
1559
    raise EGLContext.Create(cCannotAlterAnActiveContext)
1560
  else
1561
    FAcceleration := val;
1562
end;
1563

1564
// GetActive
1565
//
1566

1567
function TGLContext.GetActive: Boolean;
1568
begin
1569
  Result := (FActivationCount > 0);
1570
end;
1571

1572
// SetActive
1573
//
1574

1575
procedure TGLContext.SetActive(const aActive: Boolean);
1576
begin
1577
  // activation/deactivation can be nested...
1578
  while aActive <> Active do
1579
  begin
1580
    if aActive then
1581
      Activate
1582
    else
1583
      Deactivate;
1584
  end;
1585
end;
1586

1587
// CreateContext
1588
//
1589

1590
procedure TGLContext.CreateContext(ADeviceHandle: HDC);
1591
begin
1592
  if IsValid then
1593
    raise EGLContext.Create(cContextAlreadyCreated);
1594
  DoCreateContext(ADeviceHandle);
1595
  Manager.ContextCreatedBy(Self);
1596
end;
1597

1598
// CreateMemoryContext
1599
//
1600

1601
procedure TGLContext.CreateMemoryContext(outputDevice: HWND;
1602
  width, height: Integer; BufferCount: integer);
1603
begin
1604
  if IsValid then
1605
    raise EGLContext.Create(cContextAlreadyCreated);
1606
  DoCreateMemoryContext(outputDevice, width, height, BufferCount);
1607
  Manager.ContextCreatedBy(Self);
1608
end;
1609

1610
// PrepareHandlesData
1611
//
1612

1613
procedure TGLContext.PrepareHandlesData;
1614
var
1615
  I: Integer;
1616
  LHandle: TGLContextHandle;
1617
begin
1618
  if vCurrentGLContext = Self then
1619
  begin
1620
{$IFNDEF GLS_MULTITHREAD}
1621
    for i := Manager.FHandles.Count - 1 downto 0 do
1622
    begin
1623
      LHandle := TGLContextHandle(Manager.FHandles[i]);
1624
      if Assigned(LHandle.FOnPrepare) then
1625
        LHandle.FOnPrepare(Self);
1626
    end;
1627
{$ELSE}
1628
    with Manager.FHandles.LockList do
1629
      try
1630
        for i := Count - 1 downto 0 do
1631
        begin
1632
          LHandle := TGLContextHandle(Items[i]);
1633
          if Assigned(LHandle.FOnPrepare) then
1634
            LHandle.FOnPrepare(Self);
1635
        end;
1636
      finally
1637
        Manager.FHandles.UnlockList;
1638
      end;
1639
{$ENDIF}
1640
    FIsPraparationNeed := False;
1641
  end;
1642
end;
1643

1644
// PropagateSharedContext
1645
//
1646

1647
procedure TGLContext.PropagateSharedContext;
1648
var
1649
  i, j: Integer;
1650
  otherContext: TGLContext;
1651
  otherList: TList;
1652
begin
1653
{$IFNDEF GLS_MULTITHREAD}
1654
  with FSharedContexts do
1655
  begin
1656
    for i := 1 to Count - 1 do
1657
    begin
1658
      otherContext := TGLContext(Items[i]);
1659
      otherList := otherContext.FSharedContexts;
1660
      for J := 0 to otherList.Count - 1 do
1661
        if IndexOf(otherList[J]) < 0 then
1662
          Add(otherList[J]);
1663
    end;
1664
    for i := 1 to Count - 1 do
1665
    begin
1666
      otherContext := TGLContext(Items[i]);
1667
      otherList := otherContext.FSharedContexts;
1668
      if otherList.IndexOf(Self) < 0 then
1669
        otherList.Add(Self);
1670
    end;
1671
  end;
1672
{$ELSE}
1673
  with FSharedContexts.LockList do
1674
    try
1675
      for i := 1 to Count - 1 do
1676
      begin
1677
        otherContext := TGLContext(Items[i]);
1678
        otherList := otherContext.FSharedContexts.LockList;
1679
        for J := 0 to otherList.Count - 1 do
1680
          if IndexOf(otherList[J]) < 0 then
1681
            Add(otherList[J]);
1682
        otherContext.FSharedContexts.UnlockList;
1683
      end;
1684
      for i := 1 to Count - 1 do
1685
      begin
1686
        otherContext := TGLContext(Items[i]);
1687
        otherList := otherContext.FSharedContexts.LockList;
1688
        if otherList.IndexOf(Self) < 0 then
1689
          otherList.Add(Self);
1690
        otherContext.FSharedContexts.UnlockList;
1691
      end;
1692
    finally
1693
      FSharedContexts.UnlockList;
1694
    end;
1695
{$ENDIF}
1696
end;
1697

1698
// ShareLists
1699
//
1700

1701
procedure TGLContext.ShareLists(aContext: TGLContext);
1702
begin
1703
{$IFNDEF GLS_MULTITHREAD}
1704
  if FSharedContexts.IndexOf(aContext) < 0 then
1705
  begin
1706
    if DoShareLists(aContext) then
1707
    begin
1708
      FSharedContexts.Add(aContext);
1709
      PropagateSharedContext;
1710
    end;
1711
  end;
1712
{$ELSE}
1713
  with FSharedContexts.LockList do
1714
    try
1715
      if IndexOf(aContext) < 0 then
1716
      begin
1717
        if DoShareLists(aContext) then
1718
        begin
1719
          Add(aContext);
1720
          PropagateSharedContext;
1721
        end;
1722
      end;
1723
    finally
1724
      FSharedContexts.UnlockList;
1725
    end;
1726
{$ENDIF}
1727
end;
1728

1729
// DestroyAllHandles
1730
//
1731

1732
procedure TGLContext.DestroyAllHandles;
1733
var
1734
  i: Integer;
1735
begin
1736
  Activate;
1737
  try
1738
{$IFNDEF GLS_MULTITHREAD}
1739
    for i := Manager.FHandles.Count - 1 downto 0 do
1740
      TGLContextHandle(Manager.FHandles[i]).ContextDestroying;
1741
{$ELSE}
1742
    with Manager.FHandles.LockList do
1743
      try
1744
        for i := Count - 1 downto 0 do
1745
          TGLContextHandle(Items[i]).ContextDestroying;
1746
      finally
1747
        Manager.FHandles.UnlockList;
1748
      end;
1749
{$ENDIF}
1750
  finally
1751
    Deactivate;
1752
  end;
1753
end;
1754

1755
// DestroyContext
1756
//
1757

1758
procedure TGLContext.DestroyContext;
1759
var
1760
  I: Integer;
1761
  oldContext, otherContext: TGLContext;
1762
  contextHandle: TGLContextHandle;
1763
  aList: TList;
1764
begin
1765

1766
  if vCurrentGLContext <> Self then
1767
  begin
1768
    oldContext := vCurrentGLContext;
1769
    if Assigned(oldContext) then
1770
      oldContext.Deactivate;
1771
  end
1772
  else
1773
    oldContext := nil;
1774

1775
  Activate;
1776
  try
1777
{$IFNDEF GLS_MULTITHREAD}
1778
    for i := Manager.FHandles.Count - 1 downto 0 do
1779
    begin
1780
      contextHandle := TGLContextHandle(Manager.FHandles[i]);
1781
      contextHandle.ContextDestroying;
1782
    end;
1783
{$ELSE}
1784
    aList := Manager.FHandles.LockList;
1785
    try
1786
      for i := aList.Count - 1 downto 0 do
1787
      begin
1788
        contextHandle := TGLContextHandle(aList[i]);
1789
        contextHandle.ContextDestroying;
1790
      end;
1791
    finally
1792
      Manager.FHandles.UnlockList;
1793
    end;
1794
{$ENDIF}
1795
    Manager.DestroyingContextBy(Self);
1796

1797
{$IFDEF GLS_MULTITHREAD}
1798
    aList := FSharedContexts.LockList;
1799
{$ELSE}
1800
    aList := FSharedContexts;
1801
{$ENDIF}
1802
    for I := 1 to aList.Count - 1 do
1803
    begin
1804
      otherContext := TGLContext(aList[I]);
1805
      otherContext.FSharedContexts.Remove(Self);
1806
    end;
1807
    FSharedContexts.Clear;
1808
    FSharedContexts.Add(Self);
1809
{$IFDEF GLS_MULTITHREAD}
1810
    FSharedContexts.UnlockList;
1811
{$ENDIF}
1812
    Active := False;
1813
    DoDestroyContext;
1814
  finally
1815
    if Assigned(oldContext) then
1816
      oldContext.Activate;
1817
  end;
1818
  FAcceleration := chaUnknown;
1819
  FGL.Close;
1820
end;
1821

1822
// Activate
1823
//
1824

1825
procedure TGLContext.Activate;
1826
begin
1827
{$IFDEF GLS_MULTITHREAD}
1828
  FLock.Enter;
1829
{$ENDIF}
1830
  if FActivationCount = 0 then
1831
  begin
1832
    if not IsValid then
1833
      raise EGLContext.Create(cContextNotCreated);
1834

1835
    vContextActivationFailureOccurred := False;
1836
    try
1837
      DoActivate;
1838
    except
1839
      vContextActivationFailureOccurred := True;
1840
    end;
1841
    vGL := FGL;
1842
    vCurrentGLContext := Self;
1843
  end
1844
  else
1845
    Assert(vCurrentGLContext = Self, 'vCurrentGLContext <> Self');
1846
  Inc(FActivationCount);
1847
end;
1848

1849
// Deactivate
1850
//
1851

1852
procedure TGLContext.Deactivate;
1853
begin
1854
  Assert(vCurrentGLContext = Self);
1855
  Dec(FActivationCount);
1856
  if FActivationCount = 0 then
1857
  begin
1858
    if not IsValid then
1859
      raise EGLContext.Create(cContextNotCreated);
1860
    if not vContextActivationFailureOccurred then
1861
      DoDeactivate;
1862
    vCurrentGLContext := nil;
1863
    vGL := GLwithoutContext;
1864
  end
1865
  else if FActivationCount < 0 then
1866
    raise EGLContext.Create(cUnbalancedContexActivations);
1867
{$IFDEF GLS_MULTITHREAD}
1868
  FLock.Leave;
1869
{$ENDIF}
1870
end;
1871

1872
// FindCompatibleContext
1873
//
1874

1875
function TGLContext.FindCompatibleContext: TGLContext;
1876
var
1877
  i: Integer;
1878
begin
1879
  Result := nil;
1880
{$IFNDEF GLS_MULTITHREAD}
1881
  for i := 0 to FSharedContexts.Count - 1 do
1882
    if TGLContext(FSharedContexts[i]) <> Self then
1883
    begin
1884
      Result := TGLContext(FSharedContexts[i]);
1885
      Break;
1886
    end;
1887
{$ELSE}
1888
  with FSharedContexts.LockList do
1889
    try
1890
      for i := 0 to Count - 1 do
1891
        if TGLContext(Items[i]) <> Self then
1892
        begin
1893
          Result := TGLContext(Items[i]);
1894
          Break;
1895
        end;
1896
    finally
1897
      FSharedContexts.UnlockList;
1898
    end;
1899
{$ENDIF}
1900
end;
1901

1902
class function TGLContext.ServiceContext: TGLContext;
1903
begin
1904
  Result := GLContextManager.FServiceContext;
1905
end;
1906

1907
procedure TGLContext.MakeGLCurrent;
1908
begin
1909
  vGL := FGL;
1910
end;
1911

1912
function TGLContext.GetXGL: TAbstractMultitextureCoordinator;
1913
begin
1914
  if FXGL = nil then
1915
    FXGL := vMultitextureCoordinatorClass.Create(Self);
1916
  Result := FXGL;
1917
end;
1918

1919
// ------------------
1920
// ------------------ TGLContextHandle ------------------
1921
// ------------------
1922

1923
// Create
1924
//
1925

1926
constructor TGLContextHandle.Create;
1927
begin
1928
  inherited Create;
1929
  FHandles := TList.Create;
1930
  //first is a dummy record
1931
  new(FLastHandle);
1932
  FillChar(FLastHandle^, sizeof(FLastHandle^), 0);
1933
  FHandles.Add(FLastHandle);
1934
  GLContextManager.FHandles.Add(Self);
1935
end;
1936

1937
// CreateAndAllocate
1938
//
1939

1940
constructor TGLContextHandle.CreateAndAllocate(failIfAllocationFailed: Boolean =
1941
  True);
1942
begin
1943
  Create;
1944
  AllocateHandle;
1945
  if failIfAllocationFailed and (Handle = 0) then
1946
    raise EGLContext.Create('Auto-allocation failed');
1947
end;
1948

1949
// Destroy
1950
//
1951

1952
destructor TGLContextHandle.Destroy;
1953
var
1954
  i : integer;
1955
begin
1956
  DestroyHandle;
1957
  for i := 0 to FHandles.Count-1 do
1958
    Dispose(RCItem(i));
1959
  FHandles.Free;
1960
  if Assigned(GLContextManager) then
1961
    GLContextManager.FHandles.Remove(Self);
1962
  inherited Destroy;
1963
end;
1964

1965
// AllocateHandle
1966
//
1967

1968
function TGLContextHandle.AllocateHandle: TGLuint;
1969
var
1970
  I: Integer;
1971
  bSucces: Boolean;
1972
  aList: TList;
1973
  p : PGLRCHandle;
1974

1975
begin
1976
  // if handle aready allocated in current context
1977
  Result := GetHandle;
1978
  if Result <> 0 then
1979
    exit;
1980

1981
  if vCurrentGLContext = nil then
1982
  begin
1983
    GLSLogger.LogError('Failed to allocate OpenGL identifier - no active rendering context!');
1984
    exit;
1985
  end;
1986

1987
  //add entry
1988
  New(FLastHandle);
1989
  FillChar(FLastHandle^, sizeof(FLastHandle^), 0);
1990
  FHandles.Add(FLastHandle);
1991
  FLastHandle.FRenderingContext := vCurrentGLContext;
1992

1993
  bSucces := False;
1994
  if Transferable then
1995
  begin
1996
{$IFNDEF GLS_MULTITHREAD}
1997
    aList := vCurrentGLContext.FSharedContexts;
1998
{$ELSE}
1999
    aList := vCurrentGLContext.FSharedContexts.LockList;
2000
    try
2001
{$ENDIF}
2002
      for I := aList.Count - 1 downto 0 do
2003
      begin
2004
        P := SearchRC(aList[I]);
2005
        if (P.FHandle > 0) then
2006
        begin
2007
          // Copy shared handle
2008
          //FLastHandle.FRenderingContext := vCurrentGLContext;
2009
          FLastHandle.FHandle           := P.FHandle;
2010
          FLastHandle.FChanged          := P.FChanged;
2011
          Inc(vCurrentGLContext.FOwnedHandlesCount);
2012
          bSucces := True;
2013
          break;
2014
        end;
2015
      end;
2016
{$IFNDEF GLS_MULTITHREAD}
2017
{$ELSE}
2018
    finally
2019
      vCurrentGLContext.FSharedContexts.UnlockList;
2020
    end;
2021
{$ENDIF}
2022
  end;
2023

2024
  if not bSucces then
2025
  begin
2026
    // Allocate handle in current context
2027
    FLastHandle.FHandle := DoAllocateHandle;
2028
    bSucces := FLastHandle.FHandle <> 0;
2029
    FLastHandle.FChanged := bSucces;
2030
    if bSucces then
2031
      Inc(vCurrentGLContext.FOwnedHandlesCount);
2032
  end;
2033

2034
  Result := FLastHandle.FHandle;
2035
  if not bSucces then
2036
    GLSLogger.LogError(cNoActiveRC)
2037
  else if Assigned(FOnPrepare) then
2038
    GLContextManager.NotifyPreparationNeed;
2039
end;
2040

2041
function TGLContextHandle.IsAllocatedForContext(AContext: TGLContext = nil): Boolean;
2042
begin
2043
  Result := SearchRC(AContext).FHandle > 0;
2044
end;
2045

2046
function TGLContextHandle.SearchRC(AContext: TGLContext): PGLRCHandle;
2047
var
2048
  i : integer;
2049
begin
2050
  if AContext = nil then
2051
    AContext := vCurrentGLContext;
2052

2053
  if AContext = FLastHandle.FRenderingContext then
2054
  begin
2055
    Result := FLastHandle;
2056
    exit;
2057
  end;
2058

2059
  for i := 1 to FHandles.Count-1 do
2060
    if RCItem(i).FRenderingContext = AContext then
2061
    begin
2062
      Result := RCItem(i);
2063
      exit;
2064
    end;
2065

2066
  //first handle is always a dummy
2067
  Result := FHandles[0];
2068
end;
2069

2070
procedure TGLContextHandle.CheckCurrentRC;
2071
begin
2072
  if vCurrentGLContext <> FLastHandle.FRenderingContext then
2073
    FLastHandle := SearchRC(vCurrentGLContext);
2074
end;
2075

2076
function TGLContextHandle.GetHandle: TGLuint;
2077
begin
2078
//  CheckCurrentRC;
2079
//inline doesn't always work... so optimize it here
2080
  if vCurrentGLContext <> FLastHandle.FRenderingContext then
2081
    FLastHandle := SearchRC(vCurrentGLContext);
2082

2083
  Result := FLastHandle.FHandle;
2084
end;
2085

2086
// DestroyHandle
2087
//
2088

2089
procedure TGLContextHandle.DestroyHandle;
2090
var
2091
  oldContext: TGLContext;
2092
  P : PGLRCHandle;
2093
  I: Integer;
2094
begin
2095
  oldContext := vCurrentGLContext;
2096
  if Assigned(oldContext) then
2097
    oldContext.Deactivate;
2098
  try
2099
    for I := FHandles.Count-1 downto 1 do
2100
    begin
2101
      P := FHandles[I];
2102
      if P.FHandle > 0 then
2103
      begin
2104
        P.FRenderingContext.Activate;
2105
        if IsValid(P.FHandle) then
2106
          DoDestroyHandle(P.FHandle);
2107
        Dec(P.FRenderingContext.FOwnedHandlesCount);
2108
        P.FRenderingContext.Deactivate;
2109
        P.FRenderingContext := nil;
2110
        P.FHandle := 0;
2111
        P.FChanged := True;
2112
      end;
2113
      Dispose(P);
2114
    end;
2115
    FHandles.Count := 1; //delete all in 1 step
2116
    FLastHandle := FHandles[0];
2117
  finally
2118
    if Assigned(vCurrentGLContext) then
2119
      vCurrentGLContext.Deactivate;
2120
    if Assigned(oldContext) then
2121
      oldContext.Activate;
2122
  end;
2123
end;
2124

2125
// ContextDestroying
2126
//
2127

2128
procedure TGLContextHandle.ContextDestroying;
2129
var
2130
  I: Integer;
2131
  P: PGLRCHandle;
2132
  aList: TList;
2133
  bShared: Boolean;
2134
begin
2135
  if Assigned(vCurrentGLContext) then
2136
  begin
2137
    bShared := False;
2138
    if Transferable then
2139
    begin
2140
    {$IFNDEF GLS_MULTITHREAD}
2141
      aList := vCurrentGLContext.FSharedContexts;
2142
    {$ELSE}
2143
      aList := vCurrentGLContext.FSharedContexts.LockList;
2144
      try
2145
    {$ENDIF GLS_MULTITHREAD}
2146
        for I := FHandles.Count-1 downto 1 do
2147
        begin
2148
          P := RCItem(I);
2149
          if (P.FRenderingContext <> vCurrentGLContext)
2150
            and (P.FHandle <> 0)
2151
            and (aList.IndexOf(P.FRenderingContext) > -1) then
2152
            begin
2153
              bShared := True;
2154
              break;
2155
            end;
2156
        end;
2157
    {$IFDEF GLS_MULTITHREAD}
2158
      finally
2159
        vCurrentGLContext.FSharedContexts.UnLockList;
2160
      end;
2161
    {$ENDIF GLS_MULTITHREAD}
2162
    end;
2163

2164
    for I := FHandles.Count-1 downto 1 do
2165
    begin
2166
      P := RCItem(I);
2167
      if (P.FRenderingContext = vCurrentGLContext) and (P.FHandle <> 0) then
2168
      begin
2169
        if not bShared then
2170
          if IsValid(P.FHandle) then
2171
            DoDestroyHandle(P.FHandle);
2172
        Dec(P.FRenderingContext.FOwnedHandlesCount);
2173
        P.FHandle := 0;
2174
        P.FRenderingContext := nil;
2175
        P.FChanged := True;
2176
        Dispose(P);
2177
        FHandles.Delete(I);
2178
        if FLastHandle = P then
2179
          FLastHandle := FHandles[0];
2180
        exit;
2181
      end;
2182
    end;
2183
  end;
2184
end;
2185

2186
function TGLContextHandle.GetContext: TGLContext;
2187
var
2188
  I: Integer;
2189
  P: PGLRCHandle;
2190
begin
2191
  Result := nil;
2192
  // Return first context where handle is allocated
2193
  for I := FHandles.Count-1 downto 1 do
2194
  begin
2195
    P := RCItem(I);
2196
    if (P.FRenderingContext <> nil) and (P.FHandle <> 0) then
2197
    begin
2198
      Result := P.FRenderingContext;
2199
      // If handle allocated in active context - return it
2200
      if (Result = vCurrentGLContext) then
2201
        exit;
2202
    end;
2203
  end;
2204
end;
2205

2206
function TGLContextHandle.IsDataNeedUpdate: Boolean;
2207
begin
2208
  if GetHandle = 0 then
2209
    CheckCurrentRC;
2210
  Result := (FLastHandle.FHandle = 0) or FLastHandle.FChanged;
2211
end;
2212

2213
function TGLContextHandle.IsDataComplitelyUpdated: Boolean;
2214
var
2215
  I: Integer;
2216
begin
2217
  Result := false;
2218
  for I := FHandles.Count-1 downto 1 do
2219
  begin
2220
    with RCItem(i)^ do
2221
      if (FRenderingContext <> nil) and (FHandle <> 0) and FChanged then exit;
2222
  end;
2223
  Result := true;
2224
end;
2225

2226
procedure TGLContextHandle.NotifyDataUpdated;
2227
var
2228
  I: Integer;
2229
  aList: TList;
2230
begin
2231
  if Assigned(vCurrentGLContext) then
2232
  begin
2233
    if not Transferable then
2234
    begin
2235
      CheckCurrentRC();
2236
      if FLastHandle.FHandle <> 0 then
2237
      begin
2238
        FLastHandle.FChanged := False;
2239
        exit;
2240
      end;
2241
    end
2242
    else
2243
    begin
2244
  {$IFNDEF GLS_MULTITHREAD}
2245
      aList := vCurrentGLContext.FSharedContexts;
2246
  {$ELSE}
2247
      aList := vCurrentGLContext.FSharedContexts.LockList;
2248
      try
2249
  {$ENDIF}
2250
        for I := 0 to aList.Count - 1 do
2251
        begin
2252
          with SearchRC(aList[I])^ do
2253
            if (FHandle <> 0) then
2254
              FChanged := False;
2255
        end;
2256
  {$IFDEF GLS_MULTITHREAD}
2257
      finally
2258
        vCurrentGLContext.FSharedContexts.UnlockList;
2259
      end;
2260
  {$ENDIF}
2261
    end;
2262
  end
2263
  else
2264
    GLSLogger.LogError(cNoActiveRC);
2265
end;
2266

2267
function TGLContextHandle.RCItem(AIndex: integer): PGLRCHandle;
2268
begin
2269
  Result := FHandles[AIndex];
2270
end;
2271

2272
procedure TGLContextHandle.NotifyChangesOfData;
2273
var
2274
  I: Integer;
2275
begin
2276
  for I := FHandles.Count-1 downto 1 do
2277
    RCItem(I).FChanged := True;
2278
  if Assigned(FOnPrepare) then
2279
    GLContextManager.NotifyPreparationNeed;
2280
end;
2281

2282
function TGLContextHandle.IsShared: Boolean;
2283
var
2284
  I: Integer;
2285
  vContext: TGLContext;
2286
  aList: TList;
2287
begin
2288
  Result := False;
2289
  // untransferable handles can't be shared
2290
  if not Transferable then
2291
    exit;
2292
  Result := True;
2293
{$IFNDEF GLS_MULTITHREAD}
2294
  aList := vCurrentGLContext.FSharedContexts;
2295
{$ELSE}
2296
  aList := vCurrentGLContext.FSharedContexts.LockList;
2297
  try
2298
{$ENDIF}
2299
    for I := 0 to aList.Count - 1 do
2300
    begin
2301
      vContext := aList[I];
2302
      if (vContext <> vCurrentGLContext) and
2303
        // at least one context is friendly
2304
        (SearchRC(vContext).FHandle <> 0) then
2305
        exit;
2306
    end;
2307
{$IFDEF GLS_MULTITHREAD}
2308
  finally
2309
    vCurrentGLContext.FSharedContexts.UnlockList;
2310
  end;
2311
{$ENDIF}
2312
  Result := false;
2313
end;
2314

2315
// Transferable
2316
//
2317

2318
class function TGLContextHandle.Transferable: Boolean;
2319
begin
2320
  Result := True;
2321
end;
2322

2323
class function TGLContextHandle.IsValid(const ID: GLuint): Boolean;
2324
begin
2325
  Result := True;
2326
end;
2327
// IsSupported
2328
//
2329

2330
class function TGLContextHandle.IsSupported: Boolean;
2331
begin
2332
  Result := True;
2333
end;
2334

2335
// ------------------
2336
// ------------------ TGLVirtualHandle ------------------
2337
// ------------------
2338

2339
// DoAllocateHandle
2340
//
2341

2342
function TGLVirtualHandle.DoAllocateHandle: Cardinal;
2343
begin
2344
  Result := 0;
2345
  if Assigned(FOnAllocate) then
2346
    FOnAllocate(Self, Result);
2347
end;
2348

2349
// DoDestroyHandle
2350
//
2351

2352
procedure TGLVirtualHandle.DoDestroyHandle(var AHandle: TGLuint);
2353
begin
2354
  if not vContextActivationFailureOccurred then
2355
  with GL do
2356
  begin
2357
    // reset error status
2358
    ClearError;
2359
    // delete
2360
    if Assigned(FOnDestroy) then
2361
      FOnDestroy(Self, AHandle);
2362
    // check for error
2363
    CheckError;
2364
  end;
2365
end;
2366

2367
class function TGLVirtualHandle.Transferable: Boolean;
2368
begin
2369
  Result := False;
2370
end;
2371

2372
{ TGLVirtualHandleTransf }
2373

2374
class function TGLVirtualHandleTransf.Transferable: Boolean;
2375
begin
2376
  Result := True;
2377
end;
2378

2379
// ------------------
2380
// ------------------ TGLListHandle ------------------
2381
// ------------------
2382

2383
// DoAllocateHandle
2384
//
2385

2386
function TGLListHandle.DoAllocateHandle: Cardinal;
2387
begin
2388
  Result := GL.GenLists(1);
2389
end;
2390

2391
// DoDestroyHandle
2392
//
2393

2394
procedure TGLListHandle.DoDestroyHandle(var AHandle: TGLuint);
2395
begin
2396
  if not vContextActivationFailureOccurred then
2397
  with GL do
2398
  begin
2399
    // reset error status
2400
    ClearError;
2401
    // delete
2402
    DeleteLists(AHandle, 1);
2403
    // check for error
2404
    CheckError;
2405
  end;
2406
end;
2407

2408
// IsValid
2409
//
2410

2411
class function TGLListHandle.IsValid(const ID: GLuint): Boolean;
2412
begin
2413
  Result := GL.IsList(ID);
2414
end;
2415

2416
// NewList
2417
//
2418

2419
procedure TGLListHandle.NewList(mode: Cardinal);
2420
begin
2421
  vCurrentGLContext.GLStates.NewList(GetHandle, mode);
2422
end;
2423

2424
// EndList
2425
//
2426

2427
procedure TGLListHandle.EndList;
2428
begin
2429
  vCurrentGLContext.GLStates.EndList;
2430
end;
2431

2432
// CallList
2433
//
2434

2435
procedure TGLListHandle.CallList;
2436
begin
2437
  vCurrentGLContext.GLStates.CallList(GetHandle);
2438
end;
2439

2440
// ------------------
2441
// ------------------ TGLTextureHandle ------------------
2442
// ------------------
2443

2444
// DoAllocateHandle
2445
//
2446

2447
function TGLTextureHandle.DoAllocateHandle: Cardinal;
2448
begin
2449
  Result := 0;
2450
  GL.GenTextures(1, @Result);
2451
  FTarget := ttNoShape;
2452
end;
2453

2454
// DoDestroyHandle
2455
//
2456

2457
procedure TGLTextureHandle.DoDestroyHandle(var AHandle: TGLuint);
2458
var
2459
  a: TGLint;
2460
  t: TGLTextureTarget;
2461
begin
2462
  if not vContextActivationFailureOccurred then
2463
  with GL do
2464
  begin
2465
    // reset error status
2466
    GetError;
2467
    { Unbind identifier from all image selectors. }
2468
    if ARB_multitexture then
2469
    begin
2470
      with GetContext.GLStates do
2471
      begin
2472
        for a := 0 to MaxTextureImageUnits - 1 do
2473
          for t := Low(TGLTextureTarget) to High(TGLTextureTarget) do
2474
            if TextureBinding[a, t] = AHandle then
2475
              TextureBinding[a, t] := 0;
2476
      end
2477
    end
2478
    else
2479
      with GetContext.GLStates do
2480
        for t := Low(TGLTextureTarget) to High(TGLTextureTarget) do
2481
          if TextureBinding[0, t] = AHandle then
2482
            TextureBinding[0, t] := 0;
2483

2484
    DeleteTextures(1, @AHandle);
2485
    // check for error
2486
    CheckError;
2487
  end;
2488
end;
2489

2490
// IsValid
2491
//
2492

2493
class function TGLTextureHandle.IsValid(const ID: GLuint): Boolean;
2494
begin
2495
  Result := GL.IsTexture(ID);
2496
end;
2497

2498
procedure TGLTextureHandle.SetTarget(ATarget: TGLTextureTarget);
2499
begin
2500
  if FTarget = ttNoShape then
2501
    FTarget := ATarget;
2502
end;
2503

2504
// ------------------
2505
// ------------------ TGLSamplerHandle ------------------
2506
// ------------------
2507

2508
// DoAllocateHandle
2509
//
2510

2511
function TGLSamplerHandle.DoAllocateHandle: Cardinal;
2512
begin
2513
  Result := 0;
2514
  GL.GenSamplers(1, @Result);
2515
end;
2516

2517
// DoDestroyHandle
2518
//
2519

2520
procedure TGLSamplerHandle.DoDestroyHandle(var AHandle: TGLuint);
2521
begin
2522
  if not vContextActivationFailureOccurred then
2523
  with GL do
2524
  begin
2525
    // reset error status
2526
    GetError;
2527
    // delete
2528
    DeleteSamplers(1, @AHandle);
2529
    // check for error
2530
    CheckError;
2531
  end;
2532
end;
2533

2534
// TGLSamplerHandle
2535
//
2536

2537
class function TGLSamplerHandle.IsSupported: Boolean;
2538
begin
2539
  Result := GL.ARB_sampler_objects;
2540
end;
2541

2542
// IsValid
2543
//
2544

2545
class function TGLSamplerHandle.IsValid(const ID: GLuint): Boolean;
2546
begin
2547
  Result := GL.IsSampler(ID);
2548
end;
2549

2550
// ------------------
2551
// ------------------ TGLQueryHandle ------------------
2552
// ------------------
2553

2554
// BeginQuery
2555
//
2556

2557
procedure TGLQueryHandle.BeginQuery;
2558
begin
2559
  if vCurrentGLContext.GLStates.CurrentQuery[QueryType] = 0 then
2560
    vCurrentGLContext.GLStates.BeginQuery(QueryType, GetHandle);
2561
  Factive := True;
2562
end;
2563

2564
// CounterBits
2565
//
2566

2567
function TGLQueryHandle.CounterBits: integer;
2568
begin
2569
  GL.GetQueryiv(Target, GL_QUERY_COUNTER_BITS, @Result);
2570
end;
2571

2572
// DoAllocateHandle
2573
//
2574

2575
function TGLQueryHandle.DoAllocateHandle: Cardinal;
2576
begin
2577
  Result := 0;
2578
  GL.GenQueries(1, @Result);
2579
end;
2580

2581
// DoDestroyHandle
2582
//
2583

2584
procedure TGLQueryHandle.DoDestroyHandle(var AHandle: TGLuint);
2585
begin
2586
  if not vContextActivationFailureOccurred then
2587
  with GL do
2588
  begin
2589
    // reset error status
2590
    GetError;
2591
    // delete
2592
    DeleteQueries(1, @AHandle);
2593
    // check for error
2594
    CheckError;
2595
  end;
2596
end;
2597

2598
// IsValid
2599
//
2600

2601
class function TGLQueryHandle.IsValid(const ID: GLuint): Boolean;
2602
begin
2603
  Result := GL.IsQuery(ID);
2604
end;
2605

2606
// EndQuery
2607
//
2608

2609
procedure TGLQueryHandle.EndQuery;
2610
begin
2611
  Assert(FActive = true, 'Cannot end a query before it begins');
2612
  Factive := False;
2613
  Assert(Handle <> 0);
2614
  //glEndQuery(Target);
2615
  vCurrentGLContext.GLStates.EndQuery(QueryType);
2616
end;
2617

2618
// IsResultAvailable
2619
//
2620

2621
function TGLQueryHandle.IsResultAvailable: boolean;
2622
begin
2623
  GL.GetQueryObjectiv(Handle, GL_QUERY_RESULT_AVAILABLE, @Result);
2624
end;
2625

2626
// QueryResultInt
2627
//
2628

2629
function TGLQueryHandle.QueryResultInt: TGLInt;
2630
begin
2631
  GL.GetQueryObjectiv(Handle, GL_QUERY_RESULT, @Result);
2632
end;
2633

2634
// QueryResultInt64
2635
//
2636

2637
function TGLQueryHandle.QueryResultInt64: TGLint64EXT;
2638
begin
2639
  GL.GetQueryObjecti64v(Handle, GL_QUERY_RESULT, @Result);
2640
end;
2641

2642
// QueryResultUInt
2643
//
2644

2645
function TGLQueryHandle.QueryResultUInt: TGLUInt;
2646
begin
2647
  GL.GetQueryObjectuiv(Handle, GL_QUERY_RESULT, @Result);
2648
end;
2649

2650
// QueryResultUInt64
2651
//
2652

2653
function TGLQueryHandle.QueryResultUInt64: TGLuint64EXT;
2654
begin
2655
  GL.GetQueryObjectui64v(Handle, GL_QUERY_RESULT, @Result);
2656
end;
2657

2658
function TGLQueryHandle.QueryResultBool: TGLboolean;
2659
var
2660
  I: TGLUInt;
2661
begin
2662
  GL.GetQueryObjectuiv(Handle, GL_QUERY_RESULT, @I);
2663
  Result := I > 0;
2664
end;
2665

2666
// Transferable
2667
//
2668

2669
class function TGLQueryHandle.Transferable: Boolean;
2670
begin
2671
  Result := False;
2672
end;
2673

2674
// ------------------
2675
// ------------------ TGLOcclusionQueryHandle ------------------
2676
// ------------------
2677

2678
// GetQueryType
2679
//
2680

2681
function TGLOcclusionQueryHandle.GetQueryType: TQueryType;
2682
begin
2683
  Result := qrySamplesPassed;
2684
end;
2685

2686
// GetTarget
2687
//
2688

2689
function TGLOcclusionQueryHandle.GetTarget: TGLuint;
2690
begin
2691
  Result := GL_SAMPLES_PASSED;
2692
end;
2693

2694
// IsSupported
2695
//
2696

2697
class function TGLOcclusionQueryHandle.IsSupported: Boolean;
2698
begin
2699
  Result := GL.VERSION_1_5;
2700
end;
2701

2702
// PixelCount
2703
//
2704

2705
function TGLOcclusionQueryHandle.PixelCount: Integer;
2706
begin
2707
  Result := QueryResultUInt;
2708
end;
2709

2710
// ------------------
2711
// ------------------ TGLBooleanOcclusionQueryHandle ------------------
2712
// ------------------
2713

2714
// GetQueryType
2715
//
2716

2717
function TGLBooleanOcclusionQueryHandle.GetQueryType: TQueryType;
2718
begin
2719
  Result := qryAnySamplesPassed;
2720
end;
2721

2722
// GetTarget
2723
//
2724

2725
function TGLBooleanOcclusionQueryHandle.GetTarget: TGLuint;
2726
begin
2727
  Result := GL_ANY_SAMPLES_PASSED;
2728
end;
2729

2730
// IsSupported
2731
//
2732

2733
class function TGLBooleanOcclusionQueryHandle.IsSupported: Boolean;
2734
begin
2735
  Result := GL.ARB_occlusion_query2;
2736
end;
2737

2738
// ------------------
2739
// ------------------ TGLTimerQueryHandle ------------------
2740
// ------------------
2741

2742
// GetTarget
2743
//
2744

2745
function TGLTimerQueryHandle.GetQueryType: TQueryType;
2746
begin
2747
  Result := qryTimeElapsed;
2748
end;
2749

2750
function TGLTimerQueryHandle.GetTarget: TGLuint;
2751
begin
2752
  Result := GL_TIME_ELAPSED;
2753
end;
2754

2755
// IsSupported
2756
//
2757

2758
class function TGLTimerQueryHandle.IsSupported: Boolean;
2759
begin
2760
  Result := GL.EXT_timer_query or GL.ARB_timer_query;
2761
end;
2762

2763
// Time
2764
//
2765

2766
function TGLTimerQueryHandle.Time: Integer;
2767
begin
2768
  Result := QueryResultUInt;
2769
end;
2770

2771
// ------------------
2772
// ------------------ TGLPrimitiveQueryHandle ------------------
2773
// ------------------
2774

2775
// GetQueryType
2776
//
2777

2778
function TGLPrimitiveQueryHandle.GetQueryType: TQueryType;
2779
begin
2780
  Result := qryPrimitivesGenerated;
2781
end;
2782

2783
// GetTarget
2784
//
2785

2786
function TGLPrimitiveQueryHandle.GetTarget: TGLuint;
2787
begin
2788
  Result := GL_PRIMITIVES_GENERATED;
2789
end;
2790

2791
// IsSupported
2792
//
2793

2794
class function TGLPrimitiveQueryHandle.IsSupported: Boolean;
2795
begin
2796
  Result := GL.VERSION_3_0;
2797
end;
2798

2799
// PrimitivesGenerated
2800
//
2801

2802
function TGLPrimitiveQueryHandle.PrimitivesGenerated: Integer;
2803
begin
2804
  Result := QueryResultUInt;
2805
end;
2806

2807
// ------------------
2808
// ------------------ TGLBufferObjectHandle ------------------
2809
// ------------------
2810

2811
// CreateFromData
2812
//
2813

2814
constructor TGLBufferObjectHandle.CreateFromData(p: Pointer; size: Integer;
2815
  bufferUsage: TGLuint);
2816
begin
2817
  Create;
2818
  AllocateHandle;
2819
  Bind;
2820
  BufferData(p, size, bufferUsage);
2821
  UnBind;
2822
end;
2823

2824
// DoAllocateHandle
2825
//
2826

2827
function TGLBufferObjectHandle.DoAllocateHandle: Cardinal;
2828
begin
2829
  Result := 0;
2830
  GL.GenBuffers(1, @Result);
2831
end;
2832

2833
// DoDestroyHandle
2834
//
2835

2836
procedure TGLBufferObjectHandle.DoDestroyHandle(var AHandle: TGLuint);
2837
begin
2838
  if not vContextActivationFailureOccurred then
2839
  with GL do
2840
  begin
2841
    // reset error status
2842
    GetError;
2843
    UnBind;
2844
    // delete
2845
    DeleteBuffers(1, @AHandle);
2846
    // check for error
2847
    CheckError;
2848
  end;
2849
end;
2850

2851
// IsValid
2852
//
2853

2854
class function TGLBufferObjectHandle.IsValid(const ID: GLuint): Boolean;
2855
begin
2856
  Result := GL.IsBuffer(ID);
2857
end;
2858

2859
// IsSupported
2860
//
2861

2862
class function TGLBufferObjectHandle.IsSupported: Boolean;
2863
begin
2864
  Result := GL.ARB_vertex_buffer_object;
2865
end;
2866

2867
// BindRange
2868
//
2869

2870
procedure TGLBufferObjectHandle.BindRange(index: TGLuint; offset: TGLintptr;
2871
  size: TGLsizeiptr);
2872
begin
2873
  Assert(False, 'BindRange only XBO and UBO');
2874
end;
2875

2876
// BindBase
2877
//
2878

2879
procedure TGLBufferObjectHandle.BindBase(index: TGLuint);
2880
begin
2881
  Assert(False, 'BindRange only XBO and UBO');
2882
end;
2883

2884
// UnBindBase
2885
//
2886

2887
procedure TGLBufferObjectHandle.UnBindBase(index: TGLuint);
2888
begin
2889
  Assert(False, 'BindRange only XBO and UBO');
2890
end;
2891

2892
// BufferData
2893
//
2894

2895
procedure TGLBufferObjectHandle.BufferData(p: Pointer; size: Integer;
2896
  bufferUsage: TGLuint);
2897
begin
2898
  FSize := size;
2899
  GL.BufferData(Target, size, p, bufferUsage);
2900
end;
2901

2902
// BindBufferData
2903
//
2904

2905
procedure TGLBufferObjectHandle.BindBufferData(p: Pointer; size: Integer;
2906
  bufferUsage: TGLuint);
2907
begin
2908
  Bind;
2909
  FSize := size;
2910
  GL.BufferData(Target, size, p, bufferUsage);
2911
end;
2912

2913
// BufferSubData
2914
//
2915

2916
procedure TGLBufferObjectHandle.BufferSubData(offset, size: Integer; p:
2917
  Pointer);
2918
begin
2919
  Assert(offset + size <= FSize);
2920
  GL.BufferSubData(Target, offset, size, p);
2921
end;
2922

2923
// MapBuffer
2924
//
2925

2926
function TGLBufferObjectHandle.MapBuffer(access: TGLuint): Pointer;
2927
begin
2928
  Result := GL.MapBuffer(Target, access);
2929
end;
2930

2931
// MapBufferRange
2932
//
2933

2934
function TGLBufferObjectHandle.MapBufferRange(offset: TGLint; len: TGLsizei;
2935
  access: TGLbitfield): Pointer;
2936
begin
2937
  Result := GL.MapBufferRange(Target, offset, len, access);
2938
end;
2939

2940
// Flush
2941
//
2942

2943
procedure TGLBufferObjectHandle.Flush(offset: TGLint; len: TGLsizei);
2944
begin
2945
  GL.FlushMappedBufferRange(Target, offset, len);
2946
end;
2947

2948
// UnmapBuffer
2949
//
2950

2951
function TGLBufferObjectHandle.UnmapBuffer: Boolean;
2952
begin
2953
  Result := GL.UnmapBuffer(Target);
2954
end;
2955

2956
// ------------------
2957
// ------------------ TGLVBOHandle ------------------
2958
// ------------------
2959

2960
// GetVBOTarget
2961
//
2962

2963
function TGLVBOHandle.GetVBOTarget: TGLuint;
2964
begin
2965
  Result := Target;
2966
end;
2967

2968
// ------------------
2969
// ------------------ TGLVBOArrayBufferHandle ------------------
2970
// ------------------
2971

2972
procedure TGLVBOArrayBufferHandle.Bind;
2973
begin
2974
  vCurrentGLContext.GLStates.ArrayBufferBinding := Handle;
2975
end;
2976

2977
procedure TGLVBOArrayBufferHandle.UnBind;
2978
begin
2979
  vCurrentGLContext.GLStates.ArrayBufferBinding := 0;
2980
end;
2981

2982
// GetTarget
2983
//
2984

2985
function TGLVBOArrayBufferHandle.GetTarget: TGLuint;
2986
begin
2987
  Result := GL_ARRAY_BUFFER;
2988
end;
2989

2990
// ------------------
2991
// ------------------ TGLVBOElementArrayHandle ------------------
2992
// ------------------
2993

2994
procedure TGLVBOElementArrayHandle.Bind;
2995
begin
2996
  vCurrentGLContext.GLStates.ElementBufferBinding := Handle;
2997
end;
2998

2999
procedure TGLVBOElementArrayHandle.UnBind;
3000
begin
3001
  vCurrentGLContext.GLStates.ElementBufferBinding := 0;
3002
end;
3003

3004
// GetTarget
3005
//
3006

3007
function TGLVBOElementArrayHandle.GetTarget: TGLuint;
3008
begin
3009
  Result := GL_ELEMENT_ARRAY_BUFFER;
3010
end;
3011

3012
// ------------------
3013
// ------------------ TGLPackPBOHandle ------------------
3014
// ------------------
3015

3016
procedure TGLPackPBOHandle.Bind;
3017
begin
3018
  vCurrentGLContext.GLStates.PixelPackBufferBinding := Handle;
3019
end;
3020

3021
procedure TGLPackPBOHandle.UnBind;
3022
begin
3023
  vCurrentGLContext.GLStates.PixelPackBufferBinding := 0;
3024
end;
3025

3026
// GetTarget
3027
//
3028

3029
function TGLPackPBOHandle.GetTarget: TGLuint;
3030
begin
3031
  Result := GL_PIXEL_PACK_BUFFER;
3032
end;
3033

3034
// IsSupported
3035
//
3036

3037
class function TGLPackPBOHandle.IsSupported: Boolean;
3038
begin
3039
  Result := GL.ARB_pixel_buffer_object;
3040
end;
3041

3042
// ------------------
3043
// ------------------ TGLUnpackPBOHandle ------------------
3044
// ------------------
3045

3046
procedure TGLUnpackPBOHandle.Bind;
3047
begin
3048
  vCurrentGLContext.GLStates.PixelUnpackBufferBinding := Handle;
3049
end;
3050

3051
procedure TGLUnpackPBOHandle.UnBind;
3052
begin
3053
  vCurrentGLContext.GLStates.PixelUnpackBufferBinding := 0;
3054
end;
3055

3056
// GetTarget
3057
//
3058

3059
function TGLUnpackPBOHandle.GetTarget: TGLuint;
3060
begin
3061
  Result := GL_PIXEL_UNPACK_BUFFER;
3062
end;
3063

3064
// IsSupported
3065
//
3066

3067
class function TGLUnpackPBOHandle.IsSupported: Boolean;
3068
begin
3069
  Result := GL.ARB_pixel_buffer_object;
3070
end;
3071

3072
// ------------------
3073
// ------------------ TGLTransformFeedbackBufferHandle ------------------
3074
// ------------------
3075

3076
// GetTarget
3077
//
3078

3079
procedure TGLTransformFeedbackBufferHandle.Bind;
3080
begin
3081
  vCurrentGLContext.GLStates.TransformFeedbackBufferBinding := Handle;
3082
end;
3083

3084
procedure TGLTransformFeedbackBufferHandle.UnBind;
3085
begin
3086
  vCurrentGLContext.GLStates.TransformFeedbackBufferBinding := 0;
3087
end;
3088

3089
function TGLTransformFeedbackBufferHandle.GetTarget: TGLuint;
3090
begin
3091
  Result := GL_TRANSFORM_FEEDBACK_BUFFER;
3092
end;
3093

3094
// BeginTransformFeedback
3095
//
3096

3097
procedure TGLTransformFeedbackBufferHandle.BeginTransformFeedback(primitiveMode:
3098
  TGLenum);
3099
begin
3100
  GL.BeginTransformFeedback(primitiveMode);
3101
end;
3102

3103
// EndTransformFeedback
3104
//
3105

3106
procedure TGLTransformFeedbackBufferHandle.EndTransformFeedback();
3107
begin
3108
  GL.EndTransformFeedback();
3109
end;
3110

3111
procedure TGLTransformFeedbackBufferHandle.BindRange(index: TGLuint; offset: TGLintptr;
3112
  size: TGLsizeiptr);
3113
begin
3114
  vCurrentGLContext.GLStates.SetBufferIndexedBinding(Handle, bbtTransformFeedBack,
3115
    index, offset, size);
3116
end;
3117

3118
procedure TGLTransformFeedbackBufferHandle.BindBase(index: TGLuint);
3119
begin
3120
  vCurrentGLContext.GLStates.SetBufferIndexedBinding(Handle, bbtTransformFeedBack,
3121
    index, BufferSize);
3122
end;
3123

3124
procedure TGLTransformFeedbackBufferHandle.UnBindBase(index: TGLuint);
3125
begin
3126
  vCurrentGLContext.GLStates.SetBufferIndexedBinding(0, bbtTransformFeedBack,
3127
    index, 0);
3128
end;
3129

3130
// IsSupported
3131
//
3132

3133
class function TGLTransformFeedbackBufferHandle.IsSupported: Boolean;
3134
begin
3135
  Result := GL.EXT_transform_feedback or GL.VERSION_3_0;
3136
end;
3137

3138
// ------------------
3139
// ------------------ TGLTextureBufferHandle ------------------
3140
// ------------------
3141

3142
procedure TGLTextureBufferHandle.Bind;
3143
begin
3144
  vCurrentGLContext.GLStates.TextureBufferBinding := Handle;
3145
end;
3146

3147
procedure TGLTextureBufferHandle.UnBind;
3148
begin
3149
  vCurrentGLContext.GLStates.TextureBufferBinding := 0;
3150
end;
3151

3152
// GetTarget
3153
//
3154

3155
function TGLTextureBufferHandle.GetTarget: TGLuint;
3156
begin
3157
  Result := GL_TEXTURE_BUFFER;
3158
end;
3159

3160
// IsSupported
3161
//
3162

3163
class function TGLTextureBufferHandle.IsSupported: Boolean;
3164
begin
3165
  Result := GL.EXT_texture_buffer_object or GL.ARB_texture_buffer_object or
3166
    GL.VERSION_3_1;
3167
end;
3168

3169
// ------------------
3170
// ------------------ TGLUniformBufferHandle ------------------
3171
// ------------------
3172

3173
procedure TGLUniformBufferHandle.Bind;
3174
begin
3175
  vCurrentGLContext.GLStates.UniformBufferBinding := Handle;
3176
end;
3177

3178
procedure TGLUniformBufferHandle.UnBind;
3179
begin
3180
  vCurrentGLContext.GLStates.UniformBufferBinding := 0;
3181
end;
3182

3183
procedure TGLUniformBufferHandle.BindRange(index: TGLuint; offset: TGLintptr;
3184
  size: TGLsizeiptr);
3185
begin
3186
  vCurrentGLContext.GLStates.SetBufferIndexedBinding(Handle, bbtUniform,
3187
    index, offset, size);
3188
end;
3189

3190
procedure TGLUniformBufferHandle.BindBase(index: TGLuint);
3191
begin
3192
  vCurrentGLContext.GLStates.SetBufferIndexedBinding(Handle, bbtUniform,
3193
    index, BufferSize);
3194
end;
3195

3196
procedure TGLUniformBufferHandle.UnBindBase(index: TGLuint);
3197
begin
3198
  vCurrentGLContext.GLStates.SetBufferIndexedBinding(0, bbtUniform,
3199
    index, 0);
3200
end;
3201

3202
// GetTarget
3203
//
3204

3205
function TGLUniformBufferHandle.GetTarget: TGLuint;
3206
begin
3207
  Result := GL_UNIFORM_BUFFER;
3208
end;
3209

3210
// IsSupported
3211
//
3212

3213
class function TGLUniformBufferHandle.IsSupported: Boolean;
3214
begin
3215
  Result := GL.ARB_uniform_buffer_object;
3216
end;
3217

3218
// ------------------
3219
// ------------------ TGLVertexArrayHandle ------------------
3220
// ------------------
3221

3222
// DoAllocateHandle
3223
//
3224

3225
function TGLVertexArrayHandle.DoAllocateHandle: Cardinal;
3226
begin
3227
  Result := 0;
3228
  GL.GenVertexArrays(1, @Result);
3229
end;
3230

3231
// DoDestroyHandle
3232
//
3233

3234
procedure TGLVertexArrayHandle.DoDestroyHandle(var AHandle: TGLuint);
3235
begin
3236
  if not vContextActivationFailureOccurred then
3237
  with GL do
3238
  begin
3239
    // reset error status
3240
    GetError;
3241
    // delete
3242
    DeleteVertexArrays(1, @AHandle);
3243
    // check for error
3244
    CheckError;
3245
  end;
3246
end;
3247

3248
// IsValid
3249
//
3250

3251
class function TGLVertexArrayHandle.IsValid(const ID: GLuint): Boolean;
3252
begin
3253
  Result := GL.IsVertexArray(ID);
3254
end;
3255

3256
// Bind
3257
//
3258

3259
procedure TGLVertexArrayHandle.Bind;
3260
begin
3261
  Assert(vCurrentGLContext <> nil);
3262
  vCurrentGLContext.GLStates.VertexArrayBinding := Handle;
3263
end;
3264

3265
// UnBind
3266
//
3267

3268
procedure TGLVertexArrayHandle.UnBind;
3269
begin
3270
  Assert(vCurrentGLContext <> nil);
3271
  vCurrentGLContext.GLStates.VertexArrayBinding := 0;
3272
end;
3273

3274
// IsSupported
3275
//
3276

3277
class function TGLVertexArrayHandle.IsSupported: Boolean;
3278
begin
3279
  Result := GL.ARB_vertex_array_object;
3280
end;
3281

3282
// Transferable
3283
//
3284

3285
class function TGLVertexArrayHandle.Transferable: Boolean;
3286
begin
3287
  Result := False;
3288
end;
3289

3290
// ------------------
3291
// ------------------ TGLFramebufferHandle ------------------
3292
// ------------------
3293

3294
// DoAllocateHandle
3295
//
3296

3297
function TGLFramebufferHandle.DoAllocateHandle: Cardinal;
3298
begin
3299
  Result := 0;
3300
  GL.GenFramebuffers(1, @Result)
3301
end;
3302

3303
// DoDestroyHandle
3304
//
3305

3306
procedure TGLFramebufferHandle.DoDestroyHandle(var AHandle: TGLuint);
3307
begin
3308
  if not vContextActivationFailureOccurred then
3309
  with GL do
3310
  begin
3311
    // reset error status
3312
    GetError;
3313
    // delete
3314
    DeleteFramebuffers(1, @AHandle);
3315
    // check for error
3316
    CheckError;
3317
  end;
3318
end;
3319

3320
// IsValid
3321
//
3322

3323
class function TGLFramebufferHandle.IsValid(const ID: GLuint): Boolean;
3324
begin
3325
  Result := GL.IsFramebuffer(ID);
3326
end;
3327

3328
// Bind
3329
//
3330

3331
procedure TGLFramebufferHandle.Bind;
3332
begin
3333
  Assert(vCurrentGLContext <> nil);
3334
  vCurrentGLContext.GLStates.SetFrameBuffer(Handle);
3335
end;
3336

3337
// BindForDrawing
3338
//
3339

3340
procedure TGLFramebufferHandle.BindForDrawing;
3341
begin
3342
  Assert(vCurrentGLContext <> nil);
3343
  vCurrentGLContext.GLStates.DrawFrameBuffer := Handle;
3344
end;
3345

3346
// BindForReading
3347
//
3348

3349
procedure TGLFramebufferHandle.BindForReading;
3350
begin
3351
  Assert(vCurrentGLContext <> nil);
3352
  vCurrentGLContext.GLStates.ReadFrameBuffer := Handle;
3353
end;
3354

3355
// UnBind
3356
//
3357

3358
procedure TGLFramebufferHandle.UnBind;
3359
begin
3360
  Assert(vCurrentGLContext <> nil);
3361
  vCurrentGLContext.GLStates.SetFrameBuffer(0);
3362
end;
3363

3364
// UnBindForDrawing
3365
//
3366

3367
procedure TGLFramebufferHandle.UnBindForDrawing;
3368
begin
3369
  Assert(vCurrentGLContext <> nil);
3370
  vCurrentGLContext.GLStates.DrawFrameBuffer := 0;
3371
end;
3372

3373
// UnBindForReading
3374
//
3375

3376
procedure TGLFramebufferHandle.UnBindForReading;
3377
begin
3378
  Assert(vCurrentGLContext <> nil);
3379
  vCurrentGLContext.GLStates.ReadFrameBuffer := 0;
3380
end;
3381

3382
// Attach1DTexture
3383
//
3384

3385
procedure TGLFramebufferHandle.Attach1DTexture(target: TGLenum; attachment:
3386
  TGLenum; textarget: TGLenum; texture: TGLuint; level: TGLint);
3387
begin
3388
  GL.FramebufferTexture1D(target, attachment, textarget, texture, level);
3389
end;
3390

3391
// Attach2DTexture
3392
//
3393

3394
procedure TGLFramebufferHandle.Attach2DTexture(target: TGLenum; attachment:
3395
  TGLenum; textarget: TGLenum; texture: TGLuint; level: TGLint);
3396
begin
3397
  GL.FramebufferTexture2D(target, attachment, textarget, texture, level);
3398
end;
3399

3400
// Attach3DTexture
3401
//
3402

3403
procedure TGLFramebufferHandle.Attach3DTexture(target: TGLenum; attachment:
3404
  TGLenum; textarget: TGLenum; texture: TGLuint; level: TGLint; layer: TGLint);
3405
begin
3406
  GL.FramebufferTexture3D(target, attachment, textarget, texture, level, layer);
3407
end;
3408

3409
// AttachLayer
3410
//
3411

3412
procedure TGLFramebufferHandle.AttachLayer(target: TGLenum; attachment: TGLenum;
3413
  texture: TGLuint; level: TGLint; layer: TGLint);
3414
begin
3415
  GL.FramebufferTextureLayer(target, attachment, texture, level, layer);
3416
end;
3417

3418
// AttachRenderBuffer
3419
//
3420

3421
procedure TGLFramebufferHandle.AttachRenderBuffer(target: TGLenum; attachment:
3422
  TGLenum; renderbuffertarget: TGLenum; renderbuffer: TGLuint);
3423
begin
3424
  GL.FramebufferRenderbuffer(target, attachment, renderbuffertarget,
3425
    renderbuffer);
3426
end;
3427

3428
// AttachTexture
3429
//
3430

3431
procedure TGLFramebufferHandle.AttachTexture(target: TGLenum; attachment:
3432
  TGLenum; texture: TGLuint; level: TGLint);
3433
begin
3434
  GL.FramebufferTexture(target, attachment, texture, level);
3435
end;
3436

3437
// AttachTextureLayer
3438
//
3439

3440
procedure TGLFramebufferHandle.AttachTextureLayer(target: TGLenum; attachment:
3441
  TGLenum; texture: TGLuint; level: TGLint; layer: TGLint);
3442
begin
3443
  GL.FramebufferTextureLayer(target, attachment, texture, level, layer);
3444
end;
3445

3446
// Blit
3447
//
3448

3449
procedure TGLFramebufferHandle.Blit(srcX0: TGLint; srcY0: TGLint; srcX1: TGLint;
3450
  srcY1: TGLint;
3451
  dstX0: TGLint; dstY0: TGLint; dstX1: TGLint; dstY1: TGLint;
3452
  mask: TGLbitfield; filter: TGLenum);
3453
begin
3454
  GL.BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
3455
    mask, filter);
3456
end;
3457

3458
// GetAttachmentParameter
3459
//
3460

3461
function TGLFramebufferHandle.GetAttachmentParameter(target: TGLenum;
3462
  attachment: TGLenum; pname: TGLenum): TGLint;
3463
begin
3464
  GL.GetFramebufferAttachmentParameteriv(target, attachment, pname, @Result)
3465
end;
3466

3467
// GetAttachmentObjectType
3468
//
3469

3470
function TGLFramebufferHandle.GetAttachmentObjectType(target: TGLenum;
3471
  attachment: TGLenum): TGLint;
3472
begin
3473
  GL.GetFramebufferAttachmentParameteriv(target, attachment,
3474
    GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, @Result);
3475
end;
3476

3477
// GetAttachmentObjectName
3478
//
3479

3480
function TGLFramebufferHandle.GetAttachmentObjectName(target: TGLenum;
3481
  attachment: TGLenum): TGLint;
3482
begin
3483
  GL.GetFramebufferAttachmentParameteriv(target, attachment,
3484
    GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, @Result);
3485
end;
3486

3487
// CheckStatus
3488
//
3489

3490
function TGLFramebufferHandle.GetStatus: TGLFramebufferStatus;
3491
var
3492
  Status: cardinal;
3493
begin
3494
  Status := GL.CheckFramebufferStatus(GL_FRAMEBUFFER);
3495

3496
  case Status of
3497
    GL_FRAMEBUFFER_COMPLETE_EXT: Result := fsComplete;
3498
    GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: Result := fsIncompleteAttachment;
3499
    GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: Result :=
3500
      fsIncompleteMissingAttachment;
3501
    GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: Result :=
3502
      fsIncompleteDuplicateAttachment;
3503
    GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: Result := fsIncompleteDimensions;
3504
    GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: Result := fsIncompleteFormats;
3505
    GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: Result := fsIncompleteDrawBuffer;
3506
    GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: Result := fsIncompleteReadBuffer;
3507
    GL_FRAMEBUFFER_UNSUPPORTED_EXT: Result := fsUnsupported;
3508
    GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: Result := fsIncompleteMultisample;
3509
  else
3510
    Result := fsStatusError;
3511
  end;
3512
end;
3513

3514
function TGLFramebufferHandle.GetStringStatus(out clarification: string):
3515
  TGLFramebufferStatus;
3516
const
3517
  cFBOStatus: array[TGLFramebufferStatus] of string = (
3518
    'Complete',
3519
    'Incomplete attachment',
3520
    'Incomplete missing attachment',
3521
    'Incomplete duplicate attachment',
3522
    'Incomplete dimensions',
3523
    'Incomplete formats',
3524
    'Incomplete draw buffer',
3525
    'Incomplete read buffer',
3526
    'Unsupported',
3527
    'Incomplite multisample',
3528
    'Status Error');
3529
begin
3530
  Result := GetStatus;
3531
  clarification := cFBOStatus[Result];
3532
end;
3533

3534
// IsSupported
3535
//
3536

3537
class function TGLFramebufferHandle.IsSupported: Boolean;
3538
begin
3539
  Result := GL.EXT_framebuffer_object or GL.ARB_framebuffer_object;
3540
end;
3541

3542
// Transferable
3543
//
3544

3545
class function TGLFramebufferHandle.Transferable: Boolean;
3546
begin
3547
  Result := False;
3548
end;
3549

3550
// ------------------
3551
// ------------------ TGLRenderbufferObject ------------------
3552
// ------------------
3553

3554
// DoAllocateHandle
3555
//
3556

3557
function TGLRenderbufferHandle.DoAllocateHandle: Cardinal;
3558
begin
3559
  Result := 0;
3560
  GL.GenRenderbuffers(1, @Result);
3561
end;
3562

3563
// DoDestroyHandle
3564
//
3565

3566
procedure TGLRenderbufferHandle.DoDestroyHandle(var AHandle: TGLuint);
3567
begin
3568
  if not vContextActivationFailureOccurred then
3569
  with GL do
3570
  begin
3571
    // reset error status
3572
    GetError;
3573
    // delete
3574
    DeleteRenderbuffers(1, @AHandle);
3575
    // check for error
3576
    CheckError;
3577
  end;
3578
end;
3579

3580
// IsValid
3581
//
3582

3583
class function TGLRenderbufferHandle.IsValid(const ID: GLuint): Boolean;
3584
begin
3585
  Result := GL.IsRenderbuffer(ID);
3586
end;
3587

3588
// Bind
3589
//
3590

3591
procedure TGLRenderbufferHandle.Bind;
3592
begin
3593
  vCurrentGLContext.GLStates.RenderBuffer := GetHandle;
3594
end;
3595

3596
// UnBind
3597
//
3598

3599
procedure TGLRenderbufferHandle.UnBind;
3600
begin
3601
  if vCurrentGLContext <> nil then
3602
    vCurrentGLContext.GLStates.RenderBuffer := 0;
3603
end;
3604

3605
// SetStorage
3606
//
3607

3608
procedure TGLRenderbufferHandle.SetStorage(internalformat: TGLenum; width,
3609
  height: TGLsizei);
3610
begin
3611
  GL.RenderbufferStorage(GL_RENDERBUFFER, internalformat, width, height);
3612
end;
3613

3614
// SetStorageMultisample
3615
//
3616

3617
procedure TGLRenderbufferHandle.SetStorageMultisample(internalformat: TGLenum;
3618
  samples: TGLsizei; width, height: TGLsizei);
3619
begin
3620
  GL.RenderbufferStorageMultisample(GL_RENDERBUFFER, samples, internalformat,
3621
    width, height);
3622
end;
3623

3624
// IsSupported
3625
//
3626

3627
class function TGLRenderbufferHandle.IsSupported: Boolean;
3628
begin
3629
  Result := GL.EXT_framebuffer_object or GL.ARB_framebuffer_object;
3630
end;
3631

3632
// ------------------
3633
// ------------------ TGLARBProgramHandle ------------------
3634
// ------------------
3635

3636
// DoAllocateHandle
3637
//
3638

3639
function TGLARBProgramHandle.DoAllocateHandle: Cardinal;
3640
begin
3641
  Result := 0;
3642
  GL.GenPrograms(1, @Result);
3643
  FReady := False;
3644
end;
3645

3646
// DoDestroyHandle
3647
//
3648

3649
procedure TGLARBProgramHandle.DoDestroyHandle(var AHandle: TGLuint);
3650
begin
3651
  if not vContextActivationFailureOccurred then
3652
  with GL do
3653
  begin
3654
    // reset error status
3655
    GetError;
3656
    // delete
3657
    DeletePrograms(1, @AHandle);
3658
    // check for error
3659
    CheckError;
3660
  end;
3661
end;
3662

3663
// IsValid
3664
//
3665

3666
class function TGLARBProgramHandle.IsValid(const ID: GLuint): Boolean;
3667
begin
3668
  Result := GL.IsProgram(ID);
3669
end;
3670

3671
procedure TGLARBProgramHandle.LoadARBProgram(AText: string);
3672
const
3673
  cProgType: array[0..2] of string =
3674
    ('ARB vertex', 'ARB fragment', 'NV geometry');
3675
var
3676
  errPos, P: Integer;
3677
begin
3678
  Bind;
3679
  GL.ProgramString(GetTarget, GL_PROGRAM_FORMAT_ASCII_ARB,
3680
    Length(AText), PGLChar(TGLString(AText)));
3681
  GL.GetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, @errPos);
3682
  if errPos > -1 then
3683
  begin
3684
    FInfoLog := string(GL.GetString(GL_PROGRAM_ERROR_STRING_ARB));
3685
    case GetTarget of
3686
      GL_VERTEX_PROGRAM_ARB: P := 0;
3687
      GL_FRAGMENT_PROGRAM_ARB: P := 1;
3688
    else
3689
      P := 2;
3690
    end;
3691
    GLSLogger.LogError(Format('%s Program Error - [Pos: %d][Error %s]', [cProgType[P], errPos, FInfoLog]));
3692
    FReady := False;
3693
  end
3694
  else
3695
  begin
3696
    FReady := True;
3697
    FInfoLog := '';
3698
  end;
3699
end;
3700

3701
procedure TGLARBProgramHandle.Enable;
3702
begin
3703
  if FReady then
3704
    GL.Enable(GetTarget)
3705
  else
3706
    Abort;
3707
end;
3708

3709
procedure TGLARBProgramHandle.Disable;
3710
begin
3711
  GL.Disable(GetTarget);
3712
end;
3713

3714
procedure TGLARBProgramHandle.Bind;
3715
begin
3716
  GL.BindProgram(GetTarget, Handle);
3717
end;
3718

3719
class function TGLARBVertexProgramHandle.GetTarget: TGLenum;
3720
begin
3721
  Result := GL_VERTEX_PROGRAM_ARB;
3722
end;
3723

3724
class function TGLARBVertexProgramHandle.IsSupported: Boolean;
3725
begin
3726
  Result := GL.ARB_vertex_program;
3727
end;
3728

3729
class function TGLARBFragmentProgramHandle.GetTarget: TGLenum;
3730
begin
3731
  Result := GL_FRAGMENT_PROGRAM_ARB;
3732
end;
3733

3734
class function TGLARBFragmentProgramHandle.IsSupported: Boolean;
3735
begin
3736
  Result := GL.ARB_vertex_program;
3737
end;
3738

3739
class function TGLARBGeometryProgramHandle.GetTarget: TGLenum;
3740
begin
3741
  Result := GL_GEOMETRY_PROGRAM_NV;
3742
end;
3743

3744
class function TGLARBGeometryProgramHandle.IsSupported: Boolean;
3745
begin
3746
  Result := GL.NV_geometry_program4;
3747
end;
3748

3749
// ------------------
3750
// ------------------ TGLSLHandle ------------------
3751
// ------------------
3752

3753
procedure TGLSLHandle.DoDestroyHandle(var AHandle: TGLuint);
3754
begin
3755
  if not vContextActivationFailureOccurred then
3756
  with GL do
3757
  begin
3758
    // reset error status
3759
    ClearError;
3760
    // delete
3761
    DeleteObject(AHandle);
3762
    // check for error
3763
    CheckError;
3764
  end;
3765
end;
3766

3767
// InfoLog
3768
//
3769

3770
function TGLSLHandle.InfoLog: string;
3771
var
3772
  maxLength: Integer;
3773
  log: TGLString;
3774
begin
3775
  maxLength := 0;
3776
  GL.GetObjectParameteriv(GetHandle, GL_OBJECT_INFO_LOG_LENGTH_ARB, @maxLength);
3777
  SetLength(log, maxLength);
3778
  if maxLength > 0 then
3779
  begin
3780
    GL.GetInfoLog(GetHandle, maxLength, @maxLength, @log[1]);
3781
    SetLength(log, maxLength);
3782
  end;
3783
  Result := string(log);
3784
end;
3785

3786
// IsSupported
3787
//
3788

3789
class function TGLSLHandle.IsSupported: Boolean;
3790
begin
3791
  Result := GL.ARB_shader_objects;
3792
end;
3793

3794
// ------------------
3795
// ------------------ TGLShaderHandle ------------------
3796
// ------------------
3797

3798
// DoAllocateHandle
3799
//
3800

3801
function TGLShaderHandle.DoAllocateHandle: Cardinal;
3802
begin
3803
  Result := GL.CreateShader(FShaderType)
3804
end;
3805

3806
// IsValid
3807
//
3808

3809
class function TGLShaderHandle.IsValid(const ID: GLuint): Boolean;
3810
begin
3811
  Result := GL.IsShader(ID);
3812
end;
3813

3814
// ShaderSource
3815
//
3816

3817
procedure TGLShaderHandle.ShaderSource(const source: AnsiString);
3818
var
3819
  p: PGLChar;
3820
begin
3821
  p := PGLChar(TGLString(source));
3822
  GL.ShaderSource(GetHandle, 1, @p, nil);
3823
end;
3824

3825
// CompileShader
3826
//
3827

3828
function TGLShaderHandle.CompileShader: Boolean;
3829
var
3830
  compiled: Integer;
3831
  glH: TGLuint;
3832
begin
3833
  glH := GetHandle;
3834
  GL.CompileShader(glH);
3835
  compiled := 0;
3836
  GL.GetShaderiv(glH, GL_COMPILE_STATUS, @compiled);
3837
  Result := (compiled <> 0);
3838
end;
3839

3840
// ------------------
3841
// ------------------ TGLVertexShaderHandle ------------------
3842
// ------------------
3843

3844
// Create
3845
//
3846

3847
constructor TGLVertexShaderHandle.Create;
3848
begin
3849
  FShaderType := GL_VERTEX_SHADER_ARB;
3850
  inherited;
3851
end;
3852

3853
// IsSupported
3854
//
3855

3856
class function TGLVertexShaderHandle.IsSupported: Boolean;
3857
begin
3858
  Result := GL.ARB_vertex_shader;
3859
end;
3860

3861
// ------------------
3862
// ------------------ TGLGeometryShaderHandle ------------------
3863
// ------------------
3864

3865
// Create
3866
//
3867

3868
constructor TGLGeometryShaderHandle.Create;
3869
begin
3870
  FShaderType := GL_GEOMETRY_SHADER_EXT;
3871
  inherited;
3872
end;
3873

3874
// IsSupported
3875
//
3876

3877
class function TGLGeometryShaderHandle.IsSupported: Boolean;
3878
begin
3879
  Result := GL.EXT_geometry_shader4;
3880
end;
3881

3882
// ------------------
3883
// ------------------ TGLFragmentShaderHandle ------------------
3884
// ------------------
3885

3886
// Create
3887
//
3888

3889
constructor TGLFragmentShaderHandle.Create;
3890
begin
3891
  FShaderType := GL_FRAGMENT_SHADER_ARB;
3892
  inherited;
3893
end;
3894

3895
// IsSupported
3896
//
3897

3898
class function TGLFragmentShaderHandle.IsSupported: Boolean;
3899
begin
3900
  Result := GL.ARB_fragment_shader;
3901
end;
3902

3903
// ------------------
3904
// ------------------ TGLTessControlShaderHandle ------------------
3905
// ------------------
3906

3907
// Create
3908
//
3909

3910
constructor TGLTessControlShaderHandle.Create;
3911
begin
3912
  FShaderType := GL_TESS_CONTROL_SHADER;
3913
  inherited;
3914
end;
3915

3916
// IsSupported
3917
//
3918

3919
class function TGLTessControlShaderHandle.IsSupported: Boolean;
3920
begin
3921
  Result := GL.ARB_tessellation_shader;
3922
end;
3923

3924
// ------------------
3925
// ------------------ TGLTessEvaluationShaderHandle ------------------
3926
// ------------------
3927

3928
// Create
3929
//
3930

3931
constructor TGLTessEvaluationShaderHandle.Create;
3932
begin
3933
  FShaderType := GL_TESS_EVALUATION_SHADER;
3934
  inherited;
3935
end;
3936

3937
// IsSupported
3938
//
3939

3940
class function TGLTessEvaluationShaderHandle.IsSupported: Boolean;
3941
begin
3942
  Result := GL.ARB_tessellation_shader;
3943
end;
3944

3945
// ------------------
3946
// ------------------ TGLProgramHandle ------------------
3947
// ------------------
3948

3949
// DoAllocateHandle
3950
//
3951

3952
function TGLProgramHandle.DoAllocateHandle: cardinal;
3953
begin
3954
  Result := GL.CreateProgram();
3955
end;
3956

3957
// IsValid
3958
//
3959

3960
class function TGLProgramHandle.IsValid(const ID: GLuint): Boolean;
3961
begin
3962
  Result := GL.IsProgram(ID);
3963
end;
3964

3965
// AddShader
3966
//
3967

3968
procedure TGLProgramHandle.AddShader(shaderType: TGLShaderHandleClass; const
3969
  shaderSource: string;
3970
  treatWarningsAsErrors: Boolean = False);
3971
var
3972
  shader: TGLShaderHandle;
3973
begin
3974
  shader := shaderType.CreateAndAllocate;
3975
  try
3976
    if shader.Handle = 0 then
3977
      raise EGLShader.Create('Couldn''t allocate ' + shaderType.ClassName);
3978
    shader.ShaderSource(AnsiString(shaderSource));
3979
    if (not shader.CompileShader)
3980
      or (treatWarningsAsErrors and (Pos('warning', LowerCase(shader.InfoLog)) >
3981
      0)) then
3982
      raise EGLShader.Create(FName + ' (' + shader.ClassName + '): '#13#10 +
3983
        shader.InfoLog);
3984
    AttachObject(shader);
3985
  finally
3986
    shader.Free;
3987
  end;
3988
  GL.CheckError;
3989
end;
3990

3991
// AttachObject
3992
//
3993

3994
procedure TGLProgramHandle.AttachObject(shader: TGLShaderHandle);
3995
begin
3996
  GL.AttachShader(GetHandle, shader.Handle);
3997
end;
3998

3999
// DetachAllObject
4000
//
4001

4002
procedure TGLProgramHandle.DetachAllObject;
4003
var
4004
  glH: TGLuint;
4005
  I: Integer;
4006
  count: GLSizei;
4007
  buffer: array[0..255] of TGLuint;
4008
begin
4009
  glH := GetHandle;
4010
  if glH > 0 then
4011
  begin
4012
    GL.GetAttachedShaders(glH, Length(buffer), @count, @buffer[0]);
4013
    count := MinInteger(count, Length(buffer));
4014
    for I := 0 to count - 1 do
4015
      GL.DetachShader(glH, buffer[I]);
4016
    NotifyChangesOfData;
4017
  end;
4018
end;
4019

4020
// BindAttribLocation
4021
//
4022

4023
procedure TGLProgramHandle.BindAttribLocation(index: Integer; const aName:
4024
  string);
4025
begin
4026
  GL.BindAttribLocation(GetHandle, index, PGLChar(TGLString(aName)));
4027
end;
4028

4029
// BindFragDataLocation
4030
//
4031

4032
procedure TGLProgramHandle.BindFragDataLocation(index: Integer; const aName:
4033
  string);
4034
begin
4035
  GL.BindFragDataLocation(GetHandle, index, PGLChar(TGLString(name)));
4036
end;
4037

4038
// LinkProgram
4039
//
4040

4041
function TGLProgramHandle.LinkProgram: Boolean;
4042
var
4043
  status: Integer;
4044
  glH: TGLuint;
4045
begin
4046
  glH := GetHandle;
4047
  GL.LinkProgram(glH);
4048
  status := 0;
4049
  GL.GetProgramiv(glH, GL_LINK_STATUS, @status);
4050
  Result := (status <> 0);
4051
end;
4052

4053
// ValidateProgram
4054
//
4055

4056
function TGLProgramHandle.ValidateProgram: Boolean;
4057
var
4058
  validated: Integer;
4059
  h: TGLuint;
4060
begin
4061
  h := GetHandle;
4062
  GL.ValidateProgram(h);
4063
  validated := 0;
4064
  GL.GetProgramiv(h, GL_VALIDATE_STATUS, @validated);
4065
  Result := (validated <> 0);
4066
end;
4067

4068
// GetAttribLocation
4069
//
4070

4071
function TGLProgramHandle.GetAttribLocation(const aName: string): Integer;
4072
begin
4073
  Result := GL.GetAttribLocation(GetHandle, PGLChar(TGLString(aName)));
4074
  Assert(Result >= 0, Format(glsUnknownParam, ['attrib', aName, Name]));
4075
end;
4076

4077
// GetUniformLocation
4078
//
4079

4080
function TGLProgramHandle.GetUniformLocation(const aName: string): Integer;
4081
begin
4082
  Result := GL.GetUniformLocation(GetHandle, PGLChar(TGLString(aName)));
4083
  Assert(Result >= 0, Format(glsUnknownParam, ['uniform', aName, Name]));
4084
end;
4085

4086
// GetVaryingLocation
4087
//
4088

4089
function TGLProgramHandle.GetVaryingLocation(const aName: string): Integer;
4090
begin
4091
  Result := GL.GetVaryingLocation(GetHandle, PGLChar(TGLString(aName)));
4092
  Assert(Result >= 0, Format(glsUnknownParam, ['varying', aName, Name]));
4093
end;
4094

4095
// AddActiveVarying
4096
//
4097

4098
procedure TGLProgramHandle.AddActiveVarying(const aName: string);
4099
begin
4100
  GL.ActiveVarying(GetHandle, PGLChar(TGLString(aName)));
4101
end;
4102

4103
// GetAttribLocation
4104
//
4105

4106
procedure TGLProgramHandle.UseProgramObject;
4107
begin
4108
  Assert(vCurrentGLContext <> nil);
4109
  vCurrentGLContext.GLStates.CurrentProgram := Handle;
4110
end;
4111

4112
// GetAttribLocation
4113
//
4114

4115
procedure TGLProgramHandle.EndUseProgramObject;
4116
begin
4117
  Assert(vCurrentGLContext <> nil);
4118
  vCurrentGLContext.GLStates.CurrentProgram := 0;
4119
end;
4120

4121
// GetUniform1i
4122
//
4123

4124
function TGLProgramHandle.GetUniform1i(const index: string): Integer;
4125
begin
4126
  GL.GetUniformiv(GetHandle, GetUniformLocation(index), @Result);
4127
end;
4128

4129
// GetUniform2i
4130
//
4131

4132
function TGLProgramHandle.GetUniform2i(const index: string): TVector2i;
4133
begin
4134
  GL.GetUniformiv(GetHandle, GetUniformLocation(index), @Result);
4135
end;
4136

4137
// GetUniform3i
4138
//
4139

4140
function TGLProgramHandle.GetUniform3i(const index: string): TVector3i;
4141
begin
4142
  GL.GetUniformiv(GetHandle, GetUniformLocation(index), @Result);
4143
end;
4144

4145
// GetUniform4i
4146
//
4147

4148
function TGLProgramHandle.GetUniform4i(const index: string): TVector4i;
4149
begin
4150
  GL.GetUniformiv(GetHandle, GetUniformLocation(index), @Result);
4151
end;
4152

4153
// SetUniform1f
4154
//
4155

4156
procedure TGLProgramHandle.SetUniform1f(const index: string; val: Single);
4157
begin
4158
  GL.Uniform1f(GetUniformLocation(index), val);
4159
end;
4160

4161
// GetUniform1f
4162
//
4163

4164
function TGLProgramHandle.GetUniform1f(const index: string): Single;
4165
begin
4166
  GL.GetUniformfv(GetHandle, GetUniformLocation(index), @Result);
4167
end;
4168

4169
// SetUniform1i
4170
//
4171

4172
procedure TGLProgramHandle.SetUniform1i(const index: string; val: Integer);
4173
begin
4174
  GL.Uniform1i(GetUniformLocation(index), val);
4175
end;
4176

4177
// SetUniform2i
4178
//
4179

4180
procedure TGLProgramHandle.SetUniform2i(const index: string;
4181
  const Value: TVector2i);
4182
begin
4183
  GL.Uniform2i(GetUniformLocation(index), Value.V[0], Value.V[1]);
4184
end;
4185

4186
// SetUniform3i
4187
//
4188

4189
procedure TGLProgramHandle.SetUniform3i(const index: string;
4190
  const Value: TVector3i);
4191
begin
4192
  GL.Uniform3i(GetUniformLocation(index), Value.V[0], Value.V[1], Value.V[2]);
4193
end;
4194

4195
// SetUniform4i
4196
//
4197

4198
procedure TGLProgramHandle.SetUniform4i(const index: string;
4199
  const Value: TVector4i);
4200
begin
4201
  GL.Uniform4i(GetUniformLocation(index), Value.V[0], Value.V[1], Value.V[2],
4202
    Value.V[3]);
4203
end;
4204

4205
// GetUniform2f
4206
//
4207

4208
function TGLProgramHandle.GetUniform2f(const index: string): TVector2f;
4209
begin
4210
  GL.GetUniformfv(GetHandle, GetUniformLocation(index), @Result);
4211
end;
4212

4213
// SetUniform2f
4214
//
4215

4216
procedure TGLProgramHandle.SetUniform2f(const index: string; const val:
4217
  TVector2f);
4218
begin
4219
  GL.Uniform2f(GetUniformLocation(index), val.V[0], val.V[1]);
4220
end;
4221

4222
// GetUniform3f
4223
//
4224

4225
function TGLProgramHandle.GetUniform3f(const index: string): TAffineVector;
4226
begin
4227
  GL.GetUniformfv(GetHandle, GetUniformLocation(index), @Result);
4228
end;
4229

4230
// SetUniform3f
4231
//
4232

4233
procedure TGLProgramHandle.SetUniform3f(const index: string; const val:
4234
  TAffineVector);
4235
begin
4236
  GL.Uniform3f(GetUniformLocation(index), val.V[0], val.V[1], val.V[2]);
4237
end;
4238

4239
// GetUniform4f
4240
//
4241

4242
function TGLProgramHandle.GetUniform4f(const index: string): TVector;
4243
begin
4244
  GL.GetUniformfv(GetHandle, GetUniformLocation(index), @Result);
4245
end;
4246

4247
// SetUniform4f
4248
//
4249

4250
procedure TGLProgramHandle.SetUniform4f(const index: string; const val:
4251
  TVector);
4252
begin
4253
  GL.Uniform4f(GetUniformLocation(index), val.V[0], val.V[1], val.V[2], val.V[3]);
4254
end;
4255

4256
// GetUniformMatrix2fv
4257
//
4258

4259
function TGLProgramHandle.GetUniformMatrix2fv(const index: string): TMatrix2f;
4260
begin
4261
  GL.GetUniformfv(GetHandle, GetUniformLocation(index), @Result);
4262
end;
4263

4264
// SetUniformMatrix2fv
4265
//
4266

4267
procedure TGLProgramHandle.SetUniformMatrix2fv(const index: string; const val:
4268
  TMatrix2f);
4269
begin
4270
  GL.UniformMatrix2fv(GetUniformLocation(index), 1, False, @val);
4271
end;
4272

4273
// GetUniformMatrix3fv
4274
//
4275

4276
function TGLProgramHandle.GetUniformMatrix3fv(const index: string): TMatrix3f;
4277
begin
4278
  GL.GetUniformfv(GetHandle, GetUniformLocation(index), @Result);
4279
end;
4280

4281
// SetUniformMatrix3fv
4282
//
4283

4284
procedure TGLProgramHandle.SetUniformMatrix3fv(const index: string; const val:
4285
  TMatrix3f);
4286
begin
4287
  GL.UniformMatrix3fv(GetUniformLocation(index), 1, False, @val);
4288
end;
4289

4290
// GetUniformMatrix4fv
4291
//
4292

4293
function TGLProgramHandle.GetUniformMatrix4fv(const index: string): TMatrix;
4294
begin
4295
  GL.GetUniformfv(GetHandle, GetUniformLocation(index), @Result);
4296
end;
4297

4298
// SetUniformMatrix4fv
4299
//
4300

4301
procedure TGLProgramHandle.SetUniformMatrix4fv(const index: string; const val:
4302
  TMatrix);
4303
begin
4304
  GL.UniformMatrix4fv(GetUniformLocation(index), 1, False, @val);
4305
end;
4306

4307
// SetUniformf
4308
//
4309

4310
procedure TGLProgramHandle.SetUniformf(const index: string;
4311
  const val: single);
4312
begin
4313
  SetUniform1f(index, val);
4314
end;
4315

4316
// SetUniformf
4317
//
4318

4319
procedure TGLProgramHandle.SetUniformf(const index: string; const val:
4320
  TVector2f);
4321
begin
4322
  SetUniform2f(index, val);
4323
end;
4324

4325
// SetUniformf
4326
//
4327

4328
procedure TGLProgramHandle.SetUniformf(const index: string;
4329
  const val: TVector3f);
4330
begin
4331
  SetUniform3f(index, val);
4332
end;
4333

4334
// SetUniformf
4335
//
4336

4337
procedure TGLProgramHandle.SetUniformf(const index: string;
4338
  const val: TVector4f);
4339
begin
4340
  SetUniform4f(index, val);
4341
end;
4342

4343
// SetUniformf
4344
//
4345

4346
procedure TGLProgramHandle.SetUniformi(const index: string;
4347
  const val: integer);
4348
begin
4349
  SetUniform1f(index, val);
4350
end;
4351

4352
// SetUniformf
4353
//
4354

4355
procedure TGLProgramHandle.SetUniformi(const index: string; const val:
4356
  TVector2i);
4357
begin
4358
  SetUniform2i(index, val);
4359
end;
4360

4361
// SetUniformf
4362
//
4363

4364
procedure TGLProgramHandle.SetUniformi(const index: string;
4365
  const val: TVector3i);
4366
begin
4367
  SetUniform3i(index, val);
4368
end;
4369

4370
// SetUniformf
4371
//
4372

4373
procedure TGLProgramHandle.SetUniformi(const index: string;
4374
  const val: TVector4i);
4375
begin
4376
  SetUniform4i(index, val);
4377
end;
4378

4379
// GetUniformTextureHandle
4380
//
4381

4382
function TGLProgramHandle.GetUniformTextureHandle(const index: string;
4383
  const TextureIndex: Integer; const TextureTarget: TGLTextureTarget): Cardinal;
4384
begin
4385
  Result := GetUniform1i(index);
4386
end;
4387

4388
// SetUniformTextureHandle
4389
//
4390

4391
procedure TGLProgramHandle.SetUniformTextureHandle(const index: string;
4392
  const TextureIndex: Integer; const TextureTarget: TGLTextureTarget;
4393
  const Value: Cardinal);
4394
begin
4395
  vCurrentGLContext.GLStates.TextureBinding[0, TextureTarget] := Value;
4396
  SetUniform1i(index, TextureIndex);
4397
end;
4398

4399
// SetUniformBuffer
4400
//
4401

4402
procedure TGLProgramHandle.SetUniformBuffer(const index: string;
4403
  Value: TGLUniformBufferHandle);
4404
begin
4405
  GL.UniformBuffer(Handle, GetUniformLocation(index), Value.Handle);
4406
end;
4407

4408
// GetUniformBufferSize
4409
//
4410

4411
function TGLProgramHandle.GetUniformBufferSize(const aName: string): Integer;
4412
begin
4413
  Result := GL.GetUniformBufferSize(Handle, GetUniformLocation(aName));
4414
end;
4415

4416
// GetUniformOffset
4417
//
4418

4419
function TGLProgramHandle.GetUniformOffset(const aName: string): PGLInt;
4420
begin
4421
  Result := GL.GetUniformOffset(Handle, GetUniformLocation(aName));
4422
end;
4423

4424
// GetUniformBlockIndex
4425
//
4426

4427
function TGLProgramHandle.GetUniformBlockIndex(const aName: string): Integer;
4428
begin
4429
  Result := GL.GetUniformBlockIndex(Handle, PGLChar(TGLString(aName)));
4430
  Assert(Result >= 0, Format(glsUnknownParam, ['uniform block', aName, Name]));
4431
end;
4432

4433
// Create
4434
//
4435

4436
constructor TGLProgramHandle.Create;
4437
begin
4438
  inherited Create;
4439
  FName := 'DefaultShaderName';
4440
end;
4441

4442
// ------------------
4443
// ------------------ TGLContextManager ------------------
4444
// ------------------
4445

4446
{$IFDEF GLS_SERVICE_CONTEXT}
4447
procedure OnApplicationInitialize;
4448
begin
4449
  InitProc := OldInitProc;
4450

4451
  if Assigned(InitProc) then TProcedure(InitProc);
4452

4453
  Application.Initialize;
4454
  GLContextManager.CreateServiceContext;
4455
end;
4456
{$ENDIF}
4457

4458
// Create
4459
//
4460

4461
constructor TGLContextManager.Create;
4462
begin
4463
  inherited Create;
4464
{$IFNDEF GLS_MULTITHREAD}
4465
  FHandles := TList.Create;
4466
{$ELSE}
4467
  FHandles := TThreadList.Create;
4468
{$ENDIF GLS_MULTITHREAD}
4469
  FList := TThreadList.Create;
4470
end;
4471

4472
// Destroy
4473
//
4474

4475
destructor TGLContextManager.Destroy;
4476
begin
4477
  FHandles.Free;
4478
  FList.Free;
4479
  inherited Destroy;
4480
end;
4481

4482
// CreateContext
4483
//
4484

4485
function TGLContextManager.CreateContext(AClass: TGLContextClass): TGLContext;
4486
begin
4487
  if Assigned(AClass) then
4488
  begin
4489
    Result := AClass.Create;
4490
    Result.FManager := Self;
4491
  end
4492
  else if Assigned(vContextClasses) and (vContextClasses.Count > 0) then
4493
  begin
4494
    Result := TGLContextClass(vContextClasses.Last).Create;
4495
    Result.FManager := Self;
4496
  end
4497
  else
4498
    Result := nil;
4499
end;
4500

4501
{$IFDEF GLS_SERVICE_CONTEXT}
4502

4503
procedure TGLContextManager.CreateServiceContext;
4504
begin
4505
  FServiceContext := CreateContext;
4506
  FThreadTask := TServiceContextTaskList.Create;
4507
  FServiceStarter := TFinishTaskEvent.Create;
4508
  FThread := TServiceContextThread.Create;
4509
  AddTaskForServiceContext(TServiceContextThread(FThread).DoCreateServiceContext);
4510
end;
4511

4512
procedure TGLContextManager.QueueTaskDepleted;
4513
var
4514
  TaskRec: TServiceContextTask;
4515
  I: Integer;
4516
  nowTime: Double;
4517
begin
4518
  with FThreadTask.LockList do
4519
    try
4520
      for I := 0 to Count - 1 do
4521
      begin
4522
        TaskRec := Items[I];
4523
        if Assigned(TaskRec.Task) then
4524
        begin
4525
          FThreadTask.UnlockList;
4526
          // Task queue not empty
4527
          FServiceStarter.SetEvent;
4528
          exit;
4529
        end;
4530
      end;
4531
    finally
4532
      FThreadTask.UnlockList;
4533
    end;
4534

4535
  FServiceStarter.ResetEvent;
4536
  FThreadTask.Clear;
4537
  nowTime := GLSTime;
4538
  with TServiceContextThread(FThread) do
4539
  if (nowTime - FLastTaskStartTime > 30000)
4540
    and not FReported then
4541
  begin
4542
    FReported := True;
4543
    GLSLogger.LogInfo('Service context queue task depleted');
4544
  end;
4545
end;
4546

4547
{$ENDIF GLS_SERVICE_CONTEXT}
4548

4549

4550
// Lock
4551
//
4552

4553
procedure TGLContextManager.Lock;
4554
begin
4555
  FList.LockList;
4556
end;
4557

4558
procedure TGLContextManager.NotifyPreparationNeed;
4559
var
4560
  I: Integer;
4561
  LList: TList;
4562
begin
4563
  LList := FList.LockList;
4564
  try
4565
    for I := LList.Count - 1 downto 0 do
4566
      TGLContext(LList[I]).FIsPraparationNeed := True;
4567
  finally
4568
    FList.UnlockList;
4569
  end;
4570
end;
4571

4572
// UnLock
4573
//
4574

4575
procedure TGLContextManager.UnLock;
4576
begin
4577
  FList.UnlockList;
4578
end;
4579

4580
// ContextCount
4581
//
4582

4583
function TGLContextManager.ContextCount: Integer;
4584
begin
4585
  // try..finally just a waste of CPU here, if Count fails, the list is amok,
4586
  // and so is the lock...
4587
  Result := FList.LockList.Count;
4588
  FList.UnLockList;
4589
end;
4590

4591
// RegisterContext
4592
//
4593

4594
procedure TGLContextManager.RegisterContext(aContext: TGLContext);
4595
begin
4596
  with FList.LockList do
4597
    try
4598
      if IndexOf(aContext) >= 0 then
4599
        raise EGLContext.Create(cInvalidContextRegistration)
4600
      else
4601
        Add(aContext);
4602
    finally
4603
      FList.UnlockList;
4604
    end;
4605
end;
4606

4607
// UnRegisterContext
4608
//
4609

4610
procedure TGLContextManager.UnRegisterContext(aContext: TGLContext);
4611
begin
4612
  with FList.LockList do
4613
    try
4614
      if IndexOf(aContext) < 0 then
4615
        raise EGLContext.Create(cInvalidContextRegistration)
4616
      else
4617
        Remove(aContext);
4618
    finally
4619
      FList.UnlockList;
4620
    end;
4621
end;
4622

4623
// ContextCreatedBy
4624
//
4625

4626
procedure TGLContextManager.ContextCreatedBy(aContext: TGLContext);
4627
begin
4628
  Lock;
4629
  try
4630
    Inc(FCreatedRCCount);
4631
  finally
4632
    UnLock;
4633
  end;
4634
end;
4635

4636
// DestroyingContextBy
4637
//
4638

4639
procedure TGLContextManager.DestroyingContextBy(aContext: TGLContext);
4640
var
4641
  cn: TGLContextNotification;
4642
begin
4643
  Lock;
4644
  try
4645
    Dec(FCreatedRCCount);
4646
    if FCreatedRCCount = 0 then
4647
    begin
4648
      // yes, slow and bulky, but allows for the triggered event to
4649
      // cascade-remove notifications safely
4650
      while Length(FNotifications) > 0 do
4651
      begin
4652
        cn := FNotifications[High(FNotifications)];
4653
        SetLength(FNotifications, Length(FNotifications) - 1);
4654
        cn.event(cn.obj);
4655
      end;
4656
    end;
4657
  finally
4658
    UnLock;
4659
  end;
4660
end;
4661

4662
// LastContextDestroyNotification
4663
//
4664

4665
procedure TGLContextManager.LastContextDestroyNotification(
4666
  anObject: TObject; anEvent: TNotifyEvent);
4667
begin
4668
  Lock;
4669
  try
4670
    SetLength(FNotifications, Length(FNotifications) + 1);
4671
    with FNotifications[High(FNotifications)] do
4672
    begin
4673
      obj := anObject;
4674
      event := anEvent;
4675
    end;
4676
  finally
4677
    UnLock;
4678
  end;
4679
end;
4680

4681
// RemoveNotification
4682
//
4683

4684
procedure TGLContextManager.RemoveNotification(anObject: TObject);
4685
var
4686
  i: Integer;
4687
  found: Boolean;
4688
begin
4689
  Lock;
4690
  try
4691
    found := False;
4692
    i := Low(FNotifications);
4693
    while i <= High(FNotifications) do
4694
    begin
4695
      if FNotifications[i].obj = anObject then
4696
      begin
4697
        found := True;
4698
        while i <= High(FNotifications) do
4699
        begin
4700
          FNotifications[i] := FNotifications[i + 1];
4701
          Inc(i);
4702
        end;
4703
        SetLength(FNotifications, Length(FNotifications) - 1);
4704
        Break;
4705
      end;
4706
      Inc(i);
4707
    end;
4708
    if not found then
4709
      raise EGLContext.Create(cInvalidNotificationRemoval);
4710
  finally
4711
    UnLock;
4712
  end;
4713
end;
4714

4715
// Terminate
4716
//
4717

4718
procedure TGLContextManager.Terminate;
4719
begin
4720
  FTerminated := True;
4721
{$IFDEF GLS_SERVICE_CONTEXT}
4722
  // Sevice context may not be created becouse Application.Initialize not happened
4723
  if Assigned(FServiceContext) then
4724
  begin
4725
    CheckSynchronize;
4726
    FThread.Terminate;
4727
    FServiceStarter.SetEvent;
4728
    FThread.WaitFor;
4729
    FThread.Destroy;
4730
    GLSLogger.LogDebug('Service thread destroyed');
4731
    FServiceStarter.Destroy;
4732
    FThreadTask.Destroy;
4733
  end;
4734
{$ENDIF}
4735
  if ContextCount = 0 then
4736
  begin
4737
    GLContextManager := nil;
4738
    Free;
4739
  end;
4740
end;
4741

4742
// DestroyAllHandles
4743
//
4744

4745
procedure TGLContextManager.DestroyAllHandles;
4746
var
4747
  i: Integer;
4748
begin
4749
  with FList.LockList do
4750
    try
4751
      for i := Count - 1 downto 0 do
4752
        TGLContext(Items[i]).DestroyAllHandles;
4753
    finally
4754
      FList.UnLockList;
4755
    end;
4756
end;
4757

4758
{$IFDEF GLS_SERVICE_CONTEXT}
4759

4760
{$REGION 'TServiceContextThread'}
4761

4762
constructor TServiceContextThread.Create;
4763
begin
4764
  FWindow := TForm.CreateNew(Application);
4765
  FWindow.Hide;
4766
  FWindow.Position := poScreenCenter;
4767
  FWindow.Width := 1;
4768
  FWindow.Height := 1;
4769
  FWindow.BorderStyle := bsNone;
4770
  FWindow.FormStyle := fsStayOnTop;
4771
  FWindow.Color := 0;
4772
  vServiceWindow := FWindow;
4773
{$IFDEF MSWINDOWS}
4774
  FDC := GetDC(FWindow.Handle);
4775
{$ENDIF}
4776
{$IFDEF LINUX}
4777
  FDC := FWindow.Handle;
4778
{$ENDIF}
4779
  inherited Create(False);
4780
end;
4781

4782
destructor TServiceContextThread.Destroy;
4783
begin
4784
  inherited;
4785
end;
4786

4787
procedure TServiceContextThread.DoCreateServiceContext; stdcall;
4788

4789
  procedure Fail;
4790
  begin
4791
    GLSLogger.LogError(Format('%s: can''t initialize rendering context', [ClassName]));
4792
    FWindow.Destroy;
4793
    vServiceWindow := nil;
4794
  end;
4795

4796
begin
4797
  try
4798
    GLContextManager.ServiceContext.Acceleration := chaHardware;
4799
    GLContextManager.ServiceContext.CreateMemoryContext(FDC, 1, 1, 1);
4800
  except
4801
    on EGLContext do
4802
    begin
4803
      Fail;
4804
      exit;
4805
    end;
4806
    on EPBuffer do
4807
    begin
4808
      GLSLogger.LogWarning(Format('%s: can''t initialize memory rendering context. Try initialize common context.', [ClassName]));
4809
      try
4810
        GLContextManager.ServiceContext.CreateContext(FDC);
4811
      except
4812
        Fail;
4813
        exit;
4814
      end;
4815
    end;
4816
  end;
4817
  GLSLogger.LogNotice('Service context successfuly initialized');
4818
  GLContextManager.ServiceContext.Activate;
4819
  FWindow.Hide;
4820
  vServiceWindow := nil;
4821
end;
4822

4823
procedure TServiceContextThread.Execute;
4824
var
4825
  TaskRec: TServiceContextTask;
4826

4827
  procedure NextTask;
4828
  const
4829
    NullTask: TServiceContextTask = (Task: nil; Event: nil);
4830
  var
4831
    I: Integer;
4832
  begin
4833
    TaskRec.Task := nil;
4834
    with GLContextManager.FThreadTask.LockList do
4835
      try
4836
        for I := 0 to Count - 1 do
4837
        begin
4838
          TaskRec := Items[I];
4839
          if Assigned(TaskRec.Task) then
4840
          begin
4841
            Items[I] := NullTask;
4842
            break;
4843
          end;
4844
        end;
4845
      finally
4846
        GLContextManager.FThreadTask.UnlockList;
4847
      end;
4848
  end;
4849

4850
begin
4851
  with GLContextManager do
4852
  begin
4853
    vMainThread := False;
4854
    GLSLogger.LogNotice('Service thread started');
4855
    Sleep(100);
4856
    try
4857
      while not Terminated do
4858
      begin
4859
        NextTask;
4860
        if Assigned(TaskRec.Task) then
4861
        begin
4862
          with GLContextManager.ServiceContext do
4863
          begin
4864
            if IsValid then
4865
              Activate;
4866
            try
4867
              TaskRec.Task;
4868
            except
4869
              GLSLogger.LogError('Service thread task raised exception');
4870
            end;
4871
            if IsValid then
4872
              Deactivate;
4873
            if Assigned(TaskRec.Event) then
4874
              TaskRec.Event.SetEvent;
4875
          end;
4876
         end
4877
        else
4878
          Synchronize(GLContextManager.QueueTaskDepleted);
4879
        ServiceStarter.WaitFor(30000);
4880
      end;
4881
    finally
4882
      ServiceContext.Destroy;
4883
      FServiceContext := nil;
4884
      GLSLogger.LogNotice('Service thread finished');
4885
    end;
4886
  end;
4887
end;
4888

4889
procedure AddTaskForServiceContext(ATask: TTaskProcedure; FinishEvent: TFinishTaskEvent = nil);
4890
var
4891
  TaskRec: TServiceContextTask;
4892
  rEvent: TFinishTaskEvent;
4893
begin
4894
  if vMainThread then
4895
  begin
4896
    rEvent := nil;
4897
    if Assigned(GLContextManager.ServiceContext) and Assigned(ATask) then
4898
    begin
4899
      CheckSynchronize;
4900
      with GLContextManager.FThreadTask.LockList do
4901
        try
4902
          TaskRec.Task := ATask;
4903
          if FinishEvent = nil then
4904
          begin // Synchronous call
4905
            rEvent := TFinishTaskEvent.Create;
4906
            TaskRec.Event := rEvent;
4907
          end
4908
          else  // Asynchronous call
4909
            TaskRec.Event := FinishEvent;
4910
          Add(TaskRec);
4911
          with TServiceContextThread(GLContextManager.FThread) do
4912
          begin
4913
            FLastTaskStartTime := GLSTime;
4914
            FReported := False;
4915
          end;
4916
        finally
4917
          GLContextManager.FThreadTask.UnlockList;
4918
        end;
4919
      GLContextManager.ServiceStarter.SetEvent;
4920
    end;
4921
    // Wait task finishing
4922
    if Assigned(rEvent) then
4923
    begin
4924
      rEvent.WaitFor(INFINITE);
4925
      rEvent.Destroy;
4926
      CheckSynchronize;
4927
    end;
4928
  end
4929
  else
4930
  begin // Direct task execution in service thread
4931
    try
4932
      ATask;
4933
    except
4934
      GLSLogger.LogError('Service thread task raised exception');
4935
    end;
4936
    if Assigned(FinishEvent) then
4937
      FinishEvent.SetEvent;
4938
  end;
4939
end;
4940

4941
{$ENDIF GLS_SERVICE_CONTEXT}
4942

4943
constructor TFinishTaskEvent.Create;
4944
begin
4945
  inherited Create(nil, True, False, '');
4946
end;
4947

4948
// ------------------------------------------------------------------
4949
// ------------------------------------------------------------------
4950
// ------------------------------------------------------------------
4951

4952
initialization
4953
  // ------------------------------------------------------------------
4954
  // ------------------------------------------------------------------
4955
  // ------------------------------------------------------------------
4956

4957
  vMainThread := True;
4958
{$IFDEF GLS_SERVICE_CONTEXT}
4959
  OldInitProc := InitProc;
4960
  InitProc := @OnApplicationInitialize;
4961
{$ENDIF GLS_SERVICE_CONTEXT}
4962
  GLContextManager := TGLContextManager.Create;
4963
  GLwithoutContext := TGLExtensionsAndEntryPoints.Create;
4964
  GLwithoutContext.Close;
4965
  vLocalGL := @GL;
4966

4967
finalization
4968

4969
  GLContextManager.Terminate;
4970
  vContextClasses.Free;
4971
  vContextClasses := nil;
4972
  GLwithoutContext.Free;
4973
  GLwithoutContext := nil;
4974

4975
end.
4976

4977

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.