Framebuffer 程序分析


Framebuffer 程序分析文章插图
来源:百问网
作者:韦东山
本文字数:2392 , 阅读时长:5分钟
使用 GIT 下载所有源码后 , 本节源码位于如下目录:
01_all_series_quickstart\04_嵌入式 Linux 应用开发基础知识\source\07_framebuffer\show_pixel.c1、打开设备【Framebuffer 程序分析】首先打开设备节点:
73 fd_fb = open("/dev/fb0", O_RDWR);74 if (fd_fb < 0)75 {76 printf("can't open /dev/fb0\n");77 return -1;78 }2、获取 LCD 参数LCD 驱动程序给 APP 提供 2 类参数:可变的参数 fb_var_screeninfo、固定的参数 fb_fix_screeninfo 。
编写应用程序时主要关心可变参数 , 它的结构体定义如下(#include ):
Framebuffer 程序分析文章插图
可以使用以下代码获取 fb_var_screeninfo:
12 static struct fb_var_screeninfo var; /* Current var */……79 if (ioctl(fd_fb, FBIOGET_VSCREENINFO, 82 return -1;83 }注意到 ioctl 里用的参数是:FBIOGET_VSCREENINFO , 它表示 get var screen info , 获得屏幕的可变信息;当然也可以使用 FBIOPUT_VSCREENINFO 来调整这些参数 , 但是很少用到 。
对于固定的参数 fb_fix_screeninfo , 在应用编程中很少用到 。 它的结构体定义如下:
Framebuffer 程序分析文章插图
可以使用 ioctl FBIOGET_FSCREENINFO 来读出这些信息 , 但是很少用到 。
3、映射 Framebuffer要映射一块内存 , 需要知道它的地址──这由驱动程序来设置 , 需要知道它的大小──这由应用程序决定 。 代码如下:
85 line_width = var.xres * var.bits_per_pixel / 8;86 pixel_width = var.bits_per_pixel / 8;87 screen_size = var.xres * var.yres * var.bits_per_pixel / 8;88 fb_base = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);89 if (fb_base == (unsigned char *)-1)90 {91 printf("can't mmap\n");92 return -1;93 }第 88 行中 , screen_size 是整个 Framebuffer 的大小;PROT_READ | PROT_WRITE 表示该区域可读、可写;MAP_SHARED 表示该区域是共享的 , APP 写入数据时 , 会直达驱动程序 , 这个参数的更深刻理解可以参考后面驱动基础中讲到的 mmap 知识 。
4、描点函数能够在 LCD 上描绘指定像素后 , 就可以写字、画图 , 描点函数是基础 。 代码如下:
28 void lcd_put_pixel(int x, int y, unsigned int color)29 {30 unsigned char *pen_8 = fb_base+y*line_width+x*pixel_width;31 unsigned short *pen_16;32 unsigned int *pen_32;3334 unsigned int red, green, blue;3536 pen_16 = (unsigned short *)pen_8;37 pen_32 = (unsigned int *)pen_8;3839 switch (var.bits_per_pixel)40 {41 case 8:42 {43 *pen_8 = color;44 break;45 }46 case 16:47 {48 /* 565 */49 red = (color >> 16) 50 green = (color >> 8) 51 blue = (color >> 0) 52 color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);53 *pen_16 = color;54 break;55 }56 case 32:57 {58 *pen_32 = color;59 break;60 }61 default:62 {63 printf("can't surport %dbpp\n", var.bits_per_pixel);64 break;65 }66 }67 }

  • 第 28 行中传入的 color 表示颜色 , 它的格式永远是 0x00RRGGBB , 即 RGB888 。 当 LCD 是 16bpp 时 , 要把 color 变量中的 R、G、B 抽出来再合并成 RGB565 格式 。
  • 第 30 行计算(x,y)坐标上像素对应的 Framebuffer 地址 。
  • 第 43 行 , 对于 8bpp , color 就不再表示 RBG 三原色了 , 这涉及调色板的概念 , color 是调色板的值 。
  • 第 49~51 行 , 先从 color 变量中把 R、G、B 抽出来 。
  • 第 52 行 , 把 red、green、blue 这三种 8 位颜色值 , 根据 RGB565 的格式 , 只保留 red 中的高 5 位、green 中的高 6 位、blue 中的高 5 位 , 组合成一个新的 16 位颜色值 。
  • 第 53 行 , 把新的 16 位颜色值写入 Framebuffer 。
  • 第 58 行 , 对于 32bpp , 颜色格式跟 color 参数一致 , 可以直接写入 Framebuffer 。
5、随便画几个点本程序的 main 函数 , 在最后只是简单地画了几个点:
95 /* 清屏: 全部设为白色 */96 memset(fbmem, 0xff, screen_size);9798 /* 随便设置出 100 个为红色 */99 for (i = 0; i < 100; i++)100 lcd_put_pixel(var.xres/2+i, var.yres/2, 0xFF0000);「新品首发」STM32MP157开发板火爆预售!首批仅300套