GXS.Context.pas 102 KB

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