SDL_RLEaccel.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:43k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

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