src/video/SDL_surface.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 18 Aug 2007 01:44:21 +0000
changeset 2266 e61ad15a205f
parent 2260 202ddfd1cfb1
child 2267 c785543d1843
permissions -rw-r--r--
More work in progress integrating SDL_Surface and the new SDL_Texture API
     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 int SDL_SetSurfaceRLE(SDL_Surface *surface, int flag)
   216 {
   217     Uint32 flags;
   218 
   219     if (!surface) {
   220         return -1;
   221     }
   222 
   223     if (flag) {
   224         surface->flags |= SDL_RLEACCELOK;
   225     } else {
   226         surface->flags &= ~SDL_RLEACCELOK;
   227     }
   228     if (surface->flags != flags) {
   229         SDL_InvalidateMap(surface->map);
   230     }
   231     return 0;
   232 }
   233 
   234 int SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key)
   235 {
   236     int flags;
   237 
   238     if (!surface) {
   239         return -1;
   240     }
   241 
   242     if (flag & SDL_RLEACCEL) {
   243         SDL_SetSurfaceRLE(surface, 1);
   244     }
   245 
   246     flags = surface->map->info.flags;
   247     if (flag) {
   248         surface->map->info.flags |= SDL_COPY_COLORKEY;
   249         surface->map->info.colorkey = key;
   250     } else {
   251         surface->map->info.flags &= ~SDL_COPY_COLORKEY;
   252     }
   253     if (surface->map->info.flags != flags) {
   254         SDL_InvalidateMap(surface->map);
   255     }
   256     return 0;
   257 }
   258 
   259 int SDL_SetSurfaceColorMod(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b)
   260 {
   261     int flags;
   262 
   263     if (!surface) {
   264         return -1;
   265     }
   266 
   267     surface->map->info.r = r;
   268     surface->map->info.g = g;
   269     surface->map->info.b = b;
   270 
   271     flags = surface->map->info.flags;
   272     if (r != 0xFF || g != 0xFF || b != 0xFF) {
   273         surface->map->info.flags |= SDL_COPY_MODULATE_COLOR;
   274     } else {
   275         surface->map->info.flags &= ~SDL_COPY_MODULATE_COLOR;
   276     }
   277     if (surface->map->info.flags != flags) {
   278         SDL_InvalidateMap(surface->map);
   279     }
   280     return 0;
   281 }
   282 
   283 
   284 int SDL_GetSurfaceColorMod(SDL_Surface *surface, Uint8 * r, Uint8 * g, Uint8 * b)
   285 {
   286     if (!surface) {
   287         return -1;
   288     }
   289 
   290     if (r) {
   291         *r = surface->map->info.r;
   292     }
   293     if (g) {
   294         *g = surface->map->info.g;
   295     }
   296     if (b) {
   297         *b = surface->map->info.b;
   298     }
   299     return 0;
   300 }
   301 
   302 int SDL_SetSurfaceAlphaMod(SDL_Surface *surface, Uint8 alpha)
   303 {
   304     int flags;
   305 
   306     if (!surface) {
   307         return -1;
   308     }
   309 
   310     surface->map->info.a = alpha;
   311 
   312     flags = surface->map->info.flags;
   313     if (alpha != 0xFF) {
   314         surface->map->info.flags |= SDL_COPY_MODULATE_ALPHA;
   315     } else {
   316         surface->map->info.flags &= ~SDL_COPY_MODULATE_ALPHA;
   317     }
   318     if (surface->map->info.flags != flags) {
   319         SDL_InvalidateMap(surface->map);
   320     }
   321     return 0;
   322 }
   323 
   324 int SDL_GetSurfaceAlphaMod(SDL_Surface *surface, Uint8 * alpha)
   325 {
   326     if (!surface) {
   327         return -1;
   328     }
   329 
   330     if (alpha) {
   331         *alpha = surface->map->info.a;
   332     }
   333     return 0;
   334 }
   335 
   336 int SDL_SetSurfaceBlendMode(SDL_Surface *surface, int blendMode)
   337 {
   338     int flags, status;
   339 
   340     if (!surface) {
   341         return -1;
   342     }
   343 
   344     status = 0;
   345     flags = surface->map->info.flags;
   346     surface->map->info.flags &= ~(SDL_COPY_MASK|SDL_COPY_BLEND|SDL_COPY_ADD|SDL_COPY_MOD);
   347     switch (blendMode) {
   348     case SDL_TEXTUREBLENDMODE_NONE:
   349         break;
   350     case SDL_TEXTUREBLENDMODE_MASK:
   351         surface->map->info.flags |= SDL_COPY_MASK;
   352         break;
   353     case SDL_TEXTUREBLENDMODE_BLEND:
   354         surface->map->info.flags |= SDL_COPY_BLEND;
   355         break;
   356     case SDL_TEXTUREBLENDMODE_ADD:
   357         surface->map->info.flags |= SDL_COPY_ADD;
   358         break;
   359     case SDL_TEXTUREBLENDMODE_MOD:
   360         surface->map->info.flags |= SDL_COPY_MOD;
   361         break;
   362     default:
   363         SDL_Unsupported();
   364         status = -1;
   365         break;
   366     }
   367 
   368     if (surface->map->info.flags != flags) {
   369         SDL_InvalidateMap(surface->map);
   370     }
   371     return status;
   372 }
   373 
   374 int SDL_GetSurfaceBlendMode(SDL_Surface *surface, int *blendMode)
   375 {
   376     if (!surface) {
   377         return -1;
   378     }
   379 
   380     if (!blendMode) {
   381         return 0;
   382     }
   383 
   384     switch(surface->map->info.flags & (SDL_COPY_MASK|SDL_COPY_BLEND|SDL_COPY_ADD|SDL_COPY_MOD)) {
   385     case SDL_COPY_MASK:
   386         *blendMode = SDL_TEXTUREBLENDMODE_MASK:
   387         break;
   388     case SDL_COPY_BLEND:
   389         *blendMode = SDL_TEXTUREBLENDMODE_BLEND:
   390         break;
   391     case SDL_COPY_ADD:
   392         *blendMode = SDL_TEXTUREBLENDMODE_ADD:
   393         break;
   394     case SDL_COPY_MOD:
   395         *blendMode = SDL_TEXTUREBLENDMODE_MOD:
   396         break;
   397     default:
   398         *blendMode = SDL_TEXTUREBLENDMODE_NONE:
   399         break;
   400     }
   401     return 0;
   402 }
   403 
   404 int SDL_SetSurfaceScaleMode(SDL_Surface *surface, int scaleMode)
   405 {
   406     int flags, status;
   407 
   408     if (!surface) {
   409         return -1;
   410     }
   411 
   412     status = 0;
   413     flags = surface->map->info.flags;
   414     surface->map->info.flags &= ~(SDL_COPY_NEAREST);
   415     switch (scaleMode) {
   416     case SDL_TEXTURESCALEMODE_NONE:
   417         break;
   418     case SDL_TEXTURESCALEMODE_FAST:
   419         surface->map->info.flags |= SDL_COPY_NEAREST;
   420         break;
   421     case SDL_TEXTURESCALEMODE_SLOW:
   422     case SDL_TEXTURESCALEMODE_BEST:
   423         SDL_Unsupported();
   424         surface->map->info.flags |= SDL_COPY_NEAREST;
   425         status = -1;
   426         break;
   427     default:
   428         SDL_Unsupported();
   429         status = -1;
   430         break;
   431     }
   432 
   433     if (surface->map->info.flags != flags) {
   434         SDL_InvalidateMap(surface->map);
   435     }
   436     return status;
   437 }
   438 
   439 int SDL_GetSurfaceScaleMode(SDL_Surface *surface, int *scaleMode)
   440 {
   441     if (!surface) {
   442         return -1;
   443     }
   444 
   445     if (!scaleMode) {
   446         return 0;
   447     }
   448 
   449     switch(surface->map->info.flags & (SDL_COPY_LINEAR)) {
   450     case SDL_COPY_LINEAR:
   451         *scaleMode = SDL_TEXTURESCALEMODE_FAST:
   452         break;
   453     default:
   454         *scaleMode = SDL_TEXTURESCALEMODE_NONE:
   455         break;
   456     }
   457     return 0;
   458 }
   459 
   460 SDL_bool
   461 SDL_SetClipRect(SDL_Surface * surface, const SDL_Rect * rect)
   462 {
   463     SDL_Rect full_rect;
   464 
   465     /* Don't do anything if there's no surface to act on */
   466     if (!surface) {
   467         return SDL_FALSE;
   468     }
   469 
   470     /* Set up the full surface rectangle */
   471     full_rect.x = 0;
   472     full_rect.y = 0;
   473     full_rect.w = surface->w;
   474     full_rect.h = surface->h;
   475 
   476     /* Set the clipping rectangle */
   477     if (!rect) {
   478         surface->clip_rect = full_rect;
   479         return 1;
   480     }
   481     return SDL_IntersectRect(rect, &full_rect, &surface->clip_rect);
   482 }
   483 
   484 void
   485 SDL_GetClipRect(SDL_Surface * surface, SDL_Rect * rect)
   486 {
   487     if (surface && rect) {
   488         *rect = surface->clip_rect;
   489     }
   490 }
   491 
   492 /* 
   493  * Set up a blit between two surfaces -- split into three parts:
   494  * The upper part, SDL_UpperBlit(), performs clipping and rectangle 
   495  * verification.  The lower part is a pointer to a low level
   496  * accelerated blitting function.
   497  *
   498  * These parts are separated out and each used internally by this 
   499  * library in the optimimum places.  They are exported so that if
   500  * you know exactly what you are doing, you can optimize your code
   501  * by calling the one(s) you need.
   502  */
   503 int
   504 SDL_LowerBlit(SDL_Surface * src, SDL_Rect * srcrect,
   505               SDL_Surface * dst, SDL_Rect * dstrect)
   506 {
   507     /* Check to make sure the blit mapping is valid */
   508     if ((src->map->dst != dst) ||
   509         (src->map->dst->format_version != src->map->format_version)) {
   510         if (SDL_MapSurface(src, dst) < 0) {
   511             return (-1);
   512         }
   513     }
   514     return (src->map->blit(src, srcrect, dst, dstrect));
   515 }
   516 
   517 
   518 int
   519 SDL_UpperBlit(SDL_Surface * src, SDL_Rect * srcrect,
   520               SDL_Surface * dst, SDL_Rect * dstrect)
   521 {
   522     SDL_Rect fulldst;
   523     int srcx, srcy, w, h;
   524 
   525     /* Make sure the surfaces aren't locked */
   526     if (!src || !dst) {
   527         SDL_SetError("SDL_UpperBlit: passed a NULL surface");
   528         return (-1);
   529     }
   530     if (src->locked || dst->locked) {
   531         SDL_SetError("Surfaces must not be locked during blit");
   532         return (-1);
   533     }
   534 
   535     /* If the destination rectangle is NULL, use the entire dest surface */
   536     if (dstrect == NULL) {
   537         fulldst.x = fulldst.y = 0;
   538         dstrect = &fulldst;
   539     }
   540 
   541     /* clip the source rectangle to the source surface */
   542     if (srcrect) {
   543         int maxw, maxh;
   544 
   545         srcx = srcrect->x;
   546         w = srcrect->w;
   547         if (srcx < 0) {
   548             w += srcx;
   549             dstrect->x -= srcx;
   550             srcx = 0;
   551         }
   552         maxw = src->w - srcx;
   553         if (maxw < w)
   554             w = maxw;
   555 
   556         srcy = srcrect->y;
   557         h = srcrect->h;
   558         if (srcy < 0) {
   559             h += srcy;
   560             dstrect->y -= srcy;
   561             srcy = 0;
   562         }
   563         maxh = src->h - srcy;
   564         if (maxh < h)
   565             h = maxh;
   566 
   567     } else {
   568         srcx = srcy = 0;
   569         w = src->w;
   570         h = src->h;
   571     }
   572 
   573     /* clip the destination rectangle against the clip rectangle */
   574     {
   575         SDL_Rect *clip = &dst->clip_rect;
   576         int dx, dy;
   577 
   578         dx = clip->x - dstrect->x;
   579         if (dx > 0) {
   580             w -= dx;
   581             dstrect->x += dx;
   582             srcx += dx;
   583         }
   584         dx = dstrect->x + w - clip->x - clip->w;
   585         if (dx > 0)
   586             w -= dx;
   587 
   588         dy = clip->y - dstrect->y;
   589         if (dy > 0) {
   590             h -= dy;
   591             dstrect->y += dy;
   592             srcy += dy;
   593         }
   594         dy = dstrect->y + h - clip->y - clip->h;
   595         if (dy > 0)
   596             h -= dy;
   597     }
   598 
   599     if (w > 0 && h > 0) {
   600         SDL_Rect sr;
   601         sr.x = srcx;
   602         sr.y = srcy;
   603         sr.w = dstrect->w = w;
   604         sr.h = dstrect->h = h;
   605         return SDL_LowerBlit(src, &sr, dst, dstrect);
   606     }
   607     dstrect->w = dstrect->h = 0;
   608     return 0;
   609 }
   610 
   611 /*
   612  * Lock a surface to directly access the pixels
   613  */
   614 int
   615 SDL_LockSurface(SDL_Surface * surface)
   616 {
   617     if (!surface->locked) {
   618         /* Perform the lock */
   619         if (surface->flags & SDL_RLEACCEL) {
   620             SDL_UnRLESurface(surface, 1);
   621             surface->flags |= SDL_RLEACCEL;     /* save accel'd state */
   622         }
   623     }
   624 
   625     /* Increment the surface lock count, for recursive locks */
   626     ++surface->locked;
   627 
   628     /* Ready to go.. */
   629     return (0);
   630 }
   631 
   632 /*
   633  * Unlock a previously locked surface
   634  */
   635 void
   636 SDL_UnlockSurface(SDL_Surface * surface)
   637 {
   638     /* Only perform an unlock if we are locked */
   639     if (!surface->locked || (--surface->locked > 0)) {
   640         return;
   641     }
   642 
   643     /* Update RLE encoded surface with new data */
   644     if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
   645         surface->flags &= ~SDL_RLEACCEL;        /* stop lying */
   646         SDL_RLESurface(surface);
   647     }
   648 }
   649 
   650 /* 
   651  * Convert a surface into the specified pixel format.
   652  */
   653 SDL_Surface *
   654 SDL_ConvertSurface(SDL_Surface * surface,
   655                    SDL_PixelFormat * format, Uint32 flags)
   656 {
   657     SDL_Surface *convert;
   658     Uint32 copy_flags;
   659     SDL_Rect bounds;
   660 
   661     /* Check for empty destination palette! (results in empty image) */
   662     if (format->palette != NULL) {
   663         int i;
   664         for (i = 0; i < format->palette->ncolors; ++i) {
   665             if ((format->palette->colors[i].r != 0xFF) ||
   666                 (format->palette->colors[i].g != 0xFF) ||
   667                 (format->palette->colors[i].b != 0xFF))
   668                 break;
   669         }
   670         if (i == format->palette->ncolors) {
   671             SDL_SetError("Empty destination palette");
   672             return (NULL);
   673         }
   674     }
   675 
   676     /* Create a new surface with the desired format */
   677     convert = SDL_CreateRGBSurface(0, surface->w, surface->h,
   678                                    format->BitsPerPixel, format->Rmask,
   679                                    format->Gmask, format->Bmask,
   680                                    format->Amask);
   681     if (convert == NULL) {
   682         return (NULL);
   683     }
   684 
   685     /* Copy the palette if any */
   686     if (format->palette && convert->format->palette) {
   687         SDL_memcpy(convert->format->palette->colors,
   688                    format->palette->colors,
   689                    format->palette->ncolors * sizeof(SDL_Color));
   690         convert->format->palette->ncolors = format->palette->ncolors;
   691     }
   692 
   693     /* Save the original copy flags */
   694     copy_flags = surface->map->info.flags;
   695     surface->map->info.flags = 0;
   696 
   697     /* Copy over the image data */
   698     bounds.x = 0;
   699     bounds.y = 0;
   700     bounds.w = surface->w;
   701     bounds.h = surface->h;
   702     SDL_LowerBlit(surface, &bounds, convert, &bounds);
   703 
   704     /* Clean up the original surface, and update converted surface */
   705     SDL_SetClipRect(convert, &surface->clip_rect);
   706     if (copy_flags & SDL_COPY_COLORKEY) {
   707         Uint8 keyR, keyG, keyB, keyA;
   708 
   709         SDL_GetRGBA(colorkey, surface->format, &keyR, &keyG, &keyB, &keyA);
   710         SDL_SetColorKey(convert, 1,
   711                         SDL_MapRGBA(convert->format, keyR, keyG, keyB, keyA));
   712     }
   713     convert->map->info.r = surface->map->info.r;
   714     convert->map->info.g = surface->map->info.g;
   715     convert->map->info.b = surface->map->info.b;
   716     convert->map->info.a = surface->map->info.a;
   717     convert->map->info.flags = copy_flags;
   718     surface->map->info.flags = copy_flags;
   719 
   720     /* Enable alpha blending by default if the new surface has an
   721      * alpha channel or alpha modulation */
   722     if (format->Amask || (copy_flags & SDL_COPY_MODULATE_ALPHA)) {
   723         SDL_SetSurfaceBlendMode(convert, SDL_TEXTUREBLENDMODE_BLEND);
   724     }
   725 
   726     /* We're ready to go! */
   727     return (convert);
   728 }
   729 
   730 /*
   731  * Free a surface created by the above function.
   732  */
   733 void
   734 SDL_FreeSurface(SDL_Surface * surface)
   735 {
   736     if (surface == NULL) {
   737         return;
   738     }
   739     if (--surface->refcount > 0) {
   740         return;
   741     }
   742     while (surface->locked > 0) {
   743         SDL_UnlockSurface(surface);
   744     }
   745     if (surface->flags & SDL_RLEACCEL) {
   746         SDL_UnRLESurface(surface, 0);
   747     }
   748     if (surface->format) {
   749         SDL_SetSurfacePalette(surface, NULL);
   750         SDL_FreeFormat(surface->format);
   751         surface->format = NULL;
   752     }
   753     if (surface->map != NULL) {
   754         SDL_FreeBlitMap(surface->map);
   755         surface->map = NULL;
   756     }
   757     if (surface->pixels && ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC)) {
   758         SDL_free(surface->pixels);
   759     }
   760     SDL_free(surface);
   761 #ifdef CHECK_LEAKS
   762     --surfaces_allocated;
   763 #endif
   764 }
   765 
   766 /* vi: set ts=4 sw=4 expandtab: */