Mercurial > sdl-ios-xcode
diff src/video/sdlgenblit.pl @ 1985:8055185ae4ed
Added source color and alpha modulation support.
Added perl script to generate optimized render copy functions.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 28 Aug 2006 03:17:39 +0000 |
parents | |
children | 5b5f5de5433f |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/video/sdlgenblit.pl Mon Aug 28 03:17:39 2006 +0000 @@ -0,0 +1,521 @@ +#!/usr/bin/perl -w +# +# A script to generate optimized C blitters for Simple DirectMedia Layer +# http://www.libsdl.org/ + +use warnings; +use strict; + +my %file; + +# The formats potentially supported by this script: +# SDL_PIXELFORMAT_INDEX8 +# SDL_PIXELFORMAT_RGB332 +# SDL_PIXELFORMAT_RGB444 +# SDL_PIXELFORMAT_RGB555 +# SDL_PIXELFORMAT_ARGB4444 +# SDL_PIXELFORMAT_ARGB1555 +# SDL_PIXELFORMAT_RGB565 +# SDL_PIXELFORMAT_RGB24 +# SDL_PIXELFORMAT_BGR24 +# SDL_PIXELFORMAT_RGB888 +# SDL_PIXELFORMAT_BGR888 +# SDL_PIXELFORMAT_ARGB8888 +# SDL_PIXELFORMAT_RGBA8888 +# SDL_PIXELFORMAT_ABGR8888 +# SDL_PIXELFORMAT_BGRA8888 +# SDL_PIXELFORMAT_ARGB2101010 + +# The formats we're actually creating blitters for: +my @src_formats = ( + "RGB888", + "BGR888", + "ARGB8888", + "RGBA8888", + "ABGR8888", + "BGRA8888", +); +my @dst_formats = ( + "RGB888", + "BGR888", +); + +my %format_size = ( + "RGB888" => 4, + "BGR888" => 4, + "ARGB8888" => 4, + "RGBA8888" => 4, + "ABGR8888" => 4, + "BGRA8888" => 4, +); + +my %format_type = ( + "RGB888" => "Uint32", + "BGR888" => "Uint32", + "ARGB8888" => "Uint32", + "RGBA8888" => "Uint32", + "ABGR8888" => "Uint32", + "BGRA8888" => "Uint32", +); + +my %get_rgba_string = ( + "RGB888" => "_R = (Uint8)(_pixel >> 16); _G = (Uint8)(_pixel >> 8); _B = (Uint8)_pixel; _A = 0xFF;", + "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;", + "RGBA8888" => "_R = (Uint8)(_pixel >> 24); _G = (Uint8)(_pixel >> 16); _B = (Uint8)(_pixel >> 8); _A = (Uint8)_pixel;", + "ABGR8888" => "_A = (Uint8)(_pixel >> 24); _B = (Uint8)(_pixel >> 16); _G = (Uint8)(_pixel >> 8); _R = (Uint8)_pixel;", + "BGRA8888" => "_B = (Uint8)(_pixel >> 24); _G = (Uint8)(_pixel >> 16); _R = (Uint8)(_pixel >> 8); _A = (Uint8)_pixel;", +); + +my %set_rgba_string = ( + "RGB888" => "_pixel = ((Uint32)_R << 16) | ((Uint32)_G << 8) | _B;", + "BGR888" => "_pixel = ((Uint32)_B << 16) | ((Uint32)_G << 8) | _R;", +); + +sub open_file { + my $name = shift; + open(FILE, ">$name.new") || die "Cant' open $name.new: $!"; + print FILE <<__EOF__; +/* DO NOT EDIT! This file is generated by sdlgenblit.pl */ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2006 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken\@libsdl.org +*/ +#include "SDL_config.h" + +/* *INDENT-OFF* */ + +__EOF__ +} + +sub close_file { + my $name = shift; + print FILE <<__EOF__; +/* *INDENT-ON* */ + +/* vi: set ts=4 sw=4 expandtab: */ +__EOF__ + close FILE; + if ( ! -f $name || system("cmp -s $name $name.new") != 0 ) { + rename("$name.new", "$name"); + } else { + unlink("$name.new"); + } +} + +sub output_copydefs +{ + print FILE <<__EOF__; +#define SDL_RENDERCOPY_MODULATE_COLOR 0x0001 +#define SDL_RENDERCOPY_MODULATE_ALPHA 0x0002 +#define SDL_RENDERCOPY_BLEND 0x0010 +#define SDL_RENDERCOPY_ADD 0x0020 +#define SDL_RENDERCOPY_MOD 0x0040 +#define SDL_RENDERCOPY_NEAREST 0x0100 + +typedef struct { + void *src; + int src_w, src_h; + int src_pitch; + void *dst; + int dst_w, dst_h; + int dst_pitch; + void *aux_data; + int flags; + Uint8 r, g, b, a; +} SDL_RenderCopyData; + +typedef int (*SDL_RenderCopyFunc)(SDL_RenderCopyData *data); + +extern SDL_RenderCopyFunc SDLCALL SDL_GetRenderCopyFunc(Uint32 src_format, Uint32 dst_format, int modMode, int blendMode, int scaleMode); + +__EOF__ +} + +sub output_copyfuncname +{ + my $prefix = shift; + my $src = shift; + my $dst = shift; + my $modulate = shift; + my $blend = shift; + my $scale = shift; + my $args = shift; + my $suffix = shift; + + print FILE "$prefix SDL_RenderCopy_${src}_${dst}"; + if ( $modulate ) { + print FILE "_Modulate"; + } + if ( $blend ) { + print FILE "_Blend"; + } + if ( $scale ) { + print FILE "_Scale"; + } + if ( $args ) { + print FILE "(SDL_RenderCopyData *data)"; + } + print FILE "$suffix"; +} + +sub get_rgba +{ + my $prefix = shift; + my $format = shift; + my $string = $get_rgba_string{$format}; + $string =~ s/_/$prefix/g; + if ( $prefix ne "" ) { + print FILE <<__EOF__; + ${prefix}pixel = *$prefix; +__EOF__ + } else { + print FILE <<__EOF__; + pixel = *src; +__EOF__ + } + print FILE <<__EOF__; + $string +__EOF__ +} + +sub set_rgba +{ + my $prefix = shift; + my $format = shift; + my $string = $set_rgba_string{$format}; + $string =~ s/_/$prefix/g; + print FILE <<__EOF__; + $string + *dst = ${prefix}pixel; +__EOF__ +} + +sub output_copycore +{ + my $src = shift; + my $dst = shift; + my $modulate = shift; + my $blend = shift; + if ( $modulate ) { + print FILE <<__EOF__; + if (flags & SDL_RENDERCOPY_MODULATE_COLOR) { + ${src}R = (${src}R * modulateR) / 255; + ${src}G = (${src}G * modulateG) / 255; + ${src}B = (${src}B * modulateB) / 255; + } +__EOF__ + } + if ( $modulate && $blend ) { + print FILE <<__EOF__; + if (flags & SDL_RENDERCOPY_MODULATE_ALPHA) { + ${src}A = (${src}A * modulateA) / 255; + } +__EOF__ + } + if ( $blend ) { + print FILE <<__EOF__; + if (flags & (SDL_RENDERCOPY_BLEND|SDL_RENDERCOPY_ADD)) { + /* This goes away if we ever use premultiplied alpha */ + ${src}R = (${src}R * ${src}A) / 255; + ${src}G = (${src}G * ${src}A) / 255; + ${src}B = (${src}B * ${src}A) / 255; + } + switch (flags & (SDL_RENDERCOPY_BLEND|SDL_RENDERCOPY_ADD|SDL_RENDERCOPY_MOD)) { + case SDL_RENDERCOPY_BLEND: + ${dst}R = ${src}R + ((255 - ${src}A) * ${dst}R) / 255; + ${dst}G = ${src}G + ((255 - ${src}A) * ${dst}G) / 255; + ${dst}B = ${src}B + ((255 - ${src}A) * ${dst}B) / 255; + break; + case SDL_RENDERCOPY_ADD: + ${dst}R = ${src}R + ${dst}R; if (${dst}R > 255) ${dst}R = 255; + ${dst}G = ${src}G + ${dst}G; if (${dst}G > 255) ${dst}G = 255; + ${dst}B = ${src}B + ${dst}B; if (${dst}B > 255) ${dst}B = 255; + break; + case SDL_RENDERCOPY_MOD: + ${dst}R = (${src}R * ${dst}R) / 255; + ${dst}G = (${src}G * ${dst}G) / 255; + ${dst}B = (${src}B * ${dst}B) / 255; + break; + } +__EOF__ + } +} + +sub output_copyfunc +{ + my $src = shift; + my $dst = shift; + my $modulate = shift; + my $blend = shift; + my $scale = shift; + + output_copyfuncname("int", $src, $dst, $modulate, $blend, $scale, 1, "\n"); + print FILE <<__EOF__; +{ + const int flags = data->flags; +__EOF__ + if ( $modulate ) { + print FILE <<__EOF__; + const Uint32 modulateR = data->r; + const Uint32 modulateG = data->g; + const Uint32 modulateB = data->b; + const Uint32 modulateA = data->a; +__EOF__ + } + if ( $blend ) { + print FILE <<__EOF__; + Uint32 srcpixel; + Uint32 srcR, srcG, srcB, srcA; + Uint32 dstpixel; + Uint32 dstR, dstG, dstB, dstA; +__EOF__ + } elsif ( $modulate || $src ne $dst ) { + print FILE <<__EOF__; + Uint32 pixel; + Uint32 R, G, B, A; +__EOF__ + } + if ( $scale ) { + print FILE <<__EOF__; + int srcy, srcx; + int posy, posx; + int incy, incx; + + srcy = 0; + posy = 0; + incy = (data->src_h << 16) / data->dst_h; + incx = (data->src_w << 16) / data->dst_w; + + while (data->dst_h--) { + $format_type{$src} *src; + $format_type{$dst} *dst = ($format_type{$dst} *)data->dst; + int n = data->dst_w; + srcx = -1; + posx = 0x10000L; + while (posy >= 0x10000L) { + ++srcy; + posy -= 0x10000L; + } + while (n--) { + if (posx >= 0x10000L) { + while (posx >= 0x10000L) { + ++srcx; + posx -= 0x10000L; + } + src = ($format_type{$src} *)(data->src + (srcy * data->src_pitch) + (srcx * $format_size{$src})); +__EOF__ + print FILE <<__EOF__; + } +__EOF__ + if ( $blend ) { + get_rgba("src", $src); + get_rgba("dst", $dst); + output_copycore("src", "dst", $modulate, $blend); + set_rgba("dst", $dst); + } elsif ( $modulate || $src ne $dst ) { + get_rgba("", $src); + output_copycore("", "", $modulate, $blend); + set_rgba("", $dst); + } else { + print FILE <<__EOF__; + *dst = *src; +__EOF__ + } + print FILE <<__EOF__; + posx += incx; + ++dst; + } + posy += incy; + data->dst += data->dst_pitch; + } +__EOF__ + } else { + print FILE <<__EOF__; + + while (data->dst_h--) { + $format_type{$src} *src = ($format_type{$src} *)data->src; + $format_type{$dst} *dst = ($format_type{$dst} *)data->dst; + int n = data->dst_w; + while (n--) { +__EOF__ + if ( $blend ) { + get_rgba("src", $src); + get_rgba("dst", $dst); + output_copycore("src", "dst", $modulate, $blend); + set_rgba("dst", $dst); + } elsif ( $modulate || $src ne $dst ) { + get_rgba("", $src); + output_copycore("", "", $modulate, $blend); + set_rgba("", $dst); + } else { + print FILE <<__EOF__; + *dst = *src; +__EOF__ + } + print FILE <<__EOF__; + ++src; + ++dst; + } + data->src += data->src_pitch; + data->dst += data->dst_pitch; + } +__EOF__ + } + print FILE <<__EOF__; + return 0; +} + +__EOF__ +} + +sub output_copyfunc_h +{ + my $src = shift; + my $dst = shift; + for (my $modulate = 0; $modulate <= 1; ++$modulate) { + for (my $blend = 0; $blend <= 1; ++$blend) { + for (my $scale = 0; $scale <= 1; ++$scale) { + if ( $modulate != 0 || $blend != 0 || $scale != 0 || $src ne $dst ) { + output_copyfuncname("extern int SDLCALL", $src, $dst, $modulate, $blend, $scale, 1, ";\n"); + } + } + } + } +} + +sub output_copyinc +{ + print FILE <<__EOF__; +#include "SDL_video.h" +#include "SDL_rendercopy.h" + +__EOF__ +} + +sub output_copyfunctable +{ + print FILE <<__EOF__; +static struct { + Uint32 src_format; + Uint32 dst_format; + int modMode; + int blendMode; + int scaleMode; + SDL_RenderCopyFunc func; +} SDL_RenderCopyFuncTable[] = { +__EOF__ + for (my $i = 0; $i <= $#src_formats; ++$i) { + my $src = $src_formats[$i]; + for (my $j = 0; $j <= $#dst_formats; ++$j) { + my $dst = $dst_formats[$j]; + for (my $modulate = 0; $modulate <= 1; ++$modulate) { + for (my $blend = 0; $blend <= 1; ++$blend) { + for (my $scale = 0; $scale <= 1; ++$scale) { + if ( $modulate != 0 || $blend != 0 || $scale != 0 || $src ne $dst ) { + print FILE " { SDL_PIXELFORMAT_$src, SDL_PIXELFORMAT_$dst, "; + if ( $modulate ) { + print FILE "(SDL_TEXTUREMODULATE_COLOR | SDL_TEXTUREMODULATE_ALPHA), "; + } else { + print FILE "0, "; + } + if ( $blend ) { + print FILE "(SDL_TEXTUREBLENDMODE_MASK | SDL_TEXTUREBLENDMODE_BLEND | SDL_TEXTUREBLENDMODE_ADD | SDL_TEXTUREBLENDMODE_MOD), "; + } else { + print FILE "0, "; + } + if ( $scale ) { + print FILE "SDL_TEXTURESCALEMODE_FAST, "; + } else { + print FILE "0, "; + } + output_copyfuncname("", $src_formats[$i], $dst_formats[$j], $modulate, $blend, $scale, 0, " },\n"); + } + } + } + } + } + } + print FILE <<__EOF__; +}; + +SDL_RenderCopyFunc SDL_GetRenderCopyFunc(Uint32 src_format, Uint32 dst_format, int modMode, int blendMode, int scaleMode) +{ + int i; + + for (i = 0; i < SDL_arraysize(SDL_RenderCopyFuncTable); ++i) { + if (src_format != SDL_RenderCopyFuncTable[i].src_format) { + continue; + } + if (dst_format != SDL_RenderCopyFuncTable[i].dst_format) { + continue; + } + if ((modMode & SDL_RenderCopyFuncTable[i].modMode) != modMode) { + continue; + } + if ((blendMode & SDL_RenderCopyFuncTable[i].blendMode) != blendMode) { + continue; + } + if ((scaleMode & SDL_RenderCopyFuncTable[i].scaleMode) != scaleMode) { + continue; + } + return SDL_RenderCopyFuncTable[i].func; + } + return NULL; +} + +__EOF__ +} + +sub output_copyfunc_c +{ + my $src = shift; + my $dst = shift; + + for (my $modulate = 0; $modulate <= 1; ++$modulate) { + for (my $blend = 0; $blend <= 1; ++$blend) { + for (my $scale = 0; $scale <= 1; ++$scale) { + if ( $modulate != 0 || $blend != 0 || $scale != 0 || $src ne $dst ) { + output_copyfunc($src, $dst, $modulate, $blend, $scale); + } + } + } + } +} + +open_file("SDL_rendercopy.h"); +output_copydefs(); +for (my $i = 0; $i <= $#src_formats; ++$i) { + for (my $j = 0; $j <= $#dst_formats; ++$j) { + output_copyfunc_h($src_formats[$i], $dst_formats[$j]); + } +} +print FILE "\n"; +close_file("SDL_rendercopy.h"); + +open_file("SDL_rendercopy.c"); +output_copyinc(); +output_copyfunctable(); +for (my $i = 0; $i <= $#src_formats; ++$i) { + for (my $j = 0; $j <= $#dst_formats; ++$j) { + output_copyfunc_c($src_formats[$i], $dst_formats[$j]); + } +} +close_file("SDL_rendercopy.c");