GLS.CgShader.pas 34 KB

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