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

📄 framebuffer.c

📁 ARM&linux 嵌入式系统 开发程序样例
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *	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, &current);
	
	// 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 + -