• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-2016 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");
536