aboutsummaryrefslogtreecommitdiffstats
path: root/distrib/sdl-1.2.15/src/video/SDL_video.c
diff options
context:
space:
mode:
Diffstat (limited to 'distrib/sdl-1.2.15/src/video/SDL_video.c')
-rw-r--r--distrib/sdl-1.2.15/src/video/SDL_video.c2041
1 files changed, 2041 insertions, 0 deletions
diff --git a/distrib/sdl-1.2.15/src/video/SDL_video.c b/distrib/sdl-1.2.15/src/video/SDL_video.c
new file mode 100644
index 0000000..f4f4407
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/SDL_video.c
@@ -0,0 +1,2041 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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"
+
+/* The high-level video driver subsystem */
+
+#include "SDL.h"
+#include "SDL_sysvideo.h"
+#include "SDL_blit.h"
+#include "SDL_pixels_c.h"
+#include "SDL_cursor_c.h"
+#include "../events/SDL_sysevents.h"
+#include "../events/SDL_events_c.h"
+
+/* Available video drivers */
+static VideoBootStrap *bootstrap[] = {
+#if SDL_VIDEO_DRIVER_QUARTZ
+ &QZ_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_X11
+ &X11_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_DGA
+ &DGA_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_NANOX
+ &NX_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_IPOD
+ &iPod_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_QTOPIA
+ &Qtopia_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_WSCONS
+ &WSCONS_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_FBCON
+ &FBCON_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_DIRECTFB
+ &DirectFB_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_PS2GS
+ &PS2GS_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_PS3
+ &PS3_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_GGI
+ &GGI_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_VGL
+ &VGL_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_SVGALIB
+ &SVGALIB_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_GAPI
+ &GAPI_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_WINDIB
+ &WINDIB_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_DDRAW
+ &DIRECTX_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_BWINDOW
+ &BWINDOW_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_TOOLBOX
+ &TOOLBOX_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_DRAWSPROCKET
+ &DSp_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_PHOTON
+ &ph_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_EPOC
+ &EPOC_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_XBIOS
+ &XBIOS_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_GEM
+ &GEM_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_PICOGUI
+ &PG_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_DC
+ &DC_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_NDS
+ &NDS_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_RISCOS
+ &RISCOS_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_OS2FS
+ &OS2FSLib_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_AALIB
+ &AALIB_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_CACA
+ &CACA_bootstrap,
+#endif
+#if SDL_VIDEO_DRIVER_DUMMY
+ &DUMMY_bootstrap,
+#endif
+ NULL
+};
+
+SDL_VideoDevice *current_video = NULL;
+
+/* Various local functions */
+int SDL_VideoInit(const char *driver_name, Uint32 flags);
+void SDL_VideoQuit(void);
+void SDL_GL_UpdateRectsLock(SDL_VideoDevice* this, int numrects, SDL_Rect* rects);
+
+static SDL_GrabMode SDL_WM_GrabInputOff(void);
+#if SDL_VIDEO_OPENGL
+static int lock_count = 0;
+#endif
+
+
+/*
+ * Initialize the video and event subsystems -- determine native pixel format
+ */
+int SDL_VideoInit (const char *driver_name, Uint32 flags)
+{
+ SDL_VideoDevice *video;
+ int index;
+ int i;
+ SDL_PixelFormat vformat;
+ Uint32 video_flags;
+
+ /* Toggle the event thread flags, based on OS requirements */
+#if defined(MUST_THREAD_EVENTS)
+ flags |= SDL_INIT_EVENTTHREAD;
+#elif defined(CANT_THREAD_EVENTS)
+ if ( (flags & SDL_INIT_EVENTTHREAD) == SDL_INIT_EVENTTHREAD ) {
+ SDL_SetError("OS doesn't support threaded events");
+ return(-1);
+ }
+#endif
+
+ /* Check to make sure we don't overwrite 'current_video' */
+ if ( current_video != NULL ) {
+ SDL_VideoQuit();
+ }
+
+ /* Select the proper video driver */
+ index = 0;
+ video = NULL;
+ if ( driver_name != NULL ) {
+#if 0 /* This will be replaced with a better driver selection API */
+ if ( SDL_strrchr(driver_name, ':') != NULL ) {
+ index = atoi(SDL_strrchr(driver_name, ':')+1);
+ }
+#endif
+ for ( i=0; bootstrap[i]; ++i ) {
+ if ( SDL_strcasecmp(bootstrap[i]->name, driver_name) == 0) {
+ if ( bootstrap[i]->available() ) {
+ video = bootstrap[i]->create(index);
+ break;
+ }
+ }
+ }
+ } else {
+ for ( i=0; bootstrap[i]; ++i ) {
+ if ( bootstrap[i]->available() ) {
+ video = bootstrap[i]->create(index);
+ if ( video != NULL ) {
+ break;
+ }
+ }
+ }
+ }
+ if ( video == NULL ) {
+ SDL_SetError("No available video device");
+ return(-1);
+ }
+ current_video = video;
+ current_video->name = bootstrap[i]->name;
+
+ /* Do some basic variable initialization */
+ video->screen = NULL;
+ video->shadow = NULL;
+ video->visible = NULL;
+ video->physpal = NULL;
+ video->gammacols = NULL;
+ video->gamma = NULL;
+ video->wm_title = NULL;
+ video->wm_icon = NULL;
+ video->offset_x = 0;
+ video->offset_y = 0;
+ SDL_memset(&video->info, 0, (sizeof video->info));
+
+ video->displayformatalphapixel = NULL;
+
+ /* Set some very sane GL defaults */
+ video->gl_config.driver_loaded = 0;
+ video->gl_config.dll_handle = NULL;
+ video->gl_config.red_size = 3;
+ video->gl_config.green_size = 3;
+ video->gl_config.blue_size = 2;
+ video->gl_config.alpha_size = 0;
+ video->gl_config.buffer_size = 0;
+ video->gl_config.depth_size = 16;
+ video->gl_config.stencil_size = 0;
+ video->gl_config.double_buffer = 1;
+ video->gl_config.accum_red_size = 0;
+ video->gl_config.accum_green_size = 0;
+ video->gl_config.accum_blue_size = 0;
+ video->gl_config.accum_alpha_size = 0;
+ video->gl_config.stereo = 0;
+ video->gl_config.multisamplebuffers = 0;
+ video->gl_config.multisamplesamples = 0;
+ video->gl_config.accelerated = -1; /* not known, don't set */
+ video->gl_config.swap_control = -1; /* not known, don't set */
+
+ /* Initialize the video subsystem */
+ SDL_memset(&vformat, 0, sizeof(vformat));
+ if ( video->VideoInit(video, &vformat) < 0 ) {
+ SDL_VideoQuit();
+ return(-1);
+ }
+
+ /* Create a zero sized video surface of the appropriate format */
+ video_flags = SDL_SWSURFACE;
+ SDL_VideoSurface = SDL_CreateRGBSurface(video_flags, 0, 0,
+ vformat.BitsPerPixel,
+ vformat.Rmask, vformat.Gmask, vformat.Bmask, 0);
+ if ( SDL_VideoSurface == NULL ) {
+ SDL_VideoQuit();
+ return(-1);
+ }
+ SDL_PublicSurface = NULL; /* Until SDL_SetVideoMode() */
+
+#if 0 /* Don't change the current palette - may be used by other programs.
+ * The application can't do anything with the display surface until
+ * a video mode has been set anyway. :)
+ */
+ /* If we have a palettized surface, create a default palette */
+ if ( SDL_VideoSurface->format->palette ) {
+ SDL_PixelFormat *vf = SDL_VideoSurface->format;
+ SDL_DitherColors(vf->palette->colors, vf->BitsPerPixel);
+ video->SetColors(video,
+ 0, vf->palette->ncolors, vf->palette->colors);
+ }
+#endif
+ video->info.vfmt = SDL_VideoSurface->format;
+
+ /* Start the event loop */
+ if ( SDL_StartEventLoop(flags) < 0 ) {
+ SDL_VideoQuit();
+ return(-1);
+ }
+ SDL_CursorInit(flags & SDL_INIT_EVENTTHREAD);
+
+ /* We're ready to go! */
+ return(0);
+}
+
+char *SDL_VideoDriverName(char *namebuf, int maxlen)
+{
+ if ( current_video != NULL ) {
+ SDL_strlcpy(namebuf, current_video->name, maxlen);
+ return(namebuf);
+ }
+ return(NULL);
+}
+
+/*
+ * Get the current display surface
+ */
+SDL_Surface *SDL_GetVideoSurface(void)
+{
+ SDL_Surface *visible;
+
+ visible = NULL;
+ if ( current_video ) {
+ visible = current_video->visible;
+ }
+ return(visible);
+}
+
+/*
+ * Get the current information about the video hardware
+ */
+const SDL_VideoInfo *SDL_GetVideoInfo(void)
+{
+ const SDL_VideoInfo *info;
+
+ info = NULL;
+ if ( current_video ) {
+ info = &current_video->info;
+ }
+ return(info);
+}
+
+/*
+ * Return a pointer to an array of available screen dimensions for the
+ * given format, sorted largest to smallest. Returns NULL if there are
+ * no dimensions available for a particular format, or (SDL_Rect **)-1
+ * if any dimension is okay for the given format. If 'format' is NULL,
+ * the mode list will be for the format given by SDL_GetVideoInfo()->vfmt
+ */
+SDL_Rect ** SDL_ListModes (SDL_PixelFormat *format, Uint32 flags)
+{
+ SDL_VideoDevice *video = current_video;
+ SDL_VideoDevice *this = current_video;
+ SDL_Rect **modes;
+
+ modes = NULL;
+ if ( SDL_VideoSurface ) {
+ if ( format == NULL ) {
+ format = SDL_VideoSurface->format;
+ }
+ modes = video->ListModes(this, format, flags);
+ }
+ return(modes);
+}
+
+/*
+ * Check to see if a particular video mode is supported.
+ * It returns 0 if the requested mode is not supported under any bit depth,
+ * or returns the bits-per-pixel of the closest available mode with the
+ * given width and height. If this bits-per-pixel is different from the
+ * one used when setting the video mode, SDL_SetVideoMode() will succeed,
+ * but will emulate the requested bits-per-pixel with a shadow surface.
+ */
+static Uint8 SDL_closest_depths[4][8] = {
+ /* 8 bit closest depth ordering */
+ { 0, 8, 16, 15, 32, 24, 0, 0 },
+ /* 15,16 bit closest depth ordering */
+ { 0, 16, 15, 32, 24, 8, 0, 0 },
+ /* 24 bit closest depth ordering */
+ { 0, 24, 32, 16, 15, 8, 0, 0 },
+ /* 32 bit closest depth ordering */
+ { 0, 32, 16, 15, 24, 8, 0, 0 }
+};
+
+
+#ifdef __MACOS__ /* MPW optimization bug? */
+#define NEGATIVE_ONE 0xFFFFFFFF
+#else
+#define NEGATIVE_ONE -1
+#endif
+
+int SDL_VideoModeOK (int width, int height, int bpp, Uint32 flags)
+{
+ int table, b, i;
+ int supported;
+ SDL_PixelFormat format;
+ SDL_Rect **sizes;
+
+ /* Currently 1 and 4 bpp are not supported */
+ if ( bpp < 8 || bpp > 32 ) {
+ return(0);
+ }
+ if ( (width <= 0) || (height <= 0) ) {
+ return(0);
+ }
+
+ /* Search through the list valid of modes */
+ SDL_memset(&format, 0, sizeof(format));
+ supported = 0;
+ table = ((bpp+7)/8)-1;
+ SDL_closest_depths[table][0] = bpp;
+ SDL_closest_depths[table][7] = 0;
+ for ( b = 0; !supported && SDL_closest_depths[table][b]; ++b ) {
+ format.BitsPerPixel = SDL_closest_depths[table][b];
+ sizes = SDL_ListModes(&format, flags);
+ if ( sizes == (SDL_Rect **)0 ) {
+ /* No sizes supported at this bit-depth */
+ continue;
+ } else
+ if (sizes == (SDL_Rect **)NEGATIVE_ONE) {
+ /* Any size supported at this bit-depth */
+ supported = 1;
+ continue;
+ } else if (current_video->handles_any_size) {
+ /* Driver can center a smaller surface to simulate fullscreen */
+ for ( i=0; sizes[i]; ++i ) {
+ if ((sizes[i]->w >= width) && (sizes[i]->h >= height)) {
+ supported = 1; /* this mode can fit the centered window. */
+ break;
+ }
+ }
+ } else
+ for ( i=0; sizes[i]; ++i ) {
+ if ((sizes[i]->w == width) && (sizes[i]->h == height)) {
+ supported = 1;
+ break;
+ }
+ }
+ }
+ if ( supported ) {
+ --b;
+ return(SDL_closest_depths[table][b]);
+ } else {
+ return(0);
+ }
+}
+
+/*
+ * Get the closest non-emulated video mode to the one requested
+ */
+static int SDL_GetVideoMode (int *w, int *h, int *BitsPerPixel, Uint32 flags)
+{
+ int table, b, i;
+ int supported;
+ int native_bpp;
+ SDL_PixelFormat format;
+ SDL_Rect **sizes;
+
+ /* Check parameters */
+ if ( *BitsPerPixel < 8 || *BitsPerPixel > 32 ) {
+ SDL_SetError("Invalid bits per pixel (range is {8...32})");
+ return(0);
+ }
+ if ((*w <= 0) || (*h <= 0)) {
+ SDL_SetError("Invalid width or height");
+ return(0);
+ }
+
+ /* Try the original video mode, get the closest depth */
+ native_bpp = SDL_VideoModeOK(*w, *h, *BitsPerPixel, flags);
+ if ( native_bpp == *BitsPerPixel ) {
+ return(1);
+ }
+ if ( native_bpp > 0 ) {
+ *BitsPerPixel = native_bpp;
+ return(1);
+ }
+
+ /* No exact size match at any depth, look for closest match */
+ SDL_memset(&format, 0, sizeof(format));
+ supported = 0;
+ table = ((*BitsPerPixel+7)/8)-1;
+ SDL_closest_depths[table][0] = *BitsPerPixel;
+ SDL_closest_depths[table][7] = SDL_VideoSurface->format->BitsPerPixel;
+ for ( b = 0; !supported && SDL_closest_depths[table][b]; ++b ) {
+ int best;
+
+ format.BitsPerPixel = SDL_closest_depths[table][b];
+ sizes = SDL_ListModes(&format, flags);
+ if ( sizes == (SDL_Rect **)0 ) {
+ /* No sizes supported at this bit-depth */
+ continue;
+ }
+ best=0;
+ for ( i=0; sizes[i]; ++i ) {
+ /* Mode with both dimensions bigger or equal than asked ? */
+ if ((sizes[i]->w >= *w) && (sizes[i]->h >= *h)) {
+ /* Mode with any dimension smaller or equal than current best ? */
+ if ((sizes[i]->w <= sizes[best]->w) || (sizes[i]->h <= sizes[best]->h)) {
+ /* Now choose the mode that has less pixels */
+ if ((sizes[i]->w * sizes[i]->h) <= (sizes[best]->w * sizes[best]->h)) {
+ best=i;
+ supported = 1;
+ }
+ }
+ }
+ }
+ if (supported) {
+ *w=sizes[best]->w;
+ *h=sizes[best]->h;
+ *BitsPerPixel = SDL_closest_depths[table][b];
+ }
+ }
+ if ( ! supported ) {
+ SDL_SetError("No video mode large enough for %dx%d", *w, *h);
+ }
+ return(supported);
+}
+
+/* This should probably go somewhere else -- like SDL_surface.c */
+static void SDL_ClearSurface(SDL_Surface *surface)
+{
+ Uint32 black;
+
+ black = SDL_MapRGB(surface->format, 0, 0, 0);
+ SDL_FillRect(surface, NULL, black);
+ if ((surface->flags&SDL_HWSURFACE) && (surface->flags&SDL_DOUBLEBUF)) {
+ SDL_Flip(surface);
+ SDL_FillRect(surface, NULL, black);
+ }
+ if (surface->flags&SDL_FULLSCREEN) {
+ SDL_Flip(surface);
+ }
+}
+
+/*
+ * Create a shadow surface suitable for fooling the app. :-)
+ */
+static void SDL_CreateShadowSurface(int depth)
+{
+ Uint32 Rmask, Gmask, Bmask;
+
+ /* Allocate the shadow surface */
+ if ( depth == (SDL_VideoSurface->format)->BitsPerPixel ) {
+ Rmask = (SDL_VideoSurface->format)->Rmask;
+ Gmask = (SDL_VideoSurface->format)->Gmask;
+ Bmask = (SDL_VideoSurface->format)->Bmask;
+ } else {
+ Rmask = Gmask = Bmask = 0;
+ }
+ SDL_ShadowSurface = SDL_CreateRGBSurface(SDL_SWSURFACE,
+ SDL_VideoSurface->w, SDL_VideoSurface->h,
+ depth, Rmask, Gmask, Bmask, 0);
+ if ( SDL_ShadowSurface == NULL ) {
+ return;
+ }
+
+ /* 8-bit shadow surfaces report that they have exclusive palette */
+ if ( SDL_ShadowSurface->format->palette ) {
+ SDL_ShadowSurface->flags |= SDL_HWPALETTE;
+ if ( depth == (SDL_VideoSurface->format)->BitsPerPixel ) {
+ SDL_memcpy(SDL_ShadowSurface->format->palette->colors,
+ SDL_VideoSurface->format->palette->colors,
+ SDL_VideoSurface->format->palette->ncolors*
+ sizeof(SDL_Color));
+ } else {
+ SDL_DitherColors(
+ SDL_ShadowSurface->format->palette->colors, depth);
+ }
+ }
+
+ /* If the video surface is resizable, the shadow should say so */
+ if ( (SDL_VideoSurface->flags & SDL_RESIZABLE) == SDL_RESIZABLE ) {
+ SDL_ShadowSurface->flags |= SDL_RESIZABLE;
+ }
+ /* If the video surface has no frame, the shadow should say so */
+ if ( (SDL_VideoSurface->flags & SDL_NOFRAME) == SDL_NOFRAME ) {
+ SDL_ShadowSurface->flags |= SDL_NOFRAME;
+ }
+ /* If the video surface is fullscreen, the shadow should say so */
+ if ( (SDL_VideoSurface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
+ SDL_ShadowSurface->flags |= SDL_FULLSCREEN;
+ }
+ /* If the video surface is flippable, the shadow should say so */
+ if ( (SDL_VideoSurface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
+ SDL_ShadowSurface->flags |= SDL_DOUBLEBUF;
+ }
+ return;
+}
+
+#ifdef __QNXNTO__
+ #include <sys/neutrino.h>
+#endif /* __QNXNTO__ */
+
+#ifdef WIN32
+ extern int sysevents_mouse_pressed;
+#endif
+
+/*
+ * Set the requested video mode, allocating a shadow buffer if necessary.
+ */
+SDL_Surface * SDL_SetVideoMode (int width, int height, int bpp, Uint32 flags)
+{
+ SDL_VideoDevice *video, *this;
+ SDL_Surface *prev_mode, *mode;
+ int video_w;
+ int video_h;
+ int video_bpp;
+ int is_opengl;
+ SDL_GrabMode saved_grab;
+
+ #ifdef WIN32
+ sysevents_mouse_pressed = 0;
+ #endif
+
+ /* Start up the video driver, if necessary..
+ WARNING: This is the only function protected this way!
+ */
+ if ( ! current_video ) {
+ if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE) < 0 ) {
+ return(NULL);
+ }
+ }
+ this = video = current_video;
+
+ /* Default to the current width and height */
+ if ( width == 0 ) {
+ width = video->info.current_w;
+ }
+ if ( height == 0 ) {
+ height = video->info.current_h;
+ }
+ /* Default to the current video bpp */
+ if ( bpp == 0 ) {
+ flags |= SDL_ANYFORMAT;
+ bpp = SDL_VideoSurface->format->BitsPerPixel;
+ }
+
+ /* Get a good video mode, the closest one possible */
+ video_w = width;
+ video_h = height;
+ video_bpp = bpp;
+ if ( ! SDL_GetVideoMode(&video_w, &video_h, &video_bpp, flags) ) {
+ return(NULL);
+ }
+
+ /* Check the requested flags */
+ /* There's no palette in > 8 bits-per-pixel mode */
+ if ( video_bpp > 8 ) {
+ flags &= ~SDL_HWPALETTE;
+ }
+#if 0
+ if ( (flags&SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
+ /* There's no windowed double-buffering */
+ flags &= ~SDL_DOUBLEBUF;
+ }
+#endif
+ if ( (flags&SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
+ /* Use hardware surfaces when double-buffering */
+ flags |= SDL_HWSURFACE;
+ }
+
+ is_opengl = ( ( flags & SDL_OPENGL ) == SDL_OPENGL );
+ if ( is_opengl ) {
+ /* These flags are for 2D video modes only */
+ flags &= ~(SDL_HWSURFACE|SDL_DOUBLEBUF);
+ }
+
+ /* Reset the keyboard here so event callbacks can run */
+ SDL_ResetKeyboard();
+ SDL_ResetMouse();
+ SDL_SetMouseRange(width, height);
+ SDL_cursorstate &= ~CURSOR_USINGSW;
+
+ /* Clean up any previous video mode */
+ if ( SDL_PublicSurface != NULL ) {
+ SDL_PublicSurface = NULL;
+ }
+ if ( SDL_ShadowSurface != NULL ) {
+ SDL_Surface *ready_to_go;
+ ready_to_go = SDL_ShadowSurface;
+ SDL_ShadowSurface = NULL;
+ SDL_FreeSurface(ready_to_go);
+ }
+ if ( video->physpal ) {
+ SDL_free(video->physpal->colors);
+ SDL_free(video->physpal);
+ video->physpal = NULL;
+ }
+ if( video->gammacols) {
+ SDL_free(video->gammacols);
+ video->gammacols = NULL;
+ }
+
+ /* Save the previous grab state and turn off grab for mode switch */
+ saved_grab = SDL_WM_GrabInputOff();
+
+ /* Try to set the video mode, along with offset and clipping */
+ prev_mode = SDL_VideoSurface;
+ SDL_LockCursor();
+ SDL_VideoSurface = NULL; /* In case it's freed by driver */
+ mode = video->SetVideoMode(this, prev_mode,video_w,video_h,video_bpp,flags);
+ if ( mode ) { /* Prevent resize events from mode change */
+ /* But not on OS/2 */
+#ifndef __OS2__
+ SDL_PrivateResize(mode->w, mode->h);
+#endif
+
+ /* Sam - If we asked for OpenGL mode, and didn't get it, fail */
+ if ( is_opengl && !(mode->flags & SDL_OPENGL) ) {
+ mode = NULL;
+ SDL_SetError("OpenGL not available");
+ }
+ }
+ /*
+ * rcg11292000
+ * If you try to set an SDL_OPENGL surface, and fail to find a
+ * matching visual, then the next call to SDL_SetVideoMode()
+ * will segfault, since we no longer point to a dummy surface,
+ * but rather NULL.
+ * Sam 11/29/00
+ * WARNING, we need to make sure that the previous mode hasn't
+ * already been freed by the video driver. What do we do in
+ * that case? Should we call SDL_VideoInit() again?
+ */
+ SDL_VideoSurface = (mode != NULL) ? mode : prev_mode;
+
+ if ( (mode != NULL) && (!is_opengl) ) {
+ /* Sanity check */
+ if ( (mode->w < width) || (mode->h < height) ) {
+ SDL_SetError("Video mode smaller than requested");
+ return(NULL);
+ }
+
+ /* If we have a palettized surface, create a default palette */
+ if ( mode->format->palette ) {
+ SDL_PixelFormat *vf = mode->format;
+ SDL_DitherColors(vf->palette->colors, vf->BitsPerPixel);
+ video->SetColors(this, 0, vf->palette->ncolors,
+ vf->palette->colors);
+ }
+
+ /* Clear the surface to black */
+ video->offset_x = 0;
+ video->offset_y = 0;
+ mode->offset = 0;
+ SDL_SetClipRect(mode, NULL);
+ SDL_ClearSurface(mode);
+
+ /* Now adjust the offsets to match the desired mode */
+ video->offset_x = (mode->w-width)/2;
+ video->offset_y = (mode->h-height)/2;
+ mode->offset = video->offset_y*mode->pitch +
+ video->offset_x*mode->format->BytesPerPixel;
+#ifdef DEBUG_VIDEO
+ fprintf(stderr,
+ "Requested mode: %dx%dx%d, obtained mode %dx%dx%d (offset %d)\n",
+ width, height, bpp,
+ mode->w, mode->h, mode->format->BitsPerPixel, mode->offset);
+#endif
+ mode->w = width;
+ mode->h = height;
+ SDL_SetClipRect(mode, NULL);
+ }
+ SDL_ResetCursor();
+ SDL_UnlockCursor();
+
+ /* If we failed setting a video mode, return NULL... (Uh Oh!) */
+ if ( mode == NULL ) {
+ return(NULL);
+ }
+
+ /* If there is no window manager, set the SDL_NOFRAME flag */
+ if ( ! video->info.wm_available ) {
+ mode->flags |= SDL_NOFRAME;
+ }
+
+ /* Reset the mouse cursor and grab for new video mode */
+ SDL_SetCursor(NULL);
+ if ( video->UpdateMouse ) {
+ video->UpdateMouse(this);
+ }
+ SDL_WM_GrabInput(saved_grab);
+ SDL_GetRelativeMouseState(NULL, NULL); /* Clear first large delta */
+
+#if SDL_VIDEO_OPENGL
+ /* Load GL symbols (before MakeCurrent, where we need glGetString). */
+ if ( flags & (SDL_OPENGL | SDL_OPENGLBLIT) ) {
+
+#if defined(__QNXNTO__) && (_NTO_VERSION < 630)
+#define __SDL_NOGETPROCADDR__
+#elif defined(__MINT__)
+#define __SDL_NOGETPROCADDR__
+#endif
+#ifdef __SDL_NOGETPROCADDR__
+ #define SDL_PROC(ret,func,params) video->func=func;
+#else
+ #define SDL_PROC(ret,func,params) \
+ do { \
+ video->func = SDL_GL_GetProcAddress(#func); \
+ if ( ! video->func ) { \
+ SDL_SetError("Couldn't load GL function %s: %s\n", #func, SDL_GetError()); \
+ return(NULL); \
+ } \
+ } while ( 0 );
+
+#endif /* __SDL_NOGETPROCADDR__ */
+
+#include "SDL_glfuncs.h"
+#undef SDL_PROC
+ }
+#endif /* SDL_VIDEO_OPENGL */
+
+ /* If we're running OpenGL, make the context current */
+ if ( (video->screen->flags & SDL_OPENGL) &&
+ video->GL_MakeCurrent ) {
+ if ( video->GL_MakeCurrent(this) < 0 ) {
+ return(NULL);
+ }
+ }
+
+ /* Set up a fake SDL surface for OpenGL "blitting" */
+ if ( (flags & SDL_OPENGLBLIT) == SDL_OPENGLBLIT ) {
+ /* Load GL functions for performing the texture updates */
+#if SDL_VIDEO_OPENGL
+
+ /* Create a software surface for blitting */
+#ifdef GL_VERSION_1_2
+ /* If the implementation either supports the packed pixels
+ extension, or implements the core OpenGL 1.2 API, it will
+ support the GL_UNSIGNED_SHORT_5_6_5 texture format.
+ */
+ if ( (bpp == 16) &&
+ (SDL_strstr((const char *)video->glGetString(GL_EXTENSIONS), "GL_EXT_packed_pixels") ||
+ (SDL_atof((const char *)video->glGetString(GL_VERSION)) >= 1.2f))
+ ) {
+ video->is_32bit = 0;
+ SDL_VideoSurface = SDL_CreateRGBSurface(
+ flags,
+ width,
+ height,
+ 16,
+ 31 << 11,
+ 63 << 5,
+ 31,
+ 0
+ );
+ }
+ else
+#endif /* OpenGL 1.2 */
+ {
+ video->is_32bit = 1;
+ SDL_VideoSurface = SDL_CreateRGBSurface(
+ flags,
+ width,
+ height,
+ 32,
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+ 0x000000FF,
+ 0x0000FF00,
+ 0x00FF0000,
+ 0xFF000000
+#else
+ 0xFF000000,
+ 0x00FF0000,
+ 0x0000FF00,
+ 0x000000FF
+#endif
+ );
+ }
+ if ( ! SDL_VideoSurface ) {
+ return(NULL);
+ }
+ SDL_VideoSurface->flags = mode->flags | SDL_OPENGLBLIT;
+
+ /* Free the original video mode surface (is this safe?) */
+ SDL_FreeSurface(mode);
+
+ /* Set the surface completely opaque & white by default */
+ SDL_memset( SDL_VideoSurface->pixels, 255, SDL_VideoSurface->h * SDL_VideoSurface->pitch );
+ video->glGenTextures( 1, &video->texture );
+ video->glBindTexture( GL_TEXTURE_2D, video->texture );
+ video->glTexImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ video->is_32bit ? GL_RGBA : GL_RGB,
+ 256,
+ 256,
+ 0,
+ video->is_32bit ? GL_RGBA : GL_RGB,
+#ifdef GL_VERSION_1_2
+ video->is_32bit ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5,
+#else
+ GL_UNSIGNED_BYTE,
+#endif
+ NULL);
+
+ video->UpdateRects = SDL_GL_UpdateRectsLock;
+#else
+ SDL_SetError("Somebody forgot to #define SDL_VIDEO_OPENGL");
+ return(NULL);
+#endif
+ }
+
+ /* Create a shadow surface if necessary */
+ /* There are three conditions under which we create a shadow surface:
+ 1. We need a particular bits-per-pixel that we didn't get.
+ 2. We need a hardware palette and didn't get one.
+ 3. We need a software surface and got a hardware surface.
+ */
+ if ( !(SDL_VideoSurface->flags & SDL_OPENGL) &&
+ (
+ ( !(flags&SDL_ANYFORMAT) &&
+ (SDL_VideoSurface->format->BitsPerPixel != bpp)) ||
+ ( (flags&SDL_HWPALETTE) &&
+ !(SDL_VideoSurface->flags&SDL_HWPALETTE)) ||
+ /* If the surface is in hardware, video writes are visible
+ as soon as they are performed, so we need to buffer them
+ */
+ ( ((flags&SDL_HWSURFACE) == SDL_SWSURFACE) &&
+ (SDL_VideoSurface->flags&SDL_HWSURFACE)) ||
+ ( (flags&SDL_DOUBLEBUF) &&
+ (SDL_VideoSurface->flags&SDL_HWSURFACE) &&
+ !(SDL_VideoSurface->flags&SDL_DOUBLEBUF))
+ ) ) {
+ SDL_CreateShadowSurface(bpp);
+ if ( SDL_ShadowSurface == NULL ) {
+ SDL_SetError("Couldn't create shadow surface");
+ return(NULL);
+ }
+ SDL_PublicSurface = SDL_ShadowSurface;
+ } else {
+ SDL_PublicSurface = SDL_VideoSurface;
+ }
+ video->info.vfmt = SDL_VideoSurface->format;
+ video->info.current_w = SDL_VideoSurface->w;
+ video->info.current_h = SDL_VideoSurface->h;
+
+ /* We're done! */
+ return(SDL_PublicSurface);
+}
+
+/*
+ * Convert a surface into the video pixel format.
+ */
+SDL_Surface * SDL_DisplayFormat (SDL_Surface *surface)
+{
+ Uint32 flags;
+
+ if ( ! SDL_PublicSurface ) {
+ SDL_SetError("No video mode has been set");
+ return(NULL);
+ }
+ /* Set the flags appropriate for copying to display surface */
+ if (((SDL_PublicSurface->flags&SDL_HWSURFACE) == SDL_HWSURFACE) && current_video->info.blit_hw)
+ flags = SDL_HWSURFACE;
+ else
+ flags = SDL_SWSURFACE;
+#ifdef AUTORLE_DISPLAYFORMAT
+ flags |= (surface->flags & (SDL_SRCCOLORKEY|SDL_SRCALPHA));
+ flags |= SDL_RLEACCELOK;
+#else
+ flags |= surface->flags & (SDL_SRCCOLORKEY|SDL_SRCALPHA|SDL_RLEACCELOK);
+#endif
+ return(SDL_ConvertSurface(surface, SDL_PublicSurface->format, flags));
+}
+
+/*
+ * Convert a surface into a format that's suitable for blitting to
+ * the screen, but including an alpha channel.
+ */
+SDL_Surface *SDL_DisplayFormatAlpha(SDL_Surface *surface)
+{
+ SDL_PixelFormat *vf;
+ SDL_PixelFormat *format;
+ SDL_Surface *converted;
+ Uint32 flags;
+ /* default to ARGB8888 */
+ Uint32 amask = 0xff000000;
+ Uint32 rmask = 0x00ff0000;
+ Uint32 gmask = 0x0000ff00;
+ Uint32 bmask = 0x000000ff;
+
+ if ( ! SDL_PublicSurface ) {
+ SDL_SetError("No video mode has been set");
+ return(NULL);
+ }
+ vf = SDL_PublicSurface->format;
+
+ switch(vf->BytesPerPixel) {
+ case 2:
+ /* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}.
+ For anything else (like ARGB4444) it doesn't matter
+ since we have no special code for it anyway */
+ if ( (vf->Rmask == 0x1f) &&
+ (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) {
+ rmask = 0xff;
+ bmask = 0xff0000;
+ }
+ break;
+
+ case 3:
+ case 4:
+ /* Keep the video format, as long as the high 8 bits are
+ unused or alpha */
+ if ( (vf->Rmask == 0xff) && (vf->Bmask == 0xff0000) ) {
+ rmask = 0xff;
+ bmask = 0xff0000;
+ } else if ( vf->Rmask == 0xFF00 && (vf->Bmask == 0xFF000000) ) {
+ amask = 0x000000FF;
+ rmask = 0x0000FF00;
+ gmask = 0x00FF0000;
+ bmask = 0xFF000000;
+ }
+ break;
+
+ default:
+ /* We have no other optimised formats right now. When/if a new
+ optimised alpha format is written, add the converter here */
+ break;
+ }
+ format = SDL_AllocFormat(32, rmask, gmask, bmask, amask);
+ flags = SDL_PublicSurface->flags & SDL_HWSURFACE;
+ flags |= surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK);
+ converted = SDL_ConvertSurface(surface, format, flags);
+ SDL_FreeFormat(format);
+ return(converted);
+}
+
+/*
+ * Update a specific portion of the physical screen
+ */
+void SDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
+{
+ if ( screen ) {
+ SDL_Rect rect;
+
+ /* Perform some checking */
+ if ( w == 0 )
+ w = screen->w;
+ if ( h == 0 )
+ h = screen->h;
+ if ( (int)(x+w) > screen->w )
+ return;
+ if ( (int)(y+h) > screen->h )
+ return;
+
+ /* Fill the rectangle */
+ rect.x = (Sint16)x;
+ rect.y = (Sint16)y;
+ rect.w = (Uint16)w;
+ rect.h = (Uint16)h;
+ SDL_UpdateRects(screen, 1, &rect);
+ }
+}
+void SDL_UpdateRects (SDL_Surface *screen, int numrects, SDL_Rect *rects)
+{
+ int i;
+ SDL_VideoDevice *video = current_video;
+ SDL_VideoDevice *this = current_video;
+
+ if ( (screen->flags & (SDL_OPENGL | SDL_OPENGLBLIT)) == SDL_OPENGL ) {
+ SDL_SetError("OpenGL active, use SDL_GL_SwapBuffers()");
+ return;
+ }
+ if ( screen == SDL_ShadowSurface ) {
+ /* Blit the shadow surface using saved mapping */
+ SDL_Palette *pal = screen->format->palette;
+ SDL_Color *saved_colors = NULL;
+ if ( pal && !(SDL_VideoSurface->flags & SDL_HWPALETTE) ) {
+ /* simulated 8bpp, use correct physical palette */
+ saved_colors = pal->colors;
+ if ( video->gammacols ) {
+ /* gamma-corrected palette */
+ pal->colors = video->gammacols;
+ } else if ( video->physpal ) {
+ /* physical palette different from logical */
+ pal->colors = video->physpal->colors;
+ }
+ }
+ if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) {
+ SDL_LockCursor();
+ SDL_DrawCursor(SDL_ShadowSurface);
+ for ( i=0; i<numrects; ++i ) {
+ SDL_LowerBlit(SDL_ShadowSurface, &rects[i],
+ SDL_VideoSurface, &rects[i]);
+ }
+ SDL_EraseCursor(SDL_ShadowSurface);
+ SDL_UnlockCursor();
+ } else {
+ for ( i=0; i<numrects; ++i ) {
+ SDL_LowerBlit(SDL_ShadowSurface, &rects[i],
+ SDL_VideoSurface, &rects[i]);
+ }
+ }
+ if ( saved_colors ) {
+ pal->colors = saved_colors;
+ }
+
+ /* Fall through to video surface update */
+ screen = SDL_VideoSurface;
+ }
+ if ( screen == SDL_VideoSurface ) {
+ /* Update the video surface */
+ if ( screen->offset ) {
+ for ( i=0; i<numrects; ++i ) {
+ rects[i].x += video->offset_x;
+ rects[i].y += video->offset_y;
+ }
+ video->UpdateRects(this, numrects, rects);
+ for ( i=0; i<numrects; ++i ) {
+ rects[i].x -= video->offset_x;
+ rects[i].y -= video->offset_y;
+ }
+ } else {
+ video->UpdateRects(this, numrects, rects);
+ }
+ }
+}
+
+/*
+ * Performs hardware double buffering, if possible, or a full update if not.
+ */
+int SDL_Flip(SDL_Surface *screen)
+{
+ SDL_VideoDevice *video = current_video;
+ /* Copy the shadow surface to the video surface */
+ if ( screen == SDL_ShadowSurface ) {
+ SDL_Rect rect;
+ SDL_Palette *pal = screen->format->palette;
+ SDL_Color *saved_colors = NULL;
+ if ( pal && !(SDL_VideoSurface->flags & SDL_HWPALETTE) ) {
+ /* simulated 8bpp, use correct physical palette */
+ saved_colors = pal->colors;
+ if ( video->gammacols ) {
+ /* gamma-corrected palette */
+ pal->colors = video->gammacols;
+ } else if ( video->physpal ) {
+ /* physical palette different from logical */
+ pal->colors = video->physpal->colors;
+ }
+ }
+
+ rect.x = 0;
+ rect.y = 0;
+ rect.w = screen->w;
+ rect.h = screen->h;
+ if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) {
+ SDL_LockCursor();
+ SDL_DrawCursor(SDL_ShadowSurface);
+ SDL_LowerBlit(SDL_ShadowSurface, &rect,
+ SDL_VideoSurface, &rect);
+ SDL_EraseCursor(SDL_ShadowSurface);
+ SDL_UnlockCursor();
+ } else {
+ SDL_LowerBlit(SDL_ShadowSurface, &rect,
+ SDL_VideoSurface, &rect);
+ }
+ if ( saved_colors ) {
+ pal->colors = saved_colors;
+ }
+
+ /* Fall through to video surface update */
+ screen = SDL_VideoSurface;
+ }
+ if ( (screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
+ SDL_VideoDevice *this = current_video;
+ return(video->FlipHWSurface(this, SDL_VideoSurface));
+ } else {
+ SDL_UpdateRect(screen, 0, 0, 0, 0);
+ }
+ return(0);
+}
+
+static void SetPalette_logical(SDL_Surface *screen, SDL_Color *colors,
+ int firstcolor, int ncolors)
+{
+ SDL_Palette *pal = screen->format->palette;
+ SDL_Palette *vidpal;
+
+ if ( colors != (pal->colors + firstcolor) ) {
+ SDL_memcpy(pal->colors + firstcolor, colors,
+ ncolors * sizeof(*colors));
+ }
+
+ if ( current_video && SDL_VideoSurface ) {
+ vidpal = SDL_VideoSurface->format->palette;
+ if ( (screen == SDL_ShadowSurface) && vidpal ) {
+ /*
+ * This is a shadow surface, and the physical
+ * framebuffer is also indexed. Propagate the
+ * changes to its logical palette so that
+ * updates are always identity blits
+ */
+ SDL_memcpy(vidpal->colors + firstcolor, colors,
+ ncolors * sizeof(*colors));
+ }
+ }
+ SDL_FormatChanged(screen);
+}
+
+static int SetPalette_physical(SDL_Surface *screen,
+ SDL_Color *colors, int firstcolor, int ncolors)
+{
+ SDL_VideoDevice *video = current_video;
+ int gotall = 1;
+
+ if ( video->physpal ) {
+ /* We need to copy the new colors, since we haven't
+ * already done the copy in the logical set above.
+ */
+ SDL_memcpy(video->physpal->colors + firstcolor,
+ colors, ncolors * sizeof(*colors));
+ }
+ if ( screen == SDL_ShadowSurface ) {
+ if ( SDL_VideoSurface->flags & SDL_HWPALETTE ) {
+ /*
+ * The real screen is also indexed - set its physical
+ * palette. The physical palette does not include the
+ * gamma modification, we apply it directly instead,
+ * but this only happens if we have hardware palette.
+ */
+ screen = SDL_VideoSurface;
+ } else {
+ /*
+ * The video surface is not indexed - invalidate any
+ * active shadow-to-video blit mappings.
+ */
+ if ( screen->map->dst == SDL_VideoSurface ) {
+ SDL_InvalidateMap(screen->map);
+ }
+ if ( video->gamma ) {
+ if( ! video->gammacols ) {
+ SDL_Palette *pp = video->physpal;
+ if(!pp)
+ pp = screen->format->palette;
+ video->gammacols = SDL_malloc(pp->ncolors
+ * sizeof(SDL_Color));
+ SDL_ApplyGamma(video->gamma,
+ pp->colors,
+ video->gammacols,
+ pp->ncolors);
+ } else {
+ SDL_ApplyGamma(video->gamma, colors,
+ video->gammacols
+ + firstcolor,
+ ncolors);
+ }
+ }
+ SDL_UpdateRect(screen, 0, 0, 0, 0);
+ }
+ }
+
+ if ( screen == SDL_VideoSurface ) {
+ SDL_Color gcolors[256];
+
+ if ( video->gamma ) {
+ SDL_ApplyGamma(video->gamma, colors, gcolors, ncolors);
+ colors = gcolors;
+ }
+ gotall = video->SetColors(video, firstcolor, ncolors, colors);
+ if ( ! gotall ) {
+ /* The video flags shouldn't have SDL_HWPALETTE, and
+ the video driver is responsible for copying back the
+ correct colors into the video surface palette.
+ */
+ ;
+ }
+ SDL_CursorPaletteChanged();
+ }
+ return gotall;
+}
+
+/*
+ * Set the physical and/or logical colormap of a surface:
+ * Only the screen has a physical colormap. It determines what is actually
+ * sent to the display.
+ * The logical colormap is used to map blits to/from the surface.
+ * 'which' is one or both of SDL_LOGPAL, SDL_PHYSPAL
+ *
+ * Return nonzero if all colours were set as requested, or 0 otherwise.
+ */
+int SDL_SetPalette(SDL_Surface *screen, int which,
+ SDL_Color *colors, int firstcolor, int ncolors)
+{
+ SDL_Palette *pal;
+ int gotall;
+ int palsize;
+
+ if ( !screen ) {
+ return 0;
+ }
+ if ( !current_video || screen != SDL_PublicSurface ) {
+ /* only screens have physical palettes */
+ which &= ~SDL_PHYSPAL;
+ } else if ( (screen->flags & SDL_HWPALETTE) != SDL_HWPALETTE ) {
+ /* hardware palettes required for split colormaps */
+ which |= SDL_PHYSPAL | SDL_LOGPAL;
+ }
+
+ /* Verify the parameters */
+ pal = screen->format->palette;
+ if( !pal ) {
+ return 0; /* not a palettized surface */
+ }
+ gotall = 1;
+ palsize = 1 << screen->format->BitsPerPixel;
+ if ( ncolors > (palsize - firstcolor) ) {
+ ncolors = (palsize - firstcolor);
+ gotall = 0;
+ }
+
+ if ( which & SDL_LOGPAL ) {
+ /*
+ * Logical palette change: The actual screen isn't affected,
+ * but the internal colormap is altered so that the
+ * interpretation of the pixel values (for blits etc) is
+ * changed.
+ */
+ SetPalette_logical(screen, colors, firstcolor, ncolors);
+ }
+ if ( which & SDL_PHYSPAL ) {
+ SDL_VideoDevice *video = current_video;
+ /*
+ * Physical palette change: This doesn't affect the
+ * program's idea of what the screen looks like, but changes
+ * its actual appearance.
+ */
+ if ( !video->physpal && !(which & SDL_LOGPAL) ) {
+ /* Lazy physical palette allocation */
+ int size;
+ SDL_Palette *pp = SDL_malloc(sizeof(*pp));
+ if ( !pp ) {
+ return 0;
+ }
+ video->physpal = pp;
+ pp->ncolors = pal->ncolors;
+ size = pp->ncolors * sizeof(SDL_Color);
+ pp->colors = SDL_malloc(size);
+ if ( !pp->colors ) {
+ return 0;
+ }
+ SDL_memcpy(pp->colors, pal->colors, size);
+ }
+ if ( ! SetPalette_physical(screen,
+ colors, firstcolor, ncolors) ) {
+ gotall = 0;
+ }
+ }
+ return gotall;
+}
+
+int SDL_SetColors(SDL_Surface *screen, SDL_Color *colors, int firstcolor,
+ int ncolors)
+{
+ return SDL_SetPalette(screen, SDL_LOGPAL | SDL_PHYSPAL,
+ colors, firstcolor, ncolors);
+}
+
+/*
+ * Clean up the video subsystem
+ */
+void SDL_VideoQuit (void)
+{
+ SDL_Surface *ready_to_go;
+
+ if ( current_video ) {
+ SDL_VideoDevice *video = current_video;
+ SDL_VideoDevice *this = current_video;
+
+ /* Halt event processing before doing anything else */
+ SDL_StopEventLoop();
+
+ /* Clean up allocated window manager items */
+ if ( SDL_PublicSurface ) {
+ SDL_PublicSurface = NULL;
+ }
+ SDL_CursorQuit();
+
+ /* Just in case... */
+ SDL_WM_GrabInputOff();
+
+ /* Clean up the system video */
+ video->VideoQuit(this);
+
+ /* Free any lingering surfaces */
+ ready_to_go = SDL_ShadowSurface;
+ SDL_ShadowSurface = NULL;
+ SDL_FreeSurface(ready_to_go);
+ if ( SDL_VideoSurface != NULL ) {
+ ready_to_go = SDL_VideoSurface;
+ SDL_VideoSurface = NULL;
+ SDL_FreeSurface(ready_to_go);
+ }
+ SDL_PublicSurface = NULL;
+
+ /* Clean up miscellaneous memory */
+ if ( video->physpal ) {
+ SDL_free(video->physpal->colors);
+ SDL_free(video->physpal);
+ video->physpal = NULL;
+ }
+ if ( video->gammacols ) {
+ SDL_free(video->gammacols);
+ video->gammacols = NULL;
+ }
+ if ( video->gamma ) {
+ SDL_free(video->gamma);
+ video->gamma = NULL;
+ }
+ if ( video->wm_title != NULL ) {
+ SDL_free(video->wm_title);
+ video->wm_title = NULL;
+ }
+ if ( video->wm_icon != NULL ) {
+ SDL_free(video->wm_icon);
+ video->wm_icon = NULL;
+ }
+
+ /* Finish cleaning up video subsystem */
+ video->free(this);
+ current_video = NULL;
+ }
+ return;
+}
+
+/* Load the GL driver library */
+int SDL_GL_LoadLibrary(const char *path)
+{
+ SDL_VideoDevice *video = current_video;
+ SDL_VideoDevice *this = current_video;
+ int retval;
+
+ retval = -1;
+ if ( video == NULL ) {
+ SDL_SetError("Video subsystem has not been initialized");
+ } else {
+ if ( video->GL_LoadLibrary ) {
+ retval = video->GL_LoadLibrary(this, path);
+ } else {
+ SDL_SetError("No dynamic GL support in video driver");
+ }
+ }
+ return(retval);
+}
+
+void *SDL_GL_GetProcAddress(const char* proc)
+{
+ SDL_VideoDevice *video = current_video;
+ SDL_VideoDevice *this = current_video;
+ void *func;
+
+ func = NULL;
+ if ( video->GL_GetProcAddress ) {
+ if ( video->gl_config.driver_loaded ) {
+ func = video->GL_GetProcAddress(this, proc);
+ } else {
+ SDL_SetError("No GL driver has been loaded");
+ }
+ } else {
+ SDL_SetError("No dynamic GL support in video driver");
+ }
+ return func;
+}
+
+/* Set the specified GL attribute for setting up a GL video mode */
+int SDL_GL_SetAttribute( SDL_GLattr attr, int value )
+{
+ int retval;
+ SDL_VideoDevice *video = current_video;
+
+ retval = 0;
+ switch (attr) {
+ case SDL_GL_RED_SIZE:
+ video->gl_config.red_size = value;
+ break;
+ case SDL_GL_GREEN_SIZE:
+ video->gl_config.green_size = value;
+ break;
+ case SDL_GL_BLUE_SIZE:
+ video->gl_config.blue_size = value;
+ break;
+ case SDL_GL_ALPHA_SIZE:
+ video->gl_config.alpha_size = value;
+ break;
+ case SDL_GL_DOUBLEBUFFER:
+ video->gl_config.double_buffer = value;
+ break;
+ case SDL_GL_BUFFER_SIZE:
+ video->gl_config.buffer_size = value;
+ break;
+ case SDL_GL_DEPTH_SIZE:
+ video->gl_config.depth_size = value;
+ break;
+ case SDL_GL_STENCIL_SIZE:
+ video->gl_config.stencil_size = value;
+ break;
+ case SDL_GL_ACCUM_RED_SIZE:
+ video->gl_config.accum_red_size = value;
+ break;
+ case SDL_GL_ACCUM_GREEN_SIZE:
+ video->gl_config.accum_green_size = value;
+ break;
+ case SDL_GL_ACCUM_BLUE_SIZE:
+ video->gl_config.accum_blue_size = value;
+ break;
+ case SDL_GL_ACCUM_ALPHA_SIZE:
+ video->gl_config.accum_alpha_size = value;
+ break;
+ case SDL_GL_STEREO:
+ video->gl_config.stereo = value;
+ break;
+ case SDL_GL_MULTISAMPLEBUFFERS:
+ video->gl_config.multisamplebuffers = value;
+ break;
+ case SDL_GL_MULTISAMPLESAMPLES:
+ video->gl_config.multisamplesamples = value;
+ break;
+ case SDL_GL_ACCELERATED_VISUAL:
+ video->gl_config.accelerated = value;
+ break;
+ case SDL_GL_SWAP_CONTROL:
+ video->gl_config.swap_control = value;
+ break;
+ default:
+ SDL_SetError("Unknown OpenGL attribute");
+ retval = -1;
+ break;
+ }
+ return(retval);
+}
+
+/* Retrieve an attribute value from the windowing system. */
+int SDL_GL_GetAttribute(SDL_GLattr attr, int* value)
+{
+ int retval = -1;
+ SDL_VideoDevice* video = current_video;
+ SDL_VideoDevice* this = current_video;
+
+ if ( video->GL_GetAttribute ) {
+ retval = this->GL_GetAttribute(this, attr, value);
+ } else {
+ *value = 0;
+ SDL_SetError("GL_GetAttribute not supported");
+ }
+ return retval;
+}
+
+/* Perform a GL buffer swap on the current GL context */
+void SDL_GL_SwapBuffers(void)
+{
+ SDL_VideoDevice *video = current_video;
+ SDL_VideoDevice *this = current_video;
+
+ if ( video->screen->flags & SDL_OPENGL ) {
+ video->GL_SwapBuffers(this);
+ } else {
+ SDL_SetError("OpenGL video mode has not been set");
+ }
+}
+
+/* Update rects with locking */
+void SDL_GL_UpdateRectsLock(SDL_VideoDevice* this, int numrects, SDL_Rect *rects)
+{
+ SDL_GL_Lock();
+ SDL_GL_UpdateRects(numrects, rects);
+ SDL_GL_Unlock();
+}
+
+/* Update rects without state setting and changing (the caller is responsible for it) */
+void SDL_GL_UpdateRects(int numrects, SDL_Rect *rects)
+{
+#if SDL_VIDEO_OPENGL
+ SDL_VideoDevice *this = current_video;
+ SDL_Rect update, tmp;
+ int x, y, i;
+
+ for ( i = 0; i < numrects; i++ )
+ {
+ tmp.y = rects[i].y;
+ tmp.h = rects[i].h;
+ for ( y = 0; y <= rects[i].h / 256; y++ )
+ {
+ tmp.x = rects[i].x;
+ tmp.w = rects[i].w;
+ for ( x = 0; x <= rects[i].w / 256; x++ )
+ {
+ update.x = tmp.x;
+ update.y = tmp.y;
+ update.w = tmp.w;
+ update.h = tmp.h;
+
+ if ( update.w > 256 )
+ update.w = 256;
+
+ if ( update.h > 256 )
+ update.h = 256;
+
+ this->glFlush();
+ this->glTexSubImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ 0,
+ 0,
+ update.w,
+ update.h,
+ this->is_32bit? GL_RGBA : GL_RGB,
+#ifdef GL_VERSION_1_2
+ this->is_32bit ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5,
+#else
+ GL_UNSIGNED_BYTE,
+#endif
+ (Uint8 *)this->screen->pixels +
+ this->screen->format->BytesPerPixel * update.x +
+ update.y * this->screen->pitch );
+
+ this->glFlush();
+ /*
+ * Note the parens around the function name:
+ * This is because some OpenGL implementations define glTexCoord etc
+ * as macros, and we don't want them expanded here.
+ */
+ this->glBegin(GL_TRIANGLE_STRIP);
+ (this->glTexCoord2f)( 0.0, 0.0 );
+ (this->glVertex2i)( update.x, update.y );
+ (this->glTexCoord2f)( (float)(update.w / 256.0), 0.0 );
+ (this->glVertex2i)( update.x + update.w, update.y );
+ (this->glTexCoord2f)( 0.0, (float)(update.h / 256.0) );
+ (this->glVertex2i)( update.x, update.y + update.h );
+ (this->glTexCoord2f)( (float)(update.w / 256.0), (float)(update.h / 256.0) );
+ (this->glVertex2i)( update.x + update.w , update.y + update.h );
+ this->glEnd();
+
+ tmp.x += 256;
+ tmp.w -= 256;
+ }
+ tmp.y += 256;
+ tmp.h -= 256;
+ }
+ }
+#endif
+}
+
+/* Lock == save current state */
+void SDL_GL_Lock()
+{
+#if SDL_VIDEO_OPENGL
+ lock_count--;
+ if (lock_count==-1)
+ {
+ SDL_VideoDevice *this = current_video;
+
+ this->glPushAttrib( GL_ALL_ATTRIB_BITS ); /* TODO: narrow range of what is saved */
+#ifdef GL_CLIENT_PIXEL_STORE_BIT
+ this->glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
+#endif
+
+ this->glEnable(GL_TEXTURE_2D);
+ this->glEnable(GL_BLEND);
+ this->glDisable(GL_FOG);
+ this->glDisable(GL_ALPHA_TEST);
+ this->glDisable(GL_DEPTH_TEST);
+ this->glDisable(GL_SCISSOR_TEST);
+ this->glDisable(GL_STENCIL_TEST);
+ this->glDisable(GL_CULL_FACE);
+
+ this->glBindTexture( GL_TEXTURE_2D, this->texture );
+ this->glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+ this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+ this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+ this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+ this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+
+ this->glPixelStorei( GL_UNPACK_ROW_LENGTH, this->screen->pitch / this->screen->format->BytesPerPixel );
+ this->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ (this->glColor4f)(1.0, 1.0, 1.0, 1.0); /* Solaris workaround */
+
+ this->glViewport(0, 0, this->screen->w, this->screen->h);
+ this->glMatrixMode(GL_PROJECTION);
+ this->glPushMatrix();
+ this->glLoadIdentity();
+
+ this->glOrtho(0.0, (GLdouble) this->screen->w, (GLdouble) this->screen->h, 0.0, 0.0, 1.0);
+
+ this->glMatrixMode(GL_MODELVIEW);
+ this->glPushMatrix();
+ this->glLoadIdentity();
+ }
+#endif
+}
+
+/* Unlock == restore saved state */
+void SDL_GL_Unlock()
+{
+#if SDL_VIDEO_OPENGL
+ lock_count++;
+ if (lock_count==0)
+ {
+ SDL_VideoDevice *this = current_video;
+
+ this->glPopMatrix();
+ this->glMatrixMode(GL_PROJECTION);
+ this->glPopMatrix();
+
+ this->glPopClientAttrib();
+ this->glPopAttrib();
+ }
+#endif
+}
+
+#if SDL_AUDIO_DRIVER_PULSE
+void SDL_Audio_SetCaption(const char *caption);
+#endif
+
+/*
+ * Sets/Gets the title and icon text of the display window, if any.
+ */
+void SDL_WM_SetCaption (const char *title, const char *icon)
+{
+ SDL_VideoDevice *video = current_video;
+ SDL_VideoDevice *this = current_video;
+
+ if ( video ) {
+ if ( title ) {
+ if ( video->wm_title ) {
+ SDL_free(video->wm_title);
+ }
+ video->wm_title = SDL_strdup(title);
+ }
+ if ( icon ) {
+ if ( video->wm_icon ) {
+ SDL_free(video->wm_icon);
+ }
+ video->wm_icon = SDL_strdup(icon);
+ }
+ if ( (title || icon) && (video->SetCaption != NULL) ) {
+ video->SetCaption(this, video->wm_title,video->wm_icon);
+ }
+ }
+
+#if SDL_AUDIO_DRIVER_PULSE
+ /* PulseAudio can make use of this information. */
+ SDL_Audio_SetCaption(title);
+#endif
+}
+
+void SDL_WM_GetCaption (char **title, char **icon)
+{
+ SDL_VideoDevice *video = current_video;
+
+ if ( video ) {
+ if ( title ) {
+ *title = video->wm_title;
+ }
+ if ( icon ) {
+ *icon = video->wm_icon;
+ }
+ }
+}
+
+/* Utility function used by SDL_WM_SetIcon();
+ * flags & 1 for color key, flags & 2 for alpha channel. */
+static void CreateMaskFromColorKeyOrAlpha(SDL_Surface *icon, Uint8 *mask, int flags)
+{
+ int x, y;
+ Uint32 colorkey;
+#define SET_MASKBIT(icon, x, y, mask) \
+ mask[(y*((icon->w+7)/8))+(x/8)] &= ~(0x01<<(7-(x%8)))
+
+ colorkey = icon->format->colorkey;
+ switch (icon->format->BytesPerPixel) {
+ case 1: { Uint8 *pixels;
+ for ( y=0; y<icon->h; ++y ) {
+ pixels = (Uint8 *)icon->pixels + y*icon->pitch;
+ for ( x=0; x<icon->w; ++x ) {
+ if ( *pixels++ == colorkey ) {
+ SET_MASKBIT(icon, x, y, mask);
+ }
+ }
+ }
+ }
+ break;
+
+ case 2: { Uint16 *pixels;
+ for ( y=0; y<icon->h; ++y ) {
+ pixels = (Uint16 *)icon->pixels +
+ y*icon->pitch/2;
+ for ( x=0; x<icon->w; ++x ) {
+ if ( (flags & 1) && *pixels == colorkey ) {
+ SET_MASKBIT(icon, x, y, mask);
+ } else if((flags & 2) && (*pixels & icon->format->Amask) == 0) {
+ SET_MASKBIT(icon, x, y, mask);
+ }
+ pixels++;
+ }
+ }
+ }
+ break;
+
+ case 4: { Uint32 *pixels;
+ for ( y=0; y<icon->h; ++y ) {
+ pixels = (Uint32 *)icon->pixels +
+ y*icon->pitch/4;
+ for ( x=0; x<icon->w; ++x ) {
+ if ( (flags & 1) && *pixels == colorkey ) {
+ SET_MASKBIT(icon, x, y, mask);
+ } else if((flags & 2) && (*pixels & icon->format->Amask) == 0) {
+ SET_MASKBIT(icon, x, y, mask);
+ }
+ pixels++;
+ }
+ }
+ }
+ break;
+ }
+}
+
+/*
+ * Sets the window manager icon for the display window.
+ */
+void SDL_WM_SetIcon (SDL_Surface *icon, Uint8 *mask)
+{
+ SDL_VideoDevice *video = current_video;
+ SDL_VideoDevice *this = current_video;
+
+ if ( icon && video->SetIcon ) {
+ /* Generate a mask if necessary, and create the icon! */
+ if ( mask == NULL ) {
+ int mask_len = icon->h*(icon->w+7)/8;
+ int flags = 0;
+ mask = (Uint8 *)SDL_malloc(mask_len);
+ if ( mask == NULL ) {
+ return;
+ }
+ SDL_memset(mask, ~0, mask_len);
+ if ( icon->flags & SDL_SRCCOLORKEY ) flags |= 1;
+ if ( icon->flags & SDL_SRCALPHA ) flags |= 2;
+ if( flags ) {
+ CreateMaskFromColorKeyOrAlpha(icon, mask, flags);
+ }
+ video->SetIcon(video, icon, mask);
+ SDL_free(mask);
+ } else {
+ video->SetIcon(this, icon, mask);
+ }
+ }
+}
+
+/*
+ * Grab or ungrab the keyboard and mouse input.
+ * This function returns the final grab mode after calling the
+ * driver dependent function.
+ */
+static SDL_GrabMode SDL_WM_GrabInputRaw(SDL_GrabMode mode)
+{
+ SDL_VideoDevice *video = current_video;
+ SDL_VideoDevice *this = current_video;
+
+ /* Only do something if we have support for grabs */
+ if ( video->GrabInput == NULL ) {
+ return(video->input_grab);
+ }
+
+ /* If the final grab mode if off, only then do we actually grab */
+#ifdef DEBUG_GRAB
+ printf("SDL_WM_GrabInputRaw(%d) ... ", mode);
+#endif
+ if ( mode == SDL_GRAB_OFF ) {
+ if ( video->input_grab != SDL_GRAB_OFF ) {
+ mode = video->GrabInput(this, mode);
+ }
+ } else {
+ if ( video->input_grab == SDL_GRAB_OFF ) {
+ mode = video->GrabInput(this, mode);
+ }
+ }
+ if ( mode != video->input_grab ) {
+ video->input_grab = mode;
+ if ( video->CheckMouseMode ) {
+ video->CheckMouseMode(this);
+ }
+ }
+#ifdef DEBUG_GRAB
+ printf("Final mode %d\n", video->input_grab);
+#endif
+
+ /* Return the final grab state */
+ if ( mode >= SDL_GRAB_FULLSCREEN ) {
+ mode -= SDL_GRAB_FULLSCREEN;
+ }
+ return(mode);
+}
+SDL_GrabMode SDL_WM_GrabInput(SDL_GrabMode mode)
+{
+ SDL_VideoDevice *video = current_video;
+
+ /* If the video isn't initialized yet, we can't do anything */
+ if ( ! video ) {
+ return SDL_GRAB_OFF;
+ }
+
+ /* Return the current mode on query */
+ if ( mode == SDL_GRAB_QUERY ) {
+ mode = video->input_grab;
+ if ( mode >= SDL_GRAB_FULLSCREEN ) {
+ mode -= SDL_GRAB_FULLSCREEN;
+ }
+ return(mode);
+ }
+
+#ifdef DEBUG_GRAB
+ printf("SDL_WM_GrabInput(%d) ... ", mode);
+#endif
+ /* If the video surface is fullscreen, we always grab */
+ if ( mode >= SDL_GRAB_FULLSCREEN ) {
+ mode -= SDL_GRAB_FULLSCREEN;
+ }
+ if ( SDL_VideoSurface && (SDL_VideoSurface->flags & SDL_FULLSCREEN) ) {
+ mode += SDL_GRAB_FULLSCREEN;
+ }
+ return(SDL_WM_GrabInputRaw(mode));
+}
+static SDL_GrabMode SDL_WM_GrabInputOff(void)
+{
+ SDL_GrabMode mode;
+
+ /* First query the current grab state */
+ mode = SDL_WM_GrabInput(SDL_GRAB_QUERY);
+
+ /* Now explicitly turn off input grab */
+ SDL_WM_GrabInputRaw(SDL_GRAB_OFF);
+
+ /* Return the old state */
+ return(mode);
+}
+
+/*
+ * Iconify the window in window managed environments.
+ * A successful iconification will result in an SDL_APPACTIVE loss event.
+ */
+int SDL_WM_IconifyWindow(void)
+{
+ SDL_VideoDevice *video = current_video;
+ SDL_VideoDevice *this = current_video;
+ int retval;
+
+ retval = 0;
+ if ( video->IconifyWindow ) {
+ retval = video->IconifyWindow(this);
+ }
+ return(retval);
+}
+
+/*
+ * Toggle fullscreen mode
+ */
+int SDL_WM_ToggleFullScreen(SDL_Surface *surface)
+{
+ SDL_VideoDevice *video = current_video;
+ SDL_VideoDevice *this = current_video;
+ int toggled;
+
+ toggled = 0;
+ if ( SDL_PublicSurface && (surface == SDL_PublicSurface) &&
+ video->ToggleFullScreen ) {
+ if ( surface->flags & SDL_FULLSCREEN ) {
+ toggled = video->ToggleFullScreen(this, 0);
+ if ( toggled ) {
+ SDL_VideoSurface->flags &= ~SDL_FULLSCREEN;
+ SDL_PublicSurface->flags &= ~SDL_FULLSCREEN;
+ }
+ } else {
+ toggled = video->ToggleFullScreen(this, 1);
+ if ( toggled ) {
+ SDL_VideoSurface->flags |= SDL_FULLSCREEN;
+ SDL_PublicSurface->flags |= SDL_FULLSCREEN;
+ }
+ }
+ /* Double-check the grab state inside SDL_WM_GrabInput() */
+ if ( toggled ) {
+ SDL_WM_GrabInput(video->input_grab);
+ }
+ }
+ return(toggled);
+}
+
+/*
+ * Set window position
+ */
+void SDL_WM_SetPos(int x, int y)
+{
+ SDL_VideoDevice* video = current_video;
+
+ if (video && video->SetWindowPos)
+ video->SetWindowPos(video, x, y);
+}
+
+/*
+ * Get window position
+ */
+void SDL_WM_GetPos(int *px, int *py)
+{
+ SDL_VideoDevice* video = current_video;
+
+ if (video && video->GetWindowPos)
+ video->GetWindowPos(video, px, py);
+ else {
+ *px = 100;
+ *py = 100;
+ }
+}
+
+int SDL_WM_IsFullyVisible( int recenter )
+{
+ int result = 1;
+
+ SDL_VideoDevice* video = current_video;
+
+ if (video && video->IsWindowVisible) {
+ result = video->IsWindowVisible(video, recenter);
+ }
+ return result;
+}
+
+int SDL_WM_GetMonitorDPI( int *xDpi, int *yDpi )
+{
+ int result = -1;
+ SDL_VideoDevice* video = current_video;
+
+ if (video && video->GetMonitorDPI) {
+ result = video->GetMonitorDPI(video, xDpi, yDpi);
+ }
+ return result;
+}
+
+int SDL_WM_GetMonitorRect( SDL_Rect *rect )
+{
+ int result = -1;
+ SDL_VideoDevice* video = current_video;
+
+ if (video && video->GetMonitorRect) {
+ result = video->GetMonitorRect(video, rect);
+ }
+ return result;
+}
+
+/*
+ * Get some platform dependent window manager information
+ */
+int SDL_GetWMInfo (SDL_SysWMinfo *info)
+{
+ SDL_VideoDevice *video = current_video;
+ SDL_VideoDevice *this = current_video;
+
+ if ( video && video->GetWMInfo ) {
+ return(video->GetWMInfo(this, info));
+ } else {
+ return(0);
+ }
+}