src/video/sdlgenblit.pl
author Ryan C. Gordon
Thu, 20 Mar 2014 17:55:24 -0400
changeset 8659 d3a9836732ea
parent 8149 681eb46b8ac4
child 8661 e9e62c8fffb6
permissions -rwxr-xr-x
Static analysis fix: clean up unused variables and dead stores in blitters.
     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_ignore_alpha = (
    62     "RGB888" => "_R = (Uint8)(_pixel >> 16); _G = (Uint8)(_pixel >> 8); _B = (Uint8)_pixel;",
    63     "BGR888" => "_B = (Uint8)(_pixel >> 16); _G = (Uint8)(_pixel >> 8); _R = (Uint8)_pixel;",
    64     "ARGB8888" => "_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);",
    66     "ABGR8888" => "_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);",
    68 );
    69 
    70 my %get_rgba_string = (
    71     "RGB888" => $get_rgba_string_ignore_alpha{"RGB888"} . " _A = 0xFF;",
    72     "BGR888" => $get_rgba_string_ignore_alpha{"BGR888"} . " _A = 0xFF;",
    73     "ARGB8888" => $get_rgba_string_ignore_alpha{"ARGB8888"} . " _A = (Uint8)(_pixel >> 24);",
    74     "RGBA8888" => $get_rgba_string_ignore_alpha{"RGBA8888"} . " _A = (Uint8)_pixel;",
    75     "ABGR8888" => $get_rgba_string_ignore_alpha{"ABGR8888"} . " _A = (Uint8)(_pixel >> 24);",
    76     "BGRA8888" => $get_rgba_string_ignore_alpha{"BGRA8888"} . " _A = (Uint8)_pixel;",
    77 );
    78 
    79 my %set_rgba_string = (
    80     "RGB888" => "_pixel = ((Uint32)_R << 16) | ((Uint32)_G << 8) | _B;",
    81     "BGR888" => "_pixel = ((Uint32)_B << 16) | ((Uint32)_G << 8) | _R;",
    82     "ARGB8888" => "_pixel = ((Uint32)_A << 24) | ((Uint32)_R << 16) | ((Uint32)_G << 8) | _B;",
    83     "RGBA8888" => "_pixel = ((Uint32)_R << 24) | ((Uint32)_G << 16) | ((Uint32)_B << 8) | _A;",
    84     "ABGR8888" => "_pixel = ((Uint32)_A << 24) | ((Uint32)_B << 16) | ((Uint32)_G << 8) | _R;",
    85     "BGRA8888" => "_pixel = ((Uint32)_B << 24) | ((Uint32)_G << 16) | ((Uint32)_R << 8) | _A;",
    86 );
    87 
    88 sub open_file {
    89     my $name = shift;
    90     open(FILE, ">$name.new") || die "Cant' open $name.new: $!";
    91     print FILE <<__EOF__;
    92 /* DO NOT EDIT!  This file is generated by sdlgenblit.pl */
    93 /*
    94   Simple DirectMedia Layer
    95   Copyright (C) 1997-2014 Sam Lantinga <slouken\@libsdl.org>
    96 
    97   This software is provided 'as-is', without any express or implied
    98   warranty.  In no event will the authors be held liable for any damages
    99   arising from the use of this software.
   100 
   101   Permission is granted to anyone to use this software for any purpose,
   102   including commercial applications, and to alter it and redistribute it
   103   freely, subject to the following restrictions:
   104 
   105   1. The origin of this software must not be misrepresented; you must not
   106      claim that you wrote the original software. If you use this software
   107      in a product, an acknowledgment in the product documentation would be
   108      appreciated but is not required.
   109   2. Altered source versions must be plainly marked as such, and must not be
   110      misrepresented as being the original software.
   111   3. This notice may not be removed or altered from any source distribution.
   112 */
   113 #include "../SDL_internal.h"
   114 
   115 /* *INDENT-OFF* */
   116 
   117 __EOF__
   118 }
   119 
   120 sub close_file {
   121     my $name = shift;
   122     print FILE <<__EOF__;
   123 /* *INDENT-ON* */
   124 
   125 /* vi: set ts=4 sw=4 expandtab: */
   126 __EOF__
   127     close FILE;
   128     if ( ! -f $name || system("cmp -s $name $name.new") != 0 ) {
   129         rename("$name.new", "$name");
   130     } else {
   131         unlink("$name.new");
   132     }
   133 }
   134 
   135 sub output_copydefs
   136 {
   137     print FILE <<__EOF__;
   138 extern SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[];
   139 __EOF__
   140 }
   141 
   142 sub output_copyfuncname
   143 {
   144     my $prefix = shift;
   145     my $src = shift;
   146     my $dst = shift;
   147     my $modulate = shift;
   148     my $blend = shift;
   149     my $scale = shift;
   150     my $args = shift;
   151     my $suffix = shift;
   152 
   153     print FILE "$prefix SDL_Blit_${src}_${dst}";
   154     if ( $modulate ) {
   155         print FILE "_Modulate";
   156     }
   157     if ( $blend ) {
   158         print FILE "_Blend";
   159     }
   160     if ( $scale ) {
   161         print FILE "_Scale";
   162     }
   163     if ( $args ) {
   164         print FILE "(SDL_BlitInfo *info)";
   165     }
   166     print FILE "$suffix";
   167 }
   168 
   169 sub get_rgba
   170 {
   171     my $prefix = shift;
   172     my $format = shift;
   173     my $ignore_alpha = shift;
   174 
   175     my $string;
   176     if ($ignore_alpha) {
   177         $string = $get_rgba_string_ignore_alpha{$format};
   178     } else {
   179         $string = $get_rgba_string{$format};
   180     }
   181 
   182     $string =~ s/_/$prefix/g;
   183     if ( $prefix ne "" ) {
   184         print FILE <<__EOF__;
   185             ${prefix}pixel = *$prefix;
   186 __EOF__
   187     } else {
   188         print FILE <<__EOF__;
   189             pixel = *src;
   190 __EOF__
   191     }
   192     print FILE <<__EOF__;
   193             $string
   194 __EOF__
   195 }
   196 
   197 sub set_rgba
   198 {
   199     my $prefix = shift;
   200     my $format = shift;
   201     my $string = $set_rgba_string{$format};
   202     $string =~ s/_/$prefix/g;
   203     print FILE <<__EOF__;
   204             $string
   205             *dst = ${prefix}pixel;
   206 __EOF__
   207 }
   208 
   209 sub output_copycore
   210 {
   211     my $src = shift;
   212     my $dst = shift;
   213     my $modulate = shift;
   214     my $blend = shift;
   215     my $s = "";
   216     my $d = "";
   217     my $ignore_dst_alpha = 0;
   218 
   219     # Nice and easy...
   220     if ( $src eq $dst && !$modulate && !$blend ) {
   221         print FILE <<__EOF__;
   222             *dst = *src;
   223 __EOF__
   224         return;
   225     }
   226 
   227     if (not $dst =~ /A/) {
   228         $ignore_dst_alpha = !$blend;
   229     }
   230 
   231     if ( $blend ) {
   232         get_rgba("src", $src, $ignore_dst_alpha);
   233         get_rgba("dst", $dst, $ignore_dst_alpha);
   234         $s = "src";
   235         $d = "dst";
   236     } else {
   237         get_rgba("", $src, $ignore_dst_alpha);
   238     }
   239 
   240     if ( $modulate ) {
   241         print FILE <<__EOF__;
   242             if (flags & SDL_COPY_MODULATE_COLOR) {
   243                 ${s}R = (${s}R * modulateR) / 255;
   244                 ${s}G = (${s}G * modulateG) / 255;
   245                 ${s}B = (${s}B * modulateB) / 255;
   246             }
   247 __EOF__
   248         if (not $ignore_dst_alpha) {
   249             print FILE <<__EOF__;
   250             if (flags & SDL_COPY_MODULATE_ALPHA) {
   251                 ${s}A = (${s}A * modulateA) / 255;
   252             }
   253 __EOF__
   254         }
   255     }
   256     if ( $blend ) {
   257         print FILE <<__EOF__;
   258             if (flags & (SDL_COPY_BLEND|SDL_COPY_ADD)) {
   259                 /* This goes away if we ever use premultiplied alpha */
   260                 if (${s}A < 255) {
   261                     ${s}R = (${s}R * ${s}A) / 255;
   262                     ${s}G = (${s}G * ${s}A) / 255;
   263                     ${s}B = (${s}B * ${s}A) / 255;
   264                 }
   265             }
   266             switch (flags & (SDL_COPY_BLEND|SDL_COPY_ADD|SDL_COPY_MOD)) {
   267             case SDL_COPY_BLEND:
   268                 ${d}R = ${s}R + ((255 - ${s}A) * ${d}R) / 255;
   269                 ${d}G = ${s}G + ((255 - ${s}A) * ${d}G) / 255;
   270                 ${d}B = ${s}B + ((255 - ${s}A) * ${d}B) / 255;
   271                 ${d}A = ${s}A + ((255 - ${s}A) * ${d}A) / 255;
   272                 break;
   273             case SDL_COPY_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_COPY_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("static void", $src, $dst, $modulate, $blend, $scale, 1, "\n");
   302     print FILE <<__EOF__;
   303 {
   304 __EOF__
   305     if ( $modulate || $blend ) {
   306         print FILE <<__EOF__;
   307     const int flags = info->flags;
   308 __EOF__
   309     }
   310     if ( $modulate ) {
   311         print FILE <<__EOF__;
   312     const Uint32 modulateR = info->r;
   313     const Uint32 modulateG = info->g;
   314     const Uint32 modulateB = info->b;
   315     const Uint32 modulateA = info->a;
   316 __EOF__
   317     }
   318     if ( $blend ) {
   319         print FILE <<__EOF__;
   320     Uint32 srcpixel;
   321     Uint32 srcR, srcG, srcB, srcA;
   322     Uint32 dstpixel;
   323     Uint32 dstR, dstG, dstB, dstA;
   324 __EOF__
   325     } elsif ( $modulate || $src ne $dst ) {
   326         print FILE <<__EOF__;
   327     Uint32 pixel;
   328     Uint32 R, G, B, A;
   329 __EOF__
   330     }
   331     if ( $scale ) {
   332         print FILE <<__EOF__;
   333     int srcy, srcx;
   334     int posy, posx;
   335     int incy, incx;
   336 __EOF__
   337 
   338     # !!! FIXME: the script should just exclude in these cases.
   339     if ( (!$blend) && ($modulate || $src ne $dst) ) {
   340         print FILE <<__EOF__;
   341     (void) A;  /* not all formats use alpha. */
   342 __EOF__
   343     }
   344 
   345     # !!! FIXME: the script should just exclude in these cases.
   346     if ( $modulate ) {
   347         print FILE <<__EOF__;
   348     (void) modulateA;  /* not all formats use alpha. */
   349 __EOF__
   350     }
   351 
   352     print FILE <<__EOF__;
   353 
   354     srcy = 0;
   355     posy = 0;
   356     incy = (info->src_h << 16) / info->dst_h;
   357     incx = (info->src_w << 16) / info->dst_w;
   358 
   359     while (info->dst_h--) {
   360         $format_type{$src} *src = 0;
   361         $format_type{$dst} *dst = ($format_type{$dst} *)info->dst;
   362         int n = info->dst_w;
   363         srcx = -1;
   364         posx = 0x10000L;
   365         while (posy >= 0x10000L) {
   366             ++srcy;
   367             posy -= 0x10000L;
   368         }
   369         while (n--) {
   370             if (posx >= 0x10000L) {
   371                 while (posx >= 0x10000L) {
   372                     ++srcx;
   373                     posx -= 0x10000L;
   374                 }
   375                 src = ($format_type{$src} *)(info->src + (srcy * info->src_pitch) + (srcx * $format_size{$src}));
   376 __EOF__
   377         print FILE <<__EOF__;
   378             }
   379 __EOF__
   380         output_copycore($src, $dst, $modulate, $blend);
   381         print FILE <<__EOF__;
   382             posx += incx;
   383             ++dst;
   384         }
   385         posy += incy;
   386         info->dst += info->dst_pitch;
   387     }
   388 __EOF__
   389     } else {
   390         # !!! FIXME: the script should just exclude in these cases.
   391         if ( (!$blend) && ($modulate || $src ne $dst) ) {
   392             print FILE <<__EOF__;
   393     (void) A;  /* not all formats use alpha. */
   394 __EOF__
   395         }
   396 
   397         # !!! FIXME: the script should just exclude in these cases.
   398         if ( $modulate ) {
   399             print FILE <<__EOF__;
   400     (void) modulateA;  /* not all formats use alpha. */
   401 __EOF__
   402         }
   403 
   404         print FILE <<__EOF__;
   405 
   406     while (info->dst_h--) {
   407         $format_type{$src} *src = ($format_type{$src} *)info->src;
   408         $format_type{$dst} *dst = ($format_type{$dst} *)info->dst;
   409         int n = info->dst_w;
   410         while (n--) {
   411 __EOF__
   412         output_copycore($src, $dst, $modulate, $blend);
   413         print FILE <<__EOF__;
   414             ++src;
   415             ++dst;
   416         }
   417         info->src += info->src_pitch;
   418         info->dst += info->dst_pitch;
   419     }
   420 __EOF__
   421     }
   422     print FILE <<__EOF__;
   423 }
   424 
   425 __EOF__
   426 }
   427 
   428 sub output_copyfunc_h
   429 {
   430 }
   431 
   432 sub output_copyinc
   433 {
   434     print FILE <<__EOF__;
   435 #include "SDL_video.h"
   436 #include "SDL_blit.h"
   437 #include "SDL_blit_auto.h"
   438 
   439 __EOF__
   440 }
   441 
   442 sub output_copyfunctable
   443 {
   444     print FILE <<__EOF__;
   445 SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[] = {
   446 __EOF__
   447     for (my $i = 0; $i <= $#src_formats; ++$i) {
   448         my $src = $src_formats[$i];
   449         for (my $j = 0; $j <= $#dst_formats; ++$j) {
   450             my $dst = $dst_formats[$j];
   451             for (my $modulate = 0; $modulate <= 1; ++$modulate) {
   452                 for (my $blend = 0; $blend <= 1; ++$blend) {
   453                     for (my $scale = 0; $scale <= 1; ++$scale) {
   454                         if ( $modulate || $blend || $scale ) {
   455                             print FILE "    { SDL_PIXELFORMAT_$src, SDL_PIXELFORMAT_$dst, ";
   456                             my $flags = "";
   457                             my $flag = "";
   458                             if ( $modulate ) {
   459                                 $flag = "SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA";
   460                                 if ( $flags eq "" ) {
   461                                     $flags = $flag;
   462                                 } else {
   463                                     $flags = "$flags | $flag";
   464                                 }
   465                             }
   466                             if ( $blend ) {
   467                                 $flag = "SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD";
   468                                 if ( $flags eq "" ) {
   469                                     $flags = $flag;
   470                                 } else {
   471                                     $flags = "$flags | $flag";
   472                                 }
   473                             }
   474                             if ( $scale ) {
   475                                 $flag = "SDL_COPY_NEAREST";
   476                                 if ( $flags eq "" ) {
   477                                     $flags = $flag;
   478                                 } else {
   479                                     $flags = "$flags | $flag";
   480                                 }
   481                             }
   482                             if ( $flags eq "" ) {
   483                                 $flags = "0";
   484                             }
   485                             print FILE "($flags), SDL_CPU_ANY,";
   486                             output_copyfuncname("", $src_formats[$i], $dst_formats[$j], $modulate, $blend, $scale, 0, " },\n");
   487                         }
   488                     }
   489                 }
   490             }
   491         }
   492     }
   493     print FILE <<__EOF__;
   494     { 0, 0, 0, 0, NULL }
   495 };
   496 
   497 __EOF__
   498 }
   499 
   500 sub output_copyfunc_c
   501 {
   502     my $src = shift;
   503     my $dst = shift;
   504 
   505     for (my $modulate = 0; $modulate <= 1; ++$modulate) {
   506         for (my $blend = 0; $blend <= 1; ++$blend) {
   507             for (my $scale = 0; $scale <= 1; ++$scale) {
   508                 if ( $modulate || $blend || $scale ) {
   509                     output_copyfunc($src, $dst, $modulate, $blend, $scale);
   510                 }
   511             }
   512         }
   513     }
   514 }
   515 
   516 open_file("SDL_blit_auto.h");
   517 output_copydefs();
   518 for (my $i = 0; $i <= $#src_formats; ++$i) {
   519     for (my $j = 0; $j <= $#dst_formats; ++$j) {
   520         output_copyfunc_h($src_formats[$i], $dst_formats[$j]);
   521     }
   522 }
   523 print FILE "\n";
   524 close_file("SDL_blit_auto.h");
   525 
   526 open_file("SDL_blit_auto.c");
   527 output_copyinc();
   528 for (my $i = 0; $i <= $#src_formats; ++$i) {
   529     for (my $j = 0; $j <= $#dst_formats; ++$j) {
   530         output_copyfunc_c($src_formats[$i], $dst_formats[$j]);
   531     }
   532 }
   533 output_copyfunctable();
   534 close_file("SDL_blit_auto.c");