src/video/SDL_blit.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. SDL_SoftBlit
  2. SDL_BlitCopy
  3. SDL_BlitCopyOverlap
  4. SDL_CalculateBlit

   1 /*
   2     SDL - Simple DirectMedia Layer
   3     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
   4 
   5     This library is free software; you can redistribute it and/or
   6     modify it under the terms of the GNU Library General Public
   7     License as published by the Free Software Foundation; either
   8     version 2 of the License, or (at your option) any later version.
   9 
  10     This library is distributed in the hope that it will be useful,
  11     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13     Library General Public License for more details.
  14 
  15     You should have received a copy of the GNU Library General Public
  16     License along with this library; if not, write to the Free
  17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18 
  19     Sam Lantinga
  20     slouken@devolution.com
  21 */
  22 
  23 #ifdef SAVE_RCSID
  24 static char rcsid =
  25  "@(#) $Id: SDL_blit.c,v 1.5.2.20 2001/02/10 21:21:31 hercules Exp $";
  26 #endif
  27 
  28 #include <stdio.h>
  29 #include <stdlib.h>
  30 #include <string.h>
  31 
  32 #include "SDL_error.h"
  33 #include "SDL_video.h"
  34 #include "SDL_sysvideo.h"
  35 #include "SDL_blit.h"
  36 #include "SDL_RLEaccel_c.h"
  37 #include "SDL_pixels_c.h"
  38 #include "SDL_memops.h"
  39 
  40 /* The general purpose software blit routine */
  41 static int SDL_SoftBlit(SDL_Surface *src, SDL_Rect *srcrect,
     /* [<][>][^][v][top][bottom][index][help] */
  42                         SDL_Surface *dst, SDL_Rect *dstrect)
  43 {
  44         int okay;
  45         int src_locked;
  46         int dst_locked;
  47 
  48         /* Everything is okay at the beginning...  */
  49         okay = 1;
  50 
  51         /* Lock the destination if it's in hardware */
  52         dst_locked = 0;
  53         if ( dst->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
  54                 SDL_VideoDevice *video = current_video;
  55                 SDL_VideoDevice *this  = current_video;
  56                 if ( video->LockHWSurface(this, dst) < 0 ) {
  57                         okay = 0;
  58                 } else {
  59                         dst_locked = 1;
  60                 }
  61         }
  62         /* Lock the source if it's in hardware */
  63         src_locked = 0;
  64         if ( src->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
  65                 SDL_VideoDevice *video = current_video;
  66                 SDL_VideoDevice *this  = current_video;
  67                 if ( video->LockHWSurface(this, src) < 0 ) {
  68                         okay = 0;
  69                 } else {
  70                         src_locked = 1;
  71                 }
  72         }
  73 
  74         /* Unencode the destination if it's RLE encoded */
  75         if ( dst->flags & SDL_RLEACCEL ) {
  76                 SDL_UnRLESurface(dst, 1);
  77                 dst->flags |= SDL_RLEACCEL;     /* save accel'd state */
  78         }
  79 
  80         /* Set up source and destination buffer pointers, and BLIT! */
  81         if ( okay  && srcrect->w && srcrect->h ) {
  82                 SDL_BlitInfo info;
  83                 SDL_loblit RunBlit;
  84 
  85                 /* Set up the blit information */
  86                 info.s_pixels = (Uint8 *)src->pixels + src->offset +
  87                                 (Uint16)srcrect->y*src->pitch +
  88                                 (Uint16)srcrect->x*src->format->BytesPerPixel;
  89                 info.s_width = srcrect->w;
  90                 info.s_height = srcrect->h;
  91                 info.s_skip=src->pitch-info.s_width*src->format->BytesPerPixel;
  92                 info.d_pixels = (Uint8 *)dst->pixels + dst->offset +
  93                                 (Uint16)dstrect->y*dst->pitch +
  94                                 (Uint16)dstrect->x*dst->format->BytesPerPixel;
  95                 info.d_width = dstrect->w;
  96                 info.d_height = dstrect->h;
  97                 info.d_skip=dst->pitch-info.d_width*dst->format->BytesPerPixel;
  98                 info.aux_data = src->map->sw_data->aux_data;
  99                 info.src = src->format;
 100                 info.table = src->map->table;
 101                 info.dst = dst->format;
 102                 RunBlit = src->map->sw_data->blit;
 103 
 104                 /* Run the actual software blit */
 105                 RunBlit(&info);
 106         }
 107 
 108         /* Re-encode the destination if it's RLE encoded */
 109         if ( dst->flags & SDL_RLEACCEL ) {
 110                 dst->flags &= ~SDL_RLEACCEL; /* stop lying */
 111                 SDL_RLESurface(dst);
 112         }
 113 
 114         /* We need to unlock the surfaces if they're locked */
 115         if ( dst_locked ) {
 116                 SDL_VideoDevice *video = current_video;
 117                 SDL_VideoDevice *this  = current_video;
 118                 video->UnlockHWSurface(this, dst);
 119         } else
 120         if ( src_locked ) {
 121                 SDL_VideoDevice *video = current_video;
 122                 SDL_VideoDevice *this  = current_video;
 123                 video->UnlockHWSurface(this, src);
 124         }
 125         /* Blit is done! */
 126         return(okay ? 0 : -1);
 127 }
 128 
 129 static void SDL_BlitCopy(SDL_BlitInfo *info)
     /* [<][>][^][v][top][bottom][index][help] */
 130 {
 131         Uint8 *src, *dst;
 132         int w, h;
 133         int srcskip, dstskip;
 134 
 135         w = info->d_width*info->dst->BytesPerPixel;
 136         h = info->d_height;
 137         src = info->s_pixels;
 138         dst = info->d_pixels;
 139         srcskip = w+info->s_skip;
 140         dstskip = w+info->d_skip;
 141         while ( h-- ) {
 142                 SDL_memcpy(dst, src, w);
 143                 src += srcskip;
 144                 dst += dstskip;
 145         }
 146 }
 147 
 148 static void SDL_BlitCopyOverlap(SDL_BlitInfo *info)
     /* [<][>][^][v][top][bottom][index][help] */
 149 {
 150         Uint8 *src, *dst;
 151         int w, h;
 152         int srcskip, dstskip;
 153 
 154         w = info->d_width*info->dst->BytesPerPixel;
 155         h = info->d_height;
 156         src = info->s_pixels;
 157         dst = info->d_pixels;
 158         srcskip = w+info->s_skip;
 159         dstskip = w+info->d_skip;
 160         if ( dst < src ) {
 161                 while ( h-- ) {
 162                         SDL_memcpy(dst, src, w);
 163                         src += srcskip;
 164                         dst += dstskip;
 165                 }
 166         } else {
 167                 src += ((h-1) * srcskip);
 168                 dst += ((h-1) * dstskip);
 169                 while ( h-- ) {
 170                         SDL_revcpy(dst, src, w);
 171                         src -= srcskip;
 172                         dst -= dstskip;
 173                 }
 174         }
 175 }
 176 
 177 /* Figure out which of many blit routines to set up on a surface */
 178 int SDL_CalculateBlit(SDL_Surface *surface)
     /* [<][>][^][v][top][bottom][index][help] */
 179 {
 180         int blit_index;
 181 
 182         /* Clean everything out to start */
 183         if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
 184                 SDL_UnRLESurface(surface, 1);
 185         }
 186         surface->map->sw_blit = NULL;
 187 
 188         /* Figure out if an accelerated hardware blit is possible */
 189         surface->flags &= ~SDL_HWACCEL;
 190         if ( surface->map->identity ) {
 191                 int hw_blit_ok;
 192 
 193                 if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
 194                         /* We only support accelerated blitting to hardware */
 195                         if ( surface->map->dst->flags & SDL_HWSURFACE ) {
 196                                 hw_blit_ok = current_video->info.blit_hw;
 197                         } else {
 198                                 hw_blit_ok = 0;
 199                         }
 200                         if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) {
 201                                 hw_blit_ok = current_video->info.blit_hw_CC;
 202                         }
 203                         if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) {
 204                                 hw_blit_ok = current_video->info.blit_hw_A;
 205                         }
 206                 } else {
 207                         /* We only support accelerated blitting to hardware */
 208                         if ( surface->map->dst->flags & SDL_HWSURFACE ) {
 209                                 hw_blit_ok = current_video->info.blit_sw;
 210                         } else {
 211                                 hw_blit_ok = 0;
 212                         }
 213                         if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) {
 214                                 hw_blit_ok = current_video->info.blit_sw_CC;
 215                         }
 216                         if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) {
 217                                 hw_blit_ok = current_video->info.blit_sw_A;
 218                         }
 219                 }
 220                 if ( hw_blit_ok ) {
 221                         SDL_VideoDevice *video = current_video;
 222                         SDL_VideoDevice *this  = current_video;
 223                         video->CheckHWBlit(this, surface, surface->map->dst);
 224                 }
 225         }
 226 
 227         /* Get the blit function index, based on surface mode */
 228         /* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */
 229         blit_index = 0;
 230         blit_index |= (!!(surface->flags & SDL_SRCCOLORKEY))      << 0;
 231         if ( surface->flags & SDL_SRCALPHA
 232              && (surface->format->alpha != SDL_ALPHA_OPAQUE
 233                  || surface->format->Amask) ) {
 234                 blit_index |= 2;
 235         }
 236 
 237         /* Check for special "identity" case -- copy blit */
 238         if ( surface->map->identity && blit_index == 0 ) {
 239                 surface->map->sw_data->blit = SDL_BlitCopy;
 240 
 241                 /* Handle overlapping blits on the same surface */
 242                 if ( surface == surface->map->dst ) {
 243                         surface->map->sw_data->blit = SDL_BlitCopyOverlap;
 244                 }
 245         } else {
 246                 if ( surface->format->BitsPerPixel < 8 ) {
 247                         surface->map->sw_data->blit =
 248                             SDL_CalculateBlit0(surface, blit_index);
 249                 } else {
 250                         switch ( surface->format->BytesPerPixel ) {
 251                             case 1:
 252                                 surface->map->sw_data->blit =
 253                                     SDL_CalculateBlit1(surface, blit_index);
 254                                 break;
 255                             case 2:
 256                             case 3:
 257                             case 4:
 258                                 surface->map->sw_data->blit =
 259                                     SDL_CalculateBlitN(surface, blit_index);
 260                                 break;
 261                             default:
 262                                 surface->map->sw_data->blit = NULL;
 263                                 break;
 264                         }
 265                 }
 266         }
 267         /* Make sure we have a blit function */
 268         if ( surface->map->sw_data->blit == NULL ) {
 269                 SDL_InvalidateMap(surface->map);
 270                 SDL_SetError("Blit combination not supported");
 271                 return(-1);
 272         }
 273 
 274         /* Choose software blitting function */
 275         if(surface->flags & SDL_RLEACCELOK
 276            && (surface->flags & SDL_HWACCEL) != SDL_HWACCEL) {
 277 
 278                 if(surface->map->identity
 279                    && (blit_index == 1
 280                        || (blit_index == 3 && !surface->format->Amask))) {
 281                         if ( SDL_RLESurface(surface) == 0 )
 282                                 surface->map->sw_blit = SDL_RLEBlit;
 283                 } else if(blit_index == 2 && surface->format->Amask) {
 284                         if ( SDL_RLESurface(surface) == 0 )
 285                                 surface->map->sw_blit = SDL_RLEAlphaBlit;
 286                 }
 287         }
 288         
 289         if ( surface->map->sw_blit == NULL ) {
 290                 surface->map->sw_blit = SDL_SoftBlit;
 291         }
 292         return(0);
 293 }
 294 

/* [<][>][^][v][top][bottom][index][help] */