📄 framebuffer.c
字号:
/*
* framebuffer.c --- Primary C Source file of
* LCD Device Driver with Framebuffer
* for MGUI
* (C)opyright 2004 Bit 920 Labs
*
* Written by: Ye Nan <bye200009123@163.com>
* Created on: Sat. Mar 6 22:03:45 GMT +8:00 2004
*/
#ifndef __GAL_DRIVER_FB_C
#define __GAL_DRIVER_FB_C
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <linux/fb.h>
#include <linux/kd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <termios.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include "../gal.h"
#include "framebuffer.h"
int current_vt;
struct termios term;
// Framebuffer device routine
int fb_con = 0; /* framebuffer device handle */
void * frame_base = 0; /* lcd framebuffer base address */
GAL_CLIP fb_clip; /* clipping infomation */
// Framebuffer initialization.
// Failed return -1, succeed return 0.
int fb_Init(void)
{
struct fb_fix_screeninfo finfo; /* fixed screen information */
struct fb_var_screeninfo vinfo; /* variable screen information */
struct termios current;
unsigned short red[256], green[256], blue[256];
struct fb_cmap new_map = {0, 256, red, green, blue, NULL}; /* new system palette */
tcgetattr(0, &term);
current = term;
current.c_lflag &= ~ICANON;
current.c_lflag &= ~ECHO;
current.c_cc[VMIN] = 1;
current.c_cc[VTIME] = 0;
tcsetattr(0, TCSANOW, ¤t);
// Open vitual terminal
current_vt = open("/dev/tty", O_RDWR);
ioctl(current_vt, KDSETMODE, KD_GRAPHICS);
// Open framebuffer device
fb_con = open("/dev/fb0", O_RDWR, 0);
if (fb_con < 0)
{
printf("Can't open /dev/fb0.\n");
return -1;
}
// Get fixed screen information
if (ioctl(fb_con, FBIOGET_FSCREENINFO, &finfo) < 0)
{
printf("Can't get FSCREENINFO.\n");
close(fb_con);
return -1;
}
// Get variable screen information
if (ioctl(fb_con, FBIOGET_VSCREENINFO, &vinfo) < 0)
{
printf("Can't get VSCREENINFO.\n");
close(fb_con);
return -1;
}
// Palette opertion
srand(time(0));
// Make up a new palette
fb_MakePalette(&new_map);
// Apply new framebuffer palette
if (finfo.visual == FB_VISUAL_DIRECTCOLOR || vinfo.bits_per_pixel == 8)
{
if (ioctl(fb_con, FBIOPUTCMAP, &new_map) < 0)
{
printf("Error putting Colormap.\n");
return -1;
}
}
// Configure framebuffer color settings
switch (vinfo.bits_per_pixel)
{
case 8:
fb_pixel_size = 1;
break;
case 16:
fb_pixel_size = 2;
vinfo.red.offset = 11;
vinfo.red.length = 5;
vinfo.green.offset = 5;
vinfo.green.length = 6;
vinfo.blue.offset = 0;
vinfo.blue.length = 5;
break;
default:
fprintf(stderr, "Current color depth is NOT surpported.\n");
fb_pixel_size = 1;
break;
}
// Apply new settings to the framebuffer
if (ioctl(fb_con, FBIOPUT_VSCREENINFO, &vinfo) < 0)
{
fprintf(stderr, "Couldn't set ideal mode at FBIOPUT_VSCREENINFO");
return -1;
}
// Retrieve screen size information
if (ioctl(fb_con, FBIOGET_VSCREENINFO, &vinfo) < 0)
{
fprintf(stderr, "ioctl FBIOGET_VSCREENINFO");
return -1;
}
fb_width = vinfo.xres_virtual;
fb_height = vinfo.yres_virtual;
fb_bpp = vinfo.bits_per_pixel;
fb_line_size = finfo.line_length;
fb_buffer_size = finfo.smem_len;
// Map frame buffer to a vitual memory area
frame_base = mmap(NULL, BUFFER_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fb_con, 0);
if (frame_base == MAP_FAILED)
{
fprintf(stderr, "Can't mmap.\n");
close(fb_con);
return -1;
}
printf("\nVideo memory address = 0x%x\n",frame_base);
printf("Video visible resolution: x_res = %ld, y_res = %ld\n", SCREEN_WIDTH, SCREEN_HEIGHT);
// Initialize clipping infomation
fb_clip.clipmin_x = 0;
fb_clip.clipmin_y = 0;
fb_clip.clipmax_x = fb_width - 1;
fb_clip.clipmax_y = fb_height - 1 ;
// Clear screen
fb_Clear(0x00000000);
return 0;
}
// Framebuffer release
void fb_Release(void)
{
fb_AssertDevice(fb_con);
// release the vitual memeory area of frame buffer
munmap(frame_base, BUFFER_SIZE);
// close framebuffer device
if(fb_con)
close(fb_con);
tcsetattr(0, TCSANOW, &term);
return;
}
// Assert device is opened
int fb_AssertDevice(int dev)
{
if (dev == 0)
{
printf("Device is NOT opened.\n");
return -1;
}
return 0;
}
// Make up System Palette
void fb_MakePalette(struct fb_cmap *map)
{
int rs, gs, bs, i;
int r = 8, g = 8, b = 4;
if (map == NULL)
return;
rs = 256 / (r - 1);
gs = 256 / (g - 1);
bs = 256 / (b - 1);
for (i = 0; i < 256; i++)
{
map->red[i] = (rs * ((i / (g * b)) % r)) * 255;
map->green[i] = (gs * ((i / b) % g)) * 255;
map->blue[i] = (bs * ((i) % b)) * 255;
}
return;
}
// Save System Palette
int fb_SavePalette(struct fb_cmap * map)
{
fb_AssertDevice(fb_con);
if (BPP == 8)
{
if (ioctl(fb_con, FBIOGETCMAP, map) < 0)
{
printf("Save system palette failed.\n");
return -1;
}
}
return 0;
}
// Update System Palette
int fb_UpdatePalette(struct fb_cmap map)
{
fb_AssertDevice(fb_con);
if (BPP == 8)
{
if(ioctl(fb_con, FBIOPUTCMAP, &map) < 0)
{
printf("Update system palette failed.\n");
return -1;
}
}
return 0;
}
// Retrieve base address of frame buffer
void * fb_GetFrameAddr()
{
return frame_base;
}
// Retrieve screen width
unsigned int fb_GetScreenWidth()
{
return SCREEN_WIDTH;
}
// Retrieve screen height
unsigned int fb_GetScreenHeight()
{
return SCREEN_HEIGHT;
}
// Retrieve screen bpp(bits per pixel)
unsigned int fb_GetScreenBpp()
{
return BPP;
}
// Retrieve screen colors
unsigned int fb_GetScreenColors()
{
return (1 << BPP);
}
// Clear screen with specified color
void fb_Clear(ColorType color)
{
short currLine;
unsigned long startOffset;
void * currPoint;
int x;
startOffset = fb_clip.clipmin_y * LINE_SIZE + fb_clip.clipmin_x * PIXEL_SIZE;
// Directly access memory instead of call putpixel function
// to make more effective performance of drawing a line
for (currLine = fb_clip.clipmin_y; currLine <= fb_clip.clipmax_y; currLine++)
{
currPoint = frame_base + startOffset;
for (x = fb_clip.clipmin_x; x <= fb_clip.clipmax_x; x++)
{
switch (BPP)
{
case 8:
*(ByteType *)currPoint = _COLOR24_16(color) & 0xff;
break;
case 16:
*(WordType *)currPoint = _COLOR24_16(color) & 0xffff;
break;
}
(ByteType *)currPoint += PIXEL_SIZE;
}
// Make a LINE_SIZE increment to the startOffset,
// in order to move point to the start position of next line
startOffset += SCREEN_WIDTH * PIXEL_SIZE;
}
return;
}
ColorType fb_MakeColor_16(ByteType red, ByteType green, ByteType blue)
{
ColorType color;
// Adjust RGB factors to fit 16 bit display
red >>= 3;
green >>= 2;
blue >>= 3;
// Use RGB factors to make up the display color
color = (red << 11 | green << 5 | blue);
return color;
}
// Put a color pixel on the screen
void fb_PutPixel(int x, int y, ColorType color/*, int xorm */)
{
void * currPoint;
ColorType c;
if (x < fb_clip.clipmin_x || x > fb_clip.clipmax_x ||
y < fb_clip.clipmin_y || y > fb_clip.clipmax_y)
{
#ifdef ERR_DEBUG
printf("DEBUG_INFO: Pixel out of clipping range.\n");
printf("DEBUG_INFO: x = %d, y = %d\n", x, y);
#endif
return;
}
// Calculate address of specified point
currPoint = (ByteType *)frame_base + y * LINE_SIZE + x * PIXEL_SIZE;
#ifdef DEBUG
printf("DEBUG_INFO: x = %d, y= %d, currPoint = 0x%x\n", x, y, currPoint);
#endif
switch (BPP)
{
case 8:
*((ByteType *)currPoint) = (_COLOR24_8(color) & 0xff);
break;
case 16:
*((WordType *)currPoint) = (_COLOR24_16(color) & 0xffff);
break;
}
return;
}
// Retrieve the color of specified pixel
ColorType fb_GetPixel(int x, int y)
{
void * currPoint;
ColorType color;
if (x < fb_clip.clipmin_x || x > fb_clip.clipmax_x ||
y < fb_clip.clipmin_y || y > fb_clip.clipmax_y)
{
#ifdef ERR_DEBUG
printf("DEBUG_INFO: Pixel out of screen range.\n");
printf("DEBUG_INFO: x = %d, y = %d\n", x, y);
#endif
return;
}
// Calculate address of specified point
currPoint = (ByteType *)frame_base + y * LINE_SIZE + x * PIXEL_SIZE;
#ifdef DEBUG
printf("DEBUG_INFO: x = %d, y= %d, currPoint = 0x%x\n", x, y, currPoint);
#endif
switch (BPP)
{
case 8:
color = *((ByteType *)currPoint);
break;
case 16:
color = *((WordType *)currPoint);
break;
}
return color;
}
// Draw a horizontal line on the screen
void fb_DrawLine_H(int x1, int x2, int y, ColorType color/*, int xorm */)
{
long startOffset = 0;
void * currPoint;
int x;
x1 = (x1 < fb_clip.clipmin_x) ? fb_clip.clipmin_x : x1;
x2 = (x2 < fb_clip.clipmin_x) ? fb_clip.clipmin_x : x2;
x1 = (x1 > fb_clip.clipmax_x) ? fb_clip.clipmax_x : x1;
x2 = (x2 > fb_clip.clipmax_x) ? fb_clip.clipmax_x : x2;
if (y < fb_clip.clipmin_y || y > fb_clip.clipmax_y)
{
#ifdef ERR_DEBUG
printf("DEBUG_INFO: Pixel out of screen range.\n");
printf("DEBUG_INFO: x1 = %d, x2 = %d, y = %d\n", x1, x2, y);
#endif
return;
}
if (x1 > x2)
{
short tmp;
tmp = x1;
x1 = x2;
x2 = tmp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -