Frambuffer的学习

发布于:2024-09-18 ⋅ 阅读:(195) ⋅ 点赞:(0)

Frambufffer也称为帧缓存、帧缓冲,是Linux内核中将显存进行抽象后的一块缓存(内存),目的是为了给用户态进程提供一套直接写屏的接口,而不用关心物理显存的位置、换页机制等具体的细节问题,允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。

由于显存空间无法直接访问,故采用内存映射的方式进行访问显存空间:

内存映射的方式:

1.打开显示设备;

2.获取显示设备的相关参数;

3.建立内存映射;

4.写入RGB颜色值;

5.解除映射;

6.关闭显示设备;

#include "framebuffer.h"
#include <linux/fb.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <math.h>

void *pmem;
struct fb_var_screeninfo vinf;

int init_fb(char *devname)
{
	//1. 打开显示设备
	int fd = open(devname, O_RDWR);	
	if (-1 == fd)
	{
		perror("fail open fb");
		return -1;
	}
	
	//2、获取显示设备相关参数 分辨率 位深度
	int ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinf);
	if (-1 ==ret)
	{
		perror("fail ioctl");
		return -1;
	}
	
	printf("xres = %d, yres = %d\n", vinf.xres, vinf.yres);
	printf("xres_virtual = %d, yres_virtual = %d\n", vinf.xres_virtual, vinf.yres_virtual);
	printf("bits_per_pixel : %d\n", vinf.bits_per_pixel);

	size_t len = vinf.xres_virtual * vinf.yres_virtual * vinf.bits_per_pixel/8;
	//3, 建立显存和用户空间的映射关系
	pmem = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
	if ((void *)-1 == pmem)
	{
		perror("fail mmap");
		return -1;
	}
	

	return fd;
}

void draw_point(int x, int y, unsigned int col)
{
	if (x >= vinf.xres || y >= vinf.yres)
	{
		return ;
	}
	if (vinf.bits_per_pixel == RGB888_FMT)
	{
		unsigned int *p = pmem;
		*(p + y * vinf.xres_virtual + x) = col;
	}
	else if (vinf.bits_per_pixel == RGB565_FMT)
	{
		unsigned short *p  = pmem;	
		*(p + y * vinf.xres_virtual + x) = col;
	}
	return ;
}

void uninit_fb(int fd)
{

	size_t len = vinf.xres_virtual * vinf.yres_virtual * vinf.bits_per_pixel/8;
	munmap(pmem, len);
	close(fd);
}


void draw_clear(unsigned int col)
{
	for (int j = 0; j < vinf.xres; j++)
	{
		for (int i = 0; i < vinf.yres; i++)
		{
			draw_point(i, j, col);
		}
	}
}

void draw_h_line(int x, int y, int len, unsigned int col)
{
	for (int i = x; i < x+len; i++)
	{
		draw_point(i, y, col);
	}
}
void draw_s_line(int x, int y, int len, unsigned int col)
{
	for (int i = y; i < y+len; i++)
	{
		draw_point(x, i, col);
	}
}

void draw_rectangle(int x, int y, int w, int h, unsigned int col)
{
	draw_h_line(x, y, w, col);
	draw_s_line(x, y, h, col);
	draw_s_line(x+w, y, h, col);
	draw_h_line(x, y+h, w, col);
}

void draw_x_line(int x1, int y1, int x2, int y2, unsigned int col)
{
	
	int x = 0;
	int y = 0;

	if (x1 == x2)
	{
		if (y2 > y1)
		{
			draw_s_line(x1, y1, y2-y1, col);
		}
		else
		{
			draw_s_line(x2, y2, y1-y2, col);		
		}
	}

	double k = (double)(y2-y1)/(double)(x2-x1);
	double b = y1 - k*x1;
   

	for (int x = (x1 > x2 ? x2 : x1); x <= (x1 > x2 ? x1 : x2); x++)
	{
		y = x * k + b;
		draw_point(x, y, col);
	}
	
	return ;
}


void draw_circle(int x0, int y0, int r, unsigned int col)
{
	int x = 0;
	int y = 0;
	for (double si = 0; si <= 360; si+=0.01)
	{
		x = r * cos(2 * 3.14159/360 *si) + x0;
		y = r * sin(2 * 3.14159/360 *si) + y0;
		draw_point(x, y, col);
		draw_point(x-1, y, col);
		draw_point(x+1, y, col);
		draw_point(x, y-1, col);
		draw_point(x, y+1, col);
	}
	
}


void draw_bmp(int x, int y, char *picname, int w, int h)
{
	int fd = open(picname, O_RDONLY);
	if (-1 == fd)
	{
		perror("fail open bmp");
		return ;
	}
	
	lseek(fd, 54, SEEK_SET);

	unsigned char r, g, b;

	unsigned char *buff = malloc(w*h*3);
	read(fd, buff, w*h*3);
	
	unsigned char *p = buff;
	for (int j = h-1; j >= 0; j--)
	{
		for (int i = 0; i < w; i++)
		{

			b = *p; p++;
			g = *p; p++;
			r = *p; p++;
			if (vinf.bits_per_pixel == RGB888_FMT)
			{
				unsigned int col = (r << 16) | (g << 8) | (b << 0);
				draw_point(i+x, j+y, col);
			}
			else if (vinf.bits_per_pixel == RGB565_FMT)
			{
				unsigned short col = ((r >> 3) << 11) | ((g >> 2) << 5) | ((b >> 3) << 0);
				draw_point(i+x, j+y, col);
			}
		}
	}

	free(buff);
	close(fd);
}




void draw_word(int x, int y, unsigned char *word, int w, int h, unsigned int col)
{

	for (int j = 0; j < h; j++)
	{
		for (int i = 0; i < w; i++)
		{
			unsigned char tmp = word[i+j*w];
			for (int k = 0; k < 8; k++)
			{
				if (tmp & 0x80)
				{
					draw_point(i*8+k+x, j+y, col);
				}
				else
				{
					//文字的背景色
				}
				tmp = tmp << 1;
			}
		}
	}
}

int draw_utf8(UTF8_INFO *info, int x, int y, char* zi, unsigned int col, unsigned int col1)
{
    unsigned long  out = 0 ;
    int ret = enc_utf8_to_unicode_one((unsigned char*)zi,&out);

    unsigned char* data = get_utf_data(info,out);
    unsigned char temp = 0 ;
    unsigned int i,j,k;
    unsigned int num = 0;
    for(i=0;i<info->height;i++)
    {
        for(j=0;j<info->width/8;j++)
        {
            temp = data[num++];
            for(k=0;k<8;k++)
            {
                if(0x80&temp)
                {
                    draw_point( x+k+j*8, y+i, col);
                }
                else
                {

                 //   draw_point( x+k+j*8, y+i, col1);
                }
                temp= temp<<1;
            }
        }

    }
    return ret;
}


int draw_utf8_str(UTF8_INFO *info, int arg_x, int arg_y,  char* zi, unsigned int col, unsigned int col1)
{
    char* temp = zi;
    unsigned int x = arg_x ;
    unsigned int y =  arg_y;

    while(*temp != '\0')
    {
        int ret = draw_utf8(info, x, y, temp, col, col1);
        x += info->width;
        if(x > vinf.xres)
        {
            x = 0;
            y += info->height;
            if(y > vinf.yres)
            {
                y = 0;
            }
        }

        temp += ret;
    }
    return 0;
}








网站公告

今日签到

点亮在社区的每一天
去签到