sdlgenblit.pl 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. #!/usr/bin/perl -w
  2. #
  3. # A script to generate optimized C blitters for Simple DirectMedia Layer
  4. # http://www.libsdl.org/
  5. use warnings;
  6. use strict;
  7. my %file;
  8. # The formats potentially supported by this script:
  9. # SDL_PIXELFORMAT_RGB332
  10. # SDL_PIXELFORMAT_RGB444
  11. # SDL_PIXELFORMAT_RGB555
  12. # SDL_PIXELFORMAT_ARGB4444
  13. # SDL_PIXELFORMAT_ARGB1555
  14. # SDL_PIXELFORMAT_RGB565
  15. # SDL_PIXELFORMAT_RGB24
  16. # SDL_PIXELFORMAT_BGR24
  17. # SDL_PIXELFORMAT_RGB888
  18. # SDL_PIXELFORMAT_BGR888
  19. # SDL_PIXELFORMAT_ARGB8888
  20. # SDL_PIXELFORMAT_RGBA8888
  21. # SDL_PIXELFORMAT_ABGR8888
  22. # SDL_PIXELFORMAT_BGRA8888
  23. # SDL_PIXELFORMAT_ARGB2101010
  24. # The formats we're actually creating blitters for:
  25. my @src_formats = (
  26. "RGB888",
  27. "BGR888",
  28. "ARGB8888",
  29. "RGBA8888",
  30. "ABGR8888",
  31. "BGRA8888",
  32. );
  33. my @dst_formats = (
  34. "RGB888",
  35. "BGR888",
  36. "ARGB8888",
  37. );
  38. my %format_size = (
  39. "RGB888" => 4,
  40. "BGR888" => 4,
  41. "ARGB8888" => 4,
  42. "RGBA8888" => 4,
  43. "ABGR8888" => 4,
  44. "BGRA8888" => 4,
  45. );
  46. my %format_type = (
  47. "RGB888" => "Uint32",
  48. "BGR888" => "Uint32",
  49. "ARGB8888" => "Uint32",
  50. "RGBA8888" => "Uint32",
  51. "ABGR8888" => "Uint32",
  52. "BGRA8888" => "Uint32",
  53. );
  54. my %get_rgba_string_ignore_alpha = (
  55. "RGB888" => "_R = (Uint8)(_pixel >> 16); _G = (Uint8)(_pixel >> 8); _B = (Uint8)_pixel;",
  56. "BGR888" => "_B = (Uint8)(_pixel >> 16); _G = (Uint8)(_pixel >> 8); _R = (Uint8)_pixel;",
  57. "ARGB8888" => "_R = (Uint8)(_pixel >> 16); _G = (Uint8)(_pixel >> 8); _B = (Uint8)_pixel;",
  58. "RGBA8888" => "_R = (Uint8)(_pixel >> 24); _G = (Uint8)(_pixel >> 16); _B = (Uint8)(_pixel >> 8);",
  59. "ABGR8888" => "_B = (Uint8)(_pixel >> 16); _G = (Uint8)(_pixel >> 8); _R = (Uint8)_pixel;",
  60. "BGRA8888" => "_B = (Uint8)(_pixel >> 24); _G = (Uint8)(_pixel >> 16); _R = (Uint8)(_pixel >> 8);",
  61. );
  62. my %get_rgba_string = (
  63. "RGB888" => $get_rgba_string_ignore_alpha{"RGB888"} . " _A = 0xFF;",
  64. "BGR888" => $get_rgba_string_ignore_alpha{"BGR888"} . " _A = 0xFF;",
  65. "ARGB8888" => $get_rgba_string_ignore_alpha{"ARGB8888"} . " _A = (Uint8)(_pixel >> 24);",
  66. "RGBA8888" => $get_rgba_string_ignore_alpha{"RGBA8888"} . " _A = (Uint8)_pixel;",
  67. "ABGR8888" => $get_rgba_string_ignore_alpha{"ABGR8888"} . " _A = (Uint8)(_pixel >> 24);",
  68. "BGRA8888" => $get_rgba_string_ignore_alpha{"BGRA8888"} . " _A = (Uint8)_pixel;",
  69. );
  70. my %set_rgba_string = (
  71. "RGB888" => "_pixel = ((Uint32)_R << 16) | ((Uint32)_G << 8) | _B;",
  72. "BGR888" => "_pixel = ((Uint32)_B << 16) | ((Uint32)_G << 8) | _R;",
  73. "ARGB8888" => "_pixel = ((Uint32)_A << 24) | ((Uint32)_R << 16) | ((Uint32)_G << 8) | _B;",
  74. "RGBA8888" => "_pixel = ((Uint32)_R << 24) | ((Uint32)_G << 16) | ((Uint32)_B << 8) | _A;",
  75. "ABGR8888" => "_pixel = ((Uint32)_A << 24) | ((Uint32)_B << 16) | ((Uint32)_G << 8) | _R;",
  76. "BGRA8888" => "_pixel = ((Uint32)_B << 24) | ((Uint32)_G << 16) | ((Uint32)_R << 8) | _A;",
  77. );
  78. sub open_file {
  79. my $name = shift;
  80. open(FILE, ">$name.new") || die "Cant' open $name.new: $!";
  81. print FILE <<__EOF__;
  82. /* DO NOT EDIT! This file is generated by sdlgenblit.pl */
  83. /*
  84. Simple DirectMedia Layer
  85. Copyright (C) 1997-2016 Sam Lantinga <slouken\@libsdl.org>
  86. This software is provided 'as-is', without any express or implied
  87. warranty. In no event will the authors be held liable for any damages
  88. arising from the use of this software.
  89. Permission is granted to anyone to use this software for any purpose,
  90. including commercial applications, and to alter it and redistribute it
  91. freely, subject to the following restrictions:
  92. 1. The origin of this software must not be misrepresented; you must not
  93. claim that you wrote the original software. If you use this software
  94. in a product, an acknowledgment in the product documentation would be
  95. appreciated but is not required.
  96. 2. Altered source versions must be plainly marked as such, and must not be
  97. misrepresented as being the original software.
  98. 3. This notice may not be removed or altered from any source distribution.
  99. */
  100. #include "../SDL_internal.h"
  101. /* *INDENT-OFF* */
  102. __EOF__
  103. }
  104. sub close_file {
  105. my $name = shift;
  106. print FILE <<__EOF__;
  107. /* *INDENT-ON* */
  108. /* vi: set ts=4 sw=4 expandtab: */
  109. __EOF__
  110. close FILE;
  111. if ( ! -f $name || system("cmp -s $name $name.new") != 0 ) {
  112. rename("$name.new", "$name");
  113. } else {
  114. unlink("$name.new");
  115. }
  116. }
  117. sub output_copydefs
  118. {
  119. print FILE <<__EOF__;
  120. extern SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[];
  121. __EOF__
  122. }
  123. sub output_copyfuncname
  124. {
  125. my $prefix = shift;
  126. my $src = shift;
  127. my $dst = shift;
  128. my $modulate = shift;
  129. my $blend = shift;
  130. my $scale = shift;
  131. my $args = shift;
  132. my $suffix = shift;
  133. print FILE "$prefix SDL_Blit_${src}_${dst}";
  134. if ( $modulate ) {
  135. print FILE "_Modulate";
  136. }
  137. if ( $blend ) {
  138. print FILE "_Blend";
  139. }
  140. if ( $scale ) {
  141. print FILE "_Scale";
  142. }
  143. if ( $args ) {
  144. print FILE "(SDL_BlitInfo *info)";
  145. }
  146. print FILE "$suffix";
  147. }
  148. sub get_rgba
  149. {
  150. my $prefix = shift;
  151. my $format = shift;
  152. my $ignore_alpha = shift;
  153. my $string;
  154. if ($ignore_alpha) {
  155. $string = $get_rgba_string_ignore_alpha{$format};
  156. } else {
  157. $string = $get_rgba_string{$format};
  158. }
  159. $string =~ s/_/$prefix/g;
  160. if ( $prefix ne "" ) {
  161. print FILE <<__EOF__;
  162. ${prefix}pixel = *$prefix;
  163. __EOF__
  164. } else {
  165. print FILE <<__EOF__;
  166. pixel = *src;
  167. __EOF__
  168. }
  169. print FILE <<__EOF__;
  170. $string
  171. __EOF__
  172. }
  173. sub set_rgba
  174. {
  175. my $prefix = shift;
  176. my $format = shift;
  177. my $string = $set_rgba_string{$format};
  178. $string =~ s/_/$prefix/g;
  179. print FILE <<__EOF__;
  180. $string
  181. *dst = ${prefix}pixel;
  182. __EOF__
  183. }
  184. sub output_copycore
  185. {
  186. my $src = shift;
  187. my $dst = shift;
  188. my $modulate = shift;
  189. my $blend = shift;
  190. my $s = "";
  191. my $d = "";
  192. # Nice and easy...
  193. if ( $src eq $dst && !$modulate && !$blend ) {
  194. print FILE <<__EOF__;
  195. *dst = *src;
  196. __EOF__
  197. return;
  198. }
  199. my $dst_has_alpha = ($dst =~ /A/) ? 1 : 0;
  200. my $ignore_dst_alpha = !$dst_has_alpha && !$blend;
  201. if ( $blend ) {
  202. get_rgba("src", $src, $ignore_dst_alpha);
  203. get_rgba("dst", $dst, !$dst_has_alpha);
  204. $s = "src";
  205. $d = "dst";
  206. } else {
  207. get_rgba("", $src, $ignore_dst_alpha);
  208. }
  209. if ( $modulate ) {
  210. print FILE <<__EOF__;
  211. if (flags & SDL_COPY_MODULATE_COLOR) {
  212. ${s}R = (${s}R * modulateR) / 255;
  213. ${s}G = (${s}G * modulateG) / 255;
  214. ${s}B = (${s}B * modulateB) / 255;
  215. }
  216. __EOF__
  217. if (not $ignore_dst_alpha) {
  218. print FILE <<__EOF__;
  219. if (flags & SDL_COPY_MODULATE_ALPHA) {
  220. ${s}A = (${s}A * modulateA) / 255;
  221. }
  222. __EOF__
  223. }
  224. }
  225. if ( $blend ) {
  226. print FILE <<__EOF__;
  227. if (flags & (SDL_COPY_BLEND|SDL_COPY_ADD)) {
  228. /* This goes away if we ever use premultiplied alpha */
  229. if (${s}A < 255) {
  230. ${s}R = (${s}R * ${s}A) / 255;
  231. ${s}G = (${s}G * ${s}A) / 255;
  232. ${s}B = (${s}B * ${s}A) / 255;
  233. }
  234. }
  235. switch (flags & (SDL_COPY_BLEND|SDL_COPY_ADD|SDL_COPY_MOD)) {
  236. case SDL_COPY_BLEND:
  237. ${d}R = ${s}R + ((255 - ${s}A) * ${d}R) / 255;
  238. ${d}G = ${s}G + ((255 - ${s}A) * ${d}G) / 255;
  239. ${d}B = ${s}B + ((255 - ${s}A) * ${d}B) / 255;
  240. __EOF__
  241. if ( $dst_has_alpha ) {
  242. print FILE <<__EOF__;
  243. ${d}A = ${s}A + ((255 - ${s}A) * ${d}A) / 255;
  244. __EOF__
  245. }
  246. print FILE <<__EOF__;
  247. break;
  248. case SDL_COPY_ADD:
  249. ${d}R = ${s}R + ${d}R; if (${d}R > 255) ${d}R = 255;
  250. ${d}G = ${s}G + ${d}G; if (${d}G > 255) ${d}G = 255;
  251. ${d}B = ${s}B + ${d}B; if (${d}B > 255) ${d}B = 255;
  252. break;
  253. case SDL_COPY_MOD:
  254. ${d}R = (${s}R * ${d}R) / 255;
  255. ${d}G = (${s}G * ${d}G) / 255;
  256. ${d}B = (${s}B * ${d}B) / 255;
  257. break;
  258. }
  259. __EOF__
  260. }
  261. if ( $blend ) {
  262. set_rgba("dst", $dst);
  263. } else {
  264. set_rgba("", $dst);
  265. }
  266. }
  267. sub output_copyfunc
  268. {
  269. my $src = shift;
  270. my $dst = shift;
  271. my $modulate = shift;
  272. my $blend = shift;
  273. my $scale = shift;
  274. my $dst_has_alpha = ($dst =~ /A/) ? 1 : 0;
  275. my $ignore_dst_alpha = !$dst_has_alpha && !$blend;
  276. output_copyfuncname("static void", $src, $dst, $modulate, $blend, $scale, 1, "\n");
  277. print FILE <<__EOF__;
  278. {
  279. __EOF__
  280. if ( $modulate || $blend ) {
  281. print FILE <<__EOF__;
  282. const int flags = info->flags;
  283. __EOF__
  284. }
  285. if ( $modulate ) {
  286. print FILE <<__EOF__;
  287. const Uint32 modulateR = info->r;
  288. const Uint32 modulateG = info->g;
  289. const Uint32 modulateB = info->b;
  290. __EOF__
  291. if (!$ignore_dst_alpha) {
  292. print FILE <<__EOF__;
  293. const Uint32 modulateA = info->a;
  294. __EOF__
  295. }
  296. }
  297. if ( $blend ) {
  298. print FILE <<__EOF__;
  299. Uint32 srcpixel;
  300. Uint32 srcR, srcG, srcB, srcA;
  301. Uint32 dstpixel;
  302. __EOF__
  303. if ($dst_has_alpha) {
  304. print FILE <<__EOF__;
  305. Uint32 dstR, dstG, dstB, dstA;
  306. __EOF__
  307. } else {
  308. print FILE <<__EOF__;
  309. Uint32 dstR, dstG, dstB;
  310. __EOF__
  311. }
  312. } elsif ( $modulate || $src ne $dst ) {
  313. print FILE <<__EOF__;
  314. Uint32 pixel;
  315. __EOF__
  316. if (!$ignore_dst_alpha) {
  317. print FILE <<__EOF__;
  318. Uint32 R, G, B, A;
  319. __EOF__
  320. } else {
  321. print FILE <<__EOF__;
  322. Uint32 R, G, B;
  323. __EOF__
  324. }
  325. }
  326. if ( $scale ) {
  327. print FILE <<__EOF__;
  328. int srcy, srcx;
  329. int posy, posx;
  330. int incy, incx;
  331. __EOF__
  332. print FILE <<__EOF__;
  333. srcy = 0;
  334. posy = 0;
  335. incy = (info->src_h << 16) / info->dst_h;
  336. incx = (info->src_w << 16) / info->dst_w;
  337. while (info->dst_h--) {
  338. $format_type{$src} *src = 0;
  339. $format_type{$dst} *dst = ($format_type{$dst} *)info->dst;
  340. int n = info->dst_w;
  341. srcx = -1;
  342. posx = 0x10000L;
  343. while (posy >= 0x10000L) {
  344. ++srcy;
  345. posy -= 0x10000L;
  346. }
  347. while (n--) {
  348. if (posx >= 0x10000L) {
  349. while (posx >= 0x10000L) {
  350. ++srcx;
  351. posx -= 0x10000L;
  352. }
  353. src = ($format_type{$src} *)(info->src + (srcy * info->src_pitch) + (srcx * $format_size{$src}));
  354. __EOF__
  355. print FILE <<__EOF__;
  356. }
  357. __EOF__
  358. output_copycore($src, $dst, $modulate, $blend);
  359. print FILE <<__EOF__;
  360. posx += incx;
  361. ++dst;
  362. }
  363. posy += incy;
  364. info->dst += info->dst_pitch;
  365. }
  366. __EOF__
  367. } else {
  368. print FILE <<__EOF__;
  369. while (info->dst_h--) {
  370. $format_type{$src} *src = ($format_type{$src} *)info->src;
  371. $format_type{$dst} *dst = ($format_type{$dst} *)info->dst;
  372. int n = info->dst_w;
  373. while (n--) {
  374. __EOF__
  375. output_copycore($src, $dst, $modulate, $blend);
  376. print FILE <<__EOF__;
  377. ++src;
  378. ++dst;
  379. }
  380. info->src += info->src_pitch;
  381. info->dst += info->dst_pitch;
  382. }
  383. __EOF__
  384. }
  385. print FILE <<__EOF__;
  386. }
  387. __EOF__
  388. }
  389. sub output_copyfunc_h
  390. {
  391. }
  392. sub output_copyinc
  393. {
  394. print FILE <<__EOF__;
  395. #include "SDL_video.h"
  396. #include "SDL_blit.h"
  397. #include "SDL_blit_auto.h"
  398. __EOF__
  399. }
  400. sub output_copyfunctable
  401. {
  402. print FILE <<__EOF__;
  403. SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[] = {
  404. __EOF__
  405. for (my $i = 0; $i <= $#src_formats; ++$i) {
  406. my $src = $src_formats[$i];
  407. for (my $j = 0; $j <= $#dst_formats; ++$j) {
  408. my $dst = $dst_formats[$j];
  409. for (my $modulate = 0; $modulate <= 1; ++$modulate) {
  410. for (my $blend = 0; $blend <= 1; ++$blend) {
  411. for (my $scale = 0; $scale <= 1; ++$scale) {
  412. if ( $modulate || $blend || $scale ) {
  413. print FILE " { SDL_PIXELFORMAT_$src, SDL_PIXELFORMAT_$dst, ";
  414. my $flags = "";
  415. my $flag = "";
  416. if ( $modulate ) {
  417. $flag = "SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA";
  418. if ( $flags eq "" ) {
  419. $flags = $flag;
  420. } else {
  421. $flags = "$flags | $flag";
  422. }
  423. }
  424. if ( $blend ) {
  425. $flag = "SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD";
  426. if ( $flags eq "" ) {
  427. $flags = $flag;
  428. } else {
  429. $flags = "$flags | $flag";
  430. }
  431. }
  432. if ( $scale ) {
  433. $flag = "SDL_COPY_NEAREST";
  434. if ( $flags eq "" ) {
  435. $flags = $flag;
  436. } else {
  437. $flags = "$flags | $flag";
  438. }
  439. }
  440. if ( $flags eq "" ) {
  441. $flags = "0";
  442. }
  443. print FILE "($flags), SDL_CPU_ANY,";
  444. output_copyfuncname("", $src_formats[$i], $dst_formats[$j], $modulate, $blend, $scale, 0, " },\n");
  445. }
  446. }
  447. }
  448. }
  449. }
  450. }
  451. print FILE <<__EOF__;
  452. { 0, 0, 0, 0, NULL }
  453. };
  454. __EOF__
  455. }
  456. sub output_copyfunc_c
  457. {
  458. my $src = shift;
  459. my $dst = shift;
  460. for (my $modulate = 0; $modulate <= 1; ++$modulate) {
  461. for (my $blend = 0; $blend <= 1; ++$blend) {
  462. for (my $scale = 0; $scale <= 1; ++$scale) {
  463. if ( $modulate || $blend || $scale ) {
  464. output_copyfunc($src, $dst, $modulate, $blend, $scale);
  465. }
  466. }
  467. }
  468. }
  469. }
  470. open_file("SDL_blit_auto.h");
  471. output_copydefs();
  472. for (my $i = 0; $i <= $#src_formats; ++$i) {
  473. for (my $j = 0; $j <= $#dst_formats; ++$j) {
  474. output_copyfunc_h($src_formats[$i], $dst_formats[$j]);
  475. }
  476. }
  477. print FILE "\n";
  478. close_file("SDL_blit_auto.h");
  479. open_file("SDL_blit_auto.c");
  480. output_copyinc();
  481. for (my $i = 0; $i <= $#src_formats; ++$i) {
  482. for (my $j = 0; $j <= $#dst_formats; ++$j) {
  483. output_copyfunc_c($src_formats[$i], $dst_formats[$j]);
  484. }
  485. }
  486. output_copyfunctable();
  487. close_file("SDL_blit_auto.c");