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

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

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

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