src/video/sdlgenblit.pl
author Sam Lantinga <slouken@libsdl.org>
Tue, 15 Dec 2009 08:11:06 +0000
changeset 3565 f43c8f688f77
parent 2859 99210400e8b9
child 5140 e743b9c3f6d6
permissions -rwxr-xr-x
Fixed bug #906

Added better error reporting for OpenGL context creation failing.
     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     "ARGB8888",
    42 );
    43 
    44 my %format_size = (
    45     "RGB888" => 4,
    46     "BGR888" => 4,
    47     "ARGB8888" => 4,
    48     "RGBA8888" => 4,
    49     "ABGR8888" => 4,
    50     "BGRA8888" => 4,
    51 );
    52 
    53 my %format_type = (
    54     "RGB888" => "Uint32",
    55     "BGR888" => "Uint32",
    56     "ARGB8888" => "Uint32",
    57     "RGBA8888" => "Uint32",
    58     "ABGR8888" => "Uint32",
    59     "BGRA8888" => "Uint32",
    60 );
    61 
    62 my %get_rgba_string = (
    63     "RGB888" => "_R = (Uint8)(_pixel >> 16); _G = (Uint8)(_pixel >> 8); _B = (Uint8)_pixel; _A = 0xFF;",
    64     "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;",
    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     "ARGB8888" => "_pixel = ((Uint32)_A << 24) | ((Uint32)_R << 16) | ((Uint32)_G << 8) | _B;",
    74     "RGBA8888" => "_pixel = ((Uint32)_R << 24) | ((Uint32)_G << 16) | ((Uint32)_B << 8) | _A;",
    75     "ABGR8888" => "_pixel = ((Uint32)_A << 24) | ((Uint32)_B << 16) | ((Uint32)_G << 8) | _R;",
    76     "BGRA8888" => "_pixel = ((Uint32)_B << 24) | ((Uint32)_G << 16) | ((Uint32)_R << 8) | _A;",
    77 );
    78 
    79 sub open_file {
    80     my $name = shift;
    81     open(FILE, ">$name.new") || die "Cant' open $name.new: $!";
    82     print FILE <<__EOF__;
    83 /* DO NOT EDIT!  This file is generated by sdlgenblit.pl */
    84 /*
    85     SDL - Simple DirectMedia Layer
    86     Copyright (C) 1997-2009 Sam Lantinga
    87 
    88     This library is free software; you can redistribute it and/or
    89     modify it under the terms of the GNU Lesser General Public
    90     License as published by the Free Software Foundation; either
    91     version 2.1 of the License, or (at your option) any later version.
    92 
    93     This library is distributed in the hope that it will be useful,
    94     but WITHOUT ANY WARRANTY; without even the implied warranty of
    95     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    96     Lesser General Public License for more details.
    97 
    98     You should have received a copy of the GNU Lesser General Public
    99     License along with this library; if not, write to the Free Software
   100     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   101 
   102     Sam Lantinga
   103     slouken\@libsdl.org
   104 */
   105 #include "SDL_config.h"
   106 
   107 /* *INDENT-OFF* */
   108 
   109 __EOF__
   110 }
   111 
   112 sub close_file {
   113     my $name = shift;
   114     print FILE <<__EOF__;
   115 /* *INDENT-ON* */
   116 
   117 /* vi: set ts=4 sw=4 expandtab: */
   118 __EOF__
   119     close FILE;
   120     if ( ! -f $name || system("cmp -s $name $name.new") != 0 ) {
   121         rename("$name.new", "$name");
   122     } else {
   123         unlink("$name.new");
   124     }
   125 }
   126 
   127 sub output_copydefs
   128 {
   129     print FILE <<__EOF__;
   130 extern SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[];
   131 __EOF__
   132 }
   133 
   134 sub output_copyfuncname
   135 {
   136     my $prefix = shift;
   137     my $src = shift;
   138     my $dst = shift;
   139     my $modulate = shift;
   140     my $blend = shift;
   141     my $scale = shift;
   142     my $args = shift;
   143     my $suffix = shift;
   144 
   145     print FILE "$prefix SDL_Blit_${src}_${dst}";
   146     if ( $modulate ) {
   147         print FILE "_Modulate";
   148     }
   149     if ( $blend ) {
   150         print FILE "_Blend";
   151     }
   152     if ( $scale ) {
   153         print FILE "_Scale";
   154     }
   155     if ( $args ) {
   156         print FILE "(SDL_BlitInfo *info)";
   157     }
   158     print FILE "$suffix";
   159 }
   160 
   161 sub get_rgba
   162 {
   163     my $prefix = shift;
   164     my $format = shift;
   165     my $string = $get_rgba_string{$format};
   166     $string =~ s/_/$prefix/g;
   167     if ( $prefix ne "" ) {
   168         print FILE <<__EOF__;
   169             ${prefix}pixel = *$prefix;
   170 __EOF__
   171     } else {
   172         print FILE <<__EOF__;
   173             pixel = *src;
   174 __EOF__
   175     }
   176     print FILE <<__EOF__;
   177             $string
   178 __EOF__
   179 }
   180 
   181 sub set_rgba
   182 {
   183     my $prefix = shift;
   184     my $format = shift;
   185     my $string = $set_rgba_string{$format};
   186     $string =~ s/_/$prefix/g;
   187     print FILE <<__EOF__;
   188             $string
   189             *dst = ${prefix}pixel;
   190 __EOF__
   191 }
   192 
   193 sub output_copycore
   194 {
   195     my $src = shift;
   196     my $dst = shift;
   197     my $modulate = shift;
   198     my $blend = shift;
   199     my $s = "";
   200     my $d = "";
   201 
   202     # Nice and easy...
   203     if ( $src eq $dst && !$modulate && !$blend ) {
   204         print FILE <<__EOF__;
   205             *dst = *src;
   206 __EOF__
   207         return;
   208     }
   209 
   210     if ( $blend ) {
   211         get_rgba("src", $src);
   212         get_rgba("dst", $dst);
   213         $s = "src";
   214         $d = "dst";
   215     } else {
   216         get_rgba("", $src);
   217     }
   218 
   219     if ( $modulate ) {
   220         print FILE <<__EOF__;
   221             if (flags & SDL_COPY_MODULATE_COLOR) {
   222                 ${s}R = (${s}R * modulateR) / 255;
   223                 ${s}G = (${s}G * modulateG) / 255;
   224                 ${s}B = (${s}B * modulateB) / 255;
   225             }
   226             if (flags & SDL_COPY_MODULATE_ALPHA) {
   227                 ${s}A = (${s}A * modulateA) / 255;
   228             }
   229 __EOF__
   230     }
   231     if ( $blend ) {
   232         print FILE <<__EOF__;
   233             if (flags & (SDL_COPY_BLEND|SDL_COPY_ADD)) {
   234                 /* This goes away if we ever use premultiplied alpha */
   235                 if (${s}A < 255) {
   236                     ${s}R = (${s}R * ${s}A) / 255;
   237                     ${s}G = (${s}G * ${s}A) / 255;
   238                     ${s}B = (${s}B * ${s}A) / 255;
   239                 }
   240             }
   241             switch (flags & (SDL_COPY_MASK|SDL_COPY_BLEND|SDL_COPY_ADD|SDL_COPY_MOD)) {
   242             case SDL_COPY_MASK:
   243                 if (${s}A) {
   244                     ${d}R = ${s}R;
   245                     ${d}G = ${s}G;
   246                     ${d}B = ${s}B;
   247                 }
   248                 break;
   249             case SDL_COPY_BLEND:
   250                 ${d}R = ${s}R + ((255 - ${s}A) * ${d}R) / 255;
   251                 ${d}G = ${s}G + ((255 - ${s}A) * ${d}G) / 255;
   252                 ${d}B = ${s}B + ((255 - ${s}A) * ${d}B) / 255;
   253                 break;
   254             case SDL_COPY_ADD:
   255                 ${d}R = ${s}R + ${d}R; if (${d}R > 255) ${d}R = 255;
   256                 ${d}G = ${s}G + ${d}G; if (${d}G > 255) ${d}G = 255;
   257                 ${d}B = ${s}B + ${d}B; if (${d}B > 255) ${d}B = 255;
   258                 break;
   259             case SDL_COPY_MOD:
   260                 ${d}R = (${s}R * ${d}R) / 255;
   261                 ${d}G = (${s}G * ${d}G) / 255;
   262                 ${d}B = (${s}B * ${d}B) / 255;
   263                 break;
   264             }
   265 __EOF__
   266     }
   267     if ( $blend ) {
   268         set_rgba("dst", $dst);
   269     } else {
   270         set_rgba("", $dst);
   271     }
   272 }
   273 
   274 sub output_copyfunc
   275 {
   276     my $src = shift;
   277     my $dst = shift;
   278     my $modulate = shift;
   279     my $blend = shift;
   280     my $scale = shift;
   281 
   282     output_copyfuncname("static void", $src, $dst, $modulate, $blend, $scale, 1, "\n");
   283     print FILE <<__EOF__;
   284 {
   285     const int flags = info->flags;
   286 __EOF__
   287     if ( $modulate ) {
   288         print FILE <<__EOF__;
   289     const Uint32 modulateR = info->r;
   290     const Uint32 modulateG = info->g;
   291     const Uint32 modulateB = info->b;
   292     const Uint32 modulateA = info->a;
   293 __EOF__
   294     }
   295     if ( $blend ) {
   296         print FILE <<__EOF__;
   297     Uint32 srcpixel;
   298     Uint32 srcR, srcG, srcB, srcA;
   299     Uint32 dstpixel;
   300     Uint32 dstR, dstG, dstB, dstA;
   301 __EOF__
   302     } elsif ( $modulate || $src ne $dst ) {
   303         print FILE <<__EOF__;
   304     Uint32 pixel;
   305     Uint32 R, G, B, A;
   306 __EOF__
   307     }
   308     if ( $scale ) {
   309         print FILE <<__EOF__;
   310     int srcy, srcx;
   311     int posy, posx;
   312     int incy, incx;
   313 
   314     srcy = 0;
   315     posy = 0;
   316     incy = (info->src_h << 16) / info->dst_h;
   317     incx = (info->src_w << 16) / info->dst_w;
   318 
   319     while (info->dst_h--) {
   320         $format_type{$src} *src;
   321         $format_type{$dst} *dst = ($format_type{$dst} *)info->dst;
   322         int n = info->dst_w;
   323         srcx = -1;
   324         posx = 0x10000L;
   325         while (posy >= 0x10000L) {
   326             ++srcy;
   327             posy -= 0x10000L;
   328         }
   329         while (n--) {
   330             if (posx >= 0x10000L) {
   331                 while (posx >= 0x10000L) {
   332                     ++srcx;
   333                     posx -= 0x10000L;
   334                 }
   335                 src = ($format_type{$src} *)(info->src + (srcy * info->src_pitch) + (srcx * $format_size{$src}));
   336 __EOF__
   337         print FILE <<__EOF__;
   338             }
   339 __EOF__
   340         output_copycore($src, $dst, $modulate, $blend);
   341         print FILE <<__EOF__;
   342             posx += incx;
   343             ++dst;
   344         }
   345         posy += incy;
   346         info->dst += info->dst_pitch;
   347     }
   348 __EOF__
   349     } else {
   350         print FILE <<__EOF__;
   351 
   352     while (info->dst_h--) {
   353         $format_type{$src} *src = ($format_type{$src} *)info->src;
   354         $format_type{$dst} *dst = ($format_type{$dst} *)info->dst;
   355         int n = info->dst_w;
   356         while (n--) {
   357 __EOF__
   358         output_copycore($src, $dst, $modulate, $blend);
   359         print FILE <<__EOF__;
   360             ++src;
   361             ++dst;
   362         }
   363         info->src += info->src_pitch;
   364         info->dst += info->dst_pitch;
   365     }
   366 __EOF__
   367     }
   368     print FILE <<__EOF__;
   369 }
   370 
   371 __EOF__
   372 }
   373 
   374 sub output_copyfunc_h
   375 {
   376 }
   377 
   378 sub output_copyinc
   379 {
   380     print FILE <<__EOF__;
   381 #include "SDL_video.h"
   382 #include "SDL_blit.h"
   383 #include "SDL_blit_auto.h"
   384 
   385 __EOF__
   386 }
   387 
   388 sub output_copyfunctable
   389 {
   390     print FILE <<__EOF__;
   391 SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[] = {
   392 __EOF__
   393     for (my $i = 0; $i <= $#src_formats; ++$i) {
   394         my $src = $src_formats[$i];
   395         for (my $j = 0; $j <= $#dst_formats; ++$j) {
   396             my $dst = $dst_formats[$j];
   397             for (my $modulate = 0; $modulate <= 1; ++$modulate) {
   398                 for (my $blend = 0; $blend <= 1; ++$blend) {
   399                     for (my $scale = 0; $scale <= 1; ++$scale) {
   400                         if ( $modulate || $blend || $scale ) {
   401                             print FILE "    { SDL_PIXELFORMAT_$src, SDL_PIXELFORMAT_$dst, ";
   402                             my $flags = "";
   403                             my $flag = "";
   404                             if ( $modulate ) {
   405                                 $flag = "SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA";
   406                                 if ( $flags eq "" ) {
   407                                     $flags = $flag;
   408                                 } else {
   409                                     $flags = "$flags | $flag";
   410                                 }
   411                             }
   412                             if ( $blend ) {
   413                                 $flag = "SDL_COPY_MASK | SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD";
   414                                 if ( $flags eq "" ) {
   415                                     $flags = $flag;
   416                                 } else {
   417                                     $flags = "$flags | $flag";
   418                                 }
   419                             }
   420                             if ( $scale ) {
   421                                 $flag = "SDL_COPY_NEAREST";
   422                                 if ( $flags eq "" ) {
   423                                     $flags = $flag;
   424                                 } else {
   425                                     $flags = "$flags | $flag";
   426                                 }
   427                             }
   428                             if ( $flags eq "" ) {
   429                                 $flags = "0";
   430                             }
   431                             print FILE "($flags), SDL_CPU_ANY,";
   432                             output_copyfuncname("", $src_formats[$i], $dst_formats[$j], $modulate, $blend, $scale, 0, " },\n");
   433                         }
   434                     }
   435                 }
   436             }
   437         }
   438     }
   439     print FILE <<__EOF__;
   440     { 0, 0, 0, 0, NULL }
   441 };
   442 
   443 __EOF__
   444 }
   445 
   446 sub output_copyfunc_c
   447 {
   448     my $src = shift;
   449     my $dst = shift;
   450 
   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                     output_copyfunc($src, $dst, $modulate, $blend, $scale);
   456                 }
   457             }
   458         }
   459     }
   460 }
   461 
   462 open_file("SDL_blit_auto.h");
   463 output_copydefs();
   464 for (my $i = 0; $i <= $#src_formats; ++$i) {
   465     for (my $j = 0; $j <= $#dst_formats; ++$j) {
   466         output_copyfunc_h($src_formats[$i], $dst_formats[$j]);
   467     }
   468 }
   469 print FILE "\n";
   470 close_file("SDL_blit_auto.h");
   471 
   472 open_file("SDL_blit_auto.c");
   473 output_copyinc();
   474 for (my $i = 0; $i <= $#src_formats; ++$i) {
   475     for (my $j = 0; $j <= $#dst_formats; ++$j) {
   476         output_copyfunc_c($src_formats[$i], $dst_formats[$j]);
   477     }
   478 }
   479 output_copyfunctable();
   480 close_file("SDL_blit_auto.c");