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#include "SDL_video.h" 2546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_sysvideo.h" 2646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_blit.h" 2746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_RLEaccel_c.h" 2846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_pixels_c.h" 2946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 3046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && SDL_ASSEMBLY_ROUTINES 3146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MMX_ASMBLIT 3246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if (__GNUC__ > 2) /* SSE instructions aren't in GCC 2. */ 3346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define SSE_ASMBLIT 3446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 3546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 3646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 3746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if defined(MMX_ASMBLIT) 3846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_cpuinfo.h" 3946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "mmx.h" 4046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 4146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 4246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* The general purpose software blit routine */ 4346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SoftBlit(SDL_Surface *src, SDL_Rect *srcrect, 4446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Surface *dst, SDL_Rect *dstrect) 4546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 4646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int okay; 4746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int src_locked; 4846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int dst_locked; 4946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 5046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Everything is okay at the beginning... */ 5146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner okay = 1; 5246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 5346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Lock the destination if it's in hardware */ 5446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner dst_locked = 0; 5546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SDL_MUSTLOCK(dst) ) { 5646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SDL_LockSurface(dst) < 0 ) { 5746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner okay = 0; 5846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 5946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner dst_locked = 1; 6046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 6146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 6246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Lock the source if it's in hardware */ 6346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner src_locked = 0; 6446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SDL_MUSTLOCK(src) ) { 6546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SDL_LockSurface(src) < 0 ) { 6646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner okay = 0; 6746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 6846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner src_locked = 1; 6946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 7046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 7146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 7246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Set up source and destination buffer pointers, and BLIT! */ 7346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( okay && srcrect->w && srcrect->h ) { 7446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_BlitInfo info; 7546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_loblit RunBlit; 7646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 7746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Set up the blit information */ 7846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner info.s_pixels = (Uint8 *)src->pixels + 7946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner (Uint16)srcrect->y*src->pitch + 8046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner (Uint16)srcrect->x*src->format->BytesPerPixel; 8146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner info.s_width = srcrect->w; 8246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner info.s_height = srcrect->h; 8346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner info.s_skip=src->pitch-info.s_width*src->format->BytesPerPixel; 8446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner info.d_pixels = (Uint8 *)dst->pixels + 8546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner (Uint16)dstrect->y*dst->pitch + 8646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner (Uint16)dstrect->x*dst->format->BytesPerPixel; 8746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner info.d_width = dstrect->w; 8846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner info.d_height = dstrect->h; 8946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner info.d_skip=dst->pitch-info.d_width*dst->format->BytesPerPixel; 9046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner info.aux_data = src->map->sw_data->aux_data; 9146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner info.src = src->format; 9246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner info.table = src->map->table; 9346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner info.dst = dst->format; 9446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner RunBlit = src->map->sw_data->blit; 9546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 9646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Run the actual software blit */ 9746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner RunBlit(&info); 9846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 9946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 10046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* We need to unlock the surfaces if they're locked */ 10146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( dst_locked ) { 10246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_UnlockSurface(dst); 10346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 10446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( src_locked ) { 10546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_UnlockSurface(src); 10646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 10746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Blit is done! */ 10846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(okay ? 0 : -1); 10946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 11046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 11146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef MMX_ASMBLIT 11246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic __inline__ void SDL_memcpyMMX(Uint8 *to, const Uint8 *from, int len) 11346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 11446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int i; 11546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 11646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for(i=0; i<len/8; i++) { 11746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner __asm__ __volatile__ ( 11846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner " movq (%0), %%mm0\n" 11946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner " movq %%mm0, (%1)\n" 12046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner : : "r" (from), "r" (to) : "memory"); 12146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner from+=8; 12246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner to+=8; 12346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 12446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (len&7) 12546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_memcpy(to, from, len&7); 12646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 12746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 12846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef SSE_ASMBLIT 12946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic __inline__ void SDL_memcpySSE(Uint8 *to, const Uint8 *from, int len) 13046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 13146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int i; 13246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 13346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner __asm__ __volatile__ ( 13446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner " prefetchnta (%0)\n" 13546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner " prefetchnta 64(%0)\n" 13646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner " prefetchnta 128(%0)\n" 13746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner " prefetchnta 192(%0)\n" 13846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner : : "r" (from) ); 13946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 14046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for(i=0; i<len/8; i++) { 14146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner __asm__ __volatile__ ( 14246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner " prefetchnta 256(%0)\n" 14346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner " movq (%0), %%mm0\n" 14446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner " movntq %%mm0, (%1)\n" 14546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner : : "r" (from), "r" (to) : "memory"); 14646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner from+=8; 14746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner to+=8; 14846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 14946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (len&7) 15046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_memcpy(to, from, len&7); 15146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 15246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 15346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 15446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 15546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void SDL_BlitCopy(SDL_BlitInfo *info) 15646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 15746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint8 *src, *dst; 15846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int w, h; 15946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int srcskip, dstskip; 16046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 16146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner w = info->d_width*info->dst->BytesPerPixel; 16246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner h = info->d_height; 16346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner src = info->s_pixels; 16446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner dst = info->d_pixels; 16546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner srcskip = w+info->s_skip; 16646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner dstskip = w+info->d_skip; 16746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 16846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef SSE_ASMBLIT 16946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if(SDL_HasSSE()) 17046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner { 17146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner while ( h-- ) { 17246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_memcpySSE(dst, src, w); 17346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner src += srcskip; 17446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner dst += dstskip; 17546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 17646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner __asm__ __volatile__ ( 17746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner " emms\n" 17846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ::); 17946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 18046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner else 18146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 18246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef MMX_ASMBLIT 18346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if(SDL_HasMMX()) 18446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner { 18546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner while ( h-- ) { 18646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_memcpyMMX(dst, src, w); 18746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner src += srcskip; 18846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner dst += dstskip; 18946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 19046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner __asm__ __volatile__ ( 19146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner " emms\n" 19246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ::); 19346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 19446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner else 19546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 19646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner while ( h-- ) { 19746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_memcpy(dst, src, w); 19846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner src += srcskip; 19946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner dst += dstskip; 20046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 20146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 20246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 20346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void SDL_BlitCopyOverlap(SDL_BlitInfo *info) 20446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 20546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint8 *src, *dst; 20646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int w, h; 20746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int srcskip, dstskip; 20846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 20946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner w = info->d_width*info->dst->BytesPerPixel; 21046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner h = info->d_height; 21146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner src = info->s_pixels; 21246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner dst = info->d_pixels; 21346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner srcskip = w+info->s_skip; 21446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner dstskip = w+info->d_skip; 21546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( dst < src ) { 21646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner while ( h-- ) { 21746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_memcpy(dst, src, w); 21846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner src += srcskip; 21946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner dst += dstskip; 22046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 22146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 22246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner src += ((h-1) * srcskip); 22346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner dst += ((h-1) * dstskip); 22446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner while ( h-- ) { 22546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_revcpy(dst, src, w); 22646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner src -= srcskip; 22746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner dst -= dstskip; 22846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 22946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 23046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 23146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 23246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Figure out which of many blit routines to set up on a surface */ 23346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_CalculateBlit(SDL_Surface *surface) 23446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 23546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int blit_index; 23646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 23746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Clean everything out to start */ 23846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { 23946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_UnRLESurface(surface, 1); 24046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 24146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface->map->sw_blit = NULL; 24246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 24346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Figure out if an accelerated hardware blit is possible */ 24446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface->flags &= ~SDL_HWACCEL; 24546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( surface->map->identity ) { 24646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int hw_blit_ok; 24746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 24846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { 24946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* We only support accelerated blitting to hardware */ 25046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( surface->map->dst->flags & SDL_HWSURFACE ) { 25146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner hw_blit_ok = current_video->info.blit_hw; 25246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 25346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner hw_blit_ok = 0; 25446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 25546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) { 25646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner hw_blit_ok = current_video->info.blit_hw_CC; 25746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 25846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) { 25946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner hw_blit_ok = current_video->info.blit_hw_A; 26046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 26146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 26246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* We only support accelerated blitting to hardware */ 26346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( surface->map->dst->flags & SDL_HWSURFACE ) { 26446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner hw_blit_ok = current_video->info.blit_sw; 26546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 26646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner hw_blit_ok = 0; 26746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 26846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) { 26946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner hw_blit_ok = current_video->info.blit_sw_CC; 27046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 27146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) { 27246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner hw_blit_ok = current_video->info.blit_sw_A; 27346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 27446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 27546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( hw_blit_ok ) { 27646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_VideoDevice *video = current_video; 27746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_VideoDevice *this = current_video; 27846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner video->CheckHWBlit(this, surface, surface->map->dst); 27946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 28046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 28146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 28246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* if an alpha pixel format is specified, we can accelerate alpha blits */ 28346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (((surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE )&&(current_video->displayformatalphapixel)) 28446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner { 28546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( (surface->flags & SDL_SRCALPHA) ) 28646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( current_video->info.blit_hw_A ) { 28746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_VideoDevice *video = current_video; 28846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_VideoDevice *this = current_video; 28946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner video->CheckHWBlit(this, surface, surface->map->dst); 29046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 29146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 29246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 29346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Get the blit function index, based on surface mode */ 29446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */ 29546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner blit_index = 0; 29646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner blit_index |= (!!(surface->flags & SDL_SRCCOLORKEY)) << 0; 29746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( surface->flags & SDL_SRCALPHA 29846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner && (surface->format->alpha != SDL_ALPHA_OPAQUE 29946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner || surface->format->Amask) ) { 30046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner blit_index |= 2; 30146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 30246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 30346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Check for special "identity" case -- copy blit */ 30446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( surface->map->identity && blit_index == 0 ) { 30546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface->map->sw_data->blit = SDL_BlitCopy; 30646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 30746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Handle overlapping blits on the same surface */ 30846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( surface == surface->map->dst ) { 30946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface->map->sw_data->blit = SDL_BlitCopyOverlap; 31046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 31146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 31246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( surface->format->BitsPerPixel < 8 ) { 31346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface->map->sw_data->blit = 31446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_CalculateBlit0(surface, blit_index); 31546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 31646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner switch ( surface->format->BytesPerPixel ) { 31746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 1: 31846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface->map->sw_data->blit = 31946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_CalculateBlit1(surface, blit_index); 32046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 32146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 2: 32246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 3: 32346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 4: 32446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface->map->sw_data->blit = 32546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_CalculateBlitN(surface, blit_index); 32646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 32746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner default: 32846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface->map->sw_data->blit = NULL; 32946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 33046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 33146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 33246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 33346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Make sure we have a blit function */ 33446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( surface->map->sw_data->blit == NULL ) { 33546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_InvalidateMap(surface->map); 33646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("Blit combination not supported"); 33746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(-1); 33846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 33946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 34046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Choose software blitting function */ 34146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if(surface->flags & SDL_RLEACCELOK 34246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner && (surface->flags & SDL_HWACCEL) != SDL_HWACCEL) { 34346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 34446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if(surface->map->identity 34546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner && (blit_index == 1 34646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner || (blit_index == 3 && !surface->format->Amask))) { 34746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SDL_RLESurface(surface) == 0 ) 34846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface->map->sw_blit = SDL_RLEBlit; 34946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else if(blit_index == 2 && surface->format->Amask) { 35046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SDL_RLESurface(surface) == 0 ) 35146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface->map->sw_blit = SDL_RLEAlphaBlit; 35246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 35346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 35446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 35546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( surface->map->sw_blit == NULL ) { 35646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface->map->sw_blit = SDL_SoftBlit; 35746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 35846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(0); 35946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 36046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 361