zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_RLEaccel.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2013 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_config.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  } \
347  /* fallthrough */ \
348  \
349  default: \
350  general16: \
351  blitter(2, Uint8, ALPHA_BLIT_ANY); \
352  } \
353  break; \
354  \
355  case 3: \
356  blitter(3, Uint8, ALPHA_BLIT_ANY); \
357  break; \
358  \
359  case 4: \
360  if((fmt->Rmask | fmt->Gmask | fmt->Bmask) == 0x00ffffff \
361  && (fmt->Gmask == 0xff00 || fmt->Rmask == 0xff00 \
362  || fmt->Bmask == 0xff00)) { \
363  if(alpha == 128) \
364  blitter(4, Uint16, ALPHA_BLIT32_888_50); \
365  else \
366  blitter(4, Uint16, ALPHA_BLIT32_888); \
367  } else \
368  blitter(4, Uint16, ALPHA_BLIT_ANY); \
369  break; \
370  } \
371  } \
372  } while(0)
373 
374 /*
375  * This takes care of the case when the surface is clipped on the left and/or
376  * right. Top clipping has already been taken care of.
377  */
378 static void
379 RLEClipBlit(int w, Uint8 * srcbuf, SDL_Surface * dst,
380  Uint8 * dstbuf, SDL_Rect * srcrect, unsigned alpha)
381 {
382  SDL_PixelFormat *fmt = dst->format;
383 
384 #define RLECLIPBLIT(bpp, Type, do_blit) \
385  do { \
386  int linecount = srcrect->h; \
387  int ofs = 0; \
388  int left = srcrect->x; \
389  int right = left + srcrect->w; \
390  dstbuf -= left * bpp; \
391  for(;;) { \
392  int run; \
393  ofs += *(Type *)srcbuf; \
394  run = ((Type *)srcbuf)[1]; \
395  srcbuf += 2 * sizeof(Type); \
396  if(run) { \
397  /* clip to left and right borders */ \
398  if(ofs < right) { \
399  int start = 0; \
400  int len = run; \
401  int startcol; \
402  if(left - ofs > 0) { \
403  start = left - ofs; \
404  len -= start; \
405  if(len <= 0) \
406  goto nocopy ## bpp ## do_blit; \
407  } \
408  startcol = ofs + start; \
409  if(len > right - startcol) \
410  len = right - startcol; \
411  do_blit(dstbuf + startcol * bpp, srcbuf + start * bpp, \
412  len, bpp, alpha); \
413  } \
414  nocopy ## bpp ## do_blit: \
415  srcbuf += run * bpp; \
416  ofs += run; \
417  } else if(!ofs) \
418  break; \
419  if(ofs == w) { \
420  ofs = 0; \
421  dstbuf += dst->pitch; \
422  if(!--linecount) \
423  break; \
424  } \
425  } \
426  } while(0)
427 
428  CHOOSE_BLIT(RLECLIPBLIT, alpha, fmt);
429 
430 #undef RLECLIPBLIT
431 
432 }
433 
434 
435 /* blit a colorkeyed RLE surface */
436 int
438  SDL_Surface * dst, SDL_Rect * dstrect)
439 {
440  Uint8 *dstbuf;
441  Uint8 *srcbuf;
442  int x, y;
443  int w = src->w;
444  unsigned alpha;
445 
446  /* Lock the destination if necessary */
447  if (SDL_MUSTLOCK(dst)) {
448  if (SDL_LockSurface(dst) < 0) {
449  return (-1);
450  }
451  }
452 
453  /* Set up the source and destination pointers */
454  x = dstrect->x;
455  y = dstrect->y;
456  dstbuf = (Uint8 *) dst->pixels
457  + y * dst->pitch + x * src->format->BytesPerPixel;
458  srcbuf = (Uint8 *) src->map->data;
459 
460  {
461  /* skip lines at the top if necessary */
462  int vskip = srcrect->y;
463  int ofs = 0;
464  if (vskip) {
465 
466 #define RLESKIP(bpp, Type) \
467  for(;;) { \
468  int run; \
469  ofs += *(Type *)srcbuf; \
470  run = ((Type *)srcbuf)[1]; \
471  srcbuf += sizeof(Type) * 2; \
472  if(run) { \
473  srcbuf += run * bpp; \
474  ofs += run; \
475  } else if(!ofs) \
476  goto done; \
477  if(ofs == w) { \
478  ofs = 0; \
479  if(!--vskip) \
480  break; \
481  } \
482  }
483 
484  switch (src->format->BytesPerPixel) {
485  case 1:
486  RLESKIP(1, Uint8);
487  break;
488  case 2:
489  RLESKIP(2, Uint8);
490  break;
491  case 3:
492  RLESKIP(3, Uint8);
493  break;
494  case 4:
495  RLESKIP(4, Uint16);
496  break;
497  }
498 
499 #undef RLESKIP
500 
501  }
502  }
503 
504  alpha = src->map->info.a;
505  /* if left or right edge clipping needed, call clip blit */
506  if (srcrect->x || srcrect->w != src->w) {
507  RLEClipBlit(w, srcbuf, dst, dstbuf, srcrect, alpha);
508  } else {
509  SDL_PixelFormat *fmt = src->format;
510 
511 #define RLEBLIT(bpp, Type, do_blit) \
512  do { \
513  int linecount = srcrect->h; \
514  int ofs = 0; \
515  for(;;) { \
516  unsigned run; \
517  ofs += *(Type *)srcbuf; \
518  run = ((Type *)srcbuf)[1]; \
519  srcbuf += 2 * sizeof(Type); \
520  if(run) { \
521  do_blit(dstbuf + ofs * bpp, srcbuf, run, bpp, alpha); \
522  srcbuf += run * bpp; \
523  ofs += run; \
524  } else if(!ofs) \
525  break; \
526  if(ofs == w) { \
527  ofs = 0; \
528  dstbuf += dst->pitch; \
529  if(!--linecount) \
530  break; \
531  } \
532  } \
533  } while(0)
534 
535  CHOOSE_BLIT(RLEBLIT, alpha, fmt);
536 
537 #undef RLEBLIT
538  }
539 
540  done:
541  /* Unlock the destination if necessary */
542  if (SDL_MUSTLOCK(dst)) {
543  SDL_UnlockSurface(dst);
544  }
545  return (0);
546 }
547 
548 #undef OPAQUE_BLIT
549 
550 /*
551  * Per-pixel blitting macros for translucent pixels:
552  * These use the same techniques as the per-surface blitting macros
553  */
554 
555 /*
556  * For 32bpp pixels, we have made sure the alpha is stored in the top
557  * 8 bits, so proceed as usual
558  */
559 #define BLIT_TRANSL_888(src, dst) \
560  do { \
561  Uint32 s = src; \
562  Uint32 d = dst; \
563  unsigned alpha = s >> 24; \
564  Uint32 s1 = s & 0xff00ff; \
565  Uint32 d1 = d & 0xff00ff; \
566  d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff; \
567  s &= 0xff00; \
568  d &= 0xff00; \
569  d = (d + ((s - d) * alpha >> 8)) & 0xff00; \
570  dst = d1 | d | 0xff000000; \
571  } while(0)
572 
573 /*
574  * For 16bpp pixels, we have stored the 5 most significant alpha bits in
575  * bits 5-10. As before, we can process all 3 RGB components at the same time.
576  */
577 #define BLIT_TRANSL_565(src, dst) \
578  do { \
579  Uint32 s = src; \
580  Uint32 d = dst; \
581  unsigned alpha = (s & 0x3e0) >> 5; \
582  s &= 0x07e0f81f; \
583  d = (d | d << 16) & 0x07e0f81f; \
584  d += (s - d) * alpha >> 5; \
585  d &= 0x07e0f81f; \
586  dst = (Uint16)(d | d >> 16); \
587  } while(0)
588 
589 #define BLIT_TRANSL_555(src, dst) \
590  do { \
591  Uint32 s = src; \
592  Uint32 d = dst; \
593  unsigned alpha = (s & 0x3e0) >> 5; \
594  s &= 0x03e07c1f; \
595  d = (d | d << 16) & 0x03e07c1f; \
596  d += (s - d) * alpha >> 5; \
597  d &= 0x03e07c1f; \
598  dst = (Uint16)(d | d >> 16); \
599  } while(0)
600 
601 /* used to save the destination format in the encoding. Designed to be
602  macro-compatible with SDL_PixelFormat but without the unneeded fields */
603 typedef struct
604 {
605  Uint8 BytesPerPixel;
606  Uint8 padding[3];
607  Uint32 Rmask;
608  Uint32 Gmask;
609  Uint32 Bmask;
610  Uint32 Amask;
611  Uint8 Rloss;
612  Uint8 Gloss;
613  Uint8 Bloss;
614  Uint8 Aloss;
615  Uint8 Rshift;
616  Uint8 Gshift;
617  Uint8 Bshift;
618  Uint8 Ashift;
619 } RLEDestFormat;
620 
621 /* blit a pixel-alpha RLE surface clipped at the right and/or left edges */
622 static void
624  Uint8 * dstbuf, SDL_Rect * srcrect)
625 {
626  SDL_PixelFormat *df = dst->format;
627  /*
628  * clipped blitter: Ptype is the destination pixel type,
629  * Ctype the translucent count type, and do_blend the macro
630  * to blend one pixel.
631  */
632 #define RLEALPHACLIPBLIT(Ptype, Ctype, do_blend) \
633  do { \
634  int linecount = srcrect->h; \
635  int left = srcrect->x; \
636  int right = left + srcrect->w; \
637  dstbuf -= left * sizeof(Ptype); \
638  do { \
639  int ofs = 0; \
640  /* blit opaque pixels on one line */ \
641  do { \
642  unsigned run; \
643  ofs += ((Ctype *)srcbuf)[0]; \
644  run = ((Ctype *)srcbuf)[1]; \
645  srcbuf += 2 * sizeof(Ctype); \
646  if(run) { \
647  /* clip to left and right borders */ \
648  int cofs = ofs; \
649  int crun = run; \
650  if(left - cofs > 0) { \
651  crun -= left - cofs; \
652  cofs = left; \
653  } \
654  if(crun > right - cofs) \
655  crun = right - cofs; \
656  if(crun > 0) \
657  PIXEL_COPY(dstbuf + cofs * sizeof(Ptype), \
658  srcbuf + (cofs - ofs) * sizeof(Ptype), \
659  (unsigned)crun, sizeof(Ptype)); \
660  srcbuf += run * sizeof(Ptype); \
661  ofs += run; \
662  } else if(!ofs) \
663  return; \
664  } while(ofs < w); \
665  /* skip padding if necessary */ \
666  if(sizeof(Ptype) == 2) \
667  srcbuf += (uintptr_t)srcbuf & 2; \
668  /* blit translucent pixels on the same line */ \
669  ofs = 0; \
670  do { \
671  unsigned run; \
672  ofs += ((Uint16 *)srcbuf)[0]; \
673  run = ((Uint16 *)srcbuf)[1]; \
674  srcbuf += 4; \
675  if(run) { \
676  /* clip to left and right borders */ \
677  int cofs = ofs; \
678  int crun = run; \
679  if(left - cofs > 0) { \
680  crun -= left - cofs; \
681  cofs = left; \
682  } \
683  if(crun > right - cofs) \
684  crun = right - cofs; \
685  if(crun > 0) { \
686  Ptype *dst = (Ptype *)dstbuf + cofs; \
687  Uint32 *src = (Uint32 *)srcbuf + (cofs - ofs); \
688  int i; \
689  for(i = 0; i < crun; i++) \
690  do_blend(src[i], dst[i]); \
691  } \
692  srcbuf += run * 4; \
693  ofs += run; \
694  } \
695  } while(ofs < w); \
696  dstbuf += dst->pitch; \
697  } while(--linecount); \
698  } while(0)
699 
700  switch (df->BytesPerPixel) {
701  case 2:
702  if (df->Gmask == 0x07e0 || df->Rmask == 0x07e0 || df->Bmask == 0x07e0)
704  else
706  break;
707  case 4:
709  break;
710  }
711 }
712 
713 /* blit a pixel-alpha RLE surface */
714 int
716  SDL_Surface * dst, SDL_Rect * dstrect)
717 {
718  int x, y;
719  int w = src->w;
720  Uint8 *srcbuf, *dstbuf;
721  SDL_PixelFormat *df = dst->format;
722 
723  /* Lock the destination if necessary */
724  if (SDL_MUSTLOCK(dst)) {
725  if (SDL_LockSurface(dst) < 0) {
726  return -1;
727  }
728  }
729 
730  x = dstrect->x;
731  y = dstrect->y;
732  dstbuf = (Uint8 *) dst->pixels + y * dst->pitch + x * df->BytesPerPixel;
733  srcbuf = (Uint8 *) src->map->data + sizeof(RLEDestFormat);
734 
735  {
736  /* skip lines at the top if necessary */
737  int vskip = srcrect->y;
738  if (vskip) {
739  int ofs;
740  if (df->BytesPerPixel == 2) {
741  /* the 16/32 interleaved format */
742  do {
743  /* skip opaque line */
744  ofs = 0;
745  do {
746  int run;
747  ofs += srcbuf[0];
748  run = srcbuf[1];
749  srcbuf += 2;
750  if (run) {
751  srcbuf += 2 * run;
752  ofs += run;
753  } else if (!ofs)
754  goto done;
755  } while (ofs < w);
756 
757  /* skip padding */
758  srcbuf += (uintptr_t) srcbuf & 2;
759 
760  /* skip translucent line */
761  ofs = 0;
762  do {
763  int run;
764  ofs += ((Uint16 *) srcbuf)[0];
765  run = ((Uint16 *) srcbuf)[1];
766  srcbuf += 4 * (run + 1);
767  ofs += run;
768  } while (ofs < w);
769  } while (--vskip);
770  } else {
771  /* the 32/32 interleaved format */
772  vskip <<= 1; /* opaque and translucent have same format */
773  do {
774  ofs = 0;
775  do {
776  int run;
777  ofs += ((Uint16 *) srcbuf)[0];
778  run = ((Uint16 *) srcbuf)[1];
779  srcbuf += 4;
780  if (run) {
781  srcbuf += 4 * run;
782  ofs += run;
783  } else if (!ofs)
784  goto done;
785  } while (ofs < w);
786  } while (--vskip);
787  }
788  }
789  }
790 
791  /* if left or right edge clipping needed, call clip blit */
792  if (srcrect->x || srcrect->w != src->w) {
793  RLEAlphaClipBlit(w, srcbuf, dst, dstbuf, srcrect);
794  } else {
795 
796  /*
797  * non-clipped blitter. Ptype is the destination pixel type,
798  * Ctype the translucent count type, and do_blend the
799  * macro to blend one pixel.
800  */
801 #define RLEALPHABLIT(Ptype, Ctype, do_blend) \
802  do { \
803  int linecount = srcrect->h; \
804  do { \
805  int ofs = 0; \
806  /* blit opaque pixels on one line */ \
807  do { \
808  unsigned run; \
809  ofs += ((Ctype *)srcbuf)[0]; \
810  run = ((Ctype *)srcbuf)[1]; \
811  srcbuf += 2 * sizeof(Ctype); \
812  if(run) { \
813  PIXEL_COPY(dstbuf + ofs * sizeof(Ptype), srcbuf, \
814  run, sizeof(Ptype)); \
815  srcbuf += run * sizeof(Ptype); \
816  ofs += run; \
817  } else if(!ofs) \
818  goto done; \
819  } while(ofs < w); \
820  /* skip padding if necessary */ \
821  if(sizeof(Ptype) == 2) \
822  srcbuf += (uintptr_t)srcbuf & 2; \
823  /* blit translucent pixels on the same line */ \
824  ofs = 0; \
825  do { \
826  unsigned run; \
827  ofs += ((Uint16 *)srcbuf)[0]; \
828  run = ((Uint16 *)srcbuf)[1]; \
829  srcbuf += 4; \
830  if(run) { \
831  Ptype *dst = (Ptype *)dstbuf + ofs; \
832  unsigned i; \
833  for(i = 0; i < run; i++) { \
834  Uint32 src = *(Uint32 *)srcbuf; \
835  do_blend(src, *dst); \
836  srcbuf += 4; \
837  dst++; \
838  } \
839  ofs += run; \
840  } \
841  } while(ofs < w); \
842  dstbuf += dst->pitch; \
843  } while(--linecount); \
844  } while(0)
845 
846  switch (df->BytesPerPixel) {
847  case 2:
848  if (df->Gmask == 0x07e0 || df->Rmask == 0x07e0
849  || df->Bmask == 0x07e0)
851  else
853  break;
854  case 4:
856  break;
857  }
858  }
859 
860  done:
861  /* Unlock the destination if necessary */
862  if (SDL_MUSTLOCK(dst)) {
863  SDL_UnlockSurface(dst);
864  }
865  return 0;
866 }
867 
868 /*
869  * Auxiliary functions:
870  * The encoding functions take 32bpp rgb + a, and
871  * return the number of bytes copied to the destination.
872  * The decoding functions copy to 32bpp rgb + a, and
873  * return the number of bytes copied from the source.
874  * These are only used in the encoder and un-RLE code and are therefore not
875  * highly optimised.
876  */
877 
878 /* encode 32bpp rgb + a into 16bpp rgb, losing alpha */
879 static int
880 copy_opaque_16(void *dst, Uint32 * src, int n,
881  SDL_PixelFormat * sfmt, SDL_PixelFormat * dfmt)
882 {
883  int i;
884  Uint16 *d = dst;
885  for (i = 0; i < n; i++) {
886  unsigned r, g, b;
887  RGB_FROM_PIXEL(*src, sfmt, r, g, b);
888  PIXEL_FROM_RGB(*d, dfmt, r, g, b);
889  src++;
890  d++;
891  }
892  return n * 2;
893 }
894 
895 /* decode opaque pixels from 16bpp to 32bpp rgb + a */
896 static int
898  RLEDestFormat * sfmt, SDL_PixelFormat * dfmt)
899 {
900  int i;
901  Uint16 *s = src;
902  unsigned alpha = dfmt->Amask ? 255 : 0;
903  for (i = 0; i < n; i++) {
904  unsigned r, g, b;
905  RGB_FROM_PIXEL(*s, sfmt, r, g, b);
906  PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, alpha);
907  s++;
908  dst++;
909  }
910  return n * 2;
911 }
912 
913 
914 
915 /* encode 32bpp rgb + a into 32bpp G0RAB format for blitting into 565 */
916 static int
918  SDL_PixelFormat * sfmt, SDL_PixelFormat * dfmt)
919 {
920  int i;
921  Uint32 *d = dst;
922  for (i = 0; i < n; i++) {
923  unsigned r, g, b, a;
924  Uint16 pix;
925  RGBA_FROM_8888(*src, sfmt, r, g, b, a);
926  PIXEL_FROM_RGB(pix, dfmt, r, g, b);
927  *d = ((pix & 0x7e0) << 16) | (pix & 0xf81f) | ((a << 2) & 0x7e0);
928  src++;
929  d++;
930  }
931  return n * 4;
932 }
933 
934 /* encode 32bpp rgb + a into 32bpp G0RAB format for blitting into 555 */
935 static int
937  SDL_PixelFormat * sfmt, SDL_PixelFormat * dfmt)
938 {
939  int i;
940  Uint32 *d = dst;
941  for (i = 0; i < n; i++) {
942  unsigned r, g, b, a;
943  Uint16 pix;
944  RGBA_FROM_8888(*src, sfmt, r, g, b, a);
945  PIXEL_FROM_RGB(pix, dfmt, r, g, b);
946  *d = ((pix & 0x3e0) << 16) | (pix & 0xfc1f) | ((a << 2) & 0x3e0);
947  src++;
948  d++;
949  }
950  return n * 4;
951 }
952 
953 /* decode translucent pixels from 32bpp GORAB to 32bpp rgb + a */
954 static int
956  RLEDestFormat * sfmt, SDL_PixelFormat * dfmt)
957 {
958  int i;
959  Uint32 *s = src;
960  for (i = 0; i < n; i++) {
961  unsigned r, g, b, a;
962  Uint32 pix = *s++;
963  a = (pix & 0x3e0) >> 2;
964  pix = (pix & ~0x3e0) | pix >> 16;
965  RGB_FROM_PIXEL(pix, sfmt, r, g, b);
966  PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, a);
967  dst++;
968  }
969  return n * 4;
970 }
971 
972 /* encode 32bpp rgba into 32bpp rgba, keeping alpha (dual purpose) */
973 static int
974 copy_32(void *dst, Uint32 * src, int n,
975  SDL_PixelFormat * sfmt, SDL_PixelFormat * dfmt)
976 {
977  int i;
978  Uint32 *d = dst;
979  for (i = 0; i < n; i++) {
980  unsigned r, g, b, a;
981  RGBA_FROM_8888(*src, sfmt, r, g, b, a);
982  PIXEL_FROM_RGBA(*d, dfmt, r, g, b, a);
983  d++;
984  src++;
985  }
986  return n * 4;
987 }
988 
989 /* decode 32bpp rgba into 32bpp rgba, keeping alpha (dual purpose) */
990 static int
991 uncopy_32(Uint32 * dst, void *src, int n,
992  RLEDestFormat * sfmt, SDL_PixelFormat * dfmt)
993 {
994  int i;
995  Uint32 *s = src;
996  for (i = 0; i < n; i++) {
997  unsigned r, g, b, a;
998  Uint32 pixel = *s++;
999  RGB_FROM_PIXEL(pixel, sfmt, r, g, b);
1000  a = pixel >> 24;
1001  PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, a);
1002  dst++;
1003  }
1004  return n * 4;
1005 }
1006 
1007 #define ISOPAQUE(pixel, fmt) ((((pixel) & fmt->Amask) >> fmt->Ashift) == 255)
1008 
1009 #define ISTRANSL(pixel, fmt) \
1010  ((unsigned)((((pixel) & fmt->Amask) >> fmt->Ashift) - 1U) < 254U)
1011 
1012 /* convert surface to be quickly alpha-blittable onto dest, if possible */
1013 static int
1015 {
1016  SDL_Surface *dest;
1017  SDL_PixelFormat *df;
1018  int maxsize = 0;
1019  int max_opaque_run;
1020  int max_transl_run = 65535;
1021  unsigned masksum;
1022  Uint8 *rlebuf, *dst;
1023  int (*copy_opaque) (void *, Uint32 *, int,
1024  SDL_PixelFormat *, SDL_PixelFormat *);
1025  int (*copy_transl) (void *, Uint32 *, int,
1026  SDL_PixelFormat *, SDL_PixelFormat *);
1027 
1028  dest = surface->map->dst;
1029  if (!dest)
1030  return -1;
1031  df = dest->format;
1032  if (surface->format->BitsPerPixel != 32)
1033  return -1; /* only 32bpp source supported */
1034 
1035  /* find out whether the destination is one we support,
1036  and determine the max size of the encoded result */
1037  masksum = df->Rmask | df->Gmask | df->Bmask;
1038  switch (df->BytesPerPixel) {
1039  case 2:
1040  /* 16bpp: only support 565 and 555 formats */
1041  switch (masksum) {
1042  case 0xffff:
1043  if (df->Gmask == 0x07e0
1044  || df->Rmask == 0x07e0 || df->Bmask == 0x07e0) {
1045  copy_opaque = copy_opaque_16;
1046  copy_transl = copy_transl_565;
1047  } else
1048  return -1;
1049  break;
1050  case 0x7fff:
1051  if (df->Gmask == 0x03e0
1052  || df->Rmask == 0x03e0 || df->Bmask == 0x03e0) {
1053  copy_opaque = copy_opaque_16;
1054  copy_transl = copy_transl_555;
1055  } else
1056  return -1;
1057  break;
1058  default:
1059  return -1;
1060  }
1061  max_opaque_run = 255; /* runs stored as bytes */
1062 
1063  /* worst case is alternating opaque and translucent pixels,
1064  with room for alignment padding between lines */
1065  maxsize = surface->h * (2 + (4 + 2) * (surface->w + 1)) + 2;
1066  break;
1067  case 4:
1068  if (masksum != 0x00ffffff)
1069  return -1; /* requires unused high byte */
1070  copy_opaque = copy_32;
1071  copy_transl = copy_32;
1072  max_opaque_run = 255; /* runs stored as short ints */
1073 
1074  /* worst case is alternating opaque and translucent pixels */
1075  maxsize = surface->h * 2 * 4 * (surface->w + 1) + 4;
1076  break;
1077  default:
1078  return -1; /* anything else unsupported right now */
1079  }
1080 
1081  maxsize += sizeof(RLEDestFormat);
1082  rlebuf = (Uint8 *) SDL_malloc(maxsize);
1083  if (!rlebuf) {
1084  return SDL_OutOfMemory();
1085  }
1086  {
1087  /* save the destination format so we can undo the encoding later */
1088  RLEDestFormat *r = (RLEDestFormat *) rlebuf;
1089  r->BytesPerPixel = df->BytesPerPixel;
1090  r->Rmask = df->Rmask;
1091  r->Gmask = df->Gmask;
1092  r->Bmask = df->Bmask;
1093  r->Amask = df->Amask;
1094  r->Rloss = df->Rloss;
1095  r->Gloss = df->Gloss;
1096  r->Bloss = df->Bloss;
1097  r->Aloss = df->Aloss;
1098  r->Rshift = df->Rshift;
1099  r->Gshift = df->Gshift;
1100  r->Bshift = df->Bshift;
1101  r->Ashift = df->Ashift;
1102  }
1103  dst = rlebuf + sizeof(RLEDestFormat);
1104 
1105  /* Do the actual encoding */
1106  {
1107  int x, y;
1108  int h = surface->h, w = surface->w;
1109  SDL_PixelFormat *sf = surface->format;
1110  Uint32 *src = (Uint32 *) surface->pixels;
1111  Uint8 *lastline = dst; /* end of last non-blank line */
1112 
1113  /* opaque counts are 8 or 16 bits, depending on target depth */
1114 #define ADD_OPAQUE_COUNTS(n, m) \
1115  if(df->BytesPerPixel == 4) { \
1116  ((Uint16 *)dst)[0] = n; \
1117  ((Uint16 *)dst)[1] = m; \
1118  dst += 4; \
1119  } else { \
1120  dst[0] = n; \
1121  dst[1] = m; \
1122  dst += 2; \
1123  }
1124 
1125  /* translucent counts are always 16 bit */
1126 #define ADD_TRANSL_COUNTS(n, m) \
1127  (((Uint16 *)dst)[0] = n, ((Uint16 *)dst)[1] = m, dst += 4)
1128 
1129  for (y = 0; y < h; y++) {
1130  int runstart, skipstart;
1131  int blankline = 0;
1132  /* First encode all opaque pixels of a scan line */
1133  x = 0;
1134  do {
1135  int run, skip, len;
1136  skipstart = x;
1137  while (x < w && !ISOPAQUE(src[x], sf))
1138  x++;
1139  runstart = x;
1140  while (x < w && ISOPAQUE(src[x], sf))
1141  x++;
1142  skip = runstart - skipstart;
1143  if (skip == w)
1144  blankline = 1;
1145  run = x - runstart;
1146  while (skip > max_opaque_run) {
1147  ADD_OPAQUE_COUNTS(max_opaque_run, 0);
1148  skip -= max_opaque_run;
1149  }
1150  len = MIN(run, max_opaque_run);
1151  ADD_OPAQUE_COUNTS(skip, len);
1152  dst += copy_opaque(dst, src + runstart, len, sf, df);
1153  runstart += len;
1154  run -= len;
1155  while (run) {
1156  len = MIN(run, max_opaque_run);
1157  ADD_OPAQUE_COUNTS(0, len);
1158  dst += copy_opaque(dst, src + runstart, len, sf, df);
1159  runstart += len;
1160  run -= len;
1161  }
1162  } while (x < w);
1163 
1164  /* Make sure the next output address is 32-bit aligned */
1165  dst += (uintptr_t) dst & 2;
1166 
1167  /* Next, encode all translucent pixels of the same scan line */
1168  x = 0;
1169  do {
1170  int run, skip, len;
1171  skipstart = x;
1172  while (x < w && !ISTRANSL(src[x], sf))
1173  x++;
1174  runstart = x;
1175  while (x < w && ISTRANSL(src[x], sf))
1176  x++;
1177  skip = runstart - skipstart;
1178  blankline &= (skip == w);
1179  run = x - runstart;
1180  while (skip > max_transl_run) {
1181  ADD_TRANSL_COUNTS(max_transl_run, 0);
1182  skip -= max_transl_run;
1183  }
1184  len = MIN(run, max_transl_run);
1185  ADD_TRANSL_COUNTS(skip, len);
1186  dst += copy_transl(dst, src + runstart, len, sf, df);
1187  runstart += len;
1188  run -= len;
1189  while (run) {
1190  len = MIN(run, max_transl_run);
1191  ADD_TRANSL_COUNTS(0, len);
1192  dst += copy_transl(dst, src + runstart, len, sf, df);
1193  runstart += len;
1194  run -= len;
1195  }
1196  if (!blankline)
1197  lastline = dst;
1198  } while (x < w);
1199 
1200  src += surface->pitch >> 2;
1201  }
1202  dst = lastline; /* back up past trailing blank lines */
1203  ADD_OPAQUE_COUNTS(0, 0);
1204  }
1205 
1206 #undef ADD_OPAQUE_COUNTS
1207 #undef ADD_TRANSL_COUNTS
1208 
1209  /* Now that we have it encoded, release the original pixels */
1210  if (!(surface->flags & SDL_PREALLOC)) {
1211  SDL_free(surface->pixels);
1212  surface->pixels = NULL;
1213  }
1214 
1215  /* realloc the buffer to release unused memory */
1216  {
1217  Uint8 *p = SDL_realloc(rlebuf, dst - rlebuf);
1218  if (!p)
1219  p = rlebuf;
1220  surface->map->data = p;
1221  }
1222 
1223  return 0;
1224 }
1225 
1226 static Uint32
1227 getpix_8(Uint8 * srcbuf)
1228 {
1229  return *srcbuf;
1230 }
1231 
1232 static Uint32
1233 getpix_16(Uint8 * srcbuf)
1234 {
1235  return *(Uint16 *) srcbuf;
1236 }
1237 
1238 static Uint32
1239 getpix_24(Uint8 * srcbuf)
1240 {
1241 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1242  return srcbuf[0] + (srcbuf[1] << 8) + (srcbuf[2] << 16);
1243 #else
1244  return (srcbuf[0] << 16) + (srcbuf[1] << 8) + srcbuf[2];
1245 #endif
1246 }
1247 
1248 static Uint32
1249 getpix_32(Uint8 * srcbuf)
1250 {
1251  return *(Uint32 *) srcbuf;
1252 }
1253 
1254 typedef Uint32(*getpix_func) (Uint8 *);
1255 
1256 static const getpix_func getpixes[4] = {
1258 };
1259 
1260 static int
1262 {
1263  Uint8 *rlebuf, *dst;
1264  int maxn;
1265  int y;
1266  Uint8 *srcbuf, *lastline;
1267  int maxsize = 0;
1268  int bpp = surface->format->BytesPerPixel;
1269  getpix_func getpix;
1270  Uint32 ckey, rgbmask;
1271  int w, h;
1272 
1273  /* calculate the worst case size for the compressed surface */
1274  switch (bpp) {
1275  case 1:
1276  /* worst case is alternating opaque and transparent pixels,
1277  starting with an opaque pixel */
1278  maxsize = surface->h * 3 * (surface->w / 2 + 1) + 2;
1279  break;
1280  case 2:
1281  case 3:
1282  /* worst case is solid runs, at most 255 pixels wide */
1283  maxsize = surface->h * (2 * (surface->w / 255 + 1)
1284  + surface->w * bpp) + 2;
1285  break;
1286  case 4:
1287  /* worst case is solid runs, at most 65535 pixels wide */
1288  maxsize = surface->h * (4 * (surface->w / 65535 + 1)
1289  + surface->w * 4) + 4;
1290  break;
1291  }
1292 
1293  rlebuf = (Uint8 *) SDL_malloc(maxsize);
1294  if (rlebuf == NULL) {
1295  return SDL_OutOfMemory();
1296  }
1297 
1298  /* Set up the conversion */
1299  srcbuf = (Uint8 *) surface->pixels;
1300  maxn = bpp == 4 ? 65535 : 255;
1301  dst = rlebuf;
1302  rgbmask = ~surface->format->Amask;
1303  ckey = surface->map->info.colorkey & rgbmask;
1304  lastline = dst;
1305  getpix = getpixes[bpp - 1];
1306  w = surface->w;
1307  h = surface->h;
1308 
1309 #define ADD_COUNTS(n, m) \
1310  if(bpp == 4) { \
1311  ((Uint16 *)dst)[0] = n; \
1312  ((Uint16 *)dst)[1] = m; \
1313  dst += 4; \
1314  } else { \
1315  dst[0] = n; \
1316  dst[1] = m; \
1317  dst += 2; \
1318  }
1319 
1320  for (y = 0; y < h; y++) {
1321  int x = 0;
1322  int blankline = 0;
1323  do {
1324  int run, skip, len;
1325  int runstart;
1326  int skipstart = x;
1327 
1328  /* find run of transparent, then opaque pixels */
1329  while (x < w && (getpix(srcbuf + x * bpp) & rgbmask) == ckey)
1330  x++;
1331  runstart = x;
1332  while (x < w && (getpix(srcbuf + x * bpp) & rgbmask) != ckey)
1333  x++;
1334  skip = runstart - skipstart;
1335  if (skip == w)
1336  blankline = 1;
1337  run = x - runstart;
1338 
1339  /* encode segment */
1340  while (skip > maxn) {
1341  ADD_COUNTS(maxn, 0);
1342  skip -= maxn;
1343  }
1344  len = MIN(run, maxn);
1345  ADD_COUNTS(skip, len);
1346  SDL_memcpy(dst, srcbuf + runstart * bpp, len * bpp);
1347  dst += len * bpp;
1348  run -= len;
1349  runstart += len;
1350  while (run) {
1351  len = MIN(run, maxn);
1352  ADD_COUNTS(0, len);
1353  SDL_memcpy(dst, srcbuf + runstart * bpp, len * bpp);
1354  dst += len * bpp;
1355  runstart += len;
1356  run -= len;
1357  }
1358  if (!blankline)
1359  lastline = dst;
1360  } while (x < w);
1361 
1362  srcbuf += surface->pitch;
1363  }
1364  dst = lastline; /* back up bast trailing blank lines */
1365  ADD_COUNTS(0, 0);
1366 
1367 #undef ADD_COUNTS
1368 
1369  /* Now that we have it encoded, release the original pixels */
1370  if (!(surface->flags & SDL_PREALLOC)) {
1371  SDL_free(surface->pixels);
1372  surface->pixels = NULL;
1373  }
1374 
1375  /* realloc the buffer to release unused memory */
1376  {
1377  /* If realloc returns NULL, the original block is left intact */
1378  Uint8 *p = SDL_realloc(rlebuf, dst - rlebuf);
1379  if (!p)
1380  p = rlebuf;
1381  surface->map->data = p;
1382  }
1383 
1384  return (0);
1385 }
1386 
1387 int
1389 {
1390  int flags;
1391 
1392  /* Clear any previous RLE conversion */
1393  if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
1394  SDL_UnRLESurface(surface, 1);
1395  }
1396 
1397  /* We don't support RLE encoding of bitmaps */
1398  if (surface->format->BitsPerPixel < 8) {
1399  return -1;
1400  }
1401 
1402  /* Make sure the pixels are available */
1403  if (!surface->pixels) {
1404  return -1;
1405  }
1406 
1407  /* If we don't have colorkey or blending, nothing to do... */
1408  flags = surface->map->info.flags;
1409  if (!(flags & (SDL_COPY_COLORKEY | SDL_COPY_BLEND))) {
1410  return -1;
1411  }
1412 
1413  /* Pass on combinations not supported */
1414  if ((flags & SDL_COPY_MODULATE_COLOR) ||
1415  ((flags & SDL_COPY_MODULATE_ALPHA) && surface->format->Amask) ||
1416  (flags & (SDL_COPY_ADD | SDL_COPY_MOD)) ||
1417  (flags & SDL_COPY_NEAREST)) {
1418  return -1;
1419  }
1420 
1421  /* Encode and set up the blit */
1422  if (!surface->format->Amask || !(flags & SDL_COPY_BLEND)) {
1423  if (!surface->map->identity) {
1424  return -1;
1425  }
1426  if (RLEColorkeySurface(surface) < 0) {
1427  return -1;
1428  }
1429  surface->map->blit = SDL_RLEBlit;
1430  surface->map->info.flags |= SDL_COPY_RLE_COLORKEY;
1431  } else {
1432  if (RLEAlphaSurface(surface) < 0) {
1433  return -1;
1434  }
1435  surface->map->blit = SDL_RLEAlphaBlit;
1436  surface->map->info.flags |= SDL_COPY_RLE_ALPHAKEY;
1437  }
1438 
1439  /* The surface is now accelerated */
1440  surface->flags |= SDL_RLEACCEL;
1441 
1442  return (0);
1443 }
1444 
1445 /*
1446  * Un-RLE a surface with pixel alpha
1447  * This may not give back exactly the image before RLE-encoding; all
1448  * completely transparent pixels will be lost, and color and alpha depth
1449  * may have been reduced (when encoding for 16bpp targets).
1450  */
1451 static SDL_bool
1453 {
1454  Uint8 *srcbuf;
1455  Uint32 *dst;
1456  SDL_PixelFormat *sf = surface->format;
1457  RLEDestFormat *df = surface->map->data;
1458  int (*uncopy_opaque) (Uint32 *, void *, int,
1459  RLEDestFormat *, SDL_PixelFormat *);
1460  int (*uncopy_transl) (Uint32 *, void *, int,
1461  RLEDestFormat *, SDL_PixelFormat *);
1462  int w = surface->w;
1463  int bpp = df->BytesPerPixel;
1464 
1465  if (bpp == 2) {
1466  uncopy_opaque = uncopy_opaque_16;
1467  uncopy_transl = uncopy_transl_16;
1468  } else {
1469  uncopy_opaque = uncopy_transl = uncopy_32;
1470  }
1471 
1472  surface->pixels = SDL_malloc(surface->h * surface->pitch);
1473  if (!surface->pixels) {
1474  return (SDL_FALSE);
1475  }
1476  /* fill background with transparent pixels */
1477  SDL_memset(surface->pixels, 0, surface->h * surface->pitch);
1478 
1479  dst = surface->pixels;
1480  srcbuf = (Uint8 *) (df + 1);
1481  for (;;) {
1482  /* copy opaque pixels */
1483  int ofs = 0;
1484  do {
1485  unsigned run;
1486  if (bpp == 2) {
1487  ofs += srcbuf[0];
1488  run = srcbuf[1];
1489  srcbuf += 2;
1490  } else {
1491  ofs += ((Uint16 *) srcbuf)[0];
1492  run = ((Uint16 *) srcbuf)[1];
1493  srcbuf += 4;
1494  }
1495  if (run) {
1496  srcbuf += uncopy_opaque(dst + ofs, srcbuf, run, df, sf);
1497  ofs += run;
1498  } else if (!ofs)
1499  return (SDL_TRUE);
1500  } while (ofs < w);
1501 
1502  /* skip padding if needed */
1503  if (bpp == 2)
1504  srcbuf += (uintptr_t) srcbuf & 2;
1505 
1506  /* copy translucent pixels */
1507  ofs = 0;
1508  do {
1509  unsigned run;
1510  ofs += ((Uint16 *) srcbuf)[0];
1511  run = ((Uint16 *) srcbuf)[1];
1512  srcbuf += 4;
1513  if (run) {
1514  srcbuf += uncopy_transl(dst + ofs, srcbuf, run, df, sf);
1515  ofs += run;
1516  }
1517  } while (ofs < w);
1518  dst += surface->pitch >> 2;
1519  }
1520  /* Make the compiler happy */
1521  return (SDL_TRUE);
1522 }
1523 
1524 void
1526 {
1527  if (surface->flags & SDL_RLEACCEL) {
1528  surface->flags &= ~SDL_RLEACCEL;
1529 
1530  if (recode && !(surface->flags & SDL_PREALLOC)) {
1531  if (surface->map->info.flags & SDL_COPY_RLE_COLORKEY) {
1532  SDL_Rect full;
1533 
1534  /* re-create the original surface */
1535  surface->pixels = SDL_malloc(surface->h * surface->pitch);
1536  if (!surface->pixels) {
1537  /* Oh crap... */
1538  surface->flags |= SDL_RLEACCEL;
1539  return;
1540  }
1541 
1542  /* fill it with the background color */
1543  SDL_FillRect(surface, NULL, surface->map->info.colorkey);
1544 
1545  /* now render the encoded surface */
1546  full.x = full.y = 0;
1547  full.w = surface->w;
1548  full.h = surface->h;
1549  SDL_RLEBlit(surface, &full, surface, &full);
1550  } else {
1551  if (!UnRLEAlpha(surface)) {
1552  /* Oh crap... */
1553  surface->flags |= SDL_RLEACCEL;
1554  return;
1555  }
1556  }
1557  }
1558  surface->map->info.flags &=
1560 
1561  SDL_free(surface->map->data);
1562  surface->map->data = NULL;
1563  }
1564 }
1565 
1566 /* 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:936
#define CHOOSE_BLIT(blitter, alpha, fmt)
Definition: SDL_RLEaccel.c:306
#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:917
GLdouble s
Definition: glew.h:1376
static void RLEClipBlit(int w, Uint8 *srcbuf, SDL_Surface *dst, Uint8 *dstbuf, SDL_Rect *srcrect, unsigned alpha)
Definition: SDL_RLEaccel.c:379
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:7294
#define SDL_COPY_COLORKEY
Definition: SDL_blit.h:39
static int uncopy_transl_16(Uint32 *dst, void *src, int n, RLEDestFormat *sfmt, SDL_PixelFormat *dfmt)
Definition: SDL_RLEaccel.c:955
#define BLIT_TRANSL_555(src, dst)
Definition: SDL_RLEaccel.c:589
static int uncopy_32(Uint32 *dst, void *src, int n, RLEDestFormat *sfmt, SDL_PixelFormat *dfmt)
Definition: SDL_RLEaccel.c:991
SDL_blit blit
Definition: SDL_blit.h:89
GLboolean GLboolean g
Definition: glew.h:8736
#define NULL
Definition: ftobjs.h:61
Uint8 BytesPerPixel
Definition: SDL_pixels.h:277
SDL_bool
Definition: SDL_stdinc.h:116
GLclampd n
Definition: glew.h:7287
#define SDL_COPY_MOD
Definition: SDL_blit.h:38
EGLSurface EGLint x
Definition: eglext.h:293
EGLSurface surface
Definition: eglext.h:74
DECLSPEC void *SDLCALL SDL_realloc(void *mem, size_t size)
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
DECLSPEC void SDLCALL SDL_free(void *mem)
static Uint32 getpix_16(Uint8 *srcbuf)
void SDL_UnRLESurface(SDL_Surface *surface, int recode)
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:8736
#define RLEALPHACLIPBLIT(Ptype, Ctype, do_blend)
#define SDL_COPY_RLE_COLORKEY
Definition: SDL_blit.h:42
return Display return Display Bool Bool int d
Definition: SDL_x11sym.h:30
GLenum GLsizei len
Definition: glew.h:7035
if(!yyg->yy_init)
#define ADD_OPAQUE_COUNTS(n, m)
#define SDL_COPY_ADD
Definition: SDL_blit.h:37
DECLSPEC int SDLCALL SDL_FillRect(SDL_Surface *dst, const SDL_Rect *rect, Uint32 color)
Definition: SDL_fillrect.c:332
Uint32 colorkey
Definition: SDL_blit.h:69
Uint32 flags
Definition: SDL_surface.h:71
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:145
#define SDL_COPY_NEAREST
Definition: SDL_blit.h:40
DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface *surface)
Definition: SDL_surface.c:786
struct SDL_BlitMap * map
Definition: SDL_surface.h:88
GLenum GLenum dst
Definition: glew.h:2396
#define PIXEL_FROM_RGBA(Pixel, fmt, r, g, b, a)
Definition: SDL_blit.h:394
int
Definition: SDL_systhread.c:37
void * pixels
Definition: SDL_surface.h:75
#define RGB_FROM_PIXEL(Pixel, fmt, r, g, b)
Definition: SDL_blit.h:121
Uint8 BitsPerPixel
Definition: SDL_pixels.h:276
GLfloat GLfloat p
Definition: glew.h:14938
#define ADD_COUNTS(n, m)
static int copy_32(void *dst, Uint32 *src, int n, SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt)
Definition: SDL_RLEaccel.c:974
DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len)
Definition: SDL_string.c:261
#define RLESKIP(bpp, Type)
static const getpix_func getpixes[4]
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
unsigned int uintptr_t
int x
Definition: SDL_rect.h:65
#define RLECLIPBLIT(bpp, Type, do_blit)
GLclampf GLclampf GLclampf alpha
Definition: glew.h:1506
int w
Definition: SDL_rect.h:66
int SDL_RLESurface(SDL_Surface *surface)
static int RLEColorkeySurface(SDL_Surface *surface)
SDL_Surface * dst
Definition: SDL_blit.h:87
EGLSurface EGLint EGLint y
Definition: eglext.h:293
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_PixelFormat * format
Definition: SDL_surface.h:72
int SDL_RLEAlphaBlit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect)
Definition: SDL_RLEaccel.c:715
#define RLEALPHABLIT(Ptype, Ctype, do_blend)
#define ADD_TRANSL_COUNTS(n, m)
DECLSPEC void *SDLCALL SDL_memcpy(void *dst, const void *src, size_t len)
Definition: SDL_string.c:293
static SDL_bool UnRLEAlpha(SDL_Surface *surface)
GLenum GLsizei GLsizei GLsizei GLsizei GLbitfield flags
Definition: glew.h:2767
#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:880
#define SDL_COPY_MODULATE_ALPHA
Definition: SDL_blit.h:35
int h
Definition: SDL_rect.h:66
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:129
#define BLIT_TRANSL_565(src, dst)
Definition: SDL_RLEaccel.c:577
#define SDL_COPY_RLE_ALPHAKEY
Definition: SDL_blit.h:43
static int RLEAlphaSurface(SDL_Surface *surface)
#define BLIT_TRANSL_888(src, dst)
Definition: SDL_RLEaccel.c:559
int SDL_RLEBlit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect)
Definition: SDL_RLEaccel.c:437
static Uint32 getpix_32(Uint8 *srcbuf)
GLdouble GLdouble GLdouble r
Definition: glew.h:1392
GLdouble GLdouble GLdouble b
Definition: glew.h:8383
static int uncopy_opaque_16(Uint32 *dst, void *src, int n, RLEDestFormat *sfmt, SDL_PixelFormat *dfmt)
Definition: SDL_RLEaccel.c:897
GLint GLint GLint GLint GLint w
Definition: gl2ext.h:1215
png_uint_32 skip
Definition: pngrutil.c:1241
void * data
Definition: SDL_blit.h:90
uint16_t Uint16
An unsigned 16-bit integer type.
Definition: SDL_stdinc.h:137
static void RLEAlphaClipBlit(int w, Uint8 *srcbuf, SDL_Surface *dst, Uint8 *dstbuf, SDL_Rect *srcrect)
Definition: SDL_RLEaccel.c:623
#define ISTRANSL(pixel, fmt)
#define MIN(a, b)
Definition: SDL_RLEaccel.c:97
#define RGBA_FROM_8888(Pixel, fmt, r, g, b, a)
Definition: SDL_blit.h:310
GLenum src
Definition: glew.h:2396
#define PIXEL_FROM_RGB(Pixel, fmt, r, g, b)
Definition: SDL_blit.h:217
Uint32(* getpix_func)(Uint8 *)
static Uint32 getpix_8(Uint8 *srcbuf)
int i
Definition: pngrutil.c:1377
int identity
Definition: SDL_blit.h:88
DECLSPEC int SDLCALL SDL_LockSurface(SDL_Surface *surface)
Sets up a surface for directly accessing the pixels.
Definition: SDL_surface.c:765
#define m(i, j)
int y
Definition: SDL_rect.h:65
#define ISOPAQUE(pixel, fmt)
#define SDL_COPY_BLEND
Definition: SDL_blit.h:36
SDL_BlitInfo info
Definition: SDL_blit.h:91
#define SDL_PREALLOC
Definition: SDL_surface.h:53
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:63
#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
const GLdouble * m
Definition: glew.h:8385