ManaPlus
sdlgfxblitfunc.cpp
Go to the documentation of this file.
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
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 {
59  {
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 static void _SDL_gfxBlitBlitterRGBA(const SDL_gfxBlitInfo *const info)
338 {
339  const int width = info->d_width;
340  int height = info->d_height;
341  Uint8 *src = info->s_pixels;
342  const int srcskip = info->s_skip;
343  Uint8 *dst = info->d_pixels;
344  const int dstskip = info->d_skip;
345  const SDL_PixelFormat *const srcfmt = info->src;
346 
347  while ((height--) != 0)
348  {
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  src += srcskip;
389  dst += dstskip;
390  }
391 }
392 
393 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  if ((srcrect->w != 0U) && (srcrect->h != 0U))
402  {
403  SDL_gfxBlitInfo info;
404 
405  /*
406  * Set up the blit information
407  */
408  info.s_pixels = static_cast<Uint8 *>(src->pixels) + src->offset +
409  static_cast<Uint16>(srcrect->y) * src->pitch +
410  static_cast<Uint16>(srcrect->x) * src->format->BytesPerPixel;
411  info.s_width = srcrect->w;
412  info.s_height = srcrect->h;
413  info.s_skip = CAST_S32(src->pitch - info.s_width *
414  src->format->BytesPerPixel);
415  info.d_pixels = static_cast<Uint8 *>(dst->pixels) + dst->offset +
416  static_cast<Uint16>(dstrect->y) * dst->pitch +
417  static_cast<Uint16>(dstrect->x) * dst->format->BytesPerPixel;
418  info.d_width = dstrect->w;
419  info.d_height = dstrect->h;
420  info.d_skip = CAST_S32(dst->pitch - info.d_width *
421  dst->format->BytesPerPixel);
422  info.aux_data = nullptr;
423  info.src = src->format;
424  info.table = nullptr;
425  info.dst = dst->format;
426 
427  /*
428  * Run the actual software blitter
429  */
431  return 1;
432  }
433 
434  return 0;
435 }
436 
437 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  if (src == nullptr ||
453  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  if (dstrect == nullptr)
463  {
464  dr.x = 0;
465  dr.y = 0;
466  dr.w = CAST_U16(dst->w);
467  dr.h = CAST_U16(dst->h);
468  }
469  else
470  {
471  dr = *dstrect;
472  }
473 
474  /*
475  * Clip the source rectangle to the source surface
476  */
477  if (srcrect != nullptr)
478  {
479  int maxw;
480  int maxh;
481 
482  srcx = srcrect->x;
483  w = srcrect->w;
484  maxw = src->w - srcx;
485  if (maxw < w)
486  w = maxw;
487 
488  srcy = srcrect->y;
489  h = srcrect->h;
490  maxh = src->h - srcy;
491  if (maxh < h)
492  h = maxh;
493  }
494  else
495  {
496  srcx = 0;
497  srcy = 0;
498  w = src->w;
499  h = src->h;
500  }
501 
502  /*
503  * Clip the destination rectangle against the clip rectangle
504  */
505  const SDL_Rect *const clip = &dst->clip_rect;
506  int dx;
507  int dy;
508 
509  dx = clip->x - dr.x;
510  if (dx > 0)
511  {
512  w -= dx;
513  dr.x += dx;
514  srcx += CAST_S16(dx);
515  }
516  dx = dr.x + w - clip->x - clip->w;
517  if (dx > 0)
518  w -= dx;
519 
520  dy = clip->y - dr.y;
521  if (dy > 0)
522  {
523  h -= dy;
524  dr.y += dy;
525  srcy += CAST_S16(dy);
526  }
527  dy = dr.y + h - clip->y - clip->h;
528  if (dy > 0)
529  h -= dy;
530 
531  if (w > 0 && h > 0)
532  {
533  sr.x = CAST_S16(srcx);
534  sr.y = CAST_S16(srcy);
535  sr.w = dr.w = CAST_U16(w);
536  sr.h = dr.h = CAST_U16(h);
537  return _SDL_gfxBlitRGBACall(src, &sr, dst, &dr);
538  }
539 
540  return 0;
541 }
542 
543 #endif // USE_SDL2
#define CAST_U16
Definition: cast.h:29
#define CAST_S16
Definition: cast.h:28
#define CAST_S32
Definition: cast.h:30
#define reportAlways(...)
Definition: checkutils.h:253
#define final
Definition: localconsts.h:46
#define PRAGMA48(str)
Definition: localconsts.h:199
#define A_DEFAULT_COPY(func)
Definition: localconsts.h:41
bool info(InputEvent &event)
Definition: commands.cpp:57
static void _SDL_gfxBlitBlitterRGBA(const SDL_gfxBlitInfo *const info)
static int _SDL_gfxBlitRGBACall(const SDL_Surface *const src, const SDL_Rect *const srcrect, const SDL_Surface *const dst, const SDL_Rect *const dstrect)
#define GFX_DUFFS_LOOP4(pixel_copy_increment, width)
int SDLgfxBlitRGBA(const SDL_Surface *const src, const SDL_Rect *const srcrect, SDL_Surface *const dst, const SDL_Rect *const dstrect)