src/video/sdlgenblit.pl
author Ryan C. Gordon
Fri, 21 Mar 2014 00:57:43 -0400
changeset 8661 e9e62c8fffb6
parent 8659 d3a9836732ea
child 8662 f8e55cba0bca
permissions -rwxr-xr-x
Static analysis fix: more dead stores.
     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 __EOF__
   272 
   273         if ( $dst =~ /A/ ) {
   274             print FILE <<__EOF__;
   275                 ${d}A = ${s}A + ((255 - ${s}A) * ${d}A) / 255;
   276 __EOF__
   277         }
   278 
   279         print FILE <<__EOF__;
   280                 break;
   281             case SDL_COPY_ADD:
   282                 ${d}R = ${s}R + ${d}R; if (${d}R > 255) ${d}R = 255;
   283                 ${d}G = ${s}G + ${d}G; if (${d}G > 255) ${d}G = 255;
   284                 ${d}B = ${s}B + ${d}B; if (${d}B > 255) ${d}B = 255;
   285                 break;
   286             case SDL_COPY_MOD:
   287                 ${d}R = (${s}R * ${d}R) / 255;
   288                 ${d}G = (${s}G * ${d}G) / 255;
   289                 ${d}B = (${s}B * ${d}B) / 255;
   290                 break;
   291             }
   292 __EOF__
   293     }
   294     if ( $blend ) {
   295         set_rgba("dst", $dst);
   296     } else {
   297         set_rgba("", $dst);
   298     }
   299 }
   300 
   301 sub output_copyfunc
   302 {
   303     my $src = shift;
   304     my $dst = shift;
   305     my $modulate = shift;
   306     my $blend = shift;
   307     my $scale = shift;
   308 
   309     output_copyfuncname("static void", $src, $dst, $modulate, $blend, $scale, 1, "\n");
   310     print FILE <<__EOF__;
   311 {
   312 __EOF__
   313     if ( $modulate || $blend ) {
   314         print FILE <<__EOF__;
   315     const int flags = info->flags;
   316 __EOF__
   317     }
   318     if ( $modulate ) {
   319         print FILE <<__EOF__;
   320     const Uint32 modulateR = info->r;
   321     const Uint32 modulateG = info->g;
   322     const Uint32 modulateB = info->b;
   323     const Uint32 modulateA = info->a;
   324 __EOF__
   325     }
   326     if ( $blend ) {
   327         print FILE <<__EOF__;
   328     Uint32 srcpixel;
   329     Uint32 srcR, srcG, srcB, srcA;
   330     Uint32 dstpixel;
   331     Uint32 dstR, dstG, dstB, dstA;
   332 __EOF__
   333     } elsif ( $modulate || $src ne $dst ) {
   334         print FILE <<__EOF__;
   335     Uint32 pixel;
   336     Uint32 R, G, B, A;
   337 __EOF__
   338     }
   339     if ( $scale ) {
   340         print FILE <<__EOF__;
   341     int srcy, srcx;
   342     int posy, posx;
   343     int incy, incx;
   344 __EOF__
   345 
   346     # !!! FIXME: the script should just exclude in these cases.
   347     if ( (!$blend) && ($modulate || $src ne $dst) ) {
   348         print FILE <<__EOF__;
   349     (void) A;  /* not all formats use alpha. */
   350 __EOF__
   351     }
   352 
   353     # !!! FIXME: the script should just exclude in these cases.
   354     if ( $modulate ) {
   355         print FILE <<__EOF__;
   356     (void) modulateA;  /* not all formats use alpha. */
   357 __EOF__
   358     }
   359 
   360     # !!! FIXME: the script should just exclude in these cases.
   361     if ( $blend ) {
   362         print FILE <<__EOF__;
   363     (void) dstA;  /* not all formats use alpha. */
   364 __EOF__
   365     }
   366 
   367     print FILE <<__EOF__;
   368 
   369     srcy = 0;
   370     posy = 0;
   371     incy = (info->src_h << 16) / info->dst_h;
   372     incx = (info->src_w << 16) / info->dst_w;
   373 
   374     while (info->dst_h--) {
   375         $format_type{$src} *src = 0;
   376         $format_type{$dst} *dst = ($format_type{$dst} *)info->dst;
   377         int n = info->dst_w;
   378         srcx = -1;
   379         posx = 0x10000L;
   380         while (posy >= 0x10000L) {
   381             ++srcy;
   382             posy -= 0x10000L;
   383         }
   384         while (n--) {
   385             if (posx >= 0x10000L) {
   386                 while (posx >= 0x10000L) {
   387                     ++srcx;
   388                     posx -= 0x10000L;
   389                 }
   390                 src = ($format_type{$src} *)(info->src + (srcy * info->src_pitch) + (srcx * $format_size{$src}));
   391 __EOF__
   392         print FILE <<__EOF__;
   393             }
   394 __EOF__
   395         output_copycore($src, $dst, $modulate, $blend);
   396         print FILE <<__EOF__;
   397             posx += incx;
   398             ++dst;
   399         }
   400         posy += incy;
   401         info->dst += info->dst_pitch;
   402     }
   403 __EOF__
   404     } else {
   405         # !!! FIXME: the script should just exclude in these cases.
   406         if ( (!$blend) && ($modulate || $src ne $dst) ) {
   407             print FILE <<__EOF__;
   408     (void) A;  /* not all formats use alpha. */
   409 __EOF__
   410         }
   411 
   412         # !!! FIXME: the script should just exclude in these cases.
   413         if ( $modulate ) {
   414             print FILE <<__EOF__;
   415     (void) modulateA;  /* not all formats use alpha. */
   416 __EOF__
   417         }
   418 
   419         # !!! FIXME: the script should just exclude in these cases.
   420         if ( $blend ) {
   421             print FILE <<__EOF__;
   422     (void) dstA;  /* not all formats use alpha. */
   423 __EOF__
   424         }
   425 
   426         print FILE <<__EOF__;
   427 
   428     while (info->dst_h--) {
   429         $format_type{$src} *src = ($format_type{$src} *)info->src;
   430         $format_type{$dst} *dst = ($format_type{$dst} *)info->dst;
   431         int n = info->dst_w;
   432         while (n--) {
   433 __EOF__
   434         output_copycore($src, $dst, $modulate, $blend);
   435         print FILE <<__EOF__;
   436             ++src;
   437             ++dst;
   438         }
   439         info->src += info->src_pitch;
   440         info->dst += info->dst_pitch;
   441     }
   442 __EOF__
   443     }
   444     print FILE <<__EOF__;
   445 }
   446 
   447 __EOF__
   448 }
   449 
   450 sub output_copyfunc_h
   451 {
   452 }
   453 
   454 sub output_copyinc
   455 {
   456     print FILE <<__EOF__;
   457 #include "SDL_video.h"
   458 #include "SDL_blit.h"
   459 #include "SDL_blit_auto.h"
   460 
   461 __EOF__
   462 }
   463 
   464 sub output_copyfunctable
   465 {
   466     print FILE <<__EOF__;
   467 SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[] = {
   468 __EOF__
   469     for (my $i = 0; $i <= $#src_formats; ++$i) {
   470         my $src = $src_formats[$i];
   471         for (my $j = 0; $j <= $#dst_formats; ++$j) {
   472             my $dst = $dst_formats[$j];
   473             for (my $modulate = 0; $modulate <= 1; ++$modulate) {
   474                 for (my $blend = 0; $blend <= 1; ++$blend) {
   475                     for (my $scale = 0; $scale <= 1; ++$scale) {
   476                         if ( $modulate || $blend || $scale ) {
   477                             print FILE "    { SDL_PIXELFORMAT_$src, SDL_PIXELFORMAT_$dst, ";
   478                             my $flags = "";
   479                             my $flag = "";
   480                             if ( $modulate ) {
   481                                 $flag = "SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA";
   482                                 if ( $flags eq "" ) {
   483                                     $flags = $flag;
   484                                 } else {
   485                                     $flags = "$flags | $flag";
   486                                 }
   487                             }
   488                             if ( $blend ) {
   489                                 $flag = "SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD";
   490                                 if ( $flags eq "" ) {
   491                                     $flags = $flag;
   492                                 } else {
   493                                     $flags = "$flags | $flag";
   494                                 }
   495                             }
   496                             if ( $scale ) {
   497                                 $flag = "SDL_COPY_NEAREST";
   498                                 if ( $flags eq "" ) {
   499                                     $flags = $flag;
   500                                 } else {
   501                                     $flags = "$flags | $flag";
   502                                 }
   503                             }
   504                             if ( $flags eq "" ) {
   505                                 $flags = "0";
   506                             }
   507                             print FILE "($flags), SDL_CPU_ANY,";
   508                             output_copyfuncname("", $src_formats[$i], $dst_formats[$j], $modulate, $blend, $scale, 0, " },\n");
   509                         }
   510                     }
   511                 }
   512             }
   513         }
   514     }
   515     print FILE <<__EOF__;
   516     { 0, 0, 0, 0, NULL }
   517 };
   518 
   519 __EOF__
   520 }
   521 
   522 sub output_copyfunc_c
   523 {
   524     my $src = shift;
   525     my $dst = shift;
   526 
   527     for (my $modulate = 0; $modulate <= 1; ++$modulate) {
   528         for (my $blend = 0; $blend <= 1; ++$blend) {
   529             for (my $scale = 0; $scale <= 1; ++$scale) {
   530                 if ( $modulate || $blend || $scale ) {
   531                     output_copyfunc($src, $dst, $modulate, $blend, $scale);
   532                 }
   533             }
   534         }
   535     }
   536 }
   537 
   538 open_file("SDL_blit_auto.h");
   539 output_copydefs();
   540 for (my $i = 0; $i <= $#src_formats; ++$i) {
   541     for (my $j = 0; $j <= $#dst_formats; ++$j) {
   542         output_copyfunc_h($src_formats[$i], $dst_formats[$j]);
   543     }
   544 }
   545 print FILE "\n";
   546 close_file("SDL_blit_auto.h");
   547 
   548 open_file("SDL_blit_auto.c");
   549 output_copyinc();
   550 for (my $i = 0; $i <= $#src_formats; ++$i) {
   551     for (my $j = 0; $j <= $#dst_formats; ++$j) {
   552         output_copyfunc_c($src_formats[$i], $dst_formats[$j]);
   553     }
   554 }
   555 output_copyfunctable();
   556 close_file("SDL_blit_auto.c");