?? video.c
字號(hào):
/*** $Id: video.c,v 1.14 2003/11/22 04:44:14 weiym Exp $** ** Port to MiniGUI by Wei Yongming (2001/10/03).** Copyright (C) 2001 ~ 2002 Wei Yongming.** Copyright (C) 2003 Feynman Software.**** SDL - Simple DirectMedia Layer** Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga*//*** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License as published by** the Free Software Foundation; either version 2 of the License, or** (at your option) any later version.**** This program 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 General Public License for more details.**** You should have received a copy of the GNU General Public License** along with this program; if not, write to the Free Software** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*//* The high-level video driver subsystem */#include <stdio.h>#include <stdlib.h>#include <string.h>#include "common.h"#include "minigui.h"#include "newgal.h"#include "sysvideo.h"#include "blit.h"#include "pixels_c.h"/* Available video drivers */static VideoBootStrap *bootstrap[] = {#ifdef ENABLE_DUMMY &DUMMY_bootstrap,#endif#ifdef ENABLE_FBCON &FBCON_bootstrap,#endif#ifdef ENABLE_QVFB &QVFB_bootstrap,#endif#ifdef ENABLE_ECOSLCD &ECOSLCD_bootstrap,#endif#ifdef ENABLE_X11 &X11_bootstrap,#endif#ifdef ENABLE_DGA &DGA_bootstrap,#endif#ifdef ENABLE_GGI &GGI_bootstrap,#endif#ifdef ENABLE_SVGALIB &SVGALIB_bootstrap,#endif NULL};GAL_VideoDevice *current_video = NULL;/* Various local functions */int GAL_VideoInit(const char *driver_name, Uint32 flags);void GAL_VideoQuit(void);/* * Initialize the video subsystems -- determine native pixel format */int GAL_VideoInit (const char *driver_name, Uint32 flags){ GAL_VideoDevice *video; int index; int i; GAL_PixelFormat vformat; Uint32 video_flags; /* Check to make sure we don't overwrite 'current_video' */ if ( current_video != NULL ) { GAL_VideoQuit(); } /* Select the proper video driver */ index = 0; video = NULL; if ( driver_name != NULL ) { 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 ) { GAL_SetError("No available video device.\n"); return(-1); } current_video = video; current_video->name = bootstrap[i]->name; /* Do some basic variable initialization */ video->screen = NULL;#if 0 video->shadow = NULL; video->visible = NULL;#endif video->physpal = NULL; video->offset_x = 0; video->offset_y = 0; memset(&video->info, 0, (sizeof video->info)); /* Initialize the video subsystem */ memset(&vformat, 0, sizeof(vformat)); if ( video->VideoInit(video, &vformat) < 0 ) { GAL_VideoQuit(); return(-1); } /* Create a zero sized video surface of the appropriate format */ video_flags = GAL_SWSURFACE; GAL_VideoSurface = GAL_CreateRGBSurface(video_flags, 0, 0, vformat.BitsPerPixel, vformat.Rmask, vformat.Gmask, vformat.Bmask, 0); if ( GAL_VideoSurface == NULL ) { GAL_VideoQuit(); return(-1); } video->info.vfmt = GAL_VideoSurface->format; /* We're ready to go! */ return(0);}char *GAL_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 */GAL_Surface *GAL_GetVideoSurface(void){ GAL_Surface *visible; visible = NULL; if ( current_video ) {#if 0 visible = current_video->visible;#else visible = current_video->screen;#endif } return(visible);}/* * Get the current information about the video hardware */const GAL_VideoInfo *GAL_GetVideoInfo(void){ const GAL_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 (GAL_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 GAL_GetVideoInfo()->vfmt */GAL_Rect ** GAL_ListModes (GAL_PixelFormat *format, Uint32 flags){ GAL_VideoDevice *video = current_video; GAL_VideoDevice *this = current_video; GAL_Rect **modes; modes = NULL; if ( GAL_VideoSurface ) { if ( format == NULL ) { format = GAL_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, GAL_SetVideoMode() will succeed, * but will emulate the requested bits-per-pixel with a shadow surface. */static Uint8 GAL_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 GAL_VideoModeOK (int width, int height, int bpp, Uint32 flags) { int table, b, i; int supported; GAL_PixelFormat format; GAL_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; GAL_closest_depths[table][0] = bpp; GAL_closest_depths[table][7] = 0; for ( b = 0; !supported && GAL_closest_depths[table][b]; ++b ) { format.BitsPerPixel = GAL_closest_depths[table][b]; sizes = GAL_ListModes(&format, flags); if ( sizes == (GAL_Rect **)0 ) { /* No sizes supported at this bit-depth */ continue; } else if ( (sizes == (GAL_Rect **)-1) || 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(GAL_closest_depths[table][b]); } else { return(0); }}/* * Get the closest non-emulated video mode to the one requested */static int GAL_GetVideoMode (int *w, int *h, int *BitsPerPixel, Uint32 flags){ int table, b, i; int supported; int native_bpp; GAL_PixelFormat format; GAL_Rect **sizes; /* Try the original video mode, get the closest depth */ native_bpp = GAL_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; GAL_closest_depths[table][0] = *BitsPerPixel; GAL_closest_depths[table][7] = GAL_VideoSurface->format->BitsPerPixel; for ( b = 0; !supported && GAL_closest_depths[table][b]; ++b ) { format.BitsPerPixel = GAL_closest_depths[table][b]; sizes = GAL_ListModes(&format, flags); if ( sizes == (GAL_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 = GAL_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 */ --i; *w = sizes[i]->w; *h = sizes[i]->h; *BitsPerPixel = GAL_closest_depths[table][b]; supported = 1; } } if ( ! supported ) { GAL_SetError("No video mode large enough for the resolution specified.\n"); } return(supported);}/* This should probably go somewhere else -- like GAL_surface.c */static void GAL_ClearSurface(GAL_Surface *surface){ Uint32 black; black = GAL_MapRGB(surface->format, 0, 0, 0); GAL_FillRect(surface, NULL, black);#if 0 if ((surface->flags&GAL_HWSURFACE) && (surface->flags&GAL_DOUBLEBUF)) { GAL_Flip(surface); GAL_FillRect(surface, NULL, black); } GAL_Flip(surface);#endif}#if 0/* * Create a shadow surface suitable for fooling the app. :-) */static void GAL_CreateShadowSurface(int depth){ Uint32 Rmask, Gmask, Bmask; /* Allocate the shadow surface */ if ( depth == (GAL_VideoSurface->format)->BitsPerPixel ) { Rmask = (GAL_VideoSurface->format)->Rmask; Gmask = (GAL_VideoSurface->format)->Gmask; Bmask = (GAL_VideoSurface->format)->Bmask; } else { Rmask = Gmask = Bmask = 0; } GAL_ShadowSurface = GAL_CreateRGBSurface(GAL_SWSURFACE, GAL_VideoSurface->w, GAL_VideoSurface->h, depth, Rmask, Gmask, Bmask, 0); if ( GAL_ShadowSurface == NULL ) { return; } /* 8-bit shadow surfaces report that they have exclusive palette */ if ( GAL_ShadowSurface->format->palette ) { GAL_ShadowSurface->flags |= GAL_HWPALETTE; if ( depth == (GAL_VideoSurface->format)->BitsPerPixel ) { memcpy(GAL_ShadowSurface->format->palette->colors, GAL_VideoSurface->format->palette->colors, GAL_VideoSurface->format->palette->ncolors* sizeof(GAL_Color)); } else { GAL_DitherColors( GAL_ShadowSurface->format->palette->colors, depth); } } /* If the video surface is fullscreen, the shadow should say so */ if ( (GAL_VideoSurface->flags & GAL_FULLSCREEN) == GAL_FULLSCREEN ) { GAL_ShadowSurface->flags |= GAL_FULLSCREEN; } /* If the video surface is flippable, the shadow should say so */ if ( (GAL_VideoSurface->flags & GAL_DOUBLEBUF) == GAL_DOUBLEBUF ) { GAL_ShadowSurface->flags |= GAL_DOUBLEBUF; } return;}#endif/* * Set the requested video mode, allocating a shadow buffer if necessary. */GAL_Surface * GAL_SetVideoMode (int width, int height, int bpp, Uint32 flags){ GAL_VideoDevice *video, *this; GAL_Surface *prev_mode, *mode; int video_w; int video_h; int video_bpp; this = video = current_video; /* Default to the current video bpp */ if ( bpp == 0 ) { flags |= GAL_ANYFORMAT; bpp = GAL_VideoSurface->format->BitsPerPixel; } /* Get a good video mode, the closest one possible */ video_w = width; video_h = height; video_bpp = bpp;#if defined(_LITE_VERSION) && !defined(_STAND_ALONE) if ( mgIsServer && !GAL_GetVideoMode(&video_w, &video_h, &video_bpp, flags) ) {#else if ( !GAL_GetVideoMode(&video_w, &video_h, &video_bpp, flags) ) {#endif return(NULL); } /* Check the requested flags */ /* There's no palette in > 8 bits-per-pixel mode */ if ( video_bpp > 8 ) { flags &= ~GAL_HWPALETTE; }#if 0 if ( (flags&GAL_DOUBLEBUF) == GAL_DOUBLEBUF ) { /* Use hardware surfaces when double-buffering */ flags |= GAL_HWSURFACE; } /* Clean up any previous video mode */ if ( GAL_PublicSurface != NULL ) { GAL_PublicSurface = NULL; } if ( GAL_ShadowSurface != NULL ) { GAL_Surface *ready_to_go; ready_to_go = GAL_ShadowSurface; GAL_ShadowSurface = NULL; GAL_FreeSurface(ready_to_go); }#endif if ( video->physpal ) { free(video->physpal->colors); free(video->physpal); video->physpal = NULL; } /* Try to set the video mode, along with offset and clipping */ prev_mode = GAL_VideoSurface; GAL_VideoSurface = NULL; /* In case it's freed by driver */ mode = video->SetVideoMode(this, prev_mode,video_w,video_h,video_bpp,flags); /* * rcg11292000 * If you try to set an GAL_OPENGL surface, and fail to find a * matching visual, then the next call to GAL_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 GAL_VideoInit() again? */ GAL_VideoSurface = (mode != NULL) ? mode : prev_mode; if ((mode != NULL)) { /* Sanity check */ if ( (mode->w < width) || (mode->h < height) ) { GAL_SetError("Video mode smaller than requested"); return(NULL); }
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -