GLS.Context.pas 109 KB

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