aboutsummaryrefslogtreecommitdiffstats
path: root/distrib/sdl-1.2.15/src/video/SDL_blit.c
diff options
context:
space:
mode:
authorJesse Hall <jessehall@google.com>2012-07-09 11:27:07 -0700
committerJesse Hall <jessehall@google.com>2012-07-22 00:35:08 -0700
commit9682c8870b8ff5e4ac2e4c70b759f791c6f38c1f (patch)
treeded6ee18c4e1f33df235e53615a6d65e2d64f4ef /distrib/sdl-1.2.15/src/video/SDL_blit.c
parent74b55003f76dbca96e4a26d98fe464081ca5341f (diff)
downloadexternal_qemu-9682c8870b8ff5e4ac2e4c70b759f791c6f38c1f.zip
external_qemu-9682c8870b8ff5e4ac2e4c70b759f791c6f38c1f.tar.gz
external_qemu-9682c8870b8ff5e4ac2e4c70b759f791c6f38c1f.tar.bz2
Import SDL release-1.2.15
Change-Id: I505c4aea24325cad475f217db5589814b4c75dbf
Diffstat (limited to 'distrib/sdl-1.2.15/src/video/SDL_blit.c')
-rw-r--r--distrib/sdl-1.2.15/src/video/SDL_blit.c360
1 files changed, 360 insertions, 0 deletions
diff --git a/distrib/sdl-1.2.15/src/video/SDL_blit.c b/distrib/sdl-1.2.15/src/video/SDL_blit.c
new file mode 100644
index 0000000..e3f194a
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/SDL_blit.c
@@ -0,0 +1,360 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+#include "SDL_video.h"
+#include "SDL_sysvideo.h"
+#include "SDL_blit.h"
+#include "SDL_RLEaccel_c.h"
+#include "SDL_pixels_c.h"
+
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && SDL_ASSEMBLY_ROUTINES
+#define MMX_ASMBLIT
+#if (__GNUC__ > 2) /* SSE instructions aren't in GCC 2. */
+#define SSE_ASMBLIT
+#endif
+#endif
+
+#if defined(MMX_ASMBLIT)
+#include "SDL_cpuinfo.h"
+#include "mmx.h"
+#endif
+
+/* The general purpose software blit routine */
+static int SDL_SoftBlit(SDL_Surface *src, SDL_Rect *srcrect,
+ SDL_Surface *dst, SDL_Rect *dstrect)
+{
+ int okay;
+ int src_locked;
+ int dst_locked;
+
+ /* Everything is okay at the beginning... */
+ okay = 1;
+
+ /* Lock the destination if it's in hardware */
+ dst_locked = 0;
+ if ( SDL_MUSTLOCK(dst) ) {
+ if ( SDL_LockSurface(dst) < 0 ) {
+ okay = 0;
+ } else {
+ dst_locked = 1;
+ }
+ }
+ /* Lock the source if it's in hardware */
+ src_locked = 0;
+ if ( SDL_MUSTLOCK(src) ) {
+ if ( SDL_LockSurface(src) < 0 ) {
+ okay = 0;
+ } else {
+ src_locked = 1;
+ }
+ }
+
+ /* Set up source and destination buffer pointers, and BLIT! */
+ if ( okay && srcrect->w && srcrect->h ) {
+ SDL_BlitInfo info;
+ SDL_loblit RunBlit;
+
+ /* Set up the blit information */
+ info.s_pixels = (Uint8 *)src->pixels +
+ (Uint16)srcrect->y*src->pitch +
+ (Uint16)srcrect->x*src->format->BytesPerPixel;
+ info.s_width = srcrect->w;
+ info.s_height = srcrect->h;
+ info.s_skip=src->pitch-info.s_width*src->format->BytesPerPixel;
+ info.d_pixels = (Uint8 *)dst->pixels +
+ (Uint16)dstrect->y*dst->pitch +
+ (Uint16)dstrect->x*dst->format->BytesPerPixel;
+ info.d_width = dstrect->w;
+ info.d_height = dstrect->h;
+ info.d_skip=dst->pitch-info.d_width*dst->format->BytesPerPixel;
+ info.aux_data = src->map->sw_data->aux_data;
+ info.src = src->format;
+ info.table = src->map->table;
+ info.dst = dst->format;
+ RunBlit = src->map->sw_data->blit;
+
+ /* Run the actual software blit */
+ RunBlit(&info);
+ }
+
+ /* We need to unlock the surfaces if they're locked */
+ if ( dst_locked ) {
+ SDL_UnlockSurface(dst);
+ }
+ if ( src_locked ) {
+ SDL_UnlockSurface(src);
+ }
+ /* Blit is done! */
+ return(okay ? 0 : -1);
+}
+
+#ifdef MMX_ASMBLIT
+static __inline__ void SDL_memcpyMMX(Uint8 *to, const Uint8 *from, int len)
+{
+ int i;
+
+ for(i=0; i<len/8; i++) {
+ __asm__ __volatile__ (
+ " movq (%0), %%mm0\n"
+ " movq %%mm0, (%1)\n"
+ : : "r" (from), "r" (to) : "memory");
+ from+=8;
+ to+=8;
+ }
+ if (len&7)
+ SDL_memcpy(to, from, len&7);
+}
+
+#ifdef SSE_ASMBLIT
+static __inline__ void SDL_memcpySSE(Uint8 *to, const Uint8 *from, int len)
+{
+ int i;
+
+ __asm__ __volatile__ (
+ " prefetchnta (%0)\n"
+ " prefetchnta 64(%0)\n"
+ " prefetchnta 128(%0)\n"
+ " prefetchnta 192(%0)\n"
+ : : "r" (from) );
+
+ for(i=0; i<len/8; i++) {
+ __asm__ __volatile__ (
+ " prefetchnta 256(%0)\n"
+ " movq (%0), %%mm0\n"
+ " movntq %%mm0, (%1)\n"
+ : : "r" (from), "r" (to) : "memory");
+ from+=8;
+ to+=8;
+ }
+ if (len&7)
+ SDL_memcpy(to, from, len&7);
+}
+#endif
+#endif
+
+static void SDL_BlitCopy(SDL_BlitInfo *info)
+{
+ Uint8 *src, *dst;
+ int w, h;
+ int srcskip, dstskip;
+
+ w = info->d_width*info->dst->BytesPerPixel;
+ h = info->d_height;
+ src = info->s_pixels;
+ dst = info->d_pixels;
+ srcskip = w+info->s_skip;
+ dstskip = w+info->d_skip;
+
+#ifdef SSE_ASMBLIT
+ if(SDL_HasSSE())
+ {
+ while ( h-- ) {
+ SDL_memcpySSE(dst, src, w);
+ src += srcskip;
+ dst += dstskip;
+ }
+ __asm__ __volatile__ (
+ " emms\n"
+ ::);
+ }
+ else
+#endif
+#ifdef MMX_ASMBLIT
+ if(SDL_HasMMX())
+ {
+ while ( h-- ) {
+ SDL_memcpyMMX(dst, src, w);
+ src += srcskip;
+ dst += dstskip;
+ }
+ __asm__ __volatile__ (
+ " emms\n"
+ ::);
+ }
+ else
+#endif
+ while ( h-- ) {
+ SDL_memcpy(dst, src, w);
+ src += srcskip;
+ dst += dstskip;
+ }
+}
+
+static void SDL_BlitCopyOverlap(SDL_BlitInfo *info)
+{
+ Uint8 *src, *dst;
+ int w, h;
+ int srcskip, dstskip;
+
+ w = info->d_width*info->dst->BytesPerPixel;
+ h = info->d_height;
+ src = info->s_pixels;
+ dst = info->d_pixels;
+ srcskip = w+info->s_skip;
+ dstskip = w+info->d_skip;
+ if ( dst < src ) {
+ while ( h-- ) {
+ SDL_memmove(dst, src, w);
+ src += srcskip;
+ dst += dstskip;
+ }
+ } else {
+ src += ((h-1) * srcskip);
+ dst += ((h-1) * dstskip);
+ while ( h-- ) {
+ SDL_revcpy(dst, src, w);
+ src -= srcskip;
+ dst -= dstskip;
+ }
+ }
+}
+
+/* Figure out which of many blit routines to set up on a surface */
+int SDL_CalculateBlit(SDL_Surface *surface)
+{
+ int blit_index;
+
+ /* Clean everything out to start */
+ if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
+ SDL_UnRLESurface(surface, 1);
+ }
+ surface->map->sw_blit = NULL;
+
+ /* Figure out if an accelerated hardware blit is possible */
+ surface->flags &= ~SDL_HWACCEL;
+ if ( surface->map->identity ) {
+ int hw_blit_ok;
+
+ if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
+ /* We only support accelerated blitting to hardware */
+ if ( surface->map->dst->flags & SDL_HWSURFACE ) {
+ hw_blit_ok = current_video->info.blit_hw;
+ } else {
+ hw_blit_ok = 0;
+ }
+ if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) {
+ hw_blit_ok = current_video->info.blit_hw_CC;
+ }
+ if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) {
+ hw_blit_ok = current_video->info.blit_hw_A;
+ }
+ } else {
+ /* We only support accelerated blitting to hardware */
+ if ( surface->map->dst->flags & SDL_HWSURFACE ) {
+ hw_blit_ok = current_video->info.blit_sw;
+ } else {
+ hw_blit_ok = 0;
+ }
+ if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) {
+ hw_blit_ok = current_video->info.blit_sw_CC;
+ }
+ if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) {
+ hw_blit_ok = current_video->info.blit_sw_A;
+ }
+ }
+ if ( hw_blit_ok ) {
+ SDL_VideoDevice *video = current_video;
+ SDL_VideoDevice *this = current_video;
+ video->CheckHWBlit(this, surface, surface->map->dst);
+ }
+ }
+
+ /* if an alpha pixel format is specified, we can accelerate alpha blits */
+ if (((surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE )&&(current_video->displayformatalphapixel))
+ {
+ if ( (surface->flags & SDL_SRCALPHA) )
+ if ( current_video->info.blit_hw_A ) {
+ SDL_VideoDevice *video = current_video;
+ SDL_VideoDevice *this = current_video;
+ video->CheckHWBlit(this, surface, surface->map->dst);
+ }
+ }
+
+ /* Get the blit function index, based on surface mode */
+ /* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */
+ blit_index = 0;
+ blit_index |= (!!(surface->flags & SDL_SRCCOLORKEY)) << 0;
+ if ( surface->flags & SDL_SRCALPHA
+ && (surface->format->alpha != SDL_ALPHA_OPAQUE
+ || surface->format->Amask) ) {
+ blit_index |= 2;
+ }
+
+ /* Check for special "identity" case -- copy blit */
+ if ( surface->map->identity && blit_index == 0 ) {
+ surface->map->sw_data->blit = SDL_BlitCopy;
+
+ /* Handle overlapping blits on the same surface */
+ if ( surface == surface->map->dst ) {
+ surface->map->sw_data->blit = SDL_BlitCopyOverlap;
+ }
+ } else {
+ if ( surface->format->BitsPerPixel < 8 ) {
+ surface->map->sw_data->blit =
+ SDL_CalculateBlit0(surface, blit_index);
+ } else {
+ switch ( surface->format->BytesPerPixel ) {
+ case 1:
+ surface->map->sw_data->blit =
+ SDL_CalculateBlit1(surface, blit_index);
+ break;
+ case 2:
+ case 3:
+ case 4:
+ surface->map->sw_data->blit =
+ SDL_CalculateBlitN(surface, blit_index);
+ break;
+ default:
+ surface->map->sw_data->blit = NULL;
+ break;
+ }
+ }
+ }
+ /* Make sure we have a blit function */
+ if ( surface->map->sw_data->blit == NULL ) {
+ SDL_InvalidateMap(surface->map);
+ SDL_SetError("Blit combination not supported");
+ return(-1);
+ }
+
+ /* Choose software blitting function */
+ if(surface->flags & SDL_RLEACCELOK
+ && (surface->flags & SDL_HWACCEL) != SDL_HWACCEL) {
+
+ if(surface->map->identity
+ && (blit_index == 1
+ || (blit_index == 3 && !surface->format->Amask))) {
+ if ( SDL_RLESurface(surface) == 0 )
+ surface->map->sw_blit = SDL_RLEBlit;
+ } else if(blit_index == 2 && surface->format->Amask) {
+ if ( SDL_RLESurface(surface) == 0 )
+ surface->map->sw_blit = SDL_RLEAlphaBlit;
+ }
+ }
+
+ if ( surface->map->sw_blit == NULL ) {
+ surface->map->sw_blit = SDL_SoftBlit;
+ }
+ return(0);
+}
+