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");