GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/resources/sdlgfxblitfunc.cpp Lines: 77 80 96.3 %
Date: 2021-03-17 Branches: 26 35 74.3 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2017-2019  The ManaPlus Developers
4
 *  Copyright (C) 2019-2021  Andrei Karas
5
 *
6
 *  This file is part of The ManaPlus Client.
7
 *
8
 *  This program is free software; you can redistribute it and/or modify
9
 *  it under the terms of the GNU General Public License as published by
10
 *  the Free Software Foundation; either version 2 of the License, or
11
 *  any later version.
12
 *
13
 *  This program is distributed in the hope that it will be useful,
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 *  GNU General Public License for more details.
17
 *
18
 *  You should have received a copy of the GNU General Public License
19
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 */
21
22
/*
23
24
SDL_gfxBlitFunc: custom blitters (part of SDL_gfx library)
25
26
LGPL (c) A. Schiffler
27
28
*/
29
30
#ifndef USE_SDL2
31
#include "resources/sdlgfxblitfunc.h"
32
33
#include "utils/cast.h"
34
#include "utils/checkutils.h"
35
36
PRAGMA48(GCC diagnostic push)
37
PRAGMA48(GCC diagnostic ignored "-Wshadow")
38
#include <SDL_video.h>
39
PRAGMA48(GCC diagnostic pop)
40
41
#include "debug.h"
42
43
#define GFX_DUFFS_LOOP4(pixel_copy_increment, width) \
44
    int n = ((width) + 3) / 4; \
45
    switch ((width) & 3) \
46
    { \
47
        case 0: do { \
48
            pixel_copy_increment; \
49
        case 3: pixel_copy_increment; \
50
        case 2: pixel_copy_increment; \
51
        case 1: pixel_copy_increment; \
52
        default: ; \
53
            } while (--n > 0 ); \
54
    }
