Linux framebuffer programming
framebuffer and memory
framebuffer is a memory area, provide “/dev/fbN” to access it.
open framebuffer
int fbdev_fd = open("/dev/fb0",O_RDWR);
get framebuffer size
struct fb_fix_screeninfo fbdev_finfo;
ioctl(fbdev_fd, FBIOGET_FSCREENINFO, &fbdev_finfo);
uint32_t fbdev_size = fbdev_finfo.smem_len;
use mmap()
uint8_t *fbdev_mem = (uint8_t *)mmap(NULL,fbdev_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, fbdev_fd ,0);
memset(fbdev_mem, 0, fbdev_size); // make screen blank
use read() / write()
uint8_t *buf = (uint8_t *)malloc(fbdev_size);
memset(buf,0,fbdev_size);
write(fbdev_fd, buf, fbdev_size); // make screen blank
framebuffer data format
You can get and set parts of the color map. Communication is done with
16 bits per color part (red, green, blue, transparency) to support all
existing hardware. The driver does all the computations needed to
apply it to the hardware (round it down to less bits, maybe throw
away transparency).
-- from:https://www.kernel.org/doc/html/latest/fb/framebuffer.html
get bits per pixel
struct fb_var_screeninfo fbdev_vinfo;
ioctl(fbdev_fd, FBIOGET_VSCREENINFO, &fbdev_vinfo);
// you need fbdev_vinfo.bits_per_pixel
if bits_per_pixel is 8, it mean a pixel in memory use 1 bytes.
if bits_per_pixel is 32, it mean a pixel in memory use 4 bytes.
draw pixel
void fbdev_draw_pixel(uint x, uint y, uint32_t color) {
// position in framebuffer, you can also use lseek(), write()
int pos = y * fbdev_finfo.line_length +
x * fbdev_vinfo.bits_per_pixel / 8;
uint8_t *fbp8 = (uint8_t *)fbdev_mem + pos;
uint16_t *fbp16 = (uint16_t *)fbp8;
uint32_t *fbp32 = (uint32_t *)fbp8;
switch(fbdev_vinfo.bits_per_pixel) {
case 32:
*fbp32 = color;
break;
case 16:
*fbp16 = color;
break;
case 8:
*fbp8 = color;
break;
default:
*fbp8 = color;
break;
}
return;
}
example:
fbdev_draw_pixel(100,100,0xFFFFFF);
you will see a white point on screen (100,100)
draw char use bitmap font
a simple 8x8 bitmap font define:
uint8_t bm_0[8] = {
0b00000000,
0b01111110,
0b01000010,
0b01000010,
0b01000010,
0b01000010,
0b01111110,
0b00000000
};
draw this font use printf:
int x, y;
for (y = 0; y < 8; y++) {
for (x = 0; x < 8; x++) {
if (bm_0[y] & 1 << x)
putchar('#');
else
putchar(' ');
}
putchar('\n');
}
draw this font on framebuffer:
int pos_x, pos_y;
pos_x = 100;
pos_y = 50;
int x, y;
for (y = 0; y < 8; y++) {
for (x = 0; x < 8; x++) {
if (bm_0[y] & 1 << x)
fbdev_draw_pixel(pos_x+x,pos_y+y,0xFFFFFF);
else
fbdev_draw_pixel(pos_x+x,pos_y+y,0x000000);
}
}
this code will draw a 0 on screen (100,50) .