Mercurial > sdl-ios-xcode
diff src/video/SDL_blit_1.c @ 0:74212992fb08
Initial revision
author | Sam Lantinga <slouken@lokigames.com> |
---|---|
date | Thu, 26 Apr 2001 16:45:43 +0000 |
parents | |
children | e85e03f195b4 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/video/SDL_blit_1.c Thu Apr 26 16:45:43 2001 +0000 @@ -0,0 +1,530 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id$"; +#endif + +#include <stdio.h> + +#include "SDL_types.h" +#include "SDL_video.h" +#include "SDL_blit.h" +#include "SDL_sysvideo.h" +#include "SDL_endian.h" + +/* Functions to blit from 8-bit surfaces to other surfaces */ + +static void Blit1to1(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int width, height; + Uint8 *src, *map, *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = info->d_pixels; + dstskip = info->d_skip; + map = info->table; + + while ( height-- ) { +#ifdef USE_DUFFS_LOOP + DUFFS_LOOP( + { + *dst = map[*src]; + } + dst++; + src++; + , width); +#else + for ( c=width; c; --c ) { + *dst = map[*src]; + dst++; + src++; + } +#endif + src += srcskip; + dst += dstskip; + } +} +/* This is now endian dependent */ +#if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) +#define HI 1 +#define LO 0 +#else /* ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) */ +#define HI 0 +#define LO 1 +#endif +static void Blit1to2(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int width, height; + Uint8 *src, *dst; + Uint16 *map; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = info->d_pixels; + dstskip = info->d_skip; + map = (Uint16 *)info->table; + +#ifdef USE_DUFFS_LOOP + while ( height-- ) { + DUFFS_LOOP( + { + *(Uint16 *)dst = map[*src++]; + dst += 2; + }, + width); + src += srcskip; + dst += dstskip; + } +#else + /* Memory align at 4-byte boundary, if necessary */ + if ( (long)dst & 0x03 ) { + /* Don't do anything if width is 0 */ + if ( width == 0 ) { + return; + } + --width; + + while ( height-- ) { + /* Perform copy alignment */ + *(Uint16 *)dst = map[*src++]; + dst += 2; + + /* Copy in 4 pixel chunks */ + for ( c=width/4; c; --c ) { + *(Uint32 *)dst = + (map[src[HI]]<<16)|(map[src[LO]]); + src += 2; + dst += 4; + *(Uint32 *)dst = + (map[src[HI]]<<16)|(map[src[LO]]); + src += 2; + dst += 4; + } + /* Get any leftovers */ + switch (width % 4) { + case 3: + *(Uint16 *)dst = map[*src++]; + dst += 2; + case 2: + *(Uint32 *)dst = + (map[src[HI]]<<16)|(map[src[LO]]); + src += 2; + dst += 4; + break; + case 1: + *(Uint16 *)dst = map[*src++]; + dst += 2; + break; + } + src += srcskip; + dst += dstskip; + } + } else { + while ( height-- ) { + /* Copy in 4 pixel chunks */ + for ( c=width/4; c; --c ) { + *(Uint32 *)dst = + (map[src[HI]]<<16)|(map[src[LO]]); + src += 2; + dst += 4; + *(Uint32 *)dst = + (map[src[HI]]<<16)|(map[src[LO]]); + src += 2; + dst += 4; + } + /* Get any leftovers */ + switch (width % 4) { + case 3: + *(Uint16 *)dst = map[*src++]; + dst += 2; + case 2: + *(Uint32 *)dst = + (map[src[HI]]<<16)|(map[src[LO]]); + src += 2; + dst += 4; + break; + case 1: + *(Uint16 *)dst = map[*src++]; + dst += 2; + break; + } + src += srcskip; + dst += dstskip; + } + } +#endif /* USE_DUFFS_LOOP */ +} +static void Blit1to3(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int o; + int width, height; + Uint8 *src, *map, *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = info->d_pixels; + dstskip = info->d_skip; + map = info->table; + + while ( height-- ) { +#ifdef USE_DUFFS_LOOP + DUFFS_LOOP( + { + o = *src * 4; + dst[0] = map[o++]; + dst[1] = map[o++]; + dst[2] = map[o++]; + } + src++; + dst += 3; + , width); +#else + for ( c=width; c; --c ) { + o = *src * 4; + dst[0] = map[o++]; + dst[1] = map[o++]; + dst[2] = map[o++]; + src++; + dst += 3; + } +#endif /* USE_DUFFS_LOOP */ + src += srcskip; + dst += dstskip; + } +} +static void Blit1to4(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int width, height; + Uint8 *src; + Uint32 *map, *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = (Uint32 *)info->d_pixels; + dstskip = info->d_skip/4; + map = (Uint32 *)info->table; + + while ( height-- ) { +#ifdef USE_DUFFS_LOOP + DUFFS_LOOP( + *dst++ = map[*src++]; + , width); +#else + for ( c=width/4; c; --c ) { + *dst++ = map[*src++]; + *dst++ = map[*src++]; + *dst++ = map[*src++]; + *dst++ = map[*src++]; + } + switch ( width % 4 ) { + case 3: + *dst++ = map[*src++]; + case 2: + *dst++ = map[*src++]; + case 1: + *dst++ = map[*src++]; + } +#endif /* USE_DUFFS_LOOP */ + src += srcskip; + dst += dstskip; + } +} + +static void Blit1to1Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + Uint8 *palmap = info->table; + Uint32 ckey = info->src->colorkey; + + if ( palmap ) { + while ( height-- ) { + DUFFS_LOOP( + { + if ( *src != ckey ) { + *dst = palmap[*src]; + } + dst++; + src++; + }, + width); + src += srcskip; + dst += dstskip; + } + } else { + while ( height-- ) { + DUFFS_LOOP( + { + if ( *src != ckey ) { + *dst = *src; + } + dst++; + src++; + }, + width); + src += srcskip; + dst += dstskip; + } + } +} + +static void Blit1to2Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip; + Uint16 *palmap = (Uint16 *)info->table; + Uint32 ckey = info->src->colorkey; + + /* Set up some basic variables */ + dstskip /= 2; + + while ( height-- ) { + DUFFS_LOOP( + { + if ( *src != ckey ) { + *dstp=palmap[*src]; + } + src++; + dstp++; + }, + width); + src += srcskip; + dstp += dstskip; + } +} + +static void Blit1to3Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + Uint8 *palmap = info->table; + Uint32 ckey = info->src->colorkey; + int o; + + while ( height-- ) { + DUFFS_LOOP( + { + if ( *src != ckey ) { + o = *src * 4; + dst[0] = palmap[o++]; + dst[1] = palmap[o++]; + dst[2] = palmap[o++]; + } + src++; + dst += 3; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +static void Blit1to4Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip; + Uint32 *palmap = (Uint32 *)info->table; + Uint32 ckey = info->src->colorkey; + + /* Set up some basic variables */ + dstskip /= 4; + + while ( height-- ) { + DUFFS_LOOP( + { + if ( *src != ckey ) { + *dstp = palmap[*src]; + } + src++; + dstp++; + }, + width); + src += srcskip; + dstp += dstskip; + } +} + +static void Blit1toNAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *dstfmt = info->dst; + const SDL_Color *srcpal = info->src->palette->colors; + int dstbpp; + const int A = info->src->alpha; + + /* Set up some basic variables */ + dstbpp = dstfmt->BytesPerPixel; + + while ( height-- ) { + int sR, sG, sB; + int dR, dG, dB; + DUFFS_LOOP4( + { + Uint32 pixel; + sR = srcpal[*src].r; + sG = srcpal[*src].g; + sB = srcpal[*src].b; + DISEMBLE_RGB(dst, dstbpp, dstfmt, + pixel, dR, dG, dB); + ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB); + ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB); + src++; + dst += dstbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +static void Blit1toNAlphaKey(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + const SDL_Color *srcpal = info->src->palette->colors; + Uint32 ckey = srcfmt->colorkey; + int dstbpp; + const int A = srcfmt->alpha; + + /* Set up some basic variables */ + dstbpp = dstfmt->BytesPerPixel; + + while ( height-- ) { + int sR, sG, sB; + int dR, dG, dB; + DUFFS_LOOP( + { + if ( *src != ckey ) { + Uint32 pixel; + sR = srcpal[*src].r; + sG = srcpal[*src].g; + sB = srcpal[*src].b; + DISEMBLE_RGB(dst, dstbpp, dstfmt, + pixel, dR, dG, dB); + ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB); + ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB); + } + src++; + dst += dstbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +static SDL_loblit one_blit[] = { + NULL, Blit1to1, Blit1to2, Blit1to3, Blit1to4 +}; + +static SDL_loblit one_blitkey[] = { + NULL, Blit1to1Key, Blit1to2Key, Blit1to3Key, Blit1to4Key +}; + +SDL_loblit SDL_CalculateBlit1(SDL_Surface *surface, int blit_index) +{ + int which; + SDL_PixelFormat *dstfmt; + + dstfmt = surface->map->dst->format; + if ( dstfmt->BitsPerPixel < 8 ) { + which = 0; + } else { + which = dstfmt->BytesPerPixel; + } + switch(blit_index) { + case 0: /* copy */ + return one_blit[which]; + + case 1: /* colorkey */ + return one_blitkey[which]; + + case 2: /* alpha */ + /* Supporting 8bpp->8bpp alpha is doable but requires lots of + tables which consume space and takes time to precompute, + so is better left to the user */ + return which >= 2 ? Blit1toNAlpha : NULL; + + case 3: /* alpha + colorkey */ + return which >= 2 ? Blit1toNAlphaKey : NULL; + + } + return NULL; +}