⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdl_fbvideo.c

📁 Simple DirectMedia Layer - Simple DirectMedia Layer 是一个跨平台的多媒体库设计用来提供快速图形framebuffer和音频驱动。应用MPEG为软件
💻 C
📖 第 1 页 / 共 3 页
字号:
/*	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_fbvideo.c,v 1.10 2002/09/02 21:42:15 slouken Exp $";#endif/* Framebuffer console based SDL video driver implementation.*/#include <stdlib.h>#include <stdio.h>#include <string.h>#include <fcntl.h>#include <unistd.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <asm/page.h>		/* For definition of PAGE_SIZE */#include "SDL.h"#include "SDL_error.h"#include "SDL_video.h"#include "SDL_mouse.h"#include "SDL_sysvideo.h"#include "SDL_pixels_c.h"#include "SDL_events_c.h"#include "SDL_fbvideo.h"#include "SDL_fbmouse_c.h"#include "SDL_fbevents_c.h"#include "SDL_fb3dfx.h"#include "SDL_fbmatrox.h"#include "SDL_fbriva.h"#if defined(i386) && defined(FB_TYPE_VGA_PLANES)#define VGA16_FBCON_SUPPORT#ifndef FB_AUX_VGA_PLANES_VGA4#define FB_AUX_VGA_PLANES_VGA4	0#endifstatic inline void outb (unsigned char value, unsigned short port){  __asm__ __volatile__ ("outb %b0,%w1"::"a" (value), "Nd" (port));} #endif /* FB_TYPE_VGA_PLANES *//* A list of video resolutions that we query for (sorted largest to smallest) */static const SDL_Rect checkres[] = {	{  0, 0, 1600, 1200 },		/* 16 bpp: 0x11E, or 286 */	{  0, 0, 1408, 1056 },		/* 16 bpp: 0x19A, or 410 */	{  0, 0, 1280, 1024 },		/* 16 bpp: 0x11A, or 282 */	{  0, 0, 1152,  864 },		/* 16 bpp: 0x192, or 402 */	{  0, 0, 1024,  768 },		/* 16 bpp: 0x117, or 279 */	{  0, 0,  960,  720 },		/* 16 bpp: 0x18A, or 394 */	{  0, 0,  800,  600 },		/* 16 bpp: 0x114, or 276 */	{  0, 0,  768,  576 },		/* 16 bpp: 0x182, or 386 */	{  0, 0,  720,  576 },		/* PAL */	{  0, 0,  720,  480 },		/* NTSC */	{  0, 0,  640,  480 },		/* 16 bpp: 0x111, or 273 */	{  0, 0,  640,  400 },		/*  8 bpp: 0x100, or 256 */	{  0, 0,  512,  384 },	{  0, 0,  320,  240 },	{  0, 0,  320,  200 }};static const struct {	int xres;	int yres;	int pixclock;	int left;	int right;	int upper;	int lower;	int hslen;	int vslen;	int sync;	int vmode;} vesa_timings[] = {#ifdef USE_VESA_TIMINGS	/* Only tested on Matrox Millenium I */	{  640,  400, 39771,  48, 16, 39,  8,  96, 2, 2, 0 },	/* 70 Hz */	{  640,  480, 39683,  48, 16, 33, 10,  96, 2, 0, 0 },	/* 60 Hz */	{  768,  576, 26101, 144, 16, 28,  6, 112, 4, 0, 0 },	/* 60 Hz */	{  800,  600, 24038, 144, 24, 28,  8, 112, 6, 0, 0 },	/* 60 Hz */	{  960,  720, 17686, 144, 24, 28,  8, 112, 4, 0, 0 },	/* 60 Hz */	{ 1024,  768, 15386, 160, 32, 30,  4, 128, 4, 0, 0 },	/* 60 Hz */	{ 1152,  864, 12286, 192, 32, 30,  4, 128, 4, 0, 0 },	/* 60 Hz */	{ 1280, 1024,  9369, 224, 32, 32,  4, 136, 4, 0, 0 },	/* 60 Hz */	{ 1408, 1056,  8214, 256, 40, 32,  5, 144, 5, 0, 0 },	/* 60 Hz */	{ 1600, 1200,/*?*/0, 272, 48, 32,  5, 152, 5, 0, 0 },	/* 60 Hz */#else	/* You can generate these timings from your XF86Config file using	   the 'modeline2fb' perl script included with the fbset package.	   These timings were generated for Matrox Millenium I, 15" monitor.	*/	{  320,  200, 79440,  16, 16, 20,  4,  48, 1, 0, 2 },	/* 70 Hz */	{  320,  240, 63492,  16, 16, 16,  4,  48, 2, 0, 2 },	/* 72 Hz */	{  512,  384, 49603,  48, 16, 16,  1,  64, 3, 0, 0 },	/* 78 Hz */	{  640,  400, 31746,  96, 32, 41,  1,  64, 3, 2, 0 },	/* 85 Hz */	{  640,  480, 31746, 120, 16, 16,  1,  64, 3, 0, 0 },	/* 75 Hz */	{  768,  576, 26101, 144, 16, 28,  6, 112, 4, 0, 0 },	/* 60 Hz */	{  800,  600, 20000,  64, 56, 23, 37, 120, 6, 3, 0 },	/* 72 Hz */	{  960,  720, 17686, 144, 24, 28,  8, 112, 4, 0, 0 },	/* 60 Hz */	{ 1024,  768, 13333, 144, 24, 29,  3, 136, 6, 0, 0 },	/* 70 Hz */	{ 1152,  864, 12286, 192, 32, 30,  4, 128, 4, 0, 0 },	/* 60 Hz */	{ 1280, 1024,  9369, 224, 32, 32,  4, 136, 4, 0, 0 },	/* 60 Hz */	{ 1408, 1056,  8214, 256, 40, 32,  5, 144, 5, 0, 0 },	/* 60 Hz */	{ 1600, 1200,/*?*/0, 272, 48, 32,  5, 152, 5, 0, 0 },	/* 60 Hz */#endif};/* Initialization/Query functions */static int FB_VideoInit(_THIS, SDL_PixelFormat *vformat);static SDL_Rect **FB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);static SDL_Surface *FB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);#ifdef VGA16_FBCON_SUPPORTstatic SDL_Surface *FB_SetVGA16Mode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);#endifstatic int FB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);static void FB_VideoQuit(_THIS);/* Hardware surface functions */static int FB_InitHWSurfaces(_THIS, SDL_Surface *screen, char *base, int size);static void FB_FreeHWSurfaces(_THIS);static int FB_AllocHWSurface(_THIS, SDL_Surface *surface);static int FB_LockHWSurface(_THIS, SDL_Surface *surface);static void FB_UnlockHWSurface(_THIS, SDL_Surface *surface);static void FB_FreeHWSurface(_THIS, SDL_Surface *surface);static void FB_WaitVBL(_THIS);static void FB_WaitIdle(_THIS);static int FB_FlipHWSurface(_THIS, SDL_Surface *surface);/* Internal palette functions */static void FB_SavePalette(_THIS, struct fb_fix_screeninfo *finfo,                                  struct fb_var_screeninfo *vinfo);static void FB_RestorePalette(_THIS);/* FB driver bootstrap functions */static int FB_Available(void){	int console;	const char *SDL_fbdev;	SDL_fbdev = getenv("SDL_FBDEV");	if ( SDL_fbdev == NULL ) {		SDL_fbdev = "/dev/fb0";	}	console = open(SDL_fbdev, O_RDWR, 0);	if ( console >= 0 ) {		close(console);	}	return(console >= 0);}static void FB_DeleteDevice(SDL_VideoDevice *device){	free(device->hidden);	free(device);}static SDL_VideoDevice *FB_CreateDevice(int devindex){	SDL_VideoDevice *this;	/* Initialize all variables that we clean on shutdown */	this = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));	if ( this ) {		memset(this, 0, (sizeof *this));		this->hidden = (struct SDL_PrivateVideoData *)				malloc((sizeof *this->hidden));	}	if ( (this == NULL) || (this->hidden == NULL) ) {		SDL_OutOfMemory();		if ( this ) {			free(this);		}		return(0);	}	memset(this->hidden, 0, (sizeof *this->hidden));	wait_vbl = FB_WaitVBL;	wait_idle = FB_WaitIdle;	mouse_fd = -1;	keyboard_fd = -1;	/* Set the function pointers */	this->VideoInit = FB_VideoInit;	this->ListModes = FB_ListModes;	this->SetVideoMode = FB_SetVideoMode;	this->SetColors = FB_SetColors;	this->UpdateRects = NULL;	this->VideoQuit = FB_VideoQuit;	this->AllocHWSurface = FB_AllocHWSurface;	this->CheckHWBlit = NULL;	this->FillHWRect = NULL;	this->SetHWColorKey = NULL;	this->SetHWAlpha = NULL;	this->LockHWSurface = FB_LockHWSurface;	this->UnlockHWSurface = FB_UnlockHWSurface;	this->FlipHWSurface = FB_FlipHWSurface;	this->FreeHWSurface = FB_FreeHWSurface;	this->SetCaption = NULL;	this->SetIcon = NULL;	this->IconifyWindow = NULL;	this->GrabInput = NULL;	this->GetWMInfo = NULL;	this->InitOSKeymap = FB_InitOSKeymap;	this->PumpEvents = FB_PumpEvents;	this->free = FB_DeleteDevice;	return this;}VideoBootStrap FBCON_bootstrap = {	"fbcon", "Linux Framebuffer Console",	FB_Available, FB_CreateDevice};static int FB_CheckMode(_THIS, struct fb_var_screeninfo *vinfo,                        int index, unsigned int *w, unsigned int *h){	int mode_okay;	mode_okay = 0;	vinfo->bits_per_pixel = (index+1)*8;	vinfo->xres = *w;	vinfo->xres_virtual = *w;	vinfo->yres = *h;	vinfo->yres_virtual = *h;	vinfo->activate = FB_ACTIVATE_TEST;	if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, vinfo) == 0 ) {#ifdef FBCON_DEBUG		fprintf(stderr, "Checked mode %dx%d at %d bpp, got mode %dx%d at %d bpp\n", *w, *h, (index+1)*8, vinfo->xres, vinfo->yres, vinfo->bits_per_pixel);#endif		if ( (((vinfo->bits_per_pixel+7)/8)-1) == index ) {			*w = vinfo->xres;			*h = vinfo->yres;			mode_okay = 1;		}	}	return mode_okay;}static int FB_AddMode(_THIS, int index, unsigned int w, unsigned int h){	SDL_Rect *mode;	int i;	int next_mode;	/* Check to see if we already have this mode */	if ( SDL_nummodes[index] > 0 ) {		mode = SDL_modelist[index][SDL_nummodes[index]-1];		if ( (mode->w == w) && (mode->h == h) ) {#ifdef FBCON_DEBUG			fprintf(stderr, "We already have mode %dx%d at %d bytes per pixel\n", w, h, index+1);#endif			return(0);		}	}	/* Only allow a mode if we have a valid timing for it */	next_mode = -1;	for ( i=0; i<(sizeof(vesa_timings)/sizeof(vesa_timings[0])); ++i ) {		if ( (w == vesa_timings[i].xres) &&		     (h == vesa_timings[i].yres) && vesa_timings[i].pixclock ) {			next_mode = i;			break;		}	}	if ( next_mode == -1 ) {#ifdef FBCON_DEBUG		fprintf(stderr, "No valid timing line for mode %dx%d\n", w, h);#endif		return(0);	}	/* Set up the new video mode rectangle */	mode = (SDL_Rect *)malloc(sizeof *mode);	if ( mode == NULL ) {		SDL_OutOfMemory();		return(-1);	}	mode->x = 0;	mode->y = 0;	mode->w = w;	mode->h = h;#ifdef FBCON_DEBUG	fprintf(stderr, "Adding mode %dx%d at %d bytes per pixel\n", w, h, index+1);#endif	/* Allocate the new list of modes, and fill in the new mode */	next_mode = SDL_nummodes[index];	SDL_modelist[index] = (SDL_Rect **)	       realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *));	if ( SDL_modelist[index] == NULL ) {		SDL_OutOfMemory();		SDL_nummodes[index] = 0;		free(mode);		return(-1);	}	SDL_modelist[index][next_mode] = mode;	SDL_modelist[index][next_mode+1] = NULL;	SDL_nummodes[index]++;	return(0);}static int FB_VideoInit(_THIS, SDL_PixelFormat *vformat){	struct fb_fix_screeninfo finfo;	struct fb_var_screeninfo vinfo;	int i, j;	int current_index;	unsigned int current_w;	unsigned int current_h;	const char *SDL_fbdev;	/* Initialize the library */	SDL_fbdev = getenv("SDL_FBDEV");	if ( SDL_fbdev == NULL ) {		SDL_fbdev = "/dev/fb0";	}	console_fd = open(SDL_fbdev, O_RDWR, 0);	if ( console_fd < 0 ) {		SDL_SetError("Unable to open %s", SDL_fbdev);		return(-1);	}#ifndef DISABLE_THREADS	/* Create the hardware surface lock mutex */	hw_lock = SDL_CreateMutex();	if ( hw_lock == NULL ) {		SDL_SetError("Unable to create lock mutex");		FB_VideoQuit(this);		return(-1);	}#endif	/* Get the type of video hardware */	if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) {		SDL_SetError("Couldn't get console hardware info");		FB_VideoQuit(this);		return(-1);	}	switch (finfo.type) {		case FB_TYPE_PACKED_PIXELS:			/* Supported, no worries.. */			break;#ifdef VGA16_FBCON_SUPPORT		case FB_TYPE_VGA_PLANES:			/* VGA16 is supported, but that's it */			if ( finfo.type_aux == FB_AUX_VGA_PLANES_VGA4 ) {				if ( ioperm(0x3b4, 0x3df - 0x3b4 + 1, 1) < 0 ) {					SDL_SetError("No I/O port permissions");					FB_VideoQuit(this);					return(-1);				}				this->SetVideoMode = FB_SetVGA16Mode;				break;			}			/* Fall through to unsupported case */#endif /* VGA16_FBCON_SUPPORT */		default:			SDL_SetError("Unsupported console hardware");			FB_VideoQuit(this);			return(-1);	}	switch (finfo.visual) {		case FB_VISUAL_TRUECOLOR:		case FB_VISUAL_PSEUDOCOLOR:		case FB_VISUAL_STATIC_PSEUDOCOLOR:		case FB_VISUAL_DIRECTCOLOR:			break;		default:			SDL_SetError("Unsupported console hardware");			FB_VideoQuit(this);			return(-1);	}	/* Check if the user wants to disable hardware acceleration */	{ const char *fb_accel;		fb_accel = getenv("SDL_FBACCEL");		if ( fb_accel ) {			finfo.accel = atoi(fb_accel);		}	}	/* Memory map the device, compensating for buggy PPC mmap() */	mapped_offset = (((long)finfo.smem_start) -	                (((long)finfo.smem_start)&~(PAGE_SIZE-1)));	mapped_memlen = finfo.smem_len+mapped_offset;	mapped_mem = mmap(NULL, mapped_memlen,	                  PROT_READ|PROT_WRITE, MAP_SHARED, console_fd, 0);	if ( mapped_mem == (char *)-1 ) {		SDL_SetError("Unable to memory map the video hardware");		mapped_mem = NULL;		FB_VideoQuit(this);		return(-1);	}	/* Determine the current screen depth */	if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) {		SDL_SetError("Couldn't get console pixel format");		FB_VideoQuit(this);		return(-1);	}	vformat->BitsPerPixel = vinfo.bits_per_pixel;	if ( vformat->BitsPerPixel < 8 ) {		/* Assuming VGA16, we handle this via a shadow framebuffer */		vformat->BitsPerPixel = 8;	}	for ( i=0; i<vinfo.red.length; ++i ) {		vformat->Rmask <<= 1;		vformat->Rmask |= (0x00000001<<vinfo.red.offset);	}	for ( i=0; i<vinfo.green.length; ++i ) {		vformat->Gmask <<= 1;		vformat->Gmask |= (0x00000001<<vinfo.green.offset);	}	for ( i=0; i<vinfo.blue.length; ++i ) {		vformat->Bmask <<= 1;		vformat->Bmask |= (0x00000001<<vinfo.blue.offset);	}	saved_vinfo = vinfo;	/* Save hardware palette, if needed */	FB_SavePalette(this, &finfo, &vinfo);	/* If the I/O registers are available, memory map them so we	   can take advantage of any supported hardware acceleration.	 */	vinfo.accel_flags = 0;	/* Temporarily reserve registers */	ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo);	if ( finfo.accel && finfo.mmio_len ) {		mapped_iolen = finfo.mmio_len;		mapped_io = mmap(NULL, mapped_iolen, PROT_READ|PROT_WRITE,		                 MAP_SHARED, console_fd, mapped_memlen);		if ( mapped_io == (char *)-1 ) {			/* Hmm, failed to memory map I/O registers */			mapped_io = NULL;		}	}	/* Query for the list of available video modes */	current_w = vinfo.xres;	current_h = vinfo.yres;	current_index = ((vinfo.bits_per_pixel+7)/8)-1;#ifdef BROKEN_MODES	FB_AddMode(this, current_index, current_w, current_h);#else	for ( i=0; i<NUM_MODELISTS; ++i ) {		SDL_nummodes[i] = 0;		SDL_modelist[i] = NULL;		for ( j=0; j<(sizeof(checkres)/sizeof(checkres[0])); ++j ) {			unsigned int w, h;			/* See if we are querying for the current mode */			w = checkres[j].w;			h = checkres[j].h;			if ( i == current_index ) {				if ( (current_w > w) || (current_h > h) ) {					/* Only check once */					FB_AddMode(this, i, current_w, current_h);					current_index = -1;				}			}			if ( FB_CheckMode(this, &vinfo, i, &w, &h) ) {				FB_AddMode(this, i, w, h);			}		}	}#endif /* BROKEN_MODES */	/* Fill in our hardware acceleration capabilities */	this->info.wm_available = 0;	this->info.hw_available = 1;	this->info.video_mem = finfo.smem_len/1024;	if ( mapped_io ) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -