/* pygame - Python Game Library Copyright (C) 2000-2001 Pete Shinners Copyright (C) 2006 Rene Dudfield Copyright (C) 2007 Marcus von Appen 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 Pete Shinners pete@shinners.org */ #include "softBlitPyGame.h" /* The structure passed to the low level blit functions */ typedef struct { int width; int height; Uint8 *s_pixels; int s_pxskip; int s_skip; Uint8 *d_pixels; int d_pxskip; int d_skip; SDL_PixelFormat *src; SDL_PixelFormat *dst; Uint32 src_flags; Uint32 dst_flags; } SDL_BlitInfo; static void alphablit_alpha (SDL_BlitInfo * info); static void alphablit_colorkey (SDL_BlitInfo * info); static void alphablit_solid (SDL_BlitInfo * info); static void blit_blend_add (SDL_BlitInfo * info); static void blit_blend_sub (SDL_BlitInfo * info); static void blit_blend_mul (SDL_BlitInfo * info); static void blit_blend_min (SDL_BlitInfo * info); static void blit_blend_max (SDL_BlitInfo * info); static void blit_blend_rgba_add (SDL_BlitInfo * info); static void blit_blend_rgba_sub (SDL_BlitInfo * info); static void blit_blend_rgba_mul (SDL_BlitInfo * info); static void blit_blend_rgba_min (SDL_BlitInfo * info); static void blit_blend_rgba_max (SDL_BlitInfo * info); static int SoftBlitPyGame (SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect, int the_args); extern int SDL_RLESurface (SDL_Surface * surface); extern void SDL_UnRLESurface (SDL_Surface * surface, int recode); static int SoftBlitPyGame (SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect, int the_args) { int okay; int src_locked; int dst_locked; /* Everything is okay at the beginning... */ okay = 1; /* Lock the destination if it's in hardware */ dst_locked = 0; if (SDL_MUSTLOCK (dst)) { if (SDL_LockSurface (dst) < 0) okay = 0; else dst_locked = 1; } /* Lock the source if it's in hardware */ src_locked = 0; if (SDL_MUSTLOCK (src)) { if (SDL_LockSurface (src) < 0) okay = 0; else src_locked = 1; } /* Set up source and destination buffer pointers, and BLIT! */ if (okay && srcrect->w && srcrect->h) { SDL_BlitInfo info; /* Set up the blit information */ info.width = srcrect->w; info.height = srcrect->h; info.s_pixels = (Uint8 *) src->pixels + src->offset + (Uint16) srcrect->y * src->pitch + (Uint16) srcrect->x * src->format->BytesPerPixel; info.s_pxskip = src->format->BytesPerPixel; info.s_skip = src->pitch - info.width * src->format->BytesPerPixel; info.d_pixels = (Uint8 *) dst->pixels + dst->offset + (Uint16) dstrect->y * dst->pitch + (Uint16) dstrect->x * dst->format->BytesPerPixel; info.d_pxskip = dst->format->BytesPerPixel; info.d_skip = dst->pitch - info.width * dst->format->BytesPerPixel; info.src = src->format; info.dst = dst->format; info.src_flags = src->flags; info.dst_flags = dst->flags; if (info.d_pixels > info.s_pixels) { int span = info.width * info.src->BytesPerPixel; Uint8 *srcpixend = info.s_pixels + (info.height - 1) * src->pitch + span; if (info.d_pixels < srcpixend) { int dstoffset = (info.d_pixels - info.s_pixels) % src->pitch; if (dstoffset < span || dstoffset > src->pitch - span) { /* Overlapping Self blit with positive destination offset. Reverse direction of the blit. */ info.s_pixels = srcpixend - info.s_pxskip; info.s_pxskip = -info.s_pxskip; info.s_skip = -info.s_skip; info.d_pixels = (info.d_pixels + (info.height - 1) * dst->pitch + span - info.d_pxskip); info.d_pxskip = -info.d_pxskip; info.d_skip = -info.d_skip; } } } switch (the_args) { case 0: { if (src->flags & SDL_SRCALPHA && src->format->Amask) alphablit_alpha (&info); else if (src->flags & SDL_SRCCOLORKEY) alphablit_colorkey (&info); else alphablit_solid (&info); break; } case PYGAME_BLEND_ADD: { blit_blend_add (&info); break; } case PYGAME_BLEND_SUB: { blit_blend_sub (&info); break; } case PYGAME_BLEND_MULT: { blit_blend_mul (&info); break; } case PYGAME_BLEND_MIN: { blit_blend_min (&info); break; } case PYGAME_BLEND_MAX: { blit_blend_max (&info); break; } case PYGAME_BLEND_RGBA_ADD: { blit_blend_rgba_add (&info); break; } case PYGAME_BLEND_RGBA_SUB: { blit_blend_rgba_sub (&info); break; } case PYGAME_BLEND_RGBA_MULT: { blit_blend_rgba_mul (&info); break; } case PYGAME_BLEND_RGBA_MIN: { blit_blend_rgba_min (&info); break; } case PYGAME_BLEND_RGBA_MAX: { blit_blend_rgba_max (&info); break; } default: { SDL_SetError ("Invalid argument passed to blit."); okay = 0; break; } } } /* We need to unlock the surfaces if they're locked */ if (dst_locked) SDL_UnlockSurface (dst); if (src_locked) SDL_UnlockSurface (src); /* Blit is done! */ return (okay ? 0 : -1); } /* --------------------------------------------------------- */ static void blit_blend_rgba_add (SDL_BlitInfo * info) { int n; int width = info->width; int height = info->height; Uint8 *src = info->s_pixels; int srcpxskip = info->s_pxskip; int srcskip = info->s_skip; Uint8 *dst = info->d_pixels; int dstpxskip = info->d_pxskip; int dstskip = info->d_skip; SDL_PixelFormat *srcfmt = info->src; SDL_PixelFormat *dstfmt = info->dst; int srcbpp = srcfmt->BytesPerPixel; int dstbpp = dstfmt->BytesPerPixel; Uint8 dR, dG, dB, dA, sR, sG, sB, sA; Uint32 pixel; Uint32 tmp; int srcppa = (info->src_flags & SDL_SRCALPHA && srcfmt->Amask); int dstppa = (info->dst_flags & SDL_SRCALPHA && dstfmt->Amask); if (!dstppa) { blit_blend_add (info); return; } if (srcbpp == 4 && dstbpp == 4 && srcfmt->Rmask == dstfmt->Rmask && srcfmt->Gmask == dstfmt->Gmask && srcfmt->Bmask == dstfmt->Bmask && srcfmt->Amask == dstfmt->Amask && info->src_flags & SDL_SRCALPHA) { int incr = srcpxskip > 0 ? 1 : -1; if (incr < 0) { src += 3; dst += 3; } while (height--) { LOOP_UNROLLED4( { REPEAT_4( { tmp = (*dst) + (*src); (*dst) = (tmp <= 255 ? tmp : 255); src += incr; dst += incr; }); }, n, width); src += srcskip; dst += dstskip; } return; } if (srcbpp == 1) { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); BLEND_RGBA_ADD (tmp, sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* dstbpp > 1 */ { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_RGBA_ADD (tmp, sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } else /* srcbpp > 1 */ { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); BLEND_RGBA_ADD (tmp, sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* dstbpp > 1 */ { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_RGBA_ADD (tmp, sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } } static void blit_blend_rgba_sub (SDL_BlitInfo * info) { int n; int width = info->width; int height = info->height; Uint8 *src = info->s_pixels; int srcpxskip = info->s_pxskip; int srcskip = info->s_skip; Uint8 *dst = info->d_pixels; int dstpxskip = info->d_pxskip; int dstskip = info->d_skip; SDL_PixelFormat *srcfmt = info->src; SDL_PixelFormat *dstfmt = info->dst; int srcbpp = srcfmt->BytesPerPixel; int dstbpp = dstfmt->BytesPerPixel; Uint8 dR, dG, dB, dA, sR, sG, sB, sA; Uint32 pixel; Sint32 tmp2; int srcppa = (info->src_flags & SDL_SRCALPHA && srcfmt->Amask); int dstppa = (info->dst_flags & SDL_SRCALPHA && dstfmt->Amask); if (!dstppa) { blit_blend_sub (info); return; } if (srcbpp == 4 && dstbpp == 4 && srcfmt->Rmask == dstfmt->Rmask && srcfmt->Gmask == dstfmt->Gmask && srcfmt->Bmask == dstfmt->Bmask && srcfmt->Amask == dstfmt->Amask && info->src_flags & SDL_SRCALPHA) { int incr = srcpxskip > 0 ? 1 : -1; if (incr < 0) { src += 3; dst += 3; } while (height--) { LOOP_UNROLLED4( { REPEAT_4( { tmp2 = (*dst) - (*src); (*dst) = (tmp2 >= 0 ? tmp2 : 0); src += incr; dst += incr; }); }, n, width); src += srcskip; dst += dstskip; } return; } if (srcbpp == 1) { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); BLEND_RGBA_SUB (tmp2, sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* dstbpp > 1 */ { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_RGBA_SUB (tmp2, sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } else /* srcbpp > 1 */ { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); BLEND_RGBA_SUB (tmp2, sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* dstbpp > 1 */ { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_RGBA_SUB (tmp2, sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } } static void blit_blend_rgba_mul (SDL_BlitInfo * info) { int n; int width = info->width; int height = info->height; Uint8 *src = info->s_pixels; int srcpxskip = info->s_pxskip; int srcskip = info->s_skip; Uint8 *dst = info->d_pixels; int dstpxskip = info->d_pxskip; int dstskip = info->d_skip; SDL_PixelFormat *srcfmt = info->src; SDL_PixelFormat *dstfmt = info->dst; int srcbpp = srcfmt->BytesPerPixel; int dstbpp = dstfmt->BytesPerPixel; Uint8 dR, dG, dB, dA, sR, sG, sB, sA; Uint32 pixel; Uint32 tmp; int srcppa = (info->src_flags & SDL_SRCALPHA && srcfmt->Amask); int dstppa = (info->dst_flags & SDL_SRCALPHA && dstfmt->Amask); if (!dstppa) { blit_blend_mul (info); return; } if (srcbpp == 4 && dstbpp == 4 && srcfmt->Rmask == dstfmt->Rmask && srcfmt->Gmask == dstfmt->Gmask && srcfmt->Bmask == dstfmt->Bmask && srcfmt->Amask == dstfmt->Amask && info->src_flags & SDL_SRCALPHA) { int incr = srcpxskip > 0 ? 1 : -1; if (incr < 0) { src += 3; dst += 3; } while (height--) { LOOP_UNROLLED4( { REPEAT_4( { tmp = ((*dst) && (*src)) ? ((*dst) * (*src)) >> 8 : 0; (*dst) = (tmp <= 255 ? tmp : 255); src += incr; dst += incr; }); }, n, width); src += srcskip; dst += dstskip; } return; } if (srcbpp == 1) { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); BLEND_RGBA_MULT (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* dstbpp > 1 */ { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_RGBA_MULT (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } else /* srcbpp > 1 */ { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); BLEND_RGBA_MULT (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* dstbpp > 1 */ { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_RGBA_MULT (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } } static void blit_blend_rgba_min (SDL_BlitInfo * info) { int n; int width = info->width; int height = info->height; Uint8 *src = info->s_pixels; int srcpxskip = info->s_pxskip; int srcskip = info->s_skip; Uint8 *dst = info->d_pixels; int dstpxskip = info->d_pxskip; int dstskip = info->d_skip; SDL_PixelFormat *srcfmt = info->src; SDL_PixelFormat *dstfmt = info->dst; int srcbpp = srcfmt->BytesPerPixel; int dstbpp = dstfmt->BytesPerPixel; Uint8 dR, dG, dB, dA, sR, sG, sB, sA; Uint32 pixel; int srcppa = (info->src_flags & SDL_SRCALPHA && srcfmt->Amask); int dstppa = (info->dst_flags & SDL_SRCALPHA && dstfmt->Amask); if (!dstppa) { blit_blend_min (info); return; } if (srcbpp == 4 && dstbpp == 4 && srcfmt->Rmask == dstfmt->Rmask && srcfmt->Gmask == dstfmt->Gmask && srcfmt->Bmask == dstfmt->Bmask && srcfmt->Amask == dstfmt->Amask && info->src_flags & SDL_SRCALPHA) { int incr = srcpxskip > 0 ? 1 : -1; if (incr < 0) { src += 3; dst += 3; } while (height--) { LOOP_UNROLLED4( { REPEAT_4( { if ((*src) < (*dst)) (*dst) = (*src); src += incr; dst += incr; }); }, n, width); src += srcskip; dst += dstskip; } return; } if (srcbpp == 1) { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); BLEND_RGBA_MIN (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* dstbpp > 1 */ { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_RGBA_MIN (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } else /* srcbpp > 1 */ { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); BLEND_RGBA_MIN (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* dstbpp > 1 */ { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_RGBA_MIN (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } } static void blit_blend_rgba_max (SDL_BlitInfo * info) { int n; int width = info->width; int height = info->height; Uint8 *src = info->s_pixels; int srcpxskip = info->s_pxskip; int srcskip = info->s_skip; Uint8 *dst = info->d_pixels; int dstpxskip = info->d_pxskip; int dstskip = info->d_skip; SDL_PixelFormat *srcfmt = info->src; SDL_PixelFormat *dstfmt = info->dst; int srcbpp = srcfmt->BytesPerPixel; int dstbpp = dstfmt->BytesPerPixel; Uint8 dR, dG, dB, dA, sR, sG, sB, sA; Uint32 pixel; int srcppa = (info->src_flags & SDL_SRCALPHA && srcfmt->Amask); int dstppa = (info->dst_flags & SDL_SRCALPHA && dstfmt->Amask); if (!dstppa) { blit_blend_max (info); return; } if (srcbpp == 4 && dstbpp == 4 && srcfmt->Rmask == dstfmt->Rmask && srcfmt->Gmask == dstfmt->Gmask && srcfmt->Bmask == dstfmt->Bmask && srcfmt->Amask == dstfmt->Amask && info->src_flags & SDL_SRCALPHA) { int incr = srcpxskip > 0 ? 1 : -1; if (incr < 0) { src += 3; dst += 3; } while (height--) { LOOP_UNROLLED4( { REPEAT_4( { if ((*src) > (*dst)) (*dst) = (*src); src += incr; dst += incr; }); }, n, width); src += srcskip; dst += dstskip; } return; } if (srcbpp == 1) { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); BLEND_RGBA_MAX (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* dstbpp > 1 */ { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_RGBA_MAX (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } else /* srcbpp > 1 */ { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); BLEND_RGBA_MAX (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* dstbpp > 1 */ { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_RGBA_MAX (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } } /* --------------------------------------------------------- */ static void blit_blend_add (SDL_BlitInfo * info) { int n; int width = info->width; int height = info->height; Uint8 *src = info->s_pixels; int srcpxskip = info->s_pxskip; int srcskip = info->s_skip; Uint8 *dst = info->d_pixels; int dstpxskip = info->d_pxskip; int dstskip = info->d_skip; SDL_PixelFormat *srcfmt = info->src; SDL_PixelFormat *dstfmt = info->dst; int srcbpp = srcfmt->BytesPerPixel; int dstbpp = dstfmt->BytesPerPixel; Uint8 dR, dG, dB, dA, sR, sG, sB, sA; Uint32 pixel; Uint32 tmp; int srcppa = (info->src_flags & SDL_SRCALPHA && srcfmt->Amask); int dstppa = (info->dst_flags & SDL_SRCALPHA && dstfmt->Amask); if (srcbpp >= 3 && dstbpp >= 3 && !(info->src_flags & SDL_SRCALPHA)) { size_t srcoffsetR, srcoffsetG, srcoffsetB; size_t dstoffsetR, dstoffsetG, dstoffsetB; if (srcbpp == 3) { SET_OFFSETS_24 (srcoffsetR, srcoffsetG, srcoffsetB, srcfmt); } else { SET_OFFSETS_32 (srcoffsetR, srcoffsetG, srcoffsetB, srcfmt); } if (dstbpp == 3) { SET_OFFSETS_24 (dstoffsetR, dstoffsetG, dstoffsetB, dstfmt); } else { SET_OFFSETS_32 (dstoffsetR, dstoffsetG, dstoffsetB, dstfmt); } while (height--) { LOOP_UNROLLED4( { tmp = dst[dstoffsetR] + src[srcoffsetR]; dst[dstoffsetR] = (tmp <= 255 ? tmp : 255); tmp = dst[dstoffsetG] + src[srcoffsetG]; dst[dstoffsetG] = (tmp <= 255 ? tmp : 255); tmp = dst[dstoffsetB] + src[srcoffsetB]; dst[dstoffsetB] = (tmp <= 255 ? tmp : 255); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } return; } if (srcbpp == 1) { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); BLEND_ADD (tmp, sR, sG, sB, sA, dR, dG, dB, dA); *dst = (Uint8) SDL_MapRGB (dstfmt, dR, dG, dB); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else if (dstbpp == 3) { size_t offsetR, offsetG, offsetB; SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt); while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_ADD (tmp, sR, sG, sB, sA, dR, dG, dB, dA); dst[offsetR] = dR; dst[offsetG] = dG; dst[offsetB] = dB; src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* even dstbpp */ { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_ADD (tmp, sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } else /* srcbpp > 1 */ { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); BLEND_ADD (tmp, sR, sG, sB, sA, dR, dG, dB, dA); *dst = (Uint8) SDL_MapRGB (dstfmt, dR, dG, dB); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else if (dstbpp == 3) { size_t offsetR, offsetG, offsetB; SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt); while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_ADD (tmp, sR, sG, sB, sA, dR, dG, dB, dA); dst[offsetR] = dR; dst[offsetG] = dG; dst[offsetB] = dB; src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* even dstbpp */ { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_ADD (tmp, sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } } static void blit_blend_sub (SDL_BlitInfo * info) { int n; int width = info->width; int height = info->height; Uint8 *src = info->s_pixels; int srcpxskip = info->s_pxskip; int srcskip = info->s_skip; Uint8 *dst = info->d_pixels; int dstpxskip = info->d_pxskip; int dstskip = info->d_skip; SDL_PixelFormat *srcfmt = info->src; SDL_PixelFormat *dstfmt = info->dst; int srcbpp = srcfmt->BytesPerPixel; int dstbpp = dstfmt->BytesPerPixel; Uint8 dR, dG, dB, dA, sR, sG, sB, sA; Uint32 pixel; Sint32 tmp2; int srcppa = (info->src_flags & SDL_SRCALPHA && srcfmt->Amask); int dstppa = (info->dst_flags & SDL_SRCALPHA && dstfmt->Amask); if (srcbpp >= 3 && dstbpp >= 3 && !(info->src_flags & SDL_SRCALPHA)) { size_t srcoffsetR, srcoffsetG, srcoffsetB; size_t dstoffsetR, dstoffsetG, dstoffsetB; if (srcbpp == 3) { SET_OFFSETS_24 (srcoffsetR, srcoffsetG, srcoffsetB, srcfmt); } else { SET_OFFSETS_32 (srcoffsetR, srcoffsetG, srcoffsetB, srcfmt); } if (dstbpp == 3) { SET_OFFSETS_24 (dstoffsetR, dstoffsetG, dstoffsetB, dstfmt); } else { SET_OFFSETS_32 (dstoffsetR, dstoffsetG, dstoffsetB, dstfmt); } while (height--) { LOOP_UNROLLED4( { tmp2 = dst[dstoffsetR] - src[srcoffsetR]; dst[dstoffsetR] = (tmp2 >= 0 ? tmp2 : 0); tmp2 = dst[dstoffsetG] - src[srcoffsetG]; dst[dstoffsetG] = (tmp2 >= 0 ? tmp2 : 0); tmp2 = dst[dstoffsetB] - src[srcoffsetB]; dst[dstoffsetB] = (tmp2 >= 0 ? tmp2 : 0); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } return; } if (srcbpp == 1) { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); BLEND_SUB (tmp2, sR, sG, sB, sA, dR, dG, dB, dA); *dst = (Uint8) SDL_MapRGB (dstfmt, dR, dG, dB); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else if (dstbpp == 3) { size_t offsetR, offsetG, offsetB; SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt); while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstfmt); BLEND_SUB (tmp2, sR, sG, sB, sA, dR, dG, dB, dA); dst[offsetR] = dR; dst[offsetG] = dG; dst[offsetB] = dB; src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* even dstbpp */ { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_SUB (tmp2, sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } else /* srcbpp > 1 */ { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); BLEND_SUB (tmp2, sR, sG, sB, sA, dR, dG, dB, dA); *dst = (Uint8) SDL_MapRGB (dstfmt, dR, dG, dB); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else if (dstbpp == 3) { size_t offsetR, offsetG, offsetB; SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt); while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_SUB (tmp2, sR, sG, sB, sA, dR, dG, dB, dA); dst[offsetR] = dR; dst[offsetG] = dG; dst[offsetB] = dB; src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* even dstbpp */ { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_SUB (tmp2, sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } } static void blit_blend_mul (SDL_BlitInfo * info) { int n; int width = info->width; int height = info->height; Uint8 *src = info->s_pixels; int srcpxskip = info->s_pxskip; int srcskip = info->s_skip; Uint8 *dst = info->d_pixels; int dstpxskip = info->d_pxskip; int dstskip = info->d_skip; SDL_PixelFormat *srcfmt = info->src; SDL_PixelFormat *dstfmt = info->dst; int srcbpp = srcfmt->BytesPerPixel; int dstbpp = dstfmt->BytesPerPixel; Uint8 dR, dG, dB, dA, sR, sG, sB, sA; Uint32 pixel; Uint32 tmp; int srcppa = (info->src_flags & SDL_SRCALPHA && srcfmt->Amask); int dstppa = (info->dst_flags & SDL_SRCALPHA && dstfmt->Amask); if (srcbpp >= 3 && dstbpp >= 3 && !(info->src_flags & SDL_SRCALPHA)) { size_t srcoffsetR, srcoffsetG, srcoffsetB; size_t dstoffsetR, dstoffsetG, dstoffsetB; if (srcbpp == 3) { SET_OFFSETS_24 (srcoffsetR, srcoffsetG, srcoffsetB, srcfmt); } else { SET_OFFSETS_32 (srcoffsetR, srcoffsetG, srcoffsetB, srcfmt); } if (dstbpp == 3) { SET_OFFSETS_24 (dstoffsetR, dstoffsetG, dstoffsetB, dstfmt); } else { SET_OFFSETS_32 (dstoffsetR, dstoffsetG, dstoffsetB, dstfmt); } while (height--) { LOOP_UNROLLED4( { tmp = ((dst[dstoffsetR] && src[srcoffsetR]) ? (dst[dstoffsetR] * src[srcoffsetR]) >> 8 : 0); dst[dstoffsetR] = (tmp <= 255 ? tmp : 255); tmp = ((dst[dstoffsetG] && src[srcoffsetG]) ? (dst[dstoffsetG] * src[srcoffsetG]) >> 8 : 0); dst[dstoffsetG] = (tmp <= 255 ? tmp : 255); tmp = ((dst[dstoffsetB] && src[srcoffsetB]) ? (dst[dstoffsetB] * src[srcoffsetB]) >> 8 : 0); dst[dstoffsetB] = (tmp <= 255 ? tmp : 255); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } return; } if (srcbpp == 1) { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); BLEND_MULT (sR, sG, sB, sA, dR, dG, dB, dA); *dst = (Uint8) SDL_MapRGB (dstfmt, dR, dG, dB); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else if (dstbpp == 3) { size_t offsetR, offsetG, offsetB; SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt); while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_MULT (sR, sG, sB, sA, dR, dG, dB, dA); dst[offsetR] = dR; dst[offsetG] = dG; dst[offsetB] = dB; src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* even dstbpp */ { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_MULT (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } else /* srcbpp > 1 */ { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); BLEND_MULT (sR, sG, sB, sA, dR, dG, dB, dA); *dst = (Uint8) SDL_MapRGB (dstfmt, dR, dG, dB); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else if (dstbpp == 3) { size_t offsetR, offsetG, offsetB; SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt); while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_MULT (sR, sG, sB, sA, dR, dG, dB, dA); dst[offsetR] = dR; dst[offsetG] = dG; dst[offsetB] = dB; src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* even dstbpp */ { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_MULT (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } } static void blit_blend_min (SDL_BlitInfo * info) { int n; int width = info->width; int height = info->height; Uint8 *src = info->s_pixels; int srcpxskip = info->s_pxskip; int srcskip = info->s_skip; Uint8 *dst = info->d_pixels; int dstpxskip = info->d_pxskip; int dstskip = info->d_skip; SDL_PixelFormat *srcfmt = info->src; SDL_PixelFormat *dstfmt = info->dst; int srcbpp = srcfmt->BytesPerPixel; int dstbpp = dstfmt->BytesPerPixel; Uint8 dR, dG, dB, dA, sR, sG, sB, sA; Uint32 pixel; int srcppa = (info->src_flags & SDL_SRCALPHA && srcfmt->Amask); int dstppa = (info->dst_flags & SDL_SRCALPHA && dstfmt->Amask); if (srcbpp >= 3 && dstbpp >= 3 && !(info->src_flags & SDL_SRCALPHA)) { size_t srcoffsetR, srcoffsetG, srcoffsetB; size_t dstoffsetR, dstoffsetG, dstoffsetB; if (srcbpp == 3) { SET_OFFSETS_24 (srcoffsetR, srcoffsetG, srcoffsetB, srcfmt); } else { SET_OFFSETS_32 (srcoffsetR, srcoffsetG, srcoffsetB, srcfmt); } if (dstbpp == 3) { SET_OFFSETS_24 (dstoffsetR, dstoffsetG, dstoffsetB, dstfmt); } else { SET_OFFSETS_32 (dstoffsetR, dstoffsetG, dstoffsetB, dstfmt); } while (height--) { LOOP_UNROLLED4( { if (src[srcoffsetR] < dst[dstoffsetR]) { dst[dstoffsetR] = src[srcoffsetR]; } if (src[srcoffsetG] < dst[dstoffsetG]) { dst[dstoffsetG] = src[srcoffsetG]; } if (src[srcoffsetB] < dst[dstoffsetB]) { dst[dstoffsetB] = src[srcoffsetB]; } src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } return; } if (srcbpp == 1) { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); BLEND_MIN (sR, sG, sB, sA, dR, dG, dB, dA); *dst = (Uint8) SDL_MapRGB (dstfmt, dR, dG, dB); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else if (dstbpp == 3) { size_t offsetR, offsetG, offsetB; SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt); while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_MIN (sR, sG, sB, sA, dR, dG, dB, dA); dst[offsetR] = dR; dst[offsetG] = dG; dst[offsetB] = dB; src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* even dstbpp */ { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_MIN (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } else /* srcbpp > 1 */ { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); BLEND_MIN (sR, sG, sB, sA, dR, dG, dB, dA); *dst = (Uint8) SDL_MapRGB (dstfmt, dR, dG, dB); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else if (dstbpp == 3) { size_t offsetR, offsetG, offsetB; SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt); while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_MIN (sR, sG, sB, sA, dR, dG, dB, dA); dst[offsetR] = dR; dst[offsetG] = dG; dst[offsetB] = dB; src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* even dstbpp */ { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_MIN (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } } static void blit_blend_max (SDL_BlitInfo * info) { int n; int width = info->width; int height = info->height; Uint8 *src = info->s_pixels; int srcpxskip = info->s_pxskip; int srcskip = info->s_skip; Uint8 *dst = info->d_pixels; int dstpxskip = info->d_pxskip; int dstskip = info->d_skip; SDL_PixelFormat *srcfmt = info->src; SDL_PixelFormat *dstfmt = info->dst; int srcbpp = srcfmt->BytesPerPixel; int dstbpp = dstfmt->BytesPerPixel; Uint8 dR, dG, dB, dA, sR, sG, sB, sA; Uint32 pixel; int srcppa = (info->src_flags & SDL_SRCALPHA && srcfmt->Amask); int dstppa = (info->dst_flags & SDL_SRCALPHA && dstfmt->Amask); if (srcbpp >= 3 && dstbpp >= 3 && !(info->src_flags & SDL_SRCALPHA)) { size_t srcoffsetR, srcoffsetG, srcoffsetB; size_t dstoffsetR, dstoffsetG, dstoffsetB; if (srcbpp == 3) { SET_OFFSETS_24 (srcoffsetR, srcoffsetG, srcoffsetB, srcfmt); } else { SET_OFFSETS_32 (srcoffsetR, srcoffsetG, srcoffsetB, srcfmt); } if (dstbpp == 3) { SET_OFFSETS_24 (dstoffsetR, dstoffsetG, dstoffsetB, dstfmt); } else { SET_OFFSETS_32 (dstoffsetR, dstoffsetG, dstoffsetB, dstfmt); } while (height--) { LOOP_UNROLLED4( { if (src[srcoffsetR] > dst[dstoffsetR]) { dst[dstoffsetR] = src[srcoffsetR]; } if (src[srcoffsetG] > dst[dstoffsetG]) { dst[dstoffsetG] = src[srcoffsetG]; } if (src[srcoffsetB] > dst[dstoffsetB]) { dst[dstoffsetB] = src[srcoffsetB]; } src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } return; } if (srcbpp == 1) { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); BLEND_MAX (sR, sG, sB, sA, dR, dG, dB, dA); *dst = (Uint8) SDL_MapRGB (dstfmt, dR, dG, dB); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else if (dstbpp == 3) { size_t offsetR, offsetG, offsetB; SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt); while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_MAX (sR, sG, sB, sA, dR, dG, dB, dA); dst[offsetR] = dR; dst[offsetG] = dG; dst[offsetB] = dB; src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* even dstbpp */ { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_MAX (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } else /* srcbpp > 1 */ { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); BLEND_MAX (sR, sG, sB, sA, dR, dG, dB, dA); *dst = (Uint8) SDL_MapRGB (dstfmt, dR, dG, dB); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else if (dstbpp == 3) { size_t offsetR, offsetG, offsetB; SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt); while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_MAX (sR, sG, sB, sA, dR, dG, dB, dA); dst[offsetR] = dR; dst[offsetG] = dG; dst[offsetB] = dB; src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* even dstbpp */ { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); BLEND_MAX (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } } /* --------------------------------------------------------- */ static void alphablit_alpha (SDL_BlitInfo * info) { int n; int width = info->width; int height = info->height; Uint8 *src = info->s_pixels; int srcpxskip = info->s_pxskip; int srcskip = info->s_skip; Uint8 *dst = info->d_pixels; int dstpxskip = info->d_pxskip; int dstskip = info->d_skip; SDL_PixelFormat *srcfmt = info->src; SDL_PixelFormat *dstfmt = info->dst; int srcbpp = srcfmt->BytesPerPixel; int dstbpp = dstfmt->BytesPerPixel; int dR, dG, dB, dA, sR, sG, sB, sA; Uint32 pixel; int srcppa = (info->src_flags & SDL_SRCALPHA && srcfmt->Amask); int dstppa = (info->dst_flags & SDL_SRCALPHA && dstfmt->Amask); /* printf ("Alpha blit with %d and %d\n", srcbpp, dstbpp); */ if (srcbpp == 1) { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); ALPHA_BLEND (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* dstbpp > 1 */ { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); ALPHA_BLEND (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } else /* srcbpp > 1 */ { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); ALPHA_BLEND (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* dstbpp > 1 */ { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); ALPHA_BLEND (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } } static void alphablit_colorkey (SDL_BlitInfo * info) { int n; int width = info->width; int height = info->height; Uint8 *src = info->s_pixels; int srcpxskip = info->s_pxskip; int srcskip = info->s_skip; Uint8 *dst = info->d_pixels; int dstpxskip = info->d_pxskip; int dstskip = info->d_skip; SDL_PixelFormat *srcfmt = info->src; SDL_PixelFormat *dstfmt = info->dst; int srcbpp = srcfmt->BytesPerPixel; int dstbpp = dstfmt->BytesPerPixel; int dR, dG, dB, dA, sR, sG, sB, sA; int alpha = srcfmt->alpha; Uint32 colorkey = srcfmt->colorkey; Uint32 pixel; int srcppa = (info->src_flags & SDL_SRCALPHA && srcfmt->Amask); int dstppa = (info->dst_flags & SDL_SRCALPHA && dstfmt->Amask); /* printf ("Colorkey blit with %d and %d\n", srcbpp, dstbpp); */ if (srcbpp == 1) { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); sA = (*src == colorkey) ? 0 : alpha; GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); ALPHA_BLEND (sR, sG, sB, sA, dR, dG, dB, dA); *dst = (Uint8) SDL_MapRGB (dstfmt, dR, dG, dB); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* dstbpp > 1 */ { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); sA = (*src == colorkey) ? 0 : alpha; GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); ALPHA_BLEND (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } else /* srcbpp > 1 */ { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); sA = (pixel == colorkey) ? 0 : alpha; GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); ALPHA_BLEND (sR, sG, sB, sA, dR, dG, dB, dA); *dst = (Uint8) SDL_MapRGB (dstfmt, dR, dG, dB); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else if (dstbpp == 3) { /* This is interim code until SDL can properly handle self blits of surfaces with blanket alpha. */ size_t offsetR, offsetG, offsetB; SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt); while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); sA = (pixel == colorkey) ? 0 : alpha; GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); ALPHA_BLEND (sR, sG, sB, sA, dR, dG, dB, dA); dst[offsetR] = dR; dst[offsetG] = dG; dst[offsetB] = dB; src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* even dstbpp */ { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); sA = (pixel == colorkey) ? 0 : alpha; GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); ALPHA_BLEND (sR, sG, sB, sA, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } } static void alphablit_solid (SDL_BlitInfo * info) { int n; int width = info->width; int height = info->height; Uint8 *src = info->s_pixels; int srcpxskip = info->s_pxskip; int srcskip = info->s_skip; Uint8 *dst = info->d_pixels; int dstpxskip = info->d_pxskip; int dstskip = info->d_skip; SDL_PixelFormat *srcfmt = info->src; SDL_PixelFormat *dstfmt = info->dst; int srcbpp = srcfmt->BytesPerPixel; int dstbpp = dstfmt->BytesPerPixel; int dR, dG, dB, dA, sR, sG, sB, sA; int alpha = srcfmt->alpha; int pixel; int srcppa = (info->src_flags & SDL_SRCALPHA && srcfmt->Amask); int dstppa = (info->dst_flags & SDL_SRCALPHA && dstfmt->Amask); /* printf ("Solid blit with %d and %d\n", srcbpp, dstbpp); */ if (srcbpp == 1) { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); ALPHA_BLEND (sR, sG, sB, alpha, dR, dG, dB, dA); *dst = (Uint8) SDL_MapRGB (dstfmt, dR, dG, dB); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* dstbpp > 1 */ { while (height--) { LOOP_UNROLLED4( { GET_PIXELVALS_1(sR, sG, sB, sA, src, srcfmt); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); ALPHA_BLEND (sR, sG, sB, alpha, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } } else /* srcbpp > 1 */ { if (dstbpp == 1) { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXELVALS_1(dR, dG, dB, dA, dst, dstfmt); ALPHA_BLEND (sR, sG, sB, alpha, dR, dG, dB, dA); *dst = (Uint8) SDL_MapRGB (dstfmt, dR, dG, dB); src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else if (dstbpp == 3) { /* This is interim code until SDL can properly handle self blits of surfaces with blanket alpha. */ size_t offsetR, offsetG, offsetB; SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt); while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); ALPHA_BLEND (sR, sG, sB, alpha, dR, dG, dB, dA); dst[offsetR] = dR; dst[offsetG] = dG; dst[offsetB] = dB; src += srcpxskip; dst += dstpxskip; }, n, width); src += srcskip; dst += dstskip; } } else /* even dstbpp */ { while (height--) { LOOP_UNROLLED4( { GET_PIXEL(pixel, srcbpp, src); GET_PIXELVALS (sR, sG, sB, sA, pixel, srcfmt, srcppa); GET_PIXEL (pixel, dstbpp, dst); GET_PIXELVALS (dR, dG, dB, dA, pixel, dstfmt, dstppa); ALPHA_BLEND (sR, sG, sB, alpha, dR, dG, dB, dA); CREATE_PIXEL(dst, dR, dG, dB, dA, dstbpp, dstfmt); src += srcpxskip; dst += dstpxskip; }, n ,width); src += srcskip; dst += dstskip; } } } } /*we assume the "dst" has pixel alpha*/ int pygame_Blit (SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect, int the_args) { SDL_Rect fulldst; int srcx, srcy, w, h; /* Make sure the surfaces aren't locked */ if (!src || !dst) { SDL_SetError ("SDL_UpperBlit: passed a NULL surface"); return (-1); } if (src->locked || dst->locked) { SDL_SetError ("Surfaces must not be locked during blit"); return (-1); } /* If the destination rectangle is NULL, use the entire dest surface */ if (dstrect == NULL) { fulldst.x = fulldst.y = 0; dstrect = &fulldst; } /* clip the source rectangle to the source surface */ if (srcrect) { int maxw, maxh; srcx = srcrect->x; w = srcrect->w; if (srcx < 0) { w += srcx; dstrect->x -= srcx; srcx = 0; } maxw = src->w - srcx; if (maxw < w) w = maxw; srcy = srcrect->y; h = srcrect->h; if (srcy < 0) { h += srcy; dstrect->y -= srcy; srcy = 0; } maxh = src->h - srcy; if (maxh < h) h = maxh; } else { srcx = srcy = 0; w = src->w; h = src->h; } /* clip the destination rectangle against the clip rectangle */ { SDL_Rect *clip = &dst->clip_rect; int dx, dy; dx = clip->x - dstrect->x; if (dx > 0) { w -= dx; dstrect->x += dx; srcx += dx; } dx = dstrect->x + w - clip->x - clip->w; if (dx > 0) w -= dx; dy = clip->y - dstrect->y; if (dy > 0) { h -= dy; dstrect->y += dy; srcy += dy; } dy = dstrect->y + h - clip->y - clip->h; if (dy > 0) h -= dy; } if (w > 0 && h > 0) { SDL_Rect sr; sr.x = srcx; sr.y = srcy; sr.w = dstrect->w = w; sr.h = dstrect->h = h; return SoftBlitPyGame (src, &sr, dst, dstrect, the_args); } dstrect->w = dstrect->h = 0; return 0; } int pygame_AlphaBlit (SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect, int the_args) { return pygame_Blit (src, srcrect, dst, dstrect, the_args); }