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