comparison src/video/sdlgenblit.pl @ 1985:8055185ae4ed

Added source color and alpha modulation support. Added perl script to generate optimized render copy functions.
author Sam Lantinga <slouken@libsdl.org>
date Mon, 28 Aug 2006 03:17:39 +0000
parents
children 5b5f5de5433f
comparison
equal deleted inserted replaced
1984:b910bcabec26 1985:8055185ae4ed
1 #!/usr/bin/perl -w
2 #
3 # A script to generate optimized C blitters for Simple DirectMedia Layer
4 # http://www.libsdl.org/
5
6 use warnings;
7 use strict;
8
9 my %file;
10
11 # The formats potentially supported by this script:
12 # SDL_PIXELFORMAT_INDEX8
13 # SDL_PIXELFORMAT_RGB332
14 # SDL_PIXELFORMAT_RGB444
15 # SDL_PIXELFORMAT_RGB555
16 # SDL_PIXELFORMAT_ARGB4444
17 # SDL_PIXELFORMAT_ARGB1555
18 # SDL_PIXELFORMAT_RGB565
19 # SDL_PIXELFORMAT_RGB24
20 # SDL_PIXELFORMAT_BGR24
21 # SDL_PIXELFORMAT_RGB888
22 # SDL_PIXELFORMAT_BGR888
23 # SDL_PIXELFORMAT_ARGB8888
24 # SDL_PIXELFORMAT_RGBA8888
25 # SDL_PIXELFORMAT_ABGR8888
26 # SDL_PIXELFORMAT_BGRA8888
27 # SDL_PIXELFORMAT_ARGB2101010
28
29 # The formats we're actually creating blitters for:
30 my @src_formats = (
31 "RGB888",
32 "BGR888",
33 "ARGB8888",
34 "RGBA8888",
35 "ABGR8888",
36 "BGRA8888",
37 );
38 my @dst_formats = (
39 "RGB888",
40 "BGR888",
41 );
42
43 my %format_size = (
44 "RGB888" => 4,
45 "BGR888" => 4,
46 "ARGB8888" => 4,
47 "RGBA8888" => 4,
48 "ABGR8888" => 4,
49 "BGRA8888" => 4,
50 );
51
52 my %format_type = (
53 "RGB888" => "Uint32",
54 "BGR888" => "Uint32",
55 "ARGB8888" => "Uint32",
56 "RGBA8888" => "Uint32",
57 "ABGR8888" => "Uint32",
58 "BGRA8888" => "Uint32",
59 );
60
61 my %get_rgba_string = (
62 "RGB888" => "_R = (Uint8)(_pixel >> 16); _G = (Uint8)(_pixel >> 8); _B = (Uint8)_pixel; _A = 0xFF;",
63 "BGR888" => "_B = (Uint8)(_pixel >> 16); _G = (Uint8)(_pixel >> 8); _R = (Uint8)_pixel; _A = 0xFF;",
64 "ARGB8888" => "_A = (Uint8)(_pixel >> 24); _R = (Uint8)(_pixel >> 16); _G = (Uint8)(_pixel >> 8); _B = (Uint8)_pixel;",
65 "RGBA8888" => "_R = (Uint8)(_pixel >> 24); _G = (Uint8)(_pixel >> 16); _B = (Uint8)(_pixel >> 8); _A = (Uint8)_pixel;",
66 "ABGR8888" => "_A = (Uint8)(_pixel >> 24); _B = (Uint8)(_pixel >> 16); _G = (Uint8)(_pixel >> 8); _R = (Uint8)_pixel;",
67 "BGRA8888" => "_B = (Uint8)(_pixel >> 24); _G = (Uint8)(_pixel >> 16); _R = (Uint8)(_pixel >> 8); _A = (Uint8)_pixel;",
68 );
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 );
74
75 sub open_file {
76 my $name = shift;
77 open(FILE, ">$name.new") || die "Cant' open $name.new: $!";
78 print FILE <<__EOF__;
79 /* DO NOT EDIT! This file is generated by sdlgenblit.pl */
80 /*
81 SDL - Simple DirectMedia Layer
82 Copyright (C) 1997-2006 Sam Lantinga
83
84 This library is free software; you can redistribute it and/or
85 modify it under the terms of the GNU Lesser General Public
86 License as published by the Free Software Foundation; either
87 version 2.1 of the License, or (at your option) any later version.
88
89 This library is distributed in the hope that it will be useful,
90 but WITHOUT ANY WARRANTY; without even the implied warranty of
91 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
92 Lesser General Public License for more details.
93
94 You should have received a copy of the GNU Lesser General Public
95 License along with this library; if not, write to the Free Software
96 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
97
98 Sam Lantinga
99 slouken\@libsdl.org
100 */
101 #include "SDL_config.h"
102
103 /* *INDENT-OFF* */
104
105 __EOF__
106 }
107
108 sub close_file {
109 my $name = shift;
110 print FILE <<__EOF__;
111 /* *INDENT-ON* */
112
113 /* vi: set ts=4 sw=4 expandtab: */
114 __EOF__
115 close FILE;
116 if ( ! -f $name || system("cmp -s $name $name.new") != 0 ) {
117 rename("$name.new", "$name");
118 } else {
119 unlink("$name.new");
120 }
121 }
122
123 sub output_copydefs
124 {
125 print FILE <<__EOF__;
126 #define SDL_RENDERCOPY_MODULATE_COLOR 0x0001
127 #define SDL_RENDERCOPY_MODULATE_ALPHA 0x0002
128 #define SDL_RENDERCOPY_BLEND 0x0010
129 #define SDL_RENDERCOPY_ADD 0x0020
130 #define SDL_RENDERCOPY_MOD 0x0040
131 #define SDL_RENDERCOPY_NEAREST 0x0100
132
133 typedef struct {
134 void *src;
135 int src_w, src_h;
136 int src_pitch;
137 void *dst;
138 int dst_w, dst_h;
139 int dst_pitch;
140 void *aux_data;
141 int flags;
142 Uint8 r, g, b, a;
143 } SDL_RenderCopyData;
144
145 typedef int (*SDL_RenderCopyFunc)(SDL_RenderCopyData *data);
146
147 extern SDL_RenderCopyFunc SDLCALL SDL_GetRenderCopyFunc(Uint32 src_format, Uint32 dst_format, int modMode, int blendMode, int scaleMode);
148
149 __EOF__
150 }
151
152 sub output_copyfuncname
153 {
154 my $prefix = shift;
155 my $src = shift;
156 my $dst = shift;
157 my $modulate = shift;
158 my $blend = shift;
159 my $scale = shift;
160 my $args = shift;
161 my $suffix = shift;
162
163 print FILE "$prefix SDL_RenderCopy_${src}_${dst}";
164 if ( $modulate ) {
165 print FILE "_Modulate";
166 }
167 if ( $blend ) {
168 print FILE "_Blend";
169 }
170 if ( $scale ) {
171 print FILE "_Scale";
172 }
173 if ( $args ) {
174 print FILE "(SDL_RenderCopyData *data)";
175 }
176 print FILE "$suffix";
177 }
178
179 sub get_rgba
180 {
181 my $prefix = shift;
182 my $format = shift;
183 my $string = $get_rgba_string{$format};
184 $string =~ s/_/$prefix/g;
185 if ( $prefix ne "" ) {
186 print FILE <<__EOF__;
187 ${prefix}pixel = *$prefix;
188 __EOF__
189 } else {
190 print FILE <<__EOF__;
191 pixel = *src;
192 __EOF__
193 }
194 print FILE <<__EOF__;
195 $string
196 __EOF__
197 }
198
199 sub set_rgba
200 {
201 my $prefix = shift;
202 my $format = shift;
203 my $string = $set_rgba_string{$format};
204 $string =~ s/_/$prefix/g;
205 print FILE <<__EOF__;
206 $string
207 *dst = ${prefix}pixel;
208 __EOF__
209 }
210
211 sub output_copycore
212 {
213 my $src = shift;
214 my $dst = shift;
215 my $modulate = shift;
216 my $blend = shift;
217 if ( $modulate ) {
218 print FILE <<__EOF__;
219 if (flags & SDL_RENDERCOPY_MODULATE_COLOR) {
220 ${src}R = (${src}R * modulateR) / 255;
221 ${src}G = (${src}G * modulateG) / 255;
222 ${src}B = (${src}B * modulateB) / 255;
223 }
224 __EOF__
225 }
226 if ( $modulate && $blend ) {
227 print FILE <<__EOF__;
228 if (flags & SDL_RENDERCOPY_MODULATE_ALPHA) {
229 ${src}A = (${src}A * modulateA) / 255;
230 }
231 __EOF__
232 }
233 if ( $blend ) {
234 print FILE <<__EOF__;
235 if (flags & (SDL_RENDERCOPY_BLEND|SDL_RENDERCOPY_ADD)) {
236 /* This goes away if we ever use premultiplied alpha */
237 ${src}R = (${src}R * ${src}A) / 255;
238 ${src}G = (${src}G * ${src}A) / 255;
239 ${src}B = (${src}B * ${src}A) / 255;
240 }
241 switch (flags & (SDL_RENDERCOPY_BLEND|SDL_RENDERCOPY_ADD|SDL_RENDERCOPY_MOD)) {
242 case SDL_RENDERCOPY_BLEND:
243 ${dst}R = ${src}R + ((255 - ${src}A) * ${dst}R) / 255;
244 ${dst}G = ${src}G + ((255 - ${src}A) * ${dst}G) / 255;
245 ${dst}B = ${src}B + ((255 - ${src}A) * ${dst}B) / 255;
246 break;
247 case SDL_RENDERCOPY_ADD:
248 ${dst}R = ${src}R + ${dst}R; if (${dst}R > 255) ${dst}R = 255;
249 ${dst}G = ${src}G + ${dst}G; if (${dst}G > 255) ${dst}G = 255;
250 ${dst}B = ${src}B + ${dst}B; if (${dst}B > 255) ${dst}B = 255;
251 break;
252 case SDL_RENDERCOPY_MOD:
253 ${dst}R = (${src}R * ${dst}R) / 255;
254 ${dst}G = (${src}G * ${dst}G) / 255;
255 ${dst}B = (${src}B * ${dst}B) / 255;
256 break;
257 }
258 __EOF__
259 }
260 }
261
262 sub output_copyfunc
263 {
264 my $src = shift;
265 my $dst = shift;
266 my $modulate = shift;
267 my $blend = shift;
268 my $scale = shift;
269
270 output_copyfuncname("int", $src, $dst, $modulate, $blend, $scale, 1, "\n");
271 print FILE <<__EOF__;
272 {
273 const int flags = data->flags;
274 __EOF__
275 if ( $modulate ) {
276 print FILE <<__EOF__;
277 const Uint32 modulateR = data->r;
278 const Uint32 modulateG = data->g;
279 const Uint32 modulateB = data->b;
280 const Uint32 modulateA = data->a;
281 __EOF__
282 }
283 if ( $blend ) {
284 print FILE <<__EOF__;
285 Uint32 srcpixel;
286 Uint32 srcR, srcG, srcB, srcA;
287 Uint32 dstpixel;
288 Uint32 dstR, dstG, dstB, dstA;
289 __EOF__
290 } elsif ( $modulate || $src ne $dst ) {
291 print FILE <<__EOF__;
292 Uint32 pixel;
293 Uint32 R, G, B, A;
294 __EOF__
295 }
296 if ( $scale ) {
297 print FILE <<__EOF__;
298 int srcy, srcx;
299 int posy, posx;
300 int incy, incx;
301
302 srcy = 0;
303 posy = 0;
304 incy = (data->src_h << 16) / data->dst_h;
305 incx = (data->src_w << 16) / data->dst_w;
306
307 while (data->dst_h--) {
308 $format_type{$src} *src;
309 $format_type{$dst} *dst = ($format_type{$dst} *)data->dst;
310 int n = data->dst_w;
311 srcx = -1;
312 posx = 0x10000L;
313 while (posy >= 0x10000L) {
314 ++srcy;
315 posy -= 0x10000L;
316 }
317 while (n--) {
318 if (posx >= 0x10000L) {
319 while (posx >= 0x10000L) {
320 ++srcx;
321 posx -= 0x10000L;
322 }
323 src = ($format_type{$src} *)(data->src + (srcy * data->src_pitch) + (srcx * $format_size{$src}));
324 __EOF__
325 print FILE <<__EOF__;
326 }
327 __EOF__
328 if ( $blend ) {
329 get_rgba("src", $src);
330 get_rgba("dst", $dst);
331 output_copycore("src", "dst", $modulate, $blend);
332 set_rgba("dst", $dst);
333 } elsif ( $modulate || $src ne $dst ) {
334 get_rgba("", $src);
335 output_copycore("", "", $modulate, $blend);
336 set_rgba("", $dst);
337 } else {
338 print FILE <<__EOF__;
339 *dst = *src;
340 __EOF__
341 }
342 print FILE <<__EOF__;
343 posx += incx;
344 ++dst;
345 }
346 posy += incy;
347 data->dst += data->dst_pitch;
348 }
349 __EOF__
350 } else {
351 print FILE <<__EOF__;
352
353 while (data->dst_h--) {
354 $format_type{$src} *src = ($format_type{$src} *)data->src;
355 $format_type{$dst} *dst = ($format_type{$dst} *)data->dst;
356 int n = data->dst_w;
357 while (n--) {
358 __EOF__
359 if ( $blend ) {
360 get_rgba("src", $src);
361 get_rgba("dst", $dst);
362 output_copycore("src", "dst", $modulate, $blend);
363 set_rgba("dst", $dst);
364 } elsif ( $modulate || $src ne $dst ) {
365 get_rgba("", $src);
366 output_copycore("", "", $modulate, $blend);
367 set_rgba("", $dst);
368 } else {
369 print FILE <<__EOF__;
370 *dst = *src;
371 __EOF__
372 }
373 print FILE <<__EOF__;
374 ++src;
375 ++dst;
376 }
377 data->src += data->src_pitch;
378 data->dst += data->dst_pitch;
379 }
380 __EOF__
381 }
382 print FILE <<__EOF__;
383 return 0;
384 }
385
386 __EOF__
387 }
388
389 sub output_copyfunc_h
390 {
391 my $src = shift;
392 my $dst = shift;
393 for (my $modulate = 0; $modulate <= 1; ++$modulate) {
394 for (my $blend = 0; $blend <= 1; ++$blend) {
395 for (my $scale = 0; $scale <= 1; ++$scale) {
396 if ( $modulate != 0 || $blend != 0 || $scale != 0 || $src ne $dst ) {
397 output_copyfuncname("extern int SDLCALL", $src, $dst, $modulate, $blend, $scale, 1, ";\n");
398 }
399 }
400 }
401 }
402 }
403
404 sub output_copyinc
405 {
406 print FILE <<__EOF__;
407 #include "SDL_video.h"
408 #include "SDL_rendercopy.h"
409
410 __EOF__
411 }
412
413 sub output_copyfunctable
414 {
415 print FILE <<__EOF__;
416 static struct {
417 Uint32 src_format;
418 Uint32 dst_format;
419 int modMode;
420 int blendMode;
421 int scaleMode;
422 SDL_RenderCopyFunc func;
423 } SDL_RenderCopyFuncTable[] = {
424 __EOF__
425 for (my $i = 0; $i <= $#src_formats; ++$i) {
426 my $src = $src_formats[$i];
427 for (my $j = 0; $j <= $#dst_formats; ++$j) {
428 my $dst = $dst_formats[$j];
429 for (my $modulate = 0; $modulate <= 1; ++$modulate) {
430 for (my $blend = 0; $blend <= 1; ++$blend) {
431 for (my $scale = 0; $scale <= 1; ++$scale) {
432 if ( $modulate != 0 || $blend != 0 || $scale != 0 || $src ne $dst ) {
433 print FILE " { SDL_PIXELFORMAT_$src, SDL_PIXELFORMAT_$dst, ";
434 if ( $modulate ) {
435 print FILE "(SDL_TEXTUREMODULATE_COLOR | SDL_TEXTUREMODULATE_ALPHA), ";
436 } else {
437 print FILE "0, ";
438 }
439 if ( $blend ) {
440 print FILE "(SDL_TEXTUREBLENDMODE_MASK | SDL_TEXTUREBLENDMODE_BLEND | SDL_TEXTUREBLENDMODE_ADD | SDL_TEXTUREBLENDMODE_MOD), ";
441 } else {
442 print FILE "0, ";
443 }
444 if ( $scale ) {
445 print FILE "SDL_TEXTURESCALEMODE_FAST, ";
446 } else {
447 print FILE "0, ";
448 }
449 output_copyfuncname("", $src_formats[$i], $dst_formats[$j], $modulate, $blend, $scale, 0, " },\n");
450 }
451 }
452 }
453 }
454 }
455 }
456 print FILE <<__EOF__;
457 };
458
459 SDL_RenderCopyFunc SDL_GetRenderCopyFunc(Uint32 src_format, Uint32 dst_format, int modMode, int blendMode, int scaleMode)
460 {
461 int i;
462
463 for (i = 0; i < SDL_arraysize(SDL_RenderCopyFuncTable); ++i) {
464 if (src_format != SDL_RenderCopyFuncTable[i].src_format) {
465 continue;
466 }
467 if (dst_format != SDL_RenderCopyFuncTable[i].dst_format) {
468 continue;
469 }
470 if ((modMode & SDL_RenderCopyFuncTable[i].modMode) != modMode) {
471 continue;
472 }
473 if ((blendMode & SDL_RenderCopyFuncTable[i].blendMode) != blendMode) {
474 continue;
475 }
476 if ((scaleMode & SDL_RenderCopyFuncTable[i].scaleMode) != scaleMode) {
477 continue;
478 }
479 return SDL_RenderCopyFuncTable[i].func;
480 }
481 return NULL;
482 }
483
484 __EOF__
485 }
486
487 sub output_copyfunc_c
488 {
489 my $src = shift;
490 my $dst = shift;
491
492 for (my $modulate = 0; $modulate <= 1; ++$modulate) {
493 for (my $blend = 0; $blend <= 1; ++$blend) {
494 for (my $scale = 0; $scale <= 1; ++$scale) {
495 if ( $modulate != 0 || $blend != 0 || $scale != 0 || $src ne $dst ) {
496 output_copyfunc($src, $dst, $modulate, $blend, $scale);
497 }
498 }
499 }
500 }
501 }
502
503 open_file("SDL_rendercopy.h");
504 output_copydefs();
505 for (my $i = 0; $i <= $#src_formats; ++$i) {
506 for (my $j = 0; $j <= $#dst_formats; ++$j) {
507 output_copyfunc_h($src_formats[$i], $dst_formats[$j]);
508 }
509 }
510 print FILE "\n";
511 close_file("SDL_rendercopy.h");
512
513 open_file("SDL_rendercopy.c");
514 output_copyinc();
515 output_copyfunctable();
516 for (my $i = 0; $i <= $#src_formats; ++$i) {
517 for (my $j = 0; $j <= $#dst_formats; ++$j) {
518 output_copyfunc_c($src_formats[$i], $dst_formats[$j]);
519 }
520 }
521 close_file("SDL_rendercopy.c");