src/video/sdlgenblit.pl
author Sam Lantinga
Fri, 17 Aug 2007 06:40:12 +0000
changeset 2263 900c35d8e8fd
parent 2262 bee005ace1bf
child 2267 c785543d1843
permissions -rwxr-xr-x
More work in progress, still doesn't compile...
     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 extern SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[];
   127 __EOF__
   128 }
   129 
   130 sub output_copyfuncname
   131 {
   132     my $prefix = shift;
   133     my $src = shift;
   134     my $dst = shift;
   135     my $modulate = shift;
   136     my $blend = shift;
   137     my $scale = shift;
   138     my $args = shift;
   139     my $suffix = shift;
   140 
   141     print FILE "$prefix SDL_Blit_${src}_${dst}";
   142     if ( $modulate ) {
   143         print FILE "_Modulate";
   144     }
   145     if ( $blend ) {
   146         print FILE "_Blend";
   147     }
   148     if ( $scale ) {
   149         print FILE "_Scale";
   150     }
   151     if ( $args ) {
   152         print FILE "(SDL_BlitInfo *info)";
   153     }
   154     print FILE "$suffix";
   155 }
   156 
   157 sub get_rgba
   158 {
   159     my $prefix = shift;
   160     my $format = shift;
   161     my $string = $get_rgba_string{$format};
   162     $string =~ s/_/$prefix/g;
   163     if ( $prefix ne "" ) {
   164         print FILE <<__EOF__;
   165             ${prefix}pixel = *$prefix;
   166 __EOF__
   167     } else {
   168         print FILE <<__EOF__;
   169             pixel = *src;
   170 __EOF__
   171     }
   172     print FILE <<__EOF__;
   173             $string
   174 __EOF__
   175 }
   176 
   177 sub set_rgba
   178 {
   179     my $prefix = shift;
   180     my $format = shift;
   181     my $string = $set_rgba_string{$format};
   182     $string =~ s/_/$prefix/g;
   183     print FILE <<__EOF__;
   184             $string
   185             *dst = ${prefix}pixel;
   186 __EOF__
   187 }
   188 
   189 sub output_copycore
   190 {
   191     my $src = shift;
   192     my $dst = shift;
   193     my $modulate = shift;
   194     my $blend = shift;
   195     my $s = "";
   196     my $d = "";
   197 
   198     # Nice and easy...
   199     if ( $src eq $dst && !$modulate && !$blend ) {
   200         print FILE <<__EOF__;
   201             *dst = *src;
   202 __EOF__
   203         return;
   204     }
   205 
   206     if ( $blend ) {
   207         get_rgba("src", $src);
   208         get_rgba("dst", $dst);
   209         $s = "src";
   210         $d = "dst";
   211     } else {
   212         get_rgba("", $src);
   213     }
   214 
   215     if ( $modulate ) {
   216         print FILE <<__EOF__;
   217             if (flags & SDL_COPY_MODULATE_COLOR) {
   218                 ${s}R = (${s}R * modulateR) / 255;
   219                 ${s}G = (${s}G * modulateG) / 255;
   220                 ${s}B = (${s}B * modulateB) / 255;
   221             }
   222             if (flags & SDL_COPY_MODULATE_ALPHA) {
   223                 ${s}A = (${s}A * modulateA) / 255;
   224             }
   225 __EOF__
   226     }
   227     if ( $blend ) {
   228         print FILE <<__EOF__;
   229             if (flags & (SDL_COPY_BLEND|SDL_COPY_ADD)) {
   230                 /* This goes away if we ever use premultiplied alpha */
   231                 if (${s}A < 255) {
   232                     ${s}R = (${s}R * ${s}A) / 255;
   233                     ${s}G = (${s}G * ${s}A) / 255;
   234                     ${s}B = (${s}B * ${s}A) / 255;
   235                 }
   236             }
   237             switch (flags & (SDL_COPY_MASK|SDL_COPY_BLEND|SDL_COPY_ADD|SDL_COPY_MOD)) {
   238             case SDL_COPY_MASK:
   239                 if (${s}A) {
   240                     ${d}R = ${s}R;
   241                     ${d}G = ${s}G;
   242                     ${d}B = ${s}B;
   243                 }
   244                 break;
   245             case SDL_COPY_BLEND:
   246                 ${d}R = ${s}R + ((255 - ${s}A) * ${d}R) / 255;
   247                 ${d}G = ${s}G + ((255 - ${s}A) * ${d}G) / 255;
   248                 ${d}B = ${s}B + ((255 - ${s}A) * ${d}B) / 255;
   249                 break;
   250             case SDL_COPY_ADD:
   251                 ${d}R = ${s}R + ${d}R; if (${d}R > 255) ${d}R = 255;
   252                 ${d}G = ${s}G + ${d}G; if (${d}G > 255) ${d}G = 255;
   253                 ${d}B = ${s}B + ${d}B; if (${d}B > 255) ${d}B = 255;
   254                 break;
   255             case SDL_COPY_MOD:
   256                 ${d}R = (${s}R * ${d}R) / 255;
   257                 ${d}G = (${s}G * ${d}G) / 255;
   258                 ${d}B = (${s}B * ${d}B) / 255;
   259                 break;
   260             }
   261 __EOF__
   262     }
   263     if ( $blend ) {
   264         set_rgba("dst", $dst);
   265     } else {
   266         set_rgba("", $dst);
   267     }
   268 }
   269 
   270 sub output_copyfunc
   271 {
   272     my $src = shift;
   273     my $dst = shift;
   274     my $modulate = shift;
   275     my $blend = shift;
   276     my $scale = shift;
   277 
   278     output_copyfuncname("static void", $src, $dst, $modulate, $blend, $scale, 1, "\n");
   279     print FILE <<__EOF__;
   280 {
   281     const int flags = info->flags;
   282 __EOF__
   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;
   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 static 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_MASK | 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");