src/video/sdlgenblit.pl
author Sam Lantinga <slouken@libsdl.org>
Sun, 14 Jul 2013 11:28:44 -0700
changeset 7776 d4a39491577f
parent 7502 6ff02ff3cf06
child 8093 b43765095a6f
permissions -rwxr-xr-x
Added the platform specific messagebox function to the video function list
     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   Simple DirectMedia Layer
    85   Copyright (C) 1997-2013 Sam Lantinga <slouken\@libsdl.org>
    86 
    87   This software is provided 'as-is', without any express or implied
    88   warranty.  In no event will the authors be held liable for any damages
    89   arising from the use of this software.
    90 
    91   Permission is granted to anyone to use this software for any purpose,
    92   including commercial applications, and to alter it and redistribute it
    93   freely, subject to the following restrictions:
    94 
    95   1. The origin of this software must not be misrepresented; you must not
    96      claim that you wrote the original software. If you use this software
    97      in a product, an acknowledgment in the product documentation would be
    98      appreciated but is not required.
    99   2. Altered source versions must be plainly marked as such, and must not be
   100      misrepresented as being the original software.
   101   3. This notice may not be removed or altered from any source distribution.
   102 */
   103 #include "SDL_config.h"
   104 
   105 /* *INDENT-OFF* */
   106 
   107 __EOF__
   108 }
   109 
   110 sub close_file {
   111     my $name = shift;
   112     print FILE <<__EOF__;
   113 /* *INDENT-ON* */
   114 
   115 /* vi: set ts=4 sw=4 expandtab: */
   116 __EOF__
   117     close FILE;
   118     if ( ! -f $name || system("cmp -s $name $name.new") != 0 ) {
   119         rename("$name.new", "$name");
   120     } else {
   121         unlink("$name.new");
   122     }
   123 }
   124 
   125 sub output_copydefs
   126 {
   127     print FILE <<__EOF__;
   128 extern SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[];
   129 __EOF__
   130 }
   131 
   132 sub output_copyfuncname
   133 {
   134     my $prefix = shift;
   135     my $src = shift;
   136     my $dst = shift;
   137     my $modulate = shift;
   138     my $blend = shift;
   139     my $scale = shift;
   140     my $args = shift;
   141     my $suffix = shift;
   142 
   143     print FILE "$prefix SDL_Blit_${src}_${dst}";
   144     if ( $modulate ) {
   145         print FILE "_Modulate";
   146     }
   147     if ( $blend ) {
   148         print FILE "_Blend";
   149     }
   150     if ( $scale ) {
   151         print FILE "_Scale";
   152     }
   153     if ( $args ) {
   154         print FILE "(SDL_BlitInfo *info)";
   155     }
   156     print FILE "$suffix";
   157 }
   158 
   159 sub get_rgba
   160 {
   161     my $prefix = shift;
   162     my $format = shift;
   163     my $string = $get_rgba_string{$format};
   164     $string =~ s/_/$prefix/g;
   165     if ( $prefix ne "" ) {
   166         print FILE <<__EOF__;
   167             ${prefix}pixel = *$prefix;
   168 __EOF__
   169     } else {
   170         print FILE <<__EOF__;
   171             pixel = *src;
   172 __EOF__
   173     }
   174     print FILE <<__EOF__;
   175             $string
   176 __EOF__
   177 }
   178 
   179 sub set_rgba
   180 {
   181     my $prefix = shift;
   182     my $format = shift;
   183     my $string = $set_rgba_string{$format};
   184     $string =~ s/_/$prefix/g;
   185     print FILE <<__EOF__;
   186             $string
   187             *dst = ${prefix}pixel;
   188 __EOF__
   189 }
   190 
   191 sub output_copycore
   192 {
   193     my $src = shift;
   194     my $dst = shift;
   195     my $modulate = shift;
   196     my $blend = shift;
   197     my $s = "";
   198     my $d = "";
   199 
   200     # Nice and easy...
   201     if ( $src eq $dst && !$modulate && !$blend ) {
   202         print FILE <<__EOF__;
   203             *dst = *src;
   204 __EOF__
   205         return;
   206     }
   207 
   208     if ( $blend ) {
   209         get_rgba("src", $src);
   210         get_rgba("dst", $dst);
   211         $s = "src";
   212         $d = "dst";
   213     } else {
   214         get_rgba("", $src);
   215     }
   216 
   217     if ( $modulate ) {
   218         print FILE <<__EOF__;
   219             if (flags & SDL_COPY_MODULATE_COLOR) {
   220                 ${s}R = (${s}R * modulateR) / 255;
   221                 ${s}G = (${s}G * modulateG) / 255;
   222                 ${s}B = (${s}B * modulateB) / 255;
   223             }
   224             if (flags & SDL_COPY_MODULATE_ALPHA) {
   225                 ${s}A = (${s}A * modulateA) / 255;
   226             }
   227 __EOF__
   228     }
   229     if ( $blend ) {
   230         print FILE <<__EOF__;
   231             if (flags & (SDL_COPY_BLEND|SDL_COPY_ADD)) {
   232                 /* This goes away if we ever use premultiplied alpha */
   233                 if (${s}A < 255) {
   234                     ${s}R = (${s}R * ${s}A) / 255;
   235                     ${s}G = (${s}G * ${s}A) / 255;
   236                     ${s}B = (${s}B * ${s}A) / 255;
   237                 }
   238             }
   239             switch (flags & (SDL_COPY_BLEND|SDL_COPY_ADD|SDL_COPY_MOD)) {
   240             case SDL_COPY_BLEND:
   241                 ${d}R = ${s}R + ((255 - ${s}A) * ${d}R) / 255;
   242                 ${d}G = ${s}G + ((255 - ${s}A) * ${d}G) / 255;
   243                 ${d}B = ${s}B + ((255 - ${s}A) * ${d}B) / 255;
   244                 ${d}A = ${s}A + ((255 - ${s}A) * ${d}A) / 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 __EOF__
   278     if ( $modulate || $blend ) {
   279         print FILE <<__EOF__;
   280     const int flags = info->flags;
   281 __EOF__
   282     }
   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 = 0;
   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 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_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");