Made the RLE code (semi) readable again

This commit is contained in:
Sam Lantinga 2014-06-25 01:35:17 -07:00
parent b4deeeba05
commit a8955f2640
1 changed files with 253 additions and 250 deletions

View File

@ -115,22 +115,22 @@
* This can be used for any RGB permutation of course. * This can be used for any RGB permutation of course.
*/ */
#define ALPHA_BLIT32_888(to, from, length, bpp, alpha) \ #define ALPHA_BLIT32_888(to, from, length, bpp, alpha) \
do { \ do { \
int i; \ int i; \
Uint32 *src = (Uint32 *)(from); \ Uint32 *src = (Uint32 *)(from); \
Uint32 *dst = (Uint32 *)(to); \ Uint32 *dst = (Uint32 *)(to); \
for(i = 0; i < (int)(length); i++) { \ for (i = 0; i < (int)(length); i++) { \
Uint32 s = *src++; \ Uint32 s = *src++; \
Uint32 d = *dst; \ Uint32 d = *dst; \
Uint32 s1 = s & 0xff00ff; \ Uint32 s1 = s & 0xff00ff; \
Uint32 d1 = d & 0xff00ff; \ Uint32 d1 = d & 0xff00ff; \
d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff; \ d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff; \
s &= 0xff00; \ s &= 0xff00; \
d &= 0xff00; \ d &= 0xff00; \
d = (d + ((s - d) * alpha >> 8)) & 0xff00; \ d = (d + ((s - d) * alpha >> 8)) & 0xff00; \
*dst++ = d1 | d; \ *dst++ = d1 | d; \
} \ } \
} while(0) } while (0)
/* /*
* For 16bpp pixels we can go a step further: put the middle component * For 16bpp pixels we can go a step further: put the middle component
@ -139,97 +139,97 @@
* 5 bits, we have to scale alpha down to 5 bits as well. * 5 bits, we have to scale alpha down to 5 bits as well.
*/ */
#define ALPHA_BLIT16_565(to, from, length, bpp, alpha) \ #define ALPHA_BLIT16_565(to, from, length, bpp, alpha) \
do { \ do { \
int i; \ int i; \
Uint16 *src = (Uint16 *)(from); \ Uint16 *src = (Uint16 *)(from); \
Uint16 *dst = (Uint16 *)(to); \ Uint16 *dst = (Uint16 *)(to); \
Uint32 ALPHA = alpha >> 3; \ Uint32 ALPHA = alpha >> 3; \
for(i = 0; i < (int)(length); i++) { \ for(i = 0; i < (int)(length); i++) { \
Uint32 s = *src++; \ Uint32 s = *src++; \
Uint32 d = *dst; \ Uint32 d = *dst; \
s = (s | s << 16) & 0x07e0f81f; \ s = (s | s << 16) & 0x07e0f81f; \
d = (d | d << 16) & 0x07e0f81f; \ d = (d | d << 16) & 0x07e0f81f; \
d += (s - d) * ALPHA >> 5; \ d += (s - d) * ALPHA >> 5; \
d &= 0x07e0f81f; \ d &= 0x07e0f81f; \
*dst++ = (Uint16)(d | d >> 16); \ *dst++ = (Uint16)(d | d >> 16); \
} \ } \
} while(0) } while(0)
#define ALPHA_BLIT16_555(to, from, length, bpp, alpha) \ #define ALPHA_BLIT16_555(to, from, length, bpp, alpha) \
do { \ do { \
int i; \ int i; \
Uint16 *src = (Uint16 *)(from); \ Uint16 *src = (Uint16 *)(from); \
Uint16 *dst = (Uint16 *)(to); \ Uint16 *dst = (Uint16 *)(to); \
Uint32 ALPHA = alpha >> 3; \ Uint32 ALPHA = alpha >> 3; \
for(i = 0; i < (int)(length); i++) { \ for(i = 0; i < (int)(length); i++) { \
Uint32 s = *src++; \ Uint32 s = *src++; \
Uint32 d = *dst; \ Uint32 d = *dst; \
s = (s | s << 16) & 0x03e07c1f; \ s = (s | s << 16) & 0x03e07c1f; \
d = (d | d << 16) & 0x03e07c1f; \ d = (d | d << 16) & 0x03e07c1f; \
d += (s - d) * ALPHA >> 5; \ d += (s - d) * ALPHA >> 5; \
d &= 0x03e07c1f; \ d &= 0x03e07c1f; \
*dst++ = (Uint16)(d | d >> 16); \ *dst++ = (Uint16)(d | d >> 16); \
} \ } \
} while(0) } while(0)
/* /*
* The general slow catch-all function, for remaining depths and formats * The general slow catch-all function, for remaining depths and formats
*/ */
#define ALPHA_BLIT_ANY(to, from, length, bpp, alpha) \ #define ALPHA_BLIT_ANY(to, from, length, bpp, alpha) \
do { \ do { \
int i; \ int i; \
Uint8 *src = from; \ Uint8 *src = from; \
Uint8 *dst = to; \ Uint8 *dst = to; \
for(i = 0; i < (int)(length); i++) { \ for (i = 0; i < (int)(length); i++) { \
Uint32 s, d; \ Uint32 s, d; \
unsigned rs, gs, bs, rd, gd, bd; \ unsigned rs, gs, bs, rd, gd, bd; \
switch(bpp) { \ switch (bpp) { \
case 2: \ case 2: \
s = *(Uint16 *)src; \ s = *(Uint16 *)src; \
d = *(Uint16 *)dst; \ d = *(Uint16 *)dst; \
break; \ break; \
case 3: \ case 3: \
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { \ if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { \
s = (src[0] << 16) | (src[1] << 8) | src[2]; \ s = (src[0] << 16) | (src[1] << 8) | src[2]; \
d = (dst[0] << 16) | (dst[1] << 8) | dst[2]; \ d = (dst[0] << 16) | (dst[1] << 8) | dst[2]; \
} else { \ } else { \
s = (src[2] << 16) | (src[1] << 8) | src[0]; \ s = (src[2] << 16) | (src[1] << 8) | src[0]; \
d = (dst[2] << 16) | (dst[1] << 8) | dst[0]; \ d = (dst[2] << 16) | (dst[1] << 8) | dst[0]; \
} \ } \
break; \ break; \
case 4: \ case 4: \
s = *(Uint32 *)src; \ s = *(Uint32 *)src; \
d = *(Uint32 *)dst; \ d = *(Uint32 *)dst; \
break; \ break; \
} \ } \
RGB_FROM_PIXEL(s, fmt, rs, gs, bs); \ RGB_FROM_PIXEL(s, fmt, rs, gs, bs); \
RGB_FROM_PIXEL(d, fmt, rd, gd, bd); \ RGB_FROM_PIXEL(d, fmt, rd, gd, bd); \
rd += (rs - rd) * alpha >> 8; \ rd += (rs - rd) * alpha >> 8; \
gd += (gs - gd) * alpha >> 8; \ gd += (gs - gd) * alpha >> 8; \
bd += (bs - bd) * alpha >> 8; \ bd += (bs - bd) * alpha >> 8; \
PIXEL_FROM_RGB(d, fmt, rd, gd, bd); \ PIXEL_FROM_RGB(d, fmt, rd, gd, bd); \
switch(bpp) { \ switch (bpp) { \
case 2: \ case 2: \
*(Uint16 *)dst = (Uint16)d; \ *(Uint16 *)dst = (Uint16)d; \
break; \ break; \
case 3: \ case 3: \
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { \ if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { \
dst[0] = (Uint8)(d >> 16); \ dst[0] = (Uint8)(d >> 16); \
dst[1] = (Uint8)(d >> 8); \ dst[1] = (Uint8)(d >> 8); \
dst[2] = (Uint8)(d); \ dst[2] = (Uint8)(d); \
} else { \ } else { \
dst[0] = (Uint8)d; \ dst[0] = (Uint8)d; \
dst[1] = (Uint8)(d >> 8); \ dst[1] = (Uint8)(d >> 8); \
dst[2] = (Uint8)(d >> 16); \ dst[2] = (Uint8)(d >> 16); \
} \ } \
break; \ break; \
case 4: \ case 4: \
*(Uint32 *)dst = d; \ *(Uint32 *)dst = d; \
break; \ break; \
} \ } \
src += bpp; \ src += bpp; \
dst += bpp; \ dst += bpp; \
} \ } \
} while(0) } while(0)
/* /*
@ -241,16 +241,16 @@
* add them. Then shift right and add the sum of the lowest bits. * add them. Then shift right and add the sum of the lowest bits.
*/ */
#define ALPHA_BLIT32_888_50(to, from, length, bpp, alpha) \ #define ALPHA_BLIT32_888_50(to, from, length, bpp, alpha) \
do { \ do { \
int i; \ int i; \
Uint32 *src = (Uint32 *)(from); \ Uint32 *src = (Uint32 *)(from); \
Uint32 *dst = (Uint32 *)(to); \ Uint32 *dst = (Uint32 *)(to); \
for(i = 0; i < (int)(length); i++) { \ for(i = 0; i < (int)(length); i++) { \
Uint32 s = *src++; \ Uint32 s = *src++; \
Uint32 d = *dst; \ Uint32 d = *dst; \
*dst++ = (((s & 0x00fefefe) + (d & 0x00fefefe)) >> 1) \ *dst++ = (((s & 0x00fefefe) + (d & 0x00fefefe)) >> 1) \
+ (s & d & 0x00010101); \ + (s & d & 0x00010101); \
} \ } \
} while(0) } while(0)
/* /*
@ -259,116 +259,118 @@
*/ */
/* helper: blend a single 16 bit pixel at 50% */ /* helper: blend a single 16 bit pixel at 50% */
#define BLEND16_50(dst, src, mask) \ #define BLEND16_50(dst, src, mask) \
do { \ do { \
Uint32 s = *src++; \ Uint32 s = *src++; \
Uint32 d = *dst; \ Uint32 d = *dst; \
*dst++ = (Uint16)((((s & mask) + (d & mask)) >> 1) + \ *dst++ = (Uint16)((((s & mask) + (d & mask)) >> 1) + \
(s & d & (~mask & 0xffff))); \ (s & d & (~mask & 0xffff))); \
} while(0) } while(0)
/* basic 16bpp blender. mask is the pixels to keep when adding. */ /* basic 16bpp blender. mask is the pixels to keep when adding. */
#define ALPHA_BLIT16_50(to, from, length, bpp, alpha, mask) \ #define ALPHA_BLIT16_50(to, from, length, bpp, alpha, mask) \
do { \ do { \
unsigned n = (length); \ unsigned n = (length); \
Uint16 *src = (Uint16 *)(from); \ Uint16 *src = (Uint16 *)(from); \
Uint16 *dst = (Uint16 *)(to); \ Uint16 *dst = (Uint16 *)(to); \
if(((uintptr_t)src ^ (uintptr_t)dst) & 3) { \ if (((uintptr_t)src ^ (uintptr_t)dst) & 3) { \
/* source and destination not in phase, blit one by one */ \ /* source and destination not in phase, blit one by one */ \
while(n--) \ while (n--) \
BLEND16_50(dst, src, mask); \ BLEND16_50(dst, src, mask); \
} else { \ } else { \
if((uintptr_t)src & 3) { \ if ((uintptr_t)src & 3) { \
/* first odd pixel */ \ /* first odd pixel */ \
BLEND16_50(dst, src, mask); \ BLEND16_50(dst, src, mask); \
n--; \ n--; \
} \ } \
for(; n > 1; n -= 2) { \ for (; n > 1; n -= 2) { \
Uint32 s = *(Uint32 *)src; \ Uint32 s = *(Uint32 *)src; \
Uint32 d = *(Uint32 *)dst; \ Uint32 d = *(Uint32 *)dst; \
*(Uint32 *)dst = ((s & (mask | mask << 16)) >> 1) \ *(Uint32 *)dst = ((s & (mask | mask << 16)) >> 1) \
+ ((d & (mask | mask << 16)) >> 1) \ + ((d & (mask | mask << 16)) >> 1) \
+ (s & d & (~(mask | mask << 16))); \ + (s & d & (~(mask | mask << 16))); \
src += 2; \ src += 2; \
dst += 2; \ dst += 2; \
} \ } \
if(n) \ if (n) \
BLEND16_50(dst, src, mask); /* last odd pixel */ \ BLEND16_50(dst, src, mask); /* last odd pixel */ \
} \ } \
} while(0) } while(0)
#define ALPHA_BLIT16_565_50(to, from, length, bpp, alpha) \ #define ALPHA_BLIT16_565_50(to, from, length, bpp, alpha) \
ALPHA_BLIT16_50(to, from, length, bpp, alpha, 0xf7de) ALPHA_BLIT16_50(to, from, length, bpp, alpha, 0xf7de)
#define ALPHA_BLIT16_555_50(to, from, length, bpp, alpha) \ #define ALPHA_BLIT16_555_50(to, from, length, bpp, alpha) \
ALPHA_BLIT16_50(to, from, length, bpp, alpha, 0xfbde) ALPHA_BLIT16_50(to, from, length, bpp, alpha, 0xfbde)
#define CHOOSE_BLIT(blitter, alpha, fmt) \ #define CHOOSE_BLIT(blitter, alpha, fmt) \
do { \ do { \
if(alpha == 255) { \ if (alpha == 255) { \
switch(fmt->BytesPerPixel) { \ switch (fmt->BytesPerPixel) { \
case 1: blitter(1, Uint8, OPAQUE_BLIT); break; \ case 1: blitter(1, Uint8, OPAQUE_BLIT); break; \
case 2: blitter(2, Uint8, OPAQUE_BLIT); break; \ case 2: blitter(2, Uint8, OPAQUE_BLIT); break; \
case 3: blitter(3, Uint8, OPAQUE_BLIT); break; \ case 3: blitter(3, Uint8, OPAQUE_BLIT); break; \
case 4: blitter(4, Uint16, OPAQUE_BLIT); break; \ case 4: blitter(4, Uint16, OPAQUE_BLIT); break; \
} \ } \
} else { \ } else { \
switch(fmt->BytesPerPixel) { \ switch (fmt->BytesPerPixel) { \
case 1: \ case 1: \
/* No 8bpp alpha blitting */ \ /* No 8bpp alpha blitting */ \
break; \ break; \
\ \
case 2: \ case 2: \
switch(fmt->Rmask | fmt->Gmask | fmt->Bmask) { \ switch (fmt->Rmask | fmt->Gmask | fmt->Bmask) { \
case 0xffff: \ case 0xffff: \
if(fmt->Gmask == 0x07e0 \ if (fmt->Gmask == 0x07e0 \
|| fmt->Rmask == 0x07e0 \ || fmt->Rmask == 0x07e0 \
|| fmt->Bmask == 0x07e0) { \ || fmt->Bmask == 0x07e0) { \
if(alpha == 128) \ if (alpha == 128) { \
blitter(2, Uint8, ALPHA_BLIT16_565_50); \ blitter(2, Uint8, ALPHA_BLIT16_565_50); \
else { \ } else { \
blitter(2, Uint8, ALPHA_BLIT16_565); \ blitter(2, Uint8, ALPHA_BLIT16_565); \
} \ } \
} else \ } else \
goto general16; \ goto general16; \
break; \ break; \
\ \
case 0x7fff: \ case 0x7fff: \
if(fmt->Gmask == 0x03e0 \ if (fmt->Gmask == 0x03e0 \
|| fmt->Rmask == 0x03e0 \ || fmt->Rmask == 0x03e0 \
|| fmt->Bmask == 0x03e0) { \ || fmt->Bmask == 0x03e0) { \
if(alpha == 128) \ if (alpha == 128) { \
blitter(2, Uint8, ALPHA_BLIT16_555_50); \ blitter(2, Uint8, ALPHA_BLIT16_555_50); \
else { \ } else { \
blitter(2, Uint8, ALPHA_BLIT16_555); \ blitter(2, Uint8, ALPHA_BLIT16_555); \
} \ } \
break; \ break; \
} \ } else \
/* fallthrough */ \ goto general16; \
\ break; \
default: \ \
general16: \ default: \
blitter(2, Uint8, ALPHA_BLIT_ANY); \ general16: \
} \ blitter(2, Uint8, ALPHA_BLIT_ANY); \
break; \ } \
\ break; \
case 3: \ \
blitter(3, Uint8, ALPHA_BLIT_ANY); \ case 3: \
break; \ blitter(3, Uint8, ALPHA_BLIT_ANY); \
\ break; \
case 4: \ \
if((fmt->Rmask | fmt->Gmask | fmt->Bmask) == 0x00ffffff \ case 4: \
&& (fmt->Gmask == 0xff00 || fmt->Rmask == 0xff00 \ if ((fmt->Rmask | fmt->Gmask | fmt->Bmask) == 0x00ffffff \
|| fmt->Bmask == 0xff00)) { \ && (fmt->Gmask == 0xff00 || fmt->Rmask == 0xff00 \
if(alpha == 128) \ || fmt->Bmask == 0xff00)) { \
blitter(4, Uint16, ALPHA_BLIT32_888_50); \ if (alpha == 128) { \
else \ blitter(4, Uint16, ALPHA_BLIT32_888_50); \
blitter(4, Uint16, ALPHA_BLIT32_888); \ } else { \
} else \ blitter(4, Uint16, ALPHA_BLIT32_888); \
blitter(4, Uint16, ALPHA_BLIT_ANY); \ } \
break; \ } else \
} \ blitter(4, Uint16, ALPHA_BLIT_ANY); \
} \ break; \
} \
} \
} while(0) } while(0)
/* /*
@ -381,48 +383,49 @@ RLEClipBlit(int w, Uint8 * srcbuf, SDL_Surface * surf_dst,
{ {
SDL_PixelFormat *fmt = surf_dst->format; SDL_PixelFormat *fmt = surf_dst->format;
#define RLECLIPBLIT(bpp, Type, do_blit) \ #define RLECLIPBLIT(bpp, Type, do_blit) \
do { \ do { \
int linecount = srcrect->h; \ int linecount = srcrect->h; \
int ofs = 0; \ int ofs = 0; \
int left = srcrect->x; \ int left = srcrect->x; \
int right = left + srcrect->w; \ int right = left + srcrect->w; \
dstbuf -= left * bpp; \ dstbuf -= left * bpp; \
for(;;) { \ for (;;) { \
int run; \ int run; \
ofs += *(Type *)srcbuf; \ ofs += *(Type *)srcbuf; \
run = ((Type *)srcbuf)[1]; \ run = ((Type *)srcbuf)[1]; \
srcbuf += 2 * sizeof(Type); \ srcbuf += 2 * sizeof(Type); \
if(run) { \ if (run) { \
/* clip to left and right borders */ \ /* clip to left and right borders */ \
if(ofs < right) { \ if (ofs < right) { \
int start = 0; \ int start = 0; \
int len = run; \ int len = run; \
int startcol; \ int startcol; \
if(left - ofs > 0) { \ if (left - ofs > 0) { \
start = left - ofs; \ start = left - ofs; \
len -= start; \ len -= start; \
if(len <= 0) \ if (len <= 0) \
goto nocopy ## bpp ## do_blit; \ goto nocopy ## bpp ## do_blit; \
} \ } \
startcol = ofs + start; \ startcol = ofs + start; \
if(len > right - startcol) \ if (len > right - startcol) \
len = right - startcol; \ len = right - startcol; \
do_blit(dstbuf + startcol * bpp, srcbuf + start * bpp, \ do_blit(dstbuf + startcol * bpp, srcbuf + start * bpp, \
len, bpp, alpha); \ len, bpp, alpha); \
} \ } \
nocopy ## bpp ## do_blit: \ nocopy ## bpp ## do_blit: \
srcbuf += run * bpp; \ srcbuf += run * bpp; \
ofs += run; \ ofs += run; \
} else if(!ofs) \ } else if (!ofs) \
break; \ break; \
if(ofs == w) { \ \
ofs = 0; \ if (ofs == w) { \
dstbuf += surf_dst->pitch; \ ofs = 0; \
if(!--linecount) \ dstbuf += surf_dst->pitch; \
break; \ if (!--linecount) \
} \ break; \
} \ } \
} \
} while(0) } while(0)
CHOOSE_BLIT(RLECLIPBLIT, alpha, fmt); CHOOSE_BLIT(RLECLIPBLIT, alpha, fmt);