src/video/sdlgenblit.pl
author Sam Lantinga <slouken@libsdl.org>
Mon, 31 Jan 2011 23:23:57 -0800
changeset 5140 e743b9c3f6d6
parent 2859 99210400e8b9
child 5149 be02be2ea897
permissions -rwxr-xr-x
Making the API simpler, the blend modes are "none, blend, add" and are supported by all renderers.
     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     "ARGB8888",
    42 );
    43 
    44 my %format_size = (
    45     "RGB888" => 4,
    46     "BGR888" => 4,
    47     "ARGB8888" => 4,
    48     "RGBA8888" => 4,
    49     "ABGR8888" => 4,
    50     "BGRA8888" => 4,
    51 );
    52 
    53 my %format_type = (
    54     "RGB888" => "Uint32",
    55     "BGR888" => "Uint32",
    56     "ARGB8888" => "Uint32",
    57     "RGBA8888" => "Uint32",
    58     "ABGR8888" => "Uint32",
    59     "BGRA8888" => "Uint32",
    60 );
    61 
    62 my %get_rgba_string = (
    63     "RGB888" => "_R = (Uint8)(_pixel >> 16); _G = (Uint8)(_pixel >> 8); _B = (Uint8)_pixel; _A = 0xFF;",
    64     "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;",
    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     "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 
    79 sub open_file {
    80     my $name = shift;
    81     open(FILE, ">$name.new") || die "Cant' open $name.new: $!";
    82     print FILE <<__EOF__;
    83 /* DO NOT EDIT!  This file is generated by sdlgenblit.pl */
    84 /*
    85     SDL - Simple DirectMedia Layer
    86     Copyright (C) 1997-2011 Sam Lantinga
    87 
    88     This library is free software; you can redistribute it and/or
    89     modify it under the terms of the GNU Lesser General Public
    90     License as published by the Free Software Foundation; either
    91     version 2.1 of the License, or (at your option) any later version.
    92 
    93     This library is distributed in the hope that it will be useful,
    94     but WITHOUT ANY WARRANTY; without even the implied warranty of
    95     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    96     Lesser General Public License for more details.
    97 
    98     You should have received a copy of the GNU Lesser General Public
    99     License along with this library; if not, write to the Free Software
   100     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   101 
   102     Sam Lantinga
   103     slouken\@libsdl.org
   104 */
   105 #include "SDL_config.h"
   106 
   107 /* *INDENT-OFF* */
   108 
   109 __EOF__
   110 }
   111 
   112 sub close_file {
   113     my $name = shift;
   114     print FILE <<__EOF__;
   115 /* *INDENT-ON* */
   116 
   117 /* vi: set ts=4 sw=4 expandtab: */
   118 __EOF__
   119     close FILE;
   120     if ( ! -f $name || system("cmp -s $name $name.new") != 0 ) {
   121         rename("$name.new", "$name");
   122     } else {
   123         unlink("$name.new");
   124     }
   125 }
   126 
   127 sub output_copydefs
   128 {
   129     print FILE <<__EOF__;
   130 extern SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[];
   131 __EOF__
   132 }
   133 
   134 sub output_copyfuncname
   135 {
   136     my $prefix = shift;
   137     my $src = shift;
   138     my $dst = shift;
   139     my $modulate = shift;
   140     my $blend = shift;
   141     my $scale = shift;
   142     my $args = shift;
   143     my $suffix = shift;
   144 
   145     print FILE "$prefix SDL_Blit_${src}_${dst}";
   146     if ( $modulate ) {
   147         print FILE "_Modulate";
   148     }
   149     if ( $blend ) {
   150         print FILE "_Blend";
   151     }
   152     if ( $scale ) {
   153         print FILE "_Scale";
   154     }
   155     if ( $args ) {
   156         print FILE "(SDL_BlitInfo *info)";
   157     }
   158     print FILE "$suffix";
   159 }
   160 
   161 sub get_rgba
   162 {
   163     my $prefix = shift;
   164     my $format = shift;
   165     my $string = $get_rgba_string{$format};
   166     $string =~ s/_/$prefix/g;
   167     if ( $prefix ne "" ) {
   168         print FILE <<__EOF__;
   169             ${prefix}pixel = *$prefix;
   170 __EOF__
   171     } else {
   172         print FILE <<__EOF__;
   173             pixel = *src;
   174 __EOF__
   175     }
   176     print FILE <<__EOF__;
   177             $string
   178 __EOF__
   179 }
   180 
   181 sub set_rgba
   182 {
   183     my $prefix = shift;
   184     my $format = shift;
   185     my $string = $set_rgba_string{$format};
   186     $string =~ s/_/$prefix/g;
   187     print FILE <<__EOF__;
   188             $string
   189             *dst = ${prefix}pixel;
   190 __EOF__
   191 }
   192 
   193 sub output_copycore
   194 {
   195     my $src = shift;
   196     my $dst = shift;
   197     my $modulate = shift;
   198     my $blend = shift;
   199     my $s = "";
   200     my $d = "";
   201 
   202     # Nice and easy...
   203     if ( $src eq $dst && !$modulate && !$blend ) {
   204         print FILE <<__EOF__;
   205             *dst = *src;
   206 __EOF__
   207         return;
   208     }
   209 
   210     if ( $blend ) {
   211         get_rgba("src", $src);
   212         get_rgba("dst", $dst);
   213         $s = "src";
   214         $d = "dst";
   215     } else {
   216         get_rgba("", $src);
   217     }
   218 
   219     if ( $modulate ) {
   220         print FILE <<__EOF__;
   221             if (flags & SDL_COPY_MODULATE_COLOR) {
   222                 ${s}R = (${s}R * modulateR) / 255;
   223                 ${s}G = (${s}G * modulateG) / 255;
   224                 ${s}B = (${s}B * modulateB) / 255;
   225             }
   226             if (flags & SDL_COPY_MODULATE_ALPHA) {
   227                 ${s}A = (${s}A * modulateA) / 255;
   228             }
   229 __EOF__
   230     }
   231     if ( $blend ) {
   232         print FILE <<__EOF__;
   233             if (flags & (SDL_COPY_BLEND|SDL_COPY_ADD)) {
   234                 /* This goes away if we ever use premultiplied alpha */
   235                 if (${s}A < 255) {
   236                     ${s}R = (${s}R * ${s}A) / 255;
   237                     ${s}G = (${s}G * ${s}A) / 255;
   238                     ${s}B = (${s}B * ${s}A) / 255;
   239                 }
   240             }
   241             switch (flags & (SDL_COPY_BLEND|SDL_COPY_ADD)) {
   242             case SDL_COPY_BLEND:
   243                 ${d}R = ${s}R + ((255 - ${s}A) * ${d}R) / 255;
   244                 ${d}G = ${s}G + ((255 - ${s}A) * ${d}G) / 255;
   245                 ${d}B = ${s}B + ((255 - ${s}A) * ${d}B) / 255;
   246                 break;
   247             case SDL_COPY_ADD:
   248                 ${d}R = ${s}R + ${d}R; if (${d}R > 255) ${d}R = 255;
   249                 ${d}G = ${s}G + ${d}G; if (${d}G > 255) ${d}G = 255;
   250                 ${d}B = ${s}B + ${d}B; if (${d}B > 255) ${d}B = 255;
   251                 break;
   252             }
   253 __EOF__
   254     }
   255     if ( $blend ) {
   256         set_rgba("dst", $dst);
   257     } else {
   258         set_rgba("", $dst);
   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("static void", $src, $dst, $modulate, $blend, $scale, 1, "\n");
   271     print FILE <<__EOF__;
   272 {
   273     const int flags = info->flags;
   274 __EOF__
   275     if ( $modulate ) {
   276         print FILE <<__EOF__;
   277     const Uint32 modulateR = info->r;
   278     const Uint32 modulateG = info->g;
   279     const Uint32 modulateB = info->b;
   280     const Uint32 modulateA = info->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 = (info->src_h << 16) / info->dst_h;
   305     incx = (info->src_w << 16) / info->dst_w;
   306 
   307     while (info->dst_h--) {
   308         $format_type{$src} *src;
   309         $format_type{$dst} *dst = ($format_type{$dst} *)info->dst;
   310         int n = info->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} *)(info->src + (srcy * info->src_pitch) + (srcx * $format_size{$src}));
   324 __EOF__
   325         print FILE <<__EOF__;
   326             }
   327 __EOF__
   328         output_copycore($src, $dst, $modulate, $blend);
   329         print FILE <<__EOF__;
   330             posx += incx;
   331             ++dst;
   332         }
   333         posy += incy;
   334         info->dst += info->dst_pitch;
   335     }
   336 __EOF__
   337     } else {
   338         print FILE <<__EOF__;
   339 
   340     while (info->dst_h--) {
   341         $format_type{$src} *src = ($format_type{$src} *)info->src;
   342         $format_type{$dst} *dst = ($format_type{$dst} *)info->dst;
   343         int n = info->dst_w;
   344         while (n--) {
   345 __EOF__
   346         output_copycore($src, $dst, $modulate, $blend);
   347         print FILE <<__EOF__;
   348             ++src;
   349             ++dst;
   350         }
   351         info->src += info->src_pitch;
   352         info->dst += info->dst_pitch;
   353     }
   354 __EOF__
   355     }
   356     print FILE <<__EOF__;
   357 }
   358 
   359 __EOF__
   360 }
   361 
   362 sub output_copyfunc_h
   363 {
   364 }
   365 
   366 sub output_copyinc
   367 {
   368     print FILE <<__EOF__;
   369 #include "SDL_video.h"
   370 #include "SDL_blit.h"
   371 #include "SDL_blit_auto.h"
   372 
   373 __EOF__
   374 }
   375 
   376 sub output_copyfunctable
   377 {
   378     print FILE <<__EOF__;
   379 SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[] = {
   380 __EOF__
   381     for (my $i = 0; $i <= $#src_formats; ++$i) {
   382         my $src = $src_formats[$i];
   383         for (my $j = 0; $j <= $#dst_formats; ++$j) {
   384             my $dst = $dst_formats[$j];
   385             for (my $modulate = 0; $modulate <= 1; ++$modulate) {
   386                 for (my $blend = 0; $blend <= 1; ++$blend) {
   387                     for (my $scale = 0; $scale <= 1; ++$scale) {
   388                         if ( $modulate || $blend || $scale ) {
   389                             print FILE "    { SDL_PIXELFORMAT_$src, SDL_PIXELFORMAT_$dst, ";
   390                             my $flags = "";
   391                             my $flag = "";
   392                             if ( $modulate ) {
   393                                 $flag = "SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA";
   394                                 if ( $flags eq "" ) {
   395                                     $flags = $flag;
   396                                 } else {
   397                                     $flags = "$flags | $flag";
   398                                 }
   399                             }
   400                             if ( $blend ) {
   401                                 $flag = "SDL_COPY_BLEND | SDL_COPY_ADD";
   402                                 if ( $flags eq "" ) {
   403                                     $flags = $flag;
   404                                 } else {
   405                                     $flags = "$flags | $flag";
   406                                 }
   407                             }
   408                             if ( $scale ) {
   409                                 $flag = "SDL_COPY_NEAREST";
   410                                 if ( $flags eq "" ) {
   411                                     $flags = $flag;
   412                                 } else {
   413                                     $flags = "$flags | $flag";
   414                                 }
   415                             }
   416                             if ( $flags eq "" ) {
   417                                 $flags = "0";
   418                             }
   419                             print FILE "($flags), SDL_CPU_ANY,";
   420                             output_copyfuncname("", $src_formats[$i], $dst_formats[$j], $modulate, $blend, $scale, 0, " },\n");
   421                         }
   422                     }
   423                 }
   424             }
   425         }
   426     }
   427     print FILE <<__EOF__;
   428     { 0, 0, 0, 0, NULL }
   429 };
   430 
   431 __EOF__
   432 }
   433 
   434 sub output_copyfunc_c
   435 {
   436     my $src = shift;
   437     my $dst = shift;
   438 
   439     for (my $modulate = 0; $modulate <= 1; ++$modulate) {
   440         for (my $blend = 0; $blend <= 1; ++$blend) {
   441             for (my $scale = 0; $scale <= 1; ++$scale) {
   442                 if ( $modulate || $blend || $scale ) {
   443                     output_copyfunc($src, $dst, $modulate, $blend, $scale);
   444                 }
   445             }
   446         }
   447     }
   448 }
   449 
   450 open_file("SDL_blit_auto.h");
   451 output_copydefs();
   452 for (my $i = 0; $i <= $#src_formats; ++$i) {
   453     for (my $j = 0; $j <= $#dst_formats; ++$j) {
   454         output_copyfunc_h($src_formats[$i], $dst_formats[$j]);
   455     }
   456 }
   457 print FILE "\n";
   458 close_file("SDL_blit_auto.h");
   459 
   460 open_file("SDL_blit_auto.c");
   461 output_copyinc();
   462 for (my $i = 0; $i <= $#src_formats; ++$i) {
   463     for (my $j = 0; $j <= $#dst_formats; ++$j) {
   464         output_copyfunc_c($src_formats[$i], $dst_formats[$j]);
   465     }
   466 }
   467 output_copyfunctable();
   468 close_file("SDL_blit_auto.c");