src/video/SDL_RLEaccel.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 21 Aug 2004 13:10:58 +0000
changeset 944 cdea7cbc3e23
parent 880 9ef41050100c
child 1155 91569ec25acd
permissions -rw-r--r--
Date: Wed, 28 Jul 2004 14:56:57 +0800
From: Aaron Perez
Subject: [SDL] Fwd: SDL not checking malloc returning NULL

I was reading through the code and i found that in several places does a
malloc and without checking if it is NULL just use the pointer.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2004 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@libsdl.org
    21 */
    22 
    23 #ifdef SAVE_RCSID
    24 static char rcsid =
    25  "@(#) $Id$";
    26 #endif
    27 
    28 /*
    29  * RLE encoding for software colorkey and alpha-channel acceleration
    30  *
    31  * Original version by Sam Lantinga
    32  *
    33  * Mattias Engdegård (Yorick): Rewrite. New encoding format, encoder and
    34  * decoder. Added per-surface alpha blitter. Added per-pixel alpha
    35  * format, encoder and blitter.
    36  *
    37  * Many thanks to Xark and johns for hints, benchmarks and useful comments
    38  * leading to this code.
    39  *
    40  * Welcome to Macro Mayhem.
    41  */
    42 
    43 /*
    44  * The encoding translates the image data to a stream of segments of the form
    45  *
    46  * <skip> <run> <data>
    47  *
    48  * where <skip> is the number of transparent pixels to skip,
    49  *       <run>  is the number of opaque pixels to blit,
    50  * and   <data> are the pixels themselves.
    51  *
    52  * This basic structure is used both for colorkeyed surfaces, used for simple
    53  * binary transparency and for per-surface alpha blending, and for surfaces
    54  * with per-pixel alpha. The details differ, however:
    55  *
    56  * Encoding of colorkeyed surfaces:
    57  *
    58  *   Encoded pixels always have the same format as the target surface.
    59  *   <skip> and <run> are unsigned 8 bit integers, except for 32 bit depth
    60  *   where they are 16 bit. This makes the pixel data aligned at all times.
    61  *   Segments never wrap around from one scan line to the next.
    62  *
    63  *   The end of the sequence is marked by a zero <skip>,<run> pair at the *
    64  *   beginning of a line.
    65  *
    66  * Encoding of surfaces with per-pixel alpha:
    67  *
    68  *   The sequence begins with a struct RLEDestFormat describing the target
    69  *   pixel format, to provide reliable un-encoding.
    70  *
    71  *   Each scan line is encoded twice: First all completely opaque pixels,
    72  *   encoded in the target format as described above, and then all
    73  *   partially transparent (translucent) pixels (where 1 <= alpha <= 254),
    74  *   in the following 32-bit format:
    75  *
    76  *   For 32-bit targets, each pixel has the target RGB format but with
    77  *   the alpha value occupying the highest 8 bits. The <skip> and <run>
    78  *   counts are 16 bit.
    79  * 
    80  *   For 16-bit targets, each pixel has the target RGB format, but with
    81  *   the middle component (usually green) shifted 16 steps to the left,
    82  *   and the hole filled with the 5 most significant bits of the alpha value.
    83  *   i.e. if the target has the format         rrrrrggggggbbbbb,
    84  *   the encoded pixel will be 00000gggggg00000rrrrr0aaaaabbbbb.
    85  *   The <skip> and <run> counts are 8 bit for the opaque lines, 16 bit
    86  *   for the translucent lines. Two padding bytes may be inserted
    87  *   before each translucent line to keep them 32-bit aligned.
    88  *
    89  *   The end of the sequence is marked by a zero <skip>,<run> pair at the
    90  *   beginning of an opaque line.
    91  */
    92 
    93 #include <stdio.h>
    94 #include <stdlib.h>
    95 #include <string.h>
    96 
    97 #include "SDL_types.h"
    98 #include "SDL_video.h"
    99 #include "SDL_error.h"
   100 #include "SDL_sysvideo.h"
   101 #include "SDL_blit.h"
   102 #include "SDL_memops.h"
   103 #include "SDL_RLEaccel_c.h"
   104 
   105 #if (defined(i386) || defined(__x86_64__)) && defined(__GNUC__) && defined(USE_ASMBLIT)
   106 #define MMX_ASMBLIT
   107 #endif
   108 
   109 #ifdef MMX_ASMBLIT
   110 #include "mmx.h"
   111 #include "SDL_cpuinfo.h"
   112 #endif
   113 
   114 #ifndef MAX
   115 #define MAX(a, b) ((a) > (b) ? (a) : (b))
   116 #endif
   117 #ifndef MIN
   118 #define MIN(a, b) ((a) < (b) ? (a) : (b))
   119 #endif
   120 
   121 #define PIXEL_COPY(to, from, len, bpp)			\
   122 do {							\
   123     if(bpp == 4) {					\
   124 	SDL_memcpy4(to, from, (unsigned)(len));		\
   125     } else {						\
   126 	SDL_memcpy(to, from, (unsigned)(len) * (bpp));	\
   127     }							\
   128 } while(0)
   129 
   130 /*
   131  * Various colorkey blit methods, for opaque and per-surface alpha
   132  */
   133 
   134 #define OPAQUE_BLIT(to, from, length, bpp, alpha)	\
   135     PIXEL_COPY(to, from, length, bpp)
   136 
   137 #ifdef MMX_ASMBLIT
   138 
   139 #define ALPHA_BLIT32_888MMX(to, from, length, bpp, alpha)	\
   140     do {							\
   141 	Uint32 *srcp = (Uint32 *)(from);			\
   142 	Uint32 *dstp = (Uint32 *)(to);				\
   143         int i = 0x00FF00FF;					\
   144         movd_m2r(*(&i), mm3);					\
   145         punpckldq_r2r(mm3, mm3);				\
   146         i = 0xFF000000;						\
   147         movd_m2r(*(&i), mm7);					\
   148         punpckldq_r2r(mm7, mm7);				\
   149         i = alpha | alpha << 16;				\
   150         movd_m2r(*(&i), mm4);					\
   151         punpckldq_r2r(mm4, mm4);				\
   152 	pcmpeqd_r2r(mm5,mm5); /* set mm5 to "1" */		\
   153 	pxor_r2r(mm7, mm5); /* make clear alpha mask */		\
   154         i = length;						\
   155 	if(i & 1) {						\
   156           movd_m2r((*srcp), mm1); /* src -> mm1 */		\
   157           punpcklbw_r2r(mm1, mm1);				\
   158           pand_r2r(mm3, mm1);					\
   159 	  movd_m2r((*dstp), mm2); /* dst -> mm2 */		\
   160           punpcklbw_r2r(mm2, mm2);				\
   161           pand_r2r(mm3, mm2);					\
   162 	  psubw_r2r(mm2, mm1);					\
   163 	  pmullw_r2r(mm4, mm1);					\
   164 	  psrlw_i2r(8, mm1);					\
   165 	  paddw_r2r(mm1, mm2);					\
   166 	  pand_r2r(mm3, mm2);					\
   167 	  packuswb_r2r(mm2, mm2);				\
   168 	  pand_r2r(mm5, mm2); /* 00000RGB -> mm2 */		\
   169 	  movd_r2m(mm2, *dstp);					\
   170 	  ++srcp;						\
   171 	  ++dstp;						\
   172 	  i--;							\
   173 	}							\
   174 	for(; i > 0; --i) {					\
   175           movq_m2r((*srcp), mm0);				\
   176 	  movq_r2r(mm0, mm1);					\
   177           punpcklbw_r2r(mm0, mm0);				\
   178 	  movq_m2r((*dstp), mm2);				\
   179 	  punpckhbw_r2r(mm1, mm1);				\
   180 	  movq_r2r(mm2, mm6);					\
   181           pand_r2r(mm3, mm0);					\
   182           punpcklbw_r2r(mm2, mm2);				\
   183 	  pand_r2r(mm3, mm1);					\
   184 	  punpckhbw_r2r(mm6, mm6);				\
   185           pand_r2r(mm3, mm2);					\
   186 	  psubw_r2r(mm2, mm0);					\
   187 	  pmullw_r2r(mm4, mm0);					\
   188 	  pand_r2r(mm3, mm6);					\
   189 	  psubw_r2r(mm6, mm1);					\
   190 	  pmullw_r2r(mm4, mm1);					\
   191 	  psrlw_i2r(8, mm0);					\
   192 	  paddw_r2r(mm0, mm2);					\
   193 	  psrlw_i2r(8, mm1);					\
   194 	  paddw_r2r(mm1, mm6);					\
   195 	  pand_r2r(mm3, mm2);					\
   196 	  pand_r2r(mm3, mm6);					\
   197 	  packuswb_r2r(mm2, mm2);				\
   198 	  packuswb_r2r(mm6, mm6);				\
   199 	  psrlq_i2r(32, mm2);					\
   200 	  psllq_i2r(32, mm6);					\
   201 	  por_r2r(mm6, mm2);					\
   202 	  pand_r2r(mm5, mm2); /* 00000RGB -> mm2 */		\
   203          movq_r2m(mm2, *dstp);					\
   204 	  srcp += 2;						\
   205 	  dstp += 2;						\
   206 	  i--;							\
   207 	}							\
   208 	emms();							\
   209     } while(0)
   210 
   211 #define ALPHA_BLIT16_565MMX(to, from, length, bpp, alpha)	\
   212     do {						\
   213         int i, n = 0;					\
   214 	Uint16 *srcp = (Uint16 *)(from);		\
   215 	Uint16 *dstp = (Uint16 *)(to);			\
   216         Uint32 ALPHA = 0xF800;				\
   217 	movd_m2r(*(&ALPHA), mm1);			\
   218         punpcklwd_r2r(mm1, mm1);			\
   219         punpcklwd_r2r(mm1, mm1);			\
   220 	ALPHA = 0x07E0;					\
   221 	movd_m2r(*(&ALPHA), mm4);			\
   222         punpcklwd_r2r(mm4, mm4);			\
   223         punpcklwd_r2r(mm4, mm4);			\
   224 	ALPHA = 0x001F;					\
   225 	movd_m2r(*(&ALPHA), mm7);			\
   226         punpcklwd_r2r(mm7, mm7);			\
   227         punpcklwd_r2r(mm7, mm7);			\
   228 	alpha &= ~(1+2+4);				\
   229         i = (Uint32)alpha | (Uint32)alpha << 16;	\
   230         movd_m2r(*(&i), mm0);				\
   231         punpckldq_r2r(mm0, mm0);			\
   232         ALPHA = alpha >> 3;				\
   233         i = ((int)(length) & 3);			\
   234 	for(; i > 0; --i) {				\
   235 	    Uint32 s = *srcp++;				\
   236 	    Uint32 d = *dstp;				\
   237 	    s = (s | s << 16) & 0x07e0f81f;		\
   238 	    d = (d | d << 16) & 0x07e0f81f;		\
   239 	    d += (s - d) * ALPHA >> 5;			\
   240 	    d &= 0x07e0f81f;				\
   241 	    *dstp++ = d | d >> 16;			\
   242 	    n++;					\
   243 	}						\
   244 	i = (int)(length) - n;				\
   245 	for(; i > 0; --i) {				\
   246 	  movq_m2r((*dstp), mm3);			\
   247 	  movq_m2r((*srcp), mm2);			\
   248 	  movq_r2r(mm2, mm5);				\
   249 	  pand_r2r(mm1 , mm5);				\
   250 	  psrlq_i2r(11, mm5);				\
   251 	  movq_r2r(mm3, mm6);				\
   252 	  pand_r2r(mm1 , mm6);				\
   253 	  psrlq_i2r(11, mm6);				\
   254 	  psubw_r2r(mm6, mm5);				\
   255 	  pmullw_r2r(mm0, mm5);				\
   256 	  psrlw_i2r(8, mm5);				\
   257 	  paddw_r2r(mm5, mm6);				\
   258 	  psllq_i2r(11, mm6);				\
   259 	  pand_r2r(mm1, mm6);				\
   260 	  movq_r2r(mm4, mm5);				\
   261 	  por_r2r(mm7, mm5);				\
   262 	  pand_r2r(mm5, mm3);				\
   263 	  por_r2r(mm6, mm3);				\
   264 	  movq_r2r(mm2, mm5);				\
   265 	  pand_r2r(mm4 , mm5);				\
   266 	  psrlq_i2r(5, mm5);				\
   267 	  movq_r2r(mm3, mm6);				\
   268 	  pand_r2r(mm4 , mm6);				\
   269 	  psrlq_i2r(5, mm6);				\
   270 	  psubw_r2r(mm6, mm5);				\
   271 	  pmullw_r2r(mm0, mm5);				\
   272 	  psrlw_i2r(8, mm5);				\
   273 	  paddw_r2r(mm5, mm6);				\
   274 	  psllq_i2r(5, mm6);				\
   275 	  pand_r2r(mm4, mm6);				\
   276 	  movq_r2r(mm1, mm5);				\
   277 	  por_r2r(mm7, mm5);				\
   278 	  pand_r2r(mm5, mm3);				\
   279 	  por_r2r(mm6, mm3);				\
   280 	  movq_r2r(mm2, mm5);				\
   281 	  pand_r2r(mm7 , mm5);				\
   282           movq_r2r(mm3, mm6);				\
   283 	  pand_r2r(mm7 , mm6);				\
   284 	  psubw_r2r(mm6, mm5);				\
   285 	  pmullw_r2r(mm0, mm5);				\
   286 	  psrlw_i2r(8, mm5);				\
   287 	  paddw_r2r(mm5, mm6);				\
   288 	  pand_r2r(mm7, mm6);				\
   289 	  movq_r2r(mm1, mm5);				\
   290 	  por_r2r(mm4, mm5);				\
   291 	  pand_r2r(mm5, mm3);				\
   292 	  por_r2r(mm6, mm3);				\
   293 	  movq_r2m(mm3, *dstp);				\
   294 	  srcp += 4;					\
   295 	  dstp += 4;					\
   296 	  i -= 3;					\
   297 	}						\
   298 	emms();						\
   299     } while(0)
   300 
   301 #define ALPHA_BLIT16_555MMX(to, from, length, bpp, alpha)	\
   302     do {						\
   303         int i, n = 0;					\
   304 	Uint16 *srcp = (Uint16 *)(from);		\
   305 	Uint16 *dstp = (Uint16 *)(to);			\
   306         Uint32 ALPHA = 0x7C00;				\
   307 	movd_m2r(*(&ALPHA), mm1);			\
   308         punpcklwd_r2r(mm1, mm1);			\
   309         punpcklwd_r2r(mm1, mm1);			\
   310 	ALPHA = 0x03E0;					\
   311         movd_m2r(*(&ALPHA), mm4);			\
   312         punpcklwd_r2r(mm4, mm4);			\
   313         punpcklwd_r2r(mm4, mm4);			\
   314 	ALPHA = 0x001F;					\
   315 	movd_m2r(*(&ALPHA), mm7);			\
   316         punpcklwd_r2r(mm7, mm7);			\
   317         punpcklwd_r2r(mm7, mm7);			\
   318 	alpha &= ~(1+2+4);				\
   319         i = (Uint32)alpha | (Uint32)alpha << 16;	\
   320         movd_m2r(*(&i), mm0);				\
   321         punpckldq_r2r(mm0, mm0);			\
   322         i = ((int)(length) & 3);				\
   323         ALPHA = alpha >> 3;				\
   324 	for(; i > 0; --i) {				\
   325 	    Uint32 s = *srcp++;				\
   326 	    Uint32 d = *dstp;				\
   327 	    s = (s | s << 16) & 0x03e07c1f;		\
   328 	    d = (d | d << 16) & 0x03e07c1f;		\
   329 	    d += (s - d) * ALPHA >> 5;			\
   330 	    d &= 0x03e07c1f;				\
   331 	    *dstp++ = d | d >> 16;			\
   332 	    n++;					\
   333 	}						\
   334 	i = (int)(length) - n;				\
   335 	for(; i > 0; --i) {				\
   336 	  movq_m2r((*dstp), mm3);			\
   337 	  movq_m2r((*srcp), mm2);			\
   338 	  movq_r2r(mm2, mm5);				\
   339 	  pand_r2r(mm1 , mm5);				\
   340 	  psrlq_i2r(10, mm5);				\
   341 	  movq_r2r(mm3, mm6);				\
   342 	  pand_r2r(mm1 , mm6);				\
   343 	  psrlq_i2r(10, mm6);				\
   344 	  psubw_r2r(mm6, mm5);				\
   345 	  pmullw_r2r(mm0, mm5);				\
   346 	  psrlw_i2r(8, mm5);				\
   347 	  paddw_r2r(mm5, mm6);				\
   348 	  psllq_i2r(10, mm6);				\
   349 	  pand_r2r(mm1, mm6);				\
   350 	  movq_r2r(mm4, mm5);				\
   351 	  por_r2r(mm7, mm5);				\
   352 	  pand_r2r(mm5, mm3);				\
   353 	  por_r2r(mm6, mm3);				\
   354 	  movq_r2r(mm2, mm5);				\
   355 	  pand_r2r(mm4 , mm5);				\
   356 	  psrlq_i2r(5, mm5);				\
   357 	  movq_r2r(mm3, mm6);				\
   358 	  pand_r2r(mm4 , mm6);				\
   359 	  psrlq_i2r(5, mm6);				\
   360 	  psubw_r2r(mm6, mm5);				\
   361 	  pmullw_r2r(mm0, mm5);				\
   362 	  psrlw_i2r(8, mm5);				\
   363 	  paddw_r2r(mm5, mm6);				\
   364 	  psllq_i2r(5, mm6);				\
   365 	  pand_r2r(mm4, mm6);				\
   366 	  movq_r2r(mm1, mm5);				\
   367 	  por_r2r(mm7, mm5);				\
   368 	  pand_r2r(mm5, mm3);				\
   369 	  por_r2r(mm6, mm3);				\
   370 	  movq_r2r(mm2, mm5);				\
   371 	  pand_r2r(mm7 , mm5);				\
   372           movq_r2r(mm3, mm6);				\
   373 	  pand_r2r(mm7 , mm6);				\
   374 	  psubw_r2r(mm6, mm5);				\
   375 	  pmullw_r2r(mm0, mm5);				\
   376 	  psrlw_i2r(8, mm5);				\
   377 	  paddw_r2r(mm5, mm6);				\
   378 	  pand_r2r(mm7, mm6);				\
   379 	  movq_r2r(mm1, mm5);				\
   380 	  por_r2r(mm4, mm5);				\
   381 	  pand_r2r(mm5, mm3);				\
   382 	  por_r2r(mm6, mm3);				\
   383 	  movq_r2m(mm3, *dstp);				\
   384 	  srcp += 4;					\
   385 	  dstp += 4;					\
   386 	  i -= 3;					\
   387 	}						\
   388 	emms();						\
   389     } while(0)
   390 
   391 #endif
   392 
   393 /*
   394  * For 32bpp pixels on the form 0x00rrggbb:
   395  * If we treat the middle component separately, we can process the two
   396  * remaining in parallel. This is safe to do because of the gap to the left
   397  * of each component, so the bits from the multiplication don't collide.
   398  * This can be used for any RGB permutation of course.
   399  */
   400 #define ALPHA_BLIT32_888(to, from, length, bpp, alpha)		\
   401     do {							\
   402         int i;							\
   403 	Uint32 *src = (Uint32 *)(from);				\
   404 	Uint32 *dst = (Uint32 *)(to);				\
   405 	for(i = 0; i < (int)(length); i++) {			\
   406 	    Uint32 s = *src++;					\
   407 	    Uint32 d = *dst;					\
   408 	    Uint32 s1 = s & 0xff00ff;				\
   409 	    Uint32 d1 = d & 0xff00ff;				\
   410 	    d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff;	\
   411 	    s &= 0xff00;					\
   412 	    d &= 0xff00;					\
   413 	    d = (d + ((s - d) * alpha >> 8)) & 0xff00;		\
   414 	    *dst++ = d1 | d;					\
   415 	}							\
   416     } while(0)
   417 
   418 /*
   419  * For 16bpp pixels we can go a step further: put the middle component
   420  * in the high 16 bits of a 32 bit word, and process all three RGB
   421  * components at the same time. Since the smallest gap is here just
   422  * 5 bits, we have to scale alpha down to 5 bits as well.
   423  */
   424 #define ALPHA_BLIT16_565(to, from, length, bpp, alpha)	\
   425     do {						\
   426         int i;						\
   427 	Uint16 *src = (Uint16 *)(from);			\
   428 	Uint16 *dst = (Uint16 *)(to);			\
   429 	Uint32 ALPHA = alpha >> 3;			\
   430 	for(i = 0; i < (int)(length); i++) {		\
   431 	    Uint32 s = *src++;				\
   432 	    Uint32 d = *dst;				\
   433 	    s = (s | s << 16) & 0x07e0f81f;		\
   434 	    d = (d | d << 16) & 0x07e0f81f;		\
   435 	    d += (s - d) * ALPHA >> 5;			\
   436 	    d &= 0x07e0f81f;				\
   437 	    *dst++ = d | d >> 16;			\
   438 	}						\
   439     } while(0)
   440 
   441 #define ALPHA_BLIT16_555(to, from, length, bpp, alpha)	\
   442     do {						\
   443         int i;						\
   444 	Uint16 *src = (Uint16 *)(from);			\
   445 	Uint16 *dst = (Uint16 *)(to);			\
   446 	Uint32 ALPHA = alpha >> 3;			\
   447 	for(i = 0; i < (int)(length); i++) {		\
   448 	    Uint32 s = *src++;				\
   449 	    Uint32 d = *dst;				\
   450 	    s = (s | s << 16) & 0x03e07c1f;		\
   451 	    d = (d | d << 16) & 0x03e07c1f;		\
   452 	    d += (s - d) * ALPHA >> 5;			\
   453 	    d &= 0x03e07c1f;				\
   454 	    *dst++ = d | d >> 16;			\
   455 	}						\
   456     } while(0)
   457 
   458 /*
   459  * The general slow catch-all function, for remaining depths and formats
   460  */
   461 #define ALPHA_BLIT_ANY(to, from, length, bpp, alpha)			\
   462     do {								\
   463         int i;								\
   464 	Uint8 *src = from;						\
   465 	Uint8 *dst = to;						\
   466 	for(i = 0; i < (int)(length); i++) {				\
   467 	    Uint32 s, d;						\
   468 	    unsigned rs, gs, bs, rd, gd, bd;				\
   469 	    switch(bpp) {						\
   470 	    case 2:							\
   471 		s = *(Uint16 *)src;					\
   472 		d = *(Uint16 *)dst;					\
   473 		break;							\
   474 	    case 3:							\
   475 		if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {			\
   476 		    s = (src[0] << 16) | (src[1] << 8) | src[2];	\
   477 		    d = (dst[0] << 16) | (dst[1] << 8) | dst[2];	\
   478 		} else {						\
   479 		    s = (src[2] << 16) | (src[1] << 8) | src[0];	\
   480 		    d = (dst[2] << 16) | (dst[1] << 8) | dst[0];	\
   481 		}							\
   482 		break;							\
   483 	    case 4:							\
   484 		s = *(Uint32 *)src;					\
   485 		d = *(Uint32 *)dst;					\
   486 		break;							\
   487 	    }								\
   488 	    RGB_FROM_PIXEL(s, fmt, rs, gs, bs);				\
   489 	    RGB_FROM_PIXEL(d, fmt, rd, gd, bd);				\
   490 	    rd += (rs - rd) * alpha >> 8;				\
   491 	    gd += (gs - gd) * alpha >> 8;				\
   492 	    bd += (bs - bd) * alpha >> 8;				\
   493 	    PIXEL_FROM_RGB(d, fmt, rd, gd, bd);				\
   494 	    switch(bpp) {						\
   495 	    case 2:							\
   496 		*(Uint16 *)dst = d;					\
   497 		break;							\
   498 	    case 3:							\
   499 		if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {			\
   500 		    dst[0] = d >> 16;					\
   501 		    dst[1] = d >> 8;					\
   502 		    dst[2] = d;						\
   503 		} else {						\
   504 		    dst[0] = d;						\
   505 		    dst[1] = d >> 8;					\
   506 		    dst[2] = d >> 16;					\
   507 		}							\
   508 		break;							\
   509 	    case 4:							\
   510 		*(Uint32 *)dst = d;					\
   511 		break;							\
   512 	    }								\
   513 	    src += bpp;							\
   514 	    dst += bpp;							\
   515 	}								\
   516     } while(0)
   517 
   518 #ifdef MMX_ASMBLIT
   519 
   520 #define ALPHA_BLIT32_888_50MMX(to, from, length, bpp, alpha)		\
   521     do {								\
   522 	Uint32 *srcp = (Uint32 *)(from);				\
   523 	Uint32 *dstp = (Uint32 *)(to);					\
   524         int i = 0x00fefefe;						\
   525         movd_m2r(*(&i), mm4);						\
   526         punpckldq_r2r(mm4, mm4);					\
   527         i = 0x00010101;							\
   528         movd_m2r(*(&i), mm3);						\
   529         punpckldq_r2r(mm3, mm3);					\
   530         i = (int)(length);						\
   531         if( i & 1 ) {							\
   532 	  Uint32 s = *srcp++;						\
   533 	  Uint32 d = *dstp;						\
   534 	  *dstp++ = (((s & 0x00fefefe) + (d & 0x00fefefe)) >> 1)	\
   535 		     + (s & d & 0x00010101);				\
   536 	  i--;								\
   537 	}								\
   538 	for(; i > 0; --i) {						\
   539 	    movq_m2r((*dstp), mm2); /* dst -> mm2 */			\
   540 	    movq_r2r(mm2, mm6);	/* dst -> mm6 */			\
   541 	    movq_m2r((*srcp), mm1); /* src -> mm1 */			\
   542 	    movq_r2r(mm1, mm5);	/* src -> mm5 */			\
   543 	    pand_r2r(mm4, mm6);	/* dst & 0x00fefefe -> mm6 */		\
   544 	    pand_r2r(mm4, mm5); /* src & 0x00fefefe -> mm5 */		\
   545 	    paddd_r2r(mm6, mm5); /* (dst & 0x00fefefe) + (dst & 0x00fefefe) -> mm5 */	\
   546 	    psrld_i2r(1, mm5);						\
   547 	    pand_r2r(mm1, mm2);	/* s & d -> mm2 */			\
   548 	    pand_r2r(mm3, mm2);	/* s & d & 0x00010101 -> mm2 */		\
   549 	    paddd_r2r(mm5, mm2);					\
   550 	    movq_r2m(mm2, (*dstp));					\
   551 	    dstp += 2;							\
   552 	    srcp += 2;							\
   553 	    i--;							\
   554 	}								\
   555 	emms();								\
   556     } while(0)
   557 
   558 #endif
   559     
   560 /*
   561  * Special case: 50% alpha (alpha=128)
   562  * This is treated specially because it can be optimized very well, and
   563  * since it is good for many cases of semi-translucency.
   564  * The theory is to do all three components at the same time:
   565  * First zero the lowest bit of each component, which gives us room to
   566  * add them. Then shift right and add the sum of the lowest bits.
   567  */
   568 #define ALPHA_BLIT32_888_50(to, from, length, bpp, alpha)		\
   569     do {								\
   570         int i;								\
   571 	Uint32 *src = (Uint32 *)(from);					\
   572 	Uint32 *dst = (Uint32 *)(to);					\
   573 	for(i = 0; i < (int)(length); i++) {				\
   574 	    Uint32 s = *src++;						\
   575 	    Uint32 d = *dst;						\
   576 	    *dst++ = (((s & 0x00fefefe) + (d & 0x00fefefe)) >> 1)	\
   577 		     + (s & d & 0x00010101);				\
   578 	}								\
   579     } while(0)
   580 
   581 /*
   582  * For 16bpp, we can actually blend two pixels in parallel, if we take
   583  * care to shift before we add, not after.
   584  */
   585 
   586 /* helper: blend a single 16 bit pixel at 50% */
   587 #define BLEND16_50(dst, src, mask)			\
   588     do {						\
   589         Uint32 s = *src++;				\
   590 	Uint32 d = *dst;				\
   591 	*dst++ = (((s & mask) + (d & mask)) >> 1)	\
   592 	         + (s & d & (~mask & 0xffff));		\
   593     } while(0)
   594 
   595 /* basic 16bpp blender. mask is the pixels to keep when adding. */
   596 #define ALPHA_BLIT16_50(to, from, length, bpp, alpha, mask)		\
   597     do {								\
   598 	unsigned n = (length);						\
   599 	Uint16 *src = (Uint16 *)(from);					\
   600 	Uint16 *dst = (Uint16 *)(to);					\
   601 	if(((unsigned long)src ^ (unsigned long)dst) & 3) {		\
   602 	    /* source and destination not in phase, blit one by one */	\
   603 	    while(n--)							\
   604 		BLEND16_50(dst, src, mask);				\
   605 	} else {							\
   606 	    if((unsigned long)src & 3) {				\
   607 		/* first odd pixel */					\
   608 		BLEND16_50(dst, src, mask);				\
   609 		n--;							\
   610 	    }								\
   611 	    for(; n > 1; n -= 2) {					\
   612 		Uint32 s = *(Uint32 *)src;				\
   613 		Uint32 d = *(Uint32 *)dst;				\
   614 		*(Uint32 *)dst = ((s & (mask | mask << 16)) >> 1)	\
   615 		               + ((d & (mask | mask << 16)) >> 1)	\
   616 		               + (s & d & (~(mask | mask << 16)));	\
   617 		src += 2;						\
   618 		dst += 2;						\
   619 	    }								\
   620 	    if(n)							\
   621 		BLEND16_50(dst, src, mask); /* last odd pixel */	\
   622 	}								\
   623     } while(0)
   624 
   625 #define ALPHA_BLIT16_565_50(to, from, length, bpp, alpha)	\
   626     ALPHA_BLIT16_50(to, from, length, bpp, alpha, 0xf7de)
   627 
   628 #define ALPHA_BLIT16_555_50(to, from, length, bpp, alpha)	\
   629     ALPHA_BLIT16_50(to, from, length, bpp, alpha, 0xfbde)
   630 
   631 #ifdef MMX_ASMBLIT
   632 
   633 #define CHOOSE_BLIT(blitter, alpha, fmt)				\
   634     do {								\
   635         if(alpha == 255) {						\
   636 	    switch(fmt->BytesPerPixel) {				\
   637 	    case 1: blitter(1, Uint8, OPAQUE_BLIT); break;		\
   638 	    case 2: blitter(2, Uint8, OPAQUE_BLIT); break;		\
   639 	    case 3: blitter(3, Uint8, OPAQUE_BLIT); break;		\
   640 	    case 4: blitter(4, Uint16, OPAQUE_BLIT); break;		\
   641 	    }								\
   642 	} else {							\
   643 	    switch(fmt->BytesPerPixel) {				\
   644 	    case 1:							\
   645 		/* No 8bpp alpha blitting */				\
   646 		break;							\
   647 									\
   648 	    case 2:							\
   649 		switch(fmt->Rmask | fmt->Gmask | fmt->Bmask) {		\
   650 		case 0xffff:						\
   651 		    if(fmt->Gmask == 0x07e0				\
   652 		       || fmt->Rmask == 0x07e0				\
   653 		       || fmt->Bmask == 0x07e0) {			\
   654 			if(alpha == 128)				\
   655 			    blitter(2, Uint8, ALPHA_BLIT16_565_50);	\
   656 			else {						\
   657 			    if(SDL_HasMMX())				\
   658 				blitter(2, Uint8, ALPHA_BLIT16_565MMX);	\
   659 			    else					\
   660 				blitter(2, Uint8, ALPHA_BLIT16_565);	\
   661 			}						\
   662 		    } else						\
   663 			goto general16;					\
   664 		    break;						\
   665 									\
   666 		case 0x7fff:						\
   667 		    if(fmt->Gmask == 0x03e0				\
   668 		       || fmt->Rmask == 0x03e0				\
   669 		       || fmt->Bmask == 0x03e0) {			\
   670 			if(alpha == 128)				\
   671 			    blitter(2, Uint8, ALPHA_BLIT16_555_50);	\
   672 			else {						\
   673 			    if(SDL_HasMMX())				\
   674 				blitter(2, Uint8, ALPHA_BLIT16_555MMX);	\
   675 			    else					\
   676 				blitter(2, Uint8, ALPHA_BLIT16_555);	\
   677 			}						\
   678 			break;						\
   679 		    }							\
   680 		    /* fallthrough */					\
   681 									\
   682 		default:						\
   683 		general16:						\
   684 		    blitter(2, Uint8, ALPHA_BLIT_ANY);			\
   685 		}							\
   686 		break;							\
   687 									\
   688 	    case 3:							\
   689 		blitter(3, Uint8, ALPHA_BLIT_ANY);			\
   690 		break;							\
   691 									\
   692 	    case 4:							\
   693 		if((fmt->Rmask | fmt->Gmask | fmt->Bmask) == 0x00ffffff	\
   694 		   && (fmt->Gmask == 0xff00 || fmt->Rmask == 0xff00	\
   695 		       || fmt->Bmask == 0xff00)) {			\
   696 		    if(alpha == 128)					\
   697 		    {							\
   698 			if(SDL_HasMMX())				\
   699 				blitter(4, Uint16, ALPHA_BLIT32_888_50MMX);\
   700 			else						\
   701 				blitter(4, Uint16, ALPHA_BLIT32_888_50);\
   702 		    }							\
   703 		    else						\
   704 		    {							\
   705 			if(SDL_HasMMX())				\
   706 				blitter(4, Uint16, ALPHA_BLIT32_888MMX);\
   707 			else						\
   708 				blitter(4, Uint16, ALPHA_BLIT32_888);	\
   709 		    }							\
   710 		} else							\
   711 		    blitter(4, Uint16, ALPHA_BLIT_ANY);			\
   712 		break;							\
   713 	    }								\
   714 	}								\
   715     } while(0)
   716 
   717 #else
   718 	
   719 #define CHOOSE_BLIT(blitter, alpha, fmt)				\
   720     do {								\
   721         if(alpha == 255) {						\
   722 	    switch(fmt->BytesPerPixel) {				\
   723 	    case 1: blitter(1, Uint8, OPAQUE_BLIT); break;		\
   724 	    case 2: blitter(2, Uint8, OPAQUE_BLIT); break;		\
   725 	    case 3: blitter(3, Uint8, OPAQUE_BLIT); break;		\
   726 	    case 4: blitter(4, Uint16, OPAQUE_BLIT); break;		\
   727 	    }								\
   728 	} else {							\
   729 	    switch(fmt->BytesPerPixel) {				\
   730 	    case 1:							\
   731 		/* No 8bpp alpha blitting */				\
   732 		break;							\
   733 									\
   734 	    case 2:							\
   735 		switch(fmt->Rmask | fmt->Gmask | fmt->Bmask) {		\
   736 		case 0xffff:						\
   737 		    if(fmt->Gmask == 0x07e0				\
   738 		       || fmt->Rmask == 0x07e0				\
   739 		       || fmt->Bmask == 0x07e0) {			\
   740 			if(alpha == 128)				\
   741 			    blitter(2, Uint8, ALPHA_BLIT16_565_50);	\
   742 			else {						\
   743 			    blitter(2, Uint8, ALPHA_BLIT16_565);	\
   744 			}						\
   745 		    } else						\
   746 			goto general16;					\
   747 		    break;						\
   748 									\
   749 		case 0x7fff:						\
   750 		    if(fmt->Gmask == 0x03e0				\
   751 		       || fmt->Rmask == 0x03e0				\
   752 		       || fmt->Bmask == 0x03e0) {			\
   753 			if(alpha == 128)				\
   754 			    blitter(2, Uint8, ALPHA_BLIT16_555_50);	\
   755 			else {						\
   756 			    blitter(2, Uint8, ALPHA_BLIT16_555);	\
   757 			}						\
   758 			break;						\
   759 		    }							\
   760 		    /* fallthrough */					\
   761 									\
   762 		default:						\
   763 		general16:						\
   764 		    blitter(2, Uint8, ALPHA_BLIT_ANY);			\
   765 		}							\
   766 		break;							\
   767 									\
   768 	    case 3:							\
   769 		blitter(3, Uint8, ALPHA_BLIT_ANY);			\
   770 		break;							\
   771 									\
   772 	    case 4:							\
   773 		if((fmt->Rmask | fmt->Gmask | fmt->Bmask) == 0x00ffffff	\
   774 		   && (fmt->Gmask == 0xff00 || fmt->Rmask == 0xff00	\
   775 		       || fmt->Bmask == 0xff00)) {			\
   776 		    if(alpha == 128)					\
   777 			blitter(4, Uint16, ALPHA_BLIT32_888_50);	\
   778 		    else						\
   779 			blitter(4, Uint16, ALPHA_BLIT32_888);		\
   780 		} else							\
   781 		    blitter(4, Uint16, ALPHA_BLIT_ANY);			\
   782 		break;							\
   783 	    }								\
   784 	}								\
   785     } while(0)
   786 
   787 #endif
   788 
   789 /*
   790  * This takes care of the case when the surface is clipped on the left and/or
   791  * right. Top clipping has already been taken care of.
   792  */
   793 static void RLEClipBlit(int w, Uint8 *srcbuf, SDL_Surface *dst,
   794 			Uint8 *dstbuf, SDL_Rect *srcrect, unsigned alpha)
   795 {
   796     SDL_PixelFormat *fmt = dst->format;
   797 
   798 #define RLECLIPBLIT(bpp, Type, do_blit)					   \
   799     do {								   \
   800 	int linecount = srcrect->h;					   \
   801 	int ofs = 0;							   \
   802 	int left = srcrect->x;						   \
   803 	int right = left + srcrect->w;					   \
   804 	dstbuf -= left * bpp;						   \
   805 	for(;;) {							   \
   806 	    int run;							   \
   807 	    ofs += *(Type *)srcbuf;					   \
   808 	    run = ((Type *)srcbuf)[1];					   \
   809 	    srcbuf += 2 * sizeof(Type);					   \
   810 	    if(run) {							   \
   811 		/* clip to left and right borders */			   \
   812 		if(ofs < right) {					   \
   813 		    int start = 0;					   \
   814 		    int len = run;					   \
   815 		    int startcol;					   \
   816 		    if(left - ofs > 0) {				   \
   817 			start = left - ofs;				   \
   818 			len -= start;					   \
   819 			if(len <= 0)					   \
   820 			    goto nocopy ## bpp ## do_blit;		   \
   821 		    }							   \
   822 		    startcol = ofs + start;				   \
   823 		    if(len > right - startcol)				   \
   824 			len = right - startcol;				   \
   825 		    do_blit(dstbuf + startcol * bpp, srcbuf + start * bpp, \
   826 			    len, bpp, alpha);				   \
   827 		}							   \
   828 	    nocopy ## bpp ## do_blit:					   \
   829 		srcbuf += run * bpp;					   \
   830 		ofs += run;						   \
   831 	    } else if(!ofs)						   \
   832 		break;							   \
   833 	    if(ofs == w) {						   \
   834 		ofs = 0;						   \
   835 		dstbuf += dst->pitch;					   \
   836 		if(!--linecount)					   \
   837 		    break;						   \
   838 	    }								   \
   839 	}								   \
   840     } while(0)
   841 
   842     CHOOSE_BLIT(RLECLIPBLIT, alpha, fmt);
   843 
   844 #undef RLECLIPBLIT
   845 
   846 }
   847 
   848 
   849 /* blit a colorkeyed RLE surface */
   850 int SDL_RLEBlit(SDL_Surface *src, SDL_Rect *srcrect,
   851 		SDL_Surface *dst, SDL_Rect *dstrect)
   852 {
   853 	Uint8 *dstbuf;
   854 	Uint8 *srcbuf;
   855 	int x, y;
   856 	int w = src->w;
   857 	unsigned alpha;
   858 
   859 	/* Lock the destination if necessary */
   860 	if ( SDL_MUSTLOCK(dst) ) {
   861 		if ( SDL_LockSurface(dst) < 0 ) {
   862 			return(-1);
   863 		}
   864 	}
   865 
   866 	/* Set up the source and destination pointers */
   867 	x = dstrect->x;
   868 	y = dstrect->y;
   869 	dstbuf = (Uint8 *)dst->pixels
   870 	         + y * dst->pitch + x * src->format->BytesPerPixel;
   871 	srcbuf = (Uint8 *)src->map->sw_data->aux_data;
   872 
   873 	{
   874 	    /* skip lines at the top if neccessary */
   875 	    int vskip = srcrect->y;
   876 	    int ofs = 0;
   877 	    if(vskip) {
   878 
   879 #define RLESKIP(bpp, Type)			\
   880 		for(;;) {			\
   881 		    int run;			\
   882 		    ofs += *(Type *)srcbuf;	\
   883 		    run = ((Type *)srcbuf)[1];	\
   884 		    srcbuf += sizeof(Type) * 2;	\
   885 		    if(run) {			\
   886 			srcbuf += run * bpp;	\
   887 			ofs += run;		\
   888 		    } else if(!ofs)		\
   889 			goto done;		\
   890 		    if(ofs == w) {		\
   891 			ofs = 0;		\
   892 			if(!--vskip)		\
   893 			    break;		\
   894 		    }				\
   895 		}
   896 
   897 		switch(src->format->BytesPerPixel) {
   898 		case 1: RLESKIP(1, Uint8); break;
   899 		case 2: RLESKIP(2, Uint8); break;
   900 		case 3: RLESKIP(3, Uint8); break;
   901 		case 4: RLESKIP(4, Uint16); break;
   902 		}
   903 
   904 #undef RLESKIP
   905 
   906 	    }
   907 	}
   908 
   909 	alpha = (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA
   910 	        ? src->format->alpha : 255;
   911 	/* if left or right edge clipping needed, call clip blit */
   912 	if ( srcrect->x || srcrect->w != src->w ) {
   913 	    RLEClipBlit(w, srcbuf, dst, dstbuf, srcrect, alpha);
   914 	} else {
   915 	    SDL_PixelFormat *fmt = src->format;
   916 
   917 #define RLEBLIT(bpp, Type, do_blit)					      \
   918 	    do {							      \
   919 		int linecount = srcrect->h;				      \
   920 		int ofs = 0;						      \
   921 		for(;;) {						      \
   922 		    unsigned run;					      \
   923 		    ofs += *(Type *)srcbuf;				      \
   924 		    run = ((Type *)srcbuf)[1];				      \
   925 		    srcbuf += 2 * sizeof(Type);				      \
   926 		    if(run) {						      \
   927 			do_blit(dstbuf + ofs * bpp, srcbuf, run, bpp, alpha); \
   928 			srcbuf += run * bpp;				      \
   929 			ofs += run;					      \
   930 		    } else if(!ofs)					      \
   931 			break;						      \
   932 		    if(ofs == w) {					      \
   933 			ofs = 0;					      \
   934 			dstbuf += dst->pitch;				      \
   935 			if(!--linecount)				      \
   936 			    break;					      \
   937 		    }							      \
   938 		}							      \
   939 	    } while(0)
   940 
   941 	    CHOOSE_BLIT(RLEBLIT, alpha, fmt);
   942 
   943 #undef RLEBLIT
   944 	}
   945 
   946 done:
   947 	/* Unlock the destination if necessary */
   948 	if ( SDL_MUSTLOCK(dst) ) {
   949 		SDL_UnlockSurface(dst);
   950 	}
   951 	return(0);
   952 }
   953 
   954 #undef OPAQUE_BLIT
   955 
   956 /*
   957  * Per-pixel blitting macros for translucent pixels:
   958  * These use the same techniques as the per-surface blitting macros
   959  */
   960 
   961 /*
   962  * For 32bpp pixels, we have made sure the alpha is stored in the top
   963  * 8 bits, so proceed as usual
   964  */
   965 #define BLIT_TRANSL_888(src, dst)				\
   966     do {							\
   967         Uint32 s = src;						\
   968 	Uint32 d = dst;						\
   969 	unsigned alpha = s >> 24;				\
   970 	Uint32 s1 = s & 0xff00ff;				\
   971 	Uint32 d1 = d & 0xff00ff;				\
   972 	d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff;	\
   973 	s &= 0xff00;						\
   974 	d &= 0xff00;						\
   975 	d = (d + ((s - d) * alpha >> 8)) & 0xff00;		\
   976 	dst = d1 | d;						\
   977     } while(0)
   978 
   979 /*
   980  * For 16bpp pixels, we have stored the 5 most significant alpha bits in
   981  * bits 5-10. As before, we can process all 3 RGB components at the same time.
   982  */
   983 #define BLIT_TRANSL_565(src, dst)		\
   984     do {					\
   985         Uint32 s = src;				\
   986 	Uint32 d = dst;				\
   987 	unsigned alpha = (s & 0x3e0) >> 5;	\
   988 	s &= 0x07e0f81f;			\
   989 	d = (d | d << 16) & 0x07e0f81f;		\
   990 	d += (s - d) * alpha >> 5;		\
   991 	d &= 0x07e0f81f;			\
   992 	dst = d | d >> 16;			\
   993     } while(0)
   994 
   995 #define BLIT_TRANSL_555(src, dst)		\
   996     do {					\
   997         Uint32 s = src;				\
   998 	Uint32 d = dst;				\
   999 	unsigned alpha = (s & 0x3e0) >> 5;	\
  1000 	s &= 0x03e07c1f;			\
  1001 	d = (d | d << 16) & 0x03e07c1f;		\
  1002 	d += (s - d) * alpha >> 5;		\
  1003 	d &= 0x03e07c1f;			\
  1004 	dst = d | d >> 16;			\
  1005     } while(0)
  1006 
  1007 /* used to save the destination format in the encoding. Designed to be
  1008    macro-compatible with SDL_PixelFormat but without the unneeded fields */
  1009 typedef struct {
  1010     	Uint8  BytesPerPixel;
  1011 	Uint8  Rloss;
  1012 	Uint8  Gloss;
  1013 	Uint8  Bloss;
  1014 	Uint8  Rshift;
  1015 	Uint8  Gshift;
  1016 	Uint8  Bshift;
  1017 	Uint8  Ashift;
  1018 	Uint32 Rmask;
  1019 	Uint32 Gmask;
  1020 	Uint32 Bmask;
  1021 	Uint32 Amask;
  1022 } RLEDestFormat;
  1023 
  1024 /* blit a pixel-alpha RLE surface clipped at the right and/or left edges */
  1025 static void RLEAlphaClipBlit(int w, Uint8 *srcbuf, SDL_Surface *dst,
  1026 			     Uint8 *dstbuf, SDL_Rect *srcrect)
  1027 {
  1028     SDL_PixelFormat *df = dst->format;
  1029     /*
  1030      * clipped blitter: Ptype is the destination pixel type,
  1031      * Ctype the translucent count type, and do_blend the macro
  1032      * to blend one pixel.
  1033      */
  1034 #define RLEALPHACLIPBLIT(Ptype, Ctype, do_blend)			  \
  1035     do {								  \
  1036 	int linecount = srcrect->h;					  \
  1037 	int left = srcrect->x;						  \
  1038 	int right = left + srcrect->w;					  \
  1039 	dstbuf -= left * sizeof(Ptype);					  \
  1040 	do {								  \
  1041 	    int ofs = 0;						  \
  1042 	    /* blit opaque pixels on one line */			  \
  1043 	    do {							  \
  1044 		unsigned run;						  \
  1045 		ofs += ((Ctype *)srcbuf)[0];				  \
  1046 		run = ((Ctype *)srcbuf)[1];				  \
  1047 		srcbuf += 2 * sizeof(Ctype);				  \
  1048 		if(run) {						  \
  1049 		    /* clip to left and right borders */		  \
  1050 		    int cofs = ofs;					  \
  1051 		    int crun = run;					  \
  1052 		    if(left - cofs > 0) {				  \
  1053 			crun -= left - cofs;				  \
  1054 			cofs = left;					  \
  1055 		    }							  \
  1056 		    if(crun > right - cofs)				  \
  1057 			crun = right - cofs;				  \
  1058 		    if(crun > 0)					  \
  1059 			PIXEL_COPY(dstbuf + cofs * sizeof(Ptype),	  \
  1060 				   srcbuf + (cofs - ofs) * sizeof(Ptype), \
  1061 				   (unsigned)crun, sizeof(Ptype));	  \
  1062 		    srcbuf += run * sizeof(Ptype);			  \
  1063 		    ofs += run;						  \
  1064 		} else if(!ofs)						  \
  1065 		    return;						  \
  1066 	    } while(ofs < w);						  \
  1067 	    /* skip padding if necessary */				  \
  1068 	    if(sizeof(Ptype) == 2)					  \
  1069 		srcbuf += (unsigned long)srcbuf & 2;			  \
  1070 	    /* blit translucent pixels on the same line */		  \
  1071 	    ofs = 0;							  \
  1072 	    do {							  \
  1073 		unsigned run;						  \
  1074 		ofs += ((Uint16 *)srcbuf)[0];				  \
  1075 		run = ((Uint16 *)srcbuf)[1];				  \
  1076 		srcbuf += 4;						  \
  1077 		if(run) {						  \
  1078 		    /* clip to left and right borders */		  \
  1079 		    int cofs = ofs;					  \
  1080 		    int crun = run;					  \
  1081 		    if(left - cofs > 0) {				  \
  1082 			crun -= left - cofs;				  \
  1083 			cofs = left;					  \
  1084 		    }							  \
  1085 		    if(crun > right - cofs)				  \
  1086 			crun = right - cofs;				  \
  1087 		    if(crun > 0) {					  \
  1088 			Ptype *dst = (Ptype *)dstbuf + cofs;		  \
  1089 			Uint32 *src = (Uint32 *)srcbuf + (cofs - ofs);	  \
  1090 			int i;						  \
  1091 			for(i = 0; i < crun; i++)			  \
  1092 			    do_blend(src[i], dst[i]);			  \
  1093 		    }							  \
  1094 		    srcbuf += run * 4;					  \
  1095 		    ofs += run;						  \
  1096 		}							  \
  1097 	    } while(ofs < w);						  \
  1098 	    dstbuf += dst->pitch;					  \
  1099 	} while(--linecount);						  \
  1100     } while(0)
  1101 
  1102     switch(df->BytesPerPixel) {
  1103     case 2:
  1104 	if(df->Gmask == 0x07e0 || df->Rmask == 0x07e0
  1105 	   || df->Bmask == 0x07e0)
  1106 	    RLEALPHACLIPBLIT(Uint16, Uint8, BLIT_TRANSL_565);
  1107 	else
  1108 	    RLEALPHACLIPBLIT(Uint16, Uint8, BLIT_TRANSL_555);
  1109 	break;
  1110     case 4:
  1111 	RLEALPHACLIPBLIT(Uint32, Uint16, BLIT_TRANSL_888);
  1112 	break;
  1113     }
  1114 }
  1115 
  1116 /* blit a pixel-alpha RLE surface */
  1117 int SDL_RLEAlphaBlit(SDL_Surface *src, SDL_Rect *srcrect,
  1118 		     SDL_Surface *dst, SDL_Rect *dstrect)
  1119 {
  1120     int x, y;
  1121     int w = src->w;
  1122     Uint8 *srcbuf, *dstbuf;
  1123     SDL_PixelFormat *df = dst->format;
  1124 
  1125     /* Lock the destination if necessary */
  1126     if ( SDL_MUSTLOCK(dst) ) {
  1127 	if ( SDL_LockSurface(dst) < 0 ) {
  1128 	    return -1;
  1129 	}
  1130     }
  1131 
  1132     x = dstrect->x;
  1133     y = dstrect->y;
  1134     dstbuf = (Uint8 *)dst->pixels
  1135 	     + y * dst->pitch + x * df->BytesPerPixel;
  1136     srcbuf = (Uint8 *)src->map->sw_data->aux_data + sizeof(RLEDestFormat);
  1137 
  1138     {
  1139 	/* skip lines at the top if necessary */
  1140 	int vskip = srcrect->y;
  1141 	if(vskip) {
  1142 	    int ofs;
  1143 	    if(df->BytesPerPixel == 2) {
  1144 		/* the 16/32 interleaved format */
  1145 		do {
  1146 		    /* skip opaque line */
  1147 		    ofs = 0;
  1148 		    do {
  1149 			int run;
  1150 			ofs += srcbuf[0];
  1151 			run = srcbuf[1];
  1152 			srcbuf += 2;
  1153 			if(run) {
  1154 			    srcbuf += 2 * run;
  1155 			    ofs += run;
  1156 			} else if(!ofs)
  1157 			    goto done;
  1158 		    } while(ofs < w);
  1159 
  1160 		    /* skip padding */
  1161 		    srcbuf += (unsigned long)srcbuf & 2;
  1162 
  1163 		    /* skip translucent line */
  1164 		    ofs = 0;
  1165 		    do {
  1166 			int run;
  1167 			ofs += ((Uint16 *)srcbuf)[0];
  1168 			run = ((Uint16 *)srcbuf)[1];
  1169 			srcbuf += 4 * (run + 1);
  1170 			ofs += run;
  1171 		    } while(ofs < w);
  1172 		} while(--vskip);
  1173 	    } else {
  1174 		/* the 32/32 interleaved format */
  1175 		vskip <<= 1;	/* opaque and translucent have same format */
  1176 		do {
  1177 		    ofs = 0;
  1178 		    do {
  1179 			int run;
  1180 			ofs += ((Uint16 *)srcbuf)[0];
  1181 			run = ((Uint16 *)srcbuf)[1];
  1182 			srcbuf += 4;
  1183 			if(run) {
  1184 			    srcbuf += 4 * run;
  1185 			    ofs += run;
  1186 			} else if(!ofs)
  1187 			    goto done;
  1188 		    } while(ofs < w);
  1189 		} while(--vskip);
  1190 	    }
  1191 	}
  1192     }
  1193 
  1194     /* if left or right edge clipping needed, call clip blit */
  1195     if(srcrect->x || srcrect->w != src->w) {
  1196 	RLEAlphaClipBlit(w, srcbuf, dst, dstbuf, srcrect);
  1197     } else {
  1198 
  1199 	/*
  1200 	 * non-clipped blitter. Ptype is the destination pixel type,
  1201 	 * Ctype the translucent count type, and do_blend the
  1202 	 * macro to blend one pixel.
  1203 	 */
  1204 #define RLEALPHABLIT(Ptype, Ctype, do_blend)				 \
  1205 	do {								 \
  1206 	    int linecount = srcrect->h;					 \
  1207 	    do {							 \
  1208 		int ofs = 0;						 \
  1209 		/* blit opaque pixels on one line */			 \
  1210 		do {							 \
  1211 		    unsigned run;					 \
  1212 		    ofs += ((Ctype *)srcbuf)[0];			 \
  1213 		    run = ((Ctype *)srcbuf)[1];				 \
  1214 		    srcbuf += 2 * sizeof(Ctype);			 \
  1215 		    if(run) {						 \
  1216 			PIXEL_COPY(dstbuf + ofs * sizeof(Ptype), srcbuf, \
  1217 				   run, sizeof(Ptype));			 \
  1218 			srcbuf += run * sizeof(Ptype);			 \
  1219 			ofs += run;					 \
  1220 		    } else if(!ofs)					 \
  1221 			goto done;					 \
  1222 		} while(ofs < w);					 \
  1223 		/* skip padding if necessary */				 \
  1224 		if(sizeof(Ptype) == 2)					 \
  1225 		    srcbuf += (unsigned long)srcbuf & 2;		 \
  1226 		/* blit translucent pixels on the same line */		 \
  1227 		ofs = 0;						 \
  1228 		do {							 \
  1229 		    unsigned run;					 \
  1230 		    ofs += ((Uint16 *)srcbuf)[0];			 \
  1231 		    run = ((Uint16 *)srcbuf)[1];			 \
  1232 		    srcbuf += 4;					 \
  1233 		    if(run) {						 \
  1234 			Ptype *dst = (Ptype *)dstbuf + ofs;		 \
  1235 			unsigned i;					 \
  1236 			for(i = 0; i < run; i++) {			 \
  1237 			    Uint32 src = *(Uint32 *)srcbuf;		 \
  1238 			    do_blend(src, *dst);			 \
  1239 			    srcbuf += 4;				 \
  1240 			    dst++;					 \
  1241 			}						 \
  1242 			ofs += run;					 \
  1243 		    }							 \
  1244 		} while(ofs < w);					 \
  1245 		dstbuf += dst->pitch;					 \
  1246 	    } while(--linecount);					 \
  1247 	} while(0)
  1248 
  1249 	switch(df->BytesPerPixel) {
  1250 	case 2:
  1251 	    if(df->Gmask == 0x07e0 || df->Rmask == 0x07e0
  1252 	       || df->Bmask == 0x07e0)
  1253 		RLEALPHABLIT(Uint16, Uint8, BLIT_TRANSL_565);
  1254 	    else
  1255 		RLEALPHABLIT(Uint16, Uint8, BLIT_TRANSL_555);
  1256 	    break;
  1257 	case 4:
  1258 	    RLEALPHABLIT(Uint32, Uint16, BLIT_TRANSL_888);
  1259 	    break;
  1260 	}
  1261     }
  1262 
  1263  done:
  1264     /* Unlock the destination if necessary */
  1265     if ( SDL_MUSTLOCK(dst) ) {
  1266 	SDL_UnlockSurface(dst);
  1267     }
  1268     return 0;
  1269 }
  1270 
  1271 /*
  1272  * Auxiliary functions:
  1273  * The encoding functions take 32bpp rgb + a, and
  1274  * return the number of bytes copied to the destination.
  1275  * The decoding functions copy to 32bpp rgb + a, and
  1276  * return the number of bytes copied from the source.
  1277  * These are only used in the encoder and un-RLE code and are therefore not
  1278  * highly optimised.
  1279  */
  1280 
  1281 /* encode 32bpp rgb + a into 16bpp rgb, losing alpha */
  1282 static int copy_opaque_16(void *dst, Uint32 *src, int n,
  1283 			  SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt)
  1284 {
  1285     int i;
  1286     Uint16 *d = dst;
  1287     for(i = 0; i < n; i++) {
  1288 	unsigned r, g, b;
  1289 	RGB_FROM_PIXEL(*src, sfmt, r, g, b);
  1290 	PIXEL_FROM_RGB(*d, dfmt, r, g, b);
  1291 	src++;
  1292 	d++;
  1293     }
  1294     return n * 2;
  1295 }
  1296 
  1297 /* decode opaque pixels from 16bpp to 32bpp rgb + a */
  1298 static int uncopy_opaque_16(Uint32 *dst, void *src, int n,
  1299 			    RLEDestFormat *sfmt, SDL_PixelFormat *dfmt)
  1300 {
  1301     int i;
  1302     Uint16 *s = src;
  1303     unsigned alpha = dfmt->Amask ? 255 : 0;
  1304     for(i = 0; i < n; i++) {
  1305 	unsigned r, g, b;
  1306 	RGB_FROM_PIXEL(*s, sfmt, r, g, b);
  1307 	PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, alpha);
  1308 	s++;
  1309 	dst++;
  1310     }
  1311     return n * 2;
  1312 }
  1313 
  1314 
  1315 
  1316 /* encode 32bpp rgb + a into 32bpp G0RAB format for blitting into 565 */
  1317 static int copy_transl_565(void *dst, Uint32 *src, int n,
  1318 			   SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt)
  1319 {
  1320     int i;
  1321     Uint32 *d = dst;
  1322     for(i = 0; i < n; i++) {
  1323 	unsigned r, g, b, a;
  1324 	Uint16 pix;
  1325 	RGBA_FROM_8888(*src, sfmt, r, g, b, a);
  1326 	PIXEL_FROM_RGB(pix, dfmt, r, g, b);
  1327 	*d = ((pix & 0x7e0) << 16) | (pix & 0xf81f) | ((a << 2) & 0x7e0);
  1328 	src++;
  1329 	d++;
  1330     }
  1331     return n * 4;
  1332 }
  1333 
  1334 /* encode 32bpp rgb + a into 32bpp G0RAB format for blitting into 555 */
  1335 static int copy_transl_555(void *dst, Uint32 *src, int n,
  1336 			   SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt)
  1337 {
  1338     int i;
  1339     Uint32 *d = dst;
  1340     for(i = 0; i < n; i++) {
  1341 	unsigned r, g, b, a;
  1342 	Uint16 pix;
  1343 	RGBA_FROM_8888(*src, sfmt, r, g, b, a);
  1344 	PIXEL_FROM_RGB(pix, dfmt, r, g, b);
  1345 	*d = ((pix & 0x3e0) << 16) | (pix & 0xfc1f) | ((a << 2) & 0x3e0);
  1346 	src++;
  1347 	d++;
  1348     }
  1349     return n * 4;
  1350 }
  1351 
  1352 /* decode translucent pixels from 32bpp GORAB to 32bpp rgb + a */
  1353 static int uncopy_transl_16(Uint32 *dst, void *src, int n,
  1354 			    RLEDestFormat *sfmt, SDL_PixelFormat *dfmt)
  1355 {
  1356     int i;
  1357     Uint32 *s = src;
  1358     for(i = 0; i < n; i++) {
  1359 	unsigned r, g, b, a;
  1360 	Uint32 pix = *s++;
  1361 	a = (pix & 0x3e0) >> 2;
  1362 	pix = (pix & ~0x3e0) | pix >> 16;
  1363 	RGB_FROM_PIXEL(pix, sfmt, r, g, b);
  1364 	PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, a);
  1365 	dst++;
  1366     }
  1367     return n * 4;
  1368 }
  1369 
  1370 /* encode 32bpp rgba into 32bpp rgba, keeping alpha (dual purpose) */
  1371 static int copy_32(void *dst, Uint32 *src, int n,
  1372 		   SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt)
  1373 {
  1374     int i;
  1375     Uint32 *d = dst;
  1376     for(i = 0; i < n; i++) {
  1377 	unsigned r, g, b, a;
  1378 	Uint32 pixel;
  1379 	RGBA_FROM_8888(*src, sfmt, r, g, b, a);
  1380 	PIXEL_FROM_RGB(pixel, dfmt, r, g, b);
  1381 	*d++ = pixel | a << 24;
  1382 	src++;
  1383     }
  1384     return n * 4;
  1385 }
  1386 
  1387 /* decode 32bpp rgba into 32bpp rgba, keeping alpha (dual purpose) */
  1388 static int uncopy_32(Uint32 *dst, void *src, int n,
  1389 		     RLEDestFormat *sfmt, SDL_PixelFormat *dfmt)
  1390 {
  1391     int i;
  1392     Uint32 *s = src;
  1393     for(i = 0; i < n; i++) {
  1394 	unsigned r, g, b, a;
  1395 	Uint32 pixel = *s++;
  1396 	RGB_FROM_PIXEL(pixel, sfmt, r, g, b);
  1397 	a = pixel >> 24;
  1398 	PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, a);
  1399 	dst++;
  1400     }
  1401     return n * 4;
  1402 }
  1403 
  1404 #define ISOPAQUE(pixel, fmt) ((((pixel) & fmt->Amask) >> fmt->Ashift) == 255)
  1405 
  1406 #define ISTRANSL(pixel, fmt)	\
  1407     ((unsigned)((((pixel) & fmt->Amask) >> fmt->Ashift) - 1U) < 254U)
  1408 
  1409 /* convert surface to be quickly alpha-blittable onto dest, if possible */
  1410 static int RLEAlphaSurface(SDL_Surface *surface)
  1411 {
  1412     SDL_Surface *dest;
  1413     SDL_PixelFormat *df;
  1414     int maxsize = 0;
  1415     int max_opaque_run;
  1416     int max_transl_run = 65535;
  1417     unsigned masksum;
  1418     Uint8 *rlebuf, *dst;
  1419     int (*copy_opaque)(void *, Uint32 *, int,
  1420 		       SDL_PixelFormat *, SDL_PixelFormat *);
  1421     int (*copy_transl)(void *, Uint32 *, int,
  1422 		       SDL_PixelFormat *, SDL_PixelFormat *);
  1423 
  1424     dest = surface->map->dst;
  1425     if(!dest)
  1426 	return -1;
  1427     df = dest->format;
  1428     if(surface->format->BitsPerPixel != 32)
  1429 	return -1;		/* only 32bpp source supported */
  1430 
  1431     /* find out whether the destination is one we support,
  1432        and determine the max size of the encoded result */
  1433     masksum = df->Rmask | df->Gmask | df->Bmask;
  1434     switch(df->BytesPerPixel) {
  1435     case 2:
  1436 	/* 16bpp: only support 565 and 555 formats */
  1437 	switch(masksum) {
  1438 	case 0xffff:
  1439 	    if(df->Gmask == 0x07e0
  1440 	       || df->Rmask == 0x07e0 || df->Bmask == 0x07e0) {
  1441 		copy_opaque = copy_opaque_16;
  1442 		copy_transl = copy_transl_565;
  1443 	    } else
  1444 		return -1;
  1445 	    break;
  1446 	case 0x7fff:
  1447 	    if(df->Gmask == 0x03e0
  1448 	       || df->Rmask == 0x03e0 || df->Bmask == 0x03e0) {
  1449 		copy_opaque = copy_opaque_16;
  1450 		copy_transl = copy_transl_555;
  1451 	    } else
  1452 		return -1;
  1453 	    break;
  1454 	default:
  1455 	    return -1;
  1456 	}
  1457 	max_opaque_run = 255;	/* runs stored as bytes */
  1458 
  1459 	/* worst case is alternating opaque and translucent pixels,
  1460 	   with room for alignment padding between lines */
  1461 	maxsize = surface->h * (2 + (4 + 2) * (surface->w + 1)) + 2;
  1462 	break;
  1463     case 4:
  1464 	if(masksum != 0x00ffffff)
  1465 	    return -1;		/* requires unused high byte */
  1466 	copy_opaque = copy_32;
  1467 	copy_transl = copy_32;
  1468 	max_opaque_run = 255;	/* runs stored as short ints */
  1469 
  1470 	/* worst case is alternating opaque and translucent pixels */
  1471 	maxsize = surface->h * 2 * 4 * (surface->w + 1) + 4;
  1472 	break;
  1473     default:
  1474 	return -1;		/* anything else unsupported right now */
  1475     }
  1476 
  1477     maxsize += sizeof(RLEDestFormat);
  1478     rlebuf = (Uint8 *)malloc(maxsize);
  1479     if(!rlebuf) {
  1480 	SDL_OutOfMemory();
  1481 	return -1;
  1482     }
  1483     {
  1484 	/* save the destination format so we can undo the encoding later */
  1485 	RLEDestFormat *r = (RLEDestFormat *)rlebuf;
  1486 	r->BytesPerPixel = df->BytesPerPixel;
  1487 	r->Rloss = df->Rloss;
  1488 	r->Gloss = df->Gloss;
  1489 	r->Bloss = df->Bloss;
  1490 	r->Rshift = df->Rshift;
  1491 	r->Gshift = df->Gshift;
  1492 	r->Bshift = df->Bshift;
  1493 	r->Ashift = df->Ashift;
  1494 	r->Rmask = df->Rmask;
  1495 	r->Gmask = df->Gmask;
  1496 	r->Bmask = df->Bmask;
  1497 	r->Amask = df->Amask;
  1498     }
  1499     dst = rlebuf + sizeof(RLEDestFormat);
  1500 
  1501     /* Do the actual encoding */
  1502     {
  1503 	int x, y;
  1504 	int h = surface->h, w = surface->w;
  1505 	SDL_PixelFormat *sf = surface->format;
  1506 	Uint32 *src = (Uint32 *)surface->pixels;
  1507 	Uint8 *lastline = dst;	/* end of last non-blank line */
  1508 
  1509 	/* opaque counts are 8 or 16 bits, depending on target depth */
  1510 #define ADD_OPAQUE_COUNTS(n, m)			\
  1511 	if(df->BytesPerPixel == 4) {		\
  1512 	    ((Uint16 *)dst)[0] = n;		\
  1513 	    ((Uint16 *)dst)[1] = m;		\
  1514 	    dst += 4;				\
  1515 	} else {				\
  1516 	    dst[0] = n;				\
  1517 	    dst[1] = m;				\
  1518 	    dst += 2;				\
  1519 	}
  1520 
  1521 	/* translucent counts are always 16 bit */
  1522 #define ADD_TRANSL_COUNTS(n, m)		\
  1523 	(((Uint16 *)dst)[0] = n, ((Uint16 *)dst)[1] = m, dst += 4)
  1524 
  1525 	for(y = 0; y < h; y++) {
  1526 	    int runstart, skipstart;
  1527 	    int blankline = 0;
  1528 	    /* First encode all opaque pixels of a scan line */
  1529 	    x = 0;
  1530 	    do {
  1531 		int run, skip, len;
  1532 		skipstart = x;
  1533 		while(x < w && !ISOPAQUE(src[x], sf))
  1534 		    x++;
  1535 		runstart = x;
  1536 		while(x < w && ISOPAQUE(src[x], sf))
  1537 		    x++;
  1538 		skip = runstart - skipstart;
  1539 		if(skip == w)
  1540 		    blankline = 1;
  1541 		run = x - runstart;
  1542 		while(skip > max_opaque_run) {
  1543 		    ADD_OPAQUE_COUNTS(max_opaque_run, 0);
  1544 		    skip -= max_opaque_run;
  1545 		}
  1546 		len = MIN(run, max_opaque_run);
  1547 		ADD_OPAQUE_COUNTS(skip, len);
  1548 		dst += copy_opaque(dst, src + runstart, len, sf, df);
  1549 		runstart += len;
  1550 		run -= len;
  1551 		while(run) {
  1552 		    len = MIN(run, max_opaque_run);
  1553 		    ADD_OPAQUE_COUNTS(0, len);
  1554 		    dst += copy_opaque(dst, src + runstart, len, sf, df);
  1555 		    runstart += len;
  1556 		    run -= len;
  1557 		}
  1558 	    } while(x < w);
  1559 
  1560 	    /* Make sure the next output address is 32-bit aligned */
  1561 	    dst += (unsigned long)dst & 2;
  1562 
  1563 	    /* Next, encode all translucent pixels of the same scan line */
  1564 	    x = 0;
  1565 	    do {
  1566 		int run, skip, len;
  1567 		skipstart = x;
  1568 		while(x < w && !ISTRANSL(src[x], sf))
  1569 		    x++;
  1570 		runstart = x;
  1571 		while(x < w && ISTRANSL(src[x], sf))
  1572 		    x++;
  1573 		skip = runstart - skipstart;
  1574 		blankline &= (skip == w);
  1575 		run = x - runstart;
  1576 		while(skip > max_transl_run) {
  1577 		    ADD_TRANSL_COUNTS(max_transl_run, 0);
  1578 		    skip -= max_transl_run;
  1579 		}
  1580 		len = MIN(run, max_transl_run);
  1581 		ADD_TRANSL_COUNTS(skip, len);
  1582 		dst += copy_transl(dst, src + runstart, len, sf, df);
  1583 		runstart += len;
  1584 		run -= len;
  1585 		while(run) {
  1586 		    len = MIN(run, max_transl_run);
  1587 		    ADD_TRANSL_COUNTS(0, len);
  1588 		    dst += copy_transl(dst, src + runstart, len, sf, df);
  1589 		    runstart += len;
  1590 		    run -= len;
  1591 		}
  1592 		if(!blankline)
  1593 		    lastline = dst;
  1594 	    } while(x < w);
  1595 
  1596 	    src += surface->pitch >> 2;
  1597 	}
  1598 	dst = lastline;		/* back up past trailing blank lines */
  1599 	ADD_OPAQUE_COUNTS(0, 0);
  1600     }
  1601 
  1602 #undef ADD_OPAQUE_COUNTS
  1603 #undef ADD_TRANSL_COUNTS
  1604 
  1605     /* Now that we have it encoded, release the original pixels */
  1606     if((surface->flags & SDL_PREALLOC) != SDL_PREALLOC
  1607        && (surface->flags & SDL_HWSURFACE) != SDL_HWSURFACE) {
  1608 	free( surface->pixels );
  1609 	surface->pixels = NULL;
  1610     }
  1611 
  1612     /* realloc the buffer to release unused memory */
  1613     {
  1614 	Uint8 *p = realloc(rlebuf, dst - rlebuf);
  1615 	if(!p)
  1616 	    p = rlebuf;
  1617 	surface->map->sw_data->aux_data = p;
  1618     }
  1619 
  1620     return 0;
  1621 }
  1622 
  1623 static Uint32 getpix_8(Uint8 *srcbuf)
  1624 {
  1625     return *srcbuf;
  1626 }
  1627 
  1628 static Uint32 getpix_16(Uint8 *srcbuf)
  1629 {
  1630     return *(Uint16 *)srcbuf;
  1631 }
  1632 
  1633 static Uint32 getpix_24(Uint8 *srcbuf)
  1634 {
  1635     if(SDL_BYTEORDER == SDL_LIL_ENDIAN)
  1636 	return srcbuf[0] + (srcbuf[1] << 8) + (srcbuf[2] << 16);
  1637     else
  1638 	return (srcbuf[0] << 16) + (srcbuf[1] << 8) + srcbuf[2];
  1639 }
  1640 
  1641 static Uint32 getpix_32(Uint8 *srcbuf)
  1642 {
  1643     return *(Uint32 *)srcbuf;
  1644 }
  1645 
  1646 typedef Uint32 (*getpix_func)(Uint8 *);
  1647 
  1648 static getpix_func getpixes[4] = {
  1649     getpix_8, getpix_16, getpix_24, getpix_32
  1650 };
  1651 
  1652 static int RLEColorkeySurface(SDL_Surface *surface)
  1653 {
  1654         Uint8 *rlebuf, *dst;
  1655 	int maxn;
  1656 	int y;
  1657 	Uint8 *srcbuf, *curbuf, *lastline;
  1658 	int maxsize = 0;
  1659 	int skip, run;
  1660 	int bpp = surface->format->BytesPerPixel;
  1661 	getpix_func getpix;
  1662 	Uint32 ckey, rgbmask;
  1663 	int w, h;
  1664 
  1665 	/* calculate the worst case size for the compressed surface */
  1666 	switch(bpp) {
  1667 	case 1:
  1668 	    /* worst case is alternating opaque and transparent pixels,
  1669 	       starting with an opaque pixel */
  1670 	    maxsize = surface->h * 3 * (surface->w / 2 + 1) + 2;
  1671 	    break;
  1672 	case 2:
  1673 	case 3:
  1674 	    /* worst case is solid runs, at most 255 pixels wide */
  1675 	    maxsize = surface->h * (2 * (surface->w / 255 + 1)
  1676 				    + surface->w * bpp) + 2;
  1677 	    break;
  1678 	case 4:
  1679 	    /* worst case is solid runs, at most 65535 pixels wide */
  1680 	    maxsize = surface->h * (4 * (surface->w / 65535 + 1)
  1681 				    + surface->w * 4) + 4;
  1682 	    break;
  1683 	}
  1684 
  1685 	rlebuf = (Uint8 *)malloc(maxsize);
  1686 	if ( rlebuf == NULL ) {
  1687 		SDL_OutOfMemory();
  1688 		return(-1);
  1689 	}
  1690 
  1691 	/* Set up the conversion */
  1692 	srcbuf = (Uint8 *)surface->pixels;
  1693 	curbuf = srcbuf;
  1694 	maxn = bpp == 4 ? 65535 : 255;
  1695 	skip = run = 0;
  1696 	dst = rlebuf;
  1697 	rgbmask = ~surface->format->Amask;
  1698 	ckey = surface->format->colorkey & rgbmask;
  1699 	lastline = dst;
  1700 	getpix = getpixes[bpp - 1];
  1701 	w = surface->w;
  1702 	h = surface->h;
  1703 
  1704 #define ADD_COUNTS(n, m)			\
  1705 	if(bpp == 4) {				\
  1706 	    ((Uint16 *)dst)[0] = n;		\
  1707 	    ((Uint16 *)dst)[1] = m;		\
  1708 	    dst += 4;				\
  1709 	} else {				\
  1710 	    dst[0] = n;				\
  1711 	    dst[1] = m;				\
  1712 	    dst += 2;				\
  1713 	}
  1714 
  1715 	for(y = 0; y < h; y++) {
  1716 	    int x = 0;
  1717 	    int blankline = 0;
  1718 	    do {
  1719 		int run, skip, len;
  1720 		int runstart;
  1721 		int skipstart = x;
  1722 
  1723 		/* find run of transparent, then opaque pixels */
  1724 		while(x < w && (getpix(srcbuf + x * bpp) & rgbmask) == ckey)
  1725 		    x++;
  1726 		runstart = x;
  1727 		while(x < w && (getpix(srcbuf + x * bpp) & rgbmask) != ckey)
  1728 		    x++;
  1729 		skip = runstart - skipstart;
  1730 		if(skip == w)
  1731 		    blankline = 1;
  1732 		run = x - runstart;
  1733 
  1734 		/* encode segment */
  1735 		while(skip > maxn) {
  1736 		    ADD_COUNTS(maxn, 0);
  1737 		    skip -= maxn;
  1738 		}
  1739 		len = MIN(run, maxn);
  1740 		ADD_COUNTS(skip, len);
  1741 		memcpy(dst, srcbuf + runstart * bpp, len * bpp);
  1742 		dst += len * bpp;
  1743 		run -= len;
  1744 		runstart += len;
  1745 		while(run) {
  1746 		    len = MIN(run, maxn);
  1747 		    ADD_COUNTS(0, len);
  1748 		    memcpy(dst, srcbuf + runstart * bpp, len * bpp);
  1749 		    dst += len * bpp;
  1750 		    runstart += len;
  1751 		    run -= len;
  1752 		}
  1753 		if(!blankline)
  1754 		    lastline = dst;
  1755 	    } while(x < w);
  1756 
  1757 	    srcbuf += surface->pitch;
  1758 	}
  1759 	dst = lastline;		/* back up bast trailing blank lines */
  1760 	ADD_COUNTS(0, 0);
  1761 
  1762 #undef ADD_COUNTS
  1763 
  1764 	/* Now that we have it encoded, release the original pixels */
  1765 	if((surface->flags & SDL_PREALLOC) != SDL_PREALLOC
  1766 	   && (surface->flags & SDL_HWSURFACE) != SDL_HWSURFACE) {
  1767 	    free( surface->pixels );
  1768 	    surface->pixels = NULL;
  1769 	}
  1770 
  1771 	/* realloc the buffer to release unused memory */
  1772 	{
  1773 	    /* If realloc returns NULL, the original block is left intact */
  1774 	    Uint8 *p = realloc(rlebuf, dst - rlebuf);
  1775 	    if(!p)
  1776 		p = rlebuf;
  1777 	    surface->map->sw_data->aux_data = p;
  1778 	}
  1779 
  1780 	return(0);
  1781 }
  1782 
  1783 int SDL_RLESurface(SDL_Surface *surface)
  1784 {
  1785 	int retcode;
  1786 
  1787 	/* Clear any previous RLE conversion */
  1788 	if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
  1789 		SDL_UnRLESurface(surface, 1);
  1790 	}
  1791 
  1792 	/* We don't support RLE encoding of bitmaps */
  1793 	if ( surface->format->BitsPerPixel < 8 ) {
  1794 		return(-1);
  1795 	}
  1796 
  1797 	/* Lock the surface if it's in hardware */
  1798 	if ( SDL_MUSTLOCK(surface) ) {
  1799 		if ( SDL_LockSurface(surface) < 0 ) {
  1800 			return(-1);
  1801 		}
  1802 	}
  1803 
  1804 	/* Encode */
  1805 	if((surface->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
  1806 	    retcode = RLEColorkeySurface(surface);
  1807 	} else {
  1808 	    if((surface->flags & SDL_SRCALPHA) == SDL_SRCALPHA
  1809 	       && surface->format->Amask != 0)
  1810 		retcode = RLEAlphaSurface(surface);
  1811 	    else
  1812 		retcode = -1;	/* no RLE for per-surface alpha sans ckey */
  1813 	}
  1814 
  1815 	/* Unlock the surface if it's in hardware */
  1816 	if ( SDL_MUSTLOCK(surface) ) {
  1817 		SDL_UnlockSurface(surface);
  1818 	}
  1819 
  1820 	if(retcode < 0)
  1821 	    return -1;
  1822 
  1823 	/* The surface is now accelerated */
  1824 	surface->flags |= SDL_RLEACCEL;
  1825 
  1826 	return(0);
  1827 }
  1828 
  1829 /*
  1830  * Un-RLE a surface with pixel alpha
  1831  * This may not give back exactly the image before RLE-encoding; all
  1832  * completely transparent pixels will be lost, and colour and alpha depth
  1833  * may have been reduced (when encoding for 16bpp targets).
  1834  */
  1835 static SDL_bool UnRLEAlpha(SDL_Surface *surface)
  1836 {
  1837     Uint8 *srcbuf;
  1838     Uint32 *dst;
  1839     SDL_PixelFormat *sf = surface->format;
  1840     RLEDestFormat *df = surface->map->sw_data->aux_data;
  1841     int (*uncopy_opaque)(Uint32 *, void *, int,
  1842 			 RLEDestFormat *, SDL_PixelFormat *);
  1843     int (*uncopy_transl)(Uint32 *, void *, int,
  1844 			 RLEDestFormat *, SDL_PixelFormat *);
  1845     int w = surface->w;
  1846     int bpp = df->BytesPerPixel;
  1847 
  1848     if(bpp == 2) {
  1849 	uncopy_opaque = uncopy_opaque_16;
  1850 	uncopy_transl = uncopy_transl_16;
  1851     } else {
  1852 	uncopy_opaque = uncopy_transl = uncopy_32;
  1853     }
  1854 
  1855     surface->pixels = malloc(surface->h * surface->pitch);
  1856     if ( !surface->pixels ) {
  1857         return(SDL_FALSE);
  1858     }
  1859     /* fill background with transparent pixels */
  1860     memset(surface->pixels, 0, surface->h * surface->pitch);
  1861 
  1862     dst = surface->pixels;
  1863     srcbuf = (Uint8 *)(df + 1);
  1864     for(;;) {
  1865 	/* copy opaque pixels */
  1866 	int ofs = 0;
  1867 	do {
  1868 	    unsigned run;
  1869 	    if(bpp == 2) {
  1870 		ofs += srcbuf[0];
  1871 		run = srcbuf[1];
  1872 		srcbuf += 2;
  1873 	    } else {
  1874 		ofs += ((Uint16 *)srcbuf)[0];
  1875 		run = ((Uint16 *)srcbuf)[1];
  1876 		srcbuf += 4;
  1877 	    }
  1878 	    if(run) {
  1879 		srcbuf += uncopy_opaque(dst + ofs, srcbuf, run, df, sf);
  1880 		ofs += run;
  1881 	    } else if(!ofs)
  1882 		return(SDL_TRUE);
  1883 	} while(ofs < w);
  1884 
  1885 	/* skip padding if needed */
  1886 	if(bpp == 2)
  1887 	    srcbuf += (unsigned long)srcbuf & 2;
  1888 	
  1889 	/* copy translucent pixels */
  1890 	ofs = 0;
  1891 	do {
  1892 	    unsigned run;
  1893 	    ofs += ((Uint16 *)srcbuf)[0];
  1894 	    run = ((Uint16 *)srcbuf)[1];
  1895 	    srcbuf += 4;
  1896 	    if(run) {
  1897 		srcbuf += uncopy_transl(dst + ofs, srcbuf, run, df, sf);
  1898 		ofs += run;
  1899 	    }
  1900 	} while(ofs < w);
  1901 	dst += surface->pitch >> 2;
  1902     }
  1903     /* Make the compiler happy */
  1904     return(SDL_TRUE);
  1905 }
  1906 
  1907 void SDL_UnRLESurface(SDL_Surface *surface, int recode)
  1908 {
  1909     if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
  1910 	surface->flags &= ~SDL_RLEACCEL;
  1911 
  1912 	if(recode && (surface->flags & SDL_PREALLOC) != SDL_PREALLOC
  1913 	   && (surface->flags & SDL_HWSURFACE) != SDL_HWSURFACE) {
  1914 	    if((surface->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
  1915 		SDL_Rect full;
  1916 		unsigned alpha_flag;
  1917 
  1918 		/* re-create the original surface */
  1919 		surface->pixels = malloc(surface->h * surface->pitch);
  1920 		if ( !surface->pixels ) {
  1921 			/* Oh crap... */
  1922 			surface->flags |= SDL_RLEACCEL;
  1923 			return;
  1924 		}
  1925 
  1926 		/* fill it with the background colour */
  1927 		SDL_FillRect(surface, NULL, surface->format->colorkey);
  1928 
  1929 		/* now render the encoded surface */
  1930 		full.x = full.y = 0;
  1931 		full.w = surface->w;
  1932 		full.h = surface->h;
  1933 		alpha_flag = surface->flags & SDL_SRCALPHA;
  1934 		surface->flags &= ~SDL_SRCALPHA; /* opaque blit */
  1935 		SDL_RLEBlit(surface, &full, surface, &full);
  1936 		surface->flags |= alpha_flag;
  1937 	    } else {
  1938 		if ( !UnRLEAlpha(surface) ) {
  1939 		    /* Oh crap... */
  1940 		    surface->flags |= SDL_RLEACCEL;
  1941 		    return;
  1942 		}
  1943 	    }
  1944 	}
  1945 
  1946 	if ( surface->map && surface->map->sw_data->aux_data ) {
  1947 	    free(surface->map->sw_data->aux_data);
  1948 	    surface->map->sw_data->aux_data = NULL;
  1949 	}
  1950     }
  1951 }
  1952 
  1953