src/video/sdlgenblit.pl
author Sam Lantinga
Sun, 06 Mar 2011 21:17:09 -0800
changeset 5426 7a3982c50af8
parent 5184 d976b67150c5
child 5535 96594ac5fd1a
permissions -rwxr-xr-x
Fixed compiler warnings
     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_RGB332
    13 # SDL_PIXELFORMAT_RGB444
    14 # SDL_PIXELFORMAT_RGB555
    15 # SDL_PIXELFORMAT_ARGB4444
    16 # SDL_PIXELFORMAT_ARGB1555
    17 # SDL_PIXELFORMAT_RGB565
    18 # SDL_PIXELFORMAT_RGB24
    19 # SDL_PIXELFORMAT_BGR24
    20 # SDL_PIXELFORMAT_RGB888
    21 # SDL_PIXELFORMAT_BGR888
    22 # SDL_PIXELFORMAT_ARGB8888
    23 # SDL_PIXELFORMAT_RGBA8888
    24 # SDL_PIXELFORMAT_ABGR8888
    25 # SDL_PIXELFORMAT_BGRA8888
    26 # SDL_PIXELFORMAT_ARGB2101010
    27 
    28 # The formats we're actually creating blitters for:
    29 my @src_formats = (
    30     "RGB888",
    31     "BGR888",
    32     "ARGB8888",
    33     "RGBA8888",
    34     "ABGR8888",
    35     "BGRA8888",
    36 );
    37 my @dst_formats = (
    38     "RGB888",
    39     "BGR888",
    40     "ARGB8888",
    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;", "ARGB8888" => "_A = (Uint8)(_pixel >> 24); _R = (Uint8)(_pixel >> 16); _G = (Uint8)(_pixel >> 8); _B = (Uint8)_pixel;",
    64     "RGBA8888" => "_R = (Uint8)(_pixel >> 24); _G = (Uint8)(_pixel >> 16); _B = (Uint8)(_pixel >> 8); _A = (Uint8)_pixel;",
    65     "ABGR8888" => "_A = (Uint8)(_pixel >> 24); _B = (Uint8)(_pixel >> 16); _G = (Uint8)(_pixel >> 8); _R = (Uint8)_pixel;",
    66     "BGRA8888" => "_B = (Uint8)(_pixel >> 24); _G = (Uint8)(_pixel >> 16); _R = (Uint8)(_pixel >> 8); _A = (Uint8)_pixel;",
    67 );
    68 
    69 my %set_rgba_string = (
    70     "RGB888" => "_pixel = ((Uint32)_R << 16) | ((Uint32)_G << 8) | _B;",
    71     "BGR888" => "_pixel = ((Uint32)_B << 16) | ((Uint32)_G << 8) | _R;",
    72     "ARGB8888" => "_pixel = ((Uint32)_A << 24) | ((Uint32)_R << 16) | ((Uint32)_G << 8) | _B;",
    73     "RGBA8888" => "_pixel = ((Uint32)_R << 24) | ((Uint32)_G << 16) | ((Uint32)_B << 8) | _A;",
    74     "ABGR8888" => "_pixel = ((Uint32)_A << 24) | ((Uint32)_B << 16) | ((Uint32)_G << 8) | _R;",
    75     "BGRA8888" => "_pixel = ((Uint32)_B << 24) | ((Uint32)_G << 16) | ((Uint32)_R << 8) | _A;",
    76 );
    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     SDL - Simple DirectMedia Layer
    85     Copyright (C) 1997-2011 Sam Lantinga
    86 
    87     This library is free software; you can redistribute it and/or
    88     modify it under the terms of the GNU Lesser General Public
    89     License as published by the Free Software Foundation; either
    90     version 2.1 of the License, or (at your option) any later version.
    91 
    92     This library is distributed in the hope that it will be useful,
    93     but WITHOUT ANY WARRANTY; without even the implied warranty of
    94     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    95     Lesser General Public License for more details.
    96 
    97     You should have received a copy of the GNU Lesser General Public
    98     License along with this library; if not, write to the Free Software
    99     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   100 
   101     Sam Lantinga
   102     slouken\@libsdl.org
   103 */
   104 #include "SDL_config.h"
   105 
   106 /* *INDENT-OFF* */
   107 
   108 __EOF__
   109 }
   110 
   111 sub close_file {
   112     my $name = shift;
   113     print FILE <<__EOF__;
   114 /* *INDENT-ON* */
   115 
   116 /* vi: set ts=4 sw=4 expandtab: */
   117 __EOF__
   118     close FILE;
   119     if ( ! -f $name || system("cmp -s $name $name.new") != 0 ) {
   120         rename("$name.new", "$name");
   121     } else {
   122         unlink("$name.new");
   123     }
   124 }
   125 
   126 sub output_copydefs
   127 {
   128     print FILE <<__EOF__;
   129 extern SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[];
   130 __EOF__
   131 }
   132 
   133 sub output_copyfuncname
   134 {
   135     my $prefix = shift;
   136     my $src = shift;
   137     my $dst = shift;
   138     my $modulate = shift;
   139     my $blend = shift;
   140     my $scale = shift;
   141     my $args = shift;
   142     my $suffix = shift;
   143 
   144     print FILE "$prefix SDL_Blit_${src}_${dst}";
   145     if ( $modulate ) {
   146         print FILE "_Modulate";
   147     }
   148     if ( $blend ) {
   149         print FILE "_Blend";
   150     }
   151     if ( $scale ) {
   152         print FILE "_Scale";
   153     }
   154     if ( $args ) {
   155         print FILE "(SDL_BlitInfo *info)";
   156     }
   157     print FILE "$suffix";
   158 }
   159 
   160 sub get_rgba
   161 {
   162     my $prefix = shift;
   163     my $format = shift;
   164     my $string = $get_rgba_string{$format};
   165     $string =~ s/_/$prefix/g;
   166     if ( $prefix ne "" ) {
   167         print FILE <<__EOF__;
   168             ${prefix}pixel = *$prefix;
   169 __EOF__
   170     } else {
   171         print FILE <<__EOF__;
   172             pixel = *src;
   173 __EOF__
   174     }
   175     print FILE <<__EOF__;
   176             $string
   177 __EOF__
   178 }
   179 
   180 sub set_rgba
   181 {
   182     my $prefix = shift;
   183     my $format = shift;
   184     my $string = $set_rgba_string{$format};
   185     $string =~ s/_/$prefix/g;
   186     print FILE <<__EOF__;
   187             $string
   188             *dst = ${prefix}pixel;
   189 __EOF__
   190 }
   191 
   192 sub output_copycore
   193 {
   194     my $src = shift;
   195     my $dst = shift;
   196     my $modulate = shift;
   197     my $blend = shift;
   198     my $s = "";
   199     my $d = "";
   200 
   201     # Nice and easy...
   202     if ( $src eq $dst && !$modulate && !$blend ) {
   203         print FILE <<__EOF__;
   204             *dst = *src;
   205 __EOF__
   206         return;
   207     }
   208 
   209     if ( $blend ) {
   210         get_rgba("src", $src);
   211         get_rgba("dst", $dst);
   212         $s = "src";
   213         $d = "dst";
   214     } else {
   215         get_rgba("", $src);
   216     }
   217 
   218     if ( $modulate ) {
   219         print FILE <<__EOF__;
   220             if (flags & SDL_COPY_MODULATE_COLOR) {
   221                 ${s}R = (${s}R * modulateR) / 255;
   222                 ${s}G = (${s}G * modulateG) / 255;
   223                 ${s}B = (${s}B * modulateB) / 255;
   224             }
   225             if (flags & SDL_COPY_MODULATE_ALPHA) {
   226                 ${s}A = (${s}A * modulateA) / 255;
   227             }
   228 __EOF__
   229     }
   230     if ( $blend ) {
   231         print FILE <<__EOF__;
   232             if (flags & (SDL_COPY_BLEND|SDL_COPY_ADD)) {
   233                 /* This goes away if we ever use premultiplied alpha */
   234                 if (${s}A < 255) {
   235                     ${s}R = (${s}R * ${s}A) / 255;
   236                     ${s}G = (${s}G * ${s}A) / 255;
   237                     ${s}B = (${s}B * ${s}A) / 255;
   238                 }
   239             }
   240             switch (flags & (SDL_COPY_BLEND|SDL_COPY_ADD|SDL_COPY_MOD)) {
   241             case SDL_COPY_BLEND:
   242                 ${d}R = ${s}R + ((255 - ${s}A) * ${d}R) / 255;
   243                 ${d}G = ${s}G + ((255 - ${s}A) * ${d}G) / 255;
   244                 ${d}B = ${s}B + ((255 - ${s}A) * ${d}B) / 255;
   245                 break;
   246             case SDL_COPY_ADD:
   247                 ${d}R = ${s}R + ${d}R; if (${d}R > 255) ${d}R = 255;
   248                 ${d}G = ${s}G + ${d}G; if (${d}G > 255) ${d}G = 255;
   249                 ${d}B = ${s}B + ${d}B; if (${d}B > 255) ${d}B = 255;
   250                 break;
   251             case SDL_COPY_MOD:
   252                 ${d}R = (${s}R * ${d}R) / 255;
   253                 ${d}G = (${s}G * ${d}G) / 255;
   254                 ${d}B = (${s}B * ${d}B) / 255;
   255                 break;
   256             }
   257 __EOF__
   258     }
   259     if ( $blend ) {
   260         set_rgba("dst", $dst);
   261     } else {
   262         set_rgba("", $dst);
   263     }
   264 }
   265 
   266 sub output_copyfunc
   267 {
   268     my $src = shift;
   269     my $dst = shift;
   270     my $modulate = shift;
   271     my $blend = shift;
   272     my $scale = shift;
   273 
   274     output_copyfuncname("static void", $src, $dst, $modulate, $blend, $scale, 1, "\n");
   275     print FILE <<__EOF__;
   276 {
   277 __EOF__
   278     if ( $modulate || $blend ) {
   279         print FILE <<__EOF__;
   280     const int flags = info->flags;
   281 __EOF__
   282     }
   283     if ( $modulate ) {
   284         print FILE <<__EOF__;
   285     const Uint32 modulateR = info->r;
   286     const Uint32 modulateG = info->g;
   287     const Uint32 modulateB = info->b;
   288     const Uint32 modulateA = info->a;
   289 __EOF__
   290     }
   291     if ( $blend ) {
   292         print FILE <<__EOF__;
   293     Uint32 srcpixel;
   294     Uint32 srcR, srcG, srcB, srcA;
   295     Uint32 dstpixel;
   296     Uint32 dstR, dstG, dstB, dstA;
   297 __EOF__
   298     } elsif ( $modulate || $src ne $dst ) {
   299         print FILE <<__EOF__;
   300     Uint32 pixel;
   301     Uint32 R, G, B, A;
   302 __EOF__
   303     }
   304     if ( $scale ) {
   305         print FILE <<__EOF__;
   306     int srcy, srcx;
   307     int posy, posx;
   308     int incy, incx;
   309 
   310     srcy = 0;
   311     posy = 0;
   312     incy = (info->src_h << 16) / info->dst_h;
   313     incx = (info->src_w << 16) / info->dst_w;
   314 
   315     while (info->dst_h--) {
   316         $format_type{$src} *src = 0;
   317         $format_type{$dst} *dst = ($format_type{$dst} *)info->dst;
   318         int n = info->dst_w;
   319         srcx = -1;
   320         posx = 0x10000L;
   321         while (posy >= 0x10000L) {
   322             ++srcy;
   323             posy -= 0x10000L;
   324         }
   325         while (n--) {
   326             if (posx >= 0x10000L) {
   327                 while (posx >= 0x10000L) {
   328                     ++srcx;
   329                     posx -= 0x10000L;
   330                 }
   331                 src = ($format_type{$src} *)(info->src + (srcy * info->src_pitch) + (srcx * $format_size{$src}));
   332 __EOF__
   333         print FILE <<__EOF__;
   334             }
   335 __EOF__
   336         output_copycore($src, $dst, $modulate, $blend);
   337         print FILE <<__EOF__;
   338             posx += incx;
   339             ++dst;
   340         }
   341         posy += incy;
   342         info->dst += info->dst_pitch;
   343     }
   344 __EOF__
   345     } else {
   346         print FILE <<__EOF__;
   347 
   348     while (info->dst_h--) {
   349         $format_type{$src} *src = ($format_type{$src} *)info->src;
   350         $format_type{$dst} *dst = ($format_type{$dst} *)info->dst;
   351         int n = info->dst_w;
   352         while (n--) {
   353 __EOF__
   354         output_copycore($src, $dst, $modulate, $blend);
   355         print FILE <<__EOF__;
   356             ++src;
   357             ++dst;
   358         }
   359         info->src += info->src_pitch;
   360         info->dst += info->dst_pitch;
   361     }
   362 __EOF__
   363     }
   364     print FILE <<__EOF__;
   365 }
   366 
   367 __EOF__
   368 }
   369 
   370 sub output_copyfunc_h
   371 {
   372 }
   373 
   374 sub output_copyinc
   375 {
   376     print FILE <<__EOF__;
   377 #include "SDL_video.h"
   378 #include "SDL_blit.h"
   379 #include "SDL_blit_auto.h"
   380 
   381 __EOF__
   382 }
   383 
   384 sub output_copyfunctable
   385 {
   386     print FILE <<__EOF__;
   387 SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[] = {
   388 __EOF__
   389     for (my $i = 0; $i <= $#src_formats; ++$i) {
   390         my $src = $src_formats[$i];
   391         for (my $j = 0; $j <= $#dst_formats; ++$j) {
   392             my $dst = $dst_formats[$j];
   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 || $blend || $scale ) {
   397                             print FILE "    { SDL_PIXELFORMAT_$src, SDL_PIXELFORMAT_$dst, ";
   398                             my $flags = "";
   399                             my $flag = "";
   400                             if ( $modulate ) {
   401                                 $flag = "SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA";
   402                                 if ( $flags eq "" ) {
   403                                     $flags = $flag;
   404                                 } else {
   405                                     $flags = "$flags | $flag";
   406                                 }
   407                             }
   408                             if ( $blend ) {
   409                                 $flag = "SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD";
   410                                 if ( $flags eq "" ) {
   411                                     $flags = $flag;
   412                                 } else {
   413                                     $flags = "$flags | $flag";
   414                                 }
   415                             }
   416                             if ( $scale ) {
   417                                 $flag = "SDL_COPY_NEAREST";
   418                                 if ( $flags eq "" ) {
   419                                     $flags = $flag;
   420                                 } else {
   421                                     $flags = "$flags | $flag";
   422                                 }
   423                             }
   424                             if ( $flags eq "" ) {
   425                                 $flags = "0";
   426                             }
   427                             print FILE "($flags), SDL_CPU_ANY,";
   428                             output_copyfuncname("", $src_formats[$i], $dst_formats[$j], $modulate, $blend, $scale, 0, " },\n");
   429                         }
   430                     }
   431                 }
   432             }
   433         }
   434     }
   435     print FILE <<__EOF__;
   436     { 0, 0, 0, 0, NULL }
   437 };
   438 
   439 __EOF__
   440 }
   441 
   442 sub output_copyfunc_c
   443 {
   444     my $src = shift;
   445     my $dst = shift;
   446 
   447     for (my $modulate = 0; $modulate <= 1; ++$modulate) {
   448         for (my $blend = 0; $blend <= 1; ++$blend) {
   449             for (my $scale = 0; $scale <= 1; ++$scale) {
   450                 if ( $modulate || $blend || $scale ) {
   451                     output_copyfunc($src, $dst, $modulate, $blend, $scale);
   452                 }
   453             }
   454         }
   455     }
   456 }
   457 
   458 open_file("SDL_blit_auto.h");
   459 output_copydefs();
   460 for (my $i = 0; $i <= $#src_formats; ++$i) {
   461     for (my $j = 0; $j <= $#dst_formats; ++$j) {
   462         output_copyfunc_h($src_formats[$i], $dst_formats[$j]);
   463     }
   464 }
   465 print FILE "\n";
   466 close_file("SDL_blit_auto.h");
   467 
   468 open_file("SDL_blit_auto.c");
   469 output_copyinc();
   470 for (my $i = 0; $i <= $#src_formats; ++$i) {
   471     for (my $j = 0; $j <= $#dst_formats; ++$j) {
   472         output_copyfunc_c($src_formats[$i], $dst_formats[$j]);
   473     }
   474 }
   475 output_copyfunctable();
   476 close_file("SDL_blit_auto.c");