hermes.pp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. {
  2. Free Pascal port of the Hermes C library.
  3. Copyright (C) 2001-2003 Nikolay Nikolov ([email protected])
  4. Original C version by Christian Nentwich ([email protected])
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version
  9. with the following modification:
  10. As a special exception, the copyright holders of this library give you
  11. permission to link this library with independent modules to produce an
  12. executable, regardless of the license terms of these independent modules,and
  13. to copy and distribute the resulting executable under terms of your choice,
  14. provided that you also meet, for each linked independent module, the terms
  15. and conditions of the license of that module. An independent module is a
  16. module which is not derived from or based on this library. If you modify
  17. this library, you may extend this exception to your version of the library,
  18. but you are not obligated to do so. If you do not wish to do so, delete this
  19. exception statement from your version.
  20. This library is distributed in the hope that it will be useful,
  21. but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  23. Lesser General Public License for more details.
  24. You should have received a copy of the GNU Lesser General Public
  25. License along with this library; if not, write to the Free Software
  26. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  27. }
  28. {$IFNDEF FPC_DOTTEDUNITS}
  29. unit Hermes;
  30. {$ENDIF FPC_DOTTEDUNITS}
  31. {$MODE objfpc}
  32. {$if defined(darwin) and defined(cpui386)}
  33. { darwin/i386 requires a 16 byte aligned stack, and inserts code for that on
  34. entry in assembler routines (unless they are declared with "nostackframe").
  35. These assembler routines manually create their own stack frame and hardcode
  36. parameter offsets without using nostackframe, so they can never work on
  37. Darwin.
  38. }
  39. {$define noassembler}
  40. {$endif}
  41. {$IF defined(cpui386) and not defined(noassembler)}
  42. {$IF defined(linux) or defined(win32) or defined(go32v2) or defined(freebsd) or defined(haiku) or defined(beos)}
  43. {$DEFINE I386_ASSEMBLER}
  44. {$ENDIF}
  45. {$ENDIF}
  46. {$IF defined(cpux86_64) and not defined(noassembler)}
  47. {$DEFINE X86_64_ASSEMBLER}
  48. {$ENDIF}
  49. interface
  50. {$IF defined(cpui386) and defined(FPC_PIC)}
  51. { FPC_PIC is only set after parsing _INTERFFACE keyword
  52. so we need to delay the test to here }
  53. { the i386 assembler code is not prepared for PIC code }
  54. {$DEFINE noassembler}
  55. { Thus, disable assembler code in that case for now }
  56. {$UNDEF I386_ASSEMBLER}
  57. {$ENDIF}
  58. const
  59. HERMES_CONVERT_NORMAL = 0;
  60. HERMES_CONVERT_DITHER = 1;
  61. type
  62. THermesConverterHandle = Pointer;
  63. THermesPaletteHandle = Pointer;
  64. THermesClearerHandle = Pointer;
  65. PUint8 = ^Uint8;
  66. PUint16 = ^Uint16;
  67. PUint32 = ^Uint32;
  68. PUint64 = ^Uint64;
  69. PSint8 = ^Sint8;
  70. PSint16 = ^Sint16;
  71. PSint32 = ^Sint32;
  72. PSint64 = ^Sint64;
  73. Uint8 = Byte;
  74. Uint16 = Word;
  75. Uint32 = DWord;
  76. Uint64 = QWord;
  77. Sint8 = ShortInt;
  78. Sint16 = SmallInt;
  79. Sint32 = LongInt;
  80. Sint64 = Int64;
  81. PHermesFormat = ^THermesFormat;
  82. THermesFormat = record
  83. r,g,b,a: Uint32;
  84. bits: Integer;
  85. indexed: Boolean;
  86. has_colorkey: Boolean;
  87. colorkey: Uint32;
  88. end;
  89. function Hermes_FormatNewEmpty: PHermesFormat;
  90. { Create a new format structure, returns nil if failed. }
  91. function Hermes_FormatNew(bits: Integer; r, g, b, a: Uint32;
  92. indexed: Boolean): PHermesFormat;
  93. { Free a format structure }
  94. procedure Hermes_FormatFree(fmt: PHermesFormat);
  95. { Create a new format structure with colorkey info, returns nil if failed. }
  96. function Hermes_FormatNewEx(bits: Integer; r, g, b, a: Uint32;
  97. indexed, has_colorkey: Boolean;
  98. colorkey: Uint32): PHermesFormat;
  99. { Compare two formats. Return true if they are equal, false otherwise }
  100. function Hermes_FormatEquals(op1, op2: PHermesFormat): Boolean;
  101. { Copy the contents of format 'source' to format 'destination' }
  102. procedure Hermes_FormatCopy(source, dest: PHermesFormat);
  103. {
  104. Get a converter to work with, specifying a combination of the flags
  105. above. Returns nil if unsuccessful.
  106. }
  107. function Hermes_ConverterInstance(flags: DWord): THermesConverterHandle;
  108. {
  109. Return a converter if it is not needed anymore, thus releasing some
  110. memory.
  111. }
  112. procedure Hermes_ConverterReturn(handle: THermesConverterHandle);
  113. {
  114. Request a format conversion between two formats. This function returns false
  115. if the conversion cannot be provided (which should not occur too often :)
  116. Repeated calls to this function will be cached an terminate almost
  117. immediately, so don't be ashamed of calling it often.
  118. }
  119. function Hermes_ConverterRequest(handle: THermesConverterHandle;
  120. source, dest: PHermesFormat): Boolean;
  121. {
  122. Set the palette of the source surface / destination surface for a
  123. subsequent conversion. At the moment, only sourcepal is used.
  124. Returns false if unsuccessful (invalid handle!).
  125. }
  126. function Hermes_ConverterPalette(handle: THermesConverterHandle; sourcepal, destpal: THermesPaletteHandle): Boolean;
  127. {
  128. do a format conversion after calling the setup routines above. This will
  129. convert (or copy) the pixel data from s_pixels to the data in d_pixels.
  130. Both source and destination areas/origins can be specified as well as
  131. the scanline width in bytes of the source/destination.
  132. Returns false if unsuccessful (invalid handle or request not called before).
  133. }
  134. function Hermes_ConverterCopy(handle: THermesConverterHandle; s_pixels: Pointer;
  135. s_x, s_y, s_width, s_height, s_pitch: Integer;
  136. d_pixels: Pointer; d_x, d_y, d_width,
  137. d_height, d_pitch: Integer): Boolean;
  138. (*
  139. {-----------------H_BLIT---------------}
  140. {
  141. Get a blitter to work with, specifying a combination of the flags
  142. in H_Conv. Returns 0 if unsuccessful.
  143. }
  144. function Hermes_BlitterInstance(flags: DWord): THermesHandle;
  145. {
  146. Return a blitter if it is not needed anymore, thus releasing some
  147. memory.
  148. }
  149. procedure Hermes_BlitterReturn(handle: THermesHandle);
  150. {
  151. Request a format blitting between two formats. This function returns false
  152. if the blitting cannot be provided (which should not occur too often :)
  153. Repeated calls to this function will be cached an terminate almost
  154. immediately, so don't be ashamed of calling it often.
  155. }
  156. function Hermes_BlitterRequest(handle: THermesHandle;
  157. source, dest: PHermesFormat): Boolean;
  158. {
  159. Set the palette of the source surface / destination surface for a
  160. subsequent blitting. At the moment, only sourcepal is used.
  161. Returns false if unsuccessful (invalid handle!).
  162. }
  163. function Hermes_BlitterPalette(handle, sourcepal, destpal: THermesHandle): Boolean;
  164. {
  165. do a format blitting after calling the setup routines above. This will
  166. blit the pixel data from s_pixels to the data in d_pixels. Both source
  167. and destination areas/origins can be specified as well as the scanline
  168. width in bytes of the source/destination. Returns false if unsuccessful
  169. (invalid handle or request not called before).
  170. }
  171. function Hermes_BlitterBlit(handle: THermesHandle; s_pixels: Pointer;
  172. s_x, s_y, s_width, s_height, s_pitch: Integer;
  173. d_pixels: Pointer; d_x, d_y, d_width, d_height,
  174. d_pitch: Integer): Boolean;
  175. *)
  176. {-----------------H_PAL---------------}
  177. { Get a handle for a palette to work with. This allocates memory for an
  178. internal palette. Returns nil if failed.
  179. }
  180. function Hermes_PaletteInstance: THermesPaletteHandle;
  181. {
  182. Return a handle for a palette if the palette isn't used anymore. The
  183. internal palette will be deallocated.
  184. }
  185. procedure Hermes_PaletteReturn(handle: THermesPaletteHandle);
  186. {
  187. Copy the contents of the palette parameter provided into the internal
  188. palette. The user palette has to be 256*4 bytes long.
  189. }
  190. procedure Hermes_PaletteSet(handle: THermesPaletteHandle; palette: Pointer);
  191. {
  192. Return the pointer to the internal palette. The palette is 256*4 bytes
  193. long.
  194. }
  195. function Hermes_PaletteGet(handle: THermesPaletteHandle): Pointer;
  196. {
  197. Force invalidation of the palette cache. This will force lookup tables to
  198. be regenerated and has to be done manually after PaletteGet has been used
  199. and the data has been modified without the knowledge of Hermes.
  200. }
  201. procedure Hermes_PaletteInvalidateCache(handle: THermesPaletteHandle);
  202. {-----------------H_CLEAR---------------}
  203. {
  204. Get a handle for a new clearer instance to work with. Returns nil if failed.
  205. }
  206. function Hermes_ClearerInstance: THermesClearerHandle;
  207. {
  208. Return the clearer instance if it is no longer needed.
  209. }
  210. procedure Hermes_ClearerReturn(handle: THermesClearerHandle);
  211. {
  212. Request the clearing routines to be set up for clearing to a specific
  213. format later. Repeated calls to the routine will be cached and terminate
  214. after a short check.
  215. }
  216. function Hermes_ClearerRequest(handle: THermesClearerHandle; format: PHermesFormat): Boolean;
  217. {
  218. Clear a surface. pixels points to the pixel data, x1, y1, width, height
  219. specify the area to clear, pitch is the width of a scanline in bytes,
  220. the rest are the colour components.
  221. }
  222. function Hermes_ClearerClear(handle: THermesClearerHandle; pixels: Pointer;
  223. x1, y1, width, height, pitch: Integer;
  224. r, g, b: Uint32; index: Uint8): Boolean;
  225. { Initialise Hermes, returns false if failed }
  226. function Hermes_Init: Boolean;
  227. { Deinitialise Hermes, returns false if failed }
  228. function Hermes_Done: Boolean;
  229. implementation
  230. {$I hermdef.inc}
  231. const
  232. PROC_GENERIC = 1;
  233. PROC_X86_PENTIUM = 2;
  234. PROC_MMX_PENTIUM = 4;
  235. PROC_SSE2 = 8;
  236. PROC_X86_64 = 16;
  237. HERMES_CONVERT_GENERIC = 65536;
  238. {$I hermconf.inc}
  239. type
  240. THermesHandle = Integer;
  241. PHermesClearInterface = ^THermesClearInterface;
  242. THermesClearInterface = record
  243. dest: ^Uint8;
  244. value: Uint32;
  245. width, height: Integer;
  246. add: Integer;
  247. end;
  248. THermesClearPtr = procedure(hci: PHermesClearInterface); cdecl;
  249. PHermesClearer = ^THermesClearer;
  250. THermesClearer = record
  251. bits: Integer;
  252. func: THermesClearPtr;
  253. end;
  254. { Structure to hold shift amounts for the generic routines }
  255. PHermesGenericInfo = ^THermesGenericInfo;
  256. THermesGenericInfo = record
  257. r_right, g_right, b_right, a_right: Integer; {Shift amount to the right}
  258. r_left, g_left, b_left, a_left: Integer; {Shift amount to the right}
  259. end;
  260. { Pointer to specialised (one-scanline-only) conversion procedure }
  261. THermesConverterPtr = procedure(source, dest: PUint8;
  262. count, inc_source: DWord); cdecl;
  263. { Structure for conversion loop routines, don't be scared, size does NOT
  264. matter in this case :) }
  265. PHermesConverterInterface = ^THermesConverterInterface;
  266. THermesConverterInterface = record
  267. s_pixels: PUint8;
  268. s_width,s_height: Integer;
  269. s_add: Integer; { Offset to next line from end of line }
  270. d_pixels: PUint8;
  271. d_width,d_height: Integer;
  272. d_add: Integer;
  273. func: THermesConverterPtr;
  274. lookup: PUint32; { Palette lookup table ptr, for 8 bit }
  275. s_pitch: Integer; { Source and destination pitch, }
  276. d_pitch: Integer; { only used by C routines }
  277. info: THermesGenericInfo; { Only used by generic converters }
  278. mask_r, mask_g, mask_b, mask_a: Uint32; { Only used by generic converters }
  279. s_mask_a: Uint32;
  280. s_has_colorkey: Boolean;
  281. s_colorkey: Uint32;
  282. d_has_colorkey: Boolean;
  283. d_colorkey: Uint32;
  284. end;
  285. { Pointer to loop function (C, assembler main loop, generic routines) }
  286. THermesConverterLoopPtr = procedure(hci: PHermesConverterInterface); cdecl;
  287. PHermesConverter = ^THermesConverter;
  288. THermesConverter = record
  289. source,dest: THermesFormat; { Source and destination format }
  290. lookup: PUint32; { Pointer to lookup table (8bit) }
  291. flags: DWord; { Defined in H_Conv.h, DITHER,etc}
  292. loopnormal: THermesConverterLoopPtr; { Loop routine for normal conv. }
  293. loopstretch: THermesConverterLoopPtr;
  294. normal: THermesConverterPtr; { One-scanline routine }
  295. stretch: THermesConverterPtr;
  296. dither: THermesConverterLoopPtr; { Dithering routines always }
  297. ditherstretch: THermesConverterLoopPtr; { convert the whole buffer }
  298. end;
  299. PHermesFactoryStruct = ^THermesFactoryStruct;
  300. THermesFactoryStruct = record
  301. s_bits: Integer;
  302. s_idx: Boolean;
  303. s_r, s_g, s_b, s_a: Uint32;
  304. d_bits: Integer;
  305. d_idx: Boolean;
  306. d_r, d_g, d_b, d_a: Uint32;
  307. loopnormal, loopstretch: THermesConverterLoopPtr;
  308. normal, stretch: THermesConverterPtr;
  309. dither, ditherstretch: THermesConverterLoopPtr;
  310. processor: Integer;
  311. end;
  312. {dither types ?}
  313. const
  314. { p_converters holds a list of formats, for conversion from 32 bit, 24 bit,
  315. 16 bit, muhmu and 8 bit.
  316. The destination formats are listed in the order of frequency they might
  317. occur so common formats can be retrieved faster.
  318. Format of a row:
  319. source bpp, s. indexed, s. r_mask, s. g_mask, s. b_mask, s. alpha ,dest bpp,
  320. d.indexed, d. r_mask, d. g_mask, d. b_mask, d. alpha
  321. }
  322. { I wish I could touch this, but it's used in too many other placed in the code,
  323. ( at least indirectly), and many of the indicies are hardcoded }
  324. p_converters: array [0..4, 0..11, 0..11] of DWord =
  325. (
  326. ( {From 32 bit RGB 888}
  327. (32,0,$ff0000,$ff00,$ff,0,16,0,$f800,$7e0,$1f,0), {16RGB565 }
  328. (32,0,$ff0000,$ff00,$ff,0, 8,0,$e0,$1c,$3,0), { 8RGB332 }
  329. (32,0,$ff0000,$ff00,$ff,0,16,0,$7c00,$3e0,$1f,0), { 16RGB555 }
  330. (32,0,$ff0000,$ff00,$ff,0,24,0,$ff0000,$ff00,$ff,0), { 24RGB888 }
  331. (32,0,$ff0000,$ff00,$ff,0,32,0,$ff,$ff00,$ff0000,0), { 32BGR888 }
  332. (32,0,$ff0000,$ff00,$ff,0,16,0,$1f,$7e0,$f800,0), { 16BGR565 }
  333. (32,0,$ff0000,$ff00,$ff,0,16,0,$1f,$3e0,$7c00,0), { 16BGR555 }
  334. (32,0,$ff0000,$ff00,$ff,0,32,0,$ff000000,$ff0000,$ff00,$ff), { 32RGBA888 }
  335. (32,0,$ff0000,$ff00,$ff,0,32,0,$ff00,$ff0000,$ff000000,$ff), { 32BGRA888 }
  336. (32,0,$ff0000,$ff00,$ff,0,24,0,$ff,$ff00,$ff0000,0), { 24BGR888 }
  337. (0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0)
  338. )
  339. ,
  340. ( {From 24 bit RGB 888}
  341. (24,0,$ff0000,$ff00,$ff,0,32,0,$ff0000,$ff00,$ff,0), { 32RGB888 }
  342. (24,0,$ff0000,$ff00,$ff,0,16,0,$f800,$7e0,$1f,0), { 16RGB565 }
  343. (24,0,$ff0000,$ff00,$ff,0, 8,0,$e0,$1c,$3,0), { 8RGB332 }
  344. (24,0,$ff0000,$ff00,$ff,0,16,0,$7c00,$3e0,$1f,0), { 16RGB555 }
  345. (24,0,$ff0000,$ff00,$ff,0,32,0,$ff,$ff00,$ff0000,0), { 32BGR888 }
  346. (24,0,$ff0000,$ff00,$ff,0,16,0,$1f,$7e0,$f800,0), { 16BGR565 }
  347. (24,0,$ff0000,$ff00,$ff,0,16,0,$1f,$3e0,$7c00,0), { 16BGR555 }
  348. (24,0,$ff0000,$ff00,$ff,0,32,0,$ff000000,$ff0000,$ff00,$ff), { 32RGBA888 }
  349. (24,0,$ff0000,$ff00,$ff,0,32,0,$ff00,$ff0000,$ff000000,$ff), { 32BGRA888 }
  350. (24,0,$ff0000,$ff00,$ff,0,24,0,$ff,$ff00,$ff0000,0), { 24BGR888 }
  351. (0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0)
  352. )
  353. ,
  354. ( {From 16 bit RGB 565}
  355. (16,0,$f800,$7e0,$1f,0,32,0,$ff0000,$ff00,$ff,0), { 32RGB888 }
  356. (16,0,$f800,$7e0,$1f,0, 8,0,$e0,$1c,$3,0), { 8RGB332 }
  357. (16,0,$f800,$7e0,$1f,0,16,0,$7c00,$3e0,$1f,0), { 16RGB555 }
  358. (16,0,$f800,$7e0,$1f,0,24,0,$ff0000,$ff00,$ff,0), { 24RGB888 }
  359. (16,0,$f800,$7e0,$1f,0,32,0,$ff,$ff00,$ff0000,0), { 32BGR888 }
  360. (16,0,$f800,$7e0,$1f,0,16,0,$1f,$7e0,$f800,0), { 16BGR565 }
  361. (16,0,$f800,$7e0,$1f,0,16,0,$1f,$3e0,$7c00,0), { 16BGR555 }
  362. (16,0,$f800,$7e0,$1f,0,32,0,$ff000000,$ff0000,$ff00,$ff), { 32RGBA888 }
  363. (16,0,$f800,$7e0,$1f,0,32,0,$ff00,$ff0000,$ff000000,$ff), { 32BGRA888 }
  364. (16,0,$f800,$7e0,$1f,0,24,0,$ff,$ff00,$ff0000,0), { 24BGR888 }
  365. (0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0)
  366. ),
  367. ( {From 32 bit muhmu}
  368. (32,0,$ff00000,$3fc00,$ff,0,32,0,$ff0000,$ff00,$ff,0), { 32RGB888 }
  369. (32,0,$ff00000,$3fc00,$ff,0,16,0,$f800,$7e0,$1f,0), { 16RGB565 }
  370. (32,0,$ff00000,$3fc00,$ff,0, 8,0,$e0,$1c,$3,0), { 8RGB332 }
  371. (32,0,$ff00000,$3fc00,$ff,0,16,0,$7c00,$3e0,$1f,0), { 16RGB555 }
  372. (32,0,$ff00000,$3fc00,$ff,0,24,0,$ff0000,$ff00,$ff,0), { 24RGB888 }
  373. (32,0,$ff00000,$3fc00,$ff,0,32,0,$ff,$ff00,$ff0000,0), { 32BGR888 }
  374. (32,0,$ff00000,$3fc00,$ff,0,16,0,$1f,$7e0,$f800,0), { 16BGR565 }
  375. (32,0,$ff00000,$3fc00,$ff,0,16,0,$1f,$3e0,$7c00,0), { 16BGR555 }
  376. (32,0,$ff00000,$3fc00,$ff,0,32,0,$ff000000,$ff0000,$ff00,$ff), { 32RGBA888 }
  377. (32,0,$ff00000,$3fc00,$ff,0,32,0,$ff00,$ff0000,$ff000000,$ff), { 32BGRA888 }
  378. (32,0,$ff00000,$3fc00,$ff,0,24,0,$ff,$ff00,$ff0000,0), { 24BGR888 }
  379. (0,0,0,0,0,0,0,0,0,0,0,0)
  380. ),
  381. ( {From 8 bit indexed}
  382. (8,1,0,0,0,0,32,0,0,0,0,0),
  383. (8,1,0,0,0,0,24,0,0,0,0,0),
  384. (8,1,0,0,0,0,16,0,0,0,0,0),
  385. (8,1,0,0,0,0,8,0,0,0,0,0),
  386. (0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0),
  387. (0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0),
  388. (0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0),
  389. (0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0)
  390. )
  391. );
  392. numConverters: array [0..4] of Integer = (10,10,10,11,4);
  393. refcount: Integer = 0;
  394. var
  395. Clearers: array [0..3] of PHermesClearer;
  396. numClearers: Integer;
  397. standardConverters: array [0..4] of ^PHermesConverter;
  398. equalConverters: array [0..3] of PHermesConverter;
  399. {$I hermes_debug.inc}
  400. {$I hermes_dither.inc}
  401. {$I headp.inc}
  402. {$IFDEF I386_ASSEMBLER}
  403. {$I i386/headi386.inc}
  404. {$I i386/headmmx.inc}
  405. {$ENDIF I386_ASSEMBLER}
  406. {$IFDEF X86_64_ASSEMBLER}
  407. {$I x86_64/headx86_64.inc}
  408. {$ENDIF X86_64_ASSEMBLER}
  409. {$I factconv.inc}
  410. {$I hermes_list.inc}
  411. {$I hermes_utility.inc}
  412. {$I hermes_format.inc}
  413. {$I hermes_palette.inc}
  414. {$I hermes_converter.inc}
  415. {$I hermes_clearer.inc}
  416. {$I hermes_factory.inc}
  417. function Hermes_Init: Boolean;
  418. var
  419. i, j: Integer;
  420. source, dest: THermesFormat;
  421. begin
  422. if refcount > 0 then
  423. begin
  424. Inc(refcount);
  425. Result := True;
  426. exit;
  427. end;
  428. { Initialise hermes factory }
  429. Hermes_Factory_Init;
  430. { Instruct the factory to return clearing routines }
  431. Clearers[0] := Hermes_Factory_getClearer(32);
  432. Clearers[1] := Hermes_Factory_getClearer(24);
  433. Clearers[2] := Hermes_Factory_getClearer(16);
  434. Clearers[3] := Hermes_Factory_getClearer(8);
  435. numClearers := 4;
  436. { Use factory to obtain specialised converters }
  437. for j := 0 to 4 do
  438. begin
  439. standardConverters[j] := GetMem(SizeOf(PHermesConverter)*numConverters[j]);
  440. for i := 0 to numConverters[j] - 1 do
  441. begin
  442. // xxx jm color keys not taken into consideration here
  443. FillChar(source, SizeOf(source), 0);
  444. FillChar(dest, SizeOf(dest), 0);
  445. source.bits := p_converters[j, i, 0]; dest.bits := p_converters[j, i, 6];
  446. source.indexed:= p_converters[j,i,1]<>0; dest.indexed:= p_converters[j,i,7]<>0;
  447. source.r := p_converters[j, i, 2]; dest.r := p_converters[j, i, 8];
  448. source.g := p_converters[j, i, 3]; dest.g := p_converters[j, i, 9];
  449. source.b := p_converters[j, i, 4]; dest.b := p_converters[j, i, 10];
  450. source.a := p_converters[j, i, 5]; dest.a := p_converters[j, i, 11];
  451. standardConverters[j][i] := Hermes_Factory_getConverter(@source, @dest);
  452. end;
  453. end;
  454. { Set up converters for equal colour formats }
  455. equalConverters[3] := Hermes_Factory_getEqualConverter(32);
  456. equalConverters[2] := Hermes_Factory_getEqualConverter(24);
  457. equalConverters[1] := Hermes_Factory_getEqualConverter(16);
  458. equalConverters[0] := Hermes_Factory_getEqualConverter(8);
  459. { Initialise dithering tables }
  460. Dither_SetupMatrices;
  461. Inc(refcount);
  462. Result := True;
  463. end;
  464. function Hermes_Done: Boolean;
  465. var
  466. i, j: Integer;
  467. begin
  468. Dec(refcount);
  469. if refcount < 0 then
  470. begin
  471. refcount := 0;
  472. Result := False;
  473. exit;
  474. end;
  475. if refcount = 0 then
  476. begin
  477. for i := 0 to 3 do
  478. begin
  479. if Clearers[i] <> nil then
  480. begin
  481. Dispose(Clearers[i]);
  482. Clearers[i] := nil;
  483. end;
  484. if equalConverters[i] <> nil then
  485. begin
  486. Dispose(equalConverters[i]);
  487. equalConverters[i] := nil;
  488. end;
  489. end;
  490. for i := 0 to 4 do
  491. begin
  492. if standardConverters[i] <> nil then
  493. begin
  494. for j := 0 to numConverters[i] - 1 do
  495. Dispose(standardConverters[i][j]);
  496. FreeMem(standardConverters[i]);
  497. standardConverters[i] := nil;
  498. end;
  499. end;
  500. end;
  501. Result := True;
  502. end;
  503. begin
  504. DebugInit;
  505. end.