1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/video/SDL_blit.c Thu Apr 26 16:45:43 2001 +0000
1.3 @@ -0,0 +1,294 @@
1.4 +/*
1.5 + SDL - Simple DirectMedia Layer
1.6 + Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga
1.7 +
1.8 + This library is free software; you can redistribute it and/or
1.9 + modify it under the terms of the GNU Library General Public
1.10 + License as published by the Free Software Foundation; either
1.11 + version 2 of the License, or (at your option) any later version.
1.12 +
1.13 + This library is distributed in the hope that it will be useful,
1.14 + but WITHOUT ANY WARRANTY; without even the implied warranty of
1.15 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1.16 + Library General Public License for more details.
1.17 +
1.18 + You should have received a copy of the GNU Library General Public
1.19 + License along with this library; if not, write to the Free
1.20 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1.21 +
1.22 + Sam Lantinga
1.23 + slouken@devolution.com
1.24 +*/
1.25 +
1.26 +#ifdef SAVE_RCSID
1.27 +static char rcsid =
1.28 + "@(#) $Id$";
1.29 +#endif
1.30 +
1.31 +#include <stdio.h>
1.32 +#include <stdlib.h>
1.33 +#include <string.h>
1.34 +
1.35 +#include "SDL_error.h"
1.36 +#include "SDL_video.h"
1.37 +#include "SDL_sysvideo.h"
1.38 +#include "SDL_blit.h"
1.39 +#include "SDL_RLEaccel_c.h"
1.40 +#include "SDL_pixels_c.h"
1.41 +#include "SDL_memops.h"
1.42 +
1.43 +/* The general purpose software blit routine */
1.44 +static int SDL_SoftBlit(SDL_Surface *src, SDL_Rect *srcrect,
1.45 + SDL_Surface *dst, SDL_Rect *dstrect)
1.46 +{
1.47 + int okay;
1.48 + int src_locked;
1.49 + int dst_locked;
1.50 +
1.51 + /* Everything is okay at the beginning... */
1.52 + okay = 1;
1.53 +
1.54 + /* Lock the destination if it's in hardware */
1.55 + dst_locked = 0;
1.56 + if ( dst->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
1.57 + SDL_VideoDevice *video = current_video;
1.58 + SDL_VideoDevice *this = current_video;
1.59 + if ( video->LockHWSurface(this, dst) < 0 ) {
1.60 + okay = 0;
1.61 + } else {
1.62 + dst_locked = 1;
1.63 + }
1.64 + }
1.65 + /* Lock the source if it's in hardware */
1.66 + src_locked = 0;
1.67 + if ( src->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
1.68 + SDL_VideoDevice *video = current_video;
1.69 + SDL_VideoDevice *this = current_video;
1.70 + if ( video->LockHWSurface(this, src) < 0 ) {
1.71 + okay = 0;
1.72 + } else {
1.73 + src_locked = 1;
1.74 + }
1.75 + }
1.76 +
1.77 + /* Unencode the destination if it's RLE encoded */
1.78 + if ( dst->flags & SDL_RLEACCEL ) {
1.79 + SDL_UnRLESurface(dst, 1);
1.80 + dst->flags |= SDL_RLEACCEL; /* save accel'd state */
1.81 + }
1.82 +
1.83 + /* Set up source and destination buffer pointers, and BLIT! */
1.84 + if ( okay && srcrect->w && srcrect->h ) {
1.85 + SDL_BlitInfo info;
1.86 + SDL_loblit RunBlit;
1.87 +
1.88 + /* Set up the blit information */
1.89 + info.s_pixels = (Uint8 *)src->pixels + src->offset +
1.90 + (Uint16)srcrect->y*src->pitch +
1.91 + (Uint16)srcrect->x*src->format->BytesPerPixel;
1.92 + info.s_width = srcrect->w;
1.93 + info.s_height = srcrect->h;
1.94 + info.s_skip=src->pitch-info.s_width*src->format->BytesPerPixel;
1.95 + info.d_pixels = (Uint8 *)dst->pixels + dst->offset +
1.96 + (Uint16)dstrect->y*dst->pitch +
1.97 + (Uint16)dstrect->x*dst->format->BytesPerPixel;
1.98 + info.d_width = dstrect->w;
1.99 + info.d_height = dstrect->h;
1.100 + info.d_skip=dst->pitch-info.d_width*dst->format->BytesPerPixel;
1.101 + info.aux_data = src->map->sw_data->aux_data;
1.102 + info.src = src->format;
1.103 + info.table = src->map->table;
1.104 + info.dst = dst->format;
1.105 + RunBlit = src->map->sw_data->blit;
1.106 +
1.107 + /* Run the actual software blit */
1.108 + RunBlit(&info);
1.109 + }
1.110 +
1.111 + /* Re-encode the destination if it's RLE encoded */
1.112 + if ( dst->flags & SDL_RLEACCEL ) {
1.113 + dst->flags &= ~SDL_RLEACCEL; /* stop lying */
1.114 + SDL_RLESurface(dst);
1.115 + }
1.116 +
1.117 + /* We need to unlock the surfaces if they're locked */
1.118 + if ( dst_locked ) {
1.119 + SDL_VideoDevice *video = current_video;
1.120 + SDL_VideoDevice *this = current_video;
1.121 + video->UnlockHWSurface(this, dst);
1.122 + } else
1.123 + if ( src_locked ) {
1.124 + SDL_VideoDevice *video = current_video;
1.125 + SDL_VideoDevice *this = current_video;
1.126 + video->UnlockHWSurface(this, src);
1.127 + }
1.128 + /* Blit is done! */
1.129 + return(okay ? 0 : -1);
1.130 +}
1.131 +
1.132 +static void SDL_BlitCopy(SDL_BlitInfo *info)
1.133 +{
1.134 + Uint8 *src, *dst;
1.135 + int w, h;
1.136 + int srcskip, dstskip;
1.137 +
1.138 + w = info->d_width*info->dst->BytesPerPixel;
1.139 + h = info->d_height;
1.140 + src = info->s_pixels;
1.141 + dst = info->d_pixels;
1.142 + srcskip = w+info->s_skip;
1.143 + dstskip = w+info->d_skip;
1.144 + while ( h-- ) {
1.145 + SDL_memcpy(dst, src, w);
1.146 + src += srcskip;
1.147 + dst += dstskip;
1.148 + }
1.149 +}
1.150 +
1.151 +static void SDL_BlitCopyOverlap(SDL_BlitInfo *info)
1.152 +{
1.153 + Uint8 *src, *dst;
1.154 + int w, h;
1.155 + int srcskip, dstskip;
1.156 +
1.157 + w = info->d_width*info->dst->BytesPerPixel;
1.158 + h = info->d_height;
1.159 + src = info->s_pixels;
1.160 + dst = info->d_pixels;
1.161 + srcskip = w+info->s_skip;
1.162 + dstskip = w+info->d_skip;
1.163 + if ( dst < src ) {
1.164 + while ( h-- ) {
1.165 + SDL_memcpy(dst, src, w);
1.166 + src += srcskip;
1.167 + dst += dstskip;
1.168 + }
1.169 + } else {
1.170 + src += ((h-1) * srcskip);
1.171 + dst += ((h-1) * dstskip);
1.172 + while ( h-- ) {
1.173 + SDL_revcpy(dst, src, w);
1.174 + src -= srcskip;
1.175 + dst -= dstskip;
1.176 + }
1.177 + }
1.178 +}
1.179 +
1.180 +/* Figure out which of many blit routines to set up on a surface */
1.181 +int SDL_CalculateBlit(SDL_Surface *surface)
1.182 +{
1.183 + int blit_index;
1.184 +
1.185 + /* Clean everything out to start */
1.186 + if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
1.187 + SDL_UnRLESurface(surface, 1);
1.188 + }
1.189 + surface->map->sw_blit = NULL;
1.190 +
1.191 + /* Figure out if an accelerated hardware blit is possible */
1.192 + surface->flags &= ~SDL_HWACCEL;
1.193 + if ( surface->map->identity ) {
1.194 + int hw_blit_ok;
1.195 +
1.196 + if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
1.197 + /* We only support accelerated blitting to hardware */
1.198 + if ( surface->map->dst->flags & SDL_HWSURFACE ) {
1.199 + hw_blit_ok = current_video->info.blit_hw;
1.200 + } else {
1.201 + hw_blit_ok = 0;
1.202 + }
1.203 + if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) {
1.204 + hw_blit_ok = current_video->info.blit_hw_CC;
1.205 + }
1.206 + if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) {
1.207 + hw_blit_ok = current_video->info.blit_hw_A;
1.208 + }
1.209 + } else {
1.210 + /* We only support accelerated blitting to hardware */
1.211 + if ( surface->map->dst->flags & SDL_HWSURFACE ) {
1.212 + hw_blit_ok = current_video->info.blit_sw;
1.213 + } else {
1.214 + hw_blit_ok = 0;
1.215 + }
1.216 + if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) {
1.217 + hw_blit_ok = current_video->info.blit_sw_CC;
1.218 + }
1.219 + if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) {
1.220 + hw_blit_ok = current_video->info.blit_sw_A;
1.221 + }
1.222 + }
1.223 + if ( hw_blit_ok ) {
1.224 + SDL_VideoDevice *video = current_video;
1.225 + SDL_VideoDevice *this = current_video;
1.226 + video->CheckHWBlit(this, surface, surface->map->dst);
1.227 + }
1.228 + }
1.229 +
1.230 + /* Get the blit function index, based on surface mode */
1.231 + /* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */
1.232 + blit_index = 0;
1.233 + blit_index |= (!!(surface->flags & SDL_SRCCOLORKEY)) << 0;
1.234 + if ( surface->flags & SDL_SRCALPHA
1.235 + && (surface->format->alpha != SDL_ALPHA_OPAQUE
1.236 + || surface->format->Amask) ) {
1.237 + blit_index |= 2;
1.238 + }
1.239 +
1.240 + /* Check for special "identity" case -- copy blit */
1.241 + if ( surface->map->identity && blit_index == 0 ) {
1.242 + surface->map->sw_data->blit = SDL_BlitCopy;
1.243 +
1.244 + /* Handle overlapping blits on the same surface */
1.245 + if ( surface == surface->map->dst ) {
1.246 + surface->map->sw_data->blit = SDL_BlitCopyOverlap;
1.247 + }
1.248 + } else {
1.249 + if ( surface->format->BitsPerPixel < 8 ) {
1.250 + surface->map->sw_data->blit =
1.251 + SDL_CalculateBlit0(surface, blit_index);
1.252 + } else {
1.253 + switch ( surface->format->BytesPerPixel ) {
1.254 + case 1:
1.255 + surface->map->sw_data->blit =
1.256 + SDL_CalculateBlit1(surface, blit_index);
1.257 + break;
1.258 + case 2:
1.259 + case 3:
1.260 + case 4:
1.261 + surface->map->sw_data->blit =
1.262 + SDL_CalculateBlitN(surface, blit_index);
1.263 + break;
1.264 + default:
1.265 + surface->map->sw_data->blit = NULL;
1.266 + break;
1.267 + }
1.268 + }
1.269 + }
1.270 + /* Make sure we have a blit function */
1.271 + if ( surface->map->sw_data->blit == NULL ) {
1.272 + SDL_InvalidateMap(surface->map);
1.273 + SDL_SetError("Blit combination not supported");
1.274 + return(-1);
1.275 + }
1.276 +
1.277 + /* Choose software blitting function */
1.278 + if(surface->flags & SDL_RLEACCELOK
1.279 + && (surface->flags & SDL_HWACCEL) != SDL_HWACCEL) {
1.280 +
1.281 + if(surface->map->identity
1.282 + && (blit_index == 1
1.283 + || (blit_index == 3 && !surface->format->Amask))) {
1.284 + if ( SDL_RLESurface(surface) == 0 )
1.285 + surface->map->sw_blit = SDL_RLEBlit;
1.286 + } else if(blit_index == 2 && surface->format->Amask) {
1.287 + if ( SDL_RLESurface(surface) == 0 )
1.288 + surface->map->sw_blit = SDL_RLEAlphaBlit;
1.289 + }
1.290 + }
1.291 +
1.292 + if ( surface->map->sw_blit == NULL ) {
1.293 + surface->map->sw_blit = SDL_SoftBlit;
1.294 + }
1.295 + return(0);
1.296 +}
1.297 +