?? fbvideo.c
字號:
/*** $Id: fbvideo.c,v 1.36 2005/09/04 05:07:30 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*//* Framebuffer console based 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 <linux/vt.h>#include <linux/kd.h>#include <linux/keyboard.h>#include "common.h"#include "minigui.h"#if defined(_LITE_VERSION) && !defined(_STAND_ALONE)#include "client.h"#endif#include "newgal.h"#include "sysvideo.h"#include "pixels_c.h"#include "fbvideo.h"#include "fb3dfx.h"#include "fbmatrox.h"#include "fbneomagic.h"/*#define FBACCEL_DEBUG 1#define FBCON_DEBUG 1*/#if defined(i386) && defined(FB_TYPE_VGA_PLANES)#if 0#define VGA16_FBCON_SUPPORT#include <sys/io.h>#ifndef FB_AUX_VGA_PLANES_VGA4#define FB_AUX_VGA_PLANES_VGA4 0#endifinline static void outb (unsigned char value, unsigned short port){ __asm__ __volatile__ ("outb %b0,%w1"::"a" (value), "Nd" (port));} #endif#endif /* FB_TYPE_VGA_PLANES *//* Initialization/Query functions */static int FB_VideoInit(_THIS, GAL_PixelFormat *vformat);static GAL_Rect **FB_ListModes(_THIS, GAL_PixelFormat *format, Uint32 flags);static GAL_Surface *FB_SetVideoMode(_THIS, GAL_Surface *current, int width, int height, int bpp, Uint32 flags);#ifdef VGA16_FBCON_SUPPORTstatic GAL_Surface *FB_SetVGA16Mode(_THIS, GAL_Surface *current, int width, int height, int bpp, Uint32 flags);#endifstatic int FB_SetColors(_THIS, int firstcolor, int ncolors, GAL_Color *colors);static void FB_VideoQuit(_THIS);/* Hardware surface functions */static int FB_InitHWSurfaces(_THIS, GAL_Surface *screen, char *base, int size);static void FB_FreeHWSurfaces(_THIS);static void FB_RequestHWSurface (_THIS, const REQ_HWSURFACE* request, REP_HWSURFACE* reply);static int FB_AllocHWSurface(_THIS, GAL_Surface *surface);static void FB_FreeHWSurface(_THIS, GAL_Surface *surface);static void FB_WaitVBL(_THIS);static void FB_WaitIdle(_THIS);#if 0static int FB_LockHWSurface(_THIS, GAL_Surface *surface);static void FB_UnlockHWSurface(_THIS, GAL_Surface *surface);static int FB_FlipHWSurface(_THIS, GAL_Surface *surface);#endif/* 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 *GAL_fbdev; GAL_fbdev = getenv("FRAMEBUFFER"); if ( GAL_fbdev == NULL ) { GAL_fbdev = "/dev/fb0"; } console = open(GAL_fbdev, O_RDWR, 0); if ( console >= 0 ) { close(console); } return(console >= 0);}static void FB_DeleteDevice(GAL_VideoDevice *device){ free(device->hidden); free(device);}static GAL_VideoDevice *FB_CreateDevice(int devindex){ GAL_VideoDevice *this; /* Initialize all variables that we clean on shutdown */ this = (GAL_VideoDevice *)malloc(sizeof(GAL_VideoDevice)); if ( this ) { memset(this, 0, (sizeof *this)); this->hidden = (struct GAL_PrivateVideoData *) malloc((sizeof *this->hidden)); } if ( (this == NULL) || (this->hidden == NULL) ) { GAL_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->VideoQuit = FB_VideoQuit;#if defined(_LITE_VERSION) && !defined(_STAND_ALONE) this->RequestHWSurface = FB_RequestHWSurface;#endif this->AllocHWSurface = FB_AllocHWSurface; this->CheckHWBlit = NULL; this->FillHWRect = NULL; this->SetHWColorKey = NULL; this->SetHWAlpha = NULL; this->UpdateRects = NULL;#if 0 this->LockHWSurface = FB_LockHWSurface; this->UnlockHWSurface = FB_UnlockHWSurface; this->FlipHWSurface = FB_FlipHWSurface;#endif this->FreeHWSurface = FB_FreeHWSurface; this->free = FB_DeleteDevice; return this;}VideoBootStrap FBCON_bootstrap = { "fbcon", "Linux Framebuffer Console", FB_Available, FB_CreateDevice};static int ttyfd = -1;static void FB_LeaveGraphicsMode (_THIS){#ifdef _HAVE_TEXT_MODE#if defined(_LITE_VERSION) && !defined(_STAND_ALONE) if (mgIsServer) {#endif /* enter text mode*/ if (ttyfd >= 0) { ioctl (ttyfd, KDSETMODE, KD_TEXT); close (ttyfd); ttyfd = -1; }#if defined(_LITE_VERSION) && !defined(_STAND_ALONE) }#endif#endif}static int FB_EnterGraphicsMode (_THIS){#ifdef _HAVE_TEXT_MODE#if defined(_LITE_VERSION) && !defined(_STAND_ALONE) if (mgIsServer) {#endif char* tty_dev; if (geteuid() == 0) tty_dev = "/dev/tty0"; else /* not a super user, so try to open the control terminal */ tty_dev = "/dev/tty"; /* open tty, enter graphics mode */ ttyfd = open (tty_dev, O_RDWR); if (ttyfd < 0) { fprintf (stderr,"GAL ENGINE: Can't open %s: %m\n", tty_dev); goto fail; } if (ioctl (ttyfd, KDSETMODE, KD_GRAPHICS) == -1) { fprintf (stderr,"GAL ENGINE: Error when setting the terminal to graphics mode: %m\n"); fprintf (stderr,"GAL ENGINE: Maybe is not a console.\n"); goto fail; }#if defined(_LITE_VERSION) && !defined(_STAND_ALONE) } else { ttyfd = 0; }#endif return ttyfd;fail: FB_LeaveGraphicsMode (this); return -1;#else return 0;#endif}static int FB_OpenKeyboard(_THIS){#if 1 return 0;#else /* Open only if not already opened */ if ( keyboard_fd < 0 ) { static const char * const tty0[] = { "/dev/tty0", "/dev/vc/0", NULL }; static const char * const vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL }; int i, tty0_fd; /* Try to query for a free virtual terminal */ tty0_fd = -1; for ( i=0; tty0[i] && (tty0_fd < 0); ++i ) { tty0_fd = open(tty0[i], O_WRONLY, 0); } if ( tty0_fd < 0 ) { tty0_fd = dup(0); /* Maybe stdin is a VT? */ } ioctl(tty0_fd, VT_OPENQRY, ¤t_vt); close(tty0_fd); if ( (geteuid() == 0) && (current_vt > 0) ) { for ( i=0; vcs[i] && (keyboard_fd < 0); ++i ) { char vtpath[12]; sprintf(vtpath, vcs[i], current_vt); keyboard_fd = open(vtpath, O_RDWR, 0);#ifdef DEBUG_KEYBOARD fprintf(stderr, "vtpath = %s, fd = %d\n", vtpath, keyboard_fd);#endif /* DEBUG_KEYBOARD */ /* This needs to be our controlling tty so that the kernel ioctl() calls work */ if ( keyboard_fd >= 0 ) { tty0_fd = open("/dev/tty", O_RDWR, 0); if ( tty0_fd >= 0 ) { ioctl(tty0_fd, TIOCNOTTY, 0); close(tty0_fd); } } } } if ( keyboard_fd < 0 ) { /* Last resort, maybe our tty is a usable VT */ current_vt = 0; keyboard_fd = open("/dev/tty", O_RDWR); }#ifdef DEBUG_KEYBOARD fprintf(stderr, "Current VT: %d\n", current_vt);#endif /* Make sure that our input is a console terminal */ { int dummy; if ( ioctl(keyboard_fd, KDGKBMODE, &dummy) < 0 ) { close(keyboard_fd); keyboard_fd = -1; GAL_SetError("FBCON NEWGAL Engine: Unable to open a console terminal\n"); } } }#endif return(keyboard_fd);}static int FB_VideoInit(_THIS, GAL_PixelFormat *vformat){ struct fb_fix_screeninfo finfo; struct fb_var_screeninfo vinfo; int i; int current_index; unsigned int current_w; unsigned int current_h; const char *GAL_fbdev; /* Initialize the library */ GAL_fbdev = getenv("FRAMEBUFFER"); if ( GAL_fbdev == NULL ) { GAL_fbdev = "/dev/fb0"; } console_fd = open(GAL_fbdev, O_RDWR, 0); if ( console_fd < 0 ) { GAL_SetError("FBCON NEWGAL Engine: Unable to open %s\n", GAL_fbdev); return(-1); } /* Get the type of video hardware */ if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) { GAL_SetError("FBCON NEWGAL Engine: Couldn't get console hardware info\n"); 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 ) { GAL_SetError("FBCON NEWGAL Engine: No I/O port permissions\n"); FB_VideoQuit(this); return(-1); } this->SetVideoMode = FB_SetVGA16Mode; break; } /* Fall through to unsupported case */#endif /* VGA16_FBCON_SUPPORT */ default: GAL_SetError("FBCON NEWGAL Engine: Unsupported console hardware\n"); 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: GAL_SetError("FBCON NEWGAL Engine: Unsupported console hardware\n"); FB_VideoQuit(this); return(-1); }#if 0 /* Check if the user wants to disable hardware acceleration */ { const char *fb_accel; fb_accel = getenv("GAL_FBACCEL"); if ( fb_accel ) { finfo.accel = atoi(fb_accel); } }#endif /* 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;#ifdef __uClinux__ mapped_mem = mmap(NULL, mapped_memlen, PROT_READ|PROT_WRITE, 0, console_fd, 0);#else mapped_mem = mmap(NULL, mapped_memlen, PROT_READ|PROT_WRITE, MAP_SHARED, console_fd, 0);#endif if ( mapped_mem == (char *)-1 ) { GAL_SetError("FBCON NEWGAL Engine: Unable to memory map the video hardware\n"); mapped_mem = NULL; FB_VideoQuit(this); return(-1); } /* Determine the current screen depth */ if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) { GAL_SetError("FBCON NEWGAL Engine: Couldn't get console pixel format\n"); 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. */ 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; } }#if defined(_LITE_VERSION) && !defined(_STAND_ALONE) if (mgIsServer) {#endif /* 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;#if defined(_LITE_VERSION) && !defined(_STAND_ALONE) }#endif /* Fill in our hardware acceleration capabilities */ this->info.hw_available = 1; this->info.video_mem = finfo.smem_len/1024; if ( mapped_io ) { switch (finfo.accel) { case FB_ACCEL_MATROX_MGA2064W: case FB_ACCEL_MATROX_MGA1064SG: case FB_ACCEL_MATROX_MGA2164W: case FB_ACCEL_MATROX_MGA2164W_AGP: case FB_ACCEL_MATROX_MGAG100: /*case FB_ACCEL_MATROX_MGAG200: G200 acceleration broken! */ case FB_ACCEL_MATROX_MGAG400:#ifdef FBACCEL_DEBUG fprintf(stderr, "FBCON NEWGAL Engine: Matrox hardware accelerator!\n");#endif FB_MatroxAccel(this, finfo.accel); break; case FB_ACCEL_3DFX_BANSHEE:#ifdef FBACCEL_DEBUG fprintf(stderr, "FBCON NEWGAL Engine: 3DFX hardware accelerator!\n");#endif FB_3DfxAccel (this, finfo.accel); break;#ifdef FB_ACCEL_NEOMAGIC_NM2070 case FB_ACCEL_NEOMAGIC_NM2200: case FB_ACCEL_NEOMAGIC_NM2230: case FB_ACCEL_NEOMAGIC_NM2360: case FB_ACCEL_NEOMAGIC_NM2380:#ifdef FBACCEL_DEBUG fprintf(stderr, "FBCON NEWGAL Engine: NeoMagic hardware accelerator!\n");#endif
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -