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