Okay, still some bugs, but everything builds again...
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2006 Sam Lantinga
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.
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.
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
22 #include "SDL_config.h"
24 #include "SDL_video.h"
25 #include "SDL_compat.h"
26 #include "SDL_sysvideo.h"
28 #include "SDL_RLEaccel_c.h"
29 #include "SDL_pixels_c.h"
30 #include "SDL_leaks.h"
35 * Create an empty RGB surface of the appropriate depth
38 SDL_CreateRGBSurface(Uint32 flags,
39 int width, int height, int depth,
40 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
44 /* Allocate the surface */
45 surface = (SDL_Surface *) SDL_calloc(1, sizeof(*surface));
46 if (surface == NULL) {
51 surface->format = SDL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask);
52 if (!surface->format) {
53 SDL_FreeSurface(surface);
58 surface->pitch = SDL_CalculatePitch(surface);
59 SDL_SetClipRect(surface, NULL);
61 if (surface->format->BitsPerPixel <= 8) {
62 SDL_Palette *palette =
63 SDL_AllocPalette((1 << surface->format->BitsPerPixel));
65 SDL_FreeSurface(surface);
68 if (Rmask || Bmask || Gmask) {
69 const SDL_PixelFormat *format = surface->format;
71 /* create palette according to masks */
73 int Rm = 0, Gm = 0, Bm = 0;
74 int Rw = 0, Gw = 0, Bw = 0;
77 Rw = 8 - format->Rloss;
78 for (i = format->Rloss; i > 0; i -= Rw)
82 Gw = 8 - format->Gloss;
83 for (i = format->Gloss; i > 0; i -= Gw)
87 Bw = 8 - format->Bloss;
88 for (i = format->Bloss; i > 0; i -= Bw)
91 for (i = 0; i < palette->ncolors; ++i) {
93 r = (i & Rmask) >> format->Rshift;
94 r = (r << format->Rloss) | ((r * Rm) >> Rw);
95 palette->colors[i].r = r;
97 g = (i & Gmask) >> format->Gshift;
98 g = (g << format->Gloss) | ((g * Gm) >> Gw);
99 palette->colors[i].g = g;
101 b = (i & Bmask) >> format->Bshift;
102 b = (b << format->Bloss) | ((b * Bm) >> Bw);
103 palette->colors[i].b = b;
105 } else if (palette->ncolors == 2) {
106 /* Create a black and white bitmap palette */
107 palette->colors[0].r = 0xFF;
108 palette->colors[0].g = 0xFF;
109 palette->colors[0].b = 0xFF;
110 palette->colors[1].r = 0x00;
111 palette->colors[1].g = 0x00;
112 palette->colors[1].b = 0x00;
114 SDL_SetSurfacePalette(surface, palette);
115 SDL_FreePalette(palette);
119 if (surface->w && surface->h) {
120 surface->pixels = SDL_malloc(surface->h * surface->pitch);
121 if (!surface->pixels) {
122 SDL_FreeSurface(surface);
126 /* This is important for bitmaps */
127 SDL_memset(surface->pixels, 0, surface->h * surface->pitch);
130 /* Allocate an empty mapping */
131 surface->map = SDL_AllocBlitMap();
133 SDL_FreeSurface(surface);
136 SDL_FormatChanged(surface);
138 /* By default surface with an alpha mask are set up for blending */
140 SDL_SetSurfaceBlendMode(surface, SDL_TEXTUREBLENDMODE_BLEND);
143 /* The surface is ready to go */
144 surface->refcount = 1;
146 ++surfaces_allocated;
152 * Create an RGB surface from an existing memory buffer
155 SDL_CreateRGBSurfaceFrom(void *pixels,
156 int width, int height, int depth, int pitch,
157 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask,
160 SDL_Surface *surface;
163 SDL_CreateRGBSurface(0, 0, 0, depth, Rmask, Gmask, Bmask, Amask);
164 if (surface != NULL) {
165 surface->flags |= SDL_PREALLOC;
166 surface->pixels = pixels;
169 surface->pitch = pitch;
170 SDL_SetClipRect(surface, NULL);
176 SDL_SurfacePaletteChanged(void *userdata, SDL_Palette * palette)
178 SDL_Surface *surface = (SDL_Surface *) userdata;
180 SDL_FormatChanged(surface);
186 SDL_SetSurfacePalette(SDL_Surface * surface, SDL_Palette * palette)
188 if (!surface || !surface->format) {
189 SDL_SetError("SDL_SetSurfacePalette() passed a NULL surface");
193 if (palette && palette->ncolors != (1 << surface->format->BitsPerPixel)) {
195 ("SDL_SetSurfacePalette() passed a palette that doesn't match the surface format");
199 if (surface->format->palette == palette) {
203 if (surface->format->palette) {
204 SDL_DelPaletteWatch(surface->format->palette,
205 SDL_SurfacePaletteChanged, surface);
208 surface->format->palette = palette;
210 if (surface->format->palette) {
211 SDL_AddPaletteWatch(surface->format->palette,
212 SDL_SurfacePaletteChanged, surface);
218 SDL_SetSurfaceRLE(SDL_Surface * surface, int flag)
226 flags = surface->map->info.flags;
228 surface->map->info.flags |= SDL_COPY_RLE_DESIRED;
230 surface->map->info.flags &= ~SDL_COPY_RLE_DESIRED;
232 if (surface->map->info.flags != flags) {
233 SDL_InvalidateMap(surface->map);
239 SDL_SetColorKey(SDL_Surface * surface, Uint32 flag, Uint32 key)
247 if (flag & SDL_RLEACCEL) {
248 SDL_SetSurfaceRLE(surface, 1);
251 flags = surface->map->info.flags;
253 surface->map->info.flags |= SDL_COPY_COLORKEY;
254 surface->map->info.colorkey = key;
256 surface->map->info.flags &= ~SDL_COPY_COLORKEY;
258 if (surface->map->info.flags != flags) {
259 SDL_InvalidateMap(surface->map);
262 /* Compatibility mode */
263 if (surface->map->info.flags & SDL_COPY_COLORKEY) {
264 surface->flags |= SDL_SRCCOLORKEY;
266 surface->flags &= ~SDL_SRCCOLORKEY;
273 SDL_SetSurfaceColorMod(SDL_Surface * surface, Uint8 r, Uint8 g, Uint8 b)
281 surface->map->info.r = r;
282 surface->map->info.g = g;
283 surface->map->info.b = b;
285 flags = surface->map->info.flags;
286 if (r != 0xFF || g != 0xFF || b != 0xFF) {
287 surface->map->info.flags |= SDL_COPY_MODULATE_COLOR;
289 surface->map->info.flags &= ~SDL_COPY_MODULATE_COLOR;
291 if (surface->map->info.flags != flags) {
292 SDL_InvalidateMap(surface->map);
299 SDL_GetSurfaceColorMod(SDL_Surface * surface, Uint8 * r, Uint8 * g, Uint8 * b)
306 *r = surface->map->info.r;
309 *g = surface->map->info.g;
312 *b = surface->map->info.b;
318 SDL_SetSurfaceAlphaMod(SDL_Surface * surface, Uint8 alpha)
326 surface->map->info.a = alpha;
328 flags = surface->map->info.flags;
330 surface->map->info.flags |= SDL_COPY_MODULATE_ALPHA;
332 surface->map->info.flags &= ~SDL_COPY_MODULATE_ALPHA;
334 if (surface->map->info.flags != flags) {
335 SDL_InvalidateMap(surface->map);
341 SDL_GetSurfaceAlphaMod(SDL_Surface * surface, Uint8 * alpha)
348 *alpha = surface->map->info.a;
354 SDL_SetSurfaceBlendMode(SDL_Surface * surface, int blendMode)
363 flags = surface->map->info.flags;
364 surface->map->info.flags &=
365 ~(SDL_COPY_MASK | SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD);
367 case SDL_TEXTUREBLENDMODE_NONE:
369 case SDL_TEXTUREBLENDMODE_MASK:
370 surface->map->info.flags |= SDL_COPY_MASK;
372 case SDL_TEXTUREBLENDMODE_BLEND:
373 surface->map->info.flags |= SDL_COPY_BLEND;
375 case SDL_TEXTUREBLENDMODE_ADD:
376 surface->map->info.flags |= SDL_COPY_ADD;
378 case SDL_TEXTUREBLENDMODE_MOD:
379 surface->map->info.flags |= SDL_COPY_MOD;
387 if (surface->map->info.flags != flags) {
388 SDL_InvalidateMap(surface->map);
391 /* Compatibility mode */
392 if (surface->map->info.flags & SDL_COPY_BLEND) {
393 surface->flags |= SDL_SRCALPHA;
395 surface->flags &= ~SDL_SRCALPHA;
402 SDL_GetSurfaceBlendMode(SDL_Surface * surface, int *blendMode)
412 switch (surface->map->info.
413 flags & (SDL_COPY_MASK | SDL_COPY_BLEND | SDL_COPY_ADD |
416 *blendMode = SDL_TEXTUREBLENDMODE_MASK;
419 *blendMode = SDL_TEXTUREBLENDMODE_BLEND;
422 *blendMode = SDL_TEXTUREBLENDMODE_ADD;
425 *blendMode = SDL_TEXTUREBLENDMODE_MOD;
428 *blendMode = SDL_TEXTUREBLENDMODE_NONE;
435 SDL_SetSurfaceScaleMode(SDL_Surface * surface, int scaleMode)
444 flags = surface->map->info.flags;
445 surface->map->info.flags &= ~(SDL_COPY_NEAREST);
447 case SDL_TEXTURESCALEMODE_NONE:
449 case SDL_TEXTURESCALEMODE_FAST:
450 surface->map->info.flags |= SDL_COPY_NEAREST;
452 case SDL_TEXTURESCALEMODE_SLOW:
453 case SDL_TEXTURESCALEMODE_BEST:
455 surface->map->info.flags |= SDL_COPY_NEAREST;
464 if (surface->map->info.flags != flags) {
465 SDL_InvalidateMap(surface->map);
471 SDL_GetSurfaceScaleMode(SDL_Surface * surface, int *scaleMode)
481 switch (surface->map->info.flags & (SDL_COPY_NEAREST)) {
482 case SDL_COPY_NEAREST:
483 *scaleMode = SDL_TEXTURESCALEMODE_FAST;
486 *scaleMode = SDL_TEXTURESCALEMODE_NONE;
493 SDL_SetClipRect(SDL_Surface * surface, const SDL_Rect * rect)
497 /* Don't do anything if there's no surface to act on */
502 /* Set up the full surface rectangle */
505 full_rect.w = surface->w;
506 full_rect.h = surface->h;
508 /* Set the clipping rectangle */
510 surface->clip_rect = full_rect;
513 return SDL_IntersectRect(rect, &full_rect, &surface->clip_rect);
517 SDL_GetClipRect(SDL_Surface * surface, SDL_Rect * rect)
519 if (surface && rect) {
520 *rect = surface->clip_rect;
525 * Set up a blit between two surfaces -- split into three parts:
526 * The upper part, SDL_UpperBlit(), performs clipping and rectangle
527 * verification. The lower part is a pointer to a low level
528 * accelerated blitting function.
530 * These parts are separated out and each used internally by this
531 * library in the optimimum places. They are exported so that if
532 * you know exactly what you are doing, you can optimize your code
533 * by calling the one(s) you need.
536 SDL_LowerBlit(SDL_Surface * src, SDL_Rect * srcrect,
537 SDL_Surface * dst, SDL_Rect * dstrect)
539 /* Check to make sure the blit mapping is valid */
540 if ((src->map->dst != dst) ||
541 (src->map->dst->format_version != src->map->format_version)) {
542 if (SDL_MapSurface(src, dst) < 0) {
546 return (src->map->blit(src, srcrect, dst, dstrect));
551 SDL_UpperBlit(SDL_Surface * src, SDL_Rect * srcrect,
552 SDL_Surface * dst, SDL_Rect * dstrect)
555 int srcx, srcy, w, h;
557 /* Make sure the surfaces aren't locked */
559 SDL_SetError("SDL_UpperBlit: passed a NULL surface");
562 if (src->locked || dst->locked) {
563 SDL_SetError("Surfaces must not be locked during blit");
567 /* If the destination rectangle is NULL, use the entire dest surface */
568 if (dstrect == NULL) {
569 fulldst.x = fulldst.y = 0;
573 /* clip the source rectangle to the source surface */
584 maxw = src->w - srcx;
595 maxh = src->h - srcy;
605 /* clip the destination rectangle against the clip rectangle */
607 SDL_Rect *clip = &dst->clip_rect;
610 dx = clip->x - dstrect->x;
616 dx = dstrect->x + w - clip->x - clip->w;
620 dy = clip->y - dstrect->y;
626 dy = dstrect->y + h - clip->y - clip->h;
631 if (w > 0 && h > 0) {
635 sr.w = dstrect->w = w;
636 sr.h = dstrect->h = h;
637 return SDL_LowerBlit(src, &sr, dst, dstrect);
639 dstrect->w = dstrect->h = 0;
644 * Lock a surface to directly access the pixels
647 SDL_LockSurface(SDL_Surface * surface)
649 if (!surface->locked) {
650 /* Perform the lock */
651 if (surface->flags & SDL_RLEACCEL) {
652 SDL_UnRLESurface(surface, 1);
653 surface->flags |= SDL_RLEACCEL; /* save accel'd state */
657 /* Increment the surface lock count, for recursive locks */
665 * Unlock a previously locked surface
668 SDL_UnlockSurface(SDL_Surface * surface)
670 /* Only perform an unlock if we are locked */
671 if (!surface->locked || (--surface->locked > 0)) {
675 /* Update RLE encoded surface with new data */
676 if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
677 surface->flags &= ~SDL_RLEACCEL; /* stop lying */
678 SDL_RLESurface(surface);
683 * Convert a surface into the specified pixel format.
686 SDL_ConvertSurface(SDL_Surface * surface,
687 SDL_PixelFormat * format, Uint32 flags)
689 SDL_Surface *convert;
693 /* Check for empty destination palette! (results in empty image) */
694 if (format->palette != NULL) {
696 for (i = 0; i < format->palette->ncolors; ++i) {
697 if ((format->palette->colors[i].r != 0xFF) ||
698 (format->palette->colors[i].g != 0xFF) ||
699 (format->palette->colors[i].b != 0xFF))
702 if (i == format->palette->ncolors) {
703 SDL_SetError("Empty destination palette");
708 /* Create a new surface with the desired format */
709 convert = SDL_CreateRGBSurface(0, surface->w, surface->h,
710 format->BitsPerPixel, format->Rmask,
711 format->Gmask, format->Bmask,
713 if (convert == NULL) {
717 /* Copy the palette if any */
718 if (format->palette && convert->format->palette) {
719 SDL_memcpy(convert->format->palette->colors,
720 format->palette->colors,
721 format->palette->ncolors * sizeof(SDL_Color));
722 convert->format->palette->ncolors = format->palette->ncolors;
725 /* Save the original copy flags */
726 copy_flags = surface->map->info.flags;
727 surface->map->info.flags = 0;
729 /* Copy over the image data */
732 bounds.w = surface->w;
733 bounds.h = surface->h;
734 SDL_LowerBlit(surface, &bounds, convert, &bounds);
736 /* Clean up the original surface, and update converted surface */
737 SDL_SetClipRect(convert, &surface->clip_rect);
738 if (copy_flags & SDL_COPY_COLORKEY) {
739 Uint8 keyR, keyG, keyB, keyA;
741 SDL_GetRGBA(surface->map->info.colorkey, surface->format, &keyR,
742 &keyG, &keyB, &keyA);
743 SDL_SetColorKey(convert, 1,
744 SDL_MapRGBA(convert->format, keyR, keyG, keyB, keyA));
746 convert->map->info.r = surface->map->info.r;
747 convert->map->info.g = surface->map->info.g;
748 convert->map->info.b = surface->map->info.b;
749 convert->map->info.a = surface->map->info.a;
750 convert->map->info.flags = copy_flags;
751 surface->map->info.flags = copy_flags;
753 /* Enable alpha blending by default if the new surface has an
754 * alpha channel or alpha modulation */
755 if (format->Amask || (copy_flags & SDL_COPY_MODULATE_ALPHA)) {
756 SDL_SetSurfaceBlendMode(convert, SDL_TEXTUREBLENDMODE_BLEND);
759 /* We're ready to go! */
764 * Free a surface created by the above function.
767 SDL_FreeSurface(SDL_Surface * surface)
769 if (surface == NULL) {
772 if (--surface->refcount > 0) {
775 while (surface->locked > 0) {
776 SDL_UnlockSurface(surface);
778 if (surface->flags & SDL_RLEACCEL) {
779 SDL_UnRLESurface(surface, 0);
781 if (surface->format) {
782 SDL_SetSurfacePalette(surface, NULL);
783 SDL_FreeFormat(surface->format);
784 surface->format = NULL;
786 if (surface->map != NULL) {
787 SDL_FreeBlitMap(surface->map);
790 if (surface->pixels && ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC)) {
791 SDL_free(surface->pixels);
795 --surfaces_allocated;
799 /* vi: set ts=4 sw=4 expandtab: */