Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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