?? sdl_video.c
字號:
/* SDL - Simple DirectMedia Layer Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Sam Lantinga slouken@libsdl.org*/#ifdef SAVE_RCSIDstatic char rcsid = "@(#) $Id: SDL_video.c,v 1.32 2002/10/05 16:50:56 slouken Exp $";#endif/* The high-level video driver subsystem */#include <stdio.h>#include <stdlib.h>#include <string.h>#include "SDL.h"#include "SDL_error.h"#include "SDL_video.h"#include "SDL_events.h"#include "SDL_mutex.h"#include "SDL_sysvideo.h"#include "SDL_sysevents.h"#include "SDL_blit.h"#include "SDL_pixels_c.h"#include "SDL_events_c.h"#include "SDL_cursor_c.h"/* Available video drivers */static VideoBootStrap *bootstrap[] = {#ifdef ENABLE_X11 &X11_bootstrap,#endif#ifdef ENABLE_DGA &DGA_bootstrap,#endif#ifdef ENABLE_NANOX &NX_bootstrap,#endif#ifdef ENABLE_FBCON &FBCON_bootstrap,#endif#ifdef ENABLE_DIRECTFB &DirectFB_bootstrap,#endif#ifdef ENABLE_PS2GS &PS2GS_bootstrap,#endif#ifdef ENABLE_GGI &GGI_bootstrap,#endif#ifdef ENABLE_VGL &VGL_bootstrap,#endif#ifdef ENABLE_SVGALIB &SVGALIB_bootstrap,#endif#ifdef ENABLE_AALIB &AALIB_bootstrap,#endif#ifdef ENABLE_DIRECTX &DIRECTX_bootstrap,#endif#ifdef ENABLE_WINDIB &WINDIB_bootstrap,#endif#ifdef ENABLE_BWINDOW &BWINDOW_bootstrap,#endif#ifdef ENABLE_TOOLBOX &TOOLBOX_bootstrap,#endif#ifdef ENABLE_DRAWSPROCKET &DSp_bootstrap,#endif#ifdef ENABLE_QUARTZ &QZ_bootstrap,#endif#ifdef ENABLE_CYBERGRAPHICS &CGX_bootstrap,#endif#ifdef ENABLE_PHOTON &ph_bootstrap,#endif#ifdef ENABLE_EPOC &EPOC_bootstrap,#endif#ifdef ENABLE_DUMMYVIDEO &DUMMY_bootstrap,#endif#ifdef ENABLE_XBIOS &XBIOS_bootstrap,#endif#ifdef ENABLE_GEM &GEM_bootstrap,#endif#ifdef ENABLE_QTOPIA &Qtopia_bootstrap,#endif#ifdef ENABLE_PICOGUI &PG_bootstrap,#endif#ifdef ENABLE_DC &DC_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);#ifdef HAVE_OPENGLstatic 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 ( strrchr(driver_name, ':') != NULL ) { index = atoi(strrchr(driver_name, ':')+1); }#endif for ( i=0; bootstrap[i]; ++i ) { if ( strncmp(bootstrap[i]->name, driver_name, strlen(bootstrap[i]->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; memset(&video->info, 0, (sizeof video->info)); /* Set some very sane GL defaults */ video->gl_config.driver_loaded = 0; video->gl_config.dll_handle = NULL; video->gl_config.red_size = 5;#if 1 /* This seems to work on more video cards, as a default */ video->gl_config.green_size = 5;#else video->gl_config.green_size = 6;#endif video->gl_config.blue_size = 5; 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; /* Initialize the video subsystem */ 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 ) { strncpy(namebuf, current_video->name, maxlen-1); namebuf[maxlen-1] = '\0'; 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 = ¤t_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 }};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 */ 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 #ifdef macintosh /* MPW optimization bug? */ if ( (sizes == (SDL_Rect **)0xFFFFFFFF) ||#else if ( (sizes == (SDL_Rect **)-1) ||#endif current_video->handles_any_size ) { /* Any size supported at this bit-depth */ supported = 1; continue; } 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 */ 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 ) { 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; } for ( i=0; sizes[i]; ++i ) { if ((sizes[i]->w < *w) || (sizes[i]->h < *h)) { if ( i > 0 ) { --i; *w = sizes[i]->w; *h = sizes[i]->h; *BitsPerPixel = SDL_closest_depths[table][b]; supported = 1; } else { /* Largest mode too small... */; } break; } } if ( (i > 0) && ! sizes[i] ) { /* The smallest mode was larger than requested, OK */
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -