Cg.Shader.pas 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261
  1. //
  2. // The graphics platform GLScene https://github.com/glscene
  3. //
  4. unit Cg.Shader;
  5. (* Base Cg shader classes *)
  6. interface
  7. uses
  8. Winapi.OpenGL,
  9. System.Classes,
  10. System.SysUtils,
  11. GLS.OpenGLTokens,
  12. GLS.VectorGeometry,
  13. GLS.VectorLists,
  14. GLS.VectorTypes,
  15. GLS.Texture,
  16. Scenario.Strings,
  17. GLS.Cadencer,
  18. GLS.Context,
  19. GLS.BaseClasses,
  20. GLS.RenderContextInfo,
  21. GLS.Material,
  22. Scenario.TextureFormat,
  23. Cg.Import,
  24. Cg.GL;
  25. {.$I GLScene.inc}
  26. { .$DEFINE OutputCompilerWarnings }
  27. (* Define OutputCompilerWarnings to output Cg compiler warnings to a file. Useful
  28. for detecting bugs caused by using uninitialized value, implicit type cast, etc. *)
  29. type
  30. ECgShaderException = class(EGLShaderException);
  31. TCustomCgShader = class;
  32. TCgProgram = class;
  33. TCgParameter = class;
  34. TCgApplyEvent = procedure(CgProgram: TCgProgram; Sender: TObject) of object;
  35. TCgUnApplyEvent = procedure(CgProgram: TCgProgram) of object;
  36. TCgShaderEvent = procedure(CgShader: TCustomCgShader) of object;
  37. TcgProgramType = (ptVertex, ptFragment);
  38. // Available vertex program profile
  39. TCgVPProfile = (vpDetectLatest, vp20, vp30, vp40, arbvp1);
  40. // Available fragment program profile
  41. TCgFPProfile = (fpDetectLatest, fp20, fp30, fp40, arbfp1);
  42. TPrecisionSetting = (psFull, psFast);
  43. // Wrapper around a Cg program.
  44. TCgProgram = class(TGLUpdateAbleObject)
  45. private
  46. FCgContext: PcgContext;
  47. FCode: TStrings; // the Cg program itself
  48. FProgramName: String;
  49. FHandle: PCGprogram;
  50. FParams: TList;
  51. FOnApply: TCgApplyEvent;
  52. FOnUnApply: TCgUnApplyEvent;
  53. FOnProgramChanged: TNotifyEvent;
  54. FEnabled: boolean;
  55. FDetectProfile: boolean;
  56. FPrecision: TPrecisionSetting;
  57. procedure SetPrecision(const Value: TPrecisionSetting);
  58. function GetManualNotification: boolean;
  59. procedure SetManualNotification(const Value: boolean);
  60. protected
  61. FProgramType: TcgProgramType;
  62. FProfile: TcgProfile;
  63. procedure SetCode(const val: TStrings);
  64. procedure SetProgramName(const val: String);
  65. function GetParam(index: String): TCgParameter;
  66. procedure AddParamsItem(const Param: PCGParameter);
  67. (* Build a list of parameters used in the shader code.
  68. Iteratively queries all parameters so that we can manage and access them
  69. easily. Currently only collects leaf parameters i.e. data structure is
  70. not retrieved. *)
  71. procedure BuildParamsList;
  72. procedure ClearParamsList;
  73. public
  74. constructor Create(AOwner: TPersistent); override;
  75. destructor Destroy; override;
  76. function GetLatestProfile: TcgProfile; virtual; abstract;
  77. procedure Initialize; virtual;
  78. procedure Finalize;
  79. procedure Apply(var rci: TGLRenderContextInfo; Sender: TObject);
  80. procedure UnApply(var rci: TGLRenderContextInfo);
  81. // ParamByName returns CgParameter; returns nil if not found.
  82. function ParamByName(const name: String): TCgParameter;
  83. (* Use Param instead of ParamByName if you want implicit check for the
  84. existence of your requested parameter. *)
  85. property Param[index: String]: TCgParameter read GetParam;
  86. property Params: TList read FParams;
  87. // Returns a handle to a Cg parameter
  88. function DirectParamByName(const name: String): PCGParameter;
  89. function ParamCount: Integer;
  90. function GetProfileStringA: string;
  91. procedure LoadFromFile(const fileName: String);
  92. procedure ListCompilation(Output: TStrings);
  93. procedure ListParameters(Output: TStrings);
  94. // shorthands for accessing parameters
  95. procedure SetParam(ParamName: string; SingleVal: Single); overload;
  96. procedure SetParam(ParamName: string;
  97. const Vector2fVal: TVector2f); overload;
  98. procedure SetParam(ParamName: string;
  99. const Vector3fVal: TVector3f); overload;
  100. procedure SetParam(ParamName: string;
  101. const Vector4fVal: TVector4f); overload;
  102. procedure SetStateMatrix(ParamName: string; matrix, Transform: Cardinal);
  103. procedure SetTexture(ParamName: string; TextureID: Cardinal);
  104. // retruns ShaderName.[program type].ProgramName
  105. function LongName: string;
  106. (* Direct access to the profile.
  107. Set Profile of the sub-classes to any but DetectLatest if you want to
  108. specify the profile directly. *)
  109. property DirectProfile: TcgProfile read FProfile write FProfile;
  110. // Seams, that this event is never called. Probably should be deleted...
  111. property OnProgramChanged: TNotifyEvent read FOnProgramChanged
  112. write FOnProgramChanged;
  113. // If True, that shader is not reset when TCgProgram' parameters change.
  114. property ManualNotification: boolean read GetManualNotification
  115. write SetManualNotification default False;
  116. published
  117. property Code: TStrings read FCode write SetCode;
  118. property ProgramName: String read FProgramName write SetProgramName;
  119. property Enabled: boolean read FEnabled write FEnabled default True;
  120. (* Precision controls data precision of GPU operation.
  121. Possible options are 16-bit (psFast) or 32-bit (psFull). 16-bit operation
  122. is generally faster. *)
  123. property Precision: TPrecisionSetting read FPrecision write SetPrecision
  124. default psFull;
  125. property OnApply: TCgApplyEvent read FOnApply write FOnApply;
  126. property OnUnApply: TCgUnApplyEvent read FOnUnApply write FOnUnApply;
  127. end;
  128. // Wrapper around a Cg parameter of the main program.
  129. TCgParameter = class(TObject)
  130. private
  131. FOwner: TCgProgram;
  132. FName: String;
  133. FHandle: PCGParameter;
  134. FValueType: TCGtype; // e.g. CG_FLOAT
  135. FDirection: TCGenum; // e.g. CG_INOUT
  136. FVariability: TCGenum; // e.g. CG_UNIFORM
  137. protected
  138. function TypeMismatchMessage: string;
  139. procedure CheckValueType(aType: TCGtype); overload;
  140. procedure CheckValueType(const types: array of TCGtype); overload;
  141. procedure CheckAllTextureTypes;
  142. procedure CheckAllScalarTypes;
  143. procedure CheckAllVector2fTypes;
  144. procedure CheckAllVector3fTypes;
  145. procedure CheckAllVector4fTypes;
  146. procedure SetAsVector2f(const val: TVector2f);
  147. procedure SetAsVector3f(const val: TVector3f);
  148. procedure SetAsVector4f(const val: TVector4f);
  149. public
  150. constructor Create; virtual;
  151. destructor Destroy; override;
  152. (* Procedures for setting uniform pamareters.
  153. Implicitly check for data type. *)
  154. procedure SetAsScalar(const val: Single); overload;
  155. procedure SetAsScalar(const val: boolean); overload;
  156. procedure SetAsVector(const val: TVector2f); overload;
  157. procedure SetAsVector(const val: TVector3f); overload;
  158. procedure SetAsVector(const val: TVector4f); overload;
  159. (* This overloaded SetAsVector accepts open array as input. e.g.
  160. SetAsVector([0.1, 0.2]). Array length must between 1-4. *)
  161. procedure SetAsVector(const val: array of Single); overload;
  162. procedure SetAsStateMatrix(matrix, Transform: Cardinal);
  163. procedure SetAsMatrix(const val: TMatrix4f);
  164. (* Procedures for dealing with texture pamareters. *)
  165. // SetAsTexture checks for all texture types
  166. procedure SetAsTexture(TextureID: Cardinal);
  167. // SetAsTexture* check for specific type
  168. procedure SetAsTexture1D(TextureID: Cardinal);
  169. procedure SetAsTexture2D(TextureID: Cardinal);
  170. procedure SetAsTexture3D(TextureID: Cardinal);
  171. procedure SetAsTextureCUBE(TextureID: Cardinal);
  172. procedure SetAsTextureRECT(TextureID: Cardinal);
  173. // SetToTextureOf determines texture type on-the-fly.
  174. procedure SetToTextureOf(LibMaterial: TGLLibMaterial);
  175. procedure EnableTexture;
  176. procedure DisableTexture;
  177. // Procedures for setting varying parameters with an array of values.
  178. procedure SetParameterPointer(Values: TGLVectorList); overload;
  179. procedure SetParameterPointer(Values: TGLAffineVectorList); overload;
  180. procedure EnableClientState;
  181. procedure DisableClientState;
  182. // LongName retruns ShaderName.[program type].ProgramName.ParamName.
  183. function LongName: string;
  184. property Owner: TCgProgram read FOwner;
  185. property Name: String read FName;
  186. property ValueType: TCGtype read FValueType;
  187. property Handle: PCGParameter read FHandle write FHandle;
  188. property Direction: TCGenum read FDirection write FDirection;
  189. property Variability: TCGenum read FVariability write FVariability;
  190. // GLScene-friendly properties
  191. property AsVector: TGLVector write SetAsVector4f; // position f.i.
  192. property AsAffineVector: TAffineVector write SetAsVector3f; // normal f.i.
  193. property AsVector2f: TVector2f write SetAsVector2f; // texCoord f.i.
  194. end;
  195. TCgVertexProgram = class(TCgProgram)
  196. private
  197. FVPProfile: TCgVPProfile;
  198. procedure SetVPProfile(v: TCgVPProfile);
  199. public
  200. constructor Create(AOwner: TPersistent); override;
  201. function GetLatestProfile: TcgProfile; override;
  202. published
  203. property Profile: TCgVPProfile read FVPProfile write SetVPProfile
  204. default vpDetectLatest;
  205. end;
  206. TCgFragmentProgram = class(TCgProgram)
  207. private
  208. FFPProfile: TCgFPProfile;
  209. FManageTexture: boolean;
  210. procedure SetFPProfile(v: TCgFPProfile);
  211. procedure SetManageTexture(const Value: boolean);
  212. public
  213. constructor Create(AOwner: TPersistent); override;
  214. procedure Initialize; override;
  215. function GetLatestProfile: TcgProfile; override;
  216. published
  217. property Profile: TCgFPProfile read FFPProfile write SetFPProfile
  218. default fpDetectLatest;
  219. // Switch for auto enabling of texture parameters (Cg 1.2 feature)
  220. // With Cg 1.2.1, default is OFF
  221. property ManageTexture: boolean read FManageTexture write SetManageTexture
  222. default False;
  223. end;
  224. TCustomCgShader = class(TGLShader)
  225. private
  226. FVertexProgram: TCgVertexProgram;
  227. FFragmentProgram: TCgFragmentProgram;
  228. FOnInitialize: TCgShaderEvent;
  229. FDesignEnable: boolean;
  230. protected
  231. // Vertex Program
  232. procedure SetVertexProgram(const val: TCgVertexProgram);
  233. procedure SetOnApplyVertexProgram(const val: TCgApplyEvent);
  234. function GetOnApplyVertexProgram: TCgApplyEvent;
  235. procedure SetOnUnApplyVertexProgram(const val: TCgUnApplyEvent);
  236. function GetOnUnApplyVertexProgram: TCgUnApplyEvent;
  237. // Fragment Program
  238. procedure SetFragmentProgram(const val: TCgFragmentProgram);
  239. procedure SetOnApplyFragmentProgram(const val: TCgApplyEvent);
  240. function GetOnApplyFragmentProgram: TCgApplyEvent;
  241. procedure SetOnUnApplyFragmentProgram(const val: TCgUnApplyEvent);
  242. function GetOnUnApplyFragmentProgram: TCgUnApplyEvent;
  243. // OnInitialize
  244. function GetOnInitialize: TCgShaderEvent;
  245. procedure SetOnInitialize(const val: TCgShaderEvent);
  246. procedure DoInitialize(var rci: TGLRenderContextInfo;
  247. Sender: TObject); override;
  248. procedure DoFinalize; override;
  249. procedure DoApply(var rci: TGLRenderContextInfo; Sender: TObject); override;
  250. function DoUnApply(var rci: TGLRenderContextInfo): boolean; override;
  251. // IsProfileSupported to be obsoleted by global function IsCgProfileSupported
  252. function IsProfileSupported(Profile: TcgProfile): boolean;
  253. (* Everything is moved here from the public and protected sections
  254. because I would like to shield end-users of descendant shader
  255. classes from all this stuff. Those who want direct access
  256. to shader events and parameters should use the TCgShader class,
  257. where everything is published. *)
  258. property OnApplyVP: TCgApplyEvent read GetOnApplyVertexProgram
  259. write SetOnApplyVertexProgram;
  260. property OnApplyFP: TCgApplyEvent read GetOnApplyFragmentProgram
  261. write SetOnApplyFragmentProgram;
  262. property OnUnApplyVP: TCgUnApplyEvent read GetOnUnApplyVertexProgram
  263. write SetOnUnApplyVertexProgram;
  264. property OnUnApplyFP: TCgUnApplyEvent read GetOnUnApplyFragmentProgram
  265. write SetOnUnApplyFragmentProgram;
  266. (* OnInitialize can be use to set parameters that need to be set once only.
  267. See demo "Cg Texture" for example. *)
  268. property OnInitialize: TCgShaderEvent read GetOnInitialize
  269. write SetOnInitialize;
  270. property DesignEnable: boolean read FDesignEnable write FDesignEnable
  271. default False;
  272. property VertexProgram: TCgVertexProgram read FVertexProgram
  273. write SetVertexProgram;
  274. property FragmentProgram: TCgFragmentProgram read FFragmentProgram
  275. write SetFragmentProgram;
  276. public
  277. constructor Create(AOwner: TComponent); override;
  278. destructor Destroy; override;
  279. procedure LoadShaderPrograms(const VPFilename, FPFilename: string);
  280. function ShaderSupported: boolean; override;
  281. end;
  282. // Allows to use a Cadencer, which is used for noise generation in many shaders.
  283. TCadencableCustomCgShader = class(TCustomCgShader)
  284. private
  285. FCadencer: TGLCadencer;
  286. procedure SetCadencer(const Value: TGLCadencer);
  287. protected
  288. procedure DoInitialize(var rci: TGLRenderContextInfo;
  289. Sender: TObject); override;
  290. procedure Notification(AComponent: TComponent;
  291. Operation: TOperation); override;
  292. public
  293. property Cadencer: TGLCadencer read FCadencer write SetCadencer;
  294. end;
  295. TCgShader = class(TCustomCgShader)
  296. published
  297. property DesignEnable;
  298. property ShaderStyle;
  299. property FailedInitAction;
  300. property VertexProgram;
  301. property FragmentProgram;
  302. property OnApplyVP;
  303. property OnApplyFP;
  304. property OnUnApplyVP;
  305. property OnUnApplyFP;
  306. property OnInitialize;
  307. end;
  308. // global variables/functions
  309. var
  310. (* Set IncludeFilePath to indicate where to find your include file for your
  311. Cg source files. This avoids error from the Cg Compiler when the current
  312. directory is not the right path as the shader is being compiled. *)
  313. IncludeFilePath: string;
  314. {$IFDEF OutputCompilerWarnings}
  315. (* Edit the string WarningFilePath for the output filename. Default
  316. WarningFilePath is set to application path. *)
  317. WarningFilePath: string;
  318. {$ENDIF}
  319. // Misc. global functions
  320. function IsCgProfileSupported(Profile: TcgProfile): boolean;
  321. // ------------------------------------------------------------------
  322. implementation
  323. // ------------------------------------------------------------------
  324. const
  325. CgBoolean: array [False .. True] of TCGbool = (CG_FALSE, CG_TRUE);
  326. var
  327. vCgContextCount: Integer;
  328. CurCgProgram: TCgProgram; // for reporting error
  329. {$IFDEF OutputCompilerWarnings}
  330. CompilerMsg: TStringList; // useful for seeing compiler warnings
  331. {$ENDIF}
  332. function IsCgProfileSupported(Profile: TcgProfile): boolean;
  333. begin
  334. result := cgGLIsProfileSupported(Profile) = CG_TRUE;
  335. end;
  336. {$IFDEF OutputCompilerWarnings}
  337. procedure RecordWarnings;
  338. begin
  339. with CurCgProgram do
  340. CompilerMsg.Add('[' + LongName + '] ' + cgGetErrorString(cgGetError) + #10 +
  341. cgGetLastListing(FCgContext));
  342. end;
  343. {$ENDIF}
  344. procedure ErrorCallBack; cdecl;
  345. var
  346. Msg: string;
  347. begin
  348. with CurCgProgram do
  349. Msg := '[' + LongName + '] ' + String(cgGetErrorString(cgGetError)) + #10 +
  350. String(cgGetLastListing(FCgContext));
  351. raise ECgShaderException.Create(Msg);
  352. end;
  353. // ------------------
  354. // ------------------ TCgProgram ------------------
  355. // ------------------
  356. constructor TCgProgram.Create(AOwner: TPersistent);
  357. begin
  358. inherited;
  359. FCode := TStringList.Create;
  360. TStringList(FCode).OnChange := NotifyChange;
  361. FParams := TList.Create;
  362. FEnabled := True;
  363. FDetectProfile := True;
  364. end;
  365. destructor TCgProgram.Destroy;
  366. begin
  367. inherited Destroy;
  368. Assert((FParams.Count = 0), '[' + LongName + ']: bug! params unbound!');
  369. ClearParamsList;
  370. FParams.Free;
  371. FCode.Free;
  372. end;
  373. procedure TCgProgram.SetCode(const val: TStrings);
  374. begin
  375. FCode.Assign(val);
  376. end;
  377. procedure TCgProgram.LoadFromFile(const fileName: String);
  378. begin
  379. Code.LoadFromFile(fileName);
  380. end;
  381. procedure TCgProgram.SetProgramName(const val: String);
  382. begin
  383. if val <> FProgramName then
  384. begin
  385. FProgramName := val;
  386. if not GetManualNotification then
  387. NotifyChange(Self);
  388. end;
  389. end;
  390. procedure TCgProgram.AddParamsItem(const Param: PCGParameter);
  391. var
  392. newParamObj: TCgParameter;
  393. begin
  394. newParamObj := TCgParameter.Create;
  395. with newParamObj do
  396. begin
  397. FOwner := Self;
  398. FName := { StrPas } String(cgGetParameterName(Param));
  399. FHandle := Param;
  400. FValueType := cgGetParameterType(Param);
  401. FDirection := cgGetParameterDirection(Param);
  402. FVariability := cgGetParameterVariability(Param);
  403. end;
  404. FParams.Add(newParamObj);
  405. end;
  406. procedure TCgProgram.BuildParamsList;
  407. var
  408. CurParam: PCGParameter;
  409. begin
  410. ClearParamsList;
  411. CurParam := cgGetFirstLeafParameter(FHandle, CG_PROGRAM);
  412. // build params list
  413. while Assigned(CurParam) do
  414. begin
  415. AddParamsItem(CurParam);
  416. CurParam := cgGetNextLeafParameter(CurParam);
  417. end;
  418. end;
  419. procedure TCgProgram.ClearParamsList;
  420. var
  421. i: Integer;
  422. begin
  423. for i := FParams.Count - 1 downto 0 do
  424. TCgParameter(FParams[i]).Free;
  425. FParams.Clear;
  426. end;
  427. function TCgProgram.GetParam(index: String): TCgParameter;
  428. begin
  429. result := ParamByName(index);
  430. Assert(result <> nil, '[' + LongName + ']: Parameter "' +
  431. index + '" not found.');
  432. end;
  433. function TCgProgram.ParamByName(const name: String): TCgParameter;
  434. var
  435. i: Integer;
  436. begin
  437. result := nil;
  438. for i := 0 to FParams.Count - 1 do
  439. begin
  440. if TCgParameter(FParams.Items[i]).name = name then
  441. begin
  442. result := TCgParameter(FParams.Items[i]);
  443. Exit;
  444. end;
  445. end;
  446. end;
  447. function TCgProgram.DirectParamByName(const name: String): PCGParameter;
  448. begin
  449. result := cgGetNamedParameter(FHandle, PCharCG(StringCG(name)));
  450. end;
  451. function TCgProgram.ParamCount: Integer;
  452. begin
  453. result := FParams.Count;
  454. end;
  455. procedure TCgProgram.Initialize;
  456. var
  457. buf: StringCG;
  458. Arg: array of PCharCG;
  459. PArg: PPCharCG;
  460. begin
  461. Assert(FCgContext = nil);
  462. buf := StringCG(Trim(Code.Text));
  463. if buf = '' then
  464. Exit;
  465. if Precision = psFast then
  466. begin
  467. setlength(Arg, 2);
  468. Arg[0] := PCharCG('-fastprecision');
  469. Arg[1] := nil;
  470. PArg := @Arg[0];
  471. end
  472. else
  473. PArg := nil;
  474. // To force 'if' statement, use sth. like:
  475. // setlength(Arg, 3);
  476. // Arg[0]:=PChar('-ifcvt');
  477. // Arg[1]:=PChar('none');
  478. // Arg[2]:=nil;
  479. // PArg:=@Arg[0];
  480. // get a new context
  481. FCgContext := cgCreateContext;
  482. Inc(vCgContextCount);
  483. CurCgProgram := Self;
  484. try
  485. if IncludeFilePath <> '' then
  486. SetCurrentDir(IncludeFilePath);
  487. if FDetectProfile then
  488. FProfile := GetLatestProfile;
  489. cgGLSetOptimalOptions(FProfile);
  490. if FProgramName = '' then
  491. FProgramName := 'main'; // default program name
  492. FHandle := cgCreateProgram(FCgContext, CG_SOURCE, PCharCG(buf), FProfile,
  493. PCharCG(StringCG(FProgramName)), PArg);
  494. cgGLLoadProgram(FHandle);
  495. // build parameter list for the selected program
  496. BuildParamsList;
  497. {$IFDEF OutputCompilerWarnings}
  498. RecordWarnings;
  499. {$ENDIF}
  500. except
  501. cgDestroyContext(FCgContext);
  502. FCgContext := nil;
  503. Dec(vCgContextCount);
  504. raise;
  505. end;
  506. end;
  507. procedure TCgProgram.Finalize;
  508. begin
  509. if not Assigned(FCgContext) then
  510. Exit;
  511. FProgramName := '';
  512. ClearParamsList;
  513. cgDestroyContext(FCgContext);
  514. FCgContext := nil;
  515. FHandle := nil; // $added - 29/04/2006 - PhP
  516. Dec(vCgContextCount);
  517. end;
  518. procedure TCgProgram.Apply(var rci: TGLRenderContextInfo; Sender: TObject);
  519. begin
  520. if not Assigned(FHandle) then
  521. Exit;
  522. if not FEnabled then
  523. Exit;
  524. CurCgProgram := Self;
  525. cgGLBindProgram(FHandle);
  526. cgGLEnableProfile(FProfile);
  527. if Assigned(FOnApply) then
  528. FOnApply(Self, Sender);
  529. end;
  530. procedure TCgProgram.UnApply(var rci: TGLRenderContextInfo);
  531. begin
  532. if not Assigned(FHandle) then
  533. Exit;
  534. if not FEnabled then
  535. Exit;
  536. if Assigned(FOnUnApply) then
  537. FOnUnApply(Self);
  538. cgGLDisableProfile(FProfile);
  539. end;
  540. function TCgProgram.GetProfileStringA: string;
  541. begin
  542. result := String(cgGetProfileString(FProfile));
  543. end;
  544. procedure TCgProgram.ListParameters(Output: TStrings);
  545. var
  546. i: Integer;
  547. begin
  548. Output.Clear;
  549. for i := 0 to ParamCount - 1 do
  550. Output.Add(TCgParameter(FParams[i]).name);
  551. end;
  552. procedure TCgProgram.ListCompilation(Output: TStrings);
  553. procedure OutputAsTStrings(s: String);
  554. var
  555. i: Integer;
  556. begin
  557. while Length(s) > 0 do
  558. begin
  559. i := Pos(#10, s);
  560. if i = 0 then
  561. i := 255;
  562. Output.Add(Copy(s, 1, i - 1));
  563. Delete(s, 1, i);
  564. end;
  565. end;
  566. begin
  567. Output.BeginUpdate;
  568. Output.Clear;
  569. if FCgContext <> nil then
  570. OutputAsTStrings(String(cgGetProgramString(FHandle, CG_COMPILED_PROGRAM)))
  571. else
  572. Output.Add('Cg program not yet initialized');
  573. Output.EndUpdate;
  574. end;
  575. procedure TCgProgram.SetParam(ParamName: string; const Vector3fVal: TVector3f);
  576. begin
  577. ParamByName(ParamName).SetAsVector3f(Vector3fVal);
  578. end;
  579. procedure TCgProgram.SetParam(ParamName: string; const Vector2fVal: TVector2f);
  580. begin
  581. ParamByName(ParamName).SetAsVector2f(Vector2fVal);
  582. end;
  583. procedure TCgProgram.SetParam(ParamName: string; SingleVal: Single);
  584. begin
  585. Param[ParamName].SetAsScalar(SingleVal);
  586. end;
  587. procedure TCgProgram.SetParam(ParamName: string; const Vector4fVal: TVector4f);
  588. begin
  589. ParamByName(ParamName).SetAsVector4f(Vector4fVal);
  590. end;
  591. procedure TCgProgram.SetStateMatrix(ParamName: string;
  592. matrix, Transform: Cardinal);
  593. begin
  594. ParamByName(ParamName).SetAsStateMatrix(matrix, Transform);
  595. end;
  596. procedure TCgProgram.SetTexture(ParamName: string; TextureID: Cardinal);
  597. begin
  598. ParamByName(ParamName).SetAsTexture(TextureID);
  599. end;
  600. function TCgProgram.LongName: string;
  601. const
  602. ProTypeStr: array [ptVertex .. ptFragment] of string = ('VP', 'FP');
  603. begin
  604. result := (Owner as TCgShader).name + '.' + ProTypeStr[FProgramType] + '.' +
  605. ProgramName;
  606. end;
  607. procedure TCgProgram.SetPrecision(const Value: TPrecisionSetting);
  608. begin
  609. if FPrecision <> Value then
  610. begin
  611. FPrecision := Value;
  612. if not GetManualNotification then
  613. NotifyChange(Self);
  614. end;
  615. end;
  616. function TCgProgram.GetManualNotification: boolean;
  617. begin
  618. result := not Assigned(TStringList(FCode).OnChange);
  619. end;
  620. procedure TCgProgram.SetManualNotification(const Value: boolean);
  621. begin
  622. if Value = GetManualNotification then
  623. Exit;
  624. if Value then
  625. TStringList(FCode).OnChange := nil
  626. else
  627. TStringList(FCode).OnChange := NotifyChange;
  628. end;
  629. // ------------------
  630. // ------------------ TCgParameter ------------------
  631. // ------------------
  632. constructor TCgParameter.Create;
  633. begin
  634. inherited;
  635. end;
  636. destructor TCgParameter.Destroy;
  637. begin
  638. inherited;
  639. end;
  640. function TCgParameter.LongName: string;
  641. begin
  642. result := Owner.LongName + '.' + FName;
  643. end;
  644. function TCgParameter.TypeMismatchMessage: string;
  645. begin
  646. result := '[' + LongName + ']: Parameter type mismatch.';
  647. end;
  648. procedure TCgParameter.CheckValueType(aType: TCGtype);
  649. begin
  650. Assert(aType = FValueType, TypeMismatchMessage);
  651. end;
  652. procedure TCgParameter.CheckValueType(const types: array of TCGtype);
  653. function DoCheck: boolean;
  654. var
  655. i: Integer;
  656. begin
  657. result := False;
  658. for i := Low(types) to High(types) do
  659. if FValueType = types[i] then
  660. begin
  661. result := True;
  662. Break;
  663. end;
  664. end;
  665. begin
  666. Assert(DoCheck, TypeMismatchMessage);
  667. end;
  668. procedure TCgParameter.CheckAllScalarTypes;
  669. begin
  670. CheckValueType([CG_FLOAT, CG_HALF, CG_FIXED, CG_BOOL]);
  671. end;
  672. procedure TCgParameter.CheckAllTextureTypes;
  673. begin
  674. CheckValueType([CG_SAMPLER2D, CG_SAMPLER1D, CG_SAMPLERRECT, CG_SAMPLERCUBE,
  675. CG_SAMPLER3D]);
  676. end;
  677. procedure TCgParameter.CheckAllVector2fTypes;
  678. begin
  679. CheckValueType([CG_FLOAT2, CG_HALF2, CG_FIXED2]);
  680. end;
  681. procedure TCgParameter.CheckAllVector3fTypes;
  682. begin
  683. CheckValueType([CG_FLOAT3, CG_HALF3, CG_FIXED3]);
  684. end;
  685. procedure TCgParameter.CheckAllVector4fTypes;
  686. begin
  687. CheckValueType([CG_FLOAT4, CG_HALF4, CG_FIXED4]);
  688. end;
  689. procedure TCgParameter.SetAsScalar(const val: Single);
  690. begin
  691. CheckAllScalarTypes;
  692. cgGLSetParameter1f(FHandle, val);
  693. end;
  694. procedure TCgParameter.SetAsScalar(const val: boolean);
  695. const
  696. BoolToFloat: array [False .. True] of Single = (CG_FALSE, CG_TRUE);
  697. begin
  698. SetAsScalar(BoolToFloat[val]);
  699. end;
  700. procedure TCgParameter.SetAsVector2f(const val: TVector2f);
  701. begin
  702. CheckAllVector2fTypes;
  703. cgGLSetParameter2fv(FHandle, @val);
  704. end;
  705. procedure TCgParameter.SetAsVector3f(const val: TVector3f);
  706. begin
  707. CheckAllVector3fTypes;
  708. cgGLSetParameter3fv(FHandle, @val);
  709. end;
  710. procedure TCgParameter.SetAsVector4f(const val: TVector4f);
  711. begin
  712. CheckAllVector4fTypes;
  713. cgGLSetParameter4fv(FHandle, @val);
  714. end;
  715. procedure TCgParameter.SetAsVector(const val: TVector2f);
  716. begin
  717. SetAsVector2f(val);
  718. end;
  719. procedure TCgParameter.SetAsVector(const val: TVector3f);
  720. begin
  721. SetAsVector3f(val);
  722. end;
  723. procedure TCgParameter.SetAsVector(const val: TVector4f);
  724. begin
  725. SetAsVector4f(val);
  726. end;
  727. procedure TCgParameter.SetAsVector(const val: array of Single);
  728. begin
  729. case high(val) of
  730. 0:
  731. SetAsScalar(val[0]);
  732. 1:
  733. begin
  734. CheckAllVector2fTypes;
  735. cgGLSetParameter2fv(FHandle, @val);
  736. end;
  737. 2:
  738. begin
  739. CheckAllVector3fTypes;
  740. cgGLSetParameter3fv(FHandle, @val);
  741. end;
  742. 3:
  743. begin
  744. CheckAllVector4fTypes;
  745. cgGLSetParameter4fv(FHandle, @val);
  746. end;
  747. else
  748. Assert(False, 'Vector length must be between 1 to 4');
  749. end;
  750. end;
  751. procedure TCgParameter.SetAsTexture(TextureID: Cardinal);
  752. begin
  753. CheckAllTextureTypes;
  754. cgGLSetTextureParameter(FHandle, TextureID);
  755. end;
  756. procedure TCgParameter.SetAsTexture1D(TextureID: Cardinal);
  757. begin
  758. CheckValueType(CG_SAMPLER1D);
  759. cgGLSetTextureParameter(FHandle, TextureID);
  760. end;
  761. procedure TCgParameter.SetAsTexture2D(TextureID: Cardinal);
  762. begin
  763. CheckValueType(CG_SAMPLER2D);
  764. cgGLSetTextureParameter(FHandle, TextureID);
  765. end;
  766. procedure TCgParameter.SetAsTexture3D(TextureID: Cardinal);
  767. begin
  768. CheckValueType(CG_SAMPLER3D);
  769. cgGLSetTextureParameter(FHandle, TextureID);
  770. end;
  771. procedure TCgParameter.SetAsTextureRECT(TextureID: Cardinal);
  772. begin
  773. CheckValueType(CG_SAMPLERRECT);
  774. cgGLSetTextureParameter(FHandle, TextureID);
  775. end;
  776. procedure TCgParameter.SetAsTextureCUBE(TextureID: Cardinal);
  777. begin
  778. CheckValueType(CG_SAMPLERCUBE);
  779. cgGLSetTextureParameter(FHandle, TextureID);
  780. end;
  781. procedure TCgParameter.SetToTextureOf(LibMaterial: TGLLibMaterial);
  782. var
  783. TexType: TCGtype;
  784. begin
  785. case LibMaterial.Material.Texture.Image.NativeTextureTarget of
  786. ttTexture2D:
  787. TexType := CG_SAMPLER2D;
  788. ttTextureCUBE:
  789. TexType := CG_SAMPLER2D;
  790. ttTextureRECT:
  791. TexType := CG_SAMPLERRECT;
  792. ttTexture1D:
  793. TexType := CG_SAMPLER1D;
  794. ttTexture3D:
  795. TexType := CG_SAMPLER3D;
  796. else
  797. begin
  798. Assert(False, 'Unknown texture target');
  799. TexType := CG_SAMPLER2D; // to subpress compilation warning
  800. end;
  801. end;
  802. CheckValueType(TexType);
  803. cgGLSetTextureParameter(FHandle, LibMaterial.Material.Texture.Handle);
  804. end;
  805. procedure TCgParameter.DisableTexture;
  806. begin
  807. CheckAllTextureTypes;
  808. cgGLDisableTextureParameter(FHandle);
  809. end;
  810. procedure TCgParameter.EnableTexture;
  811. begin
  812. CheckAllTextureTypes;
  813. cgGLEnableTextureParameter(FHandle);
  814. end;
  815. procedure TCgParameter.SetAsStateMatrix(matrix, Transform: Cardinal);
  816. // Assuming values of matrix types are contiguous to simplify the type checking
  817. const
  818. MinFloatA = CG_FLOAT1x1;
  819. MaxFloatA = CG_FLOAT4x4;
  820. MinHalfA = CG_HALF1x1;
  821. MaxHalfA = CG_HALF4x4;
  822. MinFixedA = CG_FIXED1x1;
  823. MaxFixedA = CG_FIXED4x4;
  824. begin
  825. Assert(((FValueType >= MinFloatA) and (FValueType <= MaxFloatA) or
  826. (FValueType >= MinHalfA) and (FValueType <= MaxHalfA) or
  827. (FValueType >= MinFixedA) and (FValueType <= MaxFixedA)),
  828. TypeMismatchMessage);
  829. cgGLSetStateMatrixParameter(FHandle, matrix, Transform);
  830. end;
  831. procedure TCgParameter.SetAsMatrix(const val: TMatrix4f);
  832. begin
  833. cgGLSetMatrixParameterfr(FHandle, @val);
  834. end;
  835. procedure TCgParameter.DisableClientState;
  836. begin
  837. Assert(FVariability = CG_VARYING);
  838. cgGLDisableClientState(FHandle);
  839. end;
  840. procedure TCgParameter.EnableClientState;
  841. begin
  842. Assert(FVariability = CG_VARYING);
  843. cgGLEnableClientState(FHandle);
  844. end;
  845. procedure TCgParameter.SetParameterPointer(Values: TGLAffineVectorList);
  846. begin
  847. Assert(FVariability = CG_VARYING);
  848. cgGLSetParameterPointer(FHandle, 3, GL_FLOAT, 0, Values.List);
  849. end;
  850. procedure TCgParameter.SetParameterPointer(Values: TGLVectorList);
  851. begin
  852. Assert(FVariability = CG_VARYING);
  853. cgGLSetParameterPointer(FHandle, 4, GL_FLOAT, 0, Values.List);
  854. end;
  855. // ------------------
  856. // ------------------ TCgVertexProgram ------------------
  857. // ------------------
  858. constructor TCgVertexProgram.Create;
  859. begin
  860. inherited;
  861. FProgramType := ptVertex;
  862. FVPProfile := vpDetectLatest;
  863. end;
  864. function TCgVertexProgram.GetLatestProfile: TcgProfile;
  865. begin
  866. result := cgGLGetLatestProfile(CG_GL_VERTEX);
  867. end;
  868. procedure TCgVertexProgram.SetVPProfile(v: TCgVPProfile);
  869. begin
  870. if FVPProfile = v then
  871. Exit;
  872. FVPProfile := v;
  873. case v of
  874. vp20:
  875. FProfile := CG_PROFILE_VP20;
  876. vp30:
  877. FProfile := CG_PROFILE_VP30;
  878. vp40:
  879. FProfile := CG_PROFILE_VP40;
  880. arbvp1:
  881. FProfile := CG_PROFILE_ARBVP1;
  882. end;
  883. FDetectProfile := v = vpDetectLatest;
  884. end;
  885. // ------------------
  886. // ------------------ TCgFragmentProgram ------------------
  887. // ------------------
  888. constructor TCgFragmentProgram.Create;
  889. begin
  890. inherited;
  891. FProgramType := ptFragment;
  892. FFPProfile := fpDetectLatest;
  893. FManageTexture := False;
  894. end;
  895. procedure TCgFragmentProgram.SetManageTexture(const Value: boolean);
  896. begin
  897. FManageTexture := Value;
  898. if FCgContext <> nil then
  899. cgGLSetManageTextureParameters(@FCgContext, CgBoolean[FManageTexture]);
  900. // If FCgContext = nil (i.e. program not yet initialized), set it in
  901. // TCgFragmentProgram.Initialize
  902. end;
  903. procedure TCgFragmentProgram.Initialize;
  904. begin
  905. inherited;
  906. if FManageTexture then // ManageTexture is off by default
  907. cgGLSetManageTextureParameters(@FCgContext, CgBoolean[FManageTexture]);
  908. end;
  909. function TCgFragmentProgram.GetLatestProfile: TcgProfile;
  910. begin
  911. result := cgGLGetLatestProfile(CG_GL_FRAGMENT);
  912. end;
  913. procedure TCgFragmentProgram.SetFPProfile(v: TCgFPProfile);
  914. begin
  915. if FFPProfile = v then
  916. Exit;
  917. FFPProfile := v;
  918. case v of
  919. fp20:
  920. FProfile := CG_PROFILE_FP20;
  921. fp30:
  922. FProfile := CG_PROFILE_FP30;
  923. fp40:
  924. FProfile := CG_PROFILE_FP40;
  925. arbfp1:
  926. FProfile := CG_PROFILE_ARBFP1;
  927. end;
  928. FDetectProfile := v = fpDetectLatest;
  929. end;
  930. // ------------------
  931. // ------------------ TCustomCgShader ------------------
  932. // ------------------
  933. constructor TCustomCgShader.Create(AOwner: TComponent);
  934. begin
  935. inherited Create(AOwner);
  936. FVertexProgram := TCgVertexProgram.Create(Self);
  937. FFragmentProgram := TCgFragmentProgram.Create(Self);
  938. end;
  939. destructor TCustomCgShader.Destroy;
  940. begin
  941. inherited Destroy;
  942. FVertexProgram.Free;
  943. FFragmentProgram.Free;
  944. end;
  945. procedure TCustomCgShader.SetVertexProgram(const val: TCgVertexProgram);
  946. begin
  947. FVertexProgram.Code := val.Code;
  948. end;
  949. procedure TCustomCgShader.SetFragmentProgram(const val: TCgFragmentProgram);
  950. begin
  951. FFragmentProgram.Code := val.Code;
  952. end;
  953. procedure TCustomCgShader.SetOnApplyVertexProgram(const val: TCgApplyEvent);
  954. begin
  955. FVertexProgram.OnApply := val;
  956. end;
  957. function TCustomCgShader.GetOnApplyVertexProgram: TCgApplyEvent;
  958. begin
  959. result := FVertexProgram.OnApply;
  960. end;
  961. procedure TCustomCgShader.SetOnApplyFragmentProgram(const val: TCgApplyEvent);
  962. begin
  963. FFragmentProgram.OnApply := val;
  964. end;
  965. function TCustomCgShader.GetOnApplyFragmentProgram: TCgApplyEvent;
  966. begin
  967. result := FFragmentProgram.OnApply;
  968. end;
  969. procedure TCustomCgShader.SetOnUnApplyVertexProgram(const val: TCgUnApplyEvent);
  970. begin
  971. FVertexProgram.OnUnApply := val;
  972. end;
  973. function TCustomCgShader.GetOnUnApplyVertexProgram: TCgUnApplyEvent;
  974. begin
  975. result := FVertexProgram.OnUnApply;
  976. end;
  977. procedure TCustomCgShader.SetOnUnApplyFragmentProgram
  978. (const val: TCgUnApplyEvent);
  979. begin
  980. FFragmentProgram.OnUnApply := val;
  981. end;
  982. function TCustomCgShader.GetOnUnApplyFragmentProgram: TCgUnApplyEvent;
  983. begin
  984. result := FFragmentProgram.OnUnApply;
  985. end;
  986. function TCustomCgShader.GetOnInitialize: TCgShaderEvent;
  987. begin
  988. result := FOnInitialize;
  989. end;
  990. procedure TCustomCgShader.SetOnInitialize(const val: TCgShaderEvent);
  991. begin
  992. FOnInitialize := val;
  993. end;
  994. procedure TCustomCgShader.DoInitialize(var rci: TGLRenderContextInfo;
  995. Sender: TObject);
  996. begin
  997. if (csDesigning in ComponentState) and (not FDesignEnable) then
  998. Exit;
  999. if not ShaderSupported then
  1000. begin
  1001. Enabled := False;
  1002. HandleFailedInitialization;
  1003. end
  1004. else
  1005. try
  1006. FVertexProgram.Initialize;
  1007. FFragmentProgram.Initialize;
  1008. if Assigned(FOnInitialize) then
  1009. FOnInitialize(Self);
  1010. except
  1011. on E: Exception do
  1012. begin
  1013. Enabled := False;
  1014. HandleFailedInitialization(E.Message);
  1015. end;
  1016. end;
  1017. end;
  1018. procedure TCustomCgShader.DoApply(var rci: TGLRenderContextInfo;
  1019. Sender: TObject);
  1020. begin
  1021. if (csDesigning in ComponentState) and (not FDesignEnable) then
  1022. Exit;
  1023. FVertexProgram.Apply(rci, Sender);
  1024. FFragmentProgram.Apply(rci, Sender);
  1025. end;
  1026. function TCustomCgShader.DoUnApply(var rci: TGLRenderContextInfo): boolean;
  1027. begin
  1028. if (not(csDesigning in ComponentState)) or FDesignEnable then
  1029. begin
  1030. FVertexProgram.UnApply(rci);
  1031. FFragmentProgram.UnApply(rci);
  1032. end;
  1033. result := False;
  1034. end;
  1035. procedure TCustomCgShader.DoFinalize;
  1036. begin
  1037. FVertexProgram.Finalize;
  1038. FFragmentProgram.Finalize;
  1039. end;
  1040. procedure TCustomCgShader.LoadShaderPrograms(const VPFilename,
  1041. FPFilename: string);
  1042. begin
  1043. VertexProgram.LoadFromFile(VPFilename);
  1044. FragmentProgram.LoadFromFile(FPFilename);
  1045. end;
  1046. function TCustomCgShader.IsProfileSupported(Profile: TcgProfile): boolean;
  1047. begin
  1048. result := cgGLIsProfileSupported(Profile) = CG_TRUE;
  1049. end;
  1050. function TCustomCgShader.ShaderSupported: boolean;
  1051. begin
  1052. result := (GL.ARB_shader_objects and GL.ARB_vertex_program and
  1053. GL.ARB_vertex_shader and GL.ARB_fragment_shader);
  1054. end;
  1055. // ------------------
  1056. // ------------------ TCadencableCustomCgShader ------------------
  1057. // ------------------
  1058. procedure TCadencableCustomCgShader.DoInitialize(var rci: TGLRenderContextInfo;
  1059. Sender: TObject);
  1060. begin
  1061. if FCadencer = nil then
  1062. begin
  1063. Enabled := False;
  1064. raise ECgShaderException.CreateFmt(strErrorEx + strCadencerNotDefinedEx,
  1065. [ClassName]);
  1066. end
  1067. else
  1068. inherited;
  1069. end;
  1070. procedure TCadencableCustomCgShader.Notification(AComponent: TComponent;
  1071. Operation: TOperation);
  1072. begin
  1073. inherited;
  1074. if (AComponent is TGLCadencer) and (Operation = opRemove) then
  1075. begin
  1076. FCadencer := nil;
  1077. Enabled := False;
  1078. end;
  1079. end;
  1080. procedure TCadencableCustomCgShader.SetCadencer(const Value: TGLCadencer);
  1081. begin
  1082. if Value = FCadencer then
  1083. Exit;
  1084. if Value = nil then
  1085. if Enabled then
  1086. Enabled := False;
  1087. if FCadencer <> nil then
  1088. FCadencer.RemoveFreeNotification(Self);
  1089. FCadencer := Value;
  1090. if FCadencer <> nil then
  1091. FCadencer.FreeNotification(Self);
  1092. end;
  1093. // ------------------------------------------------------------------
  1094. initialization
  1095. // ------------------------------------------------------------------
  1096. // class registrations
  1097. RegisterClasses([TCgShader, TCustomCgShader, TCadencableCustomCgShader,
  1098. TCgFragmentProgram, TCgVertexProgram, TCgProgram]);
  1099. cgSetErrorCallBack(ErrorCallBack);
  1100. {$IFDEF OutputCompilerWarnings}
  1101. CompilerMsg := TStringList.Create;
  1102. // default WarningFilePath is set to app. path
  1103. WarningFilePath := extractfilepath(ParamStr(0));
  1104. {$ENDIF}
  1105. finalization
  1106. {$IFDEF OutputCompilerWarnings}
  1107. CompilerMsg.SaveToFile(WarningFilePath + 'CG_Warnings.txt');
  1108. CompilerMsg.Free;
  1109. {$ENDIF}
  1110. end.