cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

sdlgenblit.pl (14995B)


      1#!/usr/bin/perl -w
      2#
      3# A script to generate optimized C blitters for Simple DirectMedia Layer
      4# http://www.libsdl.org/
      5
      6use warnings;
      7use strict;
      8
      9my %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:
     29my @src_formats = (
     30    "RGB888",
     31    "BGR888",
     32    "ARGB8888",
     33    "RGBA8888",
     34    "ABGR8888",
     35    "BGRA8888",
     36);
     37my @dst_formats = (
     38    "RGB888",
     39    "BGR888",
     40    "ARGB8888",
     41);
     42
     43my %format_size = (
     44    "RGB888" => 4,
     45    "BGR888" => 4,
     46    "ARGB8888" => 4,
     47    "RGBA8888" => 4,
     48    "ABGR8888" => 4,
     49    "BGRA8888" => 4,
     50);
     51
     52my %format_type = (
     53    "RGB888" => "Uint32",
     54    "BGR888" => "Uint32",
     55    "ARGB8888" => "Uint32",
     56    "RGBA8888" => "Uint32",
     57    "ABGR8888" => "Uint32",
     58    "BGRA8888" => "Uint32",
     59);
     60
     61my %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
     70my %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
     79my %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
     88sub 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
    120sub 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
    135sub output_copydefs
    136{
    137    print FILE <<__EOF__;
    138extern SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[];
    139__EOF__
    140}
    141
    142sub 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
    169sub 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
    197sub 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
    209sub 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
    299sub 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
    429sub output_copyfunc_h
    430{
    431}
    432
    433sub 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
    443sub output_copyfunctable
    444{
    445    print FILE <<__EOF__;
    446SDL_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
    501sub 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
    517open_file("SDL_blit_auto.h");
    518output_copydefs();
    519for (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}
    524print FILE "\n";
    525close_file("SDL_blit_auto.h");
    526
    527open_file("SDL_blit_auto.c");
    528output_copyinc();
    529for (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}
    534output_copyfunctable();
    535close_file("SDL_blit_auto.c");