146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL - Simple DirectMedia Layer
346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Copyright (C) 1997-2006 Sam Lantinga
446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    This library is free software; you can redistribute it and/or
646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    modify it under the terms of the GNU Lesser General Public
746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    License as published by the Free Software Foundation; either
846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    version 2.1 of the License, or (at your option) any later version.
946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    This library is distributed in the hope that it will be useful,
1146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    but WITHOUT ANY WARRANTY; without even the implied warranty of
1246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Lesser General Public License for more details.
1446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    You should have received a copy of the GNU Lesser General Public
1646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    License along with this library; if not, write to the Free Software
1746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
1846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Sam Lantinga
2046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    slouken@libsdl.org
2146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
2246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_config.h"
2346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
2546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * RLE encoding for software colorkey and alpha-channel acceleration
2646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *
2746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Original version by Sam Lantinga
2846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *
2946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Mattias Engdeg�rd (Yorick): Rewrite. New encoding format, encoder and
3046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * decoder. Added per-surface alpha blitter. Added per-pixel alpha
3146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * format, encoder and blitter.
3246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *
3346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Many thanks to Xark and johns for hints, benchmarks and useful comments
3446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * leading to this code.
3546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *
3646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Welcome to Macro Mayhem.
3746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */
3846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
3946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
4046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * The encoding translates the image data to a stream of segments of the form
4146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *
4246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * <skip> <run> <data>
4346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *
4446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * where <skip> is the number of transparent pixels to skip,
4546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *       <run>  is the number of opaque pixels to blit,
4646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * and   <data> are the pixels themselves.
4746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *
4846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * This basic structure is used both for colorkeyed surfaces, used for simple
4946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * binary transparency and for per-surface alpha blending, and for surfaces
5046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * with per-pixel alpha. The details differ, however:
5146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *
5246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Encoding of colorkeyed surfaces:
5346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *
5446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   Encoded pixels always have the same format as the target surface.
5546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   <skip> and <run> are unsigned 8 bit integers, except for 32 bit depth
5646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   where they are 16 bit. This makes the pixel data aligned at all times.
5746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   Segments never wrap around from one scan line to the next.
5846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *
5946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   The end of the sequence is marked by a zero <skip>,<run> pair at the *
6046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   beginning of a line.
6146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *
6246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Encoding of surfaces with per-pixel alpha:
6346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *
6446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   The sequence begins with a struct RLEDestFormat describing the target
6546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   pixel format, to provide reliable un-encoding.
6646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *
6746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   Each scan line is encoded twice: First all completely opaque pixels,
6846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   encoded in the target format as described above, and then all
6946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   partially transparent (translucent) pixels (where 1 <= alpha <= 254),
7046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   in the following 32-bit format:
7146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *
7246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   For 32-bit targets, each pixel has the target RGB format but with
7346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   the alpha value occupying the highest 8 bits. The <skip> and <run>
7446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   counts are 16 bit.
7546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *
7646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   For 16-bit targets, each pixel has the target RGB format, but with
7746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   the middle component (usually green) shifted 16 steps to the left,
7846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   and the hole filled with the 5 most significant bits of the alpha value.
7946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   i.e. if the target has the format         rrrrrggggggbbbbb,
8046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   the encoded pixel will be 00000gggggg00000rrrrr0aaaaabbbbb.
8146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   The <skip> and <run> counts are 8 bit for the opaque lines, 16 bit
8246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   for the translucent lines. Two padding bytes may be inserted
8346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   before each translucent line to keep them 32-bit aligned.
8446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *
8546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   The end of the sequence is marked by a zero <skip>,<run> pair at the
8646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *   beginning of an opaque line.
8746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */
8846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
8946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_video.h"
9046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_sysvideo.h"
9146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_blit.h"
9246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_RLEaccel_c.h"
9346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
9446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && SDL_ASSEMBLY_ROUTINES
9546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MMX_ASMBLIT
9646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
9746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
9846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef MMX_ASMBLIT
9946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "mmx.h"
10046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_cpuinfo.h"
10146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
10246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
10346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef MAX
10446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MAX(a, b) ((a) > (b) ? (a) : (b))
10546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
10646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef MIN
10746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MIN(a, b) ((a) < (b) ? (a) : (b))
10846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
10946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
11046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define PIXEL_COPY(to, from, len, bpp)			\
11146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerdo {							\
11246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if(bpp == 4) {					\
11346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_memcpy4(to, from, (size_t)(len));		\
11446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } else {						\
11546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_memcpy(to, from, (size_t)(len) * (bpp));	\
11646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }							\
11746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} while(0)
11846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
11946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
12046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Various colorkey blit methods, for opaque and per-surface alpha
12146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */
12246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
12346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define OPAQUE_BLIT(to, from, length, bpp, alpha)	\
12446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    PIXEL_COPY(to, from, length, bpp)
12546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
12646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef MMX_ASMBLIT
12746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
12846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ALPHA_BLIT32_888MMX(to, from, length, bpp, alpha)	\
12946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do {							\
13046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 *srcp = (Uint32 *)(from);			\
13146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 *dstp = (Uint32 *)(to);				\
13246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        int i = 0x00FF00FF;					\
13346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        movd_m2r(*(&i), mm3);					\
13446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        punpckldq_r2r(mm3, mm3);				\
13546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        i = 0xFF000000;						\
13646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        movd_m2r(*(&i), mm7);					\
13746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        punpckldq_r2r(mm7, mm7);				\
13846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        i = alpha | alpha << 16;				\
13946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        movd_m2r(*(&i), mm4);					\
14046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        punpckldq_r2r(mm4, mm4);				\
14146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	pcmpeqd_r2r(mm5,mm5); /* set mm5 to "1" */		\
14246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	pxor_r2r(mm7, mm5); /* make clear alpha mask */		\
14346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        i = length;						\
14446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if(i & 1) {						\
14546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          movd_m2r((*srcp), mm1); /* src -> mm1 */		\
14646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          punpcklbw_r2r(mm1, mm1);				\
14746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          pand_r2r(mm3, mm1);					\
14846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movd_m2r((*dstp), mm2); /* dst -> mm2 */		\
14946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          punpcklbw_r2r(mm2, mm2);				\
15046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          pand_r2r(mm3, mm2);					\
15146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psubw_r2r(mm2, mm1);					\
15246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pmullw_r2r(mm4, mm1);					\
15346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psrlw_i2r(8, mm1);					\
15446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  paddw_r2r(mm1, mm2);					\
15546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm3, mm2);					\
15646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  packuswb_r2r(mm2, mm2);				\
15746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm5, mm2); /* 00000RGB -> mm2 */		\
15846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movd_r2m(mm2, *dstp);					\
15946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  ++srcp;						\
16046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  ++dstp;						\
16146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  i--;							\
16246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}							\
16346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for(; i > 0; --i) {					\
16446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          movq_m2r((*srcp), mm0);				\
16546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_r2r(mm0, mm1);					\
16646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          punpcklbw_r2r(mm0, mm0);				\
16746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_m2r((*dstp), mm2);				\
16846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  punpckhbw_r2r(mm1, mm1);				\
16946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_r2r(mm2, mm6);					\
17046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          pand_r2r(mm3, mm0);					\
17146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          punpcklbw_r2r(mm2, mm2);				\
17246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm3, mm1);					\
17346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  punpckhbw_r2r(mm6, mm6);				\
17446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          pand_r2r(mm3, mm2);					\
17546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psubw_r2r(mm2, mm0);					\
17646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pmullw_r2r(mm4, mm0);					\
17746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm3, mm6);					\
17846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psubw_r2r(mm6, mm1);					\
17946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pmullw_r2r(mm4, mm1);					\
18046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psrlw_i2r(8, mm0);					\
18146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  paddw_r2r(mm0, mm2);					\
18246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psrlw_i2r(8, mm1);					\
18346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  paddw_r2r(mm1, mm6);					\
18446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm3, mm2);					\
18546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm3, mm6);					\
18646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  packuswb_r2r(mm2, mm2);				\
18746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  packuswb_r2r(mm6, mm6);				\
18846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psrlq_i2r(32, mm2);					\
18946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psllq_i2r(32, mm6);					\
19046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  por_r2r(mm6, mm2);					\
19146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm5, mm2); /* 00000RGB -> mm2 */		\
19246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         movq_r2m(mm2, *dstp);					\
19346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  srcp += 2;						\
19446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  dstp += 2;						\
19546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  i--;							\
19646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}							\
19746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	emms();							\
19846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } while(0)
19946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
20046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ALPHA_BLIT16_565MMX(to, from, length, bpp, alpha)	\
20146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do {						\
20246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        int i, n = 0;					\
20346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint16 *srcp = (Uint16 *)(from);		\
20446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint16 *dstp = (Uint16 *)(to);			\
20546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        Uint32 ALPHA = 0xF800;				\
20646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	movd_m2r(*(&ALPHA), mm1);			\
20746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        punpcklwd_r2r(mm1, mm1);			\
20846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        punpcklwd_r2r(mm1, mm1);			\
20946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	ALPHA = 0x07E0;					\
21046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	movd_m2r(*(&ALPHA), mm4);			\
21146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        punpcklwd_r2r(mm4, mm4);			\
21246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        punpcklwd_r2r(mm4, mm4);			\
21346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	ALPHA = 0x001F;					\
21446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	movd_m2r(*(&ALPHA), mm7);			\
21546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        punpcklwd_r2r(mm7, mm7);			\
21646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        punpcklwd_r2r(mm7, mm7);			\
21746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	alpha &= ~(1+2+4);				\
21846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        i = (Uint32)alpha | (Uint32)alpha << 16;	\
21946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        movd_m2r(*(&i), mm0);				\
22046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        punpckldq_r2r(mm0, mm0);			\
22146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        ALPHA = alpha >> 3;				\
22246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        i = ((int)(length) & 3);			\
22346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for(; i > 0; --i) {				\
22446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    Uint32 s = *srcp++;				\
22546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    Uint32 d = *dstp;				\
22646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    s = (s | s << 16) & 0x07e0f81f;		\
22746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    d = (d | d << 16) & 0x07e0f81f;		\
22846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    d += (s - d) * ALPHA >> 5;			\
22946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    d &= 0x07e0f81f;				\
23046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    *dstp++ = d | d >> 16;			\
23146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    n++;					\
23246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}						\
23346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	i = (int)(length) - n;				\
23446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for(; i > 0; --i) {				\
23546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_m2r((*dstp), mm3);			\
23646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_m2r((*srcp), mm2);			\
23746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_r2r(mm2, mm5);				\
23846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm1 , mm5);				\
23946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psrlq_i2r(11, mm5);				\
24046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_r2r(mm3, mm6);				\
24146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm1 , mm6);				\
24246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psrlq_i2r(11, mm6);				\
24346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psubw_r2r(mm6, mm5);				\
24446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pmullw_r2r(mm0, mm5);				\
24546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psrlw_i2r(8, mm5);				\
24646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  paddw_r2r(mm5, mm6);				\
24746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psllq_i2r(11, mm6);				\
24846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm1, mm6);				\
24946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_r2r(mm4, mm5);				\
25046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  por_r2r(mm7, mm5);				\
25146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm5, mm3);				\
25246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  por_r2r(mm6, mm3);				\
25346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_r2r(mm2, mm5);				\
25446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm4 , mm5);				\
25546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psrlq_i2r(5, mm5);				\
25646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_r2r(mm3, mm6);				\
25746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm4 , mm6);				\
25846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psrlq_i2r(5, mm6);				\
25946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psubw_r2r(mm6, mm5);				\
26046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pmullw_r2r(mm0, mm5);				\
26146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psrlw_i2r(8, mm5);				\
26246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  paddw_r2r(mm5, mm6);				\
26346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psllq_i2r(5, mm6);				\
26446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm4, mm6);				\
26546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_r2r(mm1, mm5);				\
26646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  por_r2r(mm7, mm5);				\
26746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm5, mm3);				\
26846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  por_r2r(mm6, mm3);				\
26946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_r2r(mm2, mm5);				\
27046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm7 , mm5);				\
27146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          movq_r2r(mm3, mm6);				\
27246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm7 , mm6);				\
27346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psubw_r2r(mm6, mm5);				\
27446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pmullw_r2r(mm0, mm5);				\
27546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psrlw_i2r(8, mm5);				\
27646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  paddw_r2r(mm5, mm6);				\
27746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm7, mm6);				\
27846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_r2r(mm1, mm5);				\
27946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  por_r2r(mm4, mm5);				\
28046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm5, mm3);				\
28146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  por_r2r(mm6, mm3);				\
28246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_r2m(mm3, *dstp);				\
28346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  srcp += 4;					\
28446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  dstp += 4;					\
28546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  i -= 3;					\
28646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}						\
28746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	emms();						\
28846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } while(0)
28946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
29046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ALPHA_BLIT16_555MMX(to, from, length, bpp, alpha)	\
29146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do {						\
29246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        int i, n = 0;					\
29346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint16 *srcp = (Uint16 *)(from);		\
29446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint16 *dstp = (Uint16 *)(to);			\
29546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        Uint32 ALPHA = 0x7C00;				\
29646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	movd_m2r(*(&ALPHA), mm1);			\
29746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        punpcklwd_r2r(mm1, mm1);			\
29846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        punpcklwd_r2r(mm1, mm1);			\
29946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	ALPHA = 0x03E0;					\
30046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        movd_m2r(*(&ALPHA), mm4);			\
30146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        punpcklwd_r2r(mm4, mm4);			\
30246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        punpcklwd_r2r(mm4, mm4);			\
30346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	ALPHA = 0x001F;					\
30446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	movd_m2r(*(&ALPHA), mm7);			\
30546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        punpcklwd_r2r(mm7, mm7);			\
30646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        punpcklwd_r2r(mm7, mm7);			\
30746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	alpha &= ~(1+2+4);				\
30846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        i = (Uint32)alpha | (Uint32)alpha << 16;	\
30946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        movd_m2r(*(&i), mm0);				\
31046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        punpckldq_r2r(mm0, mm0);			\
31146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        i = ((int)(length) & 3);				\
31246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        ALPHA = alpha >> 3;				\
31346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for(; i > 0; --i) {				\
31446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    Uint32 s = *srcp++;				\
31546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    Uint32 d = *dstp;				\
31646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    s = (s | s << 16) & 0x03e07c1f;		\
31746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    d = (d | d << 16) & 0x03e07c1f;		\
31846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    d += (s - d) * ALPHA >> 5;			\
31946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    d &= 0x03e07c1f;				\
32046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    *dstp++ = d | d >> 16;			\
32146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    n++;					\
32246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}						\
32346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	i = (int)(length) - n;				\
32446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for(; i > 0; --i) {				\
32546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_m2r((*dstp), mm3);			\
32646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_m2r((*srcp), mm2);			\
32746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_r2r(mm2, mm5);				\
32846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm1 , mm5);				\
32946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psrlq_i2r(10, mm5);				\
33046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_r2r(mm3, mm6);				\
33146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm1 , mm6);				\
33246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psrlq_i2r(10, mm6);				\
33346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psubw_r2r(mm6, mm5);				\
33446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pmullw_r2r(mm0, mm5);				\
33546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psrlw_i2r(8, mm5);				\
33646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  paddw_r2r(mm5, mm6);				\
33746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psllq_i2r(10, mm6);				\
33846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm1, mm6);				\
33946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_r2r(mm4, mm5);				\
34046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  por_r2r(mm7, mm5);				\
34146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm5, mm3);				\
34246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  por_r2r(mm6, mm3);				\
34346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_r2r(mm2, mm5);				\
34446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm4 , mm5);				\
34546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psrlq_i2r(5, mm5);				\
34646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_r2r(mm3, mm6);				\
34746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm4 , mm6);				\
34846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psrlq_i2r(5, mm6);				\
34946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psubw_r2r(mm6, mm5);				\
35046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pmullw_r2r(mm0, mm5);				\
35146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psrlw_i2r(8, mm5);				\
35246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  paddw_r2r(mm5, mm6);				\
35346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psllq_i2r(5, mm6);				\
35446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm4, mm6);				\
35546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_r2r(mm1, mm5);				\
35646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  por_r2r(mm7, mm5);				\
35746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm5, mm3);				\
35846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  por_r2r(mm6, mm3);				\
35946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_r2r(mm2, mm5);				\
36046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm7 , mm5);				\
36146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          movq_r2r(mm3, mm6);				\
36246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm7 , mm6);				\
36346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psubw_r2r(mm6, mm5);				\
36446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pmullw_r2r(mm0, mm5);				\
36546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  psrlw_i2r(8, mm5);				\
36646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  paddw_r2r(mm5, mm6);				\
36746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm7, mm6);				\
36846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_r2r(mm1, mm5);				\
36946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  por_r2r(mm4, mm5);				\
37046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  pand_r2r(mm5, mm3);				\
37146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  por_r2r(mm6, mm3);				\
37246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  movq_r2m(mm3, *dstp);				\
37346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  srcp += 4;					\
37446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  dstp += 4;					\
37546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  i -= 3;					\
37646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}						\
37746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	emms();						\
37846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } while(0)
37946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
38046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
38146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
38246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
38346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * For 32bpp pixels on the form 0x00rrggbb:
38446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * If we treat the middle component separately, we can process the two
38546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * remaining in parallel. This is safe to do because of the gap to the left
38646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * of each component, so the bits from the multiplication don't collide.
38746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * This can be used for any RGB permutation of course.
38846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */
38946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ALPHA_BLIT32_888(to, from, length, bpp, alpha)		\
39046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do {							\
39146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        int i;							\
39246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 *src = (Uint32 *)(from);				\
39346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 *dst = (Uint32 *)(to);				\
39446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for(i = 0; i < (int)(length); i++) {			\
39546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    Uint32 s = *src++;					\
39646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    Uint32 d = *dst;					\
39746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    Uint32 s1 = s & 0xff00ff;				\
39846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    Uint32 d1 = d & 0xff00ff;				\
39946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff;	\
40046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    s &= 0xff00;					\
40146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    d &= 0xff00;					\
40246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    d = (d + ((s - d) * alpha >> 8)) & 0xff00;		\
40346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    *dst++ = d1 | d;					\
40446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}							\
40546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } while(0)
40646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
40746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
40846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * For 16bpp pixels we can go a step further: put the middle component
40946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * in the high 16 bits of a 32 bit word, and process all three RGB
41046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * components at the same time. Since the smallest gap is here just
41146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * 5 bits, we have to scale alpha down to 5 bits as well.
41246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */
41346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ALPHA_BLIT16_565(to, from, length, bpp, alpha)	\
41446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do {						\
41546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        int i;						\
41646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint16 *src = (Uint16 *)(from);			\
41746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint16 *dst = (Uint16 *)(to);			\
41846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 ALPHA = alpha >> 3;			\
41946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for(i = 0; i < (int)(length); i++) {		\
42046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    Uint32 s = *src++;				\
42146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    Uint32 d = *dst;				\
42246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    s = (s | s << 16) & 0x07e0f81f;		\
42346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    d = (d | d << 16) & 0x07e0f81f;		\
42446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    d += (s - d) * ALPHA >> 5;			\
42546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    d &= 0x07e0f81f;				\
42646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    *dst++ = (Uint16)(d | d >> 16);			\
42746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}						\
42846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } while(0)
42946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
43046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ALPHA_BLIT16_555(to, from, length, bpp, alpha)	\
43146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do {						\
43246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        int i;						\
43346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint16 *src = (Uint16 *)(from);			\
43446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint16 *dst = (Uint16 *)(to);			\
43546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 ALPHA = alpha >> 3;			\
43646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for(i = 0; i < (int)(length); i++) {		\
43746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    Uint32 s = *src++;				\
43846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    Uint32 d = *dst;				\
43946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    s = (s | s << 16) & 0x03e07c1f;		\
44046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    d = (d | d << 16) & 0x03e07c1f;		\
44146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    d += (s - d) * ALPHA >> 5;			\
44246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    d &= 0x03e07c1f;				\
44346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    *dst++ = (Uint16)(d | d >> 16);			\
44446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}						\
44546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } while(0)
44646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
44746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
44846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * The general slow catch-all function, for remaining depths and formats
44946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */
45046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ALPHA_BLIT_ANY(to, from, length, bpp, alpha)			\
45146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do {								\
45246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        int i;								\
45346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint8 *src = from;						\
45446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint8 *dst = to;						\
45546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for(i = 0; i < (int)(length); i++) {				\
45646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    Uint32 s, d;						\
45746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    unsigned rs, gs, bs, rd, gd, bd;				\
45846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    switch(bpp) {						\
45946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 2:							\
46046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		s = *(Uint16 *)src;					\
46146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		d = *(Uint16 *)dst;					\
46246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		break;							\
46346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 3:							\
46446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {			\
46546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    s = (src[0] << 16) | (src[1] << 8) | src[2];	\
46646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    d = (dst[0] << 16) | (dst[1] << 8) | dst[2];	\
46746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		} else {						\
46846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    s = (src[2] << 16) | (src[1] << 8) | src[0];	\
46946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    d = (dst[2] << 16) | (dst[1] << 8) | dst[0];	\
47046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}							\
47146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		break;							\
47246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 4:							\
47346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		s = *(Uint32 *)src;					\
47446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		d = *(Uint32 *)dst;					\
47546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		break;							\
47646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    }								\
47746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    RGB_FROM_PIXEL(s, fmt, rs, gs, bs);				\
47846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    RGB_FROM_PIXEL(d, fmt, rd, gd, bd);				\
47946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    rd += (rs - rd) * alpha >> 8;				\
48046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    gd += (gs - gd) * alpha >> 8;				\
48146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    bd += (bs - bd) * alpha >> 8;				\
48246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    PIXEL_FROM_RGB(d, fmt, rd, gd, bd);				\
48346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    switch(bpp) {						\
48446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 2:							\
48546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		*(Uint16 *)dst = (Uint16)d;					\
48646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		break;							\
48746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 3:							\
48846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {			\
48946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    dst[0] = (Uint8)(d >> 16);					\
49046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    dst[1] = (Uint8)(d >> 8);					\
49146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    dst[2] = (Uint8)(d);						\
49246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		} else {						\
49346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    dst[0] = (Uint8)d;						\
49446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    dst[1] = (Uint8)(d >> 8);					\
49546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    dst[2] = (Uint8)(d >> 16);					\
49646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}							\
49746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		break;							\
49846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 4:							\
49946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		*(Uint32 *)dst = d;					\
50046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		break;							\
50146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    }								\
50246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    src += bpp;							\
50346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    dst += bpp;							\
50446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}								\
50546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } while(0)
50646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
50746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef MMX_ASMBLIT
50846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
50946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ALPHA_BLIT32_888_50MMX(to, from, length, bpp, alpha)		\
51046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do {								\
51146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 *srcp = (Uint32 *)(from);				\
51246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 *dstp = (Uint32 *)(to);					\
51346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        int i = 0x00fefefe;						\
51446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        movd_m2r(*(&i), mm4);						\
51546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        punpckldq_r2r(mm4, mm4);					\
51646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        i = 0x00010101;							\
51746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        movd_m2r(*(&i), mm3);						\
51846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        punpckldq_r2r(mm3, mm3);					\
51946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        i = (int)(length);						\
52046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if( i & 1 ) {							\
52146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  Uint32 s = *srcp++;						\
52246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  Uint32 d = *dstp;						\
52346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  *dstp++ = (((s & 0x00fefefe) + (d & 0x00fefefe)) >> 1)	\
52446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		     + (s & d & 0x00010101);				\
52546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  i--;								\
52646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}								\
52746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for(; i > 0; --i) {						\
52846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    movq_m2r((*dstp), mm2); /* dst -> mm2 */			\
52946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    movq_r2r(mm2, mm6);	/* dst -> mm6 */			\
53046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    movq_m2r((*srcp), mm1); /* src -> mm1 */			\
53146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    movq_r2r(mm1, mm5);	/* src -> mm5 */			\
53246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    pand_r2r(mm4, mm6);	/* dst & 0x00fefefe -> mm6 */		\
53346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    pand_r2r(mm4, mm5); /* src & 0x00fefefe -> mm5 */		\
53446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    paddd_r2r(mm6, mm5); /* (dst & 0x00fefefe) + (dst & 0x00fefefe) -> mm5 */	\
53546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    psrld_i2r(1, mm5);						\
53646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    pand_r2r(mm1, mm2);	/* s & d -> mm2 */			\
53746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    pand_r2r(mm3, mm2);	/* s & d & 0x00010101 -> mm2 */		\
53846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    paddd_r2r(mm5, mm2);					\
53946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    movq_r2m(mm2, (*dstp));					\
54046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    dstp += 2;							\
54146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    srcp += 2;							\
54246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    i--;							\
54346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}								\
54446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	emms();								\
54546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } while(0)
54646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
54746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
54846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
54946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
55046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Special case: 50% alpha (alpha=128)
55146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * This is treated specially because it can be optimized very well, and
55246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * since it is good for many cases of semi-translucency.
55346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * The theory is to do all three components at the same time:
55446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * First zero the lowest bit of each component, which gives us room to
55546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * add them. Then shift right and add the sum of the lowest bits.
55646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */
55746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ALPHA_BLIT32_888_50(to, from, length, bpp, alpha)		\
55846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do {								\
55946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        int i;								\
56046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 *src = (Uint32 *)(from);					\
56146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 *dst = (Uint32 *)(to);					\
56246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for(i = 0; i < (int)(length); i++) {				\
56346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    Uint32 s = *src++;						\
56446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    Uint32 d = *dst;						\
56546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    *dst++ = (((s & 0x00fefefe) + (d & 0x00fefefe)) >> 1)	\
56646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		     + (s & d & 0x00010101);				\
56746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}								\
56846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } while(0)
56946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
57046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
57146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * For 16bpp, we can actually blend two pixels in parallel, if we take
57246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * care to shift before we add, not after.
57346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */
57446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
57546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* helper: blend a single 16 bit pixel at 50% */
57646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define BLEND16_50(dst, src, mask)			\
57746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do {						\
57846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 s = *src++;				\
57946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 d = *dst;				\
58046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	*dst++ = (Uint16)((((s & mask) + (d & mask)) >> 1) +	\
58146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	                  (s & d & (~mask & 0xffff)));		\
58246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } while(0)
58346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
58446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* basic 16bpp blender. mask is the pixels to keep when adding. */
58546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ALPHA_BLIT16_50(to, from, length, bpp, alpha, mask)		\
58646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do {								\
58746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	unsigned n = (length);						\
58846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint16 *src = (Uint16 *)(from);					\
58946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint16 *dst = (Uint16 *)(to);					\
59046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if(((uintptr_t)src ^ (uintptr_t)dst) & 3) {			\
59146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    /* source and destination not in phase, blit one by one */	\
59246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    while(n--)							\
59346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		BLEND16_50(dst, src, mask);				\
59446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	} else {							\
59546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    if((uintptr_t)src & 3) {					\
59646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* first odd pixel */					\
59746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		BLEND16_50(dst, src, mask);				\
59846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		n--;							\
59946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    }								\
60046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    for(; n > 1; n -= 2) {					\
60146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		Uint32 s = *(Uint32 *)src;				\
60246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		Uint32 d = *(Uint32 *)dst;				\
60346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		*(Uint32 *)dst = ((s & (mask | mask << 16)) >> 1)	\
60446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		               + ((d & (mask | mask << 16)) >> 1)	\
60546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		               + (s & d & (~(mask | mask << 16)));	\
60646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		src += 2;						\
60746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		dst += 2;						\
60846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    }								\
60946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    if(n)							\
61046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		BLEND16_50(dst, src, mask); /* last odd pixel */	\
61146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}								\
61246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } while(0)
61346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
61446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ALPHA_BLIT16_565_50(to, from, length, bpp, alpha)	\
61546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    ALPHA_BLIT16_50(to, from, length, bpp, alpha, 0xf7de)
61646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
61746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ALPHA_BLIT16_555_50(to, from, length, bpp, alpha)	\
61846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    ALPHA_BLIT16_50(to, from, length, bpp, alpha, 0xfbde)
61946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
62046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef MMX_ASMBLIT
62146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
62246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CHOOSE_BLIT(blitter, alpha, fmt)				\
62346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do {								\
62446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if(alpha == 255) {						\
62546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    switch(fmt->BytesPerPixel) {				\
62646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 1: blitter(1, Uint8, OPAQUE_BLIT); break;		\
62746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 2: blitter(2, Uint8, OPAQUE_BLIT); break;		\
62846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 3: blitter(3, Uint8, OPAQUE_BLIT); break;		\
62946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 4: blitter(4, Uint16, OPAQUE_BLIT); break;		\
63046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    }								\
63146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	} else {							\
63246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    switch(fmt->BytesPerPixel) {				\
63346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 1:							\
63446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* No 8bpp alpha blitting */				\
63546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		break;							\
63646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner									\
63746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 2:							\
63846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		switch(fmt->Rmask | fmt->Gmask | fmt->Bmask) {		\
63946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case 0xffff:						\
64046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    if(fmt->Gmask == 0x07e0				\
64146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		       || fmt->Rmask == 0x07e0				\
64246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		       || fmt->Bmask == 0x07e0) {			\
64346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if(alpha == 128)				\
64446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    blitter(2, Uint8, ALPHA_BLIT16_565_50);	\
64546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			else {						\
64646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    if(SDL_HasMMX())				\
64746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				blitter(2, Uint8, ALPHA_BLIT16_565MMX);	\
64846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    else					\
64946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				blitter(2, Uint8, ALPHA_BLIT16_565);	\
65046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}						\
65146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    } else						\
65246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			goto general16;					\
65346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    break;						\
65446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner									\
65546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case 0x7fff:						\
65646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    if(fmt->Gmask == 0x03e0				\
65746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		       || fmt->Rmask == 0x03e0				\
65846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		       || fmt->Bmask == 0x03e0) {			\
65946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if(alpha == 128)				\
66046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    blitter(2, Uint8, ALPHA_BLIT16_555_50);	\
66146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			else {						\
66246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    if(SDL_HasMMX())				\
66346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				blitter(2, Uint8, ALPHA_BLIT16_555MMX);	\
66446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    else					\
66546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				blitter(2, Uint8, ALPHA_BLIT16_555);	\
66646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}						\
66746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			break;						\
66846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    }							\
66946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    /* fallthrough */					\
67046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner									\
67146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		default:						\
67246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		general16:						\
67346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    blitter(2, Uint8, ALPHA_BLIT_ANY);			\
67446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}							\
67546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		break;							\
67646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner									\
67746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 3:							\
67846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		blitter(3, Uint8, ALPHA_BLIT_ANY);			\
67946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		break;							\
68046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner									\
68146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 4:							\
68246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if((fmt->Rmask | fmt->Gmask | fmt->Bmask) == 0x00ffffff	\
68346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		   && (fmt->Gmask == 0xff00 || fmt->Rmask == 0xff00	\
68446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		       || fmt->Bmask == 0xff00)) {			\
68546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    if(alpha == 128)					\
68646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    {							\
68746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if(SDL_HasMMX())				\
68846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				blitter(4, Uint16, ALPHA_BLIT32_888_50MMX);\
68946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			else						\
69046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				blitter(4, Uint16, ALPHA_BLIT32_888_50);\
69146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    }							\
69246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    else						\
69346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    {							\
69446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if(SDL_HasMMX())				\
69546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				blitter(4, Uint16, ALPHA_BLIT32_888MMX);\
69646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			else						\
69746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				blitter(4, Uint16, ALPHA_BLIT32_888);	\
69846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    }							\
69946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		} else							\
70046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    blitter(4, Uint16, ALPHA_BLIT_ANY);			\
70146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		break;							\
70246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    }								\
70346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}								\
70446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } while(0)
70546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
70646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else
70746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
70846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CHOOSE_BLIT(blitter, alpha, fmt)				\
70946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do {								\
71046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if(alpha == 255) {						\
71146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    switch(fmt->BytesPerPixel) {				\
71246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 1: blitter(1, Uint8, OPAQUE_BLIT); break;		\
71346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 2: blitter(2, Uint8, OPAQUE_BLIT); break;		\
71446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 3: blitter(3, Uint8, OPAQUE_BLIT); break;		\
71546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 4: blitter(4, Uint16, OPAQUE_BLIT); break;		\
71646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    }								\
71746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	} else {							\
71846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    switch(fmt->BytesPerPixel) {				\
71946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 1:							\
72046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* No 8bpp alpha blitting */				\
72146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		break;							\
72246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner									\
72346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 2:							\
72446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		switch(fmt->Rmask | fmt->Gmask | fmt->Bmask) {		\
72546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case 0xffff:						\
72646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    if(fmt->Gmask == 0x07e0				\
72746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		       || fmt->Rmask == 0x07e0				\
72846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		       || fmt->Bmask == 0x07e0) {			\
72946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if(alpha == 128)				\
73046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    blitter(2, Uint8, ALPHA_BLIT16_565_50);	\
73146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			else {						\
73246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    blitter(2, Uint8, ALPHA_BLIT16_565);	\
73346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}						\
73446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    } else						\
73546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			goto general16;					\
73646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    break;						\
73746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner									\
73846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case 0x7fff:						\
73946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    if(fmt->Gmask == 0x03e0				\
74046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		       || fmt->Rmask == 0x03e0				\
74146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		       || fmt->Bmask == 0x03e0) {			\
74246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if(alpha == 128)				\
74346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    blitter(2, Uint8, ALPHA_BLIT16_555_50);	\
74446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			else {						\
74546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    blitter(2, Uint8, ALPHA_BLIT16_555);	\
74646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}						\
74746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			break;						\
74846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    }							\
74946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    /* fallthrough */					\
75046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner									\
75146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		default:						\
75246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		general16:						\
75346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    blitter(2, Uint8, ALPHA_BLIT_ANY);			\
75446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}							\
75546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		break;							\
75646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner									\
75746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 3:							\
75846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		blitter(3, Uint8, ALPHA_BLIT_ANY);			\
75946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		break;							\
76046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner									\
76146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 4:							\
76246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if((fmt->Rmask | fmt->Gmask | fmt->Bmask) == 0x00ffffff	\
76346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		   && (fmt->Gmask == 0xff00 || fmt->Rmask == 0xff00	\
76446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		       || fmt->Bmask == 0xff00)) {			\
76546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    if(alpha == 128)					\
76646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			blitter(4, Uint16, ALPHA_BLIT32_888_50);	\
76746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    else						\
76846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			blitter(4, Uint16, ALPHA_BLIT32_888);		\
76946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		} else							\
77046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    blitter(4, Uint16, ALPHA_BLIT_ANY);			\
77146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		break;							\
77246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    }								\
77346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}								\
77446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } while(0)
77546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
77646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
77746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
77846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
77946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * This takes care of the case when the surface is clipped on the left and/or
78046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * right. Top clipping has already been taken care of.
78146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */
78246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void RLEClipBlit(int w, Uint8 *srcbuf, SDL_Surface *dst,
78346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			Uint8 *dstbuf, SDL_Rect *srcrect, unsigned alpha)
78446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
78546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL_PixelFormat *fmt = dst->format;
78646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
78746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define RLECLIPBLIT(bpp, Type, do_blit)					   \
78846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do {								   \
78946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int linecount = srcrect->h;					   \
79046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int ofs = 0;							   \
79146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int left = srcrect->x;						   \
79246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int right = left + srcrect->w;					   \
79346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	dstbuf -= left * bpp;						   \
79446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for(;;) {							   \
79546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    int run;							   \
79646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    ofs += *(Type *)srcbuf;					   \
79746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    run = ((Type *)srcbuf)[1];					   \
79846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    srcbuf += 2 * sizeof(Type);					   \
79946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    if(run) {							   \
80046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* clip to left and right borders */			   \
80146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if(ofs < right) {					   \
80246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    int start = 0;					   \
80346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    int len = run;					   \
80446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    int startcol;					   \
80546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    if(left - ofs > 0) {				   \
80646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			start = left - ofs;				   \
80746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			len -= start;					   \
80846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if(len <= 0)					   \
80946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    goto nocopy ## bpp ## do_blit;		   \
81046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    }							   \
81146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    startcol = ofs + start;				   \
81246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    if(len > right - startcol)				   \
81346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			len = right - startcol;				   \
81446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    do_blit(dstbuf + startcol * bpp, srcbuf + start * bpp, \
81546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    len, bpp, alpha);				   \
81646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}							   \
81746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    nocopy ## bpp ## do_blit:					   \
81846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		srcbuf += run * bpp;					   \
81946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		ofs += run;						   \
82046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    } else if(!ofs)						   \
82146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		break;							   \
82246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    if(ofs == w) {						   \
82346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		ofs = 0;						   \
82446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		dstbuf += dst->pitch;					   \
82546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if(!--linecount)					   \
82646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    break;						   \
82746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    }								   \
82846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}								   \
82946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } while(0)
83046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
83146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    CHOOSE_BLIT(RLECLIPBLIT, alpha, fmt);
83246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
83346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#undef RLECLIPBLIT
83446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
83546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
83646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
83746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
83846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* blit a colorkeyed RLE surface */
83946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_RLEBlit(SDL_Surface *src, SDL_Rect *srcrect,
84046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_Surface *dst, SDL_Rect *dstrect)
84146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
84246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint8 *dstbuf;
84346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint8 *srcbuf;
84446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int x, y;
84546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int w = src->w;
84646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	unsigned alpha;
84746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
84846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Lock the destination if necessary */
84946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( SDL_MUSTLOCK(dst) ) {
85046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( SDL_LockSurface(dst) < 0 ) {
85146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			return(-1);
85246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
85346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
85446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
85546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Set up the source and destination pointers */
85646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	x = dstrect->x;
85746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	y = dstrect->y;
85846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	dstbuf = (Uint8 *)dst->pixels
85946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	         + y * dst->pitch + x * src->format->BytesPerPixel;
86046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	srcbuf = (Uint8 *)src->map->sw_data->aux_data;
86146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
86246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	{
86346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    /* skip lines at the top if neccessary */
86446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    int vskip = srcrect->y;
86546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    int ofs = 0;
86646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    if(vskip) {
86746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
86846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define RLESKIP(bpp, Type)			\
86946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		for(;;) {			\
87046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    int run;			\
87146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    ofs += *(Type *)srcbuf;	\
87246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    run = ((Type *)srcbuf)[1];	\
87346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    srcbuf += sizeof(Type) * 2;	\
87446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    if(run) {			\
87546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			srcbuf += run * bpp;	\
87646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			ofs += run;		\
87746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    } else if(!ofs)		\
87846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			goto done;		\
87946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    if(ofs == w) {		\
88046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			ofs = 0;		\
88146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if(!--vskip)		\
88246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    break;		\
88346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    }				\
88446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
88546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
88646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		switch(src->format->BytesPerPixel) {
88746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case 1: RLESKIP(1, Uint8); break;
88846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case 2: RLESKIP(2, Uint8); break;
88946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case 3: RLESKIP(3, Uint8); break;
89046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case 4: RLESKIP(4, Uint16); break;
89146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
89246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
89346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#undef RLESKIP
89446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
89546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    }
89646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
89746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
89846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	alpha = (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA
89946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	        ? src->format->alpha : 255;
90046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* if left or right edge clipping needed, call clip blit */
90146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( srcrect->x || srcrect->w != src->w ) {
90246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    RLEClipBlit(w, srcbuf, dst, dstbuf, srcrect, alpha);
90346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	} else {
90446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    SDL_PixelFormat *fmt = src->format;
90546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
90646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define RLEBLIT(bpp, Type, do_blit)					      \
90746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    do {							      \
90846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		int linecount = srcrect->h;				      \
90946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		int ofs = 0;						      \
91046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		for(;;) {						      \
91146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    unsigned run;					      \
91246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    ofs += *(Type *)srcbuf;				      \
91346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    run = ((Type *)srcbuf)[1];				      \
91446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    srcbuf += 2 * sizeof(Type);				      \
91546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    if(run) {						      \
91646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			do_blit(dstbuf + ofs * bpp, srcbuf, run, bpp, alpha); \
91746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			srcbuf += run * bpp;				      \
91846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			ofs += run;					      \
91946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    } else if(!ofs)					      \
92046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			break;						      \
92146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    if(ofs == w) {					      \
92246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			ofs = 0;					      \
92346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			dstbuf += dst->pitch;				      \
92446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if(!--linecount)				      \
92546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    break;					      \
92646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    }							      \
92746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}							      \
92846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    } while(0)
92946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
93046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    CHOOSE_BLIT(RLEBLIT, alpha, fmt);
93146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
93246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#undef RLEBLIT
93346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
93446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
93546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerdone:
93646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Unlock the destination if necessary */
93746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( SDL_MUSTLOCK(dst) ) {
93846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_UnlockSurface(dst);
93946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
94046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(0);
94146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
94246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
94346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#undef OPAQUE_BLIT
94446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
94546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
94646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Per-pixel blitting macros for translucent pixels:
94746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * These use the same techniques as the per-surface blitting macros
94846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */
94946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
95046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
95146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * For 32bpp pixels, we have made sure the alpha is stored in the top
95246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * 8 bits, so proceed as usual
95346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */
95446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define BLIT_TRANSL_888(src, dst)				\
95546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do {							\
95646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        Uint32 s = src;						\
95746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 d = dst;						\
95846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	unsigned alpha = s >> 24;				\
95946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 s1 = s & 0xff00ff;				\
96046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 d1 = d & 0xff00ff;				\
96146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff;	\
96246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	s &= 0xff00;						\
96346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	d &= 0xff00;						\
96446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	d = (d + ((s - d) * alpha >> 8)) & 0xff00;		\
96546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	dst = d1 | d;						\
96646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } while(0)
96746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
96846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
96946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * For 16bpp pixels, we have stored the 5 most significant alpha bits in
97046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * bits 5-10. As before, we can process all 3 RGB components at the same time.
97146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */
97246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define BLIT_TRANSL_565(src, dst)		\
97346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do {					\
97446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 s = src;				\
97546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 d = dst;				\
97646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	unsigned alpha = (s & 0x3e0) >> 5;	\
97746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	s &= 0x07e0f81f;			\
97846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	d = (d | d << 16) & 0x07e0f81f;		\
97946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	d += (s - d) * alpha >> 5;		\
98046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	d &= 0x07e0f81f;			\
98146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	dst = (Uint16)(d | d >> 16);			\
98246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } while(0)
98346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
98446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define BLIT_TRANSL_555(src, dst)		\
98546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do {					\
98646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 s = src;				\
98746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 d = dst;				\
98846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	unsigned alpha = (s & 0x3e0) >> 5;	\
98946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	s &= 0x03e07c1f;			\
99046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	d = (d | d << 16) & 0x03e07c1f;		\
99146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	d += (s - d) * alpha >> 5;		\
99246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	d &= 0x03e07c1f;			\
99346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	dst = (Uint16)(d | d >> 16);			\
99446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } while(0)
99546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
99646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* used to save the destination format in the encoding. Designed to be
99746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   macro-compatible with SDL_PixelFormat but without the unneeded fields */
99846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnertypedef struct {
99946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint8  BytesPerPixel;
100046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint8  Rloss;
100146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint8  Gloss;
100246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint8  Bloss;
100346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint8  Rshift;
100446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint8  Gshift;
100546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint8  Bshift;
100646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint8  Ashift;
100746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 Rmask;
100846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 Gmask;
100946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 Bmask;
101046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 Amask;
101146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} RLEDestFormat;
101246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
101346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* blit a pixel-alpha RLE surface clipped at the right and/or left edges */
101446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void RLEAlphaClipBlit(int w, Uint8 *srcbuf, SDL_Surface *dst,
101546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			     Uint8 *dstbuf, SDL_Rect *srcrect)
101646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
101746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL_PixelFormat *df = dst->format;
101846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    /*
101946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     * clipped blitter: Ptype is the destination pixel type,
102046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     * Ctype the translucent count type, and do_blend the macro
102146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     * to blend one pixel.
102246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     */
102346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define RLEALPHACLIPBLIT(Ptype, Ctype, do_blend)			  \
102446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do {								  \
102546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int linecount = srcrect->h;					  \
102646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int left = srcrect->x;						  \
102746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int right = left + srcrect->w;					  \
102846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	dstbuf -= left * sizeof(Ptype);					  \
102946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	do {								  \
103046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    int ofs = 0;						  \
103146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    /* blit opaque pixels on one line */			  \
103246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    do {							  \
103346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		unsigned run;						  \
103446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		ofs += ((Ctype *)srcbuf)[0];				  \
103546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		run = ((Ctype *)srcbuf)[1];				  \
103646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		srcbuf += 2 * sizeof(Ctype);				  \
103746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if(run) {						  \
103846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    /* clip to left and right borders */		  \
103946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    int cofs = ofs;					  \
104046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    int crun = run;					  \
104146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    if(left - cofs > 0) {				  \
104246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			crun -= left - cofs;				  \
104346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			cofs = left;					  \
104446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    }							  \
104546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    if(crun > right - cofs)				  \
104646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			crun = right - cofs;				  \
104746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    if(crun > 0)					  \
104846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			PIXEL_COPY(dstbuf + cofs * sizeof(Ptype),	  \
104946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				   srcbuf + (cofs - ofs) * sizeof(Ptype), \
105046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				   (unsigned)crun, sizeof(Ptype));	  \
105146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    srcbuf += run * sizeof(Ptype);			  \
105246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    ofs += run;						  \
105346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		} else if(!ofs)						  \
105446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    return;						  \
105546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    } while(ofs < w);						  \
105646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    /* skip padding if necessary */				  \
105746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    if(sizeof(Ptype) == 2)					  \
105846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		srcbuf += (uintptr_t)srcbuf & 2;			  \
105946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    /* blit translucent pixels on the same line */		  \
106046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    ofs = 0;							  \
106146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    do {							  \
106246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		unsigned run;						  \
106346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		ofs += ((Uint16 *)srcbuf)[0];				  \
106446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		run = ((Uint16 *)srcbuf)[1];				  \
106546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		srcbuf += 4;						  \
106646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if(run) {						  \
106746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    /* clip to left and right borders */		  \
106846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    int cofs = ofs;					  \
106946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    int crun = run;					  \
107046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    if(left - cofs > 0) {				  \
107146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			crun -= left - cofs;				  \
107246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			cofs = left;					  \
107346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    }							  \
107446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    if(crun > right - cofs)				  \
107546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			crun = right - cofs;				  \
107646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    if(crun > 0) {					  \
107746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			Ptype *dst = (Ptype *)dstbuf + cofs;		  \
107846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			Uint32 *src = (Uint32 *)srcbuf + (cofs - ofs);	  \
107946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			int i;						  \
108046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			for(i = 0; i < crun; i++)			  \
108146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    do_blend(src[i], dst[i]);			  \
108246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    }							  \
108346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    srcbuf += run * 4;					  \
108446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    ofs += run;						  \
108546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}							  \
108646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    } while(ofs < w);						  \
108746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    dstbuf += dst->pitch;					  \
108846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	} while(--linecount);						  \
108946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } while(0)
109046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
109146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    switch(df->BytesPerPixel) {
109246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    case 2:
109346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if(df->Gmask == 0x07e0 || df->Rmask == 0x07e0
109446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	   || df->Bmask == 0x07e0)
109546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    RLEALPHACLIPBLIT(Uint16, Uint8, BLIT_TRANSL_565);
109646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	else
109746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    RLEALPHACLIPBLIT(Uint16, Uint8, BLIT_TRANSL_555);
109846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	break;
109946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    case 4:
110046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	RLEALPHACLIPBLIT(Uint32, Uint16, BLIT_TRANSL_888);
110146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	break;
110246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
110346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
110446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
110546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* blit a pixel-alpha RLE surface */
110646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_RLEAlphaBlit(SDL_Surface *src, SDL_Rect *srcrect,
110746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		     SDL_Surface *dst, SDL_Rect *dstrect)
110846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
110946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    int x, y;
111046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    int w = src->w;
111146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Uint8 *srcbuf, *dstbuf;
111246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL_PixelFormat *df = dst->format;
111346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
111446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    /* Lock the destination if necessary */
111546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if ( SDL_MUSTLOCK(dst) ) {
111646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( SDL_LockSurface(dst) < 0 ) {
111746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    return -1;
111846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
111946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
112046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
112146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    x = dstrect->x;
112246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    y = dstrect->y;
112346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    dstbuf = (Uint8 *)dst->pixels
112446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	     + y * dst->pitch + x * df->BytesPerPixel;
112546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    srcbuf = (Uint8 *)src->map->sw_data->aux_data + sizeof(RLEDestFormat);
112646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
112746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    {
112846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* skip lines at the top if necessary */
112946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int vskip = srcrect->y;
113046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if(vskip) {
113146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    int ofs;
113246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    if(df->BytesPerPixel == 2) {
113346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* the 16/32 interleaved format */
113446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		do {
113546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    /* skip opaque line */
113646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    ofs = 0;
113746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    do {
113846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			int run;
113946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			ofs += srcbuf[0];
114046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			run = srcbuf[1];
114146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			srcbuf += 2;
114246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if(run) {
114346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    srcbuf += 2 * run;
114446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    ofs += run;
114546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			} else if(!ofs)
114646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    goto done;
114746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    } while(ofs < w);
114846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
114946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    /* skip padding */
115046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    srcbuf += (uintptr_t)srcbuf & 2;
115146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
115246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    /* skip translucent line */
115346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    ofs = 0;
115446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    do {
115546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			int run;
115646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			ofs += ((Uint16 *)srcbuf)[0];
115746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			run = ((Uint16 *)srcbuf)[1];
115846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			srcbuf += 4 * (run + 1);
115946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			ofs += run;
116046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    } while(ofs < w);
116146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		} while(--vskip);
116246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    } else {
116346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* the 32/32 interleaved format */
116446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		vskip <<= 1;	/* opaque and translucent have same format */
116546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		do {
116646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    ofs = 0;
116746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    do {
116846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			int run;
116946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			ofs += ((Uint16 *)srcbuf)[0];
117046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			run = ((Uint16 *)srcbuf)[1];
117146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			srcbuf += 4;
117246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if(run) {
117346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    srcbuf += 4 * run;
117446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    ofs += run;
117546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			} else if(!ofs)
117646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    goto done;
117746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    } while(ofs < w);
117846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		} while(--vskip);
117946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    }
118046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
118146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
118246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
118346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    /* if left or right edge clipping needed, call clip blit */
118446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if(srcrect->x || srcrect->w != src->w) {
118546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	RLEAlphaClipBlit(w, srcbuf, dst, dstbuf, srcrect);
118646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } else {
118746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
118846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/*
118946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	 * non-clipped blitter. Ptype is the destination pixel type,
119046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	 * Ctype the translucent count type, and do_blend the
119146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	 * macro to blend one pixel.
119246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	 */
119346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define RLEALPHABLIT(Ptype, Ctype, do_blend)				 \
119446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	do {								 \
119546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    int linecount = srcrect->h;					 \
119646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    do {							 \
119746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		int ofs = 0;						 \
119846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* blit opaque pixels on one line */			 \
119946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		do {							 \
120046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    unsigned run;					 \
120146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    ofs += ((Ctype *)srcbuf)[0];			 \
120246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    run = ((Ctype *)srcbuf)[1];				 \
120346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    srcbuf += 2 * sizeof(Ctype);			 \
120446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    if(run) {						 \
120546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			PIXEL_COPY(dstbuf + ofs * sizeof(Ptype), srcbuf, \
120646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				   run, sizeof(Ptype));			 \
120746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			srcbuf += run * sizeof(Ptype);			 \
120846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			ofs += run;					 \
120946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    } else if(!ofs)					 \
121046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			goto done;					 \
121146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		} while(ofs < w);					 \
121246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* skip padding if necessary */				 \
121346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if(sizeof(Ptype) == 2)					 \
121446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    srcbuf += (uintptr_t)srcbuf & 2;		 	 \
121546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* blit translucent pixels on the same line */		 \
121646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		ofs = 0;						 \
121746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		do {							 \
121846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    unsigned run;					 \
121946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    ofs += ((Uint16 *)srcbuf)[0];			 \
122046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    run = ((Uint16 *)srcbuf)[1];			 \
122146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    srcbuf += 4;					 \
122246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    if(run) {						 \
122346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			Ptype *dst = (Ptype *)dstbuf + ofs;		 \
122446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			unsigned i;					 \
122546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			for(i = 0; i < run; i++) {			 \
122646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    Uint32 src = *(Uint32 *)srcbuf;		 \
122746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    do_blend(src, *dst);			 \
122846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    srcbuf += 4;				 \
122946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    dst++;					 \
123046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}						 \
123146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			ofs += run;					 \
123246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    }							 \
123346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		} while(ofs < w);					 \
123446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		dstbuf += dst->pitch;					 \
123546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    } while(--linecount);					 \
123646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	} while(0)
123746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
123846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	switch(df->BytesPerPixel) {
123946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	case 2:
124046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    if(df->Gmask == 0x07e0 || df->Rmask == 0x07e0
124146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	       || df->Bmask == 0x07e0)
124246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		RLEALPHABLIT(Uint16, Uint8, BLIT_TRANSL_565);
124346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    else
124446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		RLEALPHABLIT(Uint16, Uint8, BLIT_TRANSL_555);
124546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    break;
124646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	case 4:
124746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    RLEALPHABLIT(Uint32, Uint16, BLIT_TRANSL_888);
124846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    break;
124946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
125046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
125146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
125246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner done:
125346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    /* Unlock the destination if necessary */
125446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if ( SDL_MUSTLOCK(dst) ) {
125546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_UnlockSurface(dst);
125646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
125746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return 0;
125846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
125946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
126046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
126146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Auxiliary functions:
126246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * The encoding functions take 32bpp rgb + a, and
126346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * return the number of bytes copied to the destination.
126446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * The decoding functions copy to 32bpp rgb + a, and
126546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * return the number of bytes copied from the source.
126646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * These are only used in the encoder and un-RLE code and are therefore not
126746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * highly optimised.
126846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */
126946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
127046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* encode 32bpp rgb + a into 16bpp rgb, losing alpha */
127146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int copy_opaque_16(void *dst, Uint32 *src, int n,
127246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			  SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt)
127346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
127446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    int i;
127546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Uint16 *d = dst;
127646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    for(i = 0; i < n; i++) {
127746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	unsigned r, g, b;
127846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	RGB_FROM_PIXEL(*src, sfmt, r, g, b);
127946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	PIXEL_FROM_RGB(*d, dfmt, r, g, b);
128046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	src++;
128146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	d++;
128246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
128346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return n * 2;
128446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
128546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
128646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* decode opaque pixels from 16bpp to 32bpp rgb + a */
128746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int uncopy_opaque_16(Uint32 *dst, void *src, int n,
128846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    RLEDestFormat *sfmt, SDL_PixelFormat *dfmt)
128946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
129046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    int i;
129146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Uint16 *s = src;
129246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    unsigned alpha = dfmt->Amask ? 255 : 0;
129346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    for(i = 0; i < n; i++) {
129446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	unsigned r, g, b;
129546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	RGB_FROM_PIXEL(*s, sfmt, r, g, b);
129646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, alpha);
129746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	s++;
129846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	dst++;
129946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
130046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return n * 2;
130146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
130246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
130346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
130446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
130546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* encode 32bpp rgb + a into 32bpp G0RAB format for blitting into 565 */
130646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int copy_transl_565(void *dst, Uint32 *src, int n,
130746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			   SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt)
130846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
130946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    int i;
131046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Uint32 *d = dst;
131146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    for(i = 0; i < n; i++) {
131246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	unsigned r, g, b, a;
131346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint16 pix;
131446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	RGBA_FROM_8888(*src, sfmt, r, g, b, a);
131546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	PIXEL_FROM_RGB(pix, dfmt, r, g, b);
131646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	*d = ((pix & 0x7e0) << 16) | (pix & 0xf81f) | ((a << 2) & 0x7e0);
131746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	src++;
131846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	d++;
131946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
132046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return n * 4;
132146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
132246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
132346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* encode 32bpp rgb + a into 32bpp G0RAB format for blitting into 555 */
132446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int copy_transl_555(void *dst, Uint32 *src, int n,
132546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			   SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt)
132646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
132746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    int i;
132846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Uint32 *d = dst;
132946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    for(i = 0; i < n; i++) {
133046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	unsigned r, g, b, a;
133146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint16 pix;
133246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	RGBA_FROM_8888(*src, sfmt, r, g, b, a);
133346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	PIXEL_FROM_RGB(pix, dfmt, r, g, b);
133446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	*d = ((pix & 0x3e0) << 16) | (pix & 0xfc1f) | ((a << 2) & 0x3e0);
133546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	src++;
133646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	d++;
133746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
133846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return n * 4;
133946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
134046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
134146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* decode translucent pixels from 32bpp GORAB to 32bpp rgb + a */
134246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int uncopy_transl_16(Uint32 *dst, void *src, int n,
134346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			    RLEDestFormat *sfmt, SDL_PixelFormat *dfmt)
134446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
134546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    int i;
134646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Uint32 *s = src;
134746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    for(i = 0; i < n; i++) {
134846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	unsigned r, g, b, a;
134946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 pix = *s++;
135046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	a = (pix & 0x3e0) >> 2;
135146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	pix = (pix & ~0x3e0) | pix >> 16;
135246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	RGB_FROM_PIXEL(pix, sfmt, r, g, b);
135346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, a);
135446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	dst++;
135546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
135646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return n * 4;
135746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
135846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
135946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* encode 32bpp rgba into 32bpp rgba, keeping alpha (dual purpose) */
136046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int copy_32(void *dst, Uint32 *src, int n,
136146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		   SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt)
136246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
136346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    int i;
136446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Uint32 *d = dst;
136546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    for(i = 0; i < n; i++) {
136646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	unsigned r, g, b, a;
136746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 pixel;
136846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	RGBA_FROM_8888(*src, sfmt, r, g, b, a);
136946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	PIXEL_FROM_RGB(pixel, dfmt, r, g, b);
137046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	*d++ = pixel | a << 24;
137146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	src++;
137246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
137346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return n * 4;
137446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
137546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
137646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* decode 32bpp rgba into 32bpp rgba, keeping alpha (dual purpose) */
137746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int uncopy_32(Uint32 *dst, void *src, int n,
137846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		     RLEDestFormat *sfmt, SDL_PixelFormat *dfmt)
137946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
138046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    int i;
138146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Uint32 *s = src;
138246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    for(i = 0; i < n; i++) {
138346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	unsigned r, g, b, a;
138446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 pixel = *s++;
138546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	RGB_FROM_PIXEL(pixel, sfmt, r, g, b);
138646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	a = pixel >> 24;
138746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, a);
138846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	dst++;
138946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
139046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return n * 4;
139146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
139246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
139346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ISOPAQUE(pixel, fmt) ((((pixel) & fmt->Amask) >> fmt->Ashift) == 255)
139446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
139546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ISTRANSL(pixel, fmt)	\
139646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    ((unsigned)((((pixel) & fmt->Amask) >> fmt->Ashift) - 1U) < 254U)
139746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
139846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* convert surface to be quickly alpha-blittable onto dest, if possible */
139946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int RLEAlphaSurface(SDL_Surface *surface)
140046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
140146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL_Surface *dest;
140246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL_PixelFormat *df;
140346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    int maxsize = 0;
140446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    int max_opaque_run;
140546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    int max_transl_run = 65535;
140646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    unsigned masksum;
140746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Uint8 *rlebuf, *dst;
140846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    int (*copy_opaque)(void *, Uint32 *, int,
140946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		       SDL_PixelFormat *, SDL_PixelFormat *);
141046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    int (*copy_transl)(void *, Uint32 *, int,
141146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		       SDL_PixelFormat *, SDL_PixelFormat *);
141246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
141346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    dest = surface->map->dst;
141446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if(!dest)
141546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return -1;
141646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    df = dest->format;
141746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if(surface->format->BitsPerPixel != 32)
141846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return -1;		/* only 32bpp source supported */
141946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
142046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    /* find out whether the destination is one we support,
142146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       and determine the max size of the encoded result */
142246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    masksum = df->Rmask | df->Gmask | df->Bmask;
142346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    switch(df->BytesPerPixel) {
142446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    case 2:
142546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* 16bpp: only support 565 and 555 formats */
142646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	switch(masksum) {
142746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	case 0xffff:
142846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    if(df->Gmask == 0x07e0
142946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	       || df->Rmask == 0x07e0 || df->Bmask == 0x07e0) {
143046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		copy_opaque = copy_opaque_16;
143146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		copy_transl = copy_transl_565;
143246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    } else
143346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return -1;
143446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    break;
143546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	case 0x7fff:
143646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    if(df->Gmask == 0x03e0
143746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	       || df->Rmask == 0x03e0 || df->Bmask == 0x03e0) {
143846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		copy_opaque = copy_opaque_16;
143946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		copy_transl = copy_transl_555;
144046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    } else
144146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return -1;
144246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    break;
144346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	default:
144446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    return -1;
144546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
144646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	max_opaque_run = 255;	/* runs stored as bytes */
144746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
144846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* worst case is alternating opaque and translucent pixels,
144946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	   with room for alignment padding between lines */
145046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	maxsize = surface->h * (2 + (4 + 2) * (surface->w + 1)) + 2;
145146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	break;
145246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    case 4:
145346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if(masksum != 0x00ffffff)
145446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    return -1;		/* requires unused high byte */
145546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	copy_opaque = copy_32;
145646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	copy_transl = copy_32;
145746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	max_opaque_run = 255;	/* runs stored as short ints */
145846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
145946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* worst case is alternating opaque and translucent pixels */
146046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	maxsize = surface->h * 2 * 4 * (surface->w + 1) + 4;
146146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	break;
146246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    default:
146346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return -1;		/* anything else unsupported right now */
146446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
146546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
146646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    maxsize += sizeof(RLEDestFormat);
146746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    rlebuf = (Uint8 *)SDL_malloc(maxsize);
146846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if(!rlebuf) {
146946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_OutOfMemory();
147046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return -1;
147146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
147246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    {
147346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* save the destination format so we can undo the encoding later */
147446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	RLEDestFormat *r = (RLEDestFormat *)rlebuf;
147546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	r->BytesPerPixel = df->BytesPerPixel;
147646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	r->Rloss = df->Rloss;
147746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	r->Gloss = df->Gloss;
147846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	r->Bloss = df->Bloss;
147946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	r->Rshift = df->Rshift;
148046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	r->Gshift = df->Gshift;
148146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	r->Bshift = df->Bshift;
148246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	r->Ashift = df->Ashift;
148346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	r->Rmask = df->Rmask;
148446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	r->Gmask = df->Gmask;
148546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	r->Bmask = df->Bmask;
148646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	r->Amask = df->Amask;
148746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
148846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    dst = rlebuf + sizeof(RLEDestFormat);
148946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
149046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    /* Do the actual encoding */
149146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    {
149246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int x, y;
149346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int h = surface->h, w = surface->w;
149446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_PixelFormat *sf = surface->format;
149546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 *src = (Uint32 *)surface->pixels;
149646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint8 *lastline = dst;	/* end of last non-blank line */
149746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
149846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* opaque counts are 8 or 16 bits, depending on target depth */
149946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ADD_OPAQUE_COUNTS(n, m)			\
150046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if(df->BytesPerPixel == 4) {		\
150146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    ((Uint16 *)dst)[0] = n;		\
150246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    ((Uint16 *)dst)[1] = m;		\
150346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    dst += 4;				\
150446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	} else {				\
150546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    dst[0] = n;				\
150646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    dst[1] = m;				\
150746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    dst += 2;				\
150846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
150946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
151046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* translucent counts are always 16 bit */
151146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ADD_TRANSL_COUNTS(n, m)		\
151246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	(((Uint16 *)dst)[0] = n, ((Uint16 *)dst)[1] = m, dst += 4)
151346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
151446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for(y = 0; y < h; y++) {
151546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    int runstart, skipstart;
151646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    int blankline = 0;
151746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    /* First encode all opaque pixels of a scan line */
151846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    x = 0;
151946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    do {
152046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		int run, skip, len;
152146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		skipstart = x;
152246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		while(x < w && !ISOPAQUE(src[x], sf))
152346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    x++;
152446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		runstart = x;
152546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		while(x < w && ISOPAQUE(src[x], sf))
152646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    x++;
152746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		skip = runstart - skipstart;
152846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if(skip == w)
152946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    blankline = 1;
153046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		run = x - runstart;
153146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		while(skip > max_opaque_run) {
153246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    ADD_OPAQUE_COUNTS(max_opaque_run, 0);
153346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    skip -= max_opaque_run;
153446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
153546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		len = MIN(run, max_opaque_run);
153646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		ADD_OPAQUE_COUNTS(skip, len);
153746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		dst += copy_opaque(dst, src + runstart, len, sf, df);
153846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		runstart += len;
153946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		run -= len;
154046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		while(run) {
154146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    len = MIN(run, max_opaque_run);
154246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    ADD_OPAQUE_COUNTS(0, len);
154346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    dst += copy_opaque(dst, src + runstart, len, sf, df);
154446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    runstart += len;
154546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    run -= len;
154646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
154746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    } while(x < w);
154846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
154946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    /* Make sure the next output address is 32-bit aligned */
155046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    dst += (uintptr_t)dst & 2;
155146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
155246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    /* Next, encode all translucent pixels of the same scan line */
155346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    x = 0;
155446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    do {
155546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		int run, skip, len;
155646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		skipstart = x;
155746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		while(x < w && !ISTRANSL(src[x], sf))
155846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    x++;
155946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		runstart = x;
156046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		while(x < w && ISTRANSL(src[x], sf))
156146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    x++;
156246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		skip = runstart - skipstart;
156346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		blankline &= (skip == w);
156446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		run = x - runstart;
156546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		while(skip > max_transl_run) {
156646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    ADD_TRANSL_COUNTS(max_transl_run, 0);
156746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    skip -= max_transl_run;
156846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
156946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		len = MIN(run, max_transl_run);
157046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		ADD_TRANSL_COUNTS(skip, len);
157146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		dst += copy_transl(dst, src + runstart, len, sf, df);
157246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		runstart += len;
157346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		run -= len;
157446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		while(run) {
157546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    len = MIN(run, max_transl_run);
157646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    ADD_TRANSL_COUNTS(0, len);
157746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    dst += copy_transl(dst, src + runstart, len, sf, df);
157846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    runstart += len;
157946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    run -= len;
158046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
158146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if(!blankline)
158246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    lastline = dst;
158346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    } while(x < w);
158446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
158546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    src += surface->pitch >> 2;
158646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
158746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	dst = lastline;		/* back up past trailing blank lines */
158846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	ADD_OPAQUE_COUNTS(0, 0);
158946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
159046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
159146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#undef ADD_OPAQUE_COUNTS
159246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#undef ADD_TRANSL_COUNTS
159346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
159446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    /* Now that we have it encoded, release the original pixels */
159546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if((surface->flags & SDL_PREALLOC) != SDL_PREALLOC
159646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       && (surface->flags & SDL_HWSURFACE) != SDL_HWSURFACE) {
159746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_free( surface->pixels );
159846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	surface->pixels = NULL;
159946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
160046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
160146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    /* realloc the buffer to release unused memory */
160246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    {
160346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint8 *p = SDL_realloc(rlebuf, dst - rlebuf);
160446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if(!p)
160546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    p = rlebuf;
160646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	surface->map->sw_data->aux_data = p;
160746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
160846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
160946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return 0;
161046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
161146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
161246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic Uint32 getpix_8(Uint8 *srcbuf)
161346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
161446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return *srcbuf;
161546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
161646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
161746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic Uint32 getpix_16(Uint8 *srcbuf)
161846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
161946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return *(Uint16 *)srcbuf;
162046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
162146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
162246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic Uint32 getpix_24(Uint8 *srcbuf)
162346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
162446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if SDL_BYTEORDER == SDL_LIL_ENDIAN
162546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return srcbuf[0] + (srcbuf[1] << 8) + (srcbuf[2] << 16);
162646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else
162746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return (srcbuf[0] << 16) + (srcbuf[1] << 8) + srcbuf[2];
162846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
162946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
163046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
163146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic Uint32 getpix_32(Uint8 *srcbuf)
163246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
163346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return *(Uint32 *)srcbuf;
163446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
163546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
163646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnertypedef Uint32 (*getpix_func)(Uint8 *);
163746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
163846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic getpix_func getpixes[4] = {
163946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    getpix_8, getpix_16, getpix_24, getpix_32
164046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner};
164146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
164246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int RLEColorkeySurface(SDL_Surface *surface)
164346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
164446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        Uint8 *rlebuf, *dst;
164546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int maxn;
164646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int y;
164746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint8 *srcbuf, *curbuf, *lastline;
164846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int maxsize = 0;
164946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int skip, run;
165046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int bpp = surface->format->BytesPerPixel;
165146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	getpix_func getpix;
165246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint32 ckey, rgbmask;
165346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int w, h;
165446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
165546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* calculate the worst case size for the compressed surface */
165646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	switch(bpp) {
165746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	case 1:
165846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    /* worst case is alternating opaque and transparent pixels,
165946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	       starting with an opaque pixel */
166046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    maxsize = surface->h * 3 * (surface->w / 2 + 1) + 2;
166146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    break;
166246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	case 2:
166346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	case 3:
166446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    /* worst case is solid runs, at most 255 pixels wide */
166546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    maxsize = surface->h * (2 * (surface->w / 255 + 1)
166646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				    + surface->w * bpp) + 2;
166746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    break;
166846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	case 4:
166946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    /* worst case is solid runs, at most 65535 pixels wide */
167046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    maxsize = surface->h * (4 * (surface->w / 65535 + 1)
167146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				    + surface->w * 4) + 4;
167246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    break;
167346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
167446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
167546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	rlebuf = (Uint8 *)SDL_malloc(maxsize);
167646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( rlebuf == NULL ) {
167746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_OutOfMemory();
167846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return(-1);
167946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
168046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
168146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Set up the conversion */
168246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	srcbuf = (Uint8 *)surface->pixels;
168346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	curbuf = srcbuf;
168446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	maxn = bpp == 4 ? 65535 : 255;
168546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	skip = run = 0;
168646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	dst = rlebuf;
168746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	rgbmask = ~surface->format->Amask;
168846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	ckey = surface->format->colorkey & rgbmask;
168946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	lastline = dst;
169046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	getpix = getpixes[bpp - 1];
169146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	w = surface->w;
169246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	h = surface->h;
169346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
169446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ADD_COUNTS(n, m)			\
169546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if(bpp == 4) {				\
169646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    ((Uint16 *)dst)[0] = n;		\
169746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    ((Uint16 *)dst)[1] = m;		\
169846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    dst += 4;				\
169946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	} else {				\
170046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    dst[0] = n;				\
170146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    dst[1] = m;				\
170246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    dst += 2;				\
170346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
170446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
170546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for(y = 0; y < h; y++) {
170646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    int x = 0;
170746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    int blankline = 0;
170846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    do {
170946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		int run, skip, len;
171046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		int runstart;
171146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		int skipstart = x;
171246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
171346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* find run of transparent, then opaque pixels */
171446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		while(x < w && (getpix(srcbuf + x * bpp) & rgbmask) == ckey)
171546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    x++;
171646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		runstart = x;
171746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		while(x < w && (getpix(srcbuf + x * bpp) & rgbmask) != ckey)
171846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    x++;
171946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		skip = runstart - skipstart;
172046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if(skip == w)
172146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    blankline = 1;
172246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		run = x - runstart;
172346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
172446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* encode segment */
172546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		while(skip > maxn) {
172646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    ADD_COUNTS(maxn, 0);
172746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    skip -= maxn;
172846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
172946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		len = MIN(run, maxn);
173046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		ADD_COUNTS(skip, len);
173146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_memcpy(dst, srcbuf + runstart * bpp, len * bpp);
173246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		dst += len * bpp;
173346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		run -= len;
173446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		runstart += len;
173546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		while(run) {
173646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    len = MIN(run, maxn);
173746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    ADD_COUNTS(0, len);
173846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    SDL_memcpy(dst, srcbuf + runstart * bpp, len * bpp);
173946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    dst += len * bpp;
174046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    runstart += len;
174146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    run -= len;
174246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
174346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if(!blankline)
174446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    lastline = dst;
174546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    } while(x < w);
174646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
174746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    srcbuf += surface->pitch;
174846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
174946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	dst = lastline;		/* back up bast trailing blank lines */
175046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	ADD_COUNTS(0, 0);
175146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
175246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#undef ADD_COUNTS
175346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
175446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Now that we have it encoded, release the original pixels */
175546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if((surface->flags & SDL_PREALLOC) != SDL_PREALLOC
175646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	   && (surface->flags & SDL_HWSURFACE) != SDL_HWSURFACE) {
175746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    SDL_free( surface->pixels );
175846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    surface->pixels = NULL;
175946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
176046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
176146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* realloc the buffer to release unused memory */
176246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	{
176346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    /* If realloc returns NULL, the original block is left intact */
176446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    Uint8 *p = SDL_realloc(rlebuf, dst - rlebuf);
176546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    if(!p)
176646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		p = rlebuf;
176746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    surface->map->sw_data->aux_data = p;
176846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
176946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
177046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(0);
177146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
177246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
177346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_RLESurface(SDL_Surface *surface)
177446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
177546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int retcode;
177646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
177746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Clear any previous RLE conversion */
177846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
177946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_UnRLESurface(surface, 1);
178046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
178146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
178246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* We don't support RLE encoding of bitmaps */
178346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( surface->format->BitsPerPixel < 8 ) {
178446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return(-1);
178546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
178646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
178746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Lock the surface if it's in hardware */
178846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( SDL_MUSTLOCK(surface) ) {
178946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( SDL_LockSurface(surface) < 0 ) {
179046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			return(-1);
179146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
179246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
179346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
179446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Encode */
179546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if((surface->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
179646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    retcode = RLEColorkeySurface(surface);
179746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	} else {
179846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    if((surface->flags & SDL_SRCALPHA) == SDL_SRCALPHA
179946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	       && surface->format->Amask != 0)
180046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		retcode = RLEAlphaSurface(surface);
180146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    else
180246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		retcode = -1;	/* no RLE for per-surface alpha sans ckey */
180346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
180446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
180546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Unlock the surface if it's in hardware */
180646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( SDL_MUSTLOCK(surface) ) {
180746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_UnlockSurface(surface);
180846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
180946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
181046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if(retcode < 0)
181146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    return -1;
181246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
181346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* The surface is now accelerated */
181446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	surface->flags |= SDL_RLEACCEL;
181546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
181646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(0);
181746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
181846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
181946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
182046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Un-RLE a surface with pixel alpha
182146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * This may not give back exactly the image before RLE-encoding; all
182246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * completely transparent pixels will be lost, and colour and alpha depth
182346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * may have been reduced (when encoding for 16bpp targets).
182446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */
182546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic SDL_bool UnRLEAlpha(SDL_Surface *surface)
182646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
182746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Uint8 *srcbuf;
182846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Uint32 *dst;
182946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL_PixelFormat *sf = surface->format;
183046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    RLEDestFormat *df = surface->map->sw_data->aux_data;
183146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    int (*uncopy_opaque)(Uint32 *, void *, int,
183246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			 RLEDestFormat *, SDL_PixelFormat *);
183346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    int (*uncopy_transl)(Uint32 *, void *, int,
183446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			 RLEDestFormat *, SDL_PixelFormat *);
183546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    int w = surface->w;
183646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    int bpp = df->BytesPerPixel;
183746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
183846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if(bpp == 2) {
183946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	uncopy_opaque = uncopy_opaque_16;
184046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	uncopy_transl = uncopy_transl_16;
184146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    } else {
184246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	uncopy_opaque = uncopy_transl = uncopy_32;
184346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
184446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
184546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    surface->pixels = SDL_malloc(surface->h * surface->pitch);
184646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if ( !surface->pixels ) {
184746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        return(SDL_FALSE);
184846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
184946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    /* fill background with transparent pixels */
185046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL_memset(surface->pixels, 0, surface->h * surface->pitch);
185146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
185246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    dst = surface->pixels;
185346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    srcbuf = (Uint8 *)(df + 1);
185446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    for(;;) {
185546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* copy opaque pixels */
185646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int ofs = 0;
185746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	do {
185846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    unsigned run;
185946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    if(bpp == 2) {
186046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		ofs += srcbuf[0];
186146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		run = srcbuf[1];
186246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		srcbuf += 2;
186346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    } else {
186446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		ofs += ((Uint16 *)srcbuf)[0];
186546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		run = ((Uint16 *)srcbuf)[1];
186646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		srcbuf += 4;
186746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    }
186846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    if(run) {
186946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		srcbuf += uncopy_opaque(dst + ofs, srcbuf, run, df, sf);
187046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		ofs += run;
187146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    } else if(!ofs)
187246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return(SDL_TRUE);
187346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	} while(ofs < w);
187446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
187546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* skip padding if needed */
187646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if(bpp == 2)
187746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    srcbuf += (uintptr_t)srcbuf & 2;
187846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
187946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* copy translucent pixels */
188046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	ofs = 0;
188146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	do {
188246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    unsigned run;
188346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    ofs += ((Uint16 *)srcbuf)[0];
188446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    run = ((Uint16 *)srcbuf)[1];
188546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    srcbuf += 4;
188646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    if(run) {
188746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		srcbuf += uncopy_transl(dst + ofs, srcbuf, run, df, sf);
188846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		ofs += run;
188946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    }
189046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	} while(ofs < w);
189146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	dst += surface->pitch >> 2;
189246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
189346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    /* Make the compiler happy */
189446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return(SDL_TRUE);
189546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
189646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
189746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SDL_UnRLESurface(SDL_Surface *surface, int recode)
189846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
189946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
190046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	surface->flags &= ~SDL_RLEACCEL;
190146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
190246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if(recode && (surface->flags & SDL_PREALLOC) != SDL_PREALLOC
190346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	   && (surface->flags & SDL_HWSURFACE) != SDL_HWSURFACE) {
190446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    if((surface->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
190546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_Rect full;
190646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		unsigned alpha_flag;
190746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
190846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* re-create the original surface */
190946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		surface->pixels = SDL_malloc(surface->h * surface->pitch);
191046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( !surface->pixels ) {
191146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			/* Oh crap... */
191246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			surface->flags |= SDL_RLEACCEL;
191346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			return;
191446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
191546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
191646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* fill it with the background colour */
191746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_FillRect(surface, NULL, surface->format->colorkey);
191846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
191946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* now render the encoded surface */
192046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		full.x = full.y = 0;
192146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		full.w = surface->w;
192246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		full.h = surface->h;
192346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		alpha_flag = surface->flags & SDL_SRCALPHA;
192446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		surface->flags &= ~SDL_SRCALPHA; /* opaque blit */
192546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_RLEBlit(surface, &full, surface, &full);
192646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		surface->flags |= alpha_flag;
192746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    } else {
192846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( !UnRLEAlpha(surface) ) {
192946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    /* Oh crap... */
193046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    surface->flags |= SDL_RLEACCEL;
193146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    return;
193246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
193346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    }
193446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
193546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
193646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( surface->map && surface->map->sw_data->aux_data ) {
193746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    SDL_free(surface->map->sw_data->aux_data);
193846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    surface->map->sw_data->aux_data = NULL;
193946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
194046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
194146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
194246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
194346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1944