Mercurial > sdl-ios-xcode
view src/video/SDL_surface.c @ 3099:82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
From: "Mike Gorchak"
Subject: New QNX patches
Please apply patch qnx4.diff, which is attached. What has been done:
1)Added back OpenGL ES renderer for QNX target. Added few corrections to
OpenGL ES renderer to let it work under QNX. OpenGL ES renderer do not
support textures under QNX, so I think some additional work must be done.
2) Added GL_OES_query_matrix extension to SDL_opengles.h header file, which
required by OpenGL ES 1.1 specification.
3) Added attribute clearing at the entrance of function
SDL_GL_GetAttribure(). Added error checking into the function
SDL_GL_GetAttribure(), because some attributes can't be obtained in OpenGL
ES 1.0.
4) Porting testdyngles to OpenGL ES 1.0 (1.1 has glColor4ub() and
glColor4f() functions, but 1.0 has glColor4f() only).
5) Added error checking after obtaining attributes using
SDL_GL_GetAttribute() function to the testgl2 and testgles.
6) Small correction to testmultiaudio with printing errors.
7) Added software and accelerated OpenGL ES 1.0 support into the QNX GF
driver.
Please remove ./src/audio/nto directory - it will not be used anymore.
Please create ./src/audio/qsa directory and add content of the archive
qsa.tar.gz into this directory. I rewrote some sound code, added support for
multiple audio cards, enumeration, etc. Added initial support for capture.
As far as I can understand SDL 1.3 is not supporting audio capture right now
? Sam, Am I right ? Or audio capture must be supported through the
PlayDevice routine ?
And last, please put file SDL_gf_opengles.c to the ./src/video/qnxgf
directory. It is OpenGL ES 1.1 emulation layer for some functions, which are
not supported by OpenGL ES 1.0.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Tue, 24 Mar 2009 10:33:12 +0000 |
parents | 8cc00819c8d6 |
children | 7be21a78777e |
line wrap: on
line source
/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2009 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Sam Lantinga slouken@libsdl.org */ #include "SDL_config.h" #include "SDL_video.h" #include "SDL_compat.h" #include "SDL_sysvideo.h" #include "SDL_blit.h" #include "SDL_RLEaccel_c.h" #include "SDL_pixels_c.h" #include "SDL_leaks.h" /* Public routines */ /* * Create an empty RGB surface of the appropriate depth */ SDL_Surface * SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) { SDL_Surface *surface; /* The flags are no longer used, make the compiler happy */ flags; /* Allocate the surface */ surface = (SDL_Surface *) SDL_calloc(1, sizeof(*surface)); if (surface == NULL) { SDL_OutOfMemory(); return NULL; } surface->format = SDL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask); if (!surface->format) { SDL_FreeSurface(surface); return NULL; } surface->w = width; surface->h = height; surface->pitch = SDL_CalculatePitch(surface); SDL_SetClipRect(surface, NULL); if (surface->format->BitsPerPixel <= 8) { SDL_Palette *palette = SDL_AllocPalette((1 << surface->format->BitsPerPixel)); if (!palette) { SDL_FreeSurface(surface); return NULL; } if (Rmask || Bmask || Gmask) { const SDL_PixelFormat *format = surface->format; /* create palette according to masks */ int i; int Rm = 0, Gm = 0, Bm = 0; int Rw = 0, Gw = 0, Bw = 0; if (Rmask) { Rw = 8 - format->Rloss; for (i = format->Rloss; i > 0; i -= Rw) Rm |= 1 << i; } if (Gmask) { Gw = 8 - format->Gloss; for (i = format->Gloss; i > 0; i -= Gw) Gm |= 1 << i; } if (Bmask) { Bw = 8 - format->Bloss; for (i = format->Bloss; i > 0; i -= Bw) Bm |= 1 << i; } for (i = 0; i < palette->ncolors; ++i) { int r, g, b; r = (i & Rmask) >> format->Rshift; r = (r << format->Rloss) | ((r * Rm) >> Rw); palette->colors[i].r = r; g = (i & Gmask) >> format->Gshift; g = (g << format->Gloss) | ((g * Gm) >> Gw); palette->colors[i].g = g; b = (i & Bmask) >> format->Bshift; b = (b << format->Bloss) | ((b * Bm) >> Bw); palette->colors[i].b = b; } } else if (palette->ncolors == 2) { /* Create a black and white bitmap palette */ palette->colors[0].r = 0xFF; palette->colors[0].g = 0xFF; palette->colors[0].b = 0xFF; palette->colors[1].r = 0x00; palette->colors[1].g = 0x00; palette->colors[1].b = 0x00; } SDL_SetSurfacePalette(surface, palette); SDL_FreePalette(palette); } /* Get the pixels */ if (surface->w && surface->h) { surface->pixels = SDL_malloc(surface->h * surface->pitch); if (!surface->pixels) { SDL_FreeSurface(surface); SDL_OutOfMemory(); return NULL; } /* This is important for bitmaps */ SDL_memset(surface->pixels, 0, surface->h * surface->pitch); } /* Allocate an empty mapping */ surface->map = SDL_AllocBlitMap(); if (!surface->map) { SDL_FreeSurface(surface); return NULL; } SDL_FormatChanged(surface); /* By default surface with an alpha mask are set up for blending */ if (Amask) { SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND); } /* The surface is ready to go */ surface->refcount = 1; #ifdef CHECK_LEAKS ++surfaces_allocated; #endif return surface; } /* * Create an RGB surface from an existing memory buffer */ SDL_Surface * SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) { SDL_Surface *surface; surface = SDL_CreateRGBSurface(0, 0, 0, depth, Rmask, Gmask, Bmask, Amask); if (surface != NULL) { surface->flags |= SDL_PREALLOC; surface->pixels = pixels; surface->w = width; surface->h = height; surface->pitch = pitch; SDL_SetClipRect(surface, NULL); } return surface; } static int SDL_SurfacePaletteChanged(void *userdata, SDL_Palette * palette) { SDL_Surface *surface = (SDL_Surface *) userdata; SDL_FormatChanged(surface); return 0; } int SDL_SetSurfacePalette(SDL_Surface * surface, SDL_Palette * palette) { if (!surface || !surface->format) { SDL_SetError("SDL_SetSurfacePalette() passed a NULL surface"); return -1; } if (palette && palette->ncolors != (1 << surface->format->BitsPerPixel)) { SDL_SetError ("SDL_SetSurfacePalette() passed a palette that doesn't match the surface format"); return -1; } if (surface->format->palette == palette) { return 0; } if (surface->format->palette) { SDL_DelPaletteWatch(surface->format->palette, SDL_SurfacePaletteChanged, surface); } surface->format->palette = palette; if (surface->format->palette) { SDL_AddPaletteWatch(surface->format->palette, SDL_SurfacePaletteChanged, surface); } return 0; } int SDL_SetSurfaceRLE(SDL_Surface * surface, int flag) { int flags; if (!surface) { return -1; } flags = surface->map->info.flags; if (flag) { surface->map->info.flags |= SDL_COPY_RLE_DESIRED; } else { surface->map->info.flags &= ~SDL_COPY_RLE_DESIRED; } if (surface->map->info.flags != flags) { SDL_InvalidateMap(surface->map); } return 0; } int SDL_SetColorKey(SDL_Surface * surface, Uint32 flag, Uint32 key) { int flags; if (!surface) { return -1; } if (flag & SDL_RLEACCEL) { SDL_SetSurfaceRLE(surface, 1); } flags = surface->map->info.flags; if (flag) { surface->map->info.flags |= SDL_COPY_COLORKEY; surface->map->info.colorkey = key; } else { surface->map->info.flags &= ~SDL_COPY_COLORKEY; } if (surface->map->info.flags != flags) { SDL_InvalidateMap(surface->map); } /* Compatibility mode */ if (surface->map->info.flags & SDL_COPY_COLORKEY) { surface->flags |= SDL_SRCCOLORKEY; } else { surface->flags &= ~SDL_SRCCOLORKEY; } return 0; } /* This is a fairly slow function to switch from colorkey to alpha */ static void SDL_ConvertColorkeyToAlpha(SDL_Surface * surface) { int x, y; if (!surface) { return; } if (!(surface->map->info.flags & SDL_COPY_COLORKEY) || !surface->format->Amask) { return; } SDL_LockSurface(surface); switch (surface->format->BytesPerPixel) { case 2: { Uint16 *row, *spot; Uint16 ckey = (Uint16) surface->map->info.colorkey; Uint16 mask = (Uint16) (~surface->format->Amask); row = (Uint16 *) surface->pixels; for (y = surface->h; y--;) { spot = row; for (x = surface->w; x--;) { if (*spot == ckey) { *spot &= mask; } ++spot; } row += surface->pitch / 2; } } break; case 3: /* FIXME */ break; case 4: { Uint32 *row, *spot; Uint32 ckey = surface->map->info.colorkey; Uint32 mask = ~surface->format->Amask; row = (Uint32 *) surface->pixels; for (y = surface->h; y--;) { spot = row; for (x = surface->w; x--;) { if (*spot == ckey) { *spot &= mask; } ++spot; } row += surface->pitch / 4; } } break; } SDL_UnlockSurface(surface); SDL_SetColorKey(surface, 0, 0); SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND); } int SDL_SetSurfaceColorMod(SDL_Surface * surface, Uint8 r, Uint8 g, Uint8 b) { int flags; if (!surface) { return -1; } surface->map->info.r = r; surface->map->info.g = g; surface->map->info.b = b; flags = surface->map->info.flags; if (r != 0xFF || g != 0xFF || b != 0xFF) { surface->map->info.flags |= SDL_COPY_MODULATE_COLOR; } else { surface->map->info.flags &= ~SDL_COPY_MODULATE_COLOR; } if (surface->map->info.flags != flags) { SDL_InvalidateMap(surface->map); } return 0; } int SDL_GetSurfaceColorMod(SDL_Surface * surface, Uint8 * r, Uint8 * g, Uint8 * b) { if (!surface) { return -1; } if (r) { *r = surface->map->info.r; } if (g) { *g = surface->map->info.g; } if (b) { *b = surface->map->info.b; } return 0; } int SDL_SetSurfaceAlphaMod(SDL_Surface * surface, Uint8 alpha) { int flags; if (!surface) { return -1; } surface->map->info.a = alpha; flags = surface->map->info.flags; if (alpha != 0xFF) { surface->map->info.flags |= SDL_COPY_MODULATE_ALPHA; } else { surface->map->info.flags &= ~SDL_COPY_MODULATE_ALPHA; } if (surface->map->info.flags != flags) { SDL_InvalidateMap(surface->map); } return 0; } int SDL_GetSurfaceAlphaMod(SDL_Surface * surface, Uint8 * alpha) { if (!surface) { return -1; } if (alpha) { *alpha = surface->map->info.a; } return 0; } int SDL_SetSurfaceBlendMode(SDL_Surface * surface, int blendMode) { int flags, status; if (!surface) { return -1; } status = 0; flags = surface->map->info.flags; surface->map->info.flags &= ~(SDL_COPY_MASK | SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD); switch (blendMode) { case SDL_BLENDMODE_NONE: break; case SDL_BLENDMODE_MASK: surface->map->info.flags |= SDL_COPY_MASK; break; case SDL_BLENDMODE_BLEND: surface->map->info.flags |= SDL_COPY_BLEND; break; case SDL_BLENDMODE_ADD: surface->map->info.flags |= SDL_COPY_ADD; break; case SDL_BLENDMODE_MOD: surface->map->info.flags |= SDL_COPY_MOD; break; default: SDL_Unsupported(); status = -1; break; } if (surface->map->info.flags != flags) { SDL_InvalidateMap(surface->map); } /* Compatibility mode */ if (surface->map->info.flags & SDL_COPY_BLEND) { surface->flags |= SDL_SRCALPHA; } else { surface->flags &= ~SDL_SRCALPHA; } return status; } int SDL_GetSurfaceBlendMode(SDL_Surface * surface, int *blendMode) { if (!surface) { return -1; } if (!blendMode) { return 0; } switch (surface->map-> info.flags & (SDL_COPY_MASK | SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD)) { case SDL_COPY_MASK: *blendMode = SDL_BLENDMODE_MASK; break; case SDL_COPY_BLEND: *blendMode = SDL_BLENDMODE_BLEND; break; case SDL_COPY_ADD: *blendMode = SDL_BLENDMODE_ADD; break; case SDL_COPY_MOD: *blendMode = SDL_BLENDMODE_MOD; break; default: *blendMode = SDL_BLENDMODE_NONE; break; } return 0; } int SDL_SetSurfaceScaleMode(SDL_Surface * surface, int scaleMode) { int flags, status; if (!surface) { return -1; } status = 0; flags = surface->map->info.flags; surface->map->info.flags &= ~(SDL_COPY_NEAREST); switch (scaleMode) { case SDL_TEXTURESCALEMODE_NONE: break; case SDL_TEXTURESCALEMODE_FAST: surface->map->info.flags |= SDL_COPY_NEAREST; break; case SDL_TEXTURESCALEMODE_SLOW: case SDL_TEXTURESCALEMODE_BEST: SDL_Unsupported(); surface->map->info.flags |= SDL_COPY_NEAREST; status = -1; break; default: SDL_Unsupported(); status = -1; break; } if (surface->map->info.flags != flags) { SDL_InvalidateMap(surface->map); } return status; } int SDL_GetSurfaceScaleMode(SDL_Surface * surface, int *scaleMode) { if (!surface) { return -1; } if (!scaleMode) { return 0; } switch (surface->map->info.flags & SDL_COPY_NEAREST) { case SDL_COPY_NEAREST: *scaleMode = SDL_TEXTURESCALEMODE_FAST; break; default: *scaleMode = SDL_TEXTURESCALEMODE_NONE; break; } return 0; } SDL_bool SDL_SetClipRect(SDL_Surface * surface, const SDL_Rect * rect) { SDL_Rect full_rect; /* Don't do anything if there's no surface to act on */ if (!surface) { return SDL_FALSE; } /* Set up the full surface rectangle */ full_rect.x = 0; full_rect.y = 0; full_rect.w = surface->w; full_rect.h = surface->h; /* Set the clipping rectangle */ if (!rect) { surface->clip_rect = full_rect; return 1; } return SDL_IntersectRect(rect, &full_rect, &surface->clip_rect); } void SDL_GetClipRect(SDL_Surface * surface, SDL_Rect * rect) { if (surface && rect) { *rect = surface->clip_rect; } } /* * Set up a blit between two surfaces -- split into three parts: * The upper part, SDL_UpperBlit(), performs clipping and rectangle * verification. The lower part is a pointer to a low level * accelerated blitting function. * * These parts are separated out and each used internally by this * library in the optimimum places. They are exported so that if * you know exactly what you are doing, you can optimize your code * by calling the one(s) you need. */ int SDL_LowerBlit(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect) { /* Check to make sure the blit mapping is valid */ if ((src->map->dst != dst) || (src->map->dst->format_version != src->map->format_version)) { if (SDL_MapSurface(src, dst) < 0) { return (-1); } /* just here for debugging */ /* printf */ /* ("src = 0x%08X src->flags = %08X src->map->info.flags = %08x\ndst = 0x%08X dst->flags = %08X dst->map->info.flags = %08X\nsrc->map->blit = 0x%08x\n", */ /* src, dst->flags, src->map->info.flags, dst, dst->flags, */ /* dst->map->info.flags, src->map->blit); */ } return (src->map->blit(src, srcrect, dst, dstrect)); } int SDL_UpperBlit(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect) { SDL_Rect fulldst; int srcx, srcy, w, h; /* Make sure the surfaces aren't locked */ if (!src || !dst) { SDL_SetError("SDL_UpperBlit: passed a NULL surface"); return (-1); } if (src->locked || dst->locked) { SDL_SetError("Surfaces must not be locked during blit"); return (-1); } /* If the destination rectangle is NULL, use the entire dest surface */ if (dstrect == NULL) { fulldst.x = fulldst.y = 0; dstrect = &fulldst; } /* clip the source rectangle to the source surface */ if (srcrect) { int maxw, maxh; srcx = srcrect->x; w = srcrect->w; if (srcx < 0) { w += srcx; dstrect->x -= srcx; srcx = 0; } maxw = src->w - srcx; if (maxw < w) w = maxw; srcy = srcrect->y; h = srcrect->h; if (srcy < 0) { h += srcy; dstrect->y -= srcy; srcy = 0; } maxh = src->h - srcy; if (maxh < h) h = maxh; } else { srcx = srcy = 0; w = src->w; h = src->h; } /* clip the destination rectangle against the clip rectangle */ { SDL_Rect *clip = &dst->clip_rect; int dx, dy; dx = clip->x - dstrect->x; if (dx > 0) { w -= dx; dstrect->x += dx; srcx += dx; } dx = dstrect->x + w - clip->x - clip->w; if (dx > 0) w -= dx; dy = clip->y - dstrect->y; if (dy > 0) { h -= dy; dstrect->y += dy; srcy += dy; } dy = dstrect->y + h - clip->y - clip->h; if (dy > 0) h -= dy; } if (w > 0 && h > 0) { SDL_Rect sr; sr.x = srcx; sr.y = srcy; sr.w = dstrect->w = w; sr.h = dstrect->h = h; return SDL_LowerBlit(src, &sr, dst, dstrect); } dstrect->w = dstrect->h = 0; return 0; } /* * Lock a surface to directly access the pixels */ int SDL_LockSurface(SDL_Surface * surface) { if (!surface->locked) { /* Perform the lock */ if (surface->flags & SDL_RLEACCEL) { SDL_UnRLESurface(surface, 1); surface->flags |= SDL_RLEACCEL; /* save accel'd state */ } } /* Increment the surface lock count, for recursive locks */ ++surface->locked; /* Ready to go.. */ return (0); } /* * Unlock a previously locked surface */ void SDL_UnlockSurface(SDL_Surface * surface) { /* Only perform an unlock if we are locked */ if (!surface->locked || (--surface->locked > 0)) { return; } /* Update RLE encoded surface with new data */ if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) { surface->flags &= ~SDL_RLEACCEL; /* stop lying */ SDL_RLESurface(surface); } } /* * Convert a surface into the specified pixel format. */ SDL_Surface * SDL_ConvertSurface(SDL_Surface * surface, SDL_PixelFormat * format, Uint32 flags) { SDL_Surface *convert; Uint32 copy_flags; SDL_Rect bounds; /* Check for empty destination palette! (results in empty image) */ if (format->palette != NULL) { int i; for (i = 0; i < format->palette->ncolors; ++i) { if ((format->palette->colors[i].r != 0xFF) || (format->palette->colors[i].g != 0xFF) || (format->palette->colors[i].b != 0xFF)) break; } if (i == format->palette->ncolors) { SDL_SetError("Empty destination palette"); return (NULL); } } /* Create a new surface with the desired format */ convert = SDL_CreateRGBSurface(flags, surface->w, surface->h, format->BitsPerPixel, format->Rmask, format->Gmask, format->Bmask, format->Amask); if (convert == NULL) { return (NULL); } /* Copy the palette if any */ if (format->palette && convert->format->palette) { SDL_memcpy(convert->format->palette->colors, format->palette->colors, format->palette->ncolors * sizeof(SDL_Color)); convert->format->palette->ncolors = format->palette->ncolors; } /* Save the original copy flags */ copy_flags = surface->map->info.flags; surface->map->info.flags = 0; /* Copy over the image data */ bounds.x = 0; bounds.y = 0; bounds.w = surface->w; bounds.h = surface->h; SDL_LowerBlit(surface, &bounds, convert, &bounds); /* Clean up the original surface, and update converted surface */ convert->map->info.r = surface->map->info.r; convert->map->info.g = surface->map->info.g; convert->map->info.b = surface->map->info.b; convert->map->info.a = surface->map->info.a; convert->map->info.flags = (copy_flags & ~(SDL_COPY_COLORKEY | SDL_COPY_BLEND | SDL_COPY_RLE_DESIRED | SDL_COPY_RLE_COLORKEY | SDL_COPY_RLE_ALPHAKEY)); surface->map->info.flags = copy_flags; if (copy_flags & SDL_COPY_COLORKEY) { Uint8 keyR, keyG, keyB, keyA; SDL_GetRGBA(surface->map->info.colorkey, surface->format, &keyR, &keyG, &keyB, &keyA); SDL_SetColorKey(convert, 1, SDL_MapRGBA(convert->format, keyR, keyG, keyB, keyA)); /* This is needed when converting for 3D texture upload */ SDL_ConvertColorkeyToAlpha(convert); } SDL_SetClipRect(convert, &surface->clip_rect); /* Enable alpha blending by default if the new surface has an * alpha channel or alpha modulation */ if ((surface->format->Amask && format->Amask) || (copy_flags & SDL_COPY_MODULATE_ALPHA)) { SDL_SetSurfaceBlendMode(convert, SDL_BLENDMODE_BLEND); } if ((copy_flags & SDL_COPY_RLE_DESIRED) || (flags & SDL_RLEACCEL)) { SDL_SetSurfaceRLE(convert, SDL_RLEACCEL); } /* We're ready to go! */ return (convert); } /* * Free a surface created by the above function. */ void SDL_FreeSurface(SDL_Surface * surface) { if (surface == NULL) { return; } if (--surface->refcount > 0) { return; } while (surface->locked > 0) { SDL_UnlockSurface(surface); } if (surface->flags & SDL_RLEACCEL) { SDL_UnRLESurface(surface, 0); } if (surface->format) { SDL_SetSurfacePalette(surface, NULL); SDL_FreeFormat(surface->format); surface->format = NULL; } if (surface->map != NULL) { SDL_FreeBlitMap(surface->map); surface->map = NULL; } if (surface->pixels && ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC)) { SDL_free(surface->pixels); } SDL_free(surface); #ifdef CHECK_LEAKS --surfaces_allocated; #endif } /* vi: set ts=4 sw=4 expandtab: */