MainUnit.pas 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. unit MainUnit;
  2. (* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1 or LGPL 2.1 with linking exception
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * Alternatively, the contents of this file may be used under the terms of the
  16. * Free Pascal modified version of the GNU Lesser General Public License
  17. * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
  18. * of this license are applicable instead of those above.
  19. * Please see the file LICENSE.txt for additional information concerning this
  20. * license.
  21. *
  22. * The Original Code is Sprites Example
  23. *
  24. * The Initial Developer of the Original Code is
  25. * Alex A. Denisov
  26. *
  27. * Portions created by the Initial Developer are Copyright (C) 2000-2005
  28. * the Initial Developer. All Rights Reserved.
  29. *
  30. * Contributor(s):
  31. * Andre Beckedorf - metaException OHG
  32. *
  33. * ***** END LICENSE BLOCK ***** *)
  34. interface
  35. {$I GR32.inc}
  36. uses
  37. {$IFDEF FPC} LCLIntf, LResources, Variants, {$ENDIF}
  38. {$IFNDEF FPC} AppEvnts, {$ENDIF} {$IFDEF Windows}Windows,{$ENDIF}
  39. SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls,
  40. Math, Buttons, GR32, GR32_Transforms, GR32_Image, GR32_Layers,
  41. GR32_Containers, GR32_MicroTiles;
  42. const
  43. MAX_RUNS = 3;
  44. type
  45. TMainForm = class(TForm)
  46. BtnAdd: TButton;
  47. BtnBenchmark: TButton;
  48. BtnClearAll: TButton;
  49. BitmapList: TBitmap32List;
  50. BtnRemove: TButton;
  51. CbxUseRepaintOpt: TCheckBox;
  52. EdtLayerCount: TEdit;
  53. Image32: TImage32;
  54. LblDimension: TLabel;
  55. LblFPS: TLabel;
  56. LblTotal: TLabel;
  57. Memo: TMemo;
  58. TimerFPS: TTimer;
  59. procedure FormCreate(Sender: TObject);
  60. procedure FormDestroy(Sender: TObject);
  61. procedure BtnAddClick(Sender: TObject);
  62. procedure BtnBenchmarkClick(Sender: TObject);
  63. procedure BtnClearAllClick(Sender: TObject);
  64. procedure BtnRemoveClick(Sender: TObject);
  65. procedure CbxUseRepaintOptClick(Sender: TObject);
  66. procedure Image32Resize(Sender: TObject);
  67. procedure TimerFPSTimer(Sender: TObject);
  68. public
  69. Velocities: TArrayOfFloatPoint;
  70. FramesDrawn: Integer;
  71. LastCheck: Cardinal;
  72. LastSeed: Integer;
  73. PriorityClass, Priority: Integer;
  74. BenchmarkMode: Boolean;
  75. BenchmarkRun: Cardinal;
  76. BenchmarkList: TStringList;
  77. procedure IdleHandler(Sender: TObject; var Done: Boolean);
  78. procedure AddLayers(Count: Integer);
  79. end;
  80. var
  81. MainForm: TMainForm;
  82. implementation
  83. {$IFDEF FPC}
  84. {$R *.lfm}
  85. {$ELSE}
  86. {$R *.dfm}
  87. {$ENDIF}
  88. uses
  89. {$IFDEF Darwin}
  90. MacOSAll,
  91. {$ENDIF}
  92. {$IFNDEF FPC}
  93. JPEG,
  94. {$ELSE}
  95. LazJPG,
  96. {$ENDIF}
  97. GR32_Filters, GR32_System;
  98. { TMainForm }
  99. procedure TMainForm.FormCreate(Sender: TObject);
  100. var
  101. TempBitmap: TBitmap32;
  102. begin
  103. TempBitmap := TBitmap32.Create;
  104. try
  105. Image32.Bitmap.LoadFromResourceName(Hinstance, 'SpriteTexture');
  106. BitmapList.Bitmap[0].LoadFromResourceName(Hinstance, 'Sprite1');
  107. TempBitmap.LoadFromResourceName(Hinstance, 'Sprite1a');
  108. IntensityToAlpha(BitmapList.Bitmap[0], TempBitmap);
  109. BitmapList.Bitmap[1].LoadFromResourceName(Hinstance, 'Sprite2');
  110. TempBitmap.LoadFromResourceName(Hinstance, 'Sprite2a');
  111. IntensityToAlpha(BitmapList.Bitmap[1], TempBitmap);
  112. BitmapList.Bitmap[2].LoadFromResourceName(Hinstance, 'Sprite3');
  113. TempBitmap.LoadFromResourceName(Hinstance, 'Sprite3a');
  114. IntensityToAlpha(BitmapList.Bitmap[2], TempBitmap);
  115. finally
  116. TempBitmap.Free;
  117. end;
  118. LastSeed := 0;
  119. BenchmarkList := TStringList.Create;
  120. Application.OnIdle := IdleHandler;
  121. end;
  122. procedure TMainForm.AddLayers(Count: Integer);
  123. var
  124. X: Integer;
  125. ALayer: TBitmapLayer;
  126. L: TFloatRect;
  127. I: Integer;
  128. begin
  129. TimerFPS.Enabled := False;
  130. // make sure, we're creating reproducible randoms...
  131. RandSeed := LastSeed;
  132. Image32.BeginUpdate;
  133. for X := 1 to Count do
  134. begin
  135. // create a new layer...
  136. ALayer := TBitmapLayer.Create(Image32.Layers);
  137. with ALayer do
  138. begin
  139. Bitmap := BitmapList.Bitmaps[System.Random(BitmapList.Bitmaps.Count)].Bitmap;
  140. Bitmap.DrawMode := dmBlend;
  141. Bitmap.MasterAlpha := System.Random(255);
  142. // put it somethere
  143. L.Left := System.Random(Image32.Width);
  144. L.Top := System.Random(Image32.Height);
  145. L.Right := L.Left + Bitmap.Width;
  146. L.Bottom := L.Top + Bitmap.Height;
  147. ALayer.Location := L;
  148. I := Length(Velocities);
  149. SetLength(Velocities, I + 1);
  150. Velocities[I] := FloatPoint(Random - 0.5, Random - 0.5);
  151. end;
  152. end;
  153. Image32.EndUpdate;
  154. Image32.Changed;
  155. EdtLayerCount.Text := IntToStr(Image32.Layers.Count) + ' layers';
  156. // save current seed, so we can continue at this seed later...
  157. LastSeed := RandSeed;
  158. FramesDrawn := 0;
  159. TimerFPS.Enabled := True;
  160. end;
  161. procedure TMainForm.IdleHandler(Sender: TObject; var Done: Boolean);
  162. var
  163. I: Integer;
  164. R: TFloatRect;
  165. begin
  166. if Image32.Layers.Count = 0 then Exit;
  167. Image32.BeginUpdate;
  168. for I := 0 to Image32.Layers.Count - 1 do
  169. begin
  170. with TBitmapLayer(Image32.Layers[I]) do
  171. begin
  172. Bitmap.MasterAlpha := (Bitmap.MasterAlpha + 1) mod 256;
  173. R := Location;
  174. with Velocities[I] do
  175. begin
  176. GR32.OffsetRect(R, X, Y);
  177. X := X + (Random - 0.5) * 0.9;
  178. Y := Y + (Random - 0.5) * 0.9;
  179. if (R.Left < 0) and (X < 0) then X := 1;
  180. if (R.Top < 0) and (Y < 0) then Y := 1;
  181. if (R.Right > Image32.Width) and (X > 0) then X := -1;
  182. if (R.Bottom > Image32.Height) and (Y > 0) then Y := -1;
  183. end;
  184. Location := R;
  185. end;
  186. end;
  187. Image32.EndUpdate;
  188. Image32.Invalidate;
  189. // because we're doing Invalidate in the IdleHandler and Invalidate has
  190. // higher priority, we can count the frames here, because we can be sure that
  191. // the deferred repaint is triggered once this method is exited.
  192. Inc(FramesDrawn);
  193. end;
  194. procedure TMainForm.BtnClearAllClick(Sender: TObject);
  195. begin
  196. Image32.Layers.Clear;
  197. Velocities := nil;
  198. EdtLayerCount.Text := '0 layers';
  199. end;
  200. procedure TMainForm.BtnRemoveClick(Sender: TObject);
  201. var
  202. I: Integer;
  203. begin
  204. for I := Image32.Layers.Count - 1 downto Max(0, Image32.Layers.Count - 10) do
  205. Image32.Layers.Delete(I);
  206. EdtLayerCount.Text := IntToStr(Image32.Layers.Count) + ' layers';
  207. end;
  208. procedure TMainForm.CbxUseRepaintOptClick(Sender: TObject);
  209. begin
  210. if CbxUseRepaintOpt.Checked then
  211. Image32.RepaintMode := rmOptimizer
  212. else
  213. Image32.RepaintMode := rmFull;
  214. end;
  215. procedure TMainForm.TimerFPSTimer(Sender: TObject);
  216. var
  217. TimeElapsed: Cardinal;
  218. Diff: Integer;
  219. FPS: Single;
  220. begin
  221. TimerFPS.Enabled := False;
  222. TimeElapsed := GetTickCount - LastCheck;
  223. FPS := FramesDrawn / (TimeElapsed / 1000);
  224. LblFPS.Caption := Format('%.2f fps', [FPS]);
  225. if BenchmarkMode then
  226. begin
  227. BenchmarkList.Add(Format('%d ' + #9 + '%.2f', [Image32.Layers.Count, FPS]));
  228. Diff := 0; // stop complaining, ye my evil compiler!
  229. if Image32.Layers.Count = 10 then
  230. Diff := 4
  231. else if Image32.Layers.Count = 14 then
  232. Diff := 6
  233. else if Image32.Layers.Count < 100 then
  234. Diff := 10
  235. else if Image32.Layers.Count = 100 then
  236. Diff := 40
  237. else if Image32.Layers.Count = 140 then
  238. Diff := 60
  239. else if Image32.Layers.Count < 1000 then
  240. Diff := 100
  241. else if Image32.Layers.Count < 2000 then
  242. Diff := 500
  243. else if Image32.Layers.Count >= 2000 then
  244. begin
  245. BtnBenchmarkClick(nil);
  246. Exit;
  247. end;
  248. AddLayers(Diff);
  249. end;
  250. FramesDrawn := 0;
  251. LastCheck := GetTickCount;
  252. TimerFPS.Enabled := True;
  253. end;
  254. procedure TMainForm.Image32Resize(Sender: TObject);
  255. begin
  256. LblDimension.Caption := IntToStr(Image32.Width) + ' x ' + IntToStr(Image32.Height);
  257. end;
  258. procedure TMainForm.BtnAddClick(Sender: TObject);
  259. begin
  260. AddLayers(10);
  261. end;
  262. procedure TMainForm.BtnBenchmarkClick(Sender: TObject);
  263. begin
  264. if BenchmarkMode then
  265. begin
  266. SetThreadPriority(GetCurrentThread, Priority);
  267. SetPriorityClass(GetCurrentProcess, PriorityClass);
  268. BtnBenchmark.Caption := 'Benchmark';
  269. CbxUseRepaintOpt.Enabled := True;
  270. BtnAdd.Enabled := True;
  271. BtnRemove.Enabled := True;
  272. BtnClearAll.Enabled := True;
  273. BenchmarkMode := False;
  274. TimerFPS.Interval := 5000;
  275. BenchmarkList.SaveToFile('Results.txt');
  276. end
  277. else if (MessageDlg('Do you really want to start benchmarking? ' +
  278. 'This will take a considerable amount of time.' + #13#10 +
  279. 'Benchmarking runs with a higher task priority. Your system might become unresponsive for several seconds.',
  280. mtConfirmation, [mbYes, mbNo], 0) = mrYes) then
  281. begin
  282. PriorityClass := GetPriorityClass(GetCurrentProcess);
  283. Priority := GetThreadPriority(GetCurrentThread);
  284. SetPriorityClass(GetCurrentProcess, HIGH_PRIORITY_CLASS);
  285. SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL);
  286. BtnBenchmark.Caption := 'Stop';
  287. CbxUseRepaintOpt.Enabled := False;
  288. BtnAdd.Enabled := False;
  289. BtnRemove.Enabled := False;
  290. BtnClearAll.Enabled := False;
  291. BenchmarkMode := True;
  292. BenchmarkList.Clear;
  293. BtnClearAllClick(nil);
  294. AddLayers(10);
  295. LastCheck := GetTickCount;
  296. TimerFPS.Interval := MAX_RUNS * 5000;
  297. end;
  298. end;
  299. procedure TMainForm.FormDestroy(Sender: TObject);
  300. begin
  301. BenchmarkList.Free;
  302. end;
  303. initialization
  304. {$IFDEF COMPILERXE2_UP}
  305. FormatSettings.DecimalSeparator := '.';
  306. {$ELSE}
  307. DecimalSeparator := '.';
  308. {$ENDIF}
  309. end.