📄 scr_fb.c
字号:
/*** $Id: scr_fb.c,v 1.29 2004/09/16 02:08:23 panweiguo Exp $** ** scr_fb.c: GAL driver for Linux kernel FrameBuffers.** ** Copyright (C) 2003 Feynman Software.** Copyright (C) 2000 Song Lixin.*//*** 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*/#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <unistd.h>#include "native.h"#ifdef _NATIVE_GAL_FBCON#include <sys/ioctl.h>#include <sys/mman.h>#include <sys/stat.h>#include <sys/time.h>#include <sys/types.h>#include <fcntl.h>#include <limits.h>#include <linux/fb.h>#include <linux/kd.h>#include <linux/vt.h>#include "fb.h"#ifdef _LITE_VERSIONextern BOOL mgIsServer;#endif#ifndef FB_TYPE_VGA_PLANES#define FB_TYPE_VGA_PLANES 4#endif/* static variables*/static int fb; /* Framebuffer file handle. */static int status; /* 0=never inited, 1=once inited, 2=inited. */static short saved_red[16]; /* original hw palette*/static short saved_green[16];static short saved_blue[16];#ifdef _HAVE_TEXT_MODEstatic int tty = -1;#endif/* init framebuffer*/static PSD fb_open(PSD psd){ char * env; int type, visual; PSUBDRIVER subdriver; struct fb_fix_screeninfo fb_fix; struct fb_var_screeninfo fb_var; /* locate and open framebuffer, get info*/ if(!(env = getenv ("FRAMEBUFFER"))) env = "/dev/fb0"; fb = open(env, O_RDWR); if(fb < 0) { fprintf(stderr,"GAL fbcon engine: Error when opening %s: %m. Please check kernel config.\n", env); return NULL; } if(ioctl(fb, FBIOGET_FSCREENINFO, &fb_fix) == -1 || ioctl(fb, FBIOGET_VSCREENINFO, &fb_var) == -1) { fprintf(stderr,"GAL fbcon engine: Error when reading screen info: %m.\n"); goto fail; } /* setup screen device from framebuffer info*/ type = fb_fix.type; visual = fb_fix.visual; psd->xres = psd->xvirtres = fb_var.xres; psd->yres = psd->yvirtres = fb_var.yres; /* set planes from fb type*/ if (type == FB_TYPE_VGA_PLANES) psd->planes = 4; else if (type == FB_TYPE_PACKED_PIXELS) psd->planes = 1; else psd->planes = 0; /* force error later*/ psd->bpp = fb_var.bits_per_pixel; psd->ncolors = (psd->bpp >= 24)? (1 << 24): (1 << psd->bpp); /* set linelen to byte length, possibly converted later*/ psd->linelen = (psd->xres * psd->bpp) >> 3; /* * Some framebuffer drivers give wrong line_length value. * If line_length < xres_virtual * bpp, it's certainly wrong. * But how do i know if line_length > xres_virtual * bpp. * God bless me! * James Liu */#ifndef _FXRM9200_IAL /* workaround for Fuxu RM9200 */ if (fb_fix.line_length > psd->linelen) psd->linelen = fb_fix.line_length;#endif psd->size = 0; /* force subdriver init of size*/ psd->flags = PSF_SCREEN; /* * For 1bpp, 2bpp and 4bpp framebuffer, some systems have * different bit order. That means the highest bits represent * the first pixel or the lowest bites represent first pixel. * * For example: * * EP7211 2bpp: Byte 1 Byte 2 * | D0 D1 | D2 D3 | D4 D5 | D6 D7 | | D0 D1 | D2 D3 | D4 D5 | D6 D7 | * | pixel0 | pixel1 | pixel2 | pixel3 | | pixel4 | pixel5 | pixel6 | pixel7 | * * Helio 2bpp: Byte 1 Byte 2 * | D0 D1 | D2 D3 | D4 D5 | D6 D7 | | D0 D1 | D2 D3 | D4 D5 | D6 D7 | * | pixel3 | pixel2 | pixel1 | pixel0 | | pixel7 | pixel6 | pixel5 | pixel4 | */#ifndef _L7200_IAL /* workaround for ZhongYuan L7200 */ if (fb_var.red.msb_right)#endif psd->flags |= PSF_MSBRIGHT; /* set pixel format*/ if (visual == FB_VISUAL_TRUECOLOR || visual == FB_VISUAL_DIRECTCOLOR) { switch(psd->bpp) { case 8: psd->pixtype = PF_TRUECOLOR332; break; case 16: psd->pixtype = PF_TRUECOLOR565; break; case 24: psd->pixtype = PF_TRUECOLOR888; break; case 32: psd->pixtype = PF_TRUECOLOR0888; break; default: fprintf(stderr, "GAL fbcon engine: Unsupported FrameBuffer type\n"); goto fail; } } else psd->pixtype = PF_PALETTE; /* select a framebuffer subdriver based on planes and bpp*/ subdriver = select_fb_subdriver(psd); if (!subdriver) { fprintf(stderr,"GAL fbcon engine: No driver for screen type %d visual %d bpp %d\n", type, visual, psd->bpp); goto fail; } /* * set and initialize subdriver into screen driver * psd->size is calculated by subdriver init */ if(!set_subdriver(psd, subdriver, TRUE)) { fprintf(stderr,"GAL fbcon engine: Driver initialize failed type %d visual %d bpp %d\n", type, visual, psd->bpp); goto fail; }#ifdef _HAVE_TEXT_MODE#ifdef _LITE_VERSION if (mgIsServer)#endif { /* open tty, enter graphics mode*/ 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"; tty = open (tty_dev, O_RDWR); if(tty < 0) { fprintf(stderr,"GAL fbcon engine: Can't open /dev/tty0: %m\n"); goto fail; } if(ioctl (tty, KDSETMODE, KD_GRAPHICS) == -1) { fprintf(stderr,"GAL fbcon engine: Error when setting console to graphics mode: %m\n"); fprintf(stderr,"GAL fbcon engine: Maybe have no enough permission.\n"); goto fail; } }#endif /* mmap framebuffer into this address space*/ psd->size = (psd->size + getpagesize () - 1) / getpagesize () * getpagesize ();#ifdef _FXRM9200_IAL /* workaround for Fuxu RM9200 */ psd->addr = mmap(NULL, psd->size, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0);#elif defined (__uClinux__) psd->addr = mmap(NULL, psd->size, PROT_READ | PROT_WRITE, 0, fb, 0);#else psd->addr = mmap(NULL, psd->size, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0);#endif if(psd->addr == NULL || psd->addr == (unsigned char *)-1) { fprintf(stderr,"GAL fbcon engine: Error when mmaping %s: %m\n", env); goto fail; } /* save original palette*/ ioctl_getpalette(0, 16, saved_red, saved_green, saved_blue); status = 2; psd->gr_mode = MODE_SET; return psd; /* success*/fail:#ifdef _HAVE_TEXT_MODE#ifdef _LITE_VERSION if (mgIsServer) {#endif /* enter text mode*/ if (tty >= 0) { ioctl (tty, KDSETMODE, KD_TEXT); close (tty); tty = -1; }#ifdef _LITE_VERSION }#endif#endif close(fb); return NULL;}/* close framebuffer*/static void fb_close(PSD psd){ /* if not opened, return*/ if(status != 2) return; status = 1; /* reset hw palette*/ ioctl_setpalette(0, 16, saved_red, saved_green, saved_blue); /* unmap framebuffer*/ munmap(psd->addr, psd->size); #ifdef _HAVE_TEXT_MODE#ifdef _LITE_VERSION if (mgIsServer) {#endif /* enter text mode*/ if (tty >= 0) { ioctl (tty, KDSETMODE, KD_TEXT); close (tty); tty = -1; }#ifdef _LITE_VERSION }#endif#endif /* close framebuffer*/ close(fb);}static int fade = 100;static void fb_setpalette(PSD psd,int first, int count, GAL_Color *palette){ int i; unsigned short red[count]; unsigned short green[count]; unsigned short blue[count]; /* convert palette to framebuffer format*/ for(i=0; i < count; i++) { GAL_Color *p = &palette[i]; /* grayscale computation: * red[i] = green[i] = blue[i] = * (p->r * 77 + p->g * 151 + p->b * 28); */ red[i] = (p->r * fade / 100) << 8; green[i] = (p->g * fade / 100) << 8; blue[i] = (p->b * fade / 100) << 8; } ioctl_setpalette(first, count, red, green, blue);}static void fb_getpalette(PSD psd,int first, int count, GAL_Color *palette){ int i; unsigned short red[count]; unsigned short green[count]; unsigned short blue[count]; ioctl_getpalette(first,count,red,green,blue); for(i=0; i < count; i++) { GAL_Color *p = &palette[i]; /* grayscale computation: * red[i] = green[i] = blue[i] = * (p->r * 77 + p->g * 151 + p->b * 28); */ p->r = (red[i] >> 8) * 100 / fade; p->g = (green[i] >>8) * 100 / fade; p->b = (blue[i] >>8) * 100 / fade; }}/* get framebuffer palette*/void ioctl_getpalette(int start, int len, short *red, short *green, short *blue){ struct fb_cmap cmap; cmap.start = start; cmap.len = len; cmap.red = red; cmap.green = green; cmap.blue = blue; cmap.transp = NULL; ioctl(fb, FBIOGETCMAP, &cmap);}/* set framebuffer palette*/void ioctl_setpalette(int start, int len, short *red, short *green, short *blue){ struct fb_cmap cmap; cmap.start = start; cmap.len = len; cmap.red = red; cmap.green = green; cmap.blue = blue; cmap.transp = NULL; //printf ("enter ioctl_setpalette\n"); //ioctl(fb, FBIOPUTCMAP, &cmap);}SCREENDEVICE scrdev = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, fb_open, fb_close, fb_setpalette, fb_getpalette, native_gen_allocatememgc, fb_mapmemgc, native_gen_freememgc, native_gen_clippoint, native_gen_fillrect, NULL, /* DrawPixel subdriver*/ NULL, /* ReadPixel subdriver*/ NULL, /* DrawHLine subdriver*/ NULL, /* DrawVLine subdriver*/ NULL, /* Blit subdriver*/ NULL, /* PutBox subdriver*/ NULL /* CopyBox subdriver*/};#endif /* _NATIVE_GAL_FBCON */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -