src/video/SDL_surface.c

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

FUNCTIONS

This source file includes following functions.
  1. SDL_CreateRGBSurface
  2. SDL_CreateRGBSurfaceFrom
  3. SDL_SetColorKey
  4. SDL_SetAlpha
  5. SDL_IntersectRect
  6. SDL_SetClipRect
  7. SDL_GetClipRect
  8. SDL_LowerBlit
  9. SDL_UpperBlit
  10. SDL_FillRect
  11. SDL_LockSurface
  12. SDL_UnlockSurface
  13. SDL_ConvertSurface
  14. SDL_FreeSurface

   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_surface.c,v 1.8.2.32 2001/03/19 19:03:18 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_cursor_c.h"
  36 #include "SDL_blit.h"
  37 #include "SDL_RLEaccel_c.h"
  38 #include "SDL_pixels_c.h"
  39 #include "SDL_memops.h"
  40 #include "SDL_leaks.h"
  41 
  42 /* Public routines */
  43 /*
  44  * Create an empty RGB surface of the appropriate depth
  45  */
  46 SDL_Surface * SDL_CreateRGBSurface (Uint32 flags,
     /* [<][>][^][v][top][bottom][index][help] */
  47                         int width, int height, int depth,
  48                         Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  49 {
  50         SDL_VideoDevice *video = current_video;
  51         SDL_VideoDevice *this  = current_video;
  52         SDL_Surface *screen;
  53         SDL_Surface *surface;
  54 
  55         /* Check to see if we desire the surface in video memory */
  56         if ( video ) {
  57                 screen = SDL_PublicSurface;
  58         } else {
  59                 screen = NULL;
  60         }
  61         if ( screen && ((screen->flags&SDL_HWSURFACE) == SDL_HWSURFACE) ) {
  62                 if ( (flags&(SDL_SRCCOLORKEY|SDL_SRCALPHA)) != 0 ) {
  63                         flags |= SDL_HWSURFACE;
  64                 }
  65                 if ( (flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
  66                         if ( ! current_video->info.blit_hw_CC ) {
  67                                 flags &= ~SDL_HWSURFACE;
  68                         }
  69                 }
  70                 if ( (flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
  71                         if ( ! current_video->info.blit_hw_A ) {
  72                                 flags &= ~SDL_HWSURFACE;
  73                         }
  74                 }
  75         } else {
  76                 flags &= ~SDL_HWSURFACE;
  77         }
  78 
  79         /* Allocate the surface */
  80         surface = (SDL_Surface *)malloc(sizeof(*surface));
  81         if ( surface == NULL ) {
  82                 SDL_OutOfMemory();
  83                 return(NULL);
  84         }
  85         surface->flags = SDL_SWSURFACE;
  86         if ( (flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  87                 depth = screen->format->BitsPerPixel;
  88                 Rmask = screen->format->Rmask;
  89                 Gmask = screen->format->Gmask;
  90                 Bmask = screen->format->Bmask;
  91                 Amask = screen->format->Amask;
  92         }
  93         surface->format = SDL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask);
  94         if ( surface->format == NULL ) {
  95                 free(surface);
  96                 return(NULL);
  97         }
  98         if ( Amask ) {
  99                 surface->flags |= SDL_SRCALPHA;
 100         }
 101         surface->w = width;
 102         surface->h = height;
 103         surface->pitch = SDL_CalculatePitch(surface);
 104         surface->pixels = NULL;
 105         surface->offset = 0;
 106         surface->hwdata = NULL;
 107         surface->locked = 0;
 108         surface->map = NULL;
 109         surface->format_version = 0;
 110         SDL_SetClipRect(surface, NULL);
 111 
 112         /* Get the pixels */
 113         if ( ((flags&SDL_HWSURFACE) == SDL_SWSURFACE) || 
 114                                 (video->AllocHWSurface(this, surface) < 0) ) {
 115                 if ( surface->w && surface->h ) {
 116                         surface->pixels = malloc(surface->h*surface->pitch);
 117                         if ( surface->pixels == NULL ) {
 118                                 SDL_FreeSurface(surface);
 119                                 SDL_OutOfMemory();
 120                                 return(NULL);
 121                         }
 122                         /* This is important for bitmaps */
 123                         memset(surface->pixels, 0, surface->h*surface->pitch);
 124                 }
 125         }
 126 
 127         /* Allocate an empty mapping */
 128         surface->map = SDL_AllocBlitMap();
 129         if ( surface->map == NULL ) {
 130                 SDL_FreeSurface(surface);
 131                 return(NULL);
 132         }
 133 
 134         /* The surface is ready to go */
 135         surface->refcount = 1;
 136 #ifdef CHECK_LEAKS
 137         ++surfaces_allocated;
 138 #endif
 139         return(surface);
 140 }
 141 /*
 142  * Create an RGB surface from an existing memory buffer
 143  */
 144 SDL_Surface * SDL_CreateRGBSurfaceFrom (void *pixels,
     /* [<][>][^][v][top][bottom][index][help] */
 145                         int width, int height, int depth, int pitch,
 146                         Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
 147 {
 148         SDL_Surface *surface;
 149 
 150         surface = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, depth,
 151                                        Rmask, Gmask, Bmask, Amask);
 152         if ( surface != NULL ) {
 153                 surface->flags |= SDL_PREALLOC;
 154                 surface->pixels = pixels;
 155                 surface->w = width;
 156                 surface->h = height;
 157                 surface->pitch = pitch;
 158                 SDL_SetClipRect(surface, NULL);
 159         }
 160         return(surface);
 161 }
 162 /*
 163  * Set the color key in a blittable surface
 164  */
 165 int SDL_SetColorKey (SDL_Surface *surface, Uint32 flag, Uint32 key)
     /* [<][>][^][v][top][bottom][index][help] */
 166 {
 167         /* Sanity check the flag as it gets passed in */
 168         if ( flag & SDL_SRCCOLORKEY ) {
 169                 if ( flag & (SDL_RLEACCEL|SDL_RLEACCELOK) ) {
 170                         flag = (SDL_SRCCOLORKEY | SDL_RLEACCELOK);
 171                 } else {
 172                         flag = SDL_SRCCOLORKEY;
 173                 }
 174         } else {
 175                 flag = 0;
 176         }
 177 
 178         /* Optimize away operations that don't change anything */
 179         if ( (flag == (surface->flags & (SDL_SRCCOLORKEY|SDL_RLEACCELOK))) &&
 180              (key == surface->format->colorkey) ) {
 181                 return(0);
 182         }
 183 
 184         /* UnRLE surfaces before we change the colorkey */
 185         if ( surface->flags & SDL_RLEACCEL ) {
 186                 SDL_UnRLESurface(surface, 1);
 187         }
 188 
 189         if ( flag ) {
 190                 SDL_VideoDevice *video = current_video;
 191                 SDL_VideoDevice *this  = current_video;
 192 
 193 
 194                 surface->flags |= SDL_SRCCOLORKEY;
 195                 surface->format->colorkey = key;
 196                 if ( (surface->flags & SDL_HWACCEL) == SDL_HWACCEL ) {
 197                         if ( (video->SetHWColorKey == NULL) ||
 198                              (video->SetHWColorKey(this, surface, key) < 0) ) {
 199                                 surface->flags &= ~SDL_HWACCEL;
 200                         }
 201                 }
 202                 if ( flag & SDL_RLEACCELOK ) {
 203                         surface->flags |= SDL_RLEACCELOK;
 204                 } else {
 205                         surface->flags &= ~SDL_RLEACCELOK;
 206                 }
 207         } else {
 208                 surface->flags &= ~(SDL_SRCCOLORKEY|SDL_RLEACCELOK);
 209                 surface->format->colorkey = 0;
 210         }
 211         SDL_InvalidateMap(surface->map);
 212         return(0);
 213 }
 214 int SDL_SetAlpha (SDL_Surface *surface, Uint32 flag, Uint8 value)
     /* [<][>][^][v][top][bottom][index][help] */
 215 {
 216         Uint32 oldflags = surface->flags;
 217         Uint32 oldalpha = surface->format->alpha;
 218 
 219         /* Sanity check the flag as it gets passed in */
 220         if ( flag & SDL_SRCALPHA ) {
 221                 if ( flag & (SDL_RLEACCEL|SDL_RLEACCELOK) ) {
 222                         flag = (SDL_SRCALPHA | SDL_RLEACCELOK);
 223                 } else {
 224                         flag = SDL_SRCALPHA;
 225                 }
 226         } else {
 227                 flag = 0;
 228         }
 229 
 230         /* Optimize away operations that don't change anything */
 231         if ( (flag == (surface->flags & (SDL_SRCALPHA|SDL_RLEACCELOK))) &&
 232              (!flag || value == oldalpha) ) {
 233                 return(0);
 234         }
 235 
 236         if(!(flag & SDL_RLEACCELOK) && (surface->flags & SDL_RLEACCEL))
 237                 SDL_UnRLESurface(surface, 1);
 238 
 239         if ( flag ) {
 240                 SDL_VideoDevice *video = current_video;
 241                 SDL_VideoDevice *this  = current_video;
 242 
 243                 surface->flags |= SDL_SRCALPHA;
 244                 surface->format->alpha = value;
 245                 if ( (surface->flags & SDL_HWACCEL) == SDL_HWACCEL ) {
 246                         if ( (video->SetHWAlpha == NULL) ||
 247                              (video->SetHWAlpha(this, surface, value) < 0) ) {
 248                                 surface->flags &= ~SDL_HWACCEL;
 249                         }
 250                 }
 251                 if ( flag & SDL_RLEACCELOK ) {
 252                         surface->flags |= SDL_RLEACCELOK;
 253                 } else {
 254                         surface->flags &= ~SDL_RLEACCELOK;
 255                 }
 256         } else {
 257                 surface->flags &= ~SDL_SRCALPHA;
 258                 surface->format->alpha = SDL_ALPHA_OPAQUE;
 259         }
 260         /*
 261          * The representation for software surfaces is independent of
 262          * per-surface alpha, so no need to invalidate the blit mapping
 263          * if just the alpha value was changed. (If either is 255, we still
 264          * need to invalidate.)
 265          */
 266         if((surface->flags & SDL_HWACCEL) == SDL_HWACCEL
 267            || oldflags != surface->flags
 268            || (((oldalpha + 1) ^ (value + 1)) & 0x100))
 269                 SDL_InvalidateMap(surface->map);
 270         return(0);
 271 }
 272 
 273 /*
 274  * A function to calculate the intersection of two rectangles:
 275  * return true if the rectangles intersect, false otherwise
 276  */
 277 static __inline__
 278 SDL_bool SDL_IntersectRect(SDL_Rect *A, SDL_Rect *B, SDL_Rect *intersection)
     /* [<][>][^][v][top][bottom][index][help] */
 279 {
 280         int Amin, Amax, Bmin, Bmax;
 281 
 282         /* Horizontal intersection */
 283         Amin = A->x;
 284         Amax = Amin + A->w;
 285         Bmin = B->x;
 286         Bmax = Bmin + B->w;
 287         if(Bmin > Amin)
 288                 Amin = Bmin;
 289         intersection->x = Amin;
 290         if(Bmax < Amax)
 291                 Amax = Bmax;
 292         intersection->w = Amax - Amin > 0 ? Amax - Amin : 0;
 293 
 294         /* Vertical intersection */
 295         Amin = A->y;
 296         Amax = Amin + A->h;
 297         Bmin = B->y;
 298         Bmax = Bmin + B->h;
 299         if(Bmin > Amin)
 300                 Amin = Bmin;
 301         intersection->y = Amin;
 302         if(Bmax < Amax)
 303                 Amax = Bmax;
 304         intersection->h = Amax - Amin > 0 ? Amax - Amin : 0;
 305 
 306         return (intersection->w && intersection->h);
 307 }
 308 /*
 309  * Set the clipping rectangle for a blittable surface
 310  */
 311 SDL_bool SDL_SetClipRect(SDL_Surface *surface, SDL_Rect *rect)
     /* [<][>][^][v][top][bottom][index][help] */
 312 {
 313         SDL_Rect full_rect;
 314 
 315         /* Don't do anything if there's no surface to act on */
 316         if ( ! surface ) {
 317                 return SDL_FALSE;
 318         }
 319 
 320         /* Set up the full surface rectangle */
 321         full_rect.x = 0;
 322         full_rect.y = 0;
 323         full_rect.w = surface->w;
 324         full_rect.h = surface->h;
 325 
 326         /* Set the clipping rectangle */
 327         if ( ! rect ) {
 328                 surface->clip_rect = full_rect;
 329                 return 1;
 330         }
 331         return SDL_IntersectRect(rect, &full_rect, &surface->clip_rect);
 332 }
 333 void SDL_GetClipRect(SDL_Surface *surface, SDL_Rect *rect)
     /* [<][>][^][v][top][bottom][index][help] */
 334 {
 335         if ( surface && rect ) {
 336                 *rect = surface->clip_rect;
 337         }
 338 }
 339 /* 
 340  * Set up a blit between two surfaces -- split into three parts:
 341  * The upper part, SDL_UpperBlit(), performs clipping and rectangle 
 342  * verification.  The lower part is a pointer to a low level
 343  * accelerated blitting function.
 344  *
 345  * These parts are separated out and each used internally by this 
 346  * library in the optimimum places.  They are exported so that if
 347  * you know exactly what you are doing, you can optimize your code
 348  * by calling the one(s) you need.
 349  */
 350 int SDL_LowerBlit (SDL_Surface *src, SDL_Rect *srcrect,
     /* [<][>][^][v][top][bottom][index][help] */
 351                                 SDL_Surface *dst, SDL_Rect *dstrect)
 352 {
 353         SDL_blit do_blit;
 354 
 355         /* Check to make sure the blit mapping is valid */
 356         if ( (src->map->dst != dst) ||
 357              (src->map->dst->format_version != src->map->format_version) ) {
 358                 if ( SDL_MapSurface(src, dst) < 0 ) {
 359                         return(-1);
 360                 }
 361         }
 362 
 363         /* Figure out which blitter to use */
 364         if ( (src->flags & SDL_HWACCEL) == SDL_HWACCEL ) {
 365                 do_blit = src->map->hw_blit;
 366         } else {
 367                 do_blit = src->map->sw_blit;
 368         }
 369         return(do_blit(src, srcrect, dst, dstrect));
 370 }
 371 
 372 
 373 int SDL_UpperBlit (SDL_Surface *src, SDL_Rect *srcrect,
     /* [<][>][^][v][top][bottom][index][help] */
 374                    SDL_Surface *dst, SDL_Rect *dstrect)
 375 {
 376         SDL_Rect fulldst;
 377         int srcx, srcy, w, h;
 378 
 379         /* Make sure the surfaces aren't locked */
 380         if ( ! src || ! dst ) {
 381                 SDL_SetError("SDL_UpperBlit: passed a NULL surface");
 382                 return(-1);
 383         }
 384         if ( src->locked || dst->locked ) {
 385                 SDL_SetError("Surfaces must not be locked during blit");
 386                 return(-1);
 387         }
 388 
 389         /* If the destination rectangle is NULL, use the entire dest surface */
 390         if ( dstrect == NULL ) {
 391                 fulldst.x = fulldst.y = 0;
 392                 dstrect = &fulldst;
 393         }
 394 
 395         /* clip the source rectangle to the source surface */
 396         if(srcrect) {
 397                 int maxw, maxh;
 398         
 399                 srcx = srcrect->x;
 400                 w = srcrect->w;
 401                 if(srcx < 0) {
 402                         w += srcx;
 403                         dstrect->x -= srcx;
 404                         srcx = 0;
 405                 }
 406                 maxw = src->w - srcx;
 407                 if(maxw < w)
 408                         w = maxw;
 409 
 410                 srcy = srcrect->y;
 411                 h = srcrect->h;
 412                 if(srcy < 0) {
 413                         h += srcy;
 414                         dstrect->y -= srcy;
 415                         srcy = 0;
 416                 }
 417                 maxh = src->h - srcy;
 418                 if(maxh < h)
 419                         h = maxh;
 420             
 421         } else {
 422                 srcx = srcy = 0;
 423                 w = src->w;
 424                 h = src->h;
 425         }
 426 
 427         /* clip the destination rectangle against the clip rectangle */
 428         {
 429                 SDL_Rect *clip = &dst->clip_rect;
 430                 int dx, dy;
 431 
 432                 dx = clip->x - dstrect->x;
 433                 if(dx > 0) {
 434                         w -= dx;
 435                         dstrect->x += dx;
 436                         srcx += dx;
 437                 }
 438                 dx = dstrect->x + w - clip->x - clip->w;
 439                 if(dx > 0)
 440                         w -= dx;
 441 
 442                 dy = clip->y - dstrect->y;
 443                 if(dy > 0) {
 444                         h -= dy;
 445                         dstrect->y += dy;
 446                         srcy += dy;
 447                 }
 448                 dy = dstrect->y + h - clip->y - clip->h;
 449                 if(dy > 0)
 450                         h -= dy;
 451         }
 452 
 453         if(w > 0 && h > 0) {
 454                 SDL_Rect sr;
 455                 sr.x = srcx;
 456                 sr.y = srcy;
 457                 sr.w = dstrect->w = w;
 458                 sr.h = dstrect->h = h;
 459                 return SDL_LowerBlit(src, &sr, dst, dstrect);
 460         }
 461         dstrect->w = dstrect->h = 0;
 462         return 0;
 463 }
 464 
 465 /* 
 466  * This function performs a fast fill of the given rectangle with 'color'
 467  */
 468 int SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
     /* [<][>][^][v][top][bottom][index][help] */
 469 {
 470         SDL_VideoDevice *video = current_video;
 471         SDL_VideoDevice *this  = current_video;
 472         int x, y;
 473         Uint8 *row;
 474 
 475         /* If 'dstrect' == NULL, then fill the whole surface */
 476         if ( dstrect ) {
 477                 /* Perform clipping */
 478                 if ( !SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect) ) {
 479                         return(0);
 480                 }
 481         } else {
 482                 dstrect = &dst->clip_rect;
 483         }
 484 
 485         /* Check for hardware acceleration */
 486         if ( ((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) &&
 487                                         video->info.blit_fill ) {
 488                 return(video->FillHWRect(this, dst, dstrect, color));
 489         }
 490 
 491         /* Perform software fill */
 492         if ( SDL_LockSurface(dst) != 0 ) {
 493                 return(-1);
 494         }
 495         row = (Uint8 *)dst->pixels+dstrect->y*dst->pitch+
 496                         dstrect->x*dst->format->BytesPerPixel;
 497         if ( dst->format->palette || (color == 0) ) {
 498                 x = dstrect->w*dst->format->BytesPerPixel;
 499                 if ( !color && !((long)row&3) && !(x&3) && !(dst->pitch&3) ) {
 500                         int n = x >> 2;
 501                         for ( y=dstrect->h; y; --y ) {
 502                                 SDL_memset4(row, 0, n);
 503                                 row += dst->pitch;
 504                         }
 505                 } else {
 506 #ifdef __powerpc__
 507                         /*
 508                          * memset() on PPC (both glibc and codewarrior) uses
 509                          * the dcbz (Data Cache Block Zero) instruction, which
 510                          * causes an alignment exception if the destination is
 511                          * uncachable, so only use it on software surfaces
 512                          */
 513                         if((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
 514                                 if(dstrect->w >= 8) {
 515                                         /*
 516                                          * 64-bit stores are probably most
 517                                          * efficient to uncached video memory
 518                                          */
 519                                         double fill;
 520                                         memset(&fill, color, (sizeof fill));
 521                                         for(y = dstrect->h; y; y--) {
 522                                                 Uint8 *d = row;
 523                                                 unsigned n = x;
 524                                                 unsigned nn;
 525                                                 Uint8 c = color;
 526                                                 double f = fill;
 527                                                 while((unsigned long)d
 528                                                       & (sizeof(double) - 1)) {
 529                                                         *d++ = c;
 530                                                         n--;
 531                                                 }
 532                                                 nn = n / (sizeof(double) * 4);
 533                                                 while(nn) {
 534                                                         ((double *)d)[0] = f;
 535                                                         ((double *)d)[1] = f;
 536                                                         ((double *)d)[2] = f;
 537                                                         ((double *)d)[3] = f;
 538                                                         d += 4*sizeof(double);
 539                                                         nn--;
 540                                                 }
 541                                                 n &= ~(sizeof(double) * 4 - 1);
 542                                                 nn = n / sizeof(double);
 543                                                 while(nn) {
 544                                                         *(double *)d = f;
 545                                                         d += sizeof(double);
 546                                                         nn--;
 547                                                 }
 548                                                 n &= ~(sizeof(double) - 1);
 549                                                 while(n) {
 550                                                         *d++ = c;
 551                                                         n--;
 552                                                 }
 553                                                 row += dst->pitch;
 554                                         }
 555                                 } else {
 556                                         /* narrow boxes */
 557                                         for(y = dstrect->h; y; y--) {
 558                                                 Uint8 *d = row;
 559                                                 Uint8 c = color;
 560                                                 int n = x;
 561                                                 while(n) {
 562                                                         *d++ = c;
 563                                                         n--;
 564                                                 }
 565                                                 row += dst->pitch;
 566                                         }
 567                                 }
 568                         } else
 569 #endif /* __powerpc__ */
 570                         {
 571                                 for(y = dstrect->h; y; y--) {
 572                                         memset(row, color, x);
 573                                         row += dst->pitch;
 574                                 }
 575                         }
 576                 }
 577         } else {
 578                 switch (dst->format->BytesPerPixel) {
 579                     case 2:
 580                         for ( y=dstrect->h; y; --y ) {
 581                                 Uint16 *pixels = (Uint16 *)row;
 582                                 Uint16 c = color;
 583                                 Uint32 cc = (Uint32)c << 16 | c;
 584                                 int n = dstrect->w;
 585                                 if((unsigned long)pixels & 3) {
 586                                         *pixels++ = c;
 587                                         n--;
 588                                 }
 589                                 if(n >> 1)
 590                                         SDL_memset4(pixels, cc, n >> 1);
 591                                 if(n & 1)
 592                                         pixels[n - 1] = c;
 593                                 row += dst->pitch;
 594                         }
 595                         break;
 596 
 597                     case 3:
 598                         if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
 599                                 color <<= 8;
 600                         for ( y=dstrect->h; y; --y ) {
 601                                 Uint8 *pixels = row;
 602                                 for ( x=dstrect->w; x; --x ) {
 603                                         memcpy(pixels, &color, 3);
 604                                         pixels += 3;
 605                                 }
 606                                 row += dst->pitch;
 607                         }
 608                         break;
 609 
 610                     case 4:
 611                         for(y = dstrect->h; y; --y) {
 612                                 SDL_memset4(row, color, dstrect->w);
 613                                 row += dst->pitch;
 614                         }
 615                         break;
 616                 }
 617         }
 618         SDL_UnlockSurface(dst);
 619 
 620         /* We're done! */
 621         return(0);
 622 }
 623 
 624 /*
 625  * Lock a surface to directly access the pixels
 626  * -- Do not call this from any blit function, as SDL_DrawCursor() may recurse
 627  *    Instead, use:
 628  *    if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE )
 629  *               video->LockHWSurface(video, surface);
 630  */
 631 int SDL_LockSurface (SDL_Surface *surface)
     /* [<][>][^][v][top][bottom][index][help] */
 632 {
 633         if ( ! surface->locked ) {
 634                 /* Perform the lock */
 635                 if ( surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
 636                         SDL_VideoDevice *video = current_video;
 637                         SDL_VideoDevice *this  = current_video;
 638                         if ( video->LockHWSurface(this, surface) < 0 ) {
 639                                 return(-1);
 640                         }
 641                 }
 642                 if ( surface->flags & SDL_RLEACCEL ) {
 643                         SDL_UnRLESurface(surface, 1);
 644                         surface->flags |= SDL_RLEACCEL; /* save accel'd state */
 645                 }
 646                 /* This needs to be done here in case pixels changes value */
 647                 surface->pixels = (Uint8 *)surface->pixels + surface->offset;
 648         }
 649 
 650         /* Increment the surface lock count, for recursive locks */
 651         ++surface->locked;
 652 
 653         /* Ready to go.. */
 654         return(0);
 655 }
 656 /*
 657  * Unlock a previously locked surface
 658  * -- Do not call this from any blit function, as SDL_DrawCursor() may recurse
 659  *    Instead, use:
 660  *    if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE )
 661  *               video->UnlockHWSurface(video, surface);
 662  */
 663 void SDL_UnlockSurface (SDL_Surface *surface)
     /* [<][>][^][v][top][bottom][index][help] */
 664 {
 665         /* Only perform an unlock if we are locked */
 666         if ( ! surface->locked || (--surface->locked > 0) ) {
 667                 return;
 668         }
 669 
 670         /* Perform the unlock */
 671         surface->pixels = (Uint8 *)surface->pixels - surface->offset;
 672 
 673         /* Unlock hardware or accelerated surfaces */
 674         if ( surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
 675                 SDL_VideoDevice *video = current_video;
 676                 SDL_VideoDevice *this  = current_video;
 677                 video->UnlockHWSurface(this, surface);
 678         } else {
 679                 /* Update RLE encoded surface with new data */
 680                 if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
 681                         surface->flags &= ~SDL_RLEACCEL; /* stop lying */
 682                         SDL_RLESurface(surface);
 683                 }
 684         }
 685 }
 686 
 687 /* 
 688  * Convert a surface into the specified pixel format.
 689  */
 690 SDL_Surface * SDL_ConvertSurface (SDL_Surface *surface,
     /* [<][>][^][v][top][bottom][index][help] */
 691                                         SDL_PixelFormat *format, Uint32 flags)
 692 {
 693         SDL_Surface *convert;
 694         Uint32 colorkey = 0;
 695         Uint8 alpha = 0;
 696         Uint32 surface_flags;
 697         SDL_Rect bounds;
 698 
 699         /* Check for empty destination palette! (results in empty image) */
 700         if ( format->palette != NULL ) {
 701                 int i;
 702                 for ( i=0; i<format->palette->ncolors; ++i ) {
 703                         if ( (format->palette->colors[i].r != 0) ||
 704                              (format->palette->colors[i].g != 0) ||
 705                              (format->palette->colors[i].b != 0) )
 706                                 break;
 707                 }
 708                 if ( i == format->palette->ncolors ) {
 709                         SDL_SetError("Empty destination palette");
 710                         return(NULL);
 711                 }
 712         }
 713 
 714         /* Create a new surface with the desired format */
 715         convert = SDL_CreateRGBSurface(flags,
 716                                 surface->w, surface->h, format->BitsPerPixel,
 717                 format->Rmask, format->Gmask, format->Bmask, format->Amask);
 718         if ( convert == NULL ) {
 719                 return(NULL);
 720         }
 721 
 722         /* Copy the palette if any */
 723         if ( format->palette && convert->format->palette ) {
 724                 memcpy(convert->format->palette->colors,
 725                                 format->palette->colors,
 726                                 format->palette->ncolors*sizeof(SDL_Color));
 727                 convert->format->palette->ncolors = format->palette->ncolors;
 728         }
 729 
 730         /* Save the original surface color key and alpha */
 731         surface_flags = surface->flags;
 732         if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
 733                 /* Convert colourkeyed surfaces to RGBA if requested */
 734                 if((flags & SDL_SRCCOLORKEY) != SDL_SRCCOLORKEY
 735                    && format->Amask) {
 736                         surface_flags &= ~SDL_SRCCOLORKEY;
 737                 } else {
 738                         colorkey = surface->format->colorkey;
 739                         SDL_SetColorKey(surface, 0, 0);
 740                 }
 741         }
 742         if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
 743                 alpha = surface->format->alpha;
 744                 SDL_SetAlpha(surface, 0, 0);
 745         }
 746 
 747         /* Copy over the image data */
 748         bounds.x = 0;
 749         bounds.y = 0;
 750         bounds.w = surface->w;
 751         bounds.h = surface->h;
 752         SDL_LowerBlit(surface, &bounds, convert, &bounds);
 753 
 754         /* Clean up the original surface, and update converted surface */
 755         if ( convert != NULL ) {
 756                 SDL_SetClipRect(convert, &surface->clip_rect);
 757         }
 758         if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
 759                 Uint32 cflags = surface_flags&(SDL_SRCCOLORKEY|SDL_RLEACCELOK);
 760                 if ( convert != NULL ) {
 761                         Uint8 keyR, keyG, keyB;
 762 
 763                         SDL_GetRGB(colorkey,surface->format,&keyR,&keyG,&keyB);
 764                         SDL_SetColorKey(convert, cflags|(flags&SDL_RLEACCELOK),
 765                                 SDL_MapRGB(convert->format, keyR, keyG, keyB));
 766                 }
 767                 SDL_SetColorKey(surface, cflags, colorkey);
 768         }
 769         if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
 770                 Uint32 aflags = surface_flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
 771                 if ( convert != NULL ) {
 772                         SDL_SetAlpha(convert, aflags|(flags&SDL_RLEACCELOK),
 773                                 alpha);
 774                 }
 775                 SDL_SetAlpha(surface, aflags, alpha);
 776         }
 777 
 778         /* We're ready to go! */
 779         return(convert);
 780 }
 781 
 782 /*
 783  * Free a surface created by the above function.
 784  */
 785 void SDL_FreeSurface (SDL_Surface *surface)
     /* [<][>][^][v][top][bottom][index][help] */
 786 {
 787         /* Free anything that's not NULL, and not the screen surface */
 788         if ((surface == NULL) ||
 789             (current_video &&
 790             ((surface == SDL_ShadowSurface)||(surface == SDL_VideoSurface)))) {
 791                 return;
 792         }
 793         if ( --surface->refcount > 0 ) {
 794                 return;
 795         }
 796         if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
 797                 SDL_UnRLESurface(surface, 0);
 798         }
 799         if ( surface->format ) {
 800                 SDL_FreeFormat(surface->format);
 801                 surface->format = NULL;
 802         }
 803         if ( surface->map != NULL ) {
 804                 SDL_FreeBlitMap(surface->map);
 805                 surface->map = NULL;
 806         }
 807         if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
 808                 SDL_VideoDevice *video = current_video;
 809                 SDL_VideoDevice *this  = current_video;
 810                 video->FreeHWSurface(this, surface);
 811         }
 812         if ( surface->pixels &&
 813              ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC) ) {
 814                 free(surface->pixels);
 815         }
 816         free(surface);
 817 #ifdef CHECK_LEAKS
 818         --surfaces_allocated;
 819 #endif
 820 }

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