hermes_factory.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  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. var
  29. Processor: Integer;
  30. procedure Hermes_Factory_Init;
  31. {$IFDEF I386_ASSEMBLER}
  32. var
  33. res: Integer = 0;
  34. {$ENDIF I386_ASSEMBLER}
  35. begin
  36. Processor := PROC_GENERIC;
  37. {$IFDEF I386_ASSEMBLER}
  38. Processor := Processor or PROC_X86_PENTIUM;{There are no others at the moment}
  39. res := Hermes_X86_CPU;
  40. if (res and $800000) <> 0 then
  41. begin
  42. // Writeln('mmx disabled for debugging');
  43. Processor := Processor or PROC_MMX_PENTIUM;
  44. { Writeln('mmx!');}
  45. end;
  46. {$ENDIF I386_ASSEMBLER}
  47. {$IFDEF X86_64_ASSEMBLER}
  48. Processor := Processor or PROC_X86_64;
  49. {$ENDIF X86_64_ASSEMBLER}
  50. end;
  51. function Hermes_Factory_getClearer(bits: Uint32): PHermesClearer;
  52. begin
  53. { Try different processors in order of priority..
  54. Note that for this to work, an MMX processor has to have both MMX and
  55. X86 flags }
  56. New(Result);
  57. Result^.bits := bits;
  58. {$IFDEF I386_ASSEMBLER}
  59. if (Processor and PROC_MMX_PENTIUM) <> 0 then
  60. case bits of
  61. 32: begin
  62. Result^.func := @ClearMMX_32;
  63. exit;
  64. end;
  65. 24: ;
  66. 16: begin
  67. Result^.func := @ClearMMX_16;
  68. exit;
  69. end;
  70. 8: begin
  71. Result^.func := @ClearMMX_8;
  72. exit;
  73. end;
  74. end;
  75. if (Processor and PROC_X86_PENTIUM) <> 0 then
  76. case bits of
  77. 32: begin
  78. Result^.func := @ClearX86_32;
  79. exit;
  80. end;
  81. 24: ;
  82. 16: begin
  83. Result^.func := @ClearX86_16;
  84. exit;
  85. end;
  86. 8: begin
  87. Result^.func := @ClearX86_8;
  88. exit;
  89. end;
  90. end;
  91. {$ENDIF I386_ASSEMBLER}
  92. case bits of
  93. 32: begin
  94. Result^.func := @ClearP_32;
  95. exit;
  96. end;
  97. 24: begin
  98. Result^.func := @ClearP_24;
  99. exit;
  100. end;
  101. 16: begin
  102. Result^.func := @ClearP_16;
  103. exit;
  104. end;
  105. 8: begin
  106. Result^.func := @ClearP_8;
  107. exit;
  108. end;
  109. else
  110. begin
  111. Dispose(Result);
  112. Result := nil;
  113. end;
  114. end;
  115. end;
  116. function Hermes_Factory_getConverter(source, dest: PHermesFormat): PHermesConverter;
  117. var
  118. i: Integer;
  119. found: Boolean;
  120. begin
  121. found := False;
  122. New(Result);
  123. { Set all conversion routines to nil }
  124. Result^.loopnormal := nil;
  125. Result^.loopstretch := nil;
  126. Result^.normal := nil;
  127. Result^.stretch := nil;
  128. Result^.dither := nil;
  129. Result^.ditherstretch := nil;
  130. Result^.flags := 0;
  131. if source^.indexed then
  132. { for 8 bit indexed, just look at the destination bit depth and check
  133. if the converter's processor is a subset of our processor }
  134. for i := 0 to Factory_NumConverters - 1 do
  135. if (Factory_Converters[i].d_bits = dest^.bits) and
  136. (Factory_Converters[i].s_idx and
  137. ((processor and Factory_Converters[i].processor) <> 0)) then
  138. begin
  139. { if any routines are unassigned, assign them now }
  140. if Result^.loopnormal = nil then
  141. begin
  142. Result^.loopnormal := Factory_Converters[i].loopnormal;
  143. found := True;
  144. end;
  145. if Result^.normal = nil then
  146. begin
  147. Result^.normal := Factory_Converters[i].normal;
  148. found := True;
  149. end;
  150. if Result^.loopstretch = nil then
  151. begin
  152. Result^.loopstretch := Factory_Converters[i].loopstretch;
  153. found := True;
  154. end;
  155. if Result^.stretch = nil then
  156. begin
  157. Result^.stretch := Factory_Converters[i].stretch;
  158. found := True;
  159. end;
  160. end else
  161. else
  162. { Otherwise we need to compare everything, including bitmasks }
  163. for i := 0 to Factory_NumConverters - 1 do
  164. if (Factory_Converters[i].d_bits = dest^.bits) and
  165. (Factory_Converters[i].d_r = dest^.r) and
  166. (Factory_Converters[i].d_g = dest^.g) and
  167. (Factory_Converters[i].d_b = dest^.b) and
  168. (Factory_Converters[i].d_a = dest^.a) and
  169. (Factory_Converters[i].d_idx = dest^.indexed) and
  170. (Factory_Converters[i].s_bits = source^.bits) and
  171. (Factory_Converters[i].s_r = source^.r) and
  172. (Factory_Converters[i].s_g = source^.g) and
  173. (Factory_Converters[i].s_b = source^.b) and
  174. (Factory_Converters[i].s_a = source^.a) and
  175. (Factory_Converters[i].s_idx = source^.indexed) and
  176. ((processor and Factory_Converters[i].processor) <> 0) then
  177. begin
  178. { if any routines are unassigned, assign them now }
  179. if (Result^.loopnormal = nil) and
  180. (Factory_Converters[i].loopnormal <> nil) then
  181. begin
  182. Result^.loopnormal := Factory_Converters[i].loopnormal;
  183. found := True;
  184. end;
  185. if (Result^.normal = nil) and
  186. (Factory_Converters[i].normal <> nil) then
  187. begin
  188. Result^.normal := Factory_Converters[i].normal;
  189. found := True;
  190. end;
  191. if (Result^.loopstretch = nil) and
  192. (Factory_Converters[i].loopstretch <> nil) then
  193. begin
  194. Result^.loopstretch := Factory_Converters[i].loopstretch;
  195. found := True;
  196. end;
  197. if (Result^.stretch = nil) and
  198. (Factory_Converters[i].stretch <> nil) then
  199. begin
  200. Result^.stretch := Factory_Converters[i].stretch;
  201. found := True;
  202. end;
  203. if (Result^.dither = nil) and
  204. (Factory_Converters[i].dither <> nil) then
  205. begin
  206. Result^.dither := Factory_Converters[i].dither;
  207. found := True;
  208. end;
  209. if (Result^.ditherstretch = nil) and
  210. (Factory_Converters[i].ditherstretch <> nil) then
  211. begin
  212. Result^.ditherstretch := Factory_Converters[i].ditherstretch;
  213. found := True;
  214. end;
  215. { In the rare event of having everything assigned, pull the emergency
  216. break. Otherwise we need to continue looking (might be stretching
  217. routines somewhere :)
  218. do I sound like a stewardess? }
  219. if (Result^.loopnormal <> nil) and (Result^.normal <> nil) and
  220. (Result^.loopstretch <> nil) and (Result^.stretch <> nil) and
  221. (Result^.dither <> nil) and (Result^.ditherstretch <> nil) then
  222. break;
  223. end;
  224. if found then
  225. begin
  226. Hermes_FormatCopy(source, @Result^.source);
  227. Hermes_FormatCopy(dest, @Result^.dest);
  228. end
  229. else
  230. begin
  231. Dispose(Result);
  232. Result := nil;
  233. end;
  234. end;
  235. function Hermes_Factory_getEqualConverter(bits: Integer): PHermesConverter;
  236. var
  237. found: Boolean;
  238. {$IFDEF I386_ASSEMBLER}
  239. asm_found: Integer;
  240. {$ENDIF I386_ASSEMBLER}
  241. c_found: Integer;
  242. begin
  243. found := False;
  244. New(Result);
  245. { Set all conversion routines to null }
  246. Result^.loopnormal := nil;
  247. Result^.loopstretch := nil;
  248. Result^.normal := nil;
  249. Result^.stretch := nil;
  250. Result^.dither := nil;
  251. Result^.ditherstretch := nil;
  252. {$IFDEF I386_ASSEMBLER}
  253. { Try MMX routines }
  254. if (Result^.loopnormal = nil) or (Result^.normal = nil) or
  255. (Result^.loopstretch = nil) or (Result^.stretch = nil) then
  256. if (processor and PROC_MMX_PENTIUM) <> 0 then
  257. { case bits of
  258. end};
  259. { Try X86 routines }
  260. if (Result^.loopnormal = nil) or (Result^.normal = nil) or
  261. (Result^.loopstretch = nil) or (Result^.stretch = nil) then
  262. if (processor and PROC_X86_PENTIUM) <> 0 then
  263. begin
  264. asm_found := 0;
  265. case bits of
  266. 32: begin
  267. Result^.normal := @CopyX86p_4byte; asm_found := 1;
  268. end;
  269. 24: ;
  270. 16: begin
  271. Result^.normal := @CopyX86p_2byte; asm_found := 1;
  272. end;
  273. 8: begin
  274. Result^.normal := @CopyX86p_1byte; asm_found := 1;
  275. end;
  276. end;
  277. if (asm_found and 1) <> 0 then
  278. begin
  279. Result^.loopnormal := @ConvertX86;
  280. found := True;
  281. end;
  282. end;
  283. {$ENDIF I386_ASSEMBLER}
  284. if (Result^.loopnormal = nil) or (Result^.normal = nil) or
  285. (Result^.loopstretch = nil) or (Result^.stretch = nil) then
  286. begin
  287. c_found := 0;
  288. case bits of
  289. 32: begin
  290. if Result^.normal = nil then
  291. begin
  292. Result^.normal := @CopyP_4byte; c_found := c_found or 1;
  293. end;
  294. if Result^.stretch = nil then
  295. begin
  296. Result^.stretch := @CopyP_4byte_S; c_found := c_found or 2;
  297. end;
  298. end;
  299. 24: begin
  300. if Result^.normal = nil then
  301. begin
  302. Result^.normal := @CopyP_3byte; c_found := c_found or 1;
  303. end;
  304. if Result^.stretch = nil then
  305. begin
  306. Result^.stretch := @CopyP_3byte_S; c_found := c_found or 2;
  307. end;
  308. end;
  309. 16: begin
  310. if Result^.normal = nil then
  311. begin
  312. Result^.normal := @CopyP_2byte; c_found := c_found or 1;
  313. end;
  314. if Result^.stretch = nil then
  315. begin
  316. Result^.stretch := @CopyP_2byte_S; c_found := c_found or 2;
  317. end;
  318. end;
  319. 8: begin
  320. if Result^.normal = nil then
  321. begin
  322. Result^.normal := @CopyP_1byte; c_found := c_found or 1;
  323. end;
  324. if Result^.stretch = nil then
  325. begin
  326. Result^.stretch := @CopyP_1byte_S; c_found := c_found or 2;
  327. end;
  328. end;
  329. end;
  330. if (c_found and 1) <> 0 then
  331. begin
  332. Result^.loopnormal := @ConvertP; found := True;
  333. end;
  334. if (c_found and 2) <> 0 then
  335. begin
  336. Result^.loopstretch := @ConvertPStretch; found := True;
  337. end;
  338. end;
  339. if not found then
  340. begin
  341. Dispose(Result);
  342. Result := nil;
  343. end;
  344. end;