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

📄 sdl_fbvideo.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 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_RCSID
static char rcsid =
 "@(#) $Id: SDL_fbvideo.c,v 1.4 2002/04/22 21:38:04 wmay 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
#endif
static 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_SUPPORT
static SDL_Surface *FB_SetVGA16Mode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
#endif
static 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;
	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);
			}
		}
	}

	/* 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 ) {
		switch (finfo.accel) {
		    case FB_ACCEL_MATROX_MGA2064W:

⌨️ 快捷键说明

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