src/video/SDL_surface.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 28 May 2006 13:04:16 +0000
branchSDL-1.3
changeset 1662 782fd950bd46
parent 1456 84de7511f79f
child 1666 6e7ec5cb83c3
permissions -rw-r--r--
Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API.

WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid.

The code is now run through a consistent indent format:
indent -i4 -nut -nsc -br -ce

The headers are being converted to automatically generate doxygen documentation.
slouken@0
     1
/*
slouken@0
     2
    SDL - Simple DirectMedia Layer
slouken@1312
     3
    Copyright (C) 1997-2006 Sam Lantinga
slouken@0
     4
slouken@0
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@0
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@0
     9
slouken@0
    10
    This library is distributed in the hope that it will be useful,
slouken@0
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@0
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@0
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@0
    18
slouken@0
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@0
    21
*/
slouken@1402
    22
#include "SDL_config.h"
slouken@0
    23
slouken@0
    24
#include "SDL_video.h"
slouken@0
    25
#include "SDL_sysvideo.h"
slouken@0
    26
#include "SDL_cursor_c.h"
slouken@0
    27
#include "SDL_blit.h"
slouken@0
    28
#include "SDL_RLEaccel_c.h"
slouken@0
    29
#include "SDL_pixels_c.h"
slouken@0
    30
#include "SDL_leaks.h"
slouken@0
    31
icculus@1251
    32
slouken@0
    33
/* Public routines */
slouken@0
    34
/*
slouken@0
    35
 * Create an empty RGB surface of the appropriate depth
slouken@0
    36
 */
slouken@1662
    37
SDL_Surface *
slouken@1662
    38
