src/video/SDL_surface.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 17 Aug 2007 00:54:53 +0000
changeset 2257 340942cfda48
parent 2253 6d99edd791bf
child 2260 202ddfd1cfb1
permissions -rw-r--r--
Moved the colorkey and per-surface alpha into the blit info,
in preparation for support for general color channel modulation.

Removed and consolidated some data in the blit info.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 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     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #include "SDL_video.h"
    25 #include "SDL_compat.h"
    26 #include "SDL_sysvideo.h"
    27 #include "SDL_blit.h"
    28 #include "SDL_RLEaccel_c.h"
    29 #include "SDL_pixels_c.h"
    30 #include "SDL_leaks.h"
    31 
    32 
    33 /* Public routines */
    34 /*
    35  * Create an empty RGB surface of the appropriate depth
    36  */
    37 SDL_Surface *
    38 SDL_CreateRGBSurface(Uint32 flags,
    39                      int width, int height, int depth,
    40                      Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
    41 {
    42     SDL_Surface *surface;
    43 
    44     /* Allocate the surface */
    45     surface = (SDL_Surface *) SDL_calloc(1, sizeof(*surface));
    46     if (surface == NULL) {
    47         SDL_OutOfMemory();
    48         return NULL;
    49     }
    50 
    51     surface->format = SDL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask);
    52     if (!surface->format) {
    53         SDL_FreeSurface(surface);
    54         return NULL;
    55     }
    56     if (Amask) {
    57         surface->flags |= SDL_SRCALPHA;
    58     }
    59     surface->w = width;
    60     surface->h = height;
    61     surface->pitch = SDL_CalculatePitch(surface);
    62     SDL_SetClipRect(surface, NULL);
    63 
    64     if (surface->format->BitsPerPixel <= 8) {
    65         SDL_Palette *palette =
    66             SDL_AllocPalette((1 << surface->format->BitsPerPixel));
    67         if (!palette) {
    68             SDL_FreeSurface(surface);
    69             return NULL;
    70         }
    71         if (Rmask || Bmask || Gmask) {
    72             const SDL_PixelFormat *format = surface->format;
    73 
    74             /* create palette according to masks */
    75             int i;
    76             int Rm = 0, Gm = 0, Bm = 0;
    77             int Rw = 0, Gw = 0, Bw = 0;
    78 
    79             if (Rmask) {
    80                 Rw = 8 - format->Rloss;
    81                 for (i = format->Rloss; i > 0; i -= Rw)
    82                     Rm |= 1 << i;
    83             }
    84             if (Gmask) {
    85                 Gw = 8 - format->Gloss;
    86                 for (i = format->Gloss; i > 0; i -= Gw)
    87                     Gm |= 1 << i;
    88             }
    89             if (Bmask) {
    90                 Bw = 8 - format->Bloss;
    91                 for (i = format->Bloss; i > 0; i -= Bw)
    92                     Bm |= 1 << i;
    93             }
    94             for (i = 0; i < palette->ncolors; ++i) {
    95                 int r, g, b;
    96                 r = (i & Rmask) >> format->Rshift;
    97                 r = (r << format->Rloss) | ((r * Rm) >> Rw);
    98                 palette->colors[i].r = r;
    99 
   100                 g = (i & Gmask) >> format->Gshift;
   101                 g = (g << format->Gloss) | ((g * Gm) >> Gw);
   102                 palette->colors[i].g = g;
   103 
   104                 b = (i & Bmask) >> format->Bshift;
   105                 b = (b << format->Bloss) | ((b * Bm) >> Bw);
   106                 palette->colors[i].b = b;
   107             }
   108         } else if (palette->ncolors == 2) {
   109             /* Create a black and white bitmap palette */
   110             palette->colors[0].r = 0xFF;
   111             palette->colors[0].g = 0xFF;
   112             palette->colors[0].b = 0xFF;
   113             palette->colors[1].r = 0x00;
   114             palette->colors[1].g = 0x00;
   115             palette->colors[1].b = 0x00;
   116         }
   117         SDL_SetSurfacePalette(surface, palette);
   118         SDL_FreePalette(palette);
   119     }
   120 
   121     /* Get the pixels */
   122     if (surface->w && surface->h) {
   123         surface->pixels = SDL_malloc(surface->h * surface->pitch);
   124         if (!surface->pixels) {
   125             SDL_FreeSurface(surface);
   126             SDL_OutOfMemory();
   127             return NULL;
   128         }
   129         /* This is important for bitmaps */
   130         SDL_memset(surface->pixels, 0, surface->h * surface->pitch);
   131     }
   132 
   133     /* Allocate an empty mapping */
   134     surface->map = SDL_AllocBlitMap();
   135     if (!surface->map) {
   136         SDL_FreeSurface(surface);
   137         return NULL;
   138     }
   139     SDL_FormatChanged(surface);
   140 
   141     /* The surface is ready to go */
   142     surface->refcount = 1;
   143 #ifdef CHECK_LEAKS
   144     ++surfaces_allocated;
   145 #endif
   146     return surface;
   147 }
   148 
   149 /*
   150  * Create an RGB surface from an existing memory buffer
   151  */
   152 SDL_Surface *
   153 SDL_CreateRGBSurfaceFrom(void *pixels,
   154                          int width, int height, int depth, int pitch,
   155                          Uint32 Rmask, Uint32 Gmask, Uint32 Bmask,
   156                          Uint32 Amask)
   157 {
   158     SDL_Surface *surface;
   159 
   160     surface =
   161         SDL_CreateRGBSurface(0, 0, 0, depth, Rmask, Gmask, Bmask, Amask);
   162     if (surface != NULL) {
   163         surface->flags |= SDL_PREALLOC;
   164         surface->pixels = pixels;
   165         surface->w = width;
   166         surface->h = height;
   167         surface->pitch = pitch;
   168         SDL_SetClipRect(surface, NULL);
   169     }
   170     return surface;
   171 }
   172 
   173 static int
   174 SDL_SurfacePaletteChanged(void *userdata, SDL_Palette * palette)
   175 {
   176     SDL_Surface *surface = (SDL_Surface *) userdata;
   177 
   178     SDL_FormatChanged(surface);
   179 
   180     return 0;
   181 }
   182 
   183 int
   184 SDL_SetSurfacePalette(SDL_Surface * surface, SDL_Palette * palette)
   185 {
   186     if (!surface || !surface->format) {
   187         SDL_SetError("SDL_SetSurfacePalette() passed a NULL surface");
   188         return -1;
   189     }
   190 
   191     if (palette && palette->ncolors != (1 << surface->format->BitsPerPixel)) {
   192         SDL_SetError
   193             ("SDL_SetSurfacePalette() passed a palette that doesn't match the surface format");
   194         return -1;
   195     }
   196 
   197     if (surface->format->palette == palette) {
   198         return 0;
   199     }
   200 
   201     if (surface->format->palette) {
   202         SDL_DelPaletteWatch(surface->format->palette,
   203                             SDL_SurfacePaletteChanged, surface);
   204     }
   205 
   206     surface->format->palette = palette;
   207 
   208     if (surface->format->palette) {
   209         SDL_AddPaletteWatch(surface->format->palette,
   210                             SDL_SurfacePaletteChanged, surface);
   211     }
   212     return 0;
   213 }
   214 
   215 /*
   216  * Set the color key in a blittable surface
   217  */
   218 int
   219 SDL_SetColorKey(SDL_Surface * surface, Uint32 flag, Uint32 key)
   220 {
   221     /* Sanity check the flag as it gets passed in */
   222     if (flag & SDL_SRCCOLORKEY) {
   223         if (flag & (SDL_RLEACCEL | SDL_RLEACCELOK)) {
   224             flag = (SDL_SRCCOLORKEY | SDL_RLEACCELOK);
   225         } else {
   226             flag = SDL_SRCCOLORKEY;
   227         }
   228     } else {
   229         flag = 0;
   230     }
   231 
   232     /* Optimize away operations that don't change anything */
   233     if ((flag == (surface->flags & (SDL_SRCCOLORKEY | SDL_RLEACCELOK))) &&
   234         (key == surface->map->ckey)) {
   235         return (0);
   236     }
   237 
   238     /* UnRLE surfaces before we change the colorkey */
   239     if (surface->flags & SDL_RLEACCEL) {
   240         SDL_UnRLESurface(surface, 1);
   241     }
   242 
   243     if (flag) {
   244         surface->flags |= SDL_SRCCOLORKEY;
   245         surface->map->ckey = key;
   246         if (flag & SDL_RLEACCELOK) {
   247             surface->flags |= SDL_RLEACCELOK;
   248         } else {
   249             surface->flags &= ~SDL_RLEACCELOK;
   250         }
   251     } else {
   252         surface->flags &= ~(SDL_SRCCOLORKEY | SDL_RLEACCELOK);
   253         surface->map->ckey = 0;
   254     }
   255     SDL_InvalidateMap(surface->map);
   256     return (0);
   257 }
   258 
   259 /* This function sets the alpha channel of a surface */
   260 int
   261 SDL_SetAlpha(SDL_Surface * surface, Uint32 flag, Uint8 value)
   262 {
   263     Uint32 oldflags = surface->flags;
   264     Uint32 oldalpha = (surface->map->cmod >> 24);
   265 
   266     /* Sanity check the flag as it gets passed in */
   267     if (flag & SDL_SRCALPHA) {
   268         if (flag & (SDL_RLEACCEL | SDL_RLEACCELOK)) {
   269             flag = (SDL_SRCALPHA | SDL_RLEACCELOK);
   270         } else {
   271             flag = SDL_SRCALPHA;
   272         }
   273     } else {
   274         flag = 0;
   275     }
   276 
   277     /* Optimize away operations that don't change anything */
   278     if ((flag == (surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK))) &&
   279         (!flag || value == oldalpha)) {
   280         return (0);
   281     }
   282 
   283     if (!(flag & SDL_RLEACCELOK) && (surface->flags & SDL_RLEACCEL))
   284         SDL_UnRLESurface(surface, 1);
   285 
   286     if (flag) {
   287         surface->flags |= SDL_SRCALPHA;
   288         surface->map->cmod &= 0x00FFFFFF;
   289         surface->map->cmod |= ((Uint32)value << 24);
   290         if (flag & SDL_RLEACCELOK) {
   291             surface->flags |= SDL_RLEACCELOK;
   292         } else {
   293             surface->flags &= ~SDL_RLEACCELOK;
   294         }
   295     } else {
   296         surface->flags &= ~SDL_SRCALPHA;
   297         surface->map->cmod |= 0xFF000000;
   298     }
   299     /*
   300      * The representation for software surfaces is independent of
   301      * per-surface alpha, so no need to invalidate the blit mapping
   302      * if just the alpha value was changed. (If either is 255, we still
   303      * need to invalidate.)
   304      */
   305     if (oldflags != surface->flags
   306         || (((oldalpha + 1) ^ (value + 1)) & 0x100)) {
   307         SDL_InvalidateMap(surface->map);
   308     }
   309     return (0);
   310 }
   311 
   312 int
   313 SDL_SetAlphaChannel(SDL_Surface * surface, Uint8 value)
   314 {
   315     int row, col;
   316     int offset;
   317     Uint8 *buf;
   318 
   319     if ((surface->format->Amask != 0xFF000000) &&
   320         (surface->format->Amask != 0x000000FF)) {
   321         SDL_SetError("Unsupported surface alpha mask format");
   322         return -1;
   323     }
   324 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
   325     if (surface->format->Amask == 0xFF000000) {
   326         offset = 3;
   327     } else {
   328         offset = 0;
   329     }
   330 #else
   331     if (surface->format->Amask == 0xFF000000) {
   332         offset = 0;
   333     } else {
   334         offset = 3;
   335     }
   336 #endif /* Byte ordering */
   337 
   338     /* Quickly set the alpha channel of an RGBA or ARGB surface */
   339     if (SDL_MUSTLOCK(surface)) {
   340         if (SDL_LockSurface(surface) < 0) {
   341             return -1;
   342         }
   343     }
   344     row = surface->h;
   345     while (row--) {
   346         col = surface->w;
   347         buf = (Uint8 *) surface->pixels + row * surface->pitch + offset;
   348         while (col--) {
   349             *buf = value;
   350             buf += 4;
   351         }
   352     }
   353     if (SDL_MUSTLOCK(surface)) {
   354         SDL_UnlockSurface(surface);
   355     }
   356     return 0;
   357 }
   358 
   359 /*
   360  * Set the clipping rectangle for a blittable surface
   361  */
   362 SDL_bool
   363 SDL_SetClipRect(SDL_Surface * surface, const SDL_Rect * rect)
   364 {
   365     SDL_Rect full_rect;
   366 
   367     /* Don't do anything if there's no surface to act on */
   368     if (!surface) {
   369         return SDL_FALSE;
   370     }
   371 
   372     /* Set up the full surface rectangle */
   373     full_rect.x = 0;
   374     full_rect.y = 0;
   375     full_rect.w = surface->w;
   376     full_rect.h = surface->h;
   377 
   378     /* Set the clipping rectangle */
   379     if (!rect) {
   380         surface->clip_rect = full_rect;
   381         return 1;
   382     }
   383     return SDL_IntersectRect(rect, &full_rect, &surface->clip_rect);
   384 }
   385 
   386 void
   387 SDL_GetClipRect(SDL_Surface * surface, SDL_Rect * rect)
   388 {
   389     if (surface && rect) {
   390         *rect = surface->clip_rect;
   391     }
   392 }
   393 
   394 /* 
   395  * Set up a blit between two surfaces -- split into three parts:
   396  * The upper part, SDL_UpperBlit(), performs clipping and rectangle 
   397  * verification.  The lower part is a pointer to a low level
   398  * accelerated blitting function.
   399  *
   400  * These parts are separated out and each used internally by this 
   401  * library in the optimimum places.  They are exported so that if
   402  * you know exactly what you are doing, you can optimize your code
   403  * by calling the one(s) you need.
   404  */
   405 int
   406 SDL_LowerBlit(SDL_Surface * src, SDL_Rect * srcrect,
   407               SDL_Surface * dst, SDL_Rect * dstrect)
   408 {
   409     /* Check to make sure the blit mapping is valid */
   410     if ((src->map->dst != dst) ||
   411         (src->map->dst->format_version != src->map->format_version)) {
   412         if (SDL_MapSurface(src, dst) < 0) {
   413             return (-1);
   414         }
   415     }
   416     return (src->map->blit(src, srcrect, dst, dstrect));
   417 }
   418 
   419 
   420 int
   421 SDL_UpperBlit(SDL_Surface * src, SDL_Rect * srcrect,
   422               SDL_Surface * dst, SDL_Rect * dstrect)
   423 {
   424     SDL_Rect fulldst;
   425     int srcx, srcy, w, h;
   426 
   427     /* Make sure the surfaces aren't locked */
   428     if (!src || !dst) {
   429         SDL_SetError("SDL_UpperBlit: passed a NULL surface");
   430         return (-1);
   431     }
   432     if (src->locked || dst->locked) {
   433         SDL_SetError("Surfaces must not be locked during blit");
   434         return (-1);
   435     }
   436 
   437     /* If the destination rectangle is NULL, use the entire dest surface */
   438     if (dstrect == NULL) {
   439         fulldst.x = fulldst.y = 0;
   440         dstrect = &fulldst;
   441     }
   442 
   443     /* clip the source rectangle to the source surface */
   444     if (srcrect) {
   445         int maxw, maxh;
   446 
   447         srcx = srcrect->x;
   448         w = srcrect->w;
   449         if (srcx < 0) {
   450             w += srcx;
   451             dstrect->x -= srcx;
   452             srcx = 0;
   453         }
   454         maxw = src->w - srcx;
   455         if (maxw < w)
   456             w = maxw;
   457 
   458         srcy = srcrect->y;
   459         h = srcrect->h;
   460         if (srcy < 0) {
   461             h += srcy;
   462             dstrect->y -= srcy;
   463             srcy = 0;
   464         }
   465         maxh = src->h - srcy;
   466         if (maxh < h)
   467             h = maxh;
   468 
   469     } else {
   470         srcx = srcy = 0;
   471         w = src->w;
   472         h = src->h;
   473     }
   474 
   475     /* clip the destination rectangle against the clip rectangle */
   476     {
   477         SDL_Rect *clip = &dst->clip_rect;
   478         int dx, dy;
   479 
   480         dx = clip->x - dstrect->x;
   481         if (dx > 0) {
   482             w -= dx;
   483             dstrect->x += dx;
   484             srcx += dx;
   485         }
   486         dx = dstrect->x + w - clip->x - clip->w;
   487         if (dx > 0)
   488             w -= dx;
   489 
   490         dy = clip->y - dstrect->y;
   491         if (dy > 0) {
   492             h -= dy;
   493             dstrect->y += dy;
   494             srcy += dy;
   495         }
   496         dy = dstrect->y + h - clip->y - clip->h;
   497         if (dy > 0)
   498             h -= dy;
   499     }
   500 
   501     if (w > 0 && h > 0) {
   502         SDL_Rect sr;
   503         sr.x = srcx;
   504         sr.y = srcy;
   505         sr.w = dstrect->w = w;
   506         sr.h = dstrect->h = h;
   507         return SDL_LowerBlit(src, &sr, dst, dstrect);
   508     }
   509     dstrect->w = dstrect->h = 0;
   510     return 0;
   511 }
   512 
   513 /*
   514  * Lock a surface to directly access the pixels
   515  */
   516 int
   517 SDL_LockSurface(SDL_Surface * surface)
   518 {
   519     if (!surface->locked) {
   520         /* Perform the lock */
   521         if (surface->flags & SDL_RLEACCEL) {
   522             SDL_UnRLESurface(surface, 1);
   523             surface->flags |= SDL_RLEACCEL;     /* save accel'd state */
   524         }
   525     }
   526 
   527     /* Increment the surface lock count, for recursive locks */
   528     ++surface->locked;
   529 
   530     /* Ready to go.. */
   531     return (0);
   532 }
   533 
   534 /*
   535  * Unlock a previously locked surface
   536  */
   537 void
   538 SDL_UnlockSurface(SDL_Surface * surface)
   539 {
   540     /* Only perform an unlock if we are locked */
   541     if (!surface->locked || (--surface->locked > 0)) {
   542         return;
   543     }
   544 
   545     /* Update RLE encoded surface with new data */
   546     if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
   547         surface->flags &= ~SDL_RLEACCEL;        /* stop lying */
   548         SDL_RLESurface(surface);
   549     }
   550 }
   551 
   552 /* 
   553  * Convert a surface into the specified pixel format.
   554  */
   555 SDL_Surface *
   556 SDL_ConvertSurface(SDL_Surface * surface,
   557                    SDL_PixelFormat * format, Uint32 flags)
   558 {
   559     SDL_Surface *convert;
   560     Uint32 colorkey = 0;
   561     Uint8 alpha = 0;
   562     Uint32 surface_flags;
   563     SDL_Rect bounds;
   564 
   565     /* Check for empty destination palette! (results in empty image) */
   566     if (format->palette != NULL) {
   567         int i;
   568         for (i = 0; i < format->palette->ncolors; ++i) {
   569             if ((format->palette->colors[i].r != 0xFF) ||
   570                 (format->palette->colors[i].g != 0xFF) ||
   571                 (format->palette->colors[i].b != 0xFF))
   572                 break;
   573         }
   574         if (i == format->palette->ncolors) {
   575             SDL_SetError("Empty destination palette");
   576             return (NULL);
   577         }
   578     }
   579 
   580     /* Create a new surface with the desired format */
   581     convert = SDL_CreateRGBSurface(flags,
   582                                    surface->w, surface->h,
   583                                    format->BitsPerPixel, format->Rmask,
   584                                    format->Gmask, format->Bmask,
   585                                    format->Amask);
   586     if (convert == NULL) {
   587         return (NULL);
   588     }
   589 
   590     /* Copy the palette if any */
   591     if (format->palette && convert->format->palette) {
   592         SDL_memcpy(convert->format->palette->colors,
   593                    format->palette->colors,
   594                    format->palette->ncolors * sizeof(SDL_Color));
   595         convert->format->palette->ncolors = format->palette->ncolors;
   596     }
   597 
   598     /* Save the original surface color key and alpha */
   599     surface_flags = surface->flags;
   600     if ((surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
   601         /* Convert colourkeyed surfaces to RGBA if requested */
   602         if ((flags & SDL_SRCCOLORKEY) != SDL_SRCCOLORKEY && format->Amask) {
   603             surface_flags &= ~SDL_SRCCOLORKEY;
   604         } else {
   605             colorkey = surface->map->ckey;
   606             SDL_SetColorKey(surface, 0, 0);
   607         }
   608     }
   609     if ((surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA) {
   610         /* Copy over the alpha channel to RGBA if requested */
   611         if (format->Amask) {
   612             surface->flags &= ~SDL_SRCALPHA;
   613         } else {
   614             alpha = (Uint8)(surface->map->cmod >> 24);
   615             SDL_SetAlpha(surface, 0, 0);
   616         }
   617     }
   618 
   619     /* Copy over the image data */
   620     bounds.x = 0;
   621     bounds.y = 0;
   622     bounds.w = surface->w;
   623     bounds.h = surface->h;
   624     SDL_LowerBlit(surface, &bounds, convert, &bounds);
   625 
   626     /* Clean up the original surface, and update converted surface */
   627     if (convert != NULL) {
   628         SDL_SetClipRect(convert, &surface->clip_rect);
   629     }
   630     if ((surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
   631         Uint32 cflags = surface_flags & (SDL_SRCCOLORKEY | SDL_RLEACCELOK);
   632         if (convert != NULL) {
   633             Uint8 keyR, keyG, keyB;
   634 
   635             SDL_GetRGB(colorkey, surface->format, &keyR, &keyG, &keyB);
   636             SDL_SetColorKey(convert, cflags | (flags & SDL_RLEACCELOK),
   637                             SDL_MapRGB(convert->format, keyR, keyG, keyB));
   638         }
   639         SDL_SetColorKey(surface, cflags, colorkey);
   640     }
   641     if ((surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA) {
   642         Uint32 aflags = surface_flags & (SDL_SRCALPHA | SDL_RLEACCELOK);
   643         if (convert != NULL) {
   644             SDL_SetAlpha(convert, aflags | (flags & SDL_RLEACCELOK), alpha);
   645         }
   646         if (format->Amask) {
   647             surface->flags |= SDL_SRCALPHA;
   648         } else {
   649             SDL_SetAlpha(surface, aflags, alpha);
   650         }
   651     }
   652 
   653     /* We're ready to go! */
   654     return (convert);
   655 }
   656 
   657 /*
   658  * Free a surface created by the above function.
   659  */
   660 void
   661 SDL_FreeSurface(SDL_Surface * surface)
   662 {
   663     if (surface == NULL) {
   664         return;
   665     }
   666     if (--surface->refcount > 0) {
   667         return;
   668     }
   669     while (surface->locked > 0) {
   670         SDL_UnlockSurface(surface);
   671     }
   672     if (surface->flags & SDL_RLEACCEL) {
   673         SDL_UnRLESurface(surface, 0);
   674     }
   675     if (surface->format) {
   676         SDL_SetSurfacePalette(surface, NULL);
   677         SDL_FreeFormat(surface->format);
   678         surface->format = NULL;
   679     }
   680     if (surface->map != NULL) {
   681         SDL_FreeBlitMap(surface->map);
   682         surface->map = NULL;
   683     }
   684     if (surface->pixels && ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC)) {
   685         SDL_free(surface->pixels);
   686     }
   687     SDL_free(surface);
   688 #ifdef CHECK_LEAKS
   689     --surfaces_allocated;
   690 #endif
   691 }
   692 
   693 /* vi: set ts=4 sw=4 expandtab: */