sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

sdlgenblit.pl (17629B)


      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"},
     72     "BGR888" => $get_rgba_string_ignore_alpha{"BGR888"},
     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 = (_R << 16) | (_G << 8) | _B;",
     81     "BGR888" => "_pixel = (_B << 16) | (_G << 8) | _R;",
     82     "ARGB8888" => "_pixel = (_A << 24) | (_R << 16) | (_G << 8) | _B;",
     83     "RGBA8888" => "_pixel = (_R << 24) | (_G << 16) | (_B << 8) | _A;",
     84     "ABGR8888" => "_pixel = (_A << 24) | (_B << 16) | (_G << 8) | _R;",
     85     "BGRA8888" => "_pixel = (_B << 24) | (_G << 16) | (_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-2020 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 #if SDL_HAVE_BLIT_AUTO
    116 
    117 /* *INDENT-OFF* */
    118 
    119 __EOF__
    120 }
    121 
    122 sub close_file {
    123     my $name = shift;
    124     print FILE <<__EOF__;
    125 /* *INDENT-ON* */
    126 
    127 #endif /* SDL_HAVE_BLIT_AUTO */
    128 
    129 /* vi: set ts=4 sw=4 expandtab: */
    130 __EOF__
    131     close FILE;
    132     if ( ! -f $name || system("cmp -s $name $name.new") != 0 ) {
    133         rename("$name.new", "$name");
    134     } else {
    135         unlink("$name.new");
    136     }
    137 }
    138 
    139 sub output_copydefs
    140 {
    141     print FILE <<__EOF__;
    142 extern SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[];
    143 __EOF__
    144 }
    145 
    146 sub output_copyfuncname
    147 {
    148     my $prefix = shift;
    149     my $src = shift;
    150     my $dst = shift;
    151     my $modulate = shift;
    152     my $blend = shift;
    153     my $scale = shift;
    154     my $args = shift;
    155     my $suffix = shift;
    156 
    157     print FILE "$prefix SDL_Blit_${src}_${dst}";
    158     if ( $modulate ) {
    159         print FILE "_Modulate";
    160     }
    161     if ( $blend ) {
    162         print FILE "_Blend";
    163     }
    164     if ( $scale ) {
    165         print FILE "_Scale";
    166     }
    167     if ( $args ) {
    168         print FILE "(SDL_BlitInfo *info)";
    169     }
    170     print FILE "$suffix";
    171 }
    172 
    173 sub get_rgba
    174 {
    175     my $prefix = shift;
    176     my $format = shift;
    177     my $ignore_alpha = shift;
    178 
    179     my $string;
    180     if ($ignore_alpha) {
    181         $string = $get_rgba_string_ignore_alpha{$format};
    182     } else {
    183         $string = $get_rgba_string{$format};
    184     }
    185 
    186     $string =~ s/_/$prefix/g;
    187     if ( $prefix ne "" ) {
    188         print FILE <<__EOF__;
    189             ${prefix}pixel = *$prefix;
    190 __EOF__
    191     } else {
    192         print FILE <<__EOF__;
    193             pixel = *src;
    194 __EOF__
    195     }
    196     print FILE <<__EOF__;
    197             $string
    198 __EOF__
    199 }
    200 
    201 sub set_rgba
    202 {
    203     my $prefix = shift;
    204     my $format = shift;
    205     my $string = $set_rgba_string{$format};
    206     $string =~ s/_/$prefix/g;
    207     print FILE <<__EOF__;
    208             $string
    209             *dst = ${prefix}pixel;
    210 __EOF__
    211 }
    212 
    213 sub output_copycore
    214 {
    215     my $src = shift;
    216     my $dst = shift;
    217     my $modulate = shift;
    218     my $blend = shift;
    219     my $is_modulateA_done = shift;
    220     my $A_is_const_FF = shift;
    221     my $s = "";
    222     my $d = "";
    223 
    224     # Nice and easy...
    225     if ( $src eq $dst && !$modulate && !$blend ) {
    226         print FILE <<__EOF__;
    227             *dst = *src;
    228 __EOF__
    229         return;
    230     }
    231 
    232     my $dst_has_alpha = ($dst =~ /A/) ? 1 : 0;
    233     my $ignore_dst_alpha = !$dst_has_alpha && !$blend;
    234 
    235     if ( $blend ) {
    236         get_rgba("src", $src, $ignore_dst_alpha);
    237         get_rgba("dst", $dst, !$dst_has_alpha);
    238         $s = "src";
    239         $d = "dst";
    240     } else {
    241         get_rgba("", $src, $ignore_dst_alpha);
    242     }
    243 
    244     if ( $modulate ) {
    245         print FILE <<__EOF__;
    246             if (flags & SDL_COPY_MODULATE_COLOR) {
    247                 ${s}R = (${s}R * modulateR) / 255;
    248                 ${s}G = (${s}G * modulateG) / 255;
    249                 ${s}B = (${s}B * modulateB) / 255;
    250             }
    251 __EOF__
    252         if (!$ignore_dst_alpha && !$is_modulateA_done) {
    253             print FILE <<__EOF__;
    254             if (flags & SDL_COPY_MODULATE_ALPHA) {
    255                 ${s}A = (${s}A * modulateA) / 255;
    256             }
    257 __EOF__
    258         }
    259     }
    260     if ( $blend ) {
    261         if (!$A_is_const_FF) {
    262             print FILE <<__EOF__;
    263             if (flags & (SDL_COPY_BLEND|SDL_COPY_ADD)) {
    264                 /* This goes away if we ever use premultiplied alpha */
    265                 if (${s}A < 255) {
    266                     ${s}R = (${s}R * ${s}A) / 255;
    267                     ${s}G = (${s}G * ${s}A) / 255;
    268                     ${s}B = (${s}B * ${s}A) / 255;
    269                 }
    270             }
    271 __EOF__
    272         }
    273         print FILE <<__EOF__;
    274             switch (flags & (SDL_COPY_BLEND|SDL_COPY_ADD|SDL_COPY_MOD|SDL_COPY_MUL)) {
    275             case SDL_COPY_BLEND:
    276 __EOF__
    277         if ($A_is_const_FF) {
    278             print FILE <<__EOF__;
    279                 ${d}R = ${s}R;
    280                 ${d}G = ${s}G;
    281                 ${d}B = ${s}B;
    282 __EOF__
    283         } else {
    284             print FILE <<__EOF__;
    285                 ${d}R = ${s}R + ((255 - ${s}A) * ${d}R) / 255;
    286                 ${d}G = ${s}G + ((255 - ${s}A) * ${d}G) / 255;
    287                 ${d}B = ${s}B + ((255 - ${s}A) * ${d}B) / 255;
    288 __EOF__
    289         }
    290         if ( $dst_has_alpha ) {
    291             if ($A_is_const_FF) {
    292                 print FILE <<__EOF__;
    293                 ${d}A = 0xFF;
    294 __EOF__
    295             } else {
    296                 print FILE <<__EOF__;
    297                 ${d}A = ${s}A + ((255 - ${s}A) * ${d}A) / 255;
    298 __EOF__
    299             }
    300         }
    301 
    302         print FILE <<__EOF__;
    303                 break;
    304             case SDL_COPY_ADD:
    305                 ${d}R = ${s}R + ${d}R; if (${d}R > 255) ${d}R = 255;
    306                 ${d}G = ${s}G + ${d}G; if (${d}G > 255) ${d}G = 255;
    307                 ${d}B = ${s}B + ${d}B; if (${d}B > 255) ${d}B = 255;
    308                 break;
    309             case SDL_COPY_MOD:
    310                 ${d}R = (${s}R * ${d}R) / 255;
    311                 ${d}G = (${s}G * ${d}G) / 255;
    312                 ${d}B = (${s}B * ${d}B) / 255;
    313                 break;
    314             case SDL_COPY_MUL:
    315 __EOF__
    316         if ($A_is_const_FF) {
    317             print FILE <<__EOF__;
    318                 ${d}R = (${s}R * ${d}R) / 255;
    319                 ${d}G = (${s}G * ${d}G) / 255;
    320                 ${d}B = (${s}B * ${d}B) / 255;
    321 __EOF__
    322         } else {
    323             print FILE <<__EOF__;
    324                 ${d}R = ((${s}R * ${d}R) + (${d}R * (255 - ${s}A))) / 255; if (${d}R > 255) ${d}R = 255;
    325                 ${d}G = ((${s}G * ${d}G) + (${d}G * (255 - ${s}A))) / 255; if (${d}G > 255) ${d}G = 255;
    326                 ${d}B = ((${s}B * ${d}B) + (${d}B * (255 - ${s}A))) / 255; if (${d}B > 255) ${d}B = 255;
    327 __EOF__
    328         }
    329         if ( $dst_has_alpha ) {
    330             if ($A_is_const_FF) {
    331                 print FILE <<__EOF__;
    332                 ${d}A = 0xFF;
    333 __EOF__
    334             } else {
    335                 print FILE <<__EOF__;
    336                 ${d}A = ((${s}A * ${d}A) + (${d}A * (255 - ${s}A))) / 255; if (${d}A > 255) ${d}A = 255;
    337 __EOF__
    338             }
    339         }
    340 
    341         print FILE <<__EOF__;
    342                 break;
    343             }
    344 __EOF__
    345     }
    346     if ( $blend ) {
    347         set_rgba("dst", $dst);
    348     } else {
    349         set_rgba("", $dst);
    350     }
    351 }
    352 
    353 sub output_copyfunc
    354 {
    355     my $src = shift;
    356     my $dst = shift;
    357     my $modulate = shift;
    358     my $blend = shift;
    359     my $scale = shift;
    360 
    361     my $dst_has_alpha = ($dst =~ /A/) ? 1 : 0;
    362     my $ignore_dst_alpha = !$dst_has_alpha && !$blend;
    363     
    364     my $src_has_alpha = ($src =~ /A/) ? 1 : 0;
    365 
    366     my $is_modulateA_done = 0;
    367     my $A_is_const_FF = 0;
    368 
    369     output_copyfuncname("static void", $src, $dst, $modulate, $blend, $scale, 1, "\n");
    370     print FILE <<__EOF__;
    371 {
    372 __EOF__
    373     if ( $modulate || $blend ) {
    374         print FILE <<__EOF__;
    375     const int flags = info->flags;
    376 __EOF__
    377     }
    378     if ( $modulate ) {
    379         print FILE <<__EOF__;
    380     const Uint32 modulateR = info->r;
    381     const Uint32 modulateG = info->g;
    382     const Uint32 modulateB = info->b;
    383 __EOF__
    384         if (!$ignore_dst_alpha) {
    385             print FILE <<__EOF__;
    386     const Uint32 modulateA = info->a;
    387 __EOF__
    388         }
    389     }
    390     if ( $blend ) {
    391         print FILE <<__EOF__;
    392     Uint32 srcpixel;
    393 __EOF__
    394         if (!$ignore_dst_alpha && !$src_has_alpha) {
    395             if ($modulate){
    396                 $is_modulateA_done = 1;
    397                 print FILE <<__EOF__;
    398     const Uint32 srcA = (flags & SDL_COPY_MODULATE_ALPHA) ? modulateA : 0xFF;
    399 __EOF__
    400             } else {
    401                 $A_is_const_FF = 1;
    402             }
    403             print FILE <<__EOF__;
    404     Uint32 srcR, srcG, srcB;
    405 __EOF__
    406         } else {
    407             print FILE <<__EOF__;
    408     Uint32 srcR, srcG, srcB, srcA;
    409 __EOF__
    410         }
    411         print FILE <<__EOF__;
    412     Uint32 dstpixel;
    413 __EOF__
    414         if ($dst_has_alpha) {
    415             print FILE <<__EOF__;
    416     Uint32 dstR, dstG, dstB, dstA;
    417 __EOF__
    418         } else {
    419             print FILE <<__EOF__;
    420     Uint32 dstR, dstG, dstB;
    421 __EOF__
    422         }
    423     } elsif ( $modulate || $src ne $dst ) {
    424         print FILE <<__EOF__;
    425     Uint32 pixel;
    426 __EOF__
    427         if (!$ignore_dst_alpha && !$src_has_alpha) {
    428             if ($modulate){
    429                 $is_modulateA_done = 1;
    430                 print FILE <<__EOF__;
    431     const Uint32 A = (flags & SDL_COPY_MODULATE_ALPHA) ? modulateA : 0xFF;
    432 __EOF__
    433             } else {
    434                 $A_is_const_FF = 1;
    435                 print FILE <<__EOF__;
    436     const Uint32 A = 0xFF;
    437 __EOF__
    438             }
    439             print FILE <<__EOF__;
    440     Uint32 R, G, B;
    441 __EOF__
    442         } elsif (!$ignore_dst_alpha) {
    443             print FILE <<__EOF__;
    444     Uint32 R, G, B, A;
    445 __EOF__
    446         } else {
    447             print FILE <<__EOF__;
    448     Uint32 R, G, B;
    449 __EOF__
    450         }
    451     }
    452     if ( $scale ) {
    453         print FILE <<__EOF__;
    454     int srcy, srcx;
    455     int posy, posx;
    456     int incy, incx;
    457 __EOF__
    458 
    459     print FILE <<__EOF__;
    460 
    461     srcy = 0;
    462     posy = 0;
    463     incy = (info->src_h << 16) / info->dst_h;
    464     incx = (info->src_w << 16) / info->dst_w;
    465 
    466     while (info->dst_h--) {
    467         $format_type{$src} *src = 0;
    468         $format_type{$dst} *dst = ($format_type{$dst} *)info->dst;
    469         int n = info->dst_w;
    470         srcx = -1;
    471         posx = 0x10000L;
    472         while (posy >= 0x10000L) {
    473             ++srcy;
    474             posy -= 0x10000L;
    475         }
    476         while (n--) {
    477             if (posx >= 0x10000L) {
    478                 while (posx >= 0x10000L) {
    479                     ++srcx;
    480                     posx -= 0x10000L;
    481                 }
    482                 src = ($format_type{$src} *)(info->src + (srcy * info->src_pitch) + (srcx * $format_size{$src}));
    483 __EOF__
    484         print FILE <<__EOF__;
    485             }
    486 __EOF__
    487         output_copycore($src, $dst, $modulate, $blend, $is_modulateA_done, $A_is_const_FF);
    488         print FILE <<__EOF__;
    489             posx += incx;
    490             ++dst;
    491         }
    492         posy += incy;
    493         info->dst += info->dst_pitch;
    494     }
    495 __EOF__
    496     } else {
    497         print FILE <<__EOF__;
    498 
    499     while (info->dst_h--) {
    500         $format_type{$src} *src = ($format_type{$src} *)info->src;
    501         $format_type{$dst} *dst = ($format_type{$dst} *)info->dst;
    502         int n = info->dst_w;
    503         while (n--) {
    504 __EOF__
    505         output_copycore($src, $dst, $modulate, $blend, $is_modulateA_done, $A_is_const_FF);
    506         print FILE <<__EOF__;
    507             ++src;
    508             ++dst;
    509         }
    510         info->src += info->src_pitch;
    511         info->dst += info->dst_pitch;
    512     }
    513 __EOF__
    514     }
    515     print FILE <<__EOF__;
    516 }
    517 
    518 __EOF__
    519 }
    520 
    521 sub output_copyfunc_h
    522 {
    523 }
    524 
    525 sub output_copyinc
    526 {
    527     print FILE <<__EOF__;
    528 #include "SDL_video.h"
    529 #include "SDL_blit.h"
    530 #include "SDL_blit_auto.h"
    531 
    532 __EOF__
    533 }
    534 
    535 sub output_copyfunctable
    536 {
    537     print FILE <<__EOF__;
    538 SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[] = {
    539 __EOF__
    540     for (my $i = 0; $i <= $#src_formats; ++$i) {
    541         my $src = $src_formats[$i];
    542         for (my $j = 0; $j <= $#dst_formats; ++$j) {
    543             my $dst = $dst_formats[$j];
    544             for (my $modulate = 0; $modulate <= 1; ++$modulate) {
    545                 for (my $blend = 0; $blend <= 1; ++$blend) {
    546                     for (my $scale = 0; $scale <= 1; ++$scale) {
    547                         if ( $modulate || $blend || $scale ) {
    548                             print FILE "    { SDL_PIXELFORMAT_$src, SDL_PIXELFORMAT_$dst, ";
    549                             my $flags = "";
    550                             my $flag = "";
    551                             if ( $modulate ) {
    552                                 $flag = "SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA";
    553                                 if ( $flags eq "" ) {
    554                                     $flags = $flag;
    555                                 } else {
    556                                     $flags = "$flags | $flag";
    557                                 }
    558                             }
    559                             if ( $blend ) {
    560                                 $flag = "SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL";
    561                                 if ( $flags eq "" ) {
    562                                     $flags = $flag;
    563                                 } else {
    564                                     $flags = "$flags | $flag";
    565                                 }
    566                             }
    567                             if ( $scale ) {
    568                                 $flag = "SDL_COPY_NEAREST";
    569                                 if ( $flags eq "" ) {
    570                                     $flags = $flag;
    571                                 } else {
    572                                     $flags = "$flags | $flag";
    573                                 }
    574                             }
    575                             if ( $flags eq "" ) {
    576                                 $flags = "0";
    577                             }
    578                             print FILE "($flags), SDL_CPU_ANY,";
    579                             output_copyfuncname("", $src_formats[$i], $dst_formats[$j], $modulate, $blend, $scale, 0, " },\n");
    580                         }
    581                     }
    582                 }
    583             }
    584         }
    585     }
    586     print FILE <<__EOF__;
    587     { 0, 0, 0, 0, NULL }
    588 };
    589 
    590 __EOF__
    591 }
    592 
    593 sub output_copyfunc_c
    594 {
    595     my $src = shift;
    596     my $dst = shift;
    597 
    598     for (my $modulate = 0; $modulate <= 1; ++$modulate) {
    599         for (my $blend = 0; $blend <= 1; ++$blend) {
    600             for (my $scale = 0; $scale <= 1; ++$scale) {
    601                 if ( $modulate || $blend || $scale ) {
    602                     output_copyfunc($src, $dst, $modulate, $blend, $scale);
    603                 }
    604             }
    605         }
    606     }
    607 }
    608 
    609 open_file("SDL_blit_auto.h");
    610 output_copydefs();
    611 for (my $i = 0; $i <= $#src_formats; ++$i) {
    612     for (my $j = 0; $j <= $#dst_formats; ++$j) {
    613         output_copyfunc_h($src_formats[$i], $dst_formats[$j]);
    614     }
    615 }
    616 print FILE "\n";
    617 close_file("SDL_blit_auto.h");
    618 
    619 open_file("SDL_blit_auto.c");
    620 output_copyinc();
    621 for (my $i = 0; $i <= $#src_formats; ++$i) {
    622     for (my $j = 0; $j <= $#dst_formats; ++$j) {
    623         output_copyfunc_c($src_formats[$i], $dst_formats[$j]);
    624     }
    625 }
    626 output_copyfunctable();
    627 close_file("SDL_blit_auto.c");