src/video/sdlgenblit.pl
author Sam Lantinga <slouken@libsdl.org>
Tue, 30 Jan 2018 18:08:34 -0800
changeset 11839 971881e55d61
parent 11811 5d94cb6b24d3
child 12503 806492103856
permissions -rwxr-xr-x
Fixed ISO C99 compatibility
SDL now builds with gcc 7.2 with the following command line options:
-Wall -pedantic-errors -Wno-deprecated-declarations -Wno-overlength-strings --std=c99
     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-2018 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 
   218     # Nice and easy...
   219     if ( $src eq $dst && !$modulate && !$blend ) {
   220         print FILE <<__EOF__;
   221             *dst = *src;
   222 __EOF__
   223         return;
   224     }
   225 
   226     my $dst_has_alpha = ($dst =~ /A/) ? 1 : 0;
   227     my $ignore_dst_alpha = !$dst_has_alpha && !$blend;
   228 
   229     if ( $blend ) {
   230         get_rgba("src", $src, $ignore_dst_alpha);
   231         get_rgba("dst", $dst, !$dst_has_alpha);
   232         $s = "src";
   233         $d = "dst";
   234     } else {
   235         get_rgba("", $src, $ignore_dst_alpha);
   236     }
   237 
   238     if ( $modulate ) {
   239         print FILE <<__EOF__;
   240             if (flags & SDL_COPY_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 __EOF__
   246         if (not $ignore_dst_alpha) {
   247             print FILE <<__EOF__;
   248             if (flags & SDL_COPY_MODULATE_ALPHA) {
   249                 ${s}A = (${s}A * modulateA) / 255;
   250             }
   251 __EOF__
   252         }
   253     }
   254     if ( $blend ) {
   255         print FILE <<__EOF__;
   256             if (flags & (SDL_COPY_BLEND|SDL_COPY_ADD)) {
   257                 /* This goes away if we ever use premultiplied alpha */
   258                 if (${s}A < 255) {
   259                     ${s}R = (${s}R * ${s}A) / 255;
   260                     ${s}G = (${s}G * ${s}A) / 255;
   261                     ${s}B = (${s}B * ${s}A) / 255;
   262                 }
   263             }
   264             switch (flags & (SDL_COPY_BLEND|SDL_COPY_ADD|SDL_COPY_MOD)) {
   265             case SDL_COPY_BLEND:
   266                 ${d}R = ${s}R + ((255 - ${s}A) * ${d}R) / 255;
   267                 ${d}G = ${s}G + ((255 - ${s}A) * ${d}G) / 255;
   268                 ${d}B = ${s}B + ((255 - ${s}A) * ${d}B) / 255;
   269 __EOF__
   270 
   271         if ( $dst_has_alpha ) {
   272             print FILE <<__EOF__;
   273                 ${d}A = ${s}A + ((255 - ${s}A) * ${d}A) / 255;
   274 __EOF__
   275         }
   276 
   277         print FILE <<__EOF__;
   278                 break;
   279             case SDL_COPY_ADD:
   280                 ${d}R = ${s}R + ${d}R; if (${d}R > 255) ${d}R = 255;
   281                 ${d}G = ${s}G + ${d}G; if (${d}G > 255) ${d}G = 255;
   282                 ${d}B = ${s}B + ${d}B; if (${d}B > 255) ${d}B = 255;
   283                 break;
   284             case SDL_COPY_MOD:
   285                 ${d}R = (${s}R * ${d}R) / 255;
   286                 ${d}G = (${s}G * ${d}G) / 255;
   287                 ${d}B = (${s}B * ${d}B) / 255;
   288                 break;
   289             }
   290 __EOF__
   291     }
   292     if ( $blend ) {
   293         set_rgba("dst", $dst);
   294     } else {
   295         set_rgba("", $dst);
   296     }
   297 }
   298 
   299 sub output_copyfunc
   300 {
   301     my $src = shift;
   302     my $dst = shift;
   303     my $modulate = shift;
   304     my $blend = shift;
   305     my $scale = shift;
   306 
   307     my $dst_has_alpha = ($dst =~ /A/) ? 1 : 0;
   308     my $ignore_dst_alpha = !$dst_has_alpha && !$blend;
   309 
   310     output_copyfuncname("static void", $src, $dst, $modulate, $blend, $scale, 1, "\n");
   311     print FILE <<__EOF__;
   312 {
   313 __EOF__
   314     if ( $modulate || $blend ) {
   315         print FILE <<__EOF__;
   316     const int flags = info->flags;
   317 __EOF__
   318     }
   319     if ( $modulate ) {
   320         print FILE <<__EOF__;
   321     const Uint32 modulateR = info->r;
   322     const Uint32 modulateG = info->g;
   323     const Uint32 modulateB = info->b;
   324 __EOF__
   325         if (!$ignore_dst_alpha) {
   326             print FILE <<__EOF__;
   327     const Uint32 modulateA = info->a;
   328 __EOF__
   329         }
   330     }
   331     if ( $blend ) {
   332         print FILE <<__EOF__;
   333     Uint32 srcpixel;
   334     Uint32 srcR, srcG, srcB, srcA;
   335     Uint32 dstpixel;
   336 __EOF__
   337         if ($dst_has_alpha) {
   338             print FILE <<__EOF__;
   339     Uint32 dstR, dstG, dstB, dstA;
   340 __EOF__
   341         } else {
   342             print FILE <<__EOF__;
   343     Uint32 dstR, dstG, dstB;
   344 __EOF__
   345         }
   346     } elsif ( $modulate || $src ne $dst ) {
   347         print FILE <<__EOF__;
   348     Uint32 pixel;
   349 __EOF__
   350         if (!$ignore_dst_alpha) {
   351             print FILE <<__EOF__;
   352     Uint32 R, G, B, A;
   353 __EOF__
   354         } else {
   355             print FILE <<__EOF__;
   356     Uint32 R, G, B;
   357 __EOF__
   358         }
   359     }
   360     if ( $scale ) {
   361         print FILE <<__EOF__;
   362     int srcy, srcx;
   363     int posy, posx;
   364     int incy, incx;
   365 __EOF__
   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         print FILE <<__EOF__;
   406 
   407     while (info->dst_h--) {
   408         $format_type{$src} *src = ($format_type{$src} *)info->src;
   409         $format_type{$dst} *dst = ($format_type{$dst} *)info->dst;
   410         int n = info->dst_w;
   411         while (n--) {
   412 __EOF__
   413         output_copycore($src, $dst, $modulate, $blend);
   414         print FILE <<__EOF__;
   415             ++src;
   416             ++dst;
   417         }
   418         info->src += info->src_pitch;
   419         info->dst += info->dst_pitch;
   420     }
   421 __EOF__
   422     }
   423     print FILE <<__EOF__;
   424 }
   425 
   426 __EOF__
   427 }
   428 
   429 sub output_copyfunc_h
   430 {
   431 }
   432 
   433 sub output_copyinc
   434 {
   435     print FILE <<__EOF__;
   436 #include "SDL_video.h"
   437 #include "SDL_blit.h"
   438 #include "SDL_blit_auto.h"
   439 
   440 __EOF__
   441 }
   442 
   443 sub output_copyfunctable
   444 {
   445     print FILE <<__EOF__;
   446 SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[] = {
   447 __EOF__
   448     for (my $i = 0; $i <= $#src_formats; ++$i) {
   449         my $src = $src_formats[$i];
   450         for (my $j = 0; $j <= $#dst_formats; ++$j) {
   451             my $dst = $dst_formats[$j];
   452             for (my $modulate = 0; $modulate <= 1; ++$modulate) {
   453                 for (my $blend = 0; $blend <= 1; ++$blend) {
   454                     for (my $scale = 0; $scale <= 1; ++$scale) {
   455                         if ( $modulate || $blend || $scale ) {
   456                             print FILE "    { SDL_PIXELFORMAT_$src, SDL_PIXELFORMAT_$dst, ";
   457                             my $flags = "";
   458                             my $flag = "";
   459                             if ( $modulate ) {
   460                                 $flag = "SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA";
   461                                 if ( $flags eq "" ) {
   462                                     $flags = $flag;
   463                                 } else {
   464                                     $flags = "$flags | $flag";
   465                                 }
   466                             }
   467                             if ( $blend ) {
   468                                 $flag = "SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD";
   469                                 if ( $flags eq "" ) {
   470                                     $flags = $flag;
   471                                 } else {
   472                                     $flags = "$flags | $flag";
   473                                 }
   474                             }
   475                             if ( $scale ) {
   476                                 $flag = "SDL_COPY_NEAREST";
   477                                 if ( $flags eq "" ) {
   478                                     $flags = $flag;
   479                                 } else {
   480                                     $flags = "$flags | $flag";
   481                                 }
   482                             }
   483                             if ( $flags eq "" ) {
   484                                 $flags = "0";
   485                             }
   486                             print FILE "($flags), SDL_CPU_ANY,";
   487                             output_copyfuncname("", $src_formats[$i], $dst_formats[$j], $modulate, $blend, $scale, 0, " },\n");
   488                         }
   489                     }
   490                 }
   491             }
   492         }
   493     }
   494     print FILE <<__EOF__;
   495     { 0, 0, 0, 0, NULL }
   496 };
   497 
   498 __EOF__
   499 }
   500 
   501 sub output_copyfunc_c
   502 {
   503     my $src = shift;
   504     my $dst = shift;
   505 
   506     for (my $modulate = 0; $modulate <= 1; ++$modulate) {
   507         for (my $blend = 0; $blend <= 1; ++$blend) {
   508             for (my $scale = 0; $scale <= 1; ++$scale) {
   509                 if ( $modulate || $blend || $scale ) {
   510                     output_copyfunc($src, $dst, $modulate, $blend, $scale);
   511                 }
   512             }
   513         }
   514     }
   515 }
   516 
   517 open_file("SDL_blit_auto.h");
   518 output_copydefs();
   519 for (my $i = 0; $i <= $#src_formats; ++$i) {
   520     for (my $j = 0; $j <= $#dst_formats; ++$j) {
   521         output_copyfunc_h($src_formats[$i], $dst_formats[$j]);
   522     }
   523 }
   524 print FILE "\n";
   525 close_file("SDL_blit_auto.h");
   526 
   527 open_file("SDL_blit_auto.c");
   528 output_copyinc();
   529 for (my $i = 0; $i <= $#src_formats; ++$i) {
   530     for (my $j = 0; $j <= $#dst_formats; ++$j) {
   531         output_copyfunc_c($src_formats[$i], $dst_formats[$j]);
   532     }
   533 }
   534 output_copyfunctable();
   535 close_file("SDL_blit_auto.c");