55
56
namespace
57
{
58
    struct SDL_gfxBlitInfo final
59
    {
60
        A_DEFAULT_COPY(SDL_gfxBlitInfo)
61
62
        Uint8    *s_pixels;
63
        int       s_width;
64
        int       s_height;
65
        int       s_skip;
66
        Uint8    *d_pixels;
67
        int       d_width;
68
        int       d_height;
69
        int       d_skip;
70
        void     *aux_data;
71
        SDL_PixelFormat *src;
72
        Uint8    *table;
73
        SDL_PixelFormat *dst;
74
    };
75
76
    unsigned int GFX_ALPHA_ADJUST_ARRAY[256] =
77
    {
78
        0,  /* 0 */
79
        15,  /* 1 */
80
        22,  /* 2 */
81
        27,  /* 3 */
82
        31,  /* 4 */
83
        35,  /* 5 */
84
        39,  /* 6 */
85
        42,  /* 7 */
86
        45,  /* 8 */
87
        47,  /* 9 */
88
        50,  /* 10 */
89
        52,  /* 11 */
90
        55,  /* 12 */
91
        57,  /* 13 */
92
        59,  /* 14 */
93
        61,  /* 15 */
94
        63,  /* 16 */
95
        65,  /* 17 */
96
        67,  /* 18 */
97
        69,  /* 19 */
98
        71,  /* 20 */
99
        73,  /* 21 */
100
        74,  /* 22 */
101
        76,  /* 23 */
102
        78,  /* 24 */
103
        79,  /* 25 */
104
        81,  /* 26 */
105
        82,  /* 27 */
106
        84,  /* 28 */
107
        85,  /* 29 */
108
        87,  /* 30 */
109
        88,  /* 31 */
110
        90,  /* 32 */
111
        91,  /* 33 */
112
        93,  /* 34 */
113
        94,  /* 35 */
114
        95,  /* 36 */
115
        97,  /* 37 */
116
        98,  /* 38 */
117
        99,  /* 39 */
118
        100,  /* 40 */
119
        102,  /* 41 */
120
        103,  /* 42 */
121
        104,  /* 43 */
122
        105,  /* 44 */
123
        107,  /* 45 */
124
        108,  /* 46 */
125
        109,  /* 47 */
126
        110,  /* 48 */
127
        111,  /* 49 */
128
        112,  /* 50 */
129
        114,  /* 51 */
130
        115,  /* 52 */
131
        116,  /* 53 */
132
        117,  /* 54 */
133
        118,  /* 55 */
134
        119,  /* 56 */
135
        120,  /* 57 */
136
        121,  /* 58 */
137
        122,  /* 59 */
138
        123,  /* 60 */
139
        124,  /* 61 */
140
        125,  /* 62 */
141
        126,  /* 63 */
142
        127,  /* 64 */
143
        128,  /* 65 */
144
        129,  /* 66 */
145
        130,  /* 67 */
146
        131,  /* 68 */
147
        132,  /* 69 */
148
        133,  /* 70 */
149
        134,  /* 71 */
150
        135,  /* 72 */
151
        136,  /* 73 */
152
        137,  /* 74 */
153
        138,  /* 75 */
154
        139,  /* 76 */
155
        140,  /* 77 */
156
        141,  /* 78 */
157
        141,  /* 79 */
158
        142,  /* 80 */
159
        143,  /* 81 */
160
        144,  /* 82 */
161
        145,  /* 83 */
162
        146,  /* 84 */
163
        147,  /* 85 */
164
        148,  /* 86 */
165
        148,  /* 87 */
166
        149,  /* 88 */
167
        150,  /* 89 */
168
        151,  /* 90 */
169
        152,  /* 91 */
170
        153,  /* 92 */
171
        153,  /* 93 */
172
        154,  /* 94 */
173
        155,  /* 95 */
174
        156,  /* 96 */
175
        157,  /* 97 */
176
        158,  /* 98 */
177
        158,  /* 99 */
178
        159,  /* 100 */
179
        160,  /* 101 */
180
        161,  /* 102 */
181
        162,  /* 103 */
182
        162,  /* 104 */
183
        163,  /* 105 */
184
        164,  /* 106 */
185
        165,  /* 107 */
186
        165,  /* 108 */
187
        166,  /* 109 */
188
        167,  /* 110 */
189
        168,  /* 111 */
190
        168,  /* 112 */
191
        169,  /* 113 */
192
        170,  /* 114 */
193
        171,  /* 115 */
194
        171,  /* 116 */
195
        172,  /* 117 */
196
        173,  /* 118 */
197
        174,  /* 119 */
198
        174,  /* 120 */
199
        175,  /* 121 */
200
        176,  /* 122 */
201
        177,  /* 123 */
202
        177,  /* 124 */
203
        178,  /* 125 */
204
        179,  /* 126 */
205
        179,  /* 127 */
206
        180,  /* 128 */
207
        181,  /* 129 */
208
        182,  /* 130 */
209
        182,  /* 131 */
210
        183,  /* 132 */
211
        184,  /* 133 */
212
        184,  /* 134 */
213
        185,  /* 135 */
214
        186,  /* 136 */
215
        186,  /* 137 */
216
        187,  /* 138 */
217
        188,  /* 139 */
218
        188,  /* 140 */
219
        189,  /* 141 */
220
        190,  /* 142 */
221
        190,  /* 143 */
222
        191,  /* 144 */
223
        192,  /* 145 */
224
        192,  /* 146 */
225
        193,  /* 147 */
226
        194,  /* 148 */
227
        194,  /* 149 */
228
        195,  /* 150 */
229
        196,  /* 151 */
230
        196,  /* 152 */
231
        197,  /* 153 */
232
        198,  /* 154 */
233
        198,  /* 155 */
234
        199,  /* 156 */
235
        200,  /* 157 */
236
        200,  /* 158 */
237
        201,  /* 159 */
238
        201,  /* 160 */
239
        202,  /* 161 */
240
        203,  /* 162 */
241
        203,  /* 163 */
242
        204,  /* 164 */
243
        205,  /* 165 */
244
        205,  /* 166 */
245
        206,  /* 167 */
246
        206,  /* 168 */
247
        207,  /* 169 */
248
        208,  /* 170 */
249
        208,  /* 171 */
250
        209,  /* 172 */
251
        210,  /* 173 */
252
        210,  /* 174 */
253
        211,  /* 175 */
254
        211,  /* 176 */
255
        212,  /* 177 */
256
        213,  /* 178 */
257
        213,  /* 179 */
258
        214,  /* 180 */
259
        214,  /* 181 */
260
        215,  /* 182 */
261
        216,  /* 183 */
262
        216,  /* 184 */
263
        217,  /* 185 */
264
        217,  /* 186 */
265
        218,  /* 187 */
266
        218,  /* 188 */
267
        219,  /* 189 */
268
        220,  /* 190 */
269
        220,  /* 191 */
270
        221,  /* 192 */
271
        221,  /* 193 */
272
        222,  /* 194 */
273
        222,  /* 195 */
274
        223,  /* 196 */
275
        224,  /* 197 */
276
        224,  /* 198 */
277
        225,  /* 199 */
278
        225,  /* 200 */
279
        226,  /* 201 */
280
        226,  /* 202 */
281
        227,  /* 203 */
282
        228,  /* 204 */
283
        228,  /* 205 */
284
        229,  /* 206 */
285
        229,  /* 207 */
286
        230,  /* 208 */
287
        230,  /* 209 */
288
        231,  /* 210 */
289
        231,  /* 211 */
290
        232,  /* 212 */
291
        233,  /* 213 */
292
        233,  /* 214 */
293
        234,  /* 215 */
294
        234,  /* 216 */
295
        235,  /* 217 */
296
        235,  /* 218 */
297
        236,  /* 219 */
298
        236,  /* 220 */
299
        237,  /* 221 */
300
        237,  /* 222 */
301
        238,  /* 223 */
302
        238,  /* 224 */
303
        239,  /* 225 */
304
        240,  /* 226 */
305
        240,  /* 227 */
306
        241,  /* 228 */
307
        241,  /* 229 */
308
        242,  /* 230 */
309
        242,  /* 231 */
310
        243,  /* 232 */
311
        243,  /* 233 */
312
        244,  /* 234 */
313
        244,  /* 235 */
314
        245,  /* 236 */
315
        245,  /* 237 */
316
        246,  /* 238 */
317
        246,  /* 239 */
318
        247,  /* 240 */
319
        247,  /* 241 */
320
        248,  /* 242 */
321
        248,  /* 243 */
322
        249,  /* 244 */
323
        249,  /* 245 */
324
        250,  /* 246 */
325
        250,  /* 247 */
326
        251,  /* 248 */
327
        251,  /* 249 */
328
        252,  /* 250 */
329
        252,  /* 251 */
330
        253,  /* 252 */
331
        253,  /* 253 */
332
        254,  /* 254 */
333
        255   /* 255 */
334
    };
335
}  // namespace
336
337
661
static void _SDL_gfxBlitBlitterRGBA(const SDL_gfxBlitInfo *const info)
338
{
339
661
    const int width = info->d_width;
340
661
    int height = info->d_height;
341
661
    Uint8 *src = info->s_pixels;
342
661
    const int srcskip = info->s_skip;
343
661
    Uint8 *dst = info->d_pixels;
344
661
    const int dstskip = info->d_skip;
345
661
    const SDL_PixelFormat *const srcfmt = info->src;
346
347
24885
    while ((height--) != 0)
348
    {
349

12112
        GFX_DUFFS_LOOP4(
350
        {
351
            Uint32 pixel;
352
            uint32_t sR;
353
            uint32_t sG;
354
            uint32_t sB;
355
            uint32_t sA;
356
            uint32_t dR;
357
            uint32_t dG;
358
            uint32_t dB;
359
            uint32_t dA;
360
            uint32_t sAA;
361
362
            pixel = *(reinterpret_cast<uint32_t *>(src));
363
            sR = ((pixel & srcfmt->Rmask) >> srcfmt->Rshift);
364
            sG = ((pixel & srcfmt->Gmask) >> srcfmt->Gshift);
365
            sB = ((pixel & srcfmt->Bmask) >> srcfmt->Bshift);
366
            sA = ((pixel & srcfmt->Amask) >> srcfmt->Ashift);
367
368
            pixel = *(reinterpret_cast<uint32_t *>(dst));
369
            dR = pixel & 0xffU;
370
            dG = ((pixel & 0xff00U) >> 8);
371
            dB = ((pixel & 0xff0000U) >> 16);
372
            dA = ((pixel & 0xff000000U) >> 24);
373
374
            sAA = GFX_ALPHA_ADJUST_ARRAY[sA & 255];
375
            dR = (((sR - dR) * (sAA)) / 255) + dR;
376
            dG = (((sG - dG) * (sAA)) / 255) + dG;
377
            dB = (((sB - dB) * (sAA)) / 255) + dB;
378
            dA |= sAA;
379
380
            *(reinterpret_cast<uint32_t *>(dst)) = dR |
381
                (dG << 8) |
382
                (dB << 16) |
383
                (dA << 24);
384
385
            src += 4;
386
            dst += 4;
387
        }, width)
388
12112
        src += srcskip;
389
12112
        dst += dstskip;
390
    }
391
661
}
392
393
661
static int _SDL_gfxBlitRGBACall(const SDL_Surface *const src,
394
                                const SDL_Rect *const srcrect,
395
                                const SDL_Surface *const dst,
396
                                const SDL_Rect *const dstrect)
