SDL  2.0
SDL_RLEaccel.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../SDL_internal.h"
22 
23 /*
24  * RLE encoding for software colorkey and alpha-channel acceleration
25  *
26  * Original version by Sam Lantinga
27  *
28  * Mattias Engdegård (Yorick): Rewrite. New encoding format, encoder and
29  * decoder. Added per-surface alpha blitter. Added per-pixel alpha
30  * format, encoder and blitter.
31  *
32  * Many thanks to Xark and johns for hints, benchmarks and useful comments
33  * leading to this code.
34  *
35  * Welcome to Macro Mayhem.
36  */
37 
38 /*
39  * The encoding translates the image data to a stream of segments of the form
40  *
41  * <skip> <run> <data>
42  *
43  * where <skip> is the number of transparent pixels to skip,
44  * <run> is the number of opaque pixels to blit,
45  * and <data> are the pixels themselves.
46  *
47  * This basic structure is used both for colorkeyed surfaces, used for simple
48  * binary transparency and for per-surface alpha blending, and for surfaces
49  * with per-pixel alpha. The details differ, however:
50  *
51  * Encoding of colorkeyed surfaces:
52  *
53  * Encoded pixels always have the same format as the target surface.
54  * <skip> and <run> are unsigned 8 bit integers, except for 32 bit depth
55  * where they are 16 bit. This makes the pixel data aligned at all times.
56  * Segments never wrap around from one scan line to the next.
57  *
58  * The end of the sequence is marked by a zero <skip>,<run> pair at the *
59  * beginning of a line.
60  *
61  * Encoding of surfaces with per-pixel alpha:
62  *
63  * The sequence begins with a struct RLEDestFormat describing the target
64  * pixel format, to provide reliable un-encoding.
65  *
66  * Each scan line is encoded twice: First all completely opaque pixels,
67  * encoded in the target format as described above, and then all
68  * partially transparent (translucent) pixels (where 1 <= alpha <= 254),
69  * in the following 32-bit format:
70  *
71  * For 32-bit targets, each pixel has the target RGB format but with
72  * the alpha value occupying the highest 8 bits. The <skip> and <run>
73  * counts are 16 bit.
74  *
75  * For 16-bit targets, each pixel has the target RGB format, but with
76  * the middle component (usually green) shifted 16 steps to the left,
77  * and the hole filled with the 5 most significant bits of the alpha value.
78  * i.e. if the target has the format rrrrrggggggbbbbb,
79  * the encoded pixel will be 00000gggggg00000rrrrr0aaaaabbbbb.
80  * The <skip> and <run> counts are 8 bit for the opaque lines, 16 bit
81  * for the translucent lines. Two padding bytes may be inserted
82  * before each translucent line to keep them 32-bit aligned.
83  *
84  * The end of the sequence is marked by a zero <skip>,<run> pair at the
85  * beginning of an opaque line.
86  */
87 
88 #include "SDL_video.h"
89 #include "SDL_sysvideo.h"
90 #include "SDL_blit.h"
91 #include "SDL_RLEaccel_c.h"
92 
93 #ifndef MAX
94 #define MAX(a, b) ((a) > (b) ? (a) : (b))
95 #endif
96 #ifndef MIN
97 #define MIN(a, b) ((a) < (b) ? (a) : (b))
98 #endif
99 
100 #define PIXEL_COPY(to, from, len, bpp) \
101  SDL_memcpy(to, from, (size_t)(len) * (bpp))
102 
103 /*
104  * Various colorkey blit methods, for opaque and per-surface alpha
105  */
106 
107 #define OPAQUE_BLIT(to, from, length, bpp, alpha) \
108  PIXEL_COPY(to, from, length, bpp)
109 
110 /*
111  * For 32bpp pixels on the form 0x00rrggbb:
112  * If we treat the middle component separately, we can process the two
113  * remaining in parallel. This is safe to do because of the gap to the left
114  * of each component, so the bits from the multiplication don't collide.
115  * This can be used for any RGB permutation of course.
116  */
117 #define ALPHA_BLIT32_888(to, from, length, bpp, alpha) \
118  do { \
119  int i; \
120  Uint32 *src = (Uint32 *)(from); \
121  Uint32 *dst = (Uint32 *)(to); \
122  for (i = 0; i < (int)(length); i++) { \
123  Uint32 s = *src++; \
124  Uint32 d = *dst; \
125  Uint32 s1 = s & 0xff00ff; \
126  Uint32 d1 = d & 0xff00ff; \
127  d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff; \
128  s &= 0xff00; \
129  d &= 0xff00; \
130  d = (d + ((s - d) * alpha >> 8)) & 0xff00; \
131  *dst++ = d1 | d; \
132  } \
133  } while (0)
134 
135 /*
136  * For 16bpp pixels we can go a step further: put the middle component
137  * in the high 16 bits of a 32 bit word, and process all three RGB
138  * components at the same time. Since the smallest gap is here just
139  * 5 bits, we have to scale alpha down to 5 bits as well.
140  */
141 #define ALPHA_BLIT16_565(to, from, length, bpp, alpha) \
142  do { \
143  int i; \
144  Uint16 *src = (Uint16 *)(from); \
145  Uint16 *dst = (Uint16 *)(to); \
146  Uint32 ALPHA = alpha >> 3; \
147  for(i = 0; i < (int)(length); i++) { \
148  Uint32 s = *src++; \
149  Uint32 d = *dst; \
150  s = (s | s << 16) & 0x07e0f81f; \
151  d = (d | d << 16) & 0x07e0f81f; \
152  d += (s - d) * ALPHA >> 5; \
153  d &= 0x07e0f81f; \
154  *dst++ = (Uint16)(d | d >> 16); \
155  } \
156  } while(0)
157 
158 #define ALPHA_BLIT16_555(to, from, length, bpp, alpha) \
159  do { \
160  int i; \
161  Uint16 *src = (Uint16 *)(from); \
162  Uint16 *dst = (Uint16 *)(to); \
163  Uint32 ALPHA = alpha >> 3; \
164  for(i = 0; i < (int)(length); i++) { \
165  Uint32 s = *src++; \
166  Uint32 d = *dst; \
167  s = (s | s << 16) & 0x03e07c1f; \
168  d = (d | d << 16) & 0x03e07c1f; \
169  d += (s - d) * ALPHA >> 5; \
170  d &= 0x03e07c1f; \
171  *dst++ = (Uint16)(d | d >> 16); \
172  } \
173  } while(0)
174 
175 /*
176  * The general slow catch-all function, for remaining depths and formats
177  */
178 #define ALPHA_BLIT_ANY(to, from, length, bpp, alpha) \
179  do { \
180  int i; \
181  Uint8 *src = from; \
182  Uint8 *dst = to; \
183  for (i = 0; i < (int)(length); i++) { \
184  Uint32 s, d; \
185  unsigned rs, gs, bs, rd, gd, bd; \
186  switch (bpp) { \
187  case 2: \
188  s = *(Uint16 *)src; \
189  d = *(Uint16 *)dst; \
190  break; \
191  case 3: \
192  if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { \
193  s = (src[0] << 16) | (src[1] << 8) | src[2]; \
194  d = (dst[0] << 16) | (dst[1] << 8) | dst[2]; \
195  } else { \
196  s = (src[2] << 16) | (src[1] << 8) | src[0]; \
197  d = (dst[2] << 16) | (dst[1] << 8) | dst[0]; \
198  } \
199  break; \
200  case 4: \
201  s = *(Uint32 *)src; \
202  d = *(Uint32 *)dst; \
203  break; \
204  } \
205  RGB_FROM_PIXEL(s, fmt, rs, gs, bs); \
206  RGB_FROM_PIXEL(d, fmt, rd, gd, bd); \
207  rd += (rs - rd) * alpha >> 8; \
208  gd += (gs - gd) * alpha >> 8; \
209  bd += (bs - bd) * alpha >> 8; \
210  PIXEL_FROM_RGB(d, fmt, rd, gd, bd); \
211  switch (bpp) { \
212  case 2: \
213  *(Uint16 *)dst = (Uint16)d; \
214  break; \
215  case 3: \
216  if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { \
217  dst[0] = (Uint8)(d >> 16); \
218  dst[1] = (Uint8)(d >> 8); \
219  dst[2] = (Uint8)(d); \
220  } else { \
221  dst[0] = (Uint8)d; \
222  dst[1] = (Uint8)(d >> 8); \
223  dst[2] = (Uint8)(d >> 16); \
224  } \
225  break; \
226  case 4: \
227  *(Uint32 *)dst = d; \
228  break; \
229  } \
230  src += bpp; \
231  dst += bpp; \
232  } \
233  } while(0)
234 
235 /*
236  * Special case: 50% alpha (alpha=128)
237  * This is treated specially because it can be optimized very well, and
238  * since it is good for many cases of semi-translucency.
239  * The theory is to do all three components at the same time:
240  * First zero the lowest bit of each component, which gives us room to
241  * add them. Then shift right and add the sum of the lowest bits.
242  */
243 #define ALPHA_BLIT32_888_50(to, from, length, bpp, alpha) \
244  do { \
245  int i; \
246  Uint32 *src = (Uint32 *)(from); \
247  Uint32 *dst = (Uint32 *)(to); \
248  for(i = 0; i < (int)(length); i++) { \
249  Uint32 s = *src++; \
250  Uint32 d = *dst; \
251  *dst++ = (((s & 0x00fefefe) + (d & 0x00fefefe)) >> 1) \
252  + (s & d & 0x00010101); \
253  } \
254  } while(0)
255 
256 /*
257  * For 16bpp, we can actually blend two pixels in parallel, if we take
258  * care to shift before we add, not after.
259  */
260 
261 /* helper: blend a single 16 bit pixel at 50% */
262 #define BLEND16_50(dst, src, mask) \
263  do { \
264  Uint32 s = *src++; \
265  Uint32 d = *dst; \
266  *dst++ = (Uint16)((((s & mask) + (d & mask)) >> 1) + \
267  (s & d & (~mask & 0xffff))); \
268  } while(0)
269 
270 /* basic 16bpp blender. mask is the pixels to keep when adding. */
271 #define ALPHA_BLIT16_50(to, from, length, bpp, alpha, mask) \
272  do { \
273  unsigned n = (length); \
274  Uint16 *src = (Uint16 *)(from); \
275  Uint16 *dst = (Uint16 *)(to); \
276  if (((uintptr_t)src ^ (uintptr_t)dst) & 3) { \
277  /* source and destination not in phase, blit one by one */ \
278  while (n--) \
279  BLEND16_50(dst, src, mask); \
280  } else { \
281  if ((uintptr_t)src & 3) { \
282  /* first odd pixel */ \
283  BLEND16_50(dst, src, mask); \
284  n--; \
285  } \
286  for (; n > 1; n -= 2) { \
287  Uint32 s = *(Uint32 *)src; \
288  Uint32 d = *(Uint32 *)dst; \
289  *(Uint32 *)dst = ((s & (mask | mask << 16)) >> 1) \
290  + ((d & (mask | mask << 16)) >> 1) \
291  + (s & d & (~(mask | mask << 16))); \
292  src += 2; \
293  dst += 2; \
294  } \
295  if (n) \
296  BLEND16_50(dst, src, mask); /* last odd pixel */ \
297  } \
298  } while(0)
299 
300 #define ALPHA_BLIT16_565_50(to, from, length, bpp, alpha) \
301  ALPHA_BLIT16_50(to, from, length, bpp, alpha, 0xf7de)
302 
303 #define ALPHA_BLIT16_555_50(to, from, length, bpp, alpha) \
304  ALPHA_BLIT16_50(to, from, length, bpp, alpha, 0xfbde)
305 
306 #define CHOOSE_BLIT(blitter, alpha, fmt) \
307  do { \
308  if (alpha == 255) { \
309  switch (fmt->BytesPerPixel) { \
310  case 1: blitter(1, Uint8, OPAQUE_BLIT); break; \
311  case 2: blitter(2, Uint8, OPAQUE_BLIT); break; \
312  case 3: blitter(3, Uint8, OPAQUE_BLIT); break; \
313  case 4: blitter(4, Uint16, OPAQUE_BLIT); break; \
314  } \
315  } else { \
316  switch (fmt->BytesPerPixel) { \
317  case 1: \
318  /* No 8bpp alpha blitting */ \
319  break; \
320  \
321  case 2: \
322  switch (fmt->Rmask | fmt->Gmask | fmt->Bmask) { \
323  case 0xffff: \
324  if (fmt->Gmask == 0x07e0 \
325  || fmt->Rmask == 0x07e0 \
326  || fmt->Bmask == 0x07e0) { \
327  if (alpha == 128) { \
328  blitter(2, Uint8, ALPHA_BLIT16_565_50); \
329  } else { \
330  blitter(2, Uint8, ALPHA_BLIT16_565); \
331  } \
332  } else \
333  goto general16; \
334  break; \
335  \
336  case 0x7fff: \
337  if (fmt->Gmask == 0x03e0 \
338  || fmt->Rmask == 0x03e0 \
339  || fmt->Bmask == 0x03e0) { \
340  if (alpha == 128) { \
341  blitter(2, Uint8, ALPHA_BLIT16_555_50); \
342  } else { \
343  blitter(2, Uint8, ALPHA_BLIT16_555); \
344  } \
345  break; \
346  } else \
347  goto general16; \
348  break; \
349  \
350  default: \
351  general16: \
352  blitter(2, Uint8, ALPHA_BLIT_ANY); \
353  } \
354  break; \
355  \
356  case 3: \
357  blitter(3, Uint8, ALPHA_BLIT_ANY); \
358  break; \
359  \
360  case 4: \
361  if ((fmt->Rmask | fmt->Gmask | fmt->Bmask) == 0x00ffffff \
362  && (fmt->Gmask == 0xff00 || fmt->Rmask == 0xff00 \
363  || fmt->Bmask == 0xff00)) { \
364  if (alpha == 128) { \
365  blitter(4, Uint16, ALPHA_BLIT32_888_50); \
366  } else { \
367  blitter(4, Uint16, ALPHA_BLIT32_888); \
368  } \
369  } else \
370  blitter(4, Uint16, ALPHA_BLIT_ANY); \
371  break; \
372  } \
373  } \
374  } while(0)
375 
376 /*
377  * Set a pixel value using the given format, except that the alpha value is
378  * placed in the top byte. This is the format used for RLE with alpha.
379  */
380 #define RLEPIXEL_FROM_RGBA(Pixel, fmt, r, g, b, a) \
381 { \
382  Pixel = ((r>>fmt->Rloss)<<fmt->Rshift)| \
383  ((g>>fmt->Gloss)<<fmt->Gshift)| \
384  ((b>>fmt->Bloss)<<fmt->Bshift)| \
385  (a<<24); \
386 }
387 
388 /*
389  * This takes care of the case when the surface is clipped on the left and/or
390  * right. Top clipping has already been taken care of.
391  */
392 static void
393 RLEClipBlit(int w, Uint8 * srcbuf, SDL_Surface * surf_dst,
394  Uint8 * dstbuf, SDL_Rect * srcrect, unsigned alpha)
395 {
396  SDL_PixelFormat *fmt = surf_dst->format;
397 
398 #define RLECLIPBLIT(bpp, Type, do_blit) \
399  do { \
400  int linecount = srcrect->h; \
401  int ofs = 0; \
402  int left = srcrect->x; \
403  int right = left + srcrect->w; \
404  dstbuf -= left * bpp; \
405  for (;;) { \
406  int run; \
407  ofs += *(Type *)srcbuf; \
408  run = ((Type *)srcbuf)[1]; \
409  srcbuf += 2 * sizeof(Type); \
410  if (run) { \
411  /* clip to left and right borders */ \
412  if (ofs < right) { \
413  int start = 0; \
414  int len = run; \
415  int startcol; \
416  if (left - ofs > 0) { \
417  start = left - ofs; \
418  len -= start; \
419  if (len <= 0) \
420  goto nocopy ## bpp ## do_blit; \
421  } \
422  startcol = ofs + start; \
423  if (len > right - startcol) \
424  len = right - startcol; \
425  do_blit(dstbuf + startcol * bpp, srcbuf + start * bpp, \
426  len, bpp, alpha); \
427  } \
428  nocopy ## bpp ## do_blit: \
429  srcbuf += run * bpp; \
430  ofs += run; \
431  } else if (!ofs) \
432  break; \
433  \
434  if (ofs == w) { \
435  ofs = 0; \
436  dstbuf += surf_dst->pitch; \
437  if (!--linecount) \
438  break; \
439  } \
440  } \
441  } while(0)
442 
443  CHOOSE_BLIT(RLECLIPBLIT, alpha, fmt);
444 
445 #undef RLECLIPBLIT
446 
447 }
448 
449 
450 /* blit a colorkeyed RLE surface */
451 int
452 SDL_RLEBlit(SDL_Surface * surf_src, SDL_Rect * srcrect,
453  SDL_Surface * surf_dst, SDL_Rect * dstrect)
454 {
455  Uint8 *dstbuf;
456  Uint8 *srcbuf;
457  int x, y;
458  int w = surf_src->w;
459  unsigned alpha;
460 
461  /* Lock the destination if necessary */
462  if (SDL_MUSTLOCK(surf_dst)) {
463  if (SDL_LockSurface(surf_dst) < 0) {
464  return (-1);
465  }
466  }
467 
468  /* Set up the source and destination pointers */
469  x = dstrect->x;
470  y = dstrect->y;
471  dstbuf = (Uint8 *) surf_dst->pixels
472  + y * surf_dst->pitch + x * surf_src->format->BytesPerPixel;
473  srcbuf = (Uint8 *) surf_src->map->data;
474 
475  {
476  /* skip lines at the top if necessary */
477  int vskip = srcrect->y;
478  int ofs = 0;
479  if (vskip) {
480 
481 #define RLESKIP(bpp, Type) \
482  for(;;) { \
483  int run; \
484  ofs += *(Type *)srcbuf; \
485  run = ((Type *)srcbuf)[1]; \
486  srcbuf += sizeof(Type) * 2; \
487  if(run) { \
488  srcbuf += run * bpp; \
489  ofs += run; \
490  } else if(!ofs) \
491  goto done; \
492  if(ofs == w) { \
493  ofs = 0; \
494  if(!--vskip) \
495  break; \
496  } \
497  }
498 
499  switch (surf_src->format->BytesPerPixel) {
500  case 1:
501  RLESKIP(1, Uint8);
502  break;
503  case 2:
504  RLESKIP(2, Uint8);
505  break;
506  case 3:
507  RLESKIP(3, Uint8);
508  break;
509  case 4:
510  RLESKIP(4, Uint16);
511  break;
512  }
513 
514 #undef RLESKIP
515 
516  }
517  }
518 
519  alpha = surf_src->map->info.a;
520  /* if left or right edge clipping needed, call clip blit */
521  if (srcrect->x || srcrect->w != surf_src->w) {
522  RLEClipBlit(w, srcbuf, surf_dst, dstbuf, srcrect, alpha);
523  } else {
524  SDL_PixelFormat *fmt = surf_src->format;
525 
526 #define RLEBLIT(bpp, Type, do_blit) \
527  do { \
528  int linecount = srcrect->h; \
529  int ofs = 0; \
530  for(;;) { \
531  unsigned run; \
532  ofs += *(Type *)srcbuf; \
533  run = ((Type *)srcbuf)[1]; \
534  srcbuf += 2 * sizeof(Type); \
535  if(run) { \
536  do_blit(dstbuf + ofs * bpp, srcbuf, run, bpp, alpha); \
537  srcbuf += run * bpp; \
538  ofs += run; \
539  } else if(!ofs) \
540  break; \
541  if(ofs == w) { \
542  ofs = 0; \
543  dstbuf += surf_dst->pitch; \
544  if(!--linecount) \
545  break; \
546  } \
547  } \
548  } while(0)
549 
550  CHOOSE_BLIT(RLEBLIT, alpha, fmt);
551 
552 #undef RLEBLIT
553  }
554 
555  done:
556  /* Unlock the destination if necessary */
557  if (SDL_MUSTLOCK(surf_dst)) {
558  SDL_UnlockSurface(surf_dst);
559  }
560  return (0);
561 }
562 
563 #undef OPAQUE_BLIT
564 
565 /*
566  * Per-pixel blitting macros for translucent pixels:
567  * These use the same techniques as the per-surface blitting macros
568  */
569 
570 /*
571  * For 32bpp pixels, we have made sure the alpha is stored in the top
572  * 8 bits, so proceed as usual
573  */
574 #define BLIT_TRANSL_888(src, dst) \
575  do { \
576  Uint32 s = src; \
577  Uint32 d = dst; \
578  unsigned alpha = s >> 24; \
579  Uint32 s1 = s & 0xff00ff; \
580  Uint32 d1 = d & 0xff00ff; \
581  d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff; \
582  s &= 0xff00; \
583  d &= 0xff00; \
584  d = (d + ((s - d) * alpha >> 8)) & 0xff00; \
585  dst = d1 | d | 0xff000000; \
586  } while(0)
587 
588 /*
589  * For 16bpp pixels, we have stored the 5 most significant alpha bits in
590  * bits 5-10. As before, we can process all 3 RGB components at the same time.
591  */
592 #define BLIT_TRANSL_565(src, dst) \
593  do { \
594  Uint32 s = src; \
595  Uint32 d = dst; \
596  unsigned alpha = (s & 0x3e0) >> 5; \
597  s &= 0x07e0f81f; \
598  d = (d | d << 16) & 0x07e0f81f; \
599  d += (s - d) * alpha >> 5; \
600  d &= 0x07e0f81f; \
601  dst = (Uint16)(d | d >> 16); \
602  } while(0)
603 
604 #define BLIT_TRANSL_555(src, dst) \
605  do { \
606  Uint32 s = src; \
607  Uint32 d = dst; \
608  unsigned alpha = (s & 0x3e0) >> 5; \
609  s &= 0x03e07c1f; \
610  d = (d | d << 16) & 0x03e07c1f; \
611  d += (s - d) * alpha >> 5; \
612  d &= 0x03e07c1f; \
613  dst = (Uint16)(d | d >> 16); \
614  } while(0)
615 
616 /* used to save the destination format in the encoding. Designed to be
617  macro-compatible with SDL_PixelFormat but without the unneeded fields */
618 typedef struct
619 {
621  Uint8 padding[3];
634 } RLEDestFormat;
635 
636 /* blit a pixel-alpha RLE surface clipped at the right and/or left edges */
637 static void
638 RLEAlphaClipBlit(int w, Uint8 * srcbuf, SDL_Surface * surf_dst,
639  Uint8 * dstbuf, SDL_Rect * srcrect)
640 {
641  SDL_PixelFormat *df = surf_dst->format;
642  /*
643  * clipped blitter: Ptype is the destination pixel type,
644  * Ctype the translucent count type, and do_blend the macro
645  * to blend one pixel.
646  */
647 #define RLEALPHACLIPBLIT(Ptype, Ctype, do_blend) \
648  do { \
649  int linecount = srcrect->h; \
650  int left = srcrect->x; \
651  int right = left + srcrect->w; \
652  dstbuf -= left * sizeof(Ptype); \
653  do { \
654  int ofs = 0; \
655  /* blit opaque pixels on one line */ \
656  do { \
657  unsigned run; \
658  ofs += ((Ctype *)srcbuf)[0]; \
659  run = ((Ctype *)srcbuf)[1]; \
660  srcbuf += 2 * sizeof(Ctype); \
661  if(run) { \
662  /* clip to left and right borders */ \
663  int cofs = ofs; \
664  int crun = run; \
665  if(left - cofs > 0) { \
666  crun -= left - cofs; \
667  cofs = left; \
668  } \
669  if(crun > right - cofs) \
670  crun = right - cofs; \
671  if(crun > 0) \
672  PIXEL_COPY(dstbuf + cofs * sizeof(Ptype), \
673  srcbuf + (cofs - ofs) * sizeof(Ptype), \
674  (unsigned)crun, sizeof(Ptype)); \
675  srcbuf += run * sizeof(Ptype); \
676  ofs += run; \
677  } else if(!ofs) \
678  return; \
679  } while(ofs < w); \
680  /* skip padding if necessary */ \
681  if(sizeof(Ptype) == 2) \
682  srcbuf += (uintptr_t)srcbuf & 2; \
683  /* blit translucent pixels on the same line */ \
684  ofs = 0; \
685  do { \
686  unsigned run; \
687  ofs += ((Uint16 *)srcbuf)[0]; \
688  run = ((Uint16 *)srcbuf)[1]; \
689  srcbuf += 4; \
690  if(run) { \
691  /* clip to left and right borders */ \
692  int cofs = ofs; \
693  int crun = run; \
694  if(left - cofs > 0) { \
695  crun -= left - cofs; \
696  cofs = left; \
697  } \
698  if(crun > right - cofs) \
699  crun = right - cofs; \
700  if(crun > 0) { \
701  Ptype *dst = (Ptype *)dstbuf + cofs; \
702  Uint32 *src = (Uint32 *)srcbuf + (cofs - ofs); \
703  int i; \
704  for(i = 0; i < crun; i++) \
705  do_blend(src[i], dst[i]); \
706  } \
707  srcbuf += run * 4; \
708  ofs += run; \
709  } \
710  } while(ofs < w); \
711  dstbuf += surf_dst->pitch; \
712  } while(--linecount); \
713  } while(0)
714 
715  switch (df->BytesPerPixel) {
716  case 2:
717  if (df->Gmask == 0x07e0 || df->Rmask == 0x07e0 || df->Bmask == 0x07e0)
719  else
721  break;
722  case 4:
724  break;
725  }
726 }
727 
728 /* blit a pixel-alpha RLE surface */
729 int
730 SDL_RLEAlphaBlit(SDL_Surface * surf_src, SDL_Rect * srcrect,
731  SDL_Surface * surf_dst, SDL_Rect * dstrect)
732 {
733  int x, y;
734  int w = surf_src->w;
735  Uint8 *srcbuf, *dstbuf;
736  SDL_PixelFormat *df = surf_dst->format;
737 
738  /* Lock the destination if necessary */
739  if (SDL_MUSTLOCK(surf_dst)) {
740  if (SDL_LockSurface(surf_dst) < 0) {
741  return -1;
742  }
743  }
744 
745  x = dstrect->x;
746  y = dstrect->y;
747  dstbuf = (Uint8 *) surf_dst->pixels + y * surf_dst->pitch + x * df->BytesPerPixel;
748  srcbuf = (Uint8 *) surf_src->map->data + sizeof(RLEDestFormat);
749 
750  {
751  /* skip lines at the top if necessary */
752  int vskip = srcrect->y;
753  if (vskip) {
754  int ofs;
755  if (df->BytesPerPixel == 2) {
756  /* the 16/32 interleaved format */
757  do {
758  /* skip opaque line */
759  ofs = 0;
760  do {
761  int run;
762  ofs += srcbuf[0];
763  run = srcbuf[1];
764  srcbuf += 2;
765  if (run) {
766  srcbuf += 2 * run;
767  ofs += run;
768  } else if (!ofs)
769  goto done;
770  } while (ofs < w);
771 
772  /* skip padding */
773  srcbuf += (uintptr_t) srcbuf & 2;
774 
775  /* skip translucent line */
776  ofs = 0;
777  do {
778  int run;
779  ofs += ((Uint16 *) srcbuf)[0];
780  run = ((Uint16 *) srcbuf)[1];
781  srcbuf += 4 * (run + 1);
782  ofs += run;
783  } while (ofs < w);
784  } while (--vskip);
785  } else {
786  /* the 32/32 interleaved format */
787  vskip <<= 1; /* opaque and translucent have same format */
788  do {
789  ofs = 0;
790  do {
791  int run;
792  ofs += ((Uint16 *) srcbuf)[0];
793  run = ((Uint16 *) srcbuf)[1];
794  srcbuf += 4;
795  if (run) {
796  srcbuf += 4 * run;
797  ofs += run;
798  } else if (!ofs)
799  goto done;
800  } while (ofs < w);
801  } while (--vskip);
802  }
803  }
804  }
805 
806  /* if left or right edge clipping needed, call clip blit */
807  if (srcrect->x || srcrect->w != surf_src->w) {
808  RLEAlphaClipBlit(w, srcbuf, surf_dst, dstbuf, srcrect);
809  } else {
810 
811  /*
812  * non-clipped blitter. Ptype is the destination pixel type,
813  * Ctype the translucent count type, and do_blend the
814  * macro to blend one pixel.
815  */
816 #define RLEALPHABLIT(Ptype, Ctype, do_blend) \
817  do { \
818  int linecount = srcrect->h; \
819  do { \
820  int ofs = 0; \
821  /* blit opaque pixels on one line */ \
822  do { \
823  unsigned run; \
824  ofs += ((Ctype *)srcbuf)[0]; \
825  run = ((Ctype *)srcbuf)[1]; \
826  srcbuf += 2 * sizeof(Ctype); \
827  if(run) { \
828  PIXEL_COPY(dstbuf + ofs * sizeof(Ptype), srcbuf, \
829  run, sizeof(Ptype)); \
830  srcbuf += run * sizeof(Ptype); \
831  ofs += run; \
832  } else if(!ofs) \
833  goto done; \
834  } while(ofs < w); \
835  /* skip padding if necessary */ \
836  if(sizeof(Ptype) == 2) \
837  srcbuf += (uintptr_t)srcbuf & 2; \
838  /* blit translucent pixels on the same line */ \
839  ofs = 0; \
840  do { \
841  unsigned run; \
842  ofs += ((Uint16 *)srcbuf)[0]; \
843  run = ((Uint16 *)srcbuf)[1]; \
844  srcbuf += 4; \
845  if(run) { \
846  Ptype *dst = (Ptype *)dstbuf + ofs; \
847  unsigned i; \
848  for(i = 0; i < run; i++) { \
849  Uint32 src = *(Uint32 *)srcbuf; \
850  do_blend(src, *dst); \
851  srcbuf += 4; \
852  dst++; \
853  } \
854  ofs += run; \
855  } \
856  } while(ofs < w); \
857  dstbuf += surf_dst->pitch; \
858  } while(--linecount); \
859  } while(0)
860 
861  switch (df->BytesPerPixel) {
862  case 2:
863  if (df->Gmask == 0x07e0 || df->Rmask == 0x07e0
864  || df->Bmask == 0x07e0)
866  else
868  break;
869  case 4:
871  break;
872  }
873  }
874 
875  done:
876  /* Unlock the destination if necessary */
877  if (SDL_MUSTLOCK(surf_dst)) {
878  SDL_UnlockSurface(surf_dst);
879  }
880  return 0;
881 }
882 
883 /*
884  * Auxiliary functions:
885  * The encoding functions take 32bpp rgb + a, and
886  * return the number of bytes copied to the destination.
887  * The decoding functions copy to 32bpp rgb + a, and
888  * return the number of bytes copied from the source.
889  * These are only used in the encoder and un-RLE code and are therefore not
890  * highly optimised.
891  */
892 
893 /* encode 32bpp rgb + a into 16bpp rgb, losing alpha */
894 static int
895 copy_opaque_16(void *dst, Uint32 * src, int n,
896  SDL_PixelFormat * sfmt, SDL_PixelFormat * dfmt)
897 {
898  int i;
899  Uint16 *d = dst;
900  for (i = 0; i < n; i++) {
901  unsigned r, g, b;
902  RGB_FROM_PIXEL(*src, sfmt, r, g, b);
903  PIXEL_FROM_RGB(*d, dfmt, r, g, b);
904  src++;
905  d++;
906  }
907  return n * 2;
908 }
909 
910 /* decode opaque pixels from 16bpp to 32bpp rgb + a */
911 static int
913  RLEDestFormat * sfmt, SDL_PixelFormat * dfmt)
914 {
915  int i;
916  Uint16 *s = src;
917  unsigned alpha = dfmt->Amask ? 255 : 0;
918  for (i = 0; i < n; i++) {
919  unsigned r, g, b;
920  RGB_FROM_PIXEL(*s, sfmt, r, g, b);
921  PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, alpha);
922  s++;
923  dst++;
924  }
925  return n * 2;
926 }
927 
928 
929 
930 /* encode 32bpp rgb + a into 32bpp G0RAB format for blitting into 565 */
931 static int
933  SDL_PixelFormat * sfmt, SDL_PixelFormat * dfmt)
934 {
935  int i;
936  Uint32 *d = dst;
937  for (i = 0; i < n; i++) {
938  unsigned r, g, b, a;
939  Uint16 pix;
940  RGBA_FROM_8888(*src, sfmt, r, g, b, a);
941  PIXEL_FROM_RGB(pix, dfmt, r, g, b);
942  *d = ((pix & 0x7e0) << 16) | (pix & 0xf81f) | ((a << 2) & 0x7e0);
943  src++;
944  d++;
945  }
946  return n * 4;
947 }
948 
949 /* encode 32bpp rgb + a into 32bpp G0RAB format for blitting into 555 */
950 static int
952  SDL_PixelFormat * sfmt, SDL_PixelFormat * dfmt)
953 {
954  int i;
955  Uint32 *d = dst;
956  for (i = 0; i < n; i++) {
957  unsigned r, g, b, a;
958  Uint16 pix;
959  RGBA_FROM_8888(*src, sfmt, r, g, b, a);
960  PIXEL_FROM_RGB(pix, dfmt, r, g, b);
961  *d = ((pix & 0x3e0) << 16) | (pix & 0xfc1f) | ((a << 2) & 0x3e0);
962  src++;
963  d++;
964  }
965  return n * 4;
966 }
967 
968 /* decode translucent pixels from 32bpp GORAB to 32bpp rgb + a */
969 static int
971  RLEDestFormat * sfmt, SDL_PixelFormat * dfmt)
972 {
973  int i;
974  Uint32 *s = src;
975  for (i = 0; i < n; i++) {
976  unsigned r, g, b, a;
977  Uint32 pix = *s++;
978  a = (pix & 0x3e0) >> 2;
979  pix = (pix & ~0x3e0) | pix >> 16;
980  RGB_FROM_PIXEL(pix, sfmt, r, g, b);
981  PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, a);
982  dst++;
983  }
984  return n * 4;
985 }
986 
987 /* encode 32bpp rgba into 32bpp rgba, keeping alpha (dual purpose) */
988 static int
989 copy_32(void *dst, Uint32 * src, int n,
990  SDL_PixelFormat * sfmt, SDL_PixelFormat * dfmt)
991 {
992  int i;
993  Uint32 *d = dst;
994  for (i = 0; i < n; i++) {
995  unsigned r, g, b, a;
996  RGBA_FROM_8888(*src, sfmt, r, g, b, a);
997  RLEPIXEL_FROM_RGBA(*d, dfmt, r, g, b, a);
998  d++;
999  src++;
1000  }
1001  return n * 4;
1002 }
1003 
1004 /* decode 32bpp rgba into 32bpp rgba, keeping alpha (dual purpose) */
1005 static int
1006 uncopy_32(Uint32 * dst, void *src, int n,
1007  RLEDestFormat * sfmt, SDL_PixelFormat * dfmt)
1008 {
1009  int i;
1010  Uint32 *s = src;
1011  for (i = 0; i < n; i++) {
1012  unsigned r, g, b, a;
1013  Uint32 pixel = *s++;
1014  RGB_FROM_PIXEL(pixel, sfmt, r, g, b);
1015  a = pixel >> 24;
1016  PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, a);
1017  dst++;
1018  }
1019  return n * 4;
1020 }
1021 
1022 #define ISOPAQUE(pixel, fmt) ((((pixel) & fmt->Amask) >> fmt->Ashift) == 255)
1023 
1024 #define ISTRANSL(pixel, fmt) \
1025  ((unsigned)((((pixel) & fmt->Amask) >> fmt->Ashift) - 1U) < 254U)
1026 
1027 /* convert surface to be quickly alpha-blittable onto dest, if possible */
1028 static int
1030 {
1031  SDL_Surface *dest;
1032  SDL_PixelFormat *df;
1033  int maxsize = 0;
1034  int max_opaque_run;
1035  int max_transl_run = 65535;
1036  unsigned masksum;
1037  Uint8 *rlebuf, *dst;
1038  int (*copy_opaque) (void *, Uint32 *, int,
1039  SDL_PixelFormat *, SDL_PixelFormat *);
1040  int (*copy_transl) (void *, Uint32 *, int,
1041  SDL_PixelFormat *, SDL_PixelFormat *);
1042 
1043  dest = surface->map->dst;
1044  if (!dest)
1045  return -1;
1046  df = dest->format;
1047  if (surface->format->BitsPerPixel != 32)
1048  return -1; /* only 32bpp source supported */
1049 
1050  /* find out whether the destination is one we support,
1051  and determine the max size of the encoded result */
1052  masksum = df->Rmask | df->Gmask | df->Bmask;
1053  switch (df->BytesPerPixel) {
1054  case 2:
1055  /* 16bpp: only support 565 and 555 formats */
1056  switch (masksum) {
1057  case 0xffff:
1058  if (df->Gmask == 0x07e0
1059  || df->Rmask == 0x07e0 || df->Bmask == 0x07e0) {
1060  copy_opaque = copy_opaque_16;
1061  copy_transl = copy_transl_565;
1062  } else
1063  return -1;
1064  break;
1065  case 0x7fff:
1066  if (df->Gmask == 0x03e0
1067  || df->Rmask == 0x03e0 || df->Bmask == 0x03e0) {
1068  copy_opaque = copy_opaque_16;
1069  copy_transl = copy_transl_555;
1070  } else
1071  return -1;
1072  break;
1073  default:
1074  return -1;
1075  }
1076  max_opaque_run = 255; /* runs stored as bytes */
1077 
1078  /* worst case is alternating opaque and translucent pixels,
1079  with room for alignment padding between lines */
1080  maxsize = surface->h * (2 + (4 + 2) * (surface->w + 1)) + 2;
1081  break;
1082  case 4:
1083  if (masksum != 0x00ffffff)
1084  return -1; /* requires unused high byte */
1085  copy_opaque = copy_32;
1086  copy_transl = copy_32;
1087  max_opaque_run = 255; /* runs stored as short ints */
1088 
1089  /* worst case is alternating opaque and translucent pixels */
1090  maxsize = surface->h * 2 * 4 * (surface->w + 1) + 4;
1091  break;
1092  default:
1093  return -1; /* anything else unsupported right now */
1094  }
1095 
1096  maxsize += sizeof(RLEDestFormat);
1097  rlebuf = (Uint8 *) SDL_malloc(maxsize);
1098  if (!rlebuf) {
1099  return SDL_OutOfMemory();
1100  }
1101  {
1102  /* save the destination format so we can undo the encoding later */
1103  RLEDestFormat *r = (RLEDestFormat *) rlebuf;
1104  r->BytesPerPixel = df->BytesPerPixel;
1105  r->Rmask = df->Rmask;
1106  r->Gmask = df->Gmask;
1107  r->Bmask = df->Bmask;
1108  r->Amask = df->Amask;
1109  r->Rloss = df->Rloss;
1110  r->Gloss = df->Gloss;
1111  r->Bloss = df->Bloss;
1112  r->Aloss = df->Aloss;
1113  r->Rshift = df->Rshift;
1114  r->Gshift = df->Gshift;
1115  r->Bshift = df->Bshift;
1116  r->Ashift = df->Ashift;
1117  }
1118  dst = rlebuf + sizeof(RLEDestFormat);
1119 
1120  /* Do the actual encoding */
1121  {
1122  int x, y;
1123  int h = surface->h, w = surface->w;
1124  SDL_PixelFormat *sf = surface->format;
1125  Uint32 *src = (Uint32 *) surface->pixels;
1126  Uint8 *lastline = dst; /* end of last non-blank line */
1127 
1128  /* opaque counts are 8 or 16 bits, depending on target depth */
1129 #define ADD_OPAQUE_COUNTS(n, m) \
1130  if(df->BytesPerPixel == 4) { \
1131  ((Uint16 *)dst)[0] = n; \
1132  ((Uint16 *)dst)[1] = m; \
1133  dst += 4; \
1134  } else { \
1135  dst[0] = n; \
1136  dst[1] = m; \
1137  dst += 2; \
1138  }
1139 
1140  /* translucent counts are always 16 bit */
1141 #define ADD_TRANSL_COUNTS(n, m) \
1142  (((Uint16 *)dst)[0] = n, ((Uint16 *)dst)[1] = m, dst += 4)
1143 
1144  for (y = 0; y < h; y++) {
1145  int runstart, skipstart;
1146  int blankline = 0;
1147  /* First encode all opaque pixels of a scan line */
1148  x = 0;
1149  do {
1150  int run, skip, len;
1151  skipstart = x;
1152  while (x < w && !ISOPAQUE(src[x], sf))
1153  x++;
1154  runstart = x;
1155  while (x < w && ISOPAQUE(src[x], sf))
1156  x++;
1157  skip = runstart - skipstart;
1158  if (skip == w)
1159  blankline = 1;
1160  run = x - runstart;
1161  while (skip > max_opaque_run) {
1162  ADD_OPAQUE_COUNTS(max_opaque_run, 0);
1163  skip -= max_opaque_run;
1164  }
1165  len = MIN(run, max_opaque_run);
1166  ADD_OPAQUE_COUNTS(skip, len);
1167  dst += copy_opaque(dst, src + runstart, len, sf, df);
1168  runstart += len;
1169  run -= len;
1170  while (run) {
1171  len = MIN(run, max_opaque_run);
1172  ADD_OPAQUE_COUNTS(0, len);
1173  dst += copy_opaque(dst, src + runstart, len, sf, df);
1174  runstart += len;
1175  run -= len;
1176  }
1177  } while (x < w);
1178 
1179  /* Make sure the next output address is 32-bit aligned */
1180  dst += (uintptr_t) dst & 2;
1181 
1182  /* Next, encode all translucent pixels of the same scan line */
1183  x = 0;
1184  do {
1185  int run, skip, len;
1186  skipstart = x;
1187  while (x < w && !ISTRANSL(src[x], sf))
1188  x++;
1189  runstart = x;
1190  while (x < w && ISTRANSL(src[x], sf))
1191  x++;
1192  skip = runstart - skipstart;
1193  blankline &= (skip == w);
1194  run = x - runstart;
1195  while (skip > max_transl_run) {
1196  ADD_TRANSL_COUNTS(max_transl_run, 0);
1197  skip -= max_transl_run;
1198  }
1199  len = MIN(run, max_transl_run);
1200  ADD_TRANSL_COUNTS(skip, len);
1201  dst += copy_transl(dst, src + runstart, len, sf, df);
1202  runstart += len;
1203  run -= len;
1204  while (run) {
1205  len = MIN(run, max_transl_run);
1206  ADD_TRANSL_COUNTS(0, len);
1207  dst += copy_transl(dst, src + runstart, len, sf, df);
1208  runstart += len;
1209  run -= len;
1210  }
1211  if (!blankline)
1212  lastline = dst;
1213  } while (x < w);
1214 
1215  src += surface->pitch >> 2;
1216  }
1217  dst = lastline; /* back up past trailing blank lines */
1218  ADD_OPAQUE_COUNTS(0, 0);
1219  }
1220 
1221 #undef ADD_OPAQUE_COUNTS
1222 #undef ADD_TRANSL_COUNTS
1223 
1224  /* Now that we have it encoded, release the original pixels */
1225  if (!(surface->flags & SDL_PREALLOC)) {
1226  SDL_free(surface->pixels);
1227  surface->pixels = NULL;
1228  }
1229 
1230  /* realloc the buffer to release unused memory */
1231  {
1232  Uint8 *p = SDL_realloc(rlebuf, dst - rlebuf);
1233  if (!p)
1234  p = rlebuf;
1235  surface->map->data = p;
1236  }
1237 
1238  return 0;
1239 }
1240 
1241 static Uint32
1242 getpix_8(Uint8 * srcbuf)
1243 {
1244  return *srcbuf;
1245 }
1246 
1247 static Uint32
1248 getpix_16(Uint8 * srcbuf)
1249 {
1250  return *(Uint16 *) srcbuf;
1251 }
1252 
1253 static Uint32
1254 getpix_24(Uint8 * srcbuf)
1255 {
1256 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1257  return srcbuf[0] + (srcbuf[1] << 8) + (srcbuf[2] << 16);
1258 #else
1259  return (srcbuf[0] << 16) + (srcbuf[1] << 8) + srcbuf[2];
1260 #endif
1261 }
1262 
1263 static Uint32
1264 getpix_32(Uint8 * srcbuf)
1265 {
1266  return *(Uint32 *) srcbuf;
1267 }
1268 
1269 typedef Uint32(*getpix_func) (Uint8 *);
1270 
1271 static const getpix_func getpixes[4] = {
1273 };
1274 
1275 static int
1277 {
1278  Uint8 *rlebuf, *dst;
1279  int maxn;
1280  int y;
1281  Uint8 *srcbuf, *lastline;
1282  int maxsize = 0;
1283  int bpp = surface->format->BytesPerPixel;
1284  getpix_func getpix;
1285  Uint32 ckey, rgbmask;
1286  int w, h;
1287 
1288  /* calculate the worst case size for the compressed surface */
1289  switch (bpp) {
1290  case 1:
1291  /* worst case is alternating opaque and transparent pixels,
1292  starting with an opaque pixel */
1293  maxsize = surface->h * 3 * (surface->w / 2 + 1) + 2;
1294  break;
1295  case 2:
1296  case 3:
1297  /* worst case is solid runs, at most 255 pixels wide */
1298  maxsize = surface->h * (2 * (surface->w / 255 + 1)
1299  + surface->w * bpp) + 2;
1300  break;
1301  case 4:
1302  /* worst case is solid runs, at most 65535 pixels wide */
1303  maxsize = surface->h * (4 * (surface->w / 65535 + 1)
1304  + surface->w * 4) + 4;
1305  break;
1306  }
1307 
1308  rlebuf = (Uint8 *) SDL_malloc(maxsize);
1309  if (rlebuf == NULL) {
1310  return SDL_OutOfMemory();
1311  }
1312 
1313  /* Set up the conversion */
1314  srcbuf = (Uint8 *) surface->pixels;
1315  maxn = bpp == 4 ? 65535 : 255;
1316  dst = rlebuf;
1317  rgbmask = ~surface->format->Amask;
1318  ckey = surface->map->info.colorkey & rgbmask;
1319  lastline = dst;
1320  getpix = getpixes[bpp - 1];
1321  w = surface->w;
1322  h = surface->h;
1323 
1324 #define ADD_COUNTS(n, m) \
1325  if(bpp == 4) { \
1326  ((Uint16 *)dst)[0] = n; \
1327  ((Uint16 *)dst)[1] = m; \
1328  dst += 4; \
1329  } else { \
1330  dst[0] = n; \
1331  dst[1] = m; \
1332  dst += 2; \
1333  }
1334 
1335  for (y = 0; y < h; y++) {
1336  int x = 0;
1337  int blankline = 0;
1338  do {
1339  int run, skip, len;
1340  int runstart;
1341  int skipstart = x;
1342 
1343  /* find run of transparent, then opaque pixels */
1344  while (x < w && (getpix(srcbuf + x * bpp) & rgbmask) == ckey)
1345  x++;
1346  runstart = x;
1347  while (x < w && (getpix(srcbuf + x * bpp) & rgbmask) != ckey)
1348  x++;
1349  skip = runstart - skipstart;
1350  if (skip == w)
1351  blankline = 1;
1352  run = x - runstart;
1353 
1354  /* encode segment */
1355  while (skip > maxn) {
1356  ADD_COUNTS(maxn, 0);
1357  skip -= maxn;
1358  }
1359  len = MIN(run, maxn);
1360  ADD_COUNTS(skip, len);
1361  SDL_memcpy(dst, srcbuf + runstart * bpp, len * bpp);
1362  dst += len * bpp;
1363  run -= len;
1364  runstart += len;
1365  while (run) {
1366  len = MIN(run, maxn);
1367  ADD_COUNTS(0, len);
1368  SDL_memcpy(dst, srcbuf + runstart * bpp, len * bpp);
1369  dst += len * bpp;
1370  runstart += len;
1371  run -= len;
1372  }
1373  if (!blankline)
1374  lastline = dst;
1375  } while (x < w);
1376 
1377  srcbuf += surface->pitch;
1378  }
1379  dst = lastline; /* back up bast trailing blank lines */
1380  ADD_COUNTS(0, 0);
1381 
1382 #undef ADD_COUNTS
1383 
1384  /* Now that we have it encoded, release the original pixels */
1385  if (!(surface->flags & SDL_PREALLOC)) {
1386  SDL_free(surface->pixels);
1387  surface->pixels = NULL;
1388  }
1389 
1390  /* realloc the buffer to release unused memory */
1391  {
1392  /* If realloc returns NULL, the original block is left intact */
1393  Uint8 *p = SDL_realloc(rlebuf, dst - rlebuf);
1394  if (!p)
1395  p = rlebuf;
1396  surface->map->data = p;
1397  }
1398 
1399  return (0);
1400 }
1401 
1402 int
1404 {
1405  int flags;
1406 
1407  /* Clear any previous RLE conversion */
1408  if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
1409  SDL_UnRLESurface(surface, 1);
1410  }
1411 
1412  /* We don't support RLE encoding of bitmaps */
1413  if (surface->format->BitsPerPixel < 8) {
1414  return -1;
1415  }
1416 
1417  /* Make sure the pixels are available */
1418  if (!surface->pixels) {
1419  return -1;
1420  }
1421 
1422  /* If we don't have colorkey or blending, nothing to do... */
1423  flags = surface->map->info.flags;
1424  if (!(flags & (SDL_COPY_COLORKEY | SDL_COPY_BLEND))) {
1425  return -1;
1426  }
1427 
1428  /* Pass on combinations not supported */
1429  if ((flags & SDL_COPY_MODULATE_COLOR) ||
1430  ((flags & SDL_COPY_MODULATE_ALPHA) && surface->format->Amask) ||
1431  (flags & (SDL_COPY_ADD | SDL_COPY_MOD)) ||
1432  (flags & SDL_COPY_NEAREST)) {
1433  return -1;
1434  }
1435 
1436  /* Encode and set up the blit */
1437  if (!surface->format->Amask || !(flags & SDL_COPY_BLEND)) {
1438  if (!surface->map->identity) {
1439  return -1;
1440  }
1441  if (RLEColorkeySurface(surface) < 0) {
1442  return -1;
1443  }
1444  surface->map->blit = SDL_RLEBlit;
1445  surface->map->info.flags |= SDL_COPY_RLE_COLORKEY;
1446  } else {
1447  if (RLEAlphaSurface(surface) < 0) {
1448  return -1;
1449  }
1450  surface->map->blit = SDL_RLEAlphaBlit;
1451  surface->map->info.flags |= SDL_COPY_RLE_ALPHAKEY;
1452  }
1453 
1454  /* The surface is now accelerated */
1455  surface->flags |= SDL_RLEACCEL;
1456 
1457  return (0);
1458 }
1459 
1460 /*
1461  * Un-RLE a surface with pixel alpha
1462  * This may not give back exactly the image before RLE-encoding; all
1463  * completely transparent pixels will be lost, and color and alpha depth
1464  * may have been reduced (when encoding for 16bpp targets).
1465  */
1466 static SDL_bool
1468 {
1469  Uint8 *srcbuf;
1470  Uint32 *dst;
1471  SDL_PixelFormat *sf = surface->format;
1472  RLEDestFormat *df = surface->map->data;
1473  int (*uncopy_opaque) (Uint32 *, void *, int,
1475  int (*uncopy_transl) (Uint32 *, void *, int,
1476  RLEDestFormat *, SDL_PixelFormat *);
1477  int w = surface->w;
1478  int bpp = df->BytesPerPixel;
1479 
1480  if (bpp == 2) {
1481  uncopy_opaque = uncopy_opaque_16;
1482  uncopy_transl = uncopy_transl_16;
1483  } else {
1484  uncopy_opaque = uncopy_transl = uncopy_32;
1485  }
1486 
1487  surface->pixels = SDL_malloc(surface->h * surface->pitch);
1488  if (!surface->pixels) {
1489  return (SDL_FALSE);
1490  }
1491  /* fill background with transparent pixels */
1492  SDL_memset(surface->pixels, 0, surface->h * surface->pitch);
1493 
1494  dst = surface->pixels;
1495  srcbuf = (Uint8 *) (df + 1);
1496  for (;;) {
1497  /* copy opaque pixels */
1498  int ofs = 0;
1499  do {
1500  unsigned run;
1501  if (bpp == 2) {
1502  ofs += srcbuf[0];
1503  run = srcbuf[1];
1504  srcbuf += 2;
1505  } else {
1506  ofs += ((Uint16 *) srcbuf)[0];
1507  run = ((Uint16 *) srcbuf)[1];
1508  srcbuf += 4;
1509  }
1510  if (run) {
1511  srcbuf += uncopy_opaque(dst + ofs, srcbuf, run, df, sf);
1512  ofs += run;
1513  } else if (!ofs)
1514  return (SDL_TRUE);
1515  } while (ofs < w);
1516 
1517  /* skip padding if needed */
1518  if (bpp == 2)
1519  srcbuf += (uintptr_t) srcbuf & 2;
1520 
1521  /* copy translucent pixels */
1522  ofs = 0;
1523  do {
1524  unsigned run;
1525  ofs += ((Uint16 *) srcbuf)[0];
1526  run = ((Uint16 *) srcbuf)[1];
1527  srcbuf += 4;
1528  if (run) {
1529  srcbuf += uncopy_transl(dst + ofs, srcbuf, run, df, sf);
1530  ofs += run;
1531  }
1532  } while (ofs < w);
1533  dst += surface->pitch >> 2;
1534  }
1535  /* Make the compiler happy */
1536  return (SDL_TRUE);
1537 }
1538 
1539 void
1540 SDL_UnRLESurface(SDL_Surface * surface, int recode)
1541 {
1542  if (surface->flags & SDL_RLEACCEL) {
1543  surface->flags &= ~SDL_RLEACCEL;
1544 
1545  if (recode && !(surface->flags & SDL_PREALLOC)) {
1546  if (surface->map->info.flags & SDL_COPY_RLE_COLORKEY) {
1547  SDL_Rect full;
1548 
1549  /* re-create the original surface */
1550  surface->pixels = SDL_malloc(surface->h * surface->pitch);
1551  if (!surface->pixels) {
1552  /* Oh crap... */
1553  surface->flags |= SDL_RLEACCEL;
1554  return;
1555  }
1556 
1557  /* fill it with the background color */
1558  SDL_FillRect(surface, NULL, surface->map->info.colorkey);
1559 
1560  /* now render the encoded surface */
1561  full.x = full.y = 0;
1562  full.w = surface->w;
1563  full.h = surface->h;
1564  SDL_RLEBlit(surface, &full, surface, &full);
1565  } else {
1566  if (!UnRLEAlpha(surface)) {
1567  /* Oh crap... */
1568  surface->flags |= SDL_RLEACCEL;
1569  return;
1570  }
1571  }
1572  }
1573  surface->map->info.flags &=
1575 
1576  SDL_free(surface->map->data);
1577  surface->map->data = NULL;
1578  }
1579 }
1580 
1581 /* vi: set ts=4 sw=4 expandtab: */
static int copy_transl_555(void *dst, Uint32 *src, int n, SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt)
Definition: SDL_RLEaccel.c:951
#define CHOOSE_BLIT(blitter, alpha, fmt)
Definition: SDL_RLEaccel.c:306
GLenum GLenum dst
#define SDL_COPY_MODULATE_COLOR
Definition: SDL_blit.h:34
static int copy_transl_565(void *dst, Uint32 *src, int n, SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt)
Definition: SDL_RLEaccel.c:932
#define SDL_UnlockSurface
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2072
GLdouble s
Definition: SDL_opengl.h:2056
#define SDL_COPY_COLORKEY
Definition: SDL_blit.h:39
GLdouble n
static int uncopy_transl_16(Uint32 *dst, void *src, int n, RLEDestFormat *sfmt, SDL_PixelFormat *dfmt)
Definition: SDL_RLEaccel.c:970
#define BLIT_TRANSL_555(src, dst)
Definition: SDL_RLEaccel.c:604
static int uncopy_32(Uint32 *dst, void *src, int n, RLEDestFormat *sfmt, SDL_PixelFormat *dfmt)
SDL_blit blit
Definition: SDL_blit.h:89
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1567
Uint8 BytesPerPixel
Definition: SDL_pixels.h:318
const GLfloat * m
Uint32(* getpix_func)(Uint8 *)
#define SDL_COPY_MOD
Definition: SDL_blit.h:38
GLfloat GLfloat p
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
#define RLEPIXEL_FROM_RGBA(Pixel, fmt, r, g, b, a)
Definition: SDL_RLEaccel.c:380
static Uint32 getpix_16(Uint8 *srcbuf)
void SDL_UnRLESurface(SDL_Surface *surface, int recode)
#define RLEALPHACLIPBLIT(Ptype, Ctype, do_blend)
#define SDL_COPY_RLE_COLORKEY
Definition: SDL_blit.h:42
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:161
#define SDL_realloc
int SDL_RLEBlit(SDL_Surface *surf_src, SDL_Rect *srcrect, SDL_Surface *surf_dst, SDL_Rect *dstrect)
Definition: SDL_RLEaccel.c:452
GLenum GLsizei len
#define ADD_OPAQUE_COUNTS(n, m)
GLfloat GLfloat GLfloat alpha
static void RLEAlphaClipBlit(int w, Uint8 *srcbuf, SDL_Surface *surf_dst, Uint8 *dstbuf, SDL_Rect *srcrect)
Definition: SDL_RLEaccel.c:638
#define SDL_COPY_ADD
Definition: SDL_blit.h:37
Uint32 colorkey
Definition: SDL_blit.h:69
Uint32 flags
Definition: SDL_surface.h:71
GLboolean GLboolean g
#define SDL_COPY_NEAREST
Definition: SDL_blit.h:40
struct SDL_BlitMap * map
Definition: SDL_surface.h:88
#define SDL_memcpy
#define PIXEL_FROM_RGBA(Pixel, fmt, r, g, b, a)
Definition: SDL_blit.h:394
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1567
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 SDL_AssertionHandler void SDL_SpinLock SDL_atomic_t int int return SDL_atomic_t return void void void return void return int return SDL_AudioSpec SDL_AudioSpec return int int return return int SDL_RWops int SDL_AudioSpec Uint8 ** d
void * pixels
Definition: SDL_surface.h:75
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:143
#define RGB_FROM_PIXEL(Pixel, fmt, r, g, b)
Definition: SDL_blit.h:121
Uint8 BitsPerPixel
Definition: SDL_pixels.h:317
void SDL_free(void *mem)
#define ADD_COUNTS(n, m)
int done
Definition: checkkeys.c:28
static int copy_32(void *dst, Uint32 *src, int n, SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt)
Definition: SDL_RLEaccel.c:989
#define RLESKIP(bpp, Type)
static const getpix_func getpixes[4]
Uint8 BytesPerPixel
Definition: SDL_RLEaccel.c:620
unsigned int uintptr_t
int SDL_RLEAlphaBlit(SDL_Surface *surf_src, SDL_Rect *srcrect, SDL_Surface *surf_dst, SDL_Rect *dstrect)
Definition: SDL_RLEaccel.c:730
int x
Definition: SDL_rect.h:66
#define RLECLIPBLIT(bpp, Type, do_blit)
static void RLEClipBlit(int w, Uint8 *srcbuf, SDL_Surface *surf_dst, Uint8 *dstbuf, SDL_Rect *srcrect, unsigned alpha)
Definition: SDL_RLEaccel.c:393
int w
Definition: SDL_rect.h:67
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
int SDL_RLESurface(SDL_Surface *surface)
static int RLEColorkeySurface(SDL_Surface *surface)
SDL_Surface * dst
Definition: SDL_blit.h:87
#define NULL
Definition: begin_code.h:143
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:130
SDL_PixelFormat * format
Definition: SDL_surface.h:72
#define SDL_LockSurface
#define RLEALPHABLIT(Ptype, Ctype, do_blend)
#define ADD_TRANSL_COUNTS(n, m)
static SDL_bool UnRLEAlpha(SDL_Surface *surface)
#define SDL_MUSTLOCK(S)
Definition: SDL_surface.h:61
static int copy_opaque_16(void *dst, Uint32 *src, int n, SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt)
Definition: SDL_RLEaccel.c:895
#define SDL_COPY_MODULATE_ALPHA
Definition: SDL_blit.h:35
int h
Definition: SDL_rect.h:67
#define BLIT_TRANSL_565(src, dst)
Definition: SDL_RLEaccel.c:592
#define SDL_COPY_RLE_ALPHAKEY
Definition: SDL_blit.h:43
static int RLEAlphaSurface(SDL_Surface *surface)
#define SDL_FillRect
#define BLIT_TRANSL_888(src, dst)
Definition: SDL_RLEaccel.c:574
static Uint32 getpix_32(Uint8 *srcbuf)
uint16_t Uint16
An unsigned 16-bit integer type.
Definition: SDL_stdinc.h:151
static int uncopy_opaque_16(Uint32 *dst, void *src, int n, RLEDestFormat *sfmt, SDL_PixelFormat *dfmt)
Definition: SDL_RLEaccel.c:912
void * data
Definition: SDL_blit.h:90
GLbitfield flags
#define SDL_malloc
#define ISTRANSL(pixel, fmt)
GLubyte GLubyte GLubyte GLubyte w
#define MIN(a, b)
Definition: SDL_RLEaccel.c:97
#define RGBA_FROM_8888(Pixel, fmt, r, g, b, a)
Definition: SDL_blit.h:310
#define PIXEL_FROM_RGB(Pixel, fmt, r, g, b)
Definition: SDL_blit.h:217
static Uint32 getpix_8(Uint8 *srcbuf)
GLboolean GLboolean GLboolean GLboolean a
GLenum src
GLboolean GLboolean GLboolean b
int identity
Definition: SDL_blit.h:88
int y
Definition: SDL_rect.h:66
GLfloat GLfloat GLfloat GLfloat h
#define ISOPAQUE(pixel, fmt)
#define SDL_COPY_BLEND
Definition: SDL_blit.h:36
SDL_BlitInfo info
Definition: SDL_blit.h:91
#define SDL_memset
#define SDL_PREALLOC
Definition: SDL_surface.h:53
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64
#define SDL_RLEACCEL
Definition: SDL_surface.h:54
#define RLEBLIT(bpp, Type, do_blit)
static Uint32 getpix_24(Uint8 *srcbuf)
Uint8 a
Definition: SDL_blit.h:70