src/video/sdlgenblit.pl
author Sam Lantinga
Tue, 01 Feb 2011 21:23:43 -0800
changeset 5149 be02be2ea897
parent 5140 e743b9c3f6d6
child 5184 d976b67150c5
permissions -rwxr-xr-x
Making the API simpler, removed support for palettized video modes and textures.
     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)) {
   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             }
   252 __EOF__
   253     }
   254     if ( $blend ) {
   255         set_rgba("dst", $dst);
   256     } else {
   257         set_rgba("", $dst);
   258     }
   259 }
   260 
   261 sub output_copyfunc
   262 {
   263     my $src = shift;
   264     my $dst = shift;
   265     my $modulate = shift;
   266     my $blend = shift;
   267     my $scale = shift;
   268 
   269     output_copyfuncname("static void", $src, $dst, $modulate, $blend, $scale, 1, "\n");
   270     print FILE <<__EOF__;
   271 {
   272     const int flags = info->flags;
   273 __EOF__
   274     if ( $modulate ) {
   275         print FILE <<__EOF__;
   276     const Uint32 modulateR = info->r;
   277     const Uint32 modulateG = info->g;
   278     const Uint32 modulateB = info->b;
   279     const Uint32 modulateA = info->a;
   280 __EOF__
   281     }
   282     if ( $blend ) {
   283         print FILE <<__EOF__;
   284     Uint32 srcpixel;
   285     Uint32 srcR, srcG, srcB, srcA;
   286     Uint32 dstpixel;
   287     Uint32 dstR, dstG, dstB, dstA;
   288 __EOF__
   289     } elsif ( $modulate || $src ne $dst ) {
   290         print FILE <<__EOF__;
   291     Uint32 pixel;
   292     Uint32 R, G, B, A;
   293 __EOF__
   294     }
   295     if ( $scale ) {
   296         print FILE <<__EOF__;
   297     int srcy, srcx;
   298     int posy, posx;
   299     int incy, incx;
   300 
   301     srcy = 0;
   302     posy = 0;
   303     incy = (info->src_h << 16) / info->dst_h;
   304     incx = (info->src_w << 16) / info->dst_w;
   305 
   306     while (info->dst_h--) {
   307         $format_type{$src} *src;
   308         $format_type{$dst} *dst = ($format_type{$dst} *)info->dst;
   309         int n = info->dst_w;
   310         srcx = -1;
   311         posx = 0x10000L;
   312         while (posy >= 0x10000L) {
   313             ++srcy;
   314             posy -= 0x10000L;
   315         }
   316         while (n--) {
   317             if (posx >= 0x10000L) {
   318                 while (posx >= 0x10000L) {
   319                     ++srcx;
   320                     posx -= 0x10000L;
   321                 }
   322                 src = ($format_type{$src} *)(info->src + (srcy * info->src_pitch) + (srcx * $format_size{$src}));
   323 __EOF__
   324         print FILE <<__EOF__;
   325             }
   326 __EOF__
   327         output_copycore($src, $dst, $modulate, $blend);
   328         print FILE <<__EOF__;
   329             posx += incx;
   330             ++dst;
   331         }
   332         posy += incy;
   333         info->dst += info->dst_pitch;
   334     }
   335 __EOF__
   336     } else {
   337         print FILE <<__EOF__;
   338 
   339     while (info->dst_h--) {
   340         $format_type{$src} *src = ($format_type{$src} *)info->src;
   341         $format_type{$dst} *dst = ($format_type{$dst} *)info->dst;
   342         int n = info->dst_w;
   343         while (n--) {
   344 __EOF__
   345         output_copycore($src, $dst, $modulate, $blend);
   346         print FILE <<__EOF__;
   347             ++src;
   348             ++dst;
   349         }
   350         info->src += info->src_pitch;
   351         info->dst += info->dst_pitch;
   352     }
   353 __EOF__
   354     }
   355     print FILE <<__EOF__;
   356 }
   357 
   358 __EOF__
   359 }
   360 
   361 sub output_copyfunc_h
   362 {
   363 }
   364 
   365 sub output_copyinc
   366 {
   367     print FILE <<__EOF__;
   368 #include "SDL_video.h"
   369 #include "SDL_blit.h"
   370 #include "SDL_blit_auto.h"
   371 
   372 __EOF__
   373 }
   374 
   375 sub output_copyfunctable
   376 {
   377     print FILE <<__EOF__;
   378 SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[] = {
   379 __EOF__
   380     for (my $i = 0; $i <= $#src_formats; ++$i) {
   381         my $src = $src_formats[$i];
   382         for (my $j = 0; $j <= $#dst_formats; ++$j) {
   383             my $dst = $dst_formats[$j];
   384             for (my $modulate = 0; $modulate <= 1; ++$modulate) {
   385                 for (my $blend = 0; $blend <= 1; ++$blend) {
   386                     for (my $scale = 0; $scale <= 1; ++$scale) {
   387                         if ( $modulate || $blend || $scale ) {
   388                             print FILE "    { SDL_PIXELFORMAT_$src, SDL_PIXELFORMAT_$dst, ";
   389                             my $flags = "";
   390                             my $flag = "";
   391                             if ( $modulate ) {
   392                                 $flag = "SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA";
   393                                 if ( $flags eq "" ) {
   394                                     $flags = $flag;
   395                                 } else {
   396                                     $flags = "$flags | $flag";
   397                                 }
   398                             }
   399                             if ( $blend ) {
   400                                 $flag = "SDL_COPY_BLEND | SDL_COPY_ADD";
   401                                 if ( $flags eq "" ) {
   402                                     $flags = $flag;
   403                                 } else {
   404                                     $flags = "$flags | $flag";
   405                                 }
   406                             }
   407                             if ( $scale ) {
   408                                 $flag = "SDL_COPY_NEAREST";
   409                                 if ( $flags eq "" ) {
   410                                     $flags = $flag;
   411                                 } else {
   412                                     $flags = "$flags | $flag";
   413                                 }
   414                             }
   415                             if ( $flags eq "" ) {
   416                                 $flags = "0";
   417                             }
   418                             print FILE "($flags), SDL_CPU_ANY,";
   419                             output_copyfuncname("", $src_formats[$i], $dst_formats[$j], $modulate, $blend, $scale, 0, " },\n");
   420                         }
   421                     }
   422                 }
   423             }
   424         }
   425     }
   426     print FILE <<__EOF__;
   427     { 0, 0, 0, 0, NULL }
   428 };
   429 
   430 __EOF__
   431 }
   432 
   433 sub output_copyfunc_c
   434 {
   435     my $src = shift;
   436     my $dst = shift;
   437 
   438     for (my $modulate = 0; $modulate <= 1; ++$modulate) {
   439         for (my $blend = 0; $blend <= 1; ++$blend) {
   440             for (my $scale = 0; $scale <= 1; ++$scale) {
   441                 if ( $modulate || $blend || $scale ) {
   442                     output_copyfunc($src, $dst, $modulate, $blend, $scale);
   443                 }
   444             }
   445         }
   446     }
   447 }
   448 
   449 open_file("SDL_blit_auto.h");
   450 output_copydefs();
   451 for (my $i = 0; $i <= $#src_formats; ++$i) {
   452     for (my $j = 0; $j <= $#dst_formats; ++$j) {
   453         output_copyfunc_h($src_formats[$i], $dst_formats[$j]);
   454     }
   455 }
   456 print FILE "\n";
   457 close_file("SDL_blit_auto.h");
   458 
   459 open_file("SDL_blit_auto.c");
   460 output_copyinc();
   461 for (my $i = 0; $i <= $#src_formats; ++$i) {
   462     for (my $j = 0; $j <= $#dst_formats; ++$j) {
   463         output_copyfunc_c($src_formats[$i], $dst_formats[$j]);
   464     }
   465 }
   466 output_copyfunctable();
   467 close_file("SDL_blit_auto.c");