src/video/sdlgenblit.pl
author Sam Lantinga
Tue, 29 Aug 2006 08:24:16 +0000
changeset 1992 7387e0514595
parent 1989 5b5f5de5433f
child 2262 bee005ace1bf
permissions -rwxr-xr-x
Take advantage of the existing SDL blitters for normal copy blits.
     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 #define SDL_RENDERCOPY_MODULATE_COLOR   0x0001
   127 #define SDL_RENDERCOPY_MODULATE_ALPHA   0x0002
   128 #define SDL_RENDERCOPY_MASK             0x0010
   129 #define SDL_RENDERCOPY_BLEND            0x0020
   130 #define SDL_RENDERCOPY_ADD              0x0040
   131 #define SDL_RENDERCOPY_MOD              0x0080
   132 #define SDL_RENDERCOPY_NEAREST          0x0100
   133 
   134 typedef struct {
   135     void *src;
   136     int src_w, src_h;
   137     int src_pitch;
   138     void *dst;
   139     int dst_w, dst_h;
   140     int dst_pitch;
   141     void *aux_data;
   142     int flags;
   143     Uint8 r, g, b, a;
   144 } SDL_RenderCopyData;
   145 
   146 typedef int (*SDL_RenderCopyFunc)(SDL_RenderCopyData *data);
   147 
   148 extern SDL_RenderCopyFunc SDLCALL SDL_GetRenderCopyFunc(Uint32 src_format, Uint32 dst_format, int modMode, int blendMode, int scaleMode);
   149 
   150 __EOF__
   151 }
   152 
   153 sub output_copyfuncname
   154 {
   155     my $prefix = shift;
   156     my $src = shift;
   157     my $dst = shift;
   158     my $modulate = shift;
   159     my $blend = shift;
   160     my $scale = shift;
   161     my $args = shift;
   162     my $suffix = shift;
   163 
   164     print FILE "$prefix SDL_RenderCopy_${src}_${dst}";
   165     if ( $modulate ) {
   166         print FILE "_Modulate";
   167     }
   168     if ( $blend ) {
   169         print FILE "_Blend";
   170     }
   171     if ( $scale ) {
   172         print FILE "_Scale";
   173     }
   174     if ( $args ) {
   175         print FILE "(SDL_RenderCopyData *data)";
   176     }
   177     print FILE "$suffix";
   178 }
   179 
   180 sub get_rgba
   181 {
   182     my $prefix = shift;
   183     my $format = shift;
   184     my $string = $get_rgba_string{$format};
   185     $string =~ s/_/$prefix/g;
   186     if ( $prefix ne "" ) {
   187         print FILE <<__EOF__;
   188             ${prefix}pixel = *$prefix;
   189 __EOF__
   190     } else {
   191         print FILE <<__EOF__;
   192             pixel = *src;
   193 __EOF__
   194     }
   195     print FILE <<__EOF__;
   196             $string
   197 __EOF__
   198 }
   199 
   200 sub set_rgba
   201 {
   202     my $prefix = shift;
   203     my $format = shift;
   204     my $string = $set_rgba_string{$format};
   205     $string =~ s/_/$prefix/g;
   206     print FILE <<__EOF__;
   207             $string
   208             *dst = ${prefix}pixel;
   209 __EOF__
   210 }
   211 
   212 sub output_copycore
   213 {
   214     my $src = shift;
   215     my $dst = shift;
   216     my $modulate = shift;
   217     my $blend = shift;
   218     my $s = "";
   219     my $d = "";
   220 
   221     # Nice and easy...
   222     if ( $src eq $dst && !$modulate && !$blend ) {
   223         print FILE <<__EOF__;
   224             *dst = *src;
   225 __EOF__
   226         return;
   227     }
   228         
   229     if ( $blend ) {
   230         get_rgba("src", $src);
   231         get_rgba("dst", $dst);
   232         $s = "src";
   233         $d = "dst";
   234     } else {
   235         get_rgba("", $src);
   236     }
   237 
   238     if ( $modulate ) {
   239         print FILE <<__EOF__;
   240             if (flags & SDL_RENDERCOPY_MODULATE_COLOR) {
   241                 ${s}R = (${s}R * modulateR) / 255;
   242                 ${s}G = (${s}G * modulateG) / 255;
   243                 ${s}B = (${s}B * modulateB) / 255;
   244             }
   245             if (flags & SDL_RENDERCOPY_MODULATE_ALPHA) {
   246                 ${s}A = (${s}A * modulateA) / 255;
   247             }
   248 __EOF__
   249     }
   250     if ( $blend ) {
   251         print FILE <<__EOF__;
   252             if (flags & (SDL_RENDERCOPY_BLEND|SDL_RENDERCOPY_ADD)) {
   253                 /* This goes away if we ever use premultiplied alpha */
   254                 if (${s}A < 255) {
   255                     ${s}R = (${s}R * ${s}A) / 255;
   256                     ${s}G = (${s}G * ${s}A) / 255;
   257                     ${s}B = (${s}B * ${s}A) / 255;
   258                 }
   259             }
   260             switch (flags & (SDL_RENDERCOPY_MASK|SDL_RENDERCOPY_BLEND|SDL_RENDERCOPY_ADD|SDL_RENDERCOPY_MOD)) {
   261             case SDL_RENDERCOPY_MASK:
   262                 if (${s}A) {
   263                     ${d}R = ${s}R;
   264                     ${d}G = ${s}G;
   265                     ${d}B = ${s}B;
   266                 }
   267                 break;
   268             case SDL_RENDERCOPY_BLEND:
   269                 ${d}R = ${s}R + ((255 - ${s}A) * ${d}R) / 255;
   270                 ${d}G = ${s}G + ((255 - ${s}A) * ${d}G) / 255;
   271                 ${d}B = ${s}B + ((255 - ${s}A) * ${d}B) / 255;
   272                 break;
   273             case SDL_RENDERCOPY_ADD:
   274                 ${d}R = ${s}R + ${d}R; if (${d}R > 255) ${d}R = 255;
   275                 ${d}G = ${s}G + ${d}G; if (${d}G > 255) ${d}G = 255;
   276                 ${d}B = ${s}B + ${d}B; if (${d}B > 255) ${d}B = 255;
   277                 break;
   278             case SDL_RENDERCOPY_MOD:
   279                 ${d}R = (${s}R * ${d}R) / 255;
   280                 ${d}G = (${s}G * ${d}G) / 255;
   281                 ${d}B = (${s}B * ${d}B) / 255;
   282                 break;
   283             }
   284 __EOF__
   285     }
   286     if ( $blend ) {
   287         set_rgba("dst", $dst);
   288     } else {
   289         set_rgba("", $dst);
   290     }
   291 }
   292 
   293 sub output_copyfunc
   294 {
   295     my $src = shift;
   296     my $dst = shift;
   297     my $modulate = shift;
   298     my $blend = shift;
   299     my $scale = shift;
   300 
   301     output_copyfuncname("int", $src, $dst, $modulate, $blend, $scale, 1, "\n");
   302     print FILE <<__EOF__;
   303 {
   304     const int flags = data->flags;
   305 __EOF__
   306     if ( $modulate ) {
   307         print FILE <<__EOF__;
   308     const Uint32 modulateR = data->r;
   309     const Uint32 modulateG = data->g;
   310     const Uint32 modulateB = data->b;
   311     const Uint32 modulateA = data->a;
   312 __EOF__
   313     }
   314     if ( $blend ) {
   315         print FILE <<__EOF__;
   316     Uint32 srcpixel;
   317     Uint32 srcR, srcG, srcB, srcA;
   318     Uint32 dstpixel;
   319     Uint32 dstR, dstG, dstB, dstA;
   320 __EOF__
   321     } elsif ( $modulate || $src ne $dst ) {
   322         print FILE <<__EOF__;
   323     Uint32 pixel;
   324     Uint32 R, G, B, A;
   325 __EOF__
   326     }
   327     if ( $scale ) {
   328         print FILE <<__EOF__;
   329     int srcy, srcx;
   330     int posy, posx;
   331     int incy, incx;
   332 
   333     srcy = 0;
   334     posy = 0;
   335     incy = (data->src_h << 16) / data->dst_h;
   336     incx = (data->src_w << 16) / data->dst_w;
   337 
   338     while (data->dst_h--) {
   339         $format_type{$src} *src;
   340         $format_type{$dst} *dst = ($format_type{$dst} *)data->dst;
   341         int n = data->dst_w;
   342         srcx = -1;
   343         posx = 0x10000L;
   344         while (posy >= 0x10000L) {
   345             ++srcy;
   346             posy -= 0x10000L;
   347         }
   348         while (n--) {
   349             if (posx >= 0x10000L) {
   350                 while (posx >= 0x10000L) {
   351                     ++srcx;
   352                     posx -= 0x10000L;
   353                 }
   354                 src = ($format_type{$src} *)(data->src + (srcy * data->src_pitch) + (srcx * $format_size{$src}));
   355 __EOF__
   356         print FILE <<__EOF__;
   357             }
   358 __EOF__
   359         output_copycore($src, $dst, $modulate, $blend);
   360         print FILE <<__EOF__;
   361             posx += incx;
   362             ++dst;
   363         }
   364         posy += incy;
   365         data->dst += data->dst_pitch;
   366     }
   367 __EOF__
   368     } else {
   369         print FILE <<__EOF__;
   370 
   371     while (data->dst_h--) {
   372         $format_type{$src} *src = ($format_type{$src} *)data->src;
   373         $format_type{$dst} *dst = ($format_type{$dst} *)data->dst;
   374         int n = data->dst_w;
   375         while (n--) {
   376 __EOF__
   377         output_copycore($src, $dst, $modulate, $blend);
   378         print FILE <<__EOF__;
   379             ++src;
   380             ++dst;
   381         }
   382         data->src += data->src_pitch;
   383         data->dst += data->dst_pitch;
   384     }
   385 __EOF__
   386     }
   387     print FILE <<__EOF__;
   388     return 0;
   389 }
   390 
   391 __EOF__
   392 }
   393 
   394 sub output_copyfunc_h
   395 {
   396     my $src = shift;
   397     my $dst = shift;
   398     for (my $modulate = 0; $modulate <= 1; ++$modulate) {
   399         for (my $blend = 0; $blend <= 1; ++$blend) {
   400             for (my $scale = 0; $scale <= 1; ++$scale) {
   401                 if ( $modulate || $blend || $scale ) {
   402                     output_copyfuncname("extern int SDLCALL", $src, $dst, $modulate, $blend, $scale, 1, ";\n");
   403                 }
   404             }
   405         }
   406     }
   407 }
   408 
   409 sub output_copyinc
   410 {
   411     print FILE <<__EOF__;
   412 #include "SDL_video.h"
   413 #include "SDL_rendercopy.h"
   414 
   415 __EOF__
   416 }
   417 
   418 sub output_copyfunctable
   419 {
   420     print FILE <<__EOF__;
   421 static struct {
   422     Uint32 src_format;
   423     Uint32 dst_format;
   424     int modMode;
   425     int blendMode;
   426     int scaleMode;
   427     SDL_RenderCopyFunc func;
   428 } SDL_RenderCopyFuncTable[] = {
   429 __EOF__
   430     for (my $i = 0; $i <= $#src_formats; ++$i) {
   431         my $src = $src_formats[$i];
   432         for (my $j = 0; $j <= $#dst_formats; ++$j) {
   433             my $dst = $dst_formats[$j];
   434             for (my $modulate = 0; $modulate <= 1; ++$modulate) {
   435                 for (my $blend = 0; $blend <= 1; ++$blend) {
   436                     for (my $scale = 0; $scale <= 1; ++$scale) {
   437                         if ( $modulate || $blend || $scale ) {
   438                             print FILE "    { SDL_PIXELFORMAT_$src, SDL_PIXELFORMAT_$dst, ";
   439                             if ( $modulate ) {
   440                                 print FILE "(SDL_TEXTUREMODULATE_COLOR | SDL_TEXTUREMODULATE_ALPHA), ";
   441                             } else {
   442                                 print FILE "0, ";
   443                             }
   444                             if ( $blend ) {
   445                                 print FILE "(SDL_TEXTUREBLENDMODE_MASK | SDL_TEXTUREBLENDMODE_BLEND | SDL_TEXTUREBLENDMODE_ADD | SDL_TEXTUREBLENDMODE_MOD), ";
   446                             } else {
   447                                 print FILE "0, ";
   448                             }
   449                             if ( $scale ) {
   450                                 print FILE "SDL_TEXTURESCALEMODE_FAST, ";
   451                             } else {
   452                                 print FILE "0, ";
   453                             }
   454                             output_copyfuncname("", $src_formats[$i], $dst_formats[$j], $modulate, $blend, $scale, 0, " },\n");
   455                         }
   456                     }
   457                 }
   458             }
   459         }
   460     }
   461     print FILE <<__EOF__;
   462 };
   463 
   464 SDL_RenderCopyFunc SDL_GetRenderCopyFunc(Uint32 src_format, Uint32 dst_format, int modMode, int blendMode, int scaleMode)
   465 {
   466     int i;
   467 
   468     for (i = 0; i < SDL_arraysize(SDL_RenderCopyFuncTable); ++i) {
   469         if (src_format != SDL_RenderCopyFuncTable[i].src_format) {
   470             continue;
   471         }
   472         if (dst_format != SDL_RenderCopyFuncTable[i].dst_format) {
   473             continue;
   474         }
   475         if ((modMode & SDL_RenderCopyFuncTable[i].modMode) != modMode) {
   476             continue;
   477         }
   478         if ((blendMode & SDL_RenderCopyFuncTable[i].blendMode) != blendMode) {
   479             continue;
   480         }
   481         if ((scaleMode & SDL_RenderCopyFuncTable[i].scaleMode) != scaleMode) {
   482             continue;
   483         }
   484         return SDL_RenderCopyFuncTable[i].func;
   485     }
   486     return NULL;
   487 }
   488 
   489 __EOF__
   490 }
   491 
   492 sub output_copyfunc_c
   493 {
   494     my $src = shift;
   495     my $dst = shift;
   496 
   497     for (my $modulate = 0; $modulate <= 1; ++$modulate) {
   498         for (my $blend = 0; $blend <= 1; ++$blend) {
   499             for (my $scale = 0; $scale <= 1; ++$scale) {
   500                 if ( $modulate || $blend || $scale ) {
   501                     output_copyfunc($src, $dst, $modulate, $blend, $scale);
   502                 }
   503             }
   504         }
   505     }
   506 }
   507 
   508 open_file("SDL_rendercopy.h");
   509 output_copydefs();
   510 for (my $i = 0; $i <= $#src_formats; ++$i) {
   511     for (my $j = 0; $j <= $#dst_formats; ++$j) {
   512         output_copyfunc_h($src_formats[$i], $dst_formats[$j]);
   513     }
   514 }
   515 print FILE "\n";
   516 close_file("SDL_rendercopy.h");
   517 
   518 open_file("SDL_rendercopy.c");
   519 output_copyinc();
   520 output_copyfunctable();
   521 for (my $i = 0; $i <= $#src_formats; ++$i) {
   522     for (my $j = 0; $j <= $#dst_formats; ++$j) {
   523         output_copyfunc_c($src_formats[$i], $dst_formats[$j]);
   524     }
   525 }
   526 close_file("SDL_rendercopy.c");