GLS.Context.pas 109 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831
  1. //
  2. // The multimedia graphics platform GLScene https://github.com/glscene
  3. //
  4. unit GLS.Context;
  5. (* Prototypes and base implementation of TGLContext *)
  6. interface
  7. {$I GLScene.inc}
  8. uses
  9. Winapi.OpenGL,
  10. Winapi.OpenGLext,
  11. Winapi.Windows,
  12. System.Classes,
  13. System.SysUtils,
  14. System.Types,
  15. System.SyncObjs,
  16. VCL.Forms,
  17. VCL.Controls,
  18. VCL.Consts,
  19. {$IFDEF USE_SERVICE_CONTEXT}
  20. GLS.Generics,
  21. {$ENDIF}
  22. GLS.OpenGLTokens,
  23. GLS.OpenGLAdapter,
  24. GLS.XOpenGL,
  25. GLS.VectorGeometry,
  26. GLS.Strings,
  27. GLS.VectorTypes,
  28. GLS.State,
  29. GLS.PipelineTransformation,
  30. GLS.TextureFormat,
  31. GLS.Logger;
  32. // Buffer ID's for Multiple-Render-Targets (using GL_ATI_draw_buffers)
  33. const
  34. MRT_BUFFERS: array [0 .. 3] of TGLuint = (GL_FRONT_LEFT, GL_AUX0, GL_AUX1, GL_AUX2);
  35. type
  36. TGLRCOption = (rcoDoubleBuffered, rcoStereo, rcoDebug, rcoOGL_ES);
  37. TGLRCOptions = set of TGLRCOption;
  38. TGLContextLayer = (clUnderlay2, clUnderlay1, clMainPlane, clOverlay1, clOverlay2);
  39. TFinishTaskEvent = class(TEvent)
  40. public
  41. constructor Create; reintroduce;
  42. end;
  43. TTaskProcedure = procedure of object; stdcall;
  44. TServiceContextTask = record
  45. Task: TTaskProcedure;
  46. Event: TFinishTaskEvent;
  47. end;
  48. {$IFDEF USE_SERVICE_CONTEXT}
  49. TServiceContextTaskList = {$IFDEF USE_GENERIC_PREFIX} specialize {$ENDIF}
  50. GThreadList<TServiceContextTask>;
  51. {$ENDIF USE_SERVICE_CONTEXT}
  52. TGLContextManager = class;
  53. TGLContextAcceleration = (chaUnknown, chaHardware, chaSoftware);
  54. TGLAntiAliasing = (
  55. // Multisample Antialiasing
  56. aaDefault, aaNone, aa2x, aa2xHQ, aa4x, aa4xHQ, aa6x, aa8x, aa16x,
  57. // Coverage Sampling Antialiasing
  58. csa8x, csa8xHQ, csa16x, csa16xHQ);
  59. TGLVSyncMode = (vsmSync, vsmNoSync);
  60. (* Wrapper around an OpenGL rendering context.
  61. The aim of this class is to offer platform-independant
  62. initialization, activation and management of OpenGL
  63. rendering context. The class also offers notifications
  64. event and error/problems detection.
  65. This is a virtual abstract a class, and platform-specific
  66. subclasses must be used. All rendering context share the same lists *)
  67. TGLContext = class
  68. private
  69. FColorBits, FAlphaBits: Integer;
  70. FDepthBits: Integer;
  71. FStencilBits: Integer;
  72. FAccumBits: Integer;
  73. FAuxBuffers: Integer;
  74. FAntiAliasing: TGLAntiAliasing;
  75. FOptions: TGLRCOptions;
  76. FOnDestroyContext: TNotifyEvent;
  77. FManager: TGLContextManager;
  78. FActivationCount: Integer;
  79. FOwnedHandlesCount: Integer;
  80. FIsPraparationNeed: Boolean;
  81. procedure SetColorBits(const aColorBits: Integer); inline;
  82. procedure SetAlphaBits(const aAlphaBits: Integer); inline;
  83. procedure SetDepthBits(const val: Integer); inline;
  84. procedure SetStencilBits(const aStencilBits: Integer); inline;
  85. procedure SetAccumBits(const aAccumBits: Integer); inline;
  86. procedure SetAuxBuffers(const aAuxBuffers: Integer); inline;
  87. procedure SetOptions(const aOptions: TGLRCOptions); inline;
  88. procedure SetAntiAliasing(const val: TGLAntiAliasing); inline;
  89. procedure SetAcceleration(const val: TGLContextAcceleration); inline;
  90. function GetActive: Boolean; inline;
  91. procedure SetActive(const aActive: Boolean); inline;
  92. procedure SetLayer(const Value: TGLContextLayer); inline;
  93. protected
  94. Fgl: TGLExtensionsAndEntryPoints;
  95. Fxgl: TGLMultitextureCoordinator;
  96. FGLStates: TGLStateCache;
  97. FTransformation: TGLTransformation;
  98. FAcceleration: TGLContextAcceleration;
  99. FLayer: TGLContextLayer;
  100. {$IFNDEF USE_MULTITHREAD}
  101. FSharedContexts: TList;
  102. {$ELSE}
  103. FSharedContexts: TThreadList;
  104. FLock: TCriticalSection;
  105. {$ENDIF}
  106. procedure PropagateSharedContext;
  107. procedure DoCreateContext(ADeviceHandle: HDC); virtual; abstract;
  108. procedure DoCreateMemoryContext(outputDevice: HWND; width, height: Integer; BufferCount: Integer = 1); virtual; abstract;
  109. function DoShareLists(aContext: TGLContext): Boolean; virtual; abstract;
  110. procedure DoDestroyContext; virtual; abstract;
  111. procedure DoActivate; virtual; abstract;
  112. procedure DoDeactivate; virtual; abstract;
  113. class function ServiceContext: TGLContext;
  114. procedure MakeGLCurrent;
  115. public
  116. constructor Create; virtual;
  117. destructor Destroy; override;
  118. // An application-side cache of global per-context OpenGL states and parameters
  119. property GLStates: TGLStateCache read FGLStates;
  120. property PipelineTransformation: TGLTransformation read FTransformation;
  121. // Context manager reference
  122. property Manager: TGLContextManager read FManager;
  123. // Color bits for the rendering context
  124. property ColorBits: Integer read FColorBits write SetColorBits;
  125. // Alpha bits for the rendering context
  126. property AlphaBits: Integer read FAlphaBits write SetAlphaBits;
  127. // Depth bits for the rendering context
  128. property DepthBits: Integer read FDepthBits write SetDepthBits;
  129. // Stencil bits for the rendering context
  130. property StencilBits: Integer read FStencilBits write SetStencilBits;
  131. // Accumulation buffer bits for the rendering context
  132. property AccumBits: Integer read FAccumBits write SetAccumBits;
  133. // Auxiliary buffers bits for the rendering context
  134. property AuxBuffers: Integer read FAuxBuffers write SetAuxBuffers;
  135. // AntiAliasing option. Ignored if not hardware supported, currently based on ARB_multisample
  136. property AntiAliasing: TGLAntiAliasing read FAntiAliasing write SetAntiAliasing;
  137. // Specifies the layer plane that the rendering context is bound to
  138. property Layer: TGLContextLayer read FLayer write SetLayer;
  139. // Rendering context options
  140. property Options: TGLRCOptions read FOptions write SetOptions;
  141. (* Allows reading and defining the activity for the context.
  142. The methods of this property are just wrappers around calls to Activate and Deactivate *)
  143. property Active: Boolean read GetActive write SetActive;
  144. // Indicates if the context is hardware-accelerated
  145. property Acceleration: TGLContextAcceleration read FAcceleration write SetAcceleration;
  146. (* Triggered whenever the context is destroyed.
  147. This events happens *before* the context has been
  148. actually destroyed, OpenGL resource cleanup can still occur here *)
  149. property OnDestroyContext: TNotifyEvent read FOnDestroyContext write FOnDestroyContext;
  150. // Creates the context. This method must be invoked before the context can be used
  151. procedure CreateContext(ADeviceHandle: HDC); overload;
  152. (* Creates an in-memory context.
  153. The function should fail if no hardware-accelerated memory context
  154. can be created (the CreateContext method can handle software OpenGL contexts) *)
  155. procedure CreateMemoryContext(outputDevice: HWND; width, height: Integer; BufferCount: Integer = 1);
  156. (* Setup display list sharing between two rendering contexts.
  157. Both contexts must have the same pixel format *)
  158. procedure ShareLists(aContext: TGLContext);
  159. (* Destroy the context. Will fail if no context has been created.
  160. The method will first invoke the OnDestroyContext
  161. event, then attempts to deactivate the context
  162. (if it is active) before destroying it *)
  163. procedure DestroyContext;
  164. (* Activates the context.
  165. A context can be activated multiple times (and must be
  166. deactivated the same number of times), but this function
  167. will fail if another context is already active. *)
  168. procedure Activate;
  169. (* Deactivates the context. Will fail if the context is not active or another
  170. context has been activated *)
  171. procedure Deactivate;
  172. // Call OnPrepare for all handles
  173. procedure PrepareHandlesData;
  174. (* Returns true if the context is valid.
  175. A context is valid from the time it has been successfully
  176. created to the time of its destruction. *)
  177. function IsValid: Boolean; virtual; abstract;
  178. // Request to swap front and back buffers if they were defined
  179. procedure SwapBuffers; virtual; abstract;
  180. // Returns the first compatible context that isn't self in the shares
  181. function FindCompatibleContext: TGLContext;
  182. procedure DestroyAllHandles;
  183. function RenderOutputDevice: Pointer; virtual; abstract;
  184. // Access to OpenGL command and extension
  185. property GL: TGLExtensionsAndEntryPoints read Fgl;
  186. property MultitextureCoordinator: TGLMultitextureCoordinator read Fxgl;
  187. property IsPraparationNeed: Boolean read FIsPraparationNeed;
  188. end;
  189. TGLContextClass = class of TGLContext;
  190. (* A TGLContext with screen control property and methods.
  191. This variety of contexts is for drivers that access windows and OpenGL
  192. through an intermediate opaque cross-platform API.
  193. TGLSceneViewer won't use them, TGLMemoryViewer may be able to use them,
  194. but most of the time they will be accessed through a specific viewer
  195. class/subclass *)
  196. TGLScreenControlingContext = class(TGLContext)
  197. strict private
  198. FWidth, FHeight: Integer;
  199. FFullScreen: Boolean;
  200. public
  201. property Width: Integer read FWidth write FWidth;
  202. property Height: Integer read FHeight write FHeight;
  203. property FullScreen: Boolean read FFullScreen write FFullScreen;
  204. end;
  205. PGLRCHandle = ^TGLRCHandle;
  206. TGLRCHandle = record
  207. FRenderingContext: TGLContext;
  208. FHandle: TGLuint;
  209. FChanged: Boolean;
  210. end;
  211. TOnPrepareHandleData = procedure(aContext: TGLContext) of object;
  212. (* Wrapper around an OpenGL context handle.
  213. This wrapper also takes care of context registrations and data releases
  214. related to context releases an cleanups. This is an abstract class,
  215. use the TGLListHandle and TGLTextureHandle subclasses *)
  216. TGLContextHandle = class
  217. private
  218. FHandles: TList;
  219. FLastHandle: PGLRCHandle;
  220. FOnPrepare: TOnPrepareHandleData;
  221. function GetHandle: TGLuint; inline;
  222. function GetContext: TGLContext;
  223. function SearchRC(aContext: TGLContext): PGLRCHandle;
  224. function RCItem(AIndex: Integer): PGLRCHandle; inline;
  225. procedure CheckCurrentRC;
  226. protected
  227. // Invoked by when there is no compatible context left for relocation
  228. procedure ContextDestroying;
  229. // Specifies if the handle can be transfered across shared contexts
  230. class function Transferable: Boolean; virtual;
  231. class function IsValid(const ID: TGLuint): Boolean; virtual;
  232. function DoAllocateHandle: TGLuint; virtual; abstract;
  233. procedure DoDestroyHandle(var AHandle: TGLuint); virtual; abstract;
  234. public
  235. constructor Create; virtual;
  236. constructor CreateAndAllocate(failIfAllocationFailed: Boolean = True);
  237. destructor Destroy; override;
  238. // Return OpenGL identifier in current context
  239. property Handle: TGLuint read GetHandle;
  240. (* Return current rendering context if handle is allocated in it
  241. or first context where handle is allocated. *)
  242. property RenderingContext: TGLContext read GetContext;
  243. // Return True is data need update in current context
  244. function IsDataNeedUpdate: Boolean; inline;
  245. // Return True if data updated in all contexts
  246. function IsDataComplitelyUpdated: Boolean;
  247. // Notify the data was updated in current context
  248. procedure NotifyDataUpdated;
  249. // Notify the data was changed through all context
  250. procedure NotifyChangesOfData;
  251. // Checks if required extensions / OpenGL version are met
  252. class function IsSupported: Boolean; virtual;
  253. function IsAllocatedForContext(aContext: TGLContext = nil): Boolean;
  254. function IsShared: Boolean;
  255. function AllocateHandle: TGLuint;
  256. procedure DestroyHandle;
  257. property OnPrapare: TOnPrepareHandleData read FOnPrepare write FOnPrepare;
  258. end;
  259. TGLVirtualHandle = class;
  260. TGLVirtualHandleEvent = procedure(Sender: TGLVirtualHandle; var Handle: TGLuint) of object;
  261. // A context handle with event-based handle allocation and destruction
  262. TGLVirtualHandle = class(TGLContextHandle)
  263. private
  264. FOnAllocate, FOnDestroy: TGLVirtualHandleEvent;
  265. FTag: Integer;
  266. protected
  267. function DoAllocateHandle: TGLuint; override;
  268. procedure DoDestroyHandle(var AHandle: TGLuint); override;
  269. class function Transferable: Boolean; override;
  270. public
  271. property OnAllocate: TGLVirtualHandleEvent read FOnAllocate write FOnAllocate;
  272. property OnDestroy: TGLVirtualHandleEvent read FOnDestroy write FOnDestroy;
  273. property Tag: Integer read FTag write FTag;
  274. end;
  275. // Transferable virtual handle
  276. TGLVirtualHandleTransf = class(TGLVirtualHandle)
  277. protected
  278. class function Transferable: Boolean; override;
  279. end;
  280. // Manages a handle to a display list
  281. TGLListHandle = class(TGLContextHandle)
  282. protected
  283. function DoAllocateHandle: TGLuint; override;
  284. procedure DoDestroyHandle(var AHandle: TGLuint); override;
  285. class function IsValid(const ID: TGLuint): Boolean; override;
  286. public
  287. procedure NewList(mode: TGLuint); inline;
  288. procedure EndList; inline;
  289. procedure CallList; inline;
  290. end;
  291. // Manages a handle to a texture
  292. TGLTextureHandle = class(TGLContextHandle)
  293. private
  294. FTarget: TGLTextureTarget;
  295. procedure SetTarget(ATarget: TGLTextureTarget);
  296. protected
  297. function DoAllocateHandle: TGLuint; override;
  298. procedure DoDestroyHandle(var AHandle: TGLuint); override;
  299. class function IsValid(const ID: TGLuint): Boolean; override;
  300. public
  301. property Target: TGLTextureTarget read FTarget write SetTarget;
  302. end;
  303. // Manages a handle to a sampler
  304. TGLSamplerHandle = class(TGLContextHandle)
  305. protected
  306. function DoAllocateHandle: TGLuint; override;
  307. procedure DoDestroyHandle(var AHandle: TGLuint); override;
  308. class function IsValid(const ID: TGLuint): Boolean; override;
  309. public
  310. class function IsSupported: Boolean; override;
  311. end;
  312. (* Manages a handle to a query.
  313. Do not use this class directly, use one of its subclasses instead. *)
  314. TGLQueryHandle = class(TGLContextHandle)
  315. private
  316. FActive: Boolean;
  317. protected
  318. class function Transferable: Boolean; override;
  319. function DoAllocateHandle: TGLuint; override;
  320. procedure DoDestroyHandle(var AHandle: TGLuint); override;
  321. function GetTarget: TGLuint; virtual; abstract;
  322. function GetQueryType: TGLQueryType; virtual; abstract;
  323. class function IsValid(const ID: TGLuint): Boolean; override;
  324. public
  325. procedure BeginQuery;
  326. procedure EndQuery;
  327. // Check if result is available from the query. Result may not be available
  328. // immediately after ending the query
  329. function IsResultAvailable: Boolean;
  330. // Number of bits used to store the query result. eg. 32/64 bit
  331. function CounterBits: Integer;
  332. // Retrieve query result, may cause a stall if the result is not available yet
  333. function QueryResultInt: TGLint;
  334. function QueryResultUInt: TGLUInt;
  335. function QueryResultInt64: TGLint64EXT;
  336. function QueryResultUInt64: TGLuint64EXT;
  337. function QueryResultBool: TGLboolean;
  338. property Target: TGLuint read GetTarget;
  339. property QueryType: TGLQueryType read GetQueryType;
  340. // True if within a Begin/EndQuery.
  341. property Active: Boolean read FActive;
  342. end;
  343. (* Manages a handle to an occlusion query.
  344. Requires OpenGL 1.5+
  345. Does *NOT* check for extension availability, this is assumed to have been
  346. checked by the user. *)
  347. TGLOcclusionQueryHandle = class(TGLQueryHandle)
  348. protected
  349. function GetTarget: TGLuint; override;
  350. function GetQueryType: TGLQueryType; override;
  351. public
  352. class function IsSupported: Boolean; override;
  353. // Number of samples (pixels) drawn during the query, some pixels may
  354. // be drawn to several times in the same query
  355. function PixelCount: Integer;
  356. end;
  357. TGLBooleanOcclusionQueryHandle = class(TGLQueryHandle)
  358. protected
  359. function GetTarget: TGLuint; override;
  360. function GetQueryType: TGLQueryType; override;
  361. public
  362. class function IsSupported: Boolean; override;
  363. end;
  364. (* Manages a handle to a timer query.
  365. Requires GL_EXT_timer_query extension.
  366. Does *NOT* check for extension availability, this is assumed to have been
  367. checked by the user. *)
  368. TGLTimerQueryHandle = class(TGLQueryHandle)
  369. protected
  370. function GetTarget: TGLuint; override;
  371. function GetQueryType: TGLQueryType; override;
  372. public
  373. class function IsSupported: Boolean; override;
  374. // Time, in nanoseconds (1 ns = 10^-9 s) between starting + ending the query.
  375. // with 32 bit integer can measure up to approximately 4 seconds, use
  376. // QueryResultUInt64 if you may need longer
  377. function Time: Integer;
  378. end;
  379. (* Manages a handle to a primitive query.
  380. Requires OpenGL 3.0+
  381. Does *NOT* check for extension availability, this is assumed to have been
  382. checked by the user. *)
  383. TGLPrimitiveQueryHandle = class(TGLQueryHandle)
  384. protected
  385. function GetTarget: TGLuint; override;
  386. function GetQueryType: TGLQueryType; override;
  387. public
  388. class function IsSupported: Boolean; override;
  389. // Number of primitives (eg. Points, Triangles etc.) drawn whilst the
  390. // query was active
  391. function PrimitivesGenerated: Integer;
  392. end;
  393. (* Manages a handle to a Buffer Object.
  394. Does *NOT* check for extension availability, this is assumed to have been
  395. checked by the user. *)
  396. TGLBufferObjectHandle = class(TGLContextHandle)
  397. private
  398. FSize: Integer;
  399. protected
  400. function DoAllocateHandle: TGLuint; override;
  401. procedure DoDestroyHandle(var AHandle: TGLuint); override;
  402. function GetTarget: TGLuint; virtual; abstract;
  403. class function IsValid(const ID: TGLuint): Boolean; override;
  404. public
  405. // Creates the buffer object buffer and initializes it.
  406. constructor CreateFromData(p: Pointer; size: Integer; bufferUsage: TGLuint);
  407. procedure Bind; virtual; abstract;
  408. // Note that it is not necessary to UnBind before Binding another buffer.
  409. procedure UnBind; virtual; abstract;
  410. (* Bind a buffer object to an indexed target, used by transform feedback
  411. buffer objects and uniform buffer objects. (OpenGL 3.0+) *)
  412. procedure BindRange(index: TGLuint; offset: TGLintptr; size: TGLsizeiptr); virtual;
  413. // Equivalent to calling BindRange with offset = 0, and size = the size of buffer.
  414. procedure BindBase(index: TGLuint); virtual;
  415. procedure UnBindBase(index: TGLuint); virtual;
  416. (* Specifies buffer content.
  417. Common bufferUsage values are GL_STATIC_DRAW_ARB for data that will
  418. change rarely, but be used often, GL_STREAM_DRAW_ARB for data specified
  419. once but used only a few times, and GL_DYNAMIC_DRAW_ARB for data
  420. that is re-specified very often. Valid only if the buffer has been bound. *)
  421. procedure BufferData(p: Pointer; size: Integer; bufferUsage: TGLuint);
  422. // Invokes Bind then BufferData
  423. procedure BindBufferData(p: Pointer; size: Integer; bufferUsage: TGLuint);
  424. (* Updates part of an already existing buffer.
  425. offset and size indicate which part of the data in the buffer is
  426. to bo modified and p where the data should be taken from. *)
  427. procedure BufferSubData(offset, size: Integer; p: Pointer);
  428. (* Map buffer content to memory.
  429. Values for access are GL_READ_ONLY_ARB, GL_WRITE_ONLY_ARB and
  430. GL_READ_WRITE_ARB.
  431. Valid only if the buffer has been bound, must be followed by
  432. an UnmapBuffer, only one buffer may be mapped at a time. *)
  433. function MapBuffer(access: TGLuint): Pointer;
  434. function MapBufferRange(offset: TGLint; len: TGLsizei; access: TGLbitfield): Pointer;
  435. procedure Flush(offset: TGLint; len: TGLsizei);
  436. (* Unmap buffer content from memory.
  437. Must follow a MapBuffer, and happen before the buffer is unbound. *)
  438. function UnmapBuffer: Boolean;
  439. class function IsSupported: Boolean; override;
  440. property Target: TGLuint read GetTarget;
  441. property BufferSize: Integer read FSize;
  442. end;
  443. (* Manages a handle to an Vertex Buffer Object, VBO.
  444. Does *NOT* check for extension availability, this is assumed to have been
  445. checked by the user.
  446. Do not use this class directly, use one of its subclasses instead. *)
  447. TGLVBOHandle = class(TGLBufferObjectHandle)
  448. private
  449. function GetVBOTarget: TGLuint;
  450. public
  451. property VBOTarget: TGLuint read GetVBOTarget;
  452. end;
  453. // Manages a handle to VBO Array Buffer. Typically used to store vertices, normals, texcoords, etc.
  454. TGLVBOArrayBufferHandle = class(TGLVBOHandle)
  455. protected
  456. function GetTarget: TGLuint; override;
  457. public
  458. procedure Bind; override;
  459. procedure UnBind; override;
  460. end;
  461. // Manages a handle to VBO Element Array Buffer. Typically used to store vertex indices.
  462. TGLVBOElementArrayHandle = class(TGLVBOHandle)
  463. protected
  464. function GetTarget: TGLuint; override;
  465. public
  466. procedure Bind; override;
  467. procedure UnBind; override;
  468. end;
  469. (* Manages a handle to PBO Pixel Pack Buffer.
  470. When bound, commands such as ReadPixels write their data into a buffer object. *)
  471. TGLPackPBOHandle = class(TGLBufferObjectHandle)
  472. protected
  473. function GetTarget: TGLuint; override;
  474. public
  475. procedure Bind; override;
  476. procedure UnBind; override;
  477. class function IsSupported: Boolean; override;
  478. end;
  479. (* Manages a handle to PBO Pixel Unpack Buffer.
  480. When bound, commands such as DrawPixels read
  481. their data from a buffer object *)
  482. TGLUnpackPBOHandle = class(TGLBufferObjectHandle)
  483. protected
  484. function GetTarget: TGLuint; override;
  485. public
  486. procedure Bind; override;
  487. procedure UnBind; override;
  488. class function IsSupported: Boolean; override;
  489. end;
  490. (* Manages a handle to a Transform Feedback Buffer Object.
  491. Transform feedback buffers can be used to capture vertex data from the
  492. vertex or geometry shader stage to perform further processing without
  493. going on to the fragment shader stage. *)
  494. TGLTransformFeedbackBufferHandle = class(TGLBufferObjectHandle)
  495. // FTransformFeedbackBufferBuffer: array[0..15] of Cardinal; // (0, 0, 0, ...)
  496. // FTransformFeedbackBufferStart: array[0..15] of TGLuint64; // (0, 0, 0, ...)
  497. // FTransformFeedbackBufferSize: array[0..15] of TGLuint64; // (0, 0, 0, ...)
  498. protected
  499. function GetTarget: TGLuint; override;
  500. public
  501. procedure Bind; override;
  502. procedure UnBind; override;
  503. procedure BeginTransformFeedback(primitiveMode: TGLuint);
  504. procedure EndTransformFeedback();
  505. procedure BindRange(index: TGLuint; offset: TGLintptr; size: TGLsizeiptr); override;
  506. procedure BindBase(index: TGLuint); override;
  507. procedure UnBindBase(index: TGLuint); override;
  508. class function IsSupported: Boolean; override;
  509. end;
  510. // Manages a handle to a Buffer Texture. (TBO)
  511. TGLTextureBufferHandle = class(TGLBufferObjectHandle)
  512. protected
  513. function GetTarget: TGLuint; override;
  514. public
  515. procedure Bind; override;
  516. procedure UnBind; override;
  517. class function IsSupported: Boolean; override;
  518. end;
  519. (* Manages a handle to a Uniform Buffer Object (UBO).
  520. Uniform buffer objects store "uniform blocks"; groups of uniforms
  521. that can be passed as a group into a GLSL program *)
  522. TGLUniformBufferHandle = class(TGLBufferObjectHandle)
  523. /// FUniformBufferBuffer: array[0..15] of GLuint; // (0, 0, 0, ...)
  524. /// FUniformBufferStart: array[0..15] of TGLuint64; // (0, 0, 0, ...)
  525. /// FUniformBufferSize: array[0..15] of TGLuint64; // (0, 0, 0, ...)
  526. protected
  527. function GetTarget: TGLuint; override;
  528. public
  529. procedure Bind; override;
  530. procedure UnBind; override;
  531. procedure BindRange(index: TGLuint; offset: TGLintptr; size: TGLsizeiptr); override;
  532. procedure BindBase(index: TGLuint); override;
  533. procedure UnBindBase(index: TGLuint); override;
  534. class function IsSupported: Boolean; override;
  535. end;
  536. (* Manages a handle to a Vertex Array Object (VAO). Vertex array objects are used
  537. to rapidly switch between large sets of array state *)
  538. TGLVertexArrayHandle = class(TGLContextHandle)
  539. protected
  540. class function Transferable: Boolean; override;
  541. function DoAllocateHandle: TGLuint; override;
  542. procedure DoDestroyHandle(var AHandle: TGLuint); override;
  543. class function IsValid(const ID: TGLuint): Boolean; override;
  544. public
  545. procedure Bind;
  546. procedure UnBind;
  547. class function IsSupported: Boolean; override;
  548. end;
  549. TGLFramebufferStatus = (fsComplete, fsIncompleteAttachment, fsIncompleteMissingAttachment, fsIncompleteDuplicateAttachment,
  550. fsIncompleteDimensions, fsIncompleteFormats, fsIncompleteDrawBuffer, fsIncompleteReadBuffer, fsUnsupported,
  551. fsIncompleteMultisample, fsStatusError);
  552. (* Manages a handle to a Framebuffer Object (FBO).
  553. Framebuffer objects provide a way of drawing to rendering
  554. destinations other than the buffers provided to the GL by the
  555. window-system. One or more "framebuffer-attachable images" can be attached
  556. to a Framebuffer for uses such as: offscreen rendering, "render to texture" +
  557. "multiple render targets" (MRT).
  558. There are several types of framebuffer-attachable images:
  559. - The image of a renderbuffer object, which is always 2D.
  560. - A single level of a 1D texture, which is treated as a 2D image with a height of one.
  561. - A single level of a 2D or rectangle texture.
  562. - A single face of a cube map texture level, which is treated as a 2D image.
  563. - A single layer of a 1D or 2D array texture or 3D texture, which is treated as a 2D image.
  564. Additionally, an entire level of a 3D texture, cube map texture,
  565. or 1D or 2D array texture can be attached to an attachment point.
  566. Such attachments are treated as an array of 2D images, arranged in
  567. layers, and the corresponding attachment point is considered to be layered *)
  568. TGLFramebufferHandle = class(TGLContextHandle)
  569. protected
  570. class function Transferable: Boolean; override;
  571. function DoAllocateHandle: TGLuint; override;
  572. procedure DoDestroyHandle(var AHandle: TGLuint); override;
  573. class function IsValid(const ID: TGLuint): Boolean; override;
  574. public
  575. // Bind framebuffer for both drawing + reading
  576. procedure Bind;
  577. // Bind framebuffer for drawing
  578. procedure BindForDrawing;
  579. // Bind framebuffer for reading
  580. procedure BindForReading;
  581. { Note that it is not necessary to unbind before binding another framebuffer. }
  582. procedure UnBind;
  583. procedure UnBindForDrawing;
  584. procedure UnBindForReading;
  585. // target = GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER (attach to both READ + DRAW)
  586. // attachment = COLOR_ATTACHMENTi, DEPTH_ATTACHMENT, STENCIL_ATTACHMENT, DEPTH_STENCIL_ATTACHMENT
  587. procedure Attach1DTexture(Target: TGLuint; attachment: TGLuint; textarget: TGLuint; texture: TGLuint; level: TGLint);
  588. procedure Attach2DTexture(Target: TGLuint; attachment: TGLuint; textarget: TGLuint; texture: TGLuint; level: TGLint);
  589. procedure Attach3DTexture(Target: TGLuint; attachment: TGLuint; textarget: TGLuint; texture: TGLuint; level: TGLint; Layer: TGLint);
  590. procedure AttachLayer(Target: TGLuint; attachment: TGLuint; texture: TGLuint; level: TGLint; Layer: TGLint);
  591. procedure AttachRenderBuffer(Target: TGLuint; attachment: TGLuint; renderbuffertarget: TGLuint; renderbuffer: TGLuint);
  592. (* OpenGL 3.2+ only.
  593. If texture is the name of a three-dimensional texture, cube map texture, one-or
  594. two-dimensional array texture, or two-dimensional multisample array texture, the
  595. texture level attached to the framebuffer attachment point is an array of images,
  596. and the framebuffer attachment is considered layered *)
  597. procedure AttachTexture(Target: TGLuint; attachment: TGLuint; texture: TGLuint; level: TGLint);
  598. // OpenGL 3.2+ only
  599. procedure AttachTextureLayer(Target: TGLuint; attachment: TGLuint; texture: TGLuint; level: TGLint; Layer: TGLint);
  600. // copy rect from bound read framebuffer to bound draw framebuffer
  601. procedure Blit(srcX0: TGLint; srcY0: TGLint; srcX1: TGLint; srcY1: TGLint; dstX0: TGLint; dstY0: TGLint; dstX1: TGLint;
  602. dstY1: TGLint; mask: TGLbitfield; filter: TGLuint);
  603. (* target = GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER (equivalent to GL_DRAW_FRAMEBUFFER)
  604. If default framebuffer (0) is bound:
  605. attachment = GL_FRONT_LEFT, GL_FRONT_RIGHT, GL_BACK_LEFT, or GL_BACK_RIGHT, GL_DEPTH, GL_STENCIL
  606. if a framebuffer object is bound:
  607. attachment = GL_COLOR_ATTACHMENTi, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT, GL_DEPTH_STENCIL_ATTACHMENT
  608. param = GL_FRAMEBUFFER_ATTACHMENT_(OBJECT_TYPE, OBJECT_NAME,
  609. RED_SIZE, GREEN_SIZE, BLUE_SIZE, ALPHA_SIZE, DEPTH_SIZE, STENCIL_SIZE,
  610. COMPONENT_TYPE, COLOR_ENCODING, TEXTURE_LEVEL, LAYERED, TEXTURE_CUBE_MAP_FACE, TEXTURE_LAYER *)
  611. function GetAttachmentParameter(Target: TGLuint; attachment: TGLuint; pname: TGLuint): TGLint;
  612. (* Returns the type of object bound to attachment point:
  613. GL_NONE, GL_FRAMEBUFFER_DEFAULT, GL_TEXTURE, or GL_RENDERBUFFER *)
  614. function GetAttachmentObjectType(Target: TGLuint; attachment: TGLuint): TGLint;
  615. // Returns the name (ID) of the texture or renderbuffer attached to attachment point
  616. function GetAttachmentObjectName(Target: TGLuint; attachment: TGLuint): TGLint;
  617. function GetStatus: TGLFramebufferStatus;
  618. function GetStringStatus(out clarification: string): TGLFramebufferStatus;
  619. class function IsSupported: Boolean; override;
  620. end;
  621. (* Manages a handle to a Renderbuffer Object.
  622. A Renderbuffer is a "framebuffer-attachable image" for generalized offscreen
  623. rendering and it also provides a means to support rendering to GL logical
  624. buffer types which have no corresponding texture format (stencil, accum, etc). *)
  625. TGLRenderbufferHandle = class(TGLContextHandle)
  626. protected
  627. function DoAllocateHandle: TGLuint; override;
  628. procedure DoDestroyHandle(var AHandle: TGLuint); override;
  629. class function IsValid(const ID: TGLuint): Boolean; override;
  630. public
  631. procedure Bind;
  632. procedure UnBind;
  633. procedure SetStorage(internalformat: TGLuint; width, height: TGLsizei);
  634. procedure SetStorageMultisample(internalformat: TGLuint; samples: TGLsizei; width, height: TGLsizei);
  635. class function IsSupported: Boolean; override;
  636. end;
  637. TGLARBProgramHandle = class(TGLContextHandle)
  638. private
  639. FReady: Boolean;
  640. FInfoLog: string;
  641. protected
  642. function DoAllocateHandle: TGLuint; override;
  643. procedure DoDestroyHandle(var AHandle: TGLuint); override;
  644. class function IsValid(const ID: TGLuint): Boolean; override;
  645. class function GetTarget: TGLuint; virtual; abstract;
  646. public
  647. procedure LoadARBProgram(const AText: string);
  648. procedure Enable;
  649. procedure Disable;
  650. procedure Bind;
  651. property Ready: Boolean read FReady;
  652. property InfoLog: string read FInfoLog;
  653. end;
  654. TGLARBVertexProgramHandle = class(TGLARBProgramHandle)
  655. protected
  656. class function GetTarget: TGLuint; override;
  657. public
  658. class function IsSupported: Boolean; override;
  659. end;
  660. TGLARBFragmentProgramHandle = class(TGLARBProgramHandle)
  661. protected
  662. class function GetTarget: TGLuint; override;
  663. public
  664. class function IsSupported: Boolean; override;
  665. end;
  666. TGLARBGeometryProgramHandle = class(TGLARBProgramHandle)
  667. protected
  668. class function GetTarget: TGLuint; override;
  669. public
  670. class function IsSupported: Boolean; override;
  671. end;
  672. (* Base class for GLSL handles (programs and shaders).
  673. Do not use this class directly, use one of its subclasses instead *)
  674. TGLSLHandle = class(TGLContextHandle)
  675. protected
  676. procedure DoDestroyHandle(var AHandle: TGLuint); override;
  677. public
  678. function InfoLog: string;
  679. class function IsSupported: Boolean; override;
  680. end;
  681. (* Manages a handle to a Shader Object.
  682. Does *NOT* check for extension availability, this is assumed to have been
  683. checked by the user.
  684. Do not use this class directly, use one of its subclasses instead *)
  685. TGLShaderHandle = class(TGLSLHandle)
  686. private
  687. FShaderType: TGLuint;
  688. protected
  689. function DoAllocateHandle: TGLuint; override;
  690. class function IsValid(const ID: TGLuint): Boolean; override;
  691. public
  692. procedure ShaderSource(const source: AnsiString); overload;
  693. // Returns True if compilation sucessful
  694. function CompileShader: Boolean;
  695. property ShaderType: TGLuint read FShaderType;
  696. end;
  697. TGLShaderHandleClass = class of TGLShaderHandle;
  698. // Manages a handle to a Vertex Shader Object
  699. TGLVertexShaderHandle = class(TGLShaderHandle)
  700. public
  701. constructor Create; override;
  702. class function IsSupported: Boolean; override;
  703. end;
  704. // Manages a handle to a Geometry Shader Object
  705. TGLGeometryShaderHandle = class(TGLShaderHandle)
  706. public
  707. constructor Create; override;
  708. class function IsSupported: Boolean; override;
  709. end;
  710. // Manages a handle to a Fragment Shader Object
  711. TGLFragmentShaderHandle = class(TGLShaderHandle)
  712. public
  713. constructor Create; override;
  714. class function IsSupported: Boolean; override;
  715. end;
  716. // Manages a handle to a Tessellation Control Shader Object
  717. TGLTessControlShaderHandle = class(TGLShaderHandle)
  718. public
  719. constructor Create; override;
  720. class function IsSupported: Boolean; override;
  721. end;
  722. // Manages a handle to a Tessellation Evaluation Shader Object
  723. TGLTessEvaluationShaderHandle = class(TGLShaderHandle)
  724. public
  725. constructor Create; override;
  726. class function IsSupported: Boolean; override;
  727. end;
  728. (* Manages a GLSL Program Object.
  729. Does *NOT* check for extension availability, this is assumed to have been
  730. checked by the user *)
  731. TGLProgramHandle = class(TGLSLHandle)
  732. public
  733. class function IsValid(const ID: TGLuint): Boolean; override;
  734. private
  735. FName: string;
  736. function GetUniform1i(const index: string): Integer;
  737. procedure SetUniform1i(const index: string; val: Integer);
  738. function GetUniform2i(const index: string): TVector2i;
  739. procedure SetUniform2i(const index: string; const Value: TVector2i);
  740. function GetUniform3i(const index: string): TVector3i;
  741. procedure SetUniform3i(const index: string; const Value: TVector3i);
  742. function GetUniform4i(const index: string): TVector4i;
  743. procedure SetUniform4i(const index: string; const Value: TVector4i);
  744. function GetUniform1f(const index: string): Single;
  745. procedure SetUniform1f(const index: string; val: Single);
  746. function GetUniform2f(const index: string): TVector2f;
  747. procedure SetUniform2f(const index: string; const val: TVector2f);
  748. function GetUniform3f(const index: string): TAffineVector;
  749. procedure SetUniform3f(const index: string; const val: TAffineVector);
  750. function GetUniform4f(const index: string): TGLVector;
  751. procedure SetUniform4f(const index: string; const val: TGLVector);
  752. function GetUniformMatrix2fv(const index: string): TMatrix2f;
  753. procedure SetUniformMatrix2fv(const index: string; const val: TMatrix2f);
  754. function GetUniformMatrix3fv(const index: string): TMatrix3f;
  755. procedure SetUniformMatrix3fv(const index: string; const val: TMatrix3f);
  756. function GetUniformMatrix4fv(const index: string): TGLMatrix;
  757. procedure SetUniformMatrix4fv(const index: string; const val: TGLMatrix);
  758. function GetUniformTextureHandle(const Index: string; const TextureIndex: Integer; const TextureTarget: TGLTextureTarget)
  759. : TGLuint;
  760. procedure SetUniformTextureHandle(const Index: string; const TextureIndex: Integer; const TextureTarget: TGLTextureTarget;
  761. const Value: TGLuint);
  762. procedure SetUniformBuffer(const Index: string; Value: TGLUniformBufferHandle);
  763. protected
  764. function DoAllocateHandle: TGLuint; override;
  765. public
  766. property Name: string read FName write FName;
  767. constructor Create; override;
  768. (* Compile and attach a new shader.
  769. Raises an EGLShader exception in case of failure. *)
  770. procedure AddShader(ShaderType: TGLShaderHandleClass; const ShaderSource: string;
  771. treatWarningsAsErrors: Boolean = False);
  772. procedure AttachObject(shader: TGLShaderHandle);
  773. procedure DetachAllObject;
  774. procedure BindAttribLocation(index: Integer; const aName: string);
  775. procedure BindFragDataLocation(index: Integer; const aName: string);
  776. function LinkProgram: Boolean;
  777. function ValidateProgram: Boolean;
  778. function GetAttribLocation(const aName: string): Integer;
  779. function GetUniformLocation(const aName: string): Integer;
  780. function GetUniformOffset(const aName: string): PGLInt;
  781. function GetUniformBlockIndex(const aName: string): Integer;
  782. function GetVaryingLocation(const aName: string): Integer;
  783. // Currently, NVidia-specific.
  784. procedure AddActiveVarying(const aName: string);
  785. // Currently, NVidia-specific.
  786. function GetUniformBufferSize(const aName: string): Integer;
  787. procedure UseProgramObject;
  788. procedure EndUseProgramObject;
  789. procedure SetUniformi(const index: string; const val: Integer); overload;
  790. procedure SetUniformi(const index: string; const val: TVector2i); overload;
  791. procedure SetUniformi(const index: string; const val: TVector3i); overload;
  792. procedure SetUniformi(const index: string; const val: TVector4i); overload;
  793. procedure SetUniformf(const index: string; const val: Single); overload;
  794. procedure SetUniformf(const index: string; const val: TVector2f); overload;
  795. procedure SetUniformf(const index: string; const val: TVector3f); overload;
  796. procedure SetUniformf(const index: string; const val: TVector4f); overload;
  797. // Shader parameters.
  798. property Uniform1i[const index: string]: Integer read GetUniform1i write SetUniform1i;
  799. property Uniform2i[const index: string]: TVector2i read GetUniform2i write SetUniform2i;
  800. property Uniform3i[const index: string]: TVector3i read GetUniform3i write SetUniform3i;
  801. property Uniform4i[const index: string]: TVector4i read GetUniform4i write SetUniform4i;
  802. property Uniform1f[const index: string]: Single read GetUniform1f write SetUniform1f;
  803. property Uniform2f[const index: string]: TVector2f read GetUniform2f write SetUniform2f;
  804. property Uniform3f[const index: string]: TAffineVector read GetUniform3f write SetUniform3f;
  805. property Uniform4f[const index: string]: TGLVector read GetUniform4f write SetUniform4f;
  806. property UniformMatrix2fv[const index: string]: TMatrix2f read GetUniformMatrix2fv write SetUniformMatrix2fv;
  807. property UniformMatrix3fv[const index: string]: TMatrix3f read GetUniformMatrix3fv write SetUniformMatrix3fv;
  808. property UniformMatrix4fv[const index: string]: TGLMatrix read GetUniformMatrix4fv write SetUniformMatrix4fv;
  809. property UniformTextureHandle[const index: string; const TextureIndex: Integer; const TextureTarget: TGLTextureTarget]
  810. : TGLuint read GetUniformTextureHandle write SetUniformTextureHandle;
  811. property UniformBuffer[const index: string]: TGLUniformBufferHandle write SetUniformBuffer;
  812. end;
  813. TGLContextNotification = record
  814. obj: TObject;
  815. Event: TNotifyEvent;
  816. end;
  817. // Stores and manages all the TGLContext objects.
  818. TGLContextManager = class
  819. private
  820. FList: TThreadList;
  821. FTerminated: Boolean;
  822. FNotifications: array of TGLContextNotification;
  823. FCreatedRCCount: Integer;
  824. {$IFDEF USE_MULTITHREAD}
  825. FHandles: TThreadList;
  826. {$ELSE}
  827. FHandles: TList;
  828. {$ENDIF USE_MULTITHREAD}
  829. {$IFDEF USE_SERVICE_CONTEXT}
  830. FThread: TThread;
  831. FServiceStarter: TEvent;
  832. FThreadTask: TServiceContextTaskList;
  833. {$ENDIF}
  834. FServiceContext: TGLContext;
  835. protected
  836. procedure Lock;
  837. procedure UnLock;
  838. procedure RegisterContext(aContext: TGLContext);
  839. procedure UnRegisterContext(aContext: TGLContext);
  840. procedure ContextCreatedBy(aContext: TGLContext);
  841. procedure DestroyingContextBy(aContext: TGLContext);
  842. {$IFDEF USE_SERVICE_CONTEXT}
  843. // Create a special service and resource-keeper context.
  844. procedure CreateServiceContext;
  845. procedure QueueTaskDepleted;
  846. property ServiceStarter: TEvent read FServiceStarter;
  847. {$ENDIF}
  848. property ServiceContext: TGLContext read FServiceContext;
  849. public
  850. constructor Create;
  851. destructor Destroy; override;
  852. (* Returns an appropriate, ready-to use context.
  853. The returned context should be freed by caller. *)
  854. function CreateContext(AClass: TGLContextClass = nil): TGLContext;
  855. (* Returns the number of TGLContext object.
  856. This is *not* the number of OpenGL rendering contexts! *)
  857. function ContextCount: Integer;
  858. (* Registers a new object to notify when the last context is destroyed.
  859. When the last rendering context is destroyed, the 'anEvent' will
  860. be invoked with 'anObject' as parameter.
  861. Note that the registration is kept until the notification is triggered
  862. or a RemoveNotification on 'anObject' is issued. *)
  863. procedure LastContextDestroyNotification(anObject: TObject; anEvent: TNotifyEvent);
  864. // Unregisters an object from the notification lists.
  865. procedure RemoveNotification(anObject: TObject);
  866. // Marks the context manager for termination
  867. procedure Terminate;
  868. // Request all contexts to destroy all their handles.
  869. procedure DestroyAllHandles;
  870. // Notify all contexts about necessity of handles preparation.
  871. procedure NotifyPreparationNeed;
  872. end;
  873. EGLContext = class(Exception);
  874. EGLShader = class(EGLContext);
  875. EPBuffer = class(Exception);
  876. // Drivers should register themselves via this function.
  877. procedure RegisterGLContextClass(aGLContextClass: TGLContextClass);
  878. (* The TGLContext that is the currently active context, if any.
  879. Returns nil if no context is active. *)
  880. function CurrentGLContext: TGLContext; inline;
  881. function SafeCurrentGLContext: TGLContext; inline;
  882. function IsMainThread: Boolean;
  883. function IsServiceContextAvaible: Boolean;
  884. function GetServiceWindow: TForm;
  885. {$IFDEF USE_SERVICE_CONTEXT}
  886. procedure AddTaskForServiceContext(ATask: TTaskProcedure; FinishEvent: TFinishTaskEvent = nil);
  887. {$ENDIF}
  888. var
  889. GLContextManager: TGLContextManager;
  890. vIgnoreOpenGLErrors: Boolean = False;
  891. vContextActivationFailureOccurred: Boolean = False;
  892. {$IFDEF USE_MULTITHREAD}
  893. threadvar
  894. {$ELSE}
  895. var
  896. {$ENDIF}
  897. vCurrentGLContext: TGLContext;
  898. GL: TGLExtensionsAndEntryPoints;
  899. xgl: TGLMultitextureCoordinator;
  900. vMainThread: Boolean;
  901. GLwithoutContext: TGLExtensionsAndEntryPoints;
  902. // ------------------------------------------------------------------
  903. implementation
  904. // ------------------------------------------------------------------
  905. {$IFDEF USE_SERVICE_CONTEXT}
  906. type
  907. TServiceContextThread = class(TThread)
  908. private
  909. FDC: HDC;
  910. FWindow: TForm;
  911. FLastTaskStartTime: Double;
  912. FReported: Boolean;
  913. protected
  914. procedure Execute; override;
  915. procedure DoCreateServiceContext; stdcall;
  916. public
  917. constructor Create;
  918. destructor Destroy; override;
  919. end;
  920. {$ENDIF}
  921. var
  922. vContextClasses: TList;
  923. vServiceWindow: TForm;
  924. {$IFDEF USE_SERVICE_CONTEXT}
  925. OldInitProc: Pointer;
  926. {$ENDIF}
  927. function CurrentGLContext: TGLContext; inline;
  928. begin
  929. Result := vCurrentGLContext;
  930. end;
  931. function SafeCurrentGLContext: TGLContext; inline;
  932. begin
  933. Result := CurrentGLContext;
  934. if not Assigned(Result) then
  935. begin
  936. {$IFDEF USE_LOGGING}
  937. LogError(strNoActiveRC);
  938. {$ENDIF}
  939. Abort;
  940. end;
  941. end;
  942. function IsMainThread: Boolean;
  943. begin
  944. Result := vMainThread;
  945. end;
  946. function IsServiceContextAvaible: Boolean;
  947. begin
  948. Result := GLContextManager.ServiceContext <> nil;
  949. end;
  950. function GetServiceWindow: TForm;
  951. begin
  952. Result := vServiceWindow;
  953. end;
  954. procedure RegisterGLContextClass(aGLContextClass: TGLContextClass);
  955. begin
  956. if not Assigned(vContextClasses) then
  957. vContextClasses := TList.Create;
  958. vContextClasses.Add(aGLContextClass);
  959. end;
  960. // ------------------
  961. // ------------------ TGLContext ------------------
  962. // ------------------
  963. constructor TGLContext.Create;
  964. begin
  965. inherited Create;
  966. {$IFDEF USE_MULTITHREAD}
  967. FLock := TCriticalSection.Create;
  968. {$ENDIF}
  969. FColorBits := 32;
  970. FStencilBits := 0;
  971. FAccumBits := 0;
  972. FAuxBuffers := 0;
  973. FLayer := clMainPlane;
  974. FOptions := [];
  975. {$IFNDEF USE_MULTITHREAD}
  976. FSharedContexts := TList.Create;
  977. {$ELSE}
  978. FSharedContexts := TThreadList.Create;
  979. {$ENDIF}
  980. FSharedContexts.Add(Self);
  981. FAcceleration := chaUnknown;
  982. FGLStates := TGLStateCache.Create;
  983. FGL := TGLExtensionsAndEntryPoints.Create;
  984. FTransformation := TGLTransformation.Create;
  985. FTransformation.LoadMatricesEnabled := True;
  986. GLContextManager.RegisterContext(Self);
  987. FIsPraparationNeed := True;
  988. FXGL := TGLMultitextureCoordinator.Create;
  989. end;
  990. destructor TGLContext.Destroy;
  991. begin
  992. if IsValid then
  993. DestroyContext;
  994. GLContextManager.UnRegisterContext(Self);
  995. FGLStates.Free;
  996. FGL.Free;
  997. FXGL.Free;
  998. FTransformation.Free;
  999. FSharedContexts.Free;
  1000. {$IFDEF USE_MULTITHREAD}
  1001. FLock.Free;
  1002. {$ENDIF}
  1003. inherited Destroy;
  1004. end;
  1005. procedure TGLContext.SetColorBits(const aColorBits: Integer);
  1006. begin
  1007. if Active then
  1008. raise EGLContext.Create(strCannotAlterAnActiveContext)
  1009. else
  1010. FColorBits := aColorBits;
  1011. end;
  1012. procedure TGLContext.SetAlphaBits(const aAlphaBits: Integer);
  1013. begin
  1014. if Active then
  1015. raise EGLContext.Create(strCannotAlterAnActiveContext)
  1016. else
  1017. FAlphaBits := aAlphaBits;
  1018. end;
  1019. procedure TGLContext.SetDepthBits(const val: Integer);
  1020. begin
  1021. if Active then
  1022. raise EGLContext.Create(strCannotAlterAnActiveContext)
  1023. else
  1024. FDepthBits := val;
  1025. end;
  1026. procedure TGLContext.SetLayer(const Value: TGLContextLayer);
  1027. begin
  1028. if Active then
  1029. raise EGLContext.Create(strCannotAlterAnActiveContext)
  1030. else
  1031. FLayer := Value;
  1032. end;
  1033. procedure TGLContext.SetStencilBits(const aStencilBits: Integer);
  1034. begin
  1035. if Active then
  1036. raise EGLContext.Create(strCannotAlterAnActiveContext)
  1037. else
  1038. FStencilBits := aStencilBits;
  1039. end;
  1040. procedure TGLContext.SetAccumBits(const aAccumBits: Integer);
  1041. begin
  1042. if Active then
  1043. raise EGLContext.Create(strCannotAlterAnActiveContext)
  1044. else
  1045. FAccumBits := aAccumBits;
  1046. end;
  1047. procedure TGLContext.SetAuxBuffers(const aAuxBuffers: Integer);
  1048. begin
  1049. if Active then
  1050. raise EGLContext.Create(strCannotAlterAnActiveContext)
  1051. else
  1052. FAuxBuffers := aAuxBuffers;
  1053. end;
  1054. procedure TGLContext.SetOptions(const aOptions: TGLRCOptions);
  1055. begin
  1056. if Active then
  1057. raise EGLContext.Create(strCannotAlterAnActiveContext)
  1058. else
  1059. FOptions := aOptions;
  1060. end;
  1061. procedure TGLContext.SetAntiAliasing(const val: TGLAntiAliasing);
  1062. begin
  1063. if Active then
  1064. raise EGLContext.Create(strCannotAlterAnActiveContext)
  1065. else
  1066. FAntiAliasing := val;
  1067. end;
  1068. procedure TGLContext.SetAcceleration(const val: TGLContextAcceleration);
  1069. begin
  1070. if Active then
  1071. raise EGLContext.Create(strCannotAlterAnActiveContext)
  1072. else
  1073. FAcceleration := val;
  1074. end;
  1075. function TGLContext.GetActive: Boolean;
  1076. begin
  1077. Result := (FActivationCount > 0);
  1078. end;
  1079. procedure TGLContext.SetActive(const aActive: Boolean);
  1080. begin
  1081. // activation/deactivation can be nested...
  1082. while aActive <> Active do
  1083. begin
  1084. if aActive then
  1085. Activate
  1086. else
  1087. Deactivate;
  1088. end;
  1089. end;
  1090. procedure TGLContext.CreateContext(ADeviceHandle: HDC);
  1091. begin
  1092. if IsValid then
  1093. raise EGLContext.Create(strContextAlreadyCreated);
  1094. DoCreateContext(ADeviceHandle);
  1095. Manager.ContextCreatedBy(Self);
  1096. end;
  1097. procedure TGLContext.CreateMemoryContext(outputDevice: HWND; Width, Height: Integer; BufferCount: Integer);
  1098. begin
  1099. if IsValid then
  1100. raise EGLContext.Create(strContextAlreadyCreated);
  1101. DoCreateMemoryContext(outputDevice, width, height, BufferCount);
  1102. Manager.ContextCreatedBy(Self);
  1103. end;
  1104. procedure TGLContext.PrepareHandlesData;
  1105. var
  1106. I: Integer;
  1107. LHandle: TGLContextHandle;
  1108. begin
  1109. if vCurrentGLContext = Self then
  1110. begin
  1111. {$IFNDEF USE_MULTITHREAD}
  1112. for I := Manager.FHandles.Count - 1 downto 0 do
  1113. begin
  1114. LHandle := TGLContextHandle(Manager.FHandles[I]);
  1115. if Assigned(LHandle.FOnPrepare) then
  1116. LHandle.FOnPrepare(Self);
  1117. end;
  1118. {$ELSE}
  1119. with Manager.FHandles.LockList do
  1120. try
  1121. for I := Count - 1 downto 0 do
  1122. begin
  1123. LHandle := TGLContextHandle(Items[I]);
  1124. if Assigned(LHandle.FOnPrepare) then
  1125. LHandle.FOnPrepare(Self);
  1126. end;
  1127. finally
  1128. Manager.FHandles.UnlockList;
  1129. end;
  1130. {$ENDIF}
  1131. FIsPraparationNeed := False;
  1132. end;
  1133. end;
  1134. procedure TGLContext.PropagateSharedContext;
  1135. var
  1136. I, j: Integer;
  1137. otherContext: TGLContext;
  1138. otherList: TList;
  1139. begin
  1140. {$IFNDEF USE_MULTITHREAD}
  1141. with FSharedContexts do
  1142. begin
  1143. for I := 1 to Count - 1 do
  1144. begin
  1145. otherContext := TGLContext(Items[I]);
  1146. otherList := otherContext.FSharedContexts;
  1147. for j := 0 to otherList.Count - 1 do
  1148. if IndexOf(otherList[j]) < 0 then
  1149. Add(otherList[j]);
  1150. end;
  1151. for I := 1 to Count - 1 do
  1152. begin
  1153. otherContext := TGLContext(Items[I]);
  1154. otherList := otherContext.FSharedContexts;
  1155. if otherList.IndexOf(Self) < 0 then
  1156. otherList.Add(Self);
  1157. end;
  1158. end;
  1159. {$ELSE}
  1160. with FSharedContexts.LockList do
  1161. try
  1162. for I := 1 to Count - 1 do
  1163. begin
  1164. otherContext := TGLContext(Items[I]);
  1165. otherList := otherContext.FSharedContexts.LockList;
  1166. for j := 0 to otherList.Count - 1 do
  1167. if IndexOf(otherList[j]) < 0 then
  1168. Add(otherList[j]);
  1169. otherContext.FSharedContexts.UnlockList;
  1170. end;
  1171. for I := 1 to Count - 1 do
  1172. begin
  1173. otherContext := TGLContext(Items[I]);
  1174. otherList := otherContext.FSharedContexts.LockList;
  1175. if otherList.IndexOf(Self) < 0 then
  1176. otherList.Add(Self);
  1177. otherContext.FSharedContexts.UnlockList;
  1178. end;
  1179. finally
  1180. FSharedContexts.UnlockList;
  1181. end;
  1182. {$ENDIF}
  1183. end;
  1184. procedure TGLContext.ShareLists(aContext: TGLContext);
  1185. begin
  1186. {$IFNDEF USE_MULTITHREAD}
  1187. if FSharedContexts.IndexOf(aContext) < 0 then
  1188. begin
  1189. if DoShareLists(aContext) then
  1190. begin
  1191. FSharedContexts.Add(aContext);
  1192. PropagateSharedContext;
  1193. end;
  1194. end;
  1195. {$ELSE}
  1196. with FSharedContexts.LockList do
  1197. try
  1198. if IndexOf(aContext) < 0 then
  1199. begin
  1200. if DoShareLists(aContext) then
  1201. begin
  1202. Add(aContext);
  1203. PropagateSharedContext;
  1204. end;
  1205. end;
  1206. finally
  1207. FSharedContexts.UnlockList;
  1208. end;
  1209. {$ENDIF}
  1210. end;
  1211. procedure TGLContext.DestroyAllHandles;
  1212. var
  1213. I: Integer;
  1214. begin
  1215. Activate;
  1216. try
  1217. {$IFNDEF USE_MULTITHREAD}
  1218. for I := Manager.FHandles.Count - 1 downto 0 do
  1219. TGLContextHandle(Manager.FHandles[I]).ContextDestroying;
  1220. {$ELSE}
  1221. with Manager.FHandles.LockList do
  1222. try
  1223. for I := Count - 1 downto 0 do
  1224. TGLContextHandle(Items[I]).ContextDestroying;
  1225. finally
  1226. Manager.FHandles.UnlockList;
  1227. end;
  1228. {$ENDIF}
  1229. finally
  1230. Deactivate;
  1231. end;
  1232. end;
  1233. procedure TGLContext.DestroyContext;
  1234. var
  1235. I: Integer;
  1236. oldContext, otherContext: TGLContext;
  1237. contextHandle: TGLContextHandle;
  1238. aList: TList;
  1239. begin
  1240. if vCurrentGLContext <> Self then
  1241. begin
  1242. oldContext := vCurrentGLContext;
  1243. if Assigned(oldContext) then
  1244. oldContext.Deactivate;
  1245. end
  1246. else
  1247. oldContext := nil;
  1248. Activate;
  1249. try
  1250. {$IFNDEF USE_MULTITHREAD}
  1251. for I := Manager.FHandles.Count - 1 downto 0 do
  1252. begin
  1253. contextHandle := TGLContextHandle(Manager.FHandles[I]);
  1254. contextHandle.ContextDestroying;
  1255. end;
  1256. {$ELSE}
  1257. aList := Manager.FHandles.LockList;
  1258. try
  1259. for I := aList.Count - 1 downto 0 do
  1260. begin
  1261. contextHandle := TGLContextHandle(aList[I]);
  1262. contextHandle.ContextDestroying;
  1263. end;
  1264. finally
  1265. Manager.FHandles.UnlockList;
  1266. end;
  1267. {$ENDIF}
  1268. Manager.DestroyingContextBy(Self);
  1269. {$IFDEF USE_MULTITHREAD}
  1270. aList := FSharedContexts.LockList;
  1271. {$ELSE}
  1272. aList := FSharedContexts;
  1273. {$ENDIF}
  1274. for I := 1 to aList.Count - 1 do
  1275. begin
  1276. otherContext := TGLContext(aList[I]);
  1277. otherContext.FSharedContexts.Remove(Self);
  1278. end;
  1279. FSharedContexts.Clear;
  1280. FSharedContexts.Add(Self);
  1281. {$IFDEF USE_MULTITHREAD}
  1282. FSharedContexts.UnlockList;
  1283. {$ENDIF}
  1284. Active := False;
  1285. DoDestroyContext;
  1286. finally
  1287. if Assigned(oldContext) then
  1288. oldContext.Activate;
  1289. end;
  1290. FAcceleration := chaUnknown;
  1291. FGL.Close;
  1292. end;
  1293. procedure TGLContext.Activate;
  1294. begin
  1295. {$IFDEF USE_MULTITHREAD}
  1296. FLock.Enter;
  1297. {$ENDIF}
  1298. if FActivationCount = 0 then
  1299. begin
  1300. if not IsValid then
  1301. raise EGLContext.Create(strContextNotCreated);
  1302. vContextActivationFailureOccurred := False;
  1303. try
  1304. DoActivate;
  1305. except
  1306. vContextActivationFailureOccurred := True;
  1307. end;
  1308. GLS.Context.GL := FGL;
  1309. xgl := FXGL;
  1310. vCurrentGLContext := Self;
  1311. end
  1312. else
  1313. Assert(vCurrentGLContext = Self, 'vCurrentGLContext <> Self');
  1314. Inc(FActivationCount);
  1315. end;
  1316. procedure TGLContext.Deactivate;
  1317. begin
  1318. Assert(vCurrentGLContext = Self);
  1319. Dec(FActivationCount);
  1320. if FActivationCount = 0 then
  1321. begin
  1322. if not IsValid then
  1323. raise EGLContext.Create(strContextNotCreated);
  1324. if not vContextActivationFailureOccurred then
  1325. DoDeactivate;
  1326. vCurrentGLContext := nil;
  1327. GLS.Context.GL := GLwithoutContext;
  1328. xgl := nil;
  1329. end
  1330. else if FActivationCount < 0 then
  1331. raise EGLContext.Create(strUnbalancedContexActivations);
  1332. {$IFDEF USE_MULTITHREAD}
  1333. FLock.Leave;
  1334. {$ENDIF}
  1335. end;
  1336. function TGLContext.FindCompatibleContext: TGLContext;
  1337. var
  1338. I: Integer;
  1339. begin
  1340. Result := nil;
  1341. {$IFNDEF USE_MULTITHREAD}
  1342. for I := 0 to FSharedContexts.Count - 1 do
  1343. if TGLContext(FSharedContexts[I]) <> Self then
  1344. begin
  1345. Result := TGLContext(FSharedContexts[I]);
  1346. Break;
  1347. end;
  1348. {$ELSE}
  1349. with FSharedContexts.LockList do
  1350. try
  1351. for I := 0 to Count - 1 do
  1352. if TGLContext(Items[I]) <> Self then
  1353. begin
  1354. Result := TGLContext(Items[I]);
  1355. Break;
  1356. end;
  1357. finally
  1358. FSharedContexts.UnlockList;
  1359. end;
  1360. {$ENDIF}
  1361. end;
  1362. class function TGLContext.ServiceContext: TGLContext;
  1363. begin
  1364. Result := GLContextManager.FServiceContext;
  1365. end;
  1366. procedure TGLContext.MakeGLCurrent;
  1367. begin
  1368. GLS.Context.GL := FGL;
  1369. end;
  1370. // ------------------
  1371. // ------------------ TGLContextHandle ------------------
  1372. // ------------------
  1373. constructor TGLContextHandle.Create;
  1374. begin
  1375. inherited Create;
  1376. FHandles := TList.Create;
  1377. // first is a dummy record
  1378. new(FLastHandle);
  1379. FillChar(FLastHandle^, sizeof(FLastHandle^), 0);
  1380. FHandles.Add(FLastHandle);
  1381. GLContextManager.FHandles.Add(Self);
  1382. end;
  1383. constructor TGLContextHandle.CreateAndAllocate(failIfAllocationFailed: Boolean = True);
  1384. begin
  1385. Create;
  1386. AllocateHandle;
  1387. if failIfAllocationFailed and (Handle = 0) then
  1388. raise EGLContext.Create('Auto-allocation failed');
  1389. end;
  1390. destructor TGLContextHandle.Destroy;
  1391. var
  1392. I: Integer;
  1393. begin
  1394. DestroyHandle;
  1395. for I := 0 to FHandles.Count - 1 do
  1396. Dispose(RCItem(I));
  1397. FHandles.Free;
  1398. if Assigned(GLContextManager) then
  1399. GLContextManager.FHandles.Remove(Self);
  1400. inherited Destroy;
  1401. end;
  1402. function TGLContextHandle.AllocateHandle: Cardinal;
  1403. var
  1404. I: Integer;
  1405. bSucces: Boolean;
  1406. aList: TList;
  1407. p: PGLRCHandle;
  1408. begin
  1409. // if handle aready allocated in current context
  1410. Result := GetHandle;
  1411. if Result <> 0 then
  1412. exit;
  1413. if vCurrentGLContext = nil then
  1414. begin
  1415. {$IFDEF USE_LOGGING}
  1416. GLSLogger.LogError('Failed to allocate OpenGL identifier - no active rendering context!');
  1417. {$ENDIF}
  1418. exit;
  1419. end;
  1420. // add entry
  1421. new(FLastHandle);
  1422. FillChar(FLastHandle^, sizeof(FLastHandle^), 0);
  1423. FHandles.Add(FLastHandle);
  1424. FLastHandle.FRenderingContext := vCurrentGLContext;
  1425. bSucces := False;
  1426. if Transferable then
  1427. begin
  1428. {$IFNDEF USE_MULTITHREAD}
  1429. aList := vCurrentGLContext.FSharedContexts;
  1430. {$ELSE}
  1431. aList := vCurrentGLContext.FSharedContexts.LockList;
  1432. try
  1433. {$ENDIF}
  1434. for I := aList.Count - 1 downto 0 do
  1435. begin
  1436. p := SearchRC(aList[I]);
  1437. if (p.FHandle > 0) then
  1438. begin
  1439. // Copy shared handle
  1440. // FLastHandle.FRenderingContext := vCurrentGLContext;
  1441. FLastHandle.FHandle := p.FHandle;
  1442. FLastHandle.FChanged := p.FChanged;
  1443. Inc(vCurrentGLContext.FOwnedHandlesCount);
  1444. bSucces := True;
  1445. Break;
  1446. end;
  1447. end;
  1448. {$IFNDEF USE_MULTITHREAD}
  1449. {$ELSE}
  1450. finally
  1451. vCurrentGLContext.FSharedContexts.UnlockList;
  1452. end;
  1453. {$ENDIF}
  1454. end;
  1455. if not bSucces then
  1456. begin
  1457. // Allocate handle in current context
  1458. FLastHandle.FHandle := DoAllocateHandle;
  1459. bSucces := FLastHandle.FHandle <> 0;
  1460. FLastHandle.FChanged := bSucces;
  1461. if bSucces then
  1462. Inc(vCurrentGLContext.FOwnedHandlesCount);
  1463. end;
  1464. Result := FLastHandle.FHandle;
  1465. if not bSucces then
  1466. GLSLogger.LogError(strNoActiveRC)
  1467. else if Assigned(FOnPrepare) then
  1468. GLContextManager.NotifyPreparationNeed;
  1469. end;
  1470. function TGLContextHandle.IsAllocatedForContext(aContext: TGLContext = nil): Boolean;
  1471. begin
  1472. Result := SearchRC(aContext).FHandle > 0;
  1473. end;
  1474. function TGLContextHandle.SearchRC(aContext: TGLContext): PGLRCHandle;
  1475. var
  1476. I: Integer;
  1477. begin
  1478. if aContext = nil then
  1479. aContext := vCurrentGLContext;
  1480. if aContext = FLastHandle.FRenderingContext then
  1481. begin
  1482. Result := FLastHandle;
  1483. exit;
  1484. end;
  1485. for I := 1 to FHandles.Count - 1 do
  1486. if RCItem(I).FRenderingContext = aContext then
  1487. begin
  1488. Result := RCItem(I);
  1489. exit;
  1490. end;
  1491. // first handle is always a dummy
  1492. Result := FHandles[0];
  1493. end;
  1494. procedure TGLContextHandle.CheckCurrentRC;
  1495. begin
  1496. if vCurrentGLContext <> FLastHandle.FRenderingContext then
  1497. FLastHandle := SearchRC(vCurrentGLContext);
  1498. end;
  1499. function TGLContextHandle.GetHandle: Cardinal;
  1500. begin
  1501. // CheckCurrentRC;
  1502. // inline doesn't always work... so optimize it here
  1503. if vCurrentGLContext <> FLastHandle.FRenderingContext then
  1504. FLastHandle := SearchRC(vCurrentGLContext);
  1505. Result := FLastHandle.FHandle;
  1506. end;
  1507. procedure TGLContextHandle.DestroyHandle;
  1508. var
  1509. oldContext: TGLContext;
  1510. p: PGLRCHandle;
  1511. I: Integer;
  1512. begin
  1513. oldContext := vCurrentGLContext;
  1514. if Assigned(oldContext) then
  1515. oldContext.Deactivate;
  1516. try
  1517. for I := FHandles.Count - 1 downto 1 do
  1518. begin
  1519. p := FHandles[I];
  1520. if p.FHandle > 0 then
  1521. begin
  1522. p.FRenderingContext.Activate;
  1523. if IsValid(p.FHandle) then
  1524. DoDestroyHandle(p.FHandle);
  1525. Dec(p.FRenderingContext.FOwnedHandlesCount);
  1526. p.FRenderingContext.Deactivate;
  1527. p.FRenderingContext := nil;
  1528. p.FHandle := 0;
  1529. p.FChanged := True;
  1530. end;
  1531. Dispose(p);
  1532. end;
  1533. FHandles.Count := 1; // delete all in 1 step
  1534. FLastHandle := FHandles[0];
  1535. finally
  1536. if Assigned(vCurrentGLContext) then
  1537. vCurrentGLContext.Deactivate;
  1538. if Assigned(oldContext) then
  1539. oldContext.Activate;
  1540. end;
  1541. end;
  1542. procedure TGLContextHandle.ContextDestroying;
  1543. var
  1544. I: Integer;
  1545. p: PGLRCHandle;
  1546. aList: TList;
  1547. bShared: Boolean;
  1548. begin
  1549. if Assigned(vCurrentGLContext) then
  1550. begin
  1551. bShared := False;
  1552. if Transferable then
  1553. begin
  1554. {$IFNDEF USE_MULTITHREAD}
  1555. aList := vCurrentGLContext.FSharedContexts;
  1556. {$ELSE}
  1557. aList := vCurrentGLContext.FSharedContexts.LockList;
  1558. try
  1559. {$ENDIF USE_MULTITHREAD}
  1560. for I := FHandles.Count - 1 downto 1 do
  1561. begin
  1562. p := RCItem(I);
  1563. if (p.FRenderingContext <> vCurrentGLContext) and (p.FHandle <> 0) and
  1564. (aList.IndexOf(p.FRenderingContext) > -1) then
  1565. begin
  1566. bShared := True;
  1567. Break;
  1568. end;
  1569. end;
  1570. {$IFDEF USE_MULTITHREAD}
  1571. finally
  1572. vCurrentGLContext.FSharedContexts.UnlockList;
  1573. end;
  1574. {$ENDIF USE_MULTITHREAD}
  1575. end;
  1576. for I := FHandles.Count - 1 downto 1 do
  1577. begin
  1578. p := RCItem(I);
  1579. if (p.FRenderingContext = vCurrentGLContext) and (p.FHandle <> 0) then
  1580. begin
  1581. if not bShared then
  1582. if IsValid(p.FHandle) then
  1583. DoDestroyHandle(p.FHandle);
  1584. Dec(p.FRenderingContext.FOwnedHandlesCount);
  1585. p.FHandle := 0;
  1586. p.FRenderingContext := nil;
  1587. p.FChanged := True;
  1588. Dispose(p);
  1589. FHandles.Delete(I);
  1590. if FLastHandle = p then
  1591. FLastHandle := FHandles[0];
  1592. exit;
  1593. end;
  1594. end;
  1595. end;
  1596. end;
  1597. function TGLContextHandle.GetContext: TGLContext;
  1598. var
  1599. I: Integer;
  1600. p: PGLRCHandle;
  1601. begin
  1602. Result := nil;
  1603. // Return first context where handle is allocated
  1604. for I := FHandles.Count - 1 downto 1 do
  1605. begin
  1606. p := RCItem(I);
  1607. if (p.FRenderingContext <> nil) and (p.FHandle <> 0) then
  1608. begin
  1609. Result := p.FRenderingContext;
  1610. // If handle allocated in active context - return it
  1611. if (Result = vCurrentGLContext) then
  1612. exit;
  1613. end;
  1614. end;
  1615. end;
  1616. function TGLContextHandle.IsDataNeedUpdate: Boolean;
  1617. begin
  1618. if GetHandle = 0 then
  1619. CheckCurrentRC;
  1620. Result := (FLastHandle.FHandle = 0) or FLastHandle.FChanged;
  1621. end;
  1622. function TGLContextHandle.IsDataComplitelyUpdated: Boolean;
  1623. var
  1624. I: Integer;
  1625. begin
  1626. Result := False;
  1627. for I := FHandles.Count - 1 downto 1 do
  1628. begin
  1629. with RCItem(I)^ do
  1630. if (FRenderingContext <> nil) and (FHandle <> 0) and FChanged then
  1631. exit;
  1632. end;
  1633. Result := True;
  1634. end;
  1635. procedure TGLContextHandle.NotifyDataUpdated;
  1636. var
  1637. I: Integer;
  1638. aList: TList;
  1639. begin
  1640. if Assigned(vCurrentGLContext) then
  1641. begin
  1642. if not Transferable then
  1643. begin
  1644. CheckCurrentRC();
  1645. if FLastHandle.FHandle <> 0 then
  1646. begin
  1647. FLastHandle.FChanged := False;
  1648. exit;
  1649. end;
  1650. end
  1651. else
  1652. begin
  1653. {$IFNDEF USE_MULTITHREAD}
  1654. aList := vCurrentGLContext.FSharedContexts;
  1655. {$ELSE}
  1656. aList := vCurrentGLContext.FSharedContexts.LockList;
  1657. try
  1658. {$ENDIF}
  1659. for I := 0 to aList.Count - 1 do
  1660. begin
  1661. with SearchRC(aList[I])^ do
  1662. if (FHandle <> 0) then
  1663. FChanged := False;
  1664. end;
  1665. {$IFDEF USE_MULTITHREAD}
  1666. finally
  1667. vCurrentGLContext.FSharedContexts.UnlockList;
  1668. end;
  1669. {$ENDIF}
  1670. end;
  1671. end
  1672. {$IFDEF USE_LOGGING}
  1673. else
  1674. GLSLogger.LogError(strNoActiveRC);
  1675. {$ENDIF}
  1676. end;
  1677. function TGLContextHandle.RCItem(AIndex: Integer): PGLRCHandle;
  1678. begin
  1679. Result := FHandles[AIndex];
  1680. end;
  1681. procedure TGLContextHandle.NotifyChangesOfData;
  1682. var
  1683. I: Integer;
  1684. begin
  1685. for I := FHandles.Count - 1 downto 1 do
  1686. RCItem(I).FChanged := True;
  1687. if Assigned(FOnPrepare) then
  1688. GLContextManager.NotifyPreparationNeed;
  1689. end;
  1690. function TGLContextHandle.IsShared: Boolean;
  1691. var
  1692. I: Integer;
  1693. vContext: TGLContext;
  1694. aList: TList;
  1695. begin
  1696. Result := False;
  1697. // untransferable handles can't be shared
  1698. if not Transferable then
  1699. exit;
  1700. Result := True;
  1701. {$IFNDEF USE_MULTITHREAD}
  1702. aList := vCurrentGLContext.FSharedContexts;
  1703. {$ELSE}
  1704. aList := vCurrentGLContext.FSharedContexts.LockList;
  1705. try
  1706. {$ENDIF}
  1707. for I := 0 to aList.Count - 1 do
  1708. begin
  1709. vContext := aList[I];
  1710. if (vContext <> vCurrentGLContext) and
  1711. // at least one context is friendly
  1712. (SearchRC(vContext).FHandle <> 0) then
  1713. exit;
  1714. end;
  1715. {$IFDEF USE_MULTITHREAD}
  1716. finally
  1717. vCurrentGLContext.FSharedContexts.UnlockList;
  1718. end;
  1719. {$ENDIF}
  1720. Result := False;
  1721. end;
  1722. class function TGLContextHandle.Transferable: Boolean;
  1723. begin
  1724. Result := True;
  1725. end;
  1726. class function TGLContextHandle.IsValid(const ID: Cardinal): Boolean;
  1727. begin
  1728. Result := True;
  1729. end;
  1730. class function TGLContextHandle.IsSupported: Boolean;
  1731. begin
  1732. Result := True;
  1733. end;
  1734. // ------------------
  1735. // ------------------ TGLVirtualHandle ------------------
  1736. // ------------------
  1737. function TGLVirtualHandle.DoAllocateHandle: Cardinal;
  1738. begin
  1739. Result := 0;
  1740. if Assigned(FOnAllocate) then
  1741. FOnAllocate(Self, Result);
  1742. end;
  1743. procedure TGLVirtualHandle.DoDestroyHandle(var AHandle: Cardinal);
  1744. begin
  1745. if not vContextActivationFailureOccurred then
  1746. begin
  1747. gl.ClearError;
  1748. if Assigned(FOnDestroy) then
  1749. FOnDestroy(Self, AHandle);
  1750. gl.CheckError;
  1751. end;
  1752. end;
  1753. class function TGLVirtualHandle.Transferable: Boolean;
  1754. begin
  1755. Result := False;
  1756. end;
  1757. // ------------------
  1758. // TGLVirtualHandleTransf
  1759. // ------------------
  1760. class function TGLVirtualHandleTransf.Transferable: Boolean;
  1761. begin
  1762. Result := True;
  1763. end;
  1764. // ------------------
  1765. // ------------------ TGLListHandle ------------------
  1766. // ------------------
  1767. function TGLListHandle.DoAllocateHandle: Cardinal;
  1768. begin
  1769. Result := gl.GenLists(1);
  1770. end;
  1771. procedure TGLListHandle.DoDestroyHandle(var AHandle: Cardinal);
  1772. begin
  1773. if not vContextActivationFailureOccurred then
  1774. begin
  1775. gl.ClearError;
  1776. gl.DeleteLists(AHandle, 1);
  1777. gl.CheckError;
  1778. end;
  1779. end;
  1780. class function TGLListHandle.IsValid(const ID: Cardinal): Boolean;
  1781. begin
  1782. Result := gl.IsList(ID);
  1783. end;
  1784. procedure TGLListHandle.NewList(mode: Cardinal);
  1785. begin
  1786. vCurrentGLContext.GLStates.NewList(GetHandle, mode);
  1787. end;
  1788. procedure TGLListHandle.EndList;
  1789. begin
  1790. vCurrentGLContext.GLStates.EndList;
  1791. end;
  1792. procedure TGLListHandle.CallList;
  1793. begin
  1794. vCurrentGLContext.GLStates.CallList(GetHandle);
  1795. end;
  1796. // ------------------
  1797. // ------------------ TGLTextureHandle ------------------
  1798. // ------------------
  1799. function TGLTextureHandle.DoAllocateHandle: Cardinal;
  1800. begin
  1801. Result := 0;
  1802. gl.GenTextures(1, @Result);
  1803. FTarget := ttNoShape;
  1804. end;
  1805. procedure TGLTextureHandle.DoDestroyHandle(var AHandle: Cardinal);
  1806. var
  1807. a: TGLInt;
  1808. t: TGLTextureTarget;
  1809. begin
  1810. if not vContextActivationFailureOccurred then
  1811. begin
  1812. gl.GetError;
  1813. // Unbind identifier from all image selectors.
  1814. if gl.ARB_multitexture then
  1815. begin
  1816. with GetContext.GLStates do
  1817. begin
  1818. for a := 0 to MaxTextureImageUnits - 1 do
  1819. for t := Low(TGLTextureTarget) to High(TGLTextureTarget) do
  1820. if TextureBinding[a, t] = AHandle then
  1821. TextureBinding[a, t] := 0;
  1822. end
  1823. end
  1824. else
  1825. with GetContext.GLStates do
  1826. for t := Low(TGLTextureTarget) to High(TGLTextureTarget) do
  1827. if TextureBinding[0, t] = AHandle then
  1828. TextureBinding[0, t] := 0;
  1829. gl.DeleteTextures(1, @AHandle);
  1830. gl.CheckError;
  1831. end;
  1832. end;
  1833. class function TGLTextureHandle.IsValid(const ID: Cardinal): Boolean;
  1834. begin
  1835. Result := gl.IsTexture(ID);
  1836. end;
  1837. procedure TGLTextureHandle.SetTarget(ATarget: TGLTextureTarget);
  1838. begin
  1839. if FTarget = ttNoShape then
  1840. FTarget := ATarget;
  1841. end;
  1842. // ------------------
  1843. // ------------------ TGLSamplerHandle ------------------
  1844. // ------------------
  1845. function TGLSamplerHandle.DoAllocateHandle: Cardinal;
  1846. begin
  1847. Result := 0;
  1848. gl.GenSamplers(1, @Result);
  1849. end;
  1850. procedure TGLSamplerHandle.DoDestroyHandle(var AHandle: Cardinal);
  1851. begin
  1852. if not vContextActivationFailureOccurred then
  1853. begin
  1854. gl.GetError;
  1855. gl.DeleteSamplers(1, @AHandle);
  1856. gl.CheckError;
  1857. end;
  1858. end;
  1859. class function TGLSamplerHandle.IsSupported: Boolean;
  1860. begin
  1861. Result := gl.ARB_sampler_objects;
  1862. end;
  1863. class function TGLSamplerHandle.IsValid(const ID: Cardinal): Boolean;
  1864. begin
  1865. Result := gl.IsSampler(ID);
  1866. end;
  1867. // ------------------
  1868. // ------------------ TGLQueryHandle ------------------
  1869. // ------------------
  1870. procedure TGLQueryHandle.BeginQuery;
  1871. begin
  1872. if vCurrentGLContext.GLStates.CurrentQuery[QueryType] = 0 then
  1873. vCurrentGLContext.GLStates.BeginQuery(QueryType, GetHandle);
  1874. FActive := True;
  1875. end;
  1876. function TGLQueryHandle.CounterBits: Integer;
  1877. begin
  1878. gl.GetQueryiv(Target, GL_QUERY_COUNTER_BITS, @Result);
  1879. end;
  1880. function TGLQueryHandle.DoAllocateHandle: Cardinal;
  1881. begin
  1882. Result := 0;
  1883. gl.GenQueries(1, @Result);
  1884. end;
  1885. procedure TGLQueryHandle.DoDestroyHandle(var AHandle: Cardinal);
  1886. begin
  1887. if not vContextActivationFailureOccurred then
  1888. begin
  1889. gl.GetError;
  1890. gl.DeleteQueries(1, @AHandle);
  1891. gl.CheckError;
  1892. end;
  1893. end;
  1894. class function TGLQueryHandle.IsValid(const ID: Cardinal): Boolean;
  1895. begin
  1896. Result := gl.IsQuery(ID);
  1897. end;
  1898. procedure TGLQueryHandle.EndQuery;
  1899. begin
  1900. Assert(FActive = True, 'Cannot end a query before it begins');
  1901. FActive := False;
  1902. Assert(Handle <> 0);
  1903. // glEndQuery(Target);
  1904. vCurrentGLContext.GLStates.EndQuery(QueryType);
  1905. end;
  1906. function TGLQueryHandle.IsResultAvailable: Boolean;
  1907. begin
  1908. gl.GetQueryObjectiv(Handle, GL_QUERY_RESULT_AVAILABLE, @Result);
  1909. end;
  1910. function TGLQueryHandle.QueryResultInt: TGLInt;
  1911. begin
  1912. gl.GetQueryObjectiv(Handle, GL_QUERY_RESULT, @Result);
  1913. end;
  1914. function TGLQueryHandle.QueryResultInt64: TGLint64EXT;
  1915. begin
  1916. gl.GetQueryObjecti64v(Handle, GL_QUERY_RESULT, @Result);
  1917. end;
  1918. function TGLQueryHandle.QueryResultUInt: Cardinal;
  1919. begin
  1920. gl.GetQueryObjectuiv(Handle, GL_QUERY_RESULT, @Result);
  1921. end;
  1922. function TGLQueryHandle.QueryResultUInt64: TGLuint64EXT;
  1923. begin
  1924. gl.GetQueryObjectui64v(Handle, GL_QUERY_RESULT, @Result);
  1925. end;
  1926. function TGLQueryHandle.QueryResultBool: TGLboolean;
  1927. var
  1928. I: Cardinal;
  1929. begin
  1930. gl.GetQueryObjectuiv(Handle, GL_QUERY_RESULT, @I);
  1931. Result := I > 0;
  1932. end;
  1933. class function TGLQueryHandle.Transferable: Boolean;
  1934. begin
  1935. Result := False;
  1936. end;
  1937. // ------------------
  1938. // ------------------ TGLOcclusionQueryHandle ------------------
  1939. // ------------------
  1940. function TGLOcclusionQueryHandle.GetQueryType: TGLQueryType;
  1941. begin
  1942. Result := qrySamplesPassed;
  1943. end;
  1944. function TGLOcclusionQueryHandle.GetTarget: Cardinal;
  1945. begin
  1946. Result := GL_SAMPLES_PASSED;
  1947. end;
  1948. class function TGLOcclusionQueryHandle.IsSupported: Boolean;
  1949. begin
  1950. Result := gl.VERSION_1_5;
  1951. end;
  1952. function TGLOcclusionQueryHandle.PixelCount: Integer;
  1953. begin
  1954. Result := QueryResultUInt;
  1955. end;
  1956. // ------------------
  1957. // ------------------ TGLBooleanOcclusionQueryHandle ------------------
  1958. // ------------------
  1959. function TGLBooleanOcclusionQueryHandle.GetQueryType: TGLQueryType;
  1960. begin
  1961. Result := qryAnySamplesPassed;
  1962. end;
  1963. function TGLBooleanOcclusionQueryHandle.GetTarget: Cardinal;
  1964. begin
  1965. Result := GL_ANY_SAMPLES_PASSED;
  1966. end;
  1967. class function TGLBooleanOcclusionQueryHandle.IsSupported: Boolean;
  1968. begin
  1969. Result := gl.ARB_occlusion_query2;
  1970. end;
  1971. // ------------------
  1972. // ------------------ TGLTimerQueryHandle ------------------
  1973. // ------------------
  1974. function TGLTimerQueryHandle.GetQueryType: TGLQueryType;
  1975. begin
  1976. Result := qryTimeElapsed;
  1977. end;
  1978. function TGLTimerQueryHandle.GetTarget: Cardinal;
  1979. begin
  1980. Result := GL_TIME_ELAPSED;
  1981. end;
  1982. class function TGLTimerQueryHandle.IsSupported: Boolean;
  1983. begin
  1984. Result := gl.EXT_timer_query or gl.ARB_timer_query;
  1985. end;
  1986. function TGLTimerQueryHandle.Time: Integer;
  1987. begin
  1988. Result := QueryResultUInt;
  1989. end;
  1990. // ------------------
  1991. // ------------------ TGLPrimitiveQueryHandle ------------------
  1992. // ------------------
  1993. function TGLPrimitiveQueryHandle.GetQueryType: TGLQueryType;
  1994. begin
  1995. Result := qryPrimitivesGenerated;
  1996. end;
  1997. function TGLPrimitiveQueryHandle.GetTarget: Cardinal;
  1998. begin
  1999. Result := GL_PRIMITIVES_GENERATED;
  2000. end;
  2001. class function TGLPrimitiveQueryHandle.IsSupported: Boolean;
  2002. begin
  2003. Result := gl.VERSION_3_0;
  2004. end;
  2005. function TGLPrimitiveQueryHandle.PrimitivesGenerated: Integer;
  2006. begin
  2007. Result := QueryResultUInt;
  2008. end;
  2009. // ------------------
  2010. // ------------------ TGLBufferObjectHandle ------------------
  2011. // ------------------
  2012. constructor TGLBufferObjectHandle.CreateFromData(p: Pointer; size: Integer; bufferUsage: Cardinal);
  2013. begin
  2014. Create;
  2015. AllocateHandle;
  2016. Bind;
  2017. BufferData(p, size, bufferUsage);
  2018. UnBind;
  2019. end;
  2020. function TGLBufferObjectHandle.DoAllocateHandle: Cardinal;
  2021. begin
  2022. Result := 0;
  2023. gl.GenBuffers(1, @Result);
  2024. end;
  2025. procedure TGLBufferObjectHandle.DoDestroyHandle(var AHandle: Cardinal);
  2026. begin
  2027. if not vContextActivationFailureOccurred then
  2028. begin
  2029. gl.GetError;
  2030. UnBind;
  2031. gl.DeleteBuffers(1, @AHandle);
  2032. gl.CheckError;
  2033. end;
  2034. end;
  2035. class function TGLBufferObjectHandle.IsValid(const ID: Cardinal): Boolean;
  2036. begin
  2037. Result := gl.IsBuffer(ID);
  2038. end;
  2039. class function TGLBufferObjectHandle.IsSupported: Boolean;
  2040. begin
  2041. Result := gl.ARB_vertex_buffer_object;
  2042. end;
  2043. procedure TGLBufferObjectHandle.BindRange(index: Cardinal; offset: TGLintptr; size: TGLsizeiptr);
  2044. begin
  2045. Assert(False, 'BindRange only XBO and UBO');
  2046. end;
  2047. procedure TGLBufferObjectHandle.BindBase(index: Cardinal);
  2048. begin
  2049. Assert(False, 'BindRange only XBO and UBO');
  2050. end;
  2051. procedure TGLBufferObjectHandle.UnBindBase(index: Cardinal);
  2052. begin
  2053. Assert(False, 'BindRange only XBO and UBO');
  2054. end;
  2055. procedure TGLBufferObjectHandle.BufferData(p: Pointer; size: Integer; bufferUsage: Cardinal);
  2056. begin
  2057. FSize := size;
  2058. gl.BufferData(Target, size, p, bufferUsage);
  2059. end;
  2060. procedure TGLBufferObjectHandle.BindBufferData(p: Pointer; size: Integer; bufferUsage: Cardinal);
  2061. begin
  2062. Bind;
  2063. FSize := size;
  2064. gl.BufferData(Target, size, p, bufferUsage);
  2065. end;
  2066. procedure TGLBufferObjectHandle.BufferSubData(offset, size: Integer; p: Pointer);
  2067. begin
  2068. Assert(offset + size <= FSize);
  2069. gl.BufferSubData(Target, offset, size, p);
  2070. end;
  2071. function TGLBufferObjectHandle.MapBuffer(access: Cardinal): Pointer;
  2072. begin
  2073. Result := gl.MapBuffer(Target, access);
  2074. end;
  2075. function TGLBufferObjectHandle.MapBufferRange(offset: TGLInt; len: TGLsizei; access: TGLbitfield): Pointer;
  2076. begin
  2077. Result := gl.MapBufferRange(Target, offset, len, access);
  2078. end;
  2079. procedure TGLBufferObjectHandle.Flush(offset: TGLInt; len: TGLsizei);
  2080. begin
  2081. gl.FlushMappedBufferRange(Target, offset, len);
  2082. end;
  2083. function TGLBufferObjectHandle.UnmapBuffer: Boolean;
  2084. begin
  2085. Result := gl.UnmapBuffer(Target);
  2086. end;
  2087. // ------------------
  2088. // ------------------ TGLVBOHandle ------------------
  2089. // ------------------
  2090. function TGLVBOHandle.GetVBOTarget: Cardinal;
  2091. begin
  2092. Result := Target;
  2093. end;
  2094. // ------------------
  2095. // ------------------ TGLVBOArrayBufferHandle ------------------
  2096. // ------------------
  2097. procedure TGLVBOArrayBufferHandle.Bind;
  2098. begin
  2099. vCurrentGLContext.GLStates.ArrayBufferBinding := Handle;
  2100. end;
  2101. procedure TGLVBOArrayBufferHandle.UnBind;
  2102. begin
  2103. vCurrentGLContext.GLStates.ArrayBufferBinding := 0;
  2104. end;
  2105. function TGLVBOArrayBufferHandle.GetTarget: Cardinal;
  2106. begin
  2107. Result := GL_ARRAY_BUFFER;
  2108. end;
  2109. // ------------------
  2110. // ------------------ TGLVBOElementArrayHandle ------------------
  2111. // ------------------
  2112. procedure TGLVBOElementArrayHandle.Bind;
  2113. begin
  2114. vCurrentGLContext.GLStates.ElementBufferBinding := Handle;
  2115. end;
  2116. procedure TGLVBOElementArrayHandle.UnBind;
  2117. begin
  2118. vCurrentGLContext.GLStates.ElementBufferBinding := 0;
  2119. end;
  2120. function TGLVBOElementArrayHandle.GetTarget: TGLuint;
  2121. begin
  2122. Result := GL_ELEMENT_ARRAY_BUFFER;
  2123. end;
  2124. // ------------------
  2125. // ------------------ TGLPackPBOHandle ------------------
  2126. // ------------------
  2127. procedure TGLPackPBOHandle.Bind;
  2128. begin
  2129. vCurrentGLContext.GLStates.PixelPackBufferBinding := Handle;
  2130. end;
  2131. procedure TGLPackPBOHandle.UnBind;
  2132. begin
  2133. vCurrentGLContext.GLStates.PixelPackBufferBinding := 0;
  2134. end;
  2135. function TGLPackPBOHandle.GetTarget: TGLuint;
  2136. begin
  2137. Result := GL_PIXEL_PACK_BUFFER;
  2138. end;
  2139. class function TGLPackPBOHandle.IsSupported: Boolean;
  2140. begin
  2141. Result := GL.ARB_pixel_buffer_object;
  2142. end;
  2143. // ------------------
  2144. // ------------------ TGLUnpackPBOHandle ------------------
  2145. // ------------------
  2146. procedure TGLUnpackPBOHandle.Bind;
  2147. begin
  2148. vCurrentGLContext.GLStates.PixelUnpackBufferBinding := Handle;
  2149. end;
  2150. procedure TGLUnpackPBOHandle.UnBind;
  2151. begin
  2152. vCurrentGLContext.GLStates.PixelUnpackBufferBinding := 0;
  2153. end;
  2154. function TGLUnpackPBOHandle.GetTarget: Cardinal;
  2155. begin
  2156. Result := GL_PIXEL_UNPACK_BUFFER;
  2157. end;
  2158. class function TGLUnpackPBOHandle.IsSupported: Boolean;
  2159. begin
  2160. Result := gl.ARB_pixel_buffer_object;
  2161. end;
  2162. // ------------------
  2163. // ------------------ TGLTransformFeedbackBufferHandle ------------------
  2164. // ------------------
  2165. procedure TGLTransformFeedbackBufferHandle.Bind;
  2166. begin
  2167. vCurrentGLContext.GLStates.TransformFeedbackBufferBinding := Handle;
  2168. end;
  2169. procedure TGLTransformFeedbackBufferHandle.UnBind;
  2170. begin
  2171. vCurrentGLContext.GLStates.TransformFeedbackBufferBinding := 0;
  2172. end;
  2173. function TGLTransformFeedbackBufferHandle.GetTarget: TGLuint;
  2174. begin
  2175. Result := GL_TRANSFORM_FEEDBACK_BUFFER;
  2176. end;
  2177. procedure TGLTransformFeedbackBufferHandle.BeginTransformFeedback
  2178. (primitiveMode: TGLuint);
  2179. begin
  2180. gl.BeginTransformFeedback(primitiveMode);
  2181. end;
  2182. procedure TGLTransformFeedbackBufferHandle.EndTransformFeedback();
  2183. begin
  2184. gl.EndTransformFeedback();
  2185. end;
  2186. procedure TGLTransformFeedbackBufferHandle.BindRange(index: Cardinal; offset: TGLintptr; size: TGLsizeiptr);
  2187. begin
  2188. vCurrentGLContext.GLStates.SetBufferIndexedBinding(Handle, bbtTransformFeedBack, index, offset, size);
  2189. end;
  2190. procedure TGLTransformFeedbackBufferHandle.BindBase(index: Cardinal);
  2191. begin
  2192. vCurrentGLContext.GLStates.SetBufferIndexedBinding(Handle, bbtTransformFeedBack, index, BufferSize);
  2193. end;
  2194. procedure TGLTransformFeedbackBufferHandle.UnBindBase(index: Cardinal);
  2195. begin
  2196. vCurrentGLContext.GLStates.SetBufferIndexedBinding(0, bbtTransformFeedBack, index, 0);
  2197. end;
  2198. class function TGLTransformFeedbackBufferHandle.IsSupported: Boolean;
  2199. begin
  2200. Result := GL.EXT_transform_feedback;
  2201. end;
  2202. // ------------------
  2203. // ------------------ TGLTextureBufferHandle ------------------
  2204. // ------------------
  2205. procedure TGLTextureBufferHandle.Bind;
  2206. begin
  2207. vCurrentGLContext.GLStates.TextureBufferBinding := Handle;
  2208. end;
  2209. procedure TGLTextureBufferHandle.UnBind;
  2210. begin
  2211. vCurrentGLContext.GLStates.TextureBufferBinding := 0;
  2212. end;
  2213. function TGLTextureBufferHandle.GetTarget: Cardinal;
  2214. begin
  2215. Result := GL_TEXTURE_BUFFER;
  2216. end;
  2217. class function TGLTextureBufferHandle.IsSupported: Boolean;
  2218. begin
  2219. Result := gl.EXT_texture_buffer_object or gl.ARB_texture_buffer_object or gl.VERSION_3_1;
  2220. end;
  2221. // ------------------
  2222. // ------------------ TGLUniformBufferHandle ------------------
  2223. // ------------------
  2224. procedure TGLUniformBufferHandle.Bind;
  2225. begin
  2226. vCurrentGLContext.GLStates.UniformBufferBinding := Handle;
  2227. end;
  2228. procedure TGLUniformBufferHandle.UnBind;
  2229. begin
  2230. vCurrentGLContext.GLStates.UniformBufferBinding := 0;
  2231. end;
  2232. procedure TGLUniformBufferHandle.BindRange(index: Cardinal; offset: TGLintptr; size: TGLsizeiptr);
  2233. begin
  2234. vCurrentGLContext.GLStates.SetBufferIndexedBinding(Handle, bbtUniform, index, offset, size);
  2235. end;
  2236. procedure TGLUniformBufferHandle.BindBase(index: Cardinal);
  2237. begin
  2238. vCurrentGLContext.GLStates.SetBufferIndexedBinding(Handle, bbtUniform, index, BufferSize);
  2239. end;
  2240. procedure TGLUniformBufferHandle.UnBindBase(index: Cardinal);
  2241. begin
  2242. vCurrentGLContext.GLStates.SetBufferIndexedBinding(0, bbtUniform, index, 0);
  2243. end;
  2244. function TGLUniformBufferHandle.GetTarget: Cardinal;
  2245. begin
  2246. Result := GL_UNIFORM_BUFFER;
  2247. end;
  2248. class function TGLUniformBufferHandle.IsSupported: Boolean;
  2249. begin
  2250. Result := gl.ARB_uniform_buffer_object;
  2251. end;
  2252. // ------------------
  2253. // ------------------ TGLVertexArrayHandle ------------------
  2254. // ------------------
  2255. function TGLVertexArrayHandle.DoAllocateHandle: Cardinal;
  2256. begin
  2257. Result := 0;
  2258. gl.GenVertexArrays(1, @Result);
  2259. end;
  2260. procedure TGLVertexArrayHandle.DoDestroyHandle(var AHandle: Cardinal);
  2261. begin
  2262. if not vContextActivationFailureOccurred then
  2263. begin
  2264. gl.GetError;
  2265. gl.DeleteVertexArrays(1, @AHandle);
  2266. gl.CheckError;
  2267. end;
  2268. end;
  2269. class function TGLVertexArrayHandle.IsValid(const ID: Cardinal): Boolean;
  2270. begin
  2271. Result := gl.IsVertexArray(ID);
  2272. end;
  2273. procedure TGLVertexArrayHandle.Bind;
  2274. begin
  2275. Assert(vCurrentGLContext <> nil);
  2276. vCurrentGLContext.GLStates.VertexArrayBinding := Handle;
  2277. end;
  2278. procedure TGLVertexArrayHandle.UnBind;
  2279. begin
  2280. Assert(vCurrentGLContext <> nil);
  2281. vCurrentGLContext.GLStates.VertexArrayBinding := 0;
  2282. end;
  2283. class function TGLVertexArrayHandle.IsSupported: Boolean;
  2284. begin
  2285. Result := gl.ARB_vertex_array_object;
  2286. end;
  2287. class function TGLVertexArrayHandle.Transferable: Boolean;
  2288. begin
  2289. Result := False;
  2290. end;
  2291. // ------------------
  2292. // ------------------ TGLFramebufferHandle ------------------
  2293. // ------------------
  2294. function TGLFramebufferHandle.DoAllocateHandle: Cardinal;
  2295. begin
  2296. Result := 0;
  2297. gl.GenFramebuffers(1, @Result)
  2298. end;
  2299. procedure TGLFramebufferHandle.DoDestroyHandle(var AHandle: Cardinal);
  2300. begin
  2301. if not vContextActivationFailureOccurred then
  2302. begin
  2303. gl.GetError;
  2304. gl.DeleteFramebuffers(1, @AHandle);
  2305. gl.CheckError;
  2306. end;
  2307. end;
  2308. class function TGLFramebufferHandle.IsValid(const ID: Cardinal): Boolean;
  2309. begin
  2310. Result := gl.IsFramebuffer(ID);
  2311. end;
  2312. procedure TGLFramebufferHandle.Bind;
  2313. begin
  2314. Assert(vCurrentGLContext <> nil);
  2315. vCurrentGLContext.GLStates.SetFrameBuffer(Handle);
  2316. end;
  2317. procedure TGLFramebufferHandle.BindForDrawing;
  2318. begin
  2319. Assert(vCurrentGLContext <> nil);
  2320. vCurrentGLContext.GLStates.DrawFrameBuffer := Handle;
  2321. end;
  2322. procedure TGLFramebufferHandle.BindForReading;
  2323. begin
  2324. Assert(vCurrentGLContext <> nil);
  2325. vCurrentGLContext.GLStates.ReadFrameBuffer := Handle;
  2326. end;
  2327. procedure TGLFramebufferHandle.UnBind;
  2328. begin
  2329. Assert(vCurrentGLContext <> nil);
  2330. vCurrentGLContext.GLStates.SetFrameBuffer(0);
  2331. end;
  2332. procedure TGLFramebufferHandle.UnBindForDrawing;
  2333. begin
  2334. Assert(vCurrentGLContext <> nil);
  2335. vCurrentGLContext.GLStates.DrawFrameBuffer := 0;
  2336. end;
  2337. procedure TGLFramebufferHandle.UnBindForReading;
  2338. begin
  2339. Assert(vCurrentGLContext <> nil);
  2340. vCurrentGLContext.GLStates.ReadFrameBuffer := 0;
  2341. end;
  2342. procedure TGLFramebufferHandle.Attach1DTexture(Target: Cardinal; attachment: Cardinal; textarget: Cardinal; texture: Cardinal;
  2343. level: TGLInt);
  2344. begin
  2345. gl.FramebufferTexture1D(Target, attachment, textarget, texture, level);
  2346. end;
  2347. procedure TGLFramebufferHandle.Attach2DTexture(Target: Cardinal; attachment: Cardinal; textarget: Cardinal; texture: Cardinal;
  2348. level: TGLInt);
  2349. begin
  2350. gl.FramebufferTexture2D(Target, attachment, textarget, texture, level);
  2351. end;
  2352. procedure TGLFramebufferHandle.Attach3DTexture(Target: Cardinal; attachment: Cardinal; textarget: Cardinal; texture: Cardinal;
  2353. level: TGLInt; Layer: TGLInt);
  2354. begin
  2355. gl.FramebufferTexture3D(Target, attachment, textarget, texture, level, Layer);
  2356. end;
  2357. procedure TGLFramebufferHandle.AttachLayer(Target: Cardinal; attachment: Cardinal; texture: Cardinal; level: TGLInt;
  2358. Layer: TGLInt);
  2359. begin
  2360. gl.FramebufferTextureLayer(Target, attachment, texture, level, Layer);
  2361. end;
  2362. procedure TGLFramebufferHandle.AttachRenderBuffer(Target: Cardinal; attachment: Cardinal; renderbuffertarget: Cardinal;
  2363. renderbuffer: Cardinal);
  2364. begin
  2365. gl.FramebufferRenderbuffer(Target, attachment, renderbuffertarget, renderbuffer);
  2366. end;
  2367. procedure TGLFramebufferHandle.AttachTexture(Target: Cardinal; attachment: Cardinal; texture: Cardinal; level: TGLInt);
  2368. begin
  2369. gl.FramebufferTexture(Target, attachment, texture, level);
  2370. end;
  2371. procedure TGLFramebufferHandle.AttachTextureLayer(Target: Cardinal; attachment: Cardinal; texture: Cardinal; level: TGLInt;
  2372. Layer: TGLInt);
  2373. begin
  2374. gl.FramebufferTextureLayer(Target, attachment, texture, level, Layer);
  2375. end;
  2376. procedure TGLFramebufferHandle.Blit(srcX0: TGLInt; srcY0: TGLInt; srcX1: TGLInt; srcY1: TGLInt; dstX0: TGLInt; dstY0: TGLInt;
  2377. dstX1: TGLInt; dstY1: TGLInt; mask: TGLbitfield; filter: Cardinal);
  2378. begin
  2379. gl.BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
  2380. end;
  2381. function TGLFramebufferHandle.GetAttachmentParameter(Target: Cardinal; attachment: Cardinal; pname: Cardinal): TGLInt;
  2382. begin
  2383. gl.GetFramebufferAttachmentParameteriv(Target, attachment, pname, @Result)
  2384. end;
  2385. function TGLFramebufferHandle.GetAttachmentObjectType(Target: Cardinal; attachment: Cardinal): TGLInt;
  2386. begin
  2387. gl.GetFramebufferAttachmentParameteriv(Target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, @Result);
  2388. end;
  2389. function TGLFramebufferHandle.GetAttachmentObjectName(Target: Cardinal; attachment: Cardinal): TGLInt;
  2390. begin
  2391. gl.GetFramebufferAttachmentParameteriv(Target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, @Result);
  2392. end;
  2393. function TGLFramebufferHandle.GetStatus: TGLFramebufferStatus;
  2394. var
  2395. Status: TGLuint;
  2396. begin
  2397. Status := gl.CheckFramebufferStatus(GL_FRAMEBUFFER);
  2398. case Status of
  2399. GL_FRAMEBUFFER_COMPLETE_EXT:
  2400. Result := fsComplete;
  2401. GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
  2402. Result := fsIncompleteAttachment;
  2403. GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
  2404. Result := fsIncompleteMissingAttachment;
  2405. GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
  2406. Result := fsIncompleteDuplicateAttachment;
  2407. GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
  2408. Result := fsIncompleteDimensions;
  2409. GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
  2410. Result := fsIncompleteFormats;
  2411. GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
  2412. Result := fsIncompleteDrawBuffer;
  2413. GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
  2414. Result := fsIncompleteReadBuffer;
  2415. GL_FRAMEBUFFER_UNSUPPORTED_EXT:
  2416. Result := fsUnsupported;
  2417. GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
  2418. Result := fsIncompleteMultisample;
  2419. else
  2420. Result := fsStatusError;
  2421. end;
  2422. end;
  2423. function TGLFramebufferHandle.GetStringStatus(out clarification: string): TGLFramebufferStatus;
  2424. const
  2425. cFBOStatus: array [TGLFramebufferStatus] of string = ('Complete', 'Incomplete attachment', 'Incomplete missing attachment',
  2426. 'Incomplete duplicate attachment', 'Incomplete dimensions', 'Incomplete formats', 'Incomplete draw buffer',
  2427. 'Incomplete read buffer', 'Unsupported', 'Incomplite multisample', 'Status Error');
  2428. begin
  2429. Result := GetStatus;
  2430. clarification := cFBOStatus[Result];
  2431. end;
  2432. class function TGLFramebufferHandle.IsSupported: Boolean;
  2433. begin
  2434. Result := gl.EXT_framebuffer_object or gl.ARB_framebuffer_object;
  2435. end;
  2436. class function TGLFramebufferHandle.Transferable: Boolean;
  2437. begin
  2438. Result := False;
  2439. end;
  2440. // ------------------
  2441. // ------------------ TGLRenderbufferObject ------------------
  2442. // ------------------
  2443. function TGLRenderbufferHandle.DoAllocateHandle: Cardinal;
  2444. begin
  2445. Result := 0;
  2446. gl.GenRenderbuffers(1, @Result);
  2447. end;
  2448. procedure TGLRenderbufferHandle.DoDestroyHandle(var AHandle: Cardinal);
  2449. begin
  2450. if not vContextActivationFailureOccurred then
  2451. begin
  2452. gl.GetError;
  2453. gl.DeleteRenderbuffers(1, @AHandle);
  2454. gl.CheckError;
  2455. end;
  2456. end;
  2457. class function TGLRenderbufferHandle.IsValid(const ID: Cardinal): Boolean;
  2458. begin
  2459. Result := gl.IsRenderbuffer(ID);
  2460. end;
  2461. procedure TGLRenderbufferHandle.Bind;
  2462. begin
  2463. vCurrentGLContext.GLStates.renderbuffer := GetHandle;
  2464. end;
  2465. procedure TGLRenderbufferHandle.UnBind;
  2466. begin
  2467. if vCurrentGLContext <> nil then
  2468. vCurrentGLContext.GLStates.renderbuffer := 0;
  2469. end;
  2470. procedure TGLRenderbufferHandle.SetStorage(internalformat: Cardinal; width, height: TGLsizei);
  2471. begin
  2472. gl.RenderbufferStorage(GL_RENDERBUFFER, internalformat, width, height);
  2473. end;
  2474. procedure TGLRenderbufferHandle.SetStorageMultisample(internalformat: Cardinal; samples: TGLsizei; width, height: TGLsizei);
  2475. begin
  2476. gl.RenderbufferStorageMultisample(GL_RENDERBUFFER, samples, internalformat, width, height);
  2477. end;
  2478. class function TGLRenderbufferHandle.IsSupported: Boolean;
  2479. begin
  2480. Result := gl.EXT_framebuffer_object or gl.ARB_framebuffer_object;
  2481. end;
  2482. // ------------------
  2483. // ------------------ TGLARBProgramHandle ------------------
  2484. // ------------------
  2485. function TGLARBProgramHandle.DoAllocateHandle: Cardinal;
  2486. begin
  2487. Result := 0;
  2488. gl.GenPrograms(1, @Result);
  2489. FReady := False;
  2490. end;
  2491. procedure TGLARBProgramHandle.DoDestroyHandle(var AHandle: Cardinal);
  2492. begin
  2493. if not vContextActivationFailureOccurred then
  2494. begin
  2495. gl.GetError;
  2496. gl.DeletePrograms(1, @AHandle);
  2497. gl.CheckError;
  2498. end;
  2499. end;
  2500. class function TGLARBProgramHandle.IsValid(const ID: Cardinal): Boolean;
  2501. begin
  2502. Result := gl.IsProgram(ID);
  2503. end;
  2504. procedure TGLARBProgramHandle.LoadARBProgram(const AText: string);
  2505. const
  2506. cProgType: array [0 .. 2] of string = ('ARB vertex', 'ARB fragment', 'NV geometry');
  2507. var
  2508. errPos, p: Integer;
  2509. begin
  2510. Bind;
  2511. gl.ProgramString(GetTarget, GL_PROGRAM_FORMAT_ASCII_ARB, Length(AText), PAnsiChar(AnsiString(AText)));
  2512. gl.GetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, @errPos);
  2513. if errPos > -1 then
  2514. begin
  2515. FInfoLog := string(gl.GetString(GL_PROGRAM_ERROR_STRING_ARB));
  2516. case GetTarget of
  2517. GL_VERTEX_PROGRAM_ARB:
  2518. p := 0;
  2519. GL_FRAGMENT_PROGRAM_ARB:
  2520. p := 1;
  2521. else
  2522. p := 2;
  2523. end;
  2524. GLSLogger.LogError(Format('%s Program Error - [Pos: %d][Error %s]', [cProgType[p], errPos, FInfoLog]));
  2525. FReady := False;
  2526. end
  2527. else
  2528. begin
  2529. FReady := True;
  2530. FInfoLog := '';
  2531. end;
  2532. end;
  2533. procedure TGLARBProgramHandle.Enable;
  2534. begin
  2535. if FReady then
  2536. gl.Enable(GetTarget)
  2537. else
  2538. Abort;
  2539. end;
  2540. procedure TGLARBProgramHandle.Disable;
  2541. begin
  2542. gl.Disable(GetTarget);
  2543. end;
  2544. procedure TGLARBProgramHandle.Bind;
  2545. begin
  2546. gl.BindProgram(GetTarget, Handle);
  2547. end;
  2548. class function TGLARBVertexProgramHandle.GetTarget: Cardinal;
  2549. begin
  2550. Result := GL_VERTEX_PROGRAM_ARB;
  2551. end;
  2552. class function TGLARBVertexProgramHandle.IsSupported: Boolean;
  2553. begin
  2554. Result := gl.ARB_vertex_program;
  2555. end;
  2556. class function TGLARBFragmentProgramHandle.GetTarget: Cardinal;
  2557. begin
  2558. Result := GL_FRAGMENT_PROGRAM_ARB;
  2559. end;
  2560. class function TGLARBFragmentProgramHandle.IsSupported: Boolean;
  2561. begin
  2562. Result := gl.ARB_vertex_program;
  2563. end;
  2564. class function TGLARBGeometryProgramHandle.GetTarget: Cardinal;
  2565. begin
  2566. Result := GL_GEOMETRY_PROGRAM_NV;
  2567. end;
  2568. class function TGLARBGeometryProgramHandle.IsSupported: Boolean;
  2569. begin
  2570. Result := gl.NV_geometry_program4;
  2571. end;
  2572. // ------------------
  2573. // ------------------ TGLSLHandle ------------------
  2574. // ------------------
  2575. procedure TGLSLHandle.DoDestroyHandle(var AHandle: Cardinal);
  2576. begin
  2577. if not vContextActivationFailureOccurred then
  2578. begin
  2579. gl.ClearError;
  2580. gl.DeleteObject(AHandle);
  2581. gl.CheckError;
  2582. end;
  2583. end;
  2584. function TGLSLHandle.InfoLog: string;
  2585. var
  2586. maxLength: Integer;
  2587. log: AnsiString;
  2588. begin
  2589. maxLength := 0;
  2590. gl.GetObjectParameteriv(GetHandle, GL_OBJECT_INFO_LOG_LENGTH_ARB, @maxLength);
  2591. SetLength(log, maxLength);
  2592. if maxLength > 0 then
  2593. begin
  2594. gl.GetInfoLog(GetHandle, maxLength, @maxLength, @log[1]);
  2595. SetLength(log, maxLength);
  2596. end;
  2597. Result := string(log);
  2598. end;
  2599. class function TGLSLHandle.IsSupported: Boolean;
  2600. begin
  2601. Result := gl.ARB_shader_objects;
  2602. end;
  2603. // ------------------
  2604. // ------------------ TGLShaderHandle ------------------
  2605. // ------------------
  2606. function TGLShaderHandle.DoAllocateHandle: Cardinal;
  2607. begin
  2608. Result := gl.CreateShader(FShaderType)
  2609. end;
  2610. class function TGLShaderHandle.IsValid(const ID: Cardinal): Boolean;
  2611. begin
  2612. Result := gl.IsShader(ID);
  2613. end;
  2614. procedure TGLShaderHandle.ShaderSource(const source: AnsiString);
  2615. var
  2616. p: PAnsiChar;
  2617. begin
  2618. p := PAnsiChar(AnsiString(source));
  2619. gl.ShaderSource(GetHandle, 1, @p, nil);
  2620. end;
  2621. function TGLShaderHandle.CompileShader: Boolean;
  2622. var
  2623. compiled: Integer;
  2624. glH: Cardinal;
  2625. begin
  2626. glH := GetHandle;
  2627. gl.CompileShader(glH);
  2628. compiled := 0;
  2629. gl.GetShaderiv(glH, GL_COMPILE_STATUS, @compiled);
  2630. Result := (compiled <> 0);
  2631. end;
  2632. // ------------------
  2633. // ------------------ TGLVertexShaderHandle ------------------
  2634. // ------------------
  2635. constructor TGLVertexShaderHandle.Create;
  2636. begin
  2637. FShaderType := GL_VERTEX_SHADER_ARB;
  2638. inherited;
  2639. end;
  2640. class function TGLVertexShaderHandle.IsSupported: Boolean;
  2641. begin
  2642. Result := gl.ARB_vertex_shader;
  2643. end;
  2644. // ------------------
  2645. // ------------------ TGLGeometryShaderHandle ------------------
  2646. // ------------------
  2647. constructor TGLGeometryShaderHandle.Create;
  2648. begin
  2649. FShaderType := GL_GEOMETRY_SHADER_EXT;
  2650. inherited;
  2651. end;
  2652. class function TGLGeometryShaderHandle.IsSupported: Boolean;
  2653. begin
  2654. Result := gl.EXT_geometry_shader4;
  2655. end;
  2656. // ------------------
  2657. // ------------------ TGLFragmentShaderHandle ------------------
  2658. // ------------------
  2659. constructor TGLFragmentShaderHandle.Create;
  2660. begin
  2661. FShaderType := GL_FRAGMENT_SHADER_ARB;
  2662. inherited;
  2663. end;
  2664. class function TGLFragmentShaderHandle.IsSupported: Boolean;
  2665. begin
  2666. Result := gl.ARB_fragment_shader;
  2667. end;
  2668. // ------------------
  2669. // ------------------ TGLTessControlShaderHandle ------------------
  2670. // ------------------
  2671. constructor TGLTessControlShaderHandle.Create;
  2672. begin
  2673. FShaderType := GL_TESS_CONTROL_SHADER;
  2674. inherited;
  2675. end;
  2676. class function TGLTessControlShaderHandle.IsSupported: Boolean;
  2677. begin
  2678. Result := gl.ARB_tessellation_shader;
  2679. end;
  2680. // ------------------
  2681. // ------------------ TGLTessEvaluationShaderHandle ------------------
  2682. // ------------------
  2683. constructor TGLTessEvaluationShaderHandle.Create;
  2684. begin
  2685. FShaderType := GL_TESS_EVALUATION_SHADER;
  2686. inherited;
  2687. end;
  2688. class function TGLTessEvaluationShaderHandle.IsSupported: Boolean;
  2689. begin
  2690. Result := gl.ARB_tessellation_shader;
  2691. end;
  2692. // ------------------
  2693. // ------------------ TGLProgramHandle ------------------
  2694. // ------------------
  2695. function TGLProgramHandle.DoAllocateHandle: Cardinal;
  2696. begin
  2697. Result := gl.CreateProgram();
  2698. end;
  2699. class function TGLProgramHandle.IsValid(const ID: Cardinal): Boolean;
  2700. begin
  2701. Result := gl.IsProgram(ID);
  2702. end;
  2703. procedure TGLProgramHandle.AddShader(ShaderType: TGLShaderHandleClass; const ShaderSource: string;
  2704. treatWarningsAsErrors: Boolean = False);
  2705. var
  2706. shader: TGLShaderHandle;
  2707. begin
  2708. shader := ShaderType.CreateAndAllocate;
  2709. try
  2710. if shader.Handle = 0 then
  2711. raise EGLShader.Create('Couldn''t allocate ' + ShaderType.ClassName);
  2712. shader.ShaderSource(AnsiString(ShaderSource));
  2713. if (not shader.CompileShader) or (treatWarningsAsErrors and (Pos('warning', LowerCase(shader.InfoLog)) > 0)) then
  2714. raise EGLShader.Create(FName + ' (' + shader.ClassName + '): '#13#10 + shader.InfoLog);
  2715. AttachObject(shader);
  2716. finally
  2717. shader.Free;
  2718. end;
  2719. gl.CheckError;
  2720. end;
  2721. procedure TGLProgramHandle.AttachObject(shader: TGLShaderHandle);
  2722. begin
  2723. gl.AttachShader(GetHandle, shader.Handle);
  2724. end;
  2725. procedure TGLProgramHandle.DetachAllObject;
  2726. var
  2727. glH: Cardinal;
  2728. I: Integer;
  2729. Count: TGLsizei;
  2730. buffer: array [0 .. 255] of Cardinal;
  2731. begin
  2732. glH := GetHandle;
  2733. if glH > 0 then
  2734. begin
  2735. gl.GetAttachedShaders(glH, Length(buffer), @Count, @buffer[0]);
  2736. Count := MinInteger(Count, Length(buffer));
  2737. for I := 0 to Count - 1 do
  2738. gl.DetachShader(glH, buffer[I]);
  2739. NotifyChangesOfData;
  2740. end;
  2741. end;
  2742. procedure TGLProgramHandle.BindAttribLocation(index: Integer; const aName: string);
  2743. begin
  2744. gl.BindAttribLocation(GetHandle, index, PAnsiChar(AnsiString(aName)));
  2745. end;
  2746. procedure TGLProgramHandle.BindFragDataLocation(index: Integer; const aName: string);
  2747. begin
  2748. gl.BindFragDataLocation(GetHandle, index, PAnsiChar(AnsiString(name)));
  2749. end;
  2750. function TGLProgramHandle.LinkProgram: Boolean;
  2751. var
  2752. Status: Integer;
  2753. glH: Cardinal;
  2754. begin
  2755. glH := GetHandle;
  2756. gl.LinkProgram(glH);
  2757. Status := 0;
  2758. gl.GetProgramiv(glH, GL_LINK_STATUS, @Status);
  2759. Result := (Status <> 0);
  2760. end;
  2761. function TGLProgramHandle.ValidateProgram: Boolean;
  2762. var
  2763. validated: Integer;
  2764. h: Cardinal;
  2765. begin
  2766. h := GetHandle;
  2767. gl.ValidateProgram(h);
  2768. validated := 0;
  2769. gl.GetProgramiv(h, GL_VALIDATE_STATUS, @validated);
  2770. Result := (validated <> 0);
  2771. end;
  2772. function TGLProgramHandle.GetAttribLocation(const aName: string): Integer;
  2773. begin
  2774. Result := gl.GetAttribLocation(GetHandle, PAnsiChar(AnsiString(aName)));
  2775. Assert(Result >= 0, Format(strUnknownParam, ['attrib', aName, Name]));
  2776. end;
  2777. function TGLProgramHandle.GetUniformLocation(const aName: string): Integer;
  2778. begin
  2779. Result := gl.GetUniformLocation(GetHandle, PAnsiChar(AnsiString(aName)));
  2780. Assert(Result >= 0, Format(strUnknownParam, ['uniform', aName, Name]));
  2781. end;
  2782. function TGLProgramHandle.GetVaryingLocation(const aName: string): Integer;
  2783. begin
  2784. Result := gl.GetVaryingLocation(GetHandle, PAnsiChar(AnsiString(aName)));
  2785. Assert(Result >= 0, Format(strUnknownParam, ['varying', aName, Name]));
  2786. end;
  2787. procedure TGLProgramHandle.AddActiveVarying(const aName: string);
  2788. begin
  2789. gl.ActiveVarying(GetHandle, PAnsiChar(AnsiString(aName)));
  2790. end;
  2791. procedure TGLProgramHandle.UseProgramObject;
  2792. begin
  2793. Assert(vCurrentGLContext <> nil);
  2794. vCurrentGLContext.GLStates.CurrentProgram := Handle;
  2795. end;
  2796. procedure TGLProgramHandle.EndUseProgramObject;
  2797. begin
  2798. Assert(vCurrentGLContext <> nil);
  2799. vCurrentGLContext.GLStates.CurrentProgram := 0;
  2800. end;
  2801. function TGLProgramHandle.GetUniform1i(const index: string): Integer;
  2802. begin
  2803. gl.GetUniformiv(GetHandle, GetUniformLocation(index), @Result);
  2804. end;
  2805. function TGLProgramHandle.GetUniform2i(const index: string): TVector2i;
  2806. begin
  2807. gl.GetUniformiv(GetHandle, GetUniformLocation(index), @Result);
  2808. end;
  2809. function TGLProgramHandle.GetUniform3i(const index: string): TVector3i;
  2810. begin
  2811. gl.GetUniformiv(GetHandle, GetUniformLocation(index), @Result);
  2812. end;
  2813. function TGLProgramHandle.GetUniform4i(const index: string): TVector4i;
  2814. begin
  2815. gl.GetUniformiv(GetHandle, GetUniformLocation(index), @Result);
  2816. end;
  2817. procedure TGLProgramHandle.SetUniform1f(const index: string; val: Single);
  2818. begin
  2819. gl.Uniform1f(GetUniformLocation(index), val);
  2820. end;
  2821. function TGLProgramHandle.GetUniform1f(const index: string): Single;
  2822. begin
  2823. gl.GetUniformfv(GetHandle, GetUniformLocation(index), @Result);
  2824. end;
  2825. procedure TGLProgramHandle.SetUniform1i(const index: string; val: Integer);
  2826. begin
  2827. gl.Uniform1i(GetUniformLocation(index), val);
  2828. end;
  2829. procedure TGLProgramHandle.SetUniform2i(const index: string; const Value: TVector2i);
  2830. begin
  2831. gl.Uniform2i(GetUniformLocation(index), Value.X, Value.Y);
  2832. end;
  2833. procedure TGLProgramHandle.SetUniform3i(const index: string; const Value: TVector3i);
  2834. begin
  2835. gl.Uniform3i(GetUniformLocation(index), Value.X, Value.Y, Value.Z);
  2836. end;
  2837. procedure TGLProgramHandle.SetUniform4i(const index: string; const Value: TVector4i);
  2838. begin
  2839. gl.Uniform4i(GetUniformLocation(index), Value.X, Value.Y, Value.Z, Value.W);
  2840. end;
  2841. function TGLProgramHandle.GetUniform2f(const index: string): TVector2f;
  2842. begin
  2843. gl.GetUniformfv(GetHandle, GetUniformLocation(index), @Result);
  2844. end;
  2845. procedure TGLProgramHandle.SetUniform2f(const index: string; const val: TVector2f);
  2846. begin
  2847. gl.Uniform2f(GetUniformLocation(index), val.X, val.Y);
  2848. end;
  2849. function TGLProgramHandle.GetUniform3f(const index: string): TAffineVector;
  2850. begin
  2851. gl.GetUniformfv(GetHandle, GetUniformLocation(index), @Result);
  2852. end;
  2853. procedure TGLProgramHandle.SetUniform3f(const index: string; const val: TAffineVector);
  2854. begin
  2855. gl.Uniform3f(GetUniformLocation(index), val.X, val.Y, val.Z);
  2856. end;
  2857. function TGLProgramHandle.GetUniform4f(const index: string): TGLVector;
  2858. begin
  2859. gl.GetUniformfv(GetHandle, GetUniformLocation(index), @Result);
  2860. end;
  2861. procedure TGLProgramHandle.SetUniform4f(const index: string; const val: TGLVector);
  2862. begin
  2863. gl.Uniform4f(GetUniformLocation(index), val.X, val.Y, val.Z, val.W);
  2864. end;
  2865. function TGLProgramHandle.GetUniformMatrix2fv(const index: string): TMatrix2f;
  2866. begin
  2867. gl.GetUniformfv(GetHandle, GetUniformLocation(index), @Result);
  2868. end;
  2869. procedure TGLProgramHandle.SetUniformMatrix2fv(const index: string; const val: TMatrix2f);
  2870. begin
  2871. gl.UniformMatrix2fv(GetUniformLocation(index), 1, False, @val);
  2872. end;
  2873. function TGLProgramHandle.GetUniformMatrix3fv(const index: string): TMatrix3f;
  2874. begin
  2875. gl.GetUniformfv(GetHandle, GetUniformLocation(index), @Result);
  2876. end;
  2877. procedure TGLProgramHandle.SetUniformMatrix3fv(const index: string; const val: TMatrix3f);
  2878. begin
  2879. gl.UniformMatrix3fv(GetUniformLocation(index), 1, False, @val);
  2880. end;
  2881. function TGLProgramHandle.GetUniformMatrix4fv(const index: string): TGLMatrix;
  2882. begin
  2883. gl.GetUniformfv(GetHandle, GetUniformLocation(index), @Result);
  2884. end;
  2885. procedure TGLProgramHandle.SetUniformMatrix4fv(const index: string; const val: TGLMatrix);
  2886. begin
  2887. gl.UniformMatrix4fv(GetUniformLocation(index), 1, False, @val);
  2888. end;
  2889. procedure TGLProgramHandle.SetUniformf(const index: string; const val: Single);
  2890. begin
  2891. SetUniform1f(index, val);
  2892. end;
  2893. procedure TGLProgramHandle.SetUniformf(const index: string; const val: TVector2f);
  2894. begin
  2895. SetUniform2f(index, val);
  2896. end;
  2897. procedure TGLProgramHandle.SetUniformf(const index: string; const val: TVector3f);
  2898. begin
  2899. SetUniform3f(index, val);
  2900. end;
  2901. procedure TGLProgramHandle.SetUniformf(const index: string; const val: TVector4f);
  2902. begin
  2903. SetUniform4f(index, val);
  2904. end;
  2905. procedure TGLProgramHandle.SetUniformi(const index: string; const val: Integer);
  2906. begin
  2907. SetUniform1f(index, val);
  2908. end;
  2909. procedure TGLProgramHandle.SetUniformi(const index: string; const val: TVector2i);
  2910. begin
  2911. SetUniform2i(index, val);
  2912. end;
  2913. procedure TGLProgramHandle.SetUniformi(const index: string; const val: TVector3i);
  2914. begin
  2915. SetUniform3i(index, val);
  2916. end;
  2917. procedure TGLProgramHandle.SetUniformi(const index: string; const val: TVector4i);
  2918. begin
  2919. SetUniform4i(index, val);
  2920. end;
  2921. function TGLProgramHandle.GetUniformTextureHandle(const index: string; const TextureIndex: Integer;
  2922. const TextureTarget: TGLTextureTarget): Cardinal;
  2923. begin
  2924. Result := GetUniform1i(index);
  2925. end;
  2926. procedure TGLProgramHandle.SetUniformTextureHandle(const index: string; const TextureIndex: Integer;
  2927. const TextureTarget: TGLTextureTarget; const Value: Cardinal);
  2928. begin
  2929. vCurrentGLContext.GLStates.TextureBinding[0, TextureTarget] := Value;
  2930. SetUniform1i(index, TextureIndex);
  2931. end;
  2932. procedure TGLProgramHandle.SetUniformBuffer(const index: string; Value: TGLUniformBufferHandle);
  2933. begin
  2934. gl.UniformBuffer(Handle, GetUniformLocation(index), Value.Handle);
  2935. end;
  2936. function TGLProgramHandle.GetUniformBufferSize(const aName: string): Integer;
  2937. begin
  2938. Result := gl.GetUniformBufferSize(Handle, GetUniformLocation(aName));
  2939. end;
  2940. function TGLProgramHandle.GetUniformOffset(const aName: string): PGLInt;
  2941. begin
  2942. Result := gl.GetUniformOffset(Handle, GetUniformLocation(aName));
  2943. end;
  2944. function TGLProgramHandle.GetUniformBlockIndex(const aName: string): Integer;
  2945. begin
  2946. Result := gl.GetUniformBlockIndex(Handle, PAnsiChar(AnsiString(aName)));
  2947. Assert(Result >= 0, Format(strUnknownParam, ['uniform block', aName, Name]));
  2948. end;
  2949. constructor TGLProgramHandle.Create;
  2950. begin
  2951. inherited Create;
  2952. FName := 'DefaultShaderName';
  2953. end;
  2954. // ------------------
  2955. // ------------------ TGLContextManager ------------------
  2956. // ------------------
  2957. {$IFDEF USE_SERVICE_CONTEXT}
  2958. procedure OnApplicationInitialize;
  2959. begin
  2960. InitProc := OldInitProc;
  2961. Application.Initialize;
  2962. GLContextManager.CreateServiceContext;
  2963. end;
  2964. {$ENDIF}
  2965. constructor TGLContextManager.Create;
  2966. begin
  2967. inherited Create;
  2968. {$IFNDEF USE_MULTITHREAD}
  2969. FHandles := TList.Create;
  2970. {$ELSE}
  2971. FHandles := TThreadList.Create;
  2972. {$ENDIF USE_MULTITHREAD}
  2973. FList := TThreadList.Create;
  2974. end;
  2975. destructor TGLContextManager.Destroy;
  2976. begin
  2977. FHandles.Free;
  2978. FList.Free;
  2979. inherited Destroy;
  2980. end;
  2981. function TGLContextManager.CreateContext(AClass: TGLContextClass): TGLContext;
  2982. begin
  2983. if Assigned(AClass) then
  2984. begin
  2985. Result := AClass.Create;
  2986. Result.FManager := Self;
  2987. end
  2988. else if Assigned(vContextClasses) and (vContextClasses.Count > 0) then
  2989. begin
  2990. Result := TGLContextClass(vContextClasses.Last).Create;
  2991. Result.FManager := Self;
  2992. end
  2993. else
  2994. Result := nil;
  2995. end;
  2996. {$IFDEF USE_SERVICE_CONTEXT}
  2997. procedure TGLContextManager.CreateServiceContext;
  2998. begin
  2999. FServiceContext := CreateContext;
  3000. FThreadTask := TServiceContextTaskList.Create;
  3001. FServiceStarter := TFinishTaskEvent.Create;
  3002. FThread := TServiceContextThread.Create;
  3003. AddTaskForServiceContext(TServiceContextThread(FThread).DoCreateServiceContext);
  3004. end;
  3005. procedure TGLContextManager.QueueTaskDepleted;
  3006. var
  3007. TaskRec: TServiceContextTask;
  3008. I: Integer;
  3009. nowTime: Double;
  3010. begin
  3011. with FThreadTask.LockList do
  3012. try
  3013. for I := 0 to Count - 1 do
  3014. begin
  3015. TaskRec := Items[I];
  3016. if Assigned(TaskRec.Task) then
  3017. begin
  3018. FThreadTask.UnlockList;
  3019. // Task queue not empty
  3020. FServiceStarter.SetEvent;
  3021. exit;
  3022. end;
  3023. end;
  3024. finally
  3025. FThreadTask.UnlockList;
  3026. end;
  3027. FServiceStarter.ResetEvent;
  3028. FThreadTask.Clear;
  3029. nowTime := Now;
  3030. with TServiceContextThread(FThread) do
  3031. if (nowTime - FLastTaskStartTime > 30000) and not FReported then
  3032. begin
  3033. FReported := True;
  3034. GLSLogger.LogInfo('Service context queue task depleted');
  3035. end;
  3036. end;
  3037. {$ENDIF USE_SERVICE_CONTEXT}
  3038. procedure TGLContextManager.Lock;
  3039. begin
  3040. FList.LockList;
  3041. end;
  3042. procedure TGLContextManager.NotifyPreparationNeed;
  3043. var
  3044. I: Integer;
  3045. LList: TList;
  3046. begin
  3047. LList := FList.LockList;
  3048. try
  3049. for I := LList.Count - 1 downto 0 do
  3050. TGLContext(LList[I]).FIsPraparationNeed := True;
  3051. finally
  3052. FList.UnlockList;
  3053. end;
  3054. end;
  3055. procedure TGLContextManager.UnLock;
  3056. begin
  3057. FList.UnlockList;
  3058. end;
  3059. function TGLContextManager.ContextCount: Integer;
  3060. begin
  3061. // try..finally just a waste of CPU here, if Count fails, the list is amok,
  3062. // and so is the lock...
  3063. Result := FList.LockList.Count;
  3064. FList.UnlockList;
  3065. end;
  3066. procedure TGLContextManager.RegisterContext(aContext: TGLContext);
  3067. begin
  3068. with FList.LockList do
  3069. try
  3070. if IndexOf(aContext) >= 0 then
  3071. raise EGLContext.Create(strInvalidContextRegistration)
  3072. else
  3073. Add(aContext);
  3074. finally
  3075. FList.UnlockList;
  3076. end;
  3077. end;
  3078. procedure TGLContextManager.UnRegisterContext(aContext: TGLContext);
  3079. begin
  3080. with FList.LockList do
  3081. try
  3082. if IndexOf(aContext) < 0 then
  3083. raise EGLContext.Create(strInvalidContextRegistration)
  3084. else
  3085. Remove(aContext);
  3086. finally
  3087. FList.UnlockList;
  3088. end;
  3089. end;
  3090. procedure TGLContextManager.ContextCreatedBy(aContext: TGLContext);
  3091. begin
  3092. Lock;
  3093. try
  3094. Inc(FCreatedRCCount);
  3095. finally
  3096. UnLock;
  3097. end;
  3098. end;
  3099. procedure TGLContextManager.DestroyingContextBy(aContext: TGLContext);
  3100. var
  3101. cn: TGLContextNotification;
  3102. begin
  3103. Lock;
  3104. try
  3105. Dec(FCreatedRCCount);
  3106. if FCreatedRCCount = 0 then
  3107. begin
  3108. // yes, slow and bulky, but allows for the triggered event to
  3109. // cascade-remove notifications safely
  3110. while Length(FNotifications) > 0 do
  3111. begin
  3112. cn := FNotifications[High(FNotifications)];
  3113. SetLength(FNotifications, Length(FNotifications) - 1);
  3114. cn.Event(cn.obj);
  3115. end;
  3116. end;
  3117. finally
  3118. UnLock;
  3119. end;
  3120. end;
  3121. procedure TGLContextManager.LastContextDestroyNotification(anObject: TObject; anEvent: TNotifyEvent);
  3122. begin
  3123. Lock;
  3124. try
  3125. SetLength(FNotifications, Length(FNotifications) + 1);
  3126. with FNotifications[High(FNotifications)] do
  3127. begin
  3128. obj := anObject;
  3129. Event := anEvent;
  3130. end;
  3131. finally
  3132. UnLock;
  3133. end;
  3134. end;
  3135. procedure TGLContextManager.RemoveNotification(anObject: TObject);
  3136. var
  3137. I: Integer;
  3138. found: Boolean;
  3139. begin
  3140. Lock;
  3141. try
  3142. found := False;
  3143. I := Low(FNotifications);
  3144. while I <= High(FNotifications) do
  3145. begin
  3146. if FNotifications[I].obj = anObject then
  3147. begin
  3148. found := True;
  3149. while I <= High(FNotifications) do
  3150. begin
  3151. FNotifications[I] := FNotifications[I + 1];
  3152. Inc(I);
  3153. end;
  3154. SetLength(FNotifications, Length(FNotifications) - 1);
  3155. Break;
  3156. end;
  3157. Inc(I);
  3158. end;
  3159. if not found then
  3160. raise EGLContext.Create(strInvalidNotificationRemoval);
  3161. finally
  3162. UnLock;
  3163. end;
  3164. end;
  3165. procedure TGLContextManager.Terminate;
  3166. begin
  3167. FTerminated := True;
  3168. {$IFDEF USE_SERVICE_CONTEXT}
  3169. // Sevice context may not be created becouse Application.Initialize not happened
  3170. if Assigned(FServiceContext) then
  3171. begin
  3172. CheckSynchronize;
  3173. FThread.Terminate;
  3174. FServiceStarter.SetEvent;
  3175. FThread.WaitFor;
  3176. FThread.Destroy;
  3177. GLSLogger.LogDebug('Service thread destroyed');
  3178. FServiceStarter.Destroy;
  3179. FThreadTask.Destroy;
  3180. end;
  3181. {$ENDIF}
  3182. if ContextCount = 0 then
  3183. begin
  3184. GLContextManager := nil;
  3185. Free;
  3186. end;
  3187. end;
  3188. procedure TGLContextManager.DestroyAllHandles;
  3189. var
  3190. I: Integer;
  3191. begin
  3192. with FList.LockList do
  3193. try
  3194. for I := Count - 1 downto 0 do
  3195. TGLContext(Items[I]).DestroyAllHandles;
  3196. finally
  3197. FList.UnlockList;
  3198. end;
  3199. end;
  3200. {$IFDEF USE_SERVICE_CONTEXT}
  3201. constructor TServiceContextThread.Create;
  3202. begin
  3203. FWindow := TForm.CreateNew(nil);
  3204. FWindow.Hide;
  3205. FWindow.Position := poScreenCenter;
  3206. FWindow.width := 1;
  3207. FWindow.height := 1;
  3208. FWindow.BorderStyle := bsNone;
  3209. FWindow.FormStyle := fsStayOnTop;
  3210. FWindow.Color := 0;
  3211. vServiceWindow := FWindow;
  3212. {$IFDEF MSWINDOWS}
  3213. FDC := GetDC(FWindow.Handle);
  3214. {$ENDIF}
  3215. {$IFDEF LINUX}
  3216. FDC := FWindow.Handle;
  3217. {$ENDIF}
  3218. inherited Create(False);
  3219. end;
  3220. destructor TServiceContextThread.Destroy;
  3221. begin
  3222. ReleaseDC(FWindow.Handle, FDC);
  3223. FWindow.Free;
  3224. inherited;
  3225. end;
  3226. procedure TServiceContextThread.DoCreateServiceContext; stdcall;
  3227. procedure Fail;
  3228. begin
  3229. GLSLogger.LogError(Format('%s: can''t initialize rendering context', [ClassName]));
  3230. FWindow.Destroy;
  3231. vServiceWindow := nil;
  3232. end;
  3233. begin
  3234. try
  3235. GLContextManager.ServiceContext.Acceleration := chaHardware;
  3236. GLContextManager.ServiceContext.CreateMemoryContext(FDC, 1, 1, 1);
  3237. except
  3238. on EGLContext do
  3239. begin
  3240. Fail;
  3241. exit;
  3242. end;
  3243. on EPBuffer do
  3244. begin
  3245. GLSLogger.LogWarning(Format('%s: can''t initialize memory rendering context. Try initialize common context.',
  3246. [ClassName]));
  3247. try
  3248. GLContextManager.ServiceContext.CreateContext(FDC);
  3249. except
  3250. Fail;
  3251. exit;
  3252. end;
  3253. end;
  3254. end;
  3255. GLSLogger.LogNotice('Service context successfuly initialized');
  3256. GLContextManager.ServiceContext.Activate;
  3257. FWindow.Hide;
  3258. vServiceWindow := nil;
  3259. end;
  3260. procedure TServiceContextThread.Execute;
  3261. var
  3262. TaskRec: TServiceContextTask;
  3263. procedure NextTask;
  3264. const
  3265. NullTask: TServiceContextTask = (Task: nil; Event: nil);
  3266. var
  3267. I: Integer;
  3268. begin
  3269. TaskRec.Task := nil;
  3270. with GLContextManager.FThreadTask.LockList do
  3271. try
  3272. for I := 0 to Count - 1 do
  3273. begin
  3274. TaskRec := Items[I];
  3275. if Assigned(TaskRec.Task) then
  3276. begin
  3277. Items[I] := NullTask;
  3278. Break;
  3279. end;
  3280. end;
  3281. finally
  3282. GLContextManager.FThreadTask.UnlockList;
  3283. end;
  3284. end;
  3285. begin
  3286. with GLContextManager do
  3287. begin
  3288. vMainThread := False;
  3289. GLSLogger.LogNotice('Service thread started');
  3290. Sleep(100);
  3291. try
  3292. while not Terminated do
  3293. begin
  3294. NextTask;
  3295. if Assigned(TaskRec.Task) then
  3296. begin
  3297. with GLContextManager.ServiceContext do
  3298. begin
  3299. if IsValid then
  3300. Activate;
  3301. try
  3302. TaskRec.Task;
  3303. except
  3304. GLSLogger.LogError('Service thread task raised exception');
  3305. end;
  3306. if IsValid then
  3307. Deactivate;
  3308. if Assigned(TaskRec.Event) then
  3309. TaskRec.Event.SetEvent;
  3310. end;
  3311. end
  3312. else
  3313. Synchronize(GLContextManager.QueueTaskDepleted);
  3314. ServiceStarter.WaitFor(30000);
  3315. end;
  3316. finally
  3317. ServiceContext.Destroy;
  3318. FServiceContext := nil;
  3319. GLSLogger.LogNotice('Service thread finished');
  3320. end;
  3321. end;
  3322. end;
  3323. procedure AddTaskForServiceContext(ATask: TTaskProcedure; FinishEvent: TFinishTaskEvent = nil);
  3324. var
  3325. TaskRec: TServiceContextTask;
  3326. rEvent: TFinishTaskEvent;
  3327. begin
  3328. if vMainThread then
  3329. begin
  3330. rEvent := nil;
  3331. if Assigned(GLContextManager.ServiceContext) and Assigned(ATask) then
  3332. begin
  3333. CheckSynchronize;
  3334. with GLContextManager.FThreadTask.LockList do
  3335. try
  3336. TaskRec.Task := ATask;
  3337. if FinishEvent = nil then
  3338. begin // Synchronous call
  3339. rEvent := TFinishTaskEvent.Create;
  3340. TaskRec.Event := rEvent;
  3341. end
  3342. else // Asynchronous call
  3343. TaskRec.Event := FinishEvent;
  3344. Add(TaskRec);
  3345. with TServiceContextThread(GLContextManager.FThread) do
  3346. begin
  3347. FLastTaskStartTime := Now;
  3348. FReported := False;
  3349. end;
  3350. finally
  3351. GLContextManager.FThreadTask.UnlockList;
  3352. end;
  3353. GLContextManager.ServiceStarter.SetEvent;
  3354. end;
  3355. // Wait task finishing
  3356. if Assigned(rEvent) then
  3357. begin
  3358. rEvent.WaitFor(INFINITE);
  3359. rEvent.Destroy;
  3360. CheckSynchronize;
  3361. end;
  3362. end
  3363. else
  3364. begin // Direct task execution in service thread
  3365. try
  3366. ATask;
  3367. except
  3368. GLSLogger.LogError('Service thread task raised exception');
  3369. end;
  3370. if Assigned(FinishEvent) then
  3371. FinishEvent.SetEvent;
  3372. end;
  3373. end;
  3374. {$ENDIF USE_SERVICE_CONTEXT}
  3375. constructor TFinishTaskEvent.Create;
  3376. begin
  3377. inherited Create(nil, True, False, '');
  3378. end;
  3379. // ------------------------------------------------------------------
  3380. initialization
  3381. // ------------------------------------------------------------------
  3382. vMainThread := True;
  3383. {$IFDEF USE_SERVICE_CONTEXT}
  3384. OldInitProc := InitProc;
  3385. InitProc := @OnApplicationInitialize;
  3386. {$ENDIF USE_SERVICE_CONTEXT}
  3387. GLContextManager := TGLContextManager.Create;
  3388. GLwithoutContext := TGLExtensionsAndEntryPoints.Create;
  3389. GLwithoutContext.Close;
  3390. // vLocalGL := @GL;
  3391. finalization
  3392. GLContextManager.Terminate;
  3393. vContextClasses.Free;
  3394. vContextClasses := nil;
  3395. GLwithoutContext.Free;
  3396. GLwithoutContext := nil;
  3397. end.