SDL_CreateRGBSurface (Uint32 flags,
slouken@1662
    39
                      int width, int height, int depth,
slouken@1662
    40
                      Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
slouken@0
    41
{
slouken@1662
    42
    SDL_VideoDevice *_this = SDL_GetVideoDevice ();
slouken@1662
    43
    SDL_Surface *screen;
slouken@1662
    44
    SDL_Surface *surface;
slouken@0
    45
slouken@1662
    46
    /* Make sure the size requested doesn't overflow our datatypes */
slouken@1662
    47
    /* Next time I write a library like SDL, I'll use int for size. :) */
slouken@1662
    48
    if (width >= 16384 || height >= 65536) {
slouken@1662
    49
        SDL_SetError ("Width or height is too large");
slouken@1662
    50
        return (NULL);
slouken@1662
    51
    }
slouken@940
    52
slouken@1662
    53
    /* Check to see if we desire the surface in video memory */
slouken@1662
    54
    if (_this) {
slouken@1662
    55
        screen = SDL_PublicSurface;
slouken@1662
    56
    } else {
slouken@1662
    57
        screen = NULL;
slouken@1662
    58
    }
slouken@1662
    59
    if (screen && ((screen->flags & SDL_HWSURFACE) == SDL_HWSURFACE)) {
slouken@1662
    60
        if ((flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA)) != 0) {
slouken@1662
    61
            flags |= SDL_HWSURFACE;
slouken@1662
    62
        }
slouken@1662
    63
        if ((flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
slouken@1662
    64
            if (!_this->info.blit_hw_CC) {
slouken@1662
    65
                flags &= ~SDL_HWSURFACE;
slouken@1662
    66
            }
slouken@1662
    67
        }
slouken@1662
    68
        if ((flags & SDL_SRCALPHA) == SDL_SRCALPHA) {
slouken@1662
    69
            if (!_this->info.blit_hw_A) {
slouken@1662
    70
                flags &= ~SDL_HWSURFACE;
slouken@1662
    71
            }
slouken@1662
    72
        }
slouken@1662
    73
    } else {
slouken@1662
    74
        flags &= ~SDL_HWSURFACE;
slouken@1662
    75
    }
slouken@0
    76
slouken@1662
    77
    /* Allocate the surface */
slouken@1662
    78
    surface = (SDL_Surface *) SDL_malloc (sizeof (*surface));
slouken@1662
    79
    if (surface == NULL) {
slouken@1662
    80
        SDL_OutOfMemory ();
slouken@1662
    81
        return (NULL);
slouken@1662
    82
    }
slouken@1662
    83
    surface->flags = SDL_SWSURFACE;
slouken@1662
    84
    if ((flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
slouken@1662
    85
        if ((Amask) && (_this->displayformatalphapixel)) {
slouken@1662
    86
            depth = _this->displayformatalphapixel->BitsPerPixel;
slouken@1662
    87
            Rmask = _this->displayformatalphapixel->Rmask;
slouken@1662
    88
            Gmask = _this->displayformatalphapixel->Gmask;
slouken@1662
    89
            Bmask = _this->displayformatalphapixel->Bmask;
slouken@1662
    90
            Amask = _this->displayformatalphapixel->Amask;
slouken@1662
    91
        } else {
slouken@1662
    92
            depth = screen->format->BitsPerPixel;
slouken@1662
    93
            Rmask = screen->format->Rmask;
slouken@1662
    94
            Gmask = screen->format->Gmask;
slouken@1662
    95
            Bmask = screen->format->Bmask;
slouken@1662
    96
            Amask = screen->format->Amask;
slouken@1662
    97
        }
slouken@1662
    98
    }
slouken@1662
    99
    surface->format = SDL_AllocFormat (depth, Rmask, Gmask, Bmask, Amask);
slouken@1662
   100
    if (surface->format == NULL) {
slouken@1662
   101
        SDL_free (surface);
slouken@1662
   102
        return (NULL);
slouken@1662
   103
    }
slouken@1662
   104
    if (Amask) {
slouken@1662
   105
        surface->flags |= SDL_SRCALPHA;
slouken@1662
   106
    }
slouken@1662
   107
    surface->w = width;
slouken@1662
   108
    surface->h = height;
slouken@1662
   109
    surface->pitch = SDL_CalculatePitch (surface);
slouken@1662
   110
    surface->pixels = NULL;
slouken@1662
   111
    surface->offset = 0;
slouken@1662
   112
    surface->hwdata = NULL;
slouken@1662
   113
    surface->locked = 0;
slouken@1662
   114
    surface->map = NULL;
slouken@1662
   115
    surface->unused1 = 0;
slouken@1662
   116
    SDL_SetClipRect (surface, NULL);
slouken@1662
   117
    SDL_FormatChanged (surface);
slouken@0
   118
slouken@1662
   119
    /* Get the pixels */
slouken@1662
   120
    if (((flags & SDL_HWSURFACE) == SDL_SWSURFACE) ||
slouken@1662
   121
        (_this->AllocHWSurface (_this, surface) < 0)) {
slouken@1662
   122
        if (surface->w && surface->h) {
slouken@1662
   123
            surface->pixels = SDL_malloc (surface->h * surface->pitch);
slouken@1662
   124
            if (surface->pixels == NULL) {
slouken@1662
   125
                SDL_FreeSurface (surface);
slouken@1662
   126
                SDL_OutOfMemory ();
slouken@1662
   127
                return (NULL);
slouken@1662
   128
            }
slouken@1662
   129
            /* This is important for bitmaps */
slouken@1662
   130
            SDL_memset (surface->pixels, 0, surface->h * surface->pitch);
slouken@1662
   131
        }
slouken@1662
   132
    }
slouken@0
   133
slouken@1662
   134
    /* Allocate an empty mapping */
slouken@1662
   135
    surface->map = SDL_AllocBlitMap ();
slouken@1662
   136
    if (surface->map == NULL) {
slouken@1662
   137
        SDL_FreeSurface (surface);
slouken@1662
   138
        return (NULL);
slouken@1662
   139
    }
slouken@0
   140
slouken@1662
   141
    /* The surface is ready to go */
slouken@1662
   142
    surface->refcount = 1;
slouken@0
   143
#ifdef CHECK_LEAKS
slouken@1662
   144
    ++surfaces_allocated;
slouken@0
   145
#endif
slouken@1662
   146
    return (surface);
slouken@0
   147
}
slouken@1662
   148
slouken@0
   149
/*
slouken@0
   150
 * Create an RGB surface from an existing memory buffer
slouken@0
   151
 */
slouken@1662
   152
SDL_Surface *
slouken@1662
   153
SDL_CreateRGBSurfaceFrom (void *pixels,
slouken@1662
   154
                          int width, int height, int depth, int pitch,
slouken@1662
   155
                          Uint32 Rmask, Uint32 Gmask, Uint32 Bmask,
slouken@1662
   156
                          Uint32 Amask)
slouken@0
   157
{
slouken@1662
   158
    SDL_Surface *surface;
slouken@0
   159
slouken@1662
   160
    surface = SDL_CreateRGBSurface (SDL_SWSURFACE, 0, 0, depth,
slouken@1662
   161
                                    Rmask, Gmask, Bmask, Amask);
slouken@1662
   162
    if (surface != NULL) {
slouken@1662
   163
        surface->flags |= SDL_PREALLOC;
slouken@1662
   164
        surface->pixels = pixels;
slouken@1662
   165
        surface->w = width;
slouken@1662
   166
        surface->h = height;
slouken@1662
   167
        surface->pitch = pitch;
slouken@1662
   168
        SDL_SetClipRect (surface, NULL);
slouken@1662
   169
    }
slouken@1662
   170
    return (surface);
slouken@0
   171
}
slouken@1662
   172
slouken@0
   173
/*
slouken@0
   174
 * Set the color key in a blittable surface
slouken@0
   175
 */
slouken@1662
   176
int
slouken@1662
   177
SDL_SetColorKey (SDL_Surface * surface, Uint32 flag, Uint32 key)
slouken@0
   178
{
slouken@1662
   179
    /* Sanity check the flag as it gets passed in */
slouken@1662
   180
    if (flag & SDL_SRCCOLORKEY) {
slouken@1662
   181
        if (flag & (SDL_RLEACCEL | SDL_RLEACCELOK)) {
slouken@1662
   182
            flag = (SDL_SRCCOLORKEY | SDL_RLEACCELOK);
slouken@1662
   183
        } else {
slouken@1662
   184
            flag = SDL_SRCCOLORKEY;
slouken@1662
   185
        }
slouken@1662
   186
    } else {
slouken@1662
   187
        flag = 0;
slouken@1662
   188
    }
slouken@0
   189
slouken@1662
   190
    /* Optimize away operations that don't change anything */
slouken@1662
   191
    if ((flag == (surface->flags & (SDL_SRCCOLORKEY | SDL_RLEACCELOK))) &&
slouken@1662
   192
        (key == surface->format->colorkey)) {
slouken@1662
   193
        return (0);
slouken@1662
   194
    }
slouken@0
   195
slouken@1662
   196
    /* UnRLE surfaces before we change the colorkey */
slouken@1662
   197
    if (surface->flags & SDL_RLEACCEL) {
slouken@1662
   198
        SDL_UnRLESurface (surface, 1);
slouken@1662
   199
    }
slouken@0
   200
slouken@1662
   201
    if (flag) {
slouken@1662
   202
        SDL_VideoDevice *_this = SDL_GetVideoDevice ();
slouken@0
   203
slouken@1662
   204
        surface->flags |= SDL_SRCCOLORKEY;
slouken@1662
   205
        surface->format->colorkey = key;
slouken@1662
   206
        if ((surface->flags & SDL_HWACCEL) == SDL_HWACCEL) {
slouken@1662
   207
            if ((_this->SetHWColorKey == NULL) ||
slouken@1662
   208
                (_this->SetHWColorKey (_this, surface, key) < 0)) {
slouken@1662
   209
                surface->flags &= ~SDL_HWACCEL;
slouken@1662
   210
            }
slouken@1662
   211
        }
slouken@1662
   212
        if (flag & SDL_RLEACCELOK) {
slouken@1662
   213
            surface->flags |= SDL_RLEACCELOK;
slouken@1662
   214
        } else {
slouken@1662
   215
            surface->flags &= ~SDL_RLEACCELOK;
slouken@1662
   216
        }
slouken@1662
   217
    } else {
slouken@1662
   218
        surface->flags &= ~(SDL_SRCCOLORKEY | SDL_RLEACCELOK);
slouken@1662
   219
        surface->format->colorkey = 0;
slouken@1662
   220
    }
slouken@1662
   221
    SDL_InvalidateMap (surface->map);
slouken@1662
   222
    return (0);
slouken@1662
   223
}
slouken@0
   224
slouken@1662
   225
/* This function sets the alpha channel of a surface */
slouken@1662
   226
int
slouken@1662
   227
SDL_SetAlpha (SDL_Surface * surface, Uint32 flag, Uint8 value)
slouken@1662
   228
{
slouken@1662
   229
    Uint32 oldflags = surface->flags;
slouken@1662
   230
    Uint32 oldalpha = surface->format->alpha;
slouken@1662
   231
slouken@1662
   232
    /* Sanity check the flag as it gets passed in */
slouken@1662
   233
    if (flag & SDL_SRCALPHA) {
slouken@1662
   234
        if (flag & (SDL_RLEACCEL | SDL_RLEACCELOK)) {
slouken@1662
   235
            flag = (SDL_SRCALPHA | SDL_RLEACCELOK);
slouken@1662
   236
        } else {
slouken@1662
   237
            flag = SDL_SRCALPHA;
slouken@1662
   238
        }
slouken@1662
   239
    } else {
slouken@1662
   240
        flag = 0;
slouken@1662
   241
    }
slouken@1662
   242
slouken@1662
   243
    /* Optimize away operations that don't change anything */
slouken@1662
   244
    if ((flag == (surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK))) &&
slouken@1662
   245
        (!flag || value == oldalpha)) {
slouken@1662
   246
        return (0);
slouken@1662
   247
    }
slouken@1662
   248
slouken@1662
   249
    if (!(flag & SDL_RLEACCELOK) && (surface->flags & SDL_RLEACCEL))
slouken@1662
   250
        SDL_UnRLESurface (surface, 1);
slouken@1662
   251
slouken@1662
   252
    if (flag) {
slouken@1662
   253
        SDL_VideoDevice *_this = SDL_GetVideoDevice ();
slouken@1662
   254
slouken@1662
   255
        surface->flags |= SDL_SRCALPHA;
slouken@1662
   256
        surface->format->alpha = value;
slouken@1662
   257
        if ((surface->flags & SDL_HWACCEL) == SDL_HWACCEL) {
slouken@1662
   258
            if ((_this->SetHWAlpha == NULL) ||
slouken@1662
   259
                (_this->SetHWAlpha (_this, surface, value) < 0)) {
slouken@1662
   260
                surface->flags &= ~SDL_HWACCEL;
slouken@1662
   261
            }
slouken@1662
   262
        }
slouken@1662
   263
        if (flag & SDL_RLEACCELOK) {
slouken@1662
   264
            surface->flags |= SDL_RLEACCELOK;
slouken@1662
   265
        } else {
slouken@1662
   266
            surface->flags &= ~SDL_RLEACCELOK;
slouken@1662
   267
        }
slouken@1662
   268
    } else {
slouken@1662
   269
        surface->flags &= ~SDL_SRCALPHA;
slouken@1662
   270
        surface->format->alpha = SDL_ALPHA_OPAQUE;
slouken@1662
   271
    }
slouken@1662
   272
    /*
slouken@1662
   273
     * The representation for software surfaces is independent of
slouken@1662
   274
     * per-surface alpha, so no need to invalidate the blit mapping
slouken@1662
   275
     * if just the alpha value was changed. (If either is 255, we still
slouken@1662
   276
     * need to invalidate.)
slouken@1662
   277
     */
slouken@1662
   278
    if ((surface->flags & SDL_HWACCEL) == SDL_HWACCEL
slouken@1662
   279
        || oldflags != surface->flags
slouken@1662
   280
        || (((oldalpha + 1) ^ (value + 1)) & 0x100))
slouken@1662
   281
        SDL_InvalidateMap (surface->map);
slouken@1662
   282
    return (0);
slouken@0
   283
}
slouken@1662
   284
slouken@1662
   285
int
slouken@1662
   286
SDL_SetAlphaChannel (SDL_Surface * surface, Uint8 value)
slouken@0
   287
{
slouken@1662
   288
    int row, col;
slouken@1662
   289
    int offset;
slouken@1662
   290
    Uint8 *buf;
slouken@0
   291
slouken@1662
   292
    if ((surface->format->Amask != 0xFF000000) &&
slouken@1662
   293
        (surface->format->Amask != 0x000000FF)) {
slouken@1662
   294
        SDL_SetError ("Unsupported surface alpha mask format");
slouken@1662
   295
        return -1;
slouken@1662
   296
    }
slouken@431
   297
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
slouken@1662
   298
    if (surface->format->Amask == 0xFF000000) {
slouken@1662
   299
        offset = 3;
slouken@1662
   300
    } else {
slouken@1662
   301
        offset = 0;
slouken@1662
   302
    }
slouken@431
   303
#else
slouken@1662
   304
    if (surface->format->Amask == 0xFF000000) {
slouken@1662
   305
        offset = 0;
slouken@1662
   306
    } else {
slouken@1662
   307
        offset = 3;
slouken@1662
   308
    }
slouken@431
   309
#endif /* Byte ordering */
slouken@431
   310
slouken@1662
   311
    /* Quickly set the alpha channel of an RGBA or ARGB surface */
slouken@1662
   312
    if (SDL_MUSTLOCK (surface)) {
slouken@1662
   313
        if (SDL_LockSurface (surface) < 0) {
slouken@1662
   314
            return -1;
slouken@1662
   315
        }
slouken@1662
   316
    }
slouken@1662
   317
    row = surface->h;
slouken@1662
   318
    while (row--) {
slouken@1662
   319
        col = surface->w;
slouken@1662
   320
        buf = (Uint8 *) surface->pixels + row * surface->pitch + offset;
slouken@1662
   321
        while (col--) {
slouken@1662
   322
            *buf = value;
slouken@1662
   323
            buf += 4;
slouken@1662
   324
        }
slouken@1662
   325
    }
slouken@1662
   326
    if (SDL_MUSTLOCK (surface)) {
slouken@1662
   327
        SDL_UnlockSurface (surface);
slouken@1662
   328
    }
slouken@1662
   329
    return 0;
slouken@431
   330
}
slouken@0
   331
slouken@0
   332
/*
slouken@0
   333
 * A function to calculate the intersection of two rectangles:
slouken@0
   334
 * return true if the rectangles intersect, false otherwise
slouken@0
   335
 */
slouken@1662
   336
static __inline__ SDL_bool
slouken@1662
   337
SDL_IntersectRect (const SDL_Rect * A, const SDL_Rect * B,
slouken@1662
   338
                   SDL_Rect * intersection)
slouken@0
   339
{
slouken@1662
   340
    int Amin, Amax, Bmin, Bmax;
slouken@0
   341
slouken@1662
   342
    /* Horizontal intersection */
slouken@1662
   343
    Amin = A->x;
slouken@1662
   344
    Amax = Amin + A->w;
slouken@1662
   345
    Bmin = B->x;
slouken@1662
   346
    Bmax = Bmin + B->w;
slouken@1662
   347
    if (Bmin > Amin)
slouken@1662
   348
        Amin = Bmin;
slouken@1662
   349
    intersection->x = Amin;
slouken@1662
   350
    if (Bmax < Amax)
slouken@1662
   351
        Amax = Bmax;
slouken@1662
   352
    intersection->w = Amax - Amin > 0 ? Amax - Amin : 0;
slouken@0
   353
slouken@1662
   354
    /* Vertical intersection */
slouken@1662
   355
    Amin = A->y;
slouken@1662
   356
    Amax = Amin + A->h;
slouken@1662
   357
    Bmin = B->y;
slouken@1662
   358
    Bmax = Bmin + B->h;
slouken@1662
   359
    if (Bmin > Amin)
slouken@1662
   360
        Amin = Bmin;
slouken@1662
   361
    intersection->y = Amin;
slouken@1662
   362
    if (Bmax < Amax)
slouken@1662
   363
        Amax = Bmax;
slouken@1662
   364
    intersection->h = Amax - Amin > 0 ? Amax - Amin : 0;
slouken@0
   365
slouken@1662
   366
    return (intersection->w && intersection->h);
slouken@0
   367
}
slouken@1662
   368
slouken@0
   369
/*
slouken@0
   370
 * Set the clipping rectangle for a blittable surface
slouken@0
   371
 */
slouken@1662
   372
SDL_bool
slouken@1662
   373
SDL_SetClipRect (SDL_Surface * surface, const SDL_Rect * rect)
slouken@0
   374
{
slouken@1662
   375
    SDL_Rect full_rect;
slouken@0
   376
slouken@1662
   377
    /* Don't do anything if there's no surface to act on */
slouken@1662
   378
    if (!surface) {
slouken@1662
   379
        return SDL_FALSE;
slouken@1662
   380
    }
slouken@0
   381
slouken@1662
   382
    /* Set up the full surface rectangle */
slouken@1662
   383
    full_rect.x = 0;
slouken@1662
   384
    full_rect.y = 0;
slouken@1662
   385
    full_rect.w = surface->w;
slouken@1662
   386
    full_rect.h = surface->h;
slouken@0
   387
slouken@1662
   388
    /* Set the clipping rectangle */
slouken@1662
   389
    if (!rect) {
slouken@1662
   390
        surface->clip_rect = full_rect;
slouken@1662
   391
        return 1;
slouken@1662
   392
    }
slouken@1662
   393
    return SDL_IntersectRect (rect, &full_rect, &surface->clip_rect);
slouken@0
   394
}
slouken@1662
   395
slouken@1662
   396
void
slouken@1662
   397
SDL_GetClipRect (SDL_Surface * surface, SDL_Rect * rect)
slouken@0
   398
{
slouken@1662
   399
    if (surface && rect) {
slouken@1662
   400
        *rect = surface->clip_rect;
slouken@1662
   401
    }
slouken@0
   402
}
slouken@1662
   403
slouken@0
   404
/* 
slouken@0
   405
 * Set up a blit between two surfaces -- split into three parts:
slouken@0
   406
 * The upper part, SDL_UpperBlit(), performs clipping and rectangle 
slouken@0
   407
 * verification.  The lower part is a pointer to a low level
slouken@0
   408
 * accelerated blitting function.
slouken@0
   409
 *
slouken@0
   410
 * These parts are separated out and each used internally by this 
slouken@0
   411
 * library in the optimimum places.  They are exported so that if
slouken@0
   412
 * you know exactly what you are doing, you can optimize your code
slouken@0
   413
 * by calling the one(s) you need.
slouken@0
   414
 */
slouken@1662
   415
int
slouken@1662
   416
SDL_LowerBlit (SDL_Surface * src, SDL_Rect * srcrect,
slouken@1662
   417
               SDL_Surface * dst, SDL_Rect * dstrect)
slouken@0
   418
{
slouken@1662
   419
    SDL_blit do_blit;
slouken@0
   420
slouken@1662
   421
    /* Check to make sure the blit mapping is valid */
slouken@1662
   422
    if ((src->map->dst != dst) ||
slouken@1662
   423
        (src->map->dst->format_version != src->map->format_version)) {
slouken@1662
   424
        if (SDL_MapSurface (src, dst) < 0) {
slouken@1662
   425
            return (-1);
slouken@1662
   426
        }
slouken@1662
   427
    }
slouken@0
   428
slouken@1662
   429
    /* Figure out which blitter to use */
slouken@1662
   430
    if ((src->flags & SDL_HWACCEL) == SDL_HWACCEL) {
slouken@1662
   431
        do_blit = src->map->hw_blit;
slouken@1662
   432
    } else {
slouken@1662
   433
        do_blit = src->map->sw_blit;
slouken@1662
   434
    }
slouken@1662
   435
    return (do_blit (src, srcrect, dst, dstrect));
slouken@0
   436
}
slouken@0
   437
slouken@0
   438
slouken@1662
   439
int
slouken@1662
   440
SDL_UpperBlit (SDL_Surface * src, SDL_Rect * srcrect,
slouken@1662
   441
               SDL_Surface * dst, SDL_Rect * dstrect)
slouken@0
   442
{
slouken@1662
   443
    SDL_Rect fulldst;
slouken@1662
   444
    int srcx, srcy, w, h;
slouken@0
   445
slouken@1662
   446
    /* Make sure the surfaces aren't locked */
slouken@1662
   447
    if (!src || !dst) {
slouken@1662
   448
        SDL_SetError ("SDL_UpperBlit: passed a NULL surface");
slouken@1662
   449
        return (-1);
slouken@1662
   450
    }
slouken@1662
   451
    if (src->locked || dst->locked) {
slouken@1662
   452
        SDL_SetError ("Surfaces must not be locked during blit");
slouken@1662
   453
        return (-1);
slouken@1662
   454
    }
slouken@0
   455
slouken@1662
   456
    /* If the destination rectangle is NULL, use the entire dest surface */
slouken@1662
   457
    if (dstrect == NULL) {
slouken@1662
   458
        fulldst.x = fulldst.y = 0;
slouken@1662
   459
        dstrect = &fulldst;
slouken@1662
   460
    }
slouken@0
   461
slouken@1662
   462
    /* clip the source rectangle to the source surface */
slouken@1662
   463
    if (srcrect) {
slouken@1662
   464
        int maxw, maxh;
slouken@0
   465
slouken@1662
   466
        srcx = srcrect->x;
slouken@1662
   467
        w = srcrect->w;
slouken@1662
   468
        if (srcx < 0) {
slouken@1662
   469
            w += srcx;
slouken@1662
   470
            dstrect->x -= srcx;
slouken@1662
   471
            srcx = 0;
slouken@1662
   472
        }
slouken@1662
   473
        maxw = src->w - srcx;
slouken@1662
   474
        if (maxw < w)
slouken@1662
   475
            w = maxw;
slouken@0
   476
slouken@1662
   477
        srcy = srcrect->y;
slouken@1662
   478
        h = srcrect->h;
slouken@1662
   479
        if (srcy < 0) {
slouken@1662
   480
            h += srcy;
slouken@1662
   481
            dstrect->y -= srcy;
slouken@1662
   482
            srcy = 0;
slouken@1662
   483
        }
slouken@1662
   484
        maxh = src->h - srcy;
slouken@1662
   485
        if (maxh < h)
slouken@1662
   486
            h = maxh;
slouken@0
   487
slouken@1662
   488
    } else {
slouken@1662
   489
        srcx = srcy = 0;
slouken@1662
   490
        w = src->w;
slouken@1662
   491
        h = src->h;
slouken@1662
   492
    }
slouken@0
   493
slouken@1662
   494
    /* clip the destination rectangle against the clip rectangle */
slouken@1662
   495
    {
slouken@1662
   496
        SDL_Rect *clip = &dst->clip_rect;
slouken@1662
   497
        int dx, dy;
slouken@0
   498
slouken@1662
   499
        dx = clip->x - dstrect->x;
slouken@1662
   500
        if (dx > 0) {
slouken@1662
   501
            w -= dx;
slouken@1662
   502
            dstrect->x += dx;
slouken@1662
   503
            srcx += dx;
slouken@1662
   504
        }
slouken@1662
   505
        dx = dstrect->x + w - clip->x - clip->w;
slouken@1662
   506
        if (dx > 0)
slouken@1662
   507
            w -= dx;
slouken@1662
   508
slouken@1662
   509
        dy = clip->y - dstrect->y;
slouken@1662
   510
        if (dy > 0) {
slouken@1662
   511
            h -= dy;
slouken@1662
   512
            dstrect->y += dy;
slouken@1662
   513
            srcy += dy;
slouken@1662
   514
        }
slouken@1662
   515
        dy = dstrect->y + h - clip->y - clip->h;
slouken@1662
   516
        if (dy > 0)
slouken@1662
   517
            h -= dy;
slouken@1662
   518
    }
slouken@1662
   519
slouken@1662
   520
    if (w > 0 && h > 0) {
slouken@1662
   521
        SDL_Rect sr;
slouken@1662
   522
        sr.x = srcx;
slouken@1662
   523
        sr.y = srcy;
slouken@1662
   524
        sr.w = dstrect->w = w;
slouken@1662
   525
        sr.h = dstrect->h = h;
slouken@1662
   526
        return SDL_LowerBlit (src, &sr, dst, dstrect);
slouken@1662
   527
    }
slouken@1662
   528
    dstrect->w = dstrect->h = 0;
slouken@1662
   529
    return 0;
slouken@0
   530
}
slouken@0
   531
slouken@1662
   532
static int
slouken@1662
   533
SDL_FillRect1 (SDL_Surface * dst, SDL_Rect * dstrect, Uint32 color)
slouken@532
   534
{
slouken@1662
   535
    /* FIXME: We have to worry about packing order.. *sigh* */
slouken@1662
   536
    SDL_SetError ("1-bpp rect fill not yet implemented");
slouken@1662
   537
    return -1;
slouken@532
   538
}
slouken@532
   539
slouken@1662
   540
static int
slouken@1662
   541
SDL_FillRect4 (SDL_Surface * dst, SDL_Rect * dstrect, Uint32 color)
slouken@532
   542
{
slouken@1662
   543
    /* FIXME: We have to worry about packing order.. *sigh* */
slouken@1662
   544
    SDL_SetError ("4-bpp rect fill not yet implemented");
slouken@1662
   545
    return -1;
slouken@532
   546
}
slouken@532
   547
slouken@0
   548
/* 
slouken@0
   549
 * This function performs a fast fill of the given rectangle with 'color'
slouken@0
   550
 */
slouken@1662
   551
int
slouken@1662
   552
SDL_FillRect (SDL_Surface * dst, SDL_Rect * dstrect, Uint32 color)
slouken@0
   553
{
slouken@1662
   554
    SDL_VideoDevice *_this = SDL_GetVideoDevice ();
slouken@1662
   555
    int x, y;
slouken@1662
   556
    Uint8 *row;
slouken@0
   557
slouken@1662
   558
    /* This function doesn't work on surfaces < 8 bpp */
slouken@1662
   559
    if (dst->format->BitsPerPixel < 8) {
slouken@1662
   560
        switch (dst->format->BitsPerPixel) {
slouken@1662
   561
        case 1:
slouken@1662
   562
            return SDL_FillRect1 (dst, dstrect, color);
slouken@1662
   563
            break;
slouken@1662
   564
        case 4:
slouken@1662
   565
            return SDL_FillRect4 (dst, dstrect, color);
slouken@1662
   566
            break;
slouken@1662
   567
        default:
slouken@1662
   568
            SDL_SetError ("Fill rect on unsupported surface format");
slouken@1662
   569
            return (-1);
slouken@1662
   570
            break;
slouken@1662
   571
        }
slouken@1662
   572
    }
slouken@532
   573
slouken@1662
   574
    /* If 'dstrect' == NULL, then fill the whole surface */
slouken@1662
   575
    if (dstrect) {
slouken@1662
   576
        /* Perform clipping */
slouken@1662
   577
        if (!SDL_IntersectRect (dstrect, &dst->clip_rect, dstrect)) {
slouken@1662
   578
            return (0);
slouken@1662
   579
        }
slouken@1662
   580
    } else {
slouken@1662
   581
        dstrect = &dst->clip_rect;
slouken@1662
   582
    }
slouken@0
   583
slouken@1662
   584
    /* Check for hardware acceleration */
slouken@1662
   585
    if (((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) &&
slouken@1662
   586
        _this->info.blit_fill) {
slouken@1662
   587
        return (_this->FillHWRect (_this, dst, dstrect, color));
slouken@1662
   588
    }
slouken@0
   589
slouken@1662
   590
    /* Perform software fill */
slouken@1662
   591
    if (SDL_LockSurface (dst) != 0) {
slouken@1662
   592
        return (-1);
slouken@1662
   593
    }
slouken@1662
   594
    row = (Uint8 *) dst->pixels + dstrect->y * dst->pitch +
slouken@1662
   595
        dstrect->x * dst->format->BytesPerPixel;
slouken@1662
   596
    if (dst->format->palette || (color == 0)) {
slouken@1662
   597
        x = dstrect->w * dst->format->BytesPerPixel;
slouken@1662
   598
        if (!color && !((uintptr_t) row & 3) && !(x & 3)
slouken@1662
   599
            && !(dst->pitch & 3)) {
slouken@1662
   600
            int n = x >> 2;
slouken@1662
   601
            for (y = dstrect->h; y; --y) {
slouken@1662
   602
                SDL_memset4 (row, 0, n);
slouken@1662
   603
                row += dst->pitch;
slouken@1662
   604
            }
slouken@1662
   605
        } else {
slouken@0
   606
#ifdef __powerpc__
slouken@1662
   607
            /*
slouken@1662
   608
             * SDL_memset() on PPC (both glibc and codewarrior) uses
slouken@1662
   609
             * the dcbz (Data Cache Block Zero) instruction, which
slouken@1662
   610
             * causes an alignment exception if the destination is
slouken@1662
   611
             * uncachable, so only use it on software surfaces
slouken@1662
   612
             */
slouken@1662
   613
            if ((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
slouken@1662
   614
                if (dstrect->w >= 8) {
slouken@1662
   615
                    /*
slouken@1662
   616
                     * 64-bit stores are probably most
slouken@1662
   617
                     * efficient to uncached video memory
slouken@1662
   618
                     */
slouken@1662
   619
                    double fill;
slouken@1662
   620
                    SDL_memset (&fill, color, (sizeof fill));
slouken@1662
   621
                    for (y = dstrect->h; y; y--) {
slouken@1662
   622
                        Uint8 *d = row;
slouken@1662
   623
                        unsigned n = x;
slouken@1662
   624
                        unsigned nn;
slouken@1662
   625
                        Uint8 c = color;
slouken@1662
   626
                        double f = fill;
slouken@1662
   627
                        while ((unsigned long) d & (sizeof (double) - 1)) {
slouken@1662
   628
                            *d++ = c;
slouken@1662
   629
                            n--;
slouken@1662
   630
                        }
slouken@1662
   631
                        nn = n / (sizeof (double) * 4);
slouken@1662
   632
                        while (nn) {
slouken@1662
   633
                            ((double *) d)[0] = f;
slouken@1662
   634
                            ((double *) d)[1] = f;
slouken@1662
   635
                            ((double *) d)[2] = f;
slouken@1662
   636
                            ((double *) d)[3] = f;
slouken@1662
   637
                            d += 4 * sizeof (double);
slouken@1662
   638
                            nn--;
slouken@1662
   639
                        }
slouken@1662
   640
                        n &= ~(sizeof (double) * 4 - 1);
slouken@1662
   641
                        nn = n / sizeof (double);
slouken@1662
   642
                        while (nn) {
slouken@1662
   643
                            *(double *) d = f;
slouken@1662
   644
                            d += sizeof (double);
slouken@1662
   645
                            nn--;
slouken@1662
   646
                        }
slouken@1662
   647
                        n &= ~(sizeof (double) - 1);
slouken@1662
   648
                        while (n) {
slouken@1662
   649
                            *d++ = c;
slouken@1662
   650
                            n--;
slouken@1662
   651
                        }
slouken@1662
   652
                        row += dst->pitch;
slouken@1662
   653
                    }
slouken@1662
   654
                } else {
slouken@1662
   655
                    /* narrow boxes */
slouken@1662
   656
                    for (y = dstrect->h; y; y--) {
slouken@1662
   657
                        Uint8 *d = row;
slouken@1662
   658
                        Uint8 c = color;
slouken@1662
   659
                        int n = x;
slouken@1662
   660
                        while (n) {
slouken@1662
   661
                            *d++ = c;
slouken@1662
   662
                            n--;
slouken@1662
   663
                        }
slouken@1662
   664
                        row += dst->pitch;
slouken@1662
   665
                    }
slouken@1662
   666
                }
slouken@1662
   667
            } else
slouken@0
   668
#endif /* __powerpc__ */
slouken@1662
   669
            {
slouken@1662
   670
                for (y = dstrect->h; y; y--) {
slouken@1662
   671
                    SDL_memset (row, color, x);
slouken@1662
   672
                    row += dst->pitch;
slouken@1662
   673
                }
slouken@1662
   674
            }
slouken@1662
   675
        }
slouken@1662
   676
    } else {
slouken@1662
   677
        switch (dst->format->BytesPerPixel) {
slouken@1662
   678
        case 2:
slouken@1662
   679
            for (y = dstrect->h; y; --y) {
slouken@1662
   680
                Uint16 *pixels = (Uint16 *) row;
slouken@1662
   681
                Uint16 c = (Uint16) color;
slouken@1662
   682
                Uint32 cc = (Uint32) c << 16 | c;
slouken@1662
   683
                int n = dstrect->w;
slouken@1662
   684
                if ((uintptr_t) pixels & 3) {
slouken@1662
   685
                    *pixels++ = c;
slouken@1662
   686
                    n--;
slouken@1662
   687
                }
slouken@1662
   688
                if (n >> 1)
slouken@1662
   689
                    SDL_memset4 (pixels, cc, n >> 1);
slouken@1662
   690
                if (n & 1)
slouken@1662
   691
                    pixels[n - 1] = c;
slouken@1662
   692
                row += dst->pitch;
slouken@1662
   693
            }
slouken@1662
   694
            break;
slouken@0
   695
slouken@1662
   696
        case 3:
slouken@1662
   697
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
slouken@1662
   698
            color <<= 8;
slouken@1662
   699
#endif
slouken@1662
   700
            for (y = dstrect->h; y; --y) {
slouken@1662
   701
                Uint8 *pixels = row;
slouken@1662
   702
                for (x = dstrect->w; x; --x) {
slouken@1662
   703
                    SDL_memcpy (pixels, &color, 3);
slouken@1662
   704
                    pixels += 3;
slouken@1662
   705
                }
slouken@1662
   706
                row += dst->pitch;
slouken@1662
   707
            }
slouken@1662
   708
            break;
slouken@0
   709
slouken@1662
   710
        case 4:
slouken@1662
   711
            for (y = dstrect->h; y; --y) {
slouken@1662
   712
                SDL_memset4 (row, color, dstrect->w);
slouken@1662
   713
                row += dst->pitch;
slouken@1662
   714
            }
slouken@1662
   715
            break;
slouken@1662
   716
        }
slouken@1662
   717
    }
slouken@1662
   718
    SDL_UnlockSurface (dst);
slouken@0
   719
slouken@1662
   720
    /* We're done! */
slouken@1662
   721
    return (0);
slouken@0
   722
}
slouken@0
   723
slouken@0
   724
/*
slouken@0
   725
 * Lock a surface to directly access the pixels
slouken@0
   726
 */
slouken@1662
   727
int
slouken@1662
   728
SDL_LockSurface (SDL_Surface * surface)
slouken@0
   729
{
slouken@1662
   730
    if (!surface->locked) {
slouken@1662
   731
        /* Perform the lock */
slouken@1662
   732
        if (surface->flags & SDL_HWSURFACE) {
slouken@1662
   733
            SDL_VideoDevice *_this = SDL_GetVideoDevice ();
slouken@1662
   734
            if (_this->LockHWSurface (_this, surface) < 0) {
slouken@1662
   735
                return (-1);
slouken@1662
   736
            }
slouken@1662
   737
        }
slouken@1662
   738
        if (surface->flags & SDL_RLEACCEL) {
slouken@1662
   739
            SDL_UnRLESurface (surface, 1);
slouken@1662
   740
            surface->flags |= SDL_RLEACCEL;     /* save accel'd state */
slouken@1662
   741
        }
slouken@1662
   742
        /* This needs to be done here in case pixels changes value */
slouken@1662
   743
        surface->pixels = (Uint8 *) surface->pixels + surface->offset;
slouken@1662
   744
    }
slouken@0
   745
slouken@1662
   746
    /* Increment the surface lock count, for recursive locks */
slouken@1662
   747
    ++surface->locked;
slouken@0
   748
slouken@1662
   749
    /* Ready to go.. */
slouken@1662
   750
    return (0);
slouken@0
   751
}
slouken@1662
   752
slouken@0
   753
/*
slouken@0
   754
 * Unlock a previously locked surface
slouken@0
   755
 */
slouken@1662
   756
void
slouken@1662
   757
SDL_UnlockSurface (SDL_Surface * surface)
slouken@0
   758
{
slouken@1662
   759
    /* Only perform an unlock if we are locked */
slouken@1662
   760
    if (!surface->locked || (--surface->locked > 0)) {
slouken@1662
   761
        return;
slouken@1662
   762
    }
slouken@0
   763
slouken@1662
   764
    /* Perform the unlock */
slouken@1662
   765
    surface->pixels = (Uint8 *) surface->pixels - surface->offset;
slouken@0
   766
slouken@1662
   767
    /* Unlock hardware or accelerated surfaces */
slouken@1662
   768
    if (surface->flags & SDL_HWSURFACE) {
slouken@1662
   769
        SDL_VideoDevice *_this = SDL_GetVideoDevice ();
slouken@1662
   770
        _this->UnlockHWSurface (_this, surface);
slouken@1662
   771
    } else {
slouken@1662
   772
        /* Update RLE encoded surface with new data */
slouken@1662
   773
        if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
slouken@1662
   774
            surface->flags &= ~SDL_RLEACCEL;    /* stop lying */
slouken@1662
   775
            SDL_RLESurface (surface);
slouken@1662
   776
        }
slouken@1662
   777
    }
slouken@0
   778
}
slouken@0
   779
slouken@0
   780
/* 
slouken@0
   781
 * Convert a surface into the specified pixel format.
slouken@0
   782
 */
slouken@1662
   783
SDL_Surface *
slouken@1662
   784
SDL_ConvertSurface (SDL_Surface * surface,
slouken@1662
   785
                    SDL_PixelFormat * format, Uint32 flags)
slouken@0
   786
{
slouken@1662
   787
    SDL_Surface *convert;
slouken@1662
   788
    Uint32 colorkey = 0;
slouken@1662
   789
    Uint8 alpha = 0;
slouken@1662
   790
    Uint32 surface_flags;
slouken@1662
   791
    SDL_Rect bounds;
slouken@0
   792
slouken@1662
   793
    /* Check for empty destination palette! (results in empty image) */
slouken@1662
   794
    if (format->palette != NULL) {
slouken@1662
   795
        int i;
slouken@1662
   796
        for (i = 0; i < format->palette->ncolors; ++i) {
slouken@1662
   797
            if ((format->palette->colors[i].r != 0) ||
slouken@1662
   798
                (format->palette->colors[i].g != 0) ||
slouken@1662
   799
                (format->palette->colors[i].b != 0))
slouken@1662
   800
                break;
slouken@1662
   801
        }
slouken@1662
   802
        if (i == format->palette->ncolors) {
slouken@1662
   803
            SDL_SetError ("Empty destination palette");
slouken@1662
   804
            return (NULL);
slouken@1662
   805
        }
slouken@1662
   806
    }
slouken@0
   807
slouken@1662
   808
    /* Only create hw surfaces with alpha channel if hw alpha blits
slouken@1662
   809
       are supported */
slouken@1662
   810
    if (format->Amask != 0 && (flags & SDL_HWSURFACE)) {
slouken@1662
   811
        const SDL_VideoInfo *vi = SDL_GetVideoInfo ();
slouken@1662
   812
        if (!vi || !vi->blit_hw_A)
slouken@1662
   813
            flags &= ~SDL_HWSURFACE;
slouken@1662
   814
    }
slouken@264
   815
slouken@1662
   816
    /* Create a new surface with the desired format */
slouken@1662
   817
    convert = SDL_CreateRGBSurface (flags,
slouken@1662
   818
                                    surface->w, surface->h,
slouken@1662
   819
                                    format->BitsPerPixel, format->Rmask,
slouken@1662
   820
                                    format->Gmask, format->Bmask,
slouken@1662
   821
                                    format->Amask);
slouken@1662
   822
    if (convert == NULL) {
slouken@1662
   823
        return (NULL);
slouken@1662
   824
    }
slouken@0
   825
slouken@1662
   826
    /* Copy the palette if any */
slouken@1662
   827
    if (format->palette && convert->format->palette) {
slouken@1662
   828
        SDL_memcpy (convert->format->palette->colors,
slouken@1662
   829
                    format->palette->colors,
slouken@1662
   830
                    format->palette->ncolors * sizeof (SDL_Color));
slouken@1662
   831
        convert->format->palette->ncolors = format->palette->ncolors;
slouken@1662
   832
    }
slouken@0
   833
slouken@1662
   834
    /* Save the original surface color key and alpha */
slouken@1662
   835
    surface_flags = surface->flags;
slouken@1662
   836
    if ((surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
slouken@1662
   837
        /* Convert colourkeyed surfaces to RGBA if requested */
slouken@1662
   838
        if ((flags & SDL_SRCCOLORKEY) != SDL_SRCCOLORKEY && format->Amask) {
slouken@1662
   839
            surface_flags &= ~SDL_SRCCOLORKEY;
slouken@1662
   840
        } else {
slouken@1662
   841
            colorkey = surface->format->colorkey;
slouken@1662
   842
            SDL_SetColorKey (surface, 0, 0);
slouken@1662
   843
        }
slouken@1662
   844
    }
slouken@1662
   845
    if ((surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA) {
slouken@1662
   846
        /* Copy over the alpha channel to RGBA if requested */
slouken@1662
   847
        if (format->Amask) {
slouken@1662
   848
            surface->flags &= ~SDL_SRCALPHA;
slouken@1662
   849
        } else {
slouken@1662
   850
            alpha = surface->format->alpha;
slouken@1662
   851
            SDL_SetAlpha (surface, 0, 0);
slouken@1662
   852
        }
slouken@1662
   853
    }
slouken@0
   854
slouken@1662
   855
    /* Copy over the image data */
slouken@1662
   856
    bounds.x = 0;
slouken@1662
   857
    bounds.y = 0;
slouken@1662
   858
    bounds.w = surface->w;
slouken@1662
   859
    bounds.h = surface->h;
slouken@1662
   860
    SDL_LowerBlit (surface, &bounds, convert, &bounds);
slouken@0
   861
slouken@1662
   862
    /* Clean up the original surface, and update converted surface */
slouken@1662
   863
    if (convert != NULL) {
slouken@1662
   864
        SDL_SetClipRect (convert, &surface->clip_rect);
slouken@1662
   865
    }
slouken@1662
   866
    if ((surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
slouken@1662
   867
        Uint32 cflags = surface_flags & (SDL_SRCCOLORKEY | SDL_RLEACCELOK);
slouken@1662
   868
        if (convert != NULL) {
slouken@1662
   869
            Uint8 keyR, keyG, keyB;
slouken@0
   870
slouken@1662
   871
            SDL_GetRGB (colorkey, surface->format, &keyR, &keyG, &keyB);
slouken@1662
   872
            SDL_SetColorKey (convert, cflags | (flags & SDL_RLEACCELOK),
slouken@1662
   873
                             SDL_MapRGB (convert->format, keyR, keyG, keyB));
slouken@1662
   874
        }
slouken@1662
   875
        SDL_SetColorKey (surface, cflags, colorkey);
slouken@1662
   876
    }
slouken@1662
   877
    if ((surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA) {
slouken@1662
   878
        Uint32 aflags = surface_flags & (SDL_SRCALPHA | SDL_RLEACCELOK);
slouken@1662
   879
        if (convert != NULL) {
slouken@1662
   880
            SDL_SetAlpha (convert, aflags | (flags & SDL_RLEACCELOK), alpha);
slouken@1662
   881
        }
slouken@1662
   882
        if (format->Amask) {
slouken@1662
   883
            surface->flags |= SDL_SRCALPHA;
slouken@1662
   884
        } else {
slouken@1662
   885
            SDL_SetAlpha (surface, aflags, alpha);
slouken@1662
   886
        }
slouken@1662
   887
    }
slouken@0
   888
slouken@1662
   889
    /* We're ready to go! */
slouken@1662
   890
    return (convert);
slouken@0
   891
}
slouken@0
   892
slouken@0
   893
/*
slouken@0
   894
 * Free a surface created by the above function.
slouken@0
   895
 */
slouken@1662
   896
void
slouken@1662
   897
SDL_FreeSurface (SDL_Surface * surface)
slouken@0
   898
{
slouken@1662
   899
    SDL_VideoDevice *_this = SDL_GetVideoDevice ();
slouken@1662
   900
slouken@1662
   901
    /* Free anything that's not NULL, and not the screen surface */
slouken@1662
   902
    if ((surface == NULL) ||
slouken@1662
   903
        (_this &&
slouken@1662
   904
         ((surface == SDL_ShadowSurface) || (surface == SDL_VideoSurface)))) {
slouken@1662
   905
        return;
slouken@1662
   906
    }
slouken@1662
   907
    if (--surface->refcount > 0) {
slouken@1662
   908
        return;
slouken@1662
   909
    }
slouken@1662
   910
    while (surface->locked > 0) {
slouken@1662
   911
        SDL_UnlockSurface (surface);
slouken@1662
   912
    }
slouken@1662
   913
    if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
slouken@1662
   914
        SDL_UnRLESurface (surface, 0);
slouken@1662
   915
    }
slouken@1662
   916
    if (surface->format) {
slouken@1662
   917
        SDL_FreeFormat (surface->format);
slouken@1662
   918
        surface->format = NULL;
slouken@1662
   919
    }
slouken@1662
   920
    if (surface->map != NULL) {
slouken@1662
   921
        SDL_FreeBlitMap (surface->map);
slouken@1662
   922
        surface->map = NULL;
slouken@1662
   923
    }
slouken@1662
   924
    if (surface->hwdata) {
slouken@1662
   925
        SDL_VideoDevice *_this = SDL_GetVideoDevice ();
slouken@1662
   926
        _this->FreeHWSurface (_this, surface);
slouken@1662
   927
    }
slouken@1662
   928
    if (surface->pixels && ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC)) {
slouken@1662
   929
        SDL_free (surface->pixels);
slouken@1662
   930
    }
slouken@1662
   931
    SDL_free (surface);
slouken@0
   932
#ifdef CHECK_LEAKS
slouken@1662
   933
    --surfaces_allocated;
slouken@0
   934
#endif
slouken@0
   935
}
slouken@1662
   936
slouken@1662
   937
/* vi: set ts=4 sw=4 expandtab: */