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