397
{
398
    /*
399
    * Set up source and destination buffer pointers, then blit
400
    */
401

661
    if ((srcrect->w != 0U) && (srcrect->h != 0U))
402
    {
403
        SDL_gfxBlitInfo info;
404
405
        /*
406
        * Set up the blit information
407
        */
408
1322
        info.s_pixels = static_cast<Uint8 *>(src->pixels) + src->offset +
409
1322
            static_cast<Uint16>(srcrect->y) * src->pitch +
410
661
            static_cast<Uint16>(srcrect->x) * src->format->BytesPerPixel;
411
661
        info.s_width = srcrect->w;
412
661
        info.s_height = srcrect->h;
413
661
        info.s_skip = CAST_S32(src->pitch - info.s_width *
414
            src->format->BytesPerPixel);
415
1322
        info.d_pixels = static_cast<Uint8 *>(dst->pixels) + dst->offset +
416
1322
            static_cast<Uint16>(dstrect->y) * dst->pitch +
417
661
            static_cast<Uint16>(dstrect->x) * dst->format->BytesPerPixel;
418
661
        info.d_width = dstrect->w;
419
661
        info.d_height = dstrect->h;
420
661
        info.d_skip = CAST_S32(dst->pitch - info.d_width *
421
            dst->format->BytesPerPixel);
422
661
        info.aux_data = nullptr;
423
661
        info.src = src->format;
424
661
        info.table = nullptr;
425
661
        info.dst = dst->format;
426
427
        /*
428
        * Run the actual software blitter
429
        */
430
661
        _SDL_gfxBlitBlitterRGBA(&info);
431
        return 1;
432
    }
433
434
    return 0;
435
}
436
437
661
int SDLgfxBlitRGBA(const SDL_Surface *const src,
438
                   const SDL_Rect *const srcrect,
439
                   SDL_Surface *const dst,
440
                   const SDL_Rect *const dstrect)
441
{
442
    SDL_Rect sr;
443
    SDL_Rect dr;
444
    int srcx;
445
    int srcy;
446
    int w;
447
    int h;
448
449
    /*
450
    * Make sure the surfaces aren't locked
451
    */
452
1322
    if (src == nullptr ||
453
661
        dst == nullptr)
454
    {
455
        reportAlways("SDLgfxBlitRGBA: passed a NULL surface")
456
        return -1;
457
    }
458
459
    /*
460
    * If the destination rectangle is NULL, use the entire dest surface
461
    */
462
661
    if (dstrect == nullptr)
463
    {
464
9
        dr.x = 0;
465
9
        dr.y = 0;
466
9
        dr.w = CAST_U16(dst->w);
467
9
        dr.h = CAST_U16(dst->h);
468
    }
469
    else
470
    {
471
652
        dr = *dstrect;
472
    }
473
474
    /*
475
    * Clip the source rectangle to the source surface
476
    */
477
661
    if (srcrect != nullptr)
478
    {
479
        int maxw;
480
        int maxh;
481
482
2
        srcx = srcrect->x;
483
2
        w = srcrect->w;
484
2
        maxw = src->w - srcx;
485
2
        if (maxw < w)
486
            w = maxw;
487
488
2
        srcy = srcrect->y;
489
2
        h = srcrect->h;
490
2
        maxh = src->h - srcy;
491
2
        if (maxh < h)
492
            h = maxh;
493
    }
494
    else
495
    {
496
659
        srcx = 0;
497
659
        srcy = 0;
498
659
        w = src->w;
499
659
        h = src->h;
500
    }
501
502
    /*
503
    * Clip the destination rectangle against the clip rectangle
504
    */
505
661
    const SDL_Rect *const clip = &dst->clip_rect;
506
    int dx;
507
    int dy;
508
509
661
    dx = clip->x - dr.x;
510
661
    if (dx > 0)
511
    {
512
130
        w -= dx;
513
130
        dr.x += dx;
514
130
        srcx += CAST_S16(dx);
515
    }
516
661
    dx = dr.x + w - clip->x - clip->w;
517
661
    if (dx > 0)
518
130
        w -= dx;
519
520
661
    dy = clip->y - dr.y;
521
661
    if (dy > 0)
522
    {
523
130
        h -= dy;
524
130
        dr.y += dy;
525
130
        srcy += CAST_S16(dy);
526
    }
527
661
    dy = dr.y + h - clip->y - clip->h;
528
661
    if (dy > 0)
529
130
        h -= dy;
530
531
661
    if (w > 0 && h > 0)
532
    {
533
661
        sr.x = CAST_S16(srcx);
534
661
        sr.y = CAST_S16(srcy);
535
661
        sr.w = dr.w = CAST_U16(w);
536
661
        sr.h = dr.h = CAST_U16(h);
537
661
        return _SDL_gfxBlitRGBACall(src, &sr, dst, &dr);
538
    }
539
540
    return 0;
541
}
542
543
#endif  // USE_SDL2