The use of framebuffer under Linux

Reprinted from:

https://www.cnblogs.com/xiaojianliu/p/8473095.html

 

framebuffer framebuffer

Framebuffer is an interface provided by the Linux system for display devices. It abstracts the display buffer, shields the underlying differences in image hardware, and allows upper-layer applications to directly read and write the display buffer in graphics mode. Users do not need to care about the specific location and storage method of the physical display buffer, as these are completed by the frame buffer device driver itself.
    The framebuffer mechanism imitates the function of the graphics card, abstracting the graphics card hardware structure into a series of data structures, and can directly operate the video memory through the reading and writing of the framebuffer. Users can think of the framebuffer as an image of video memory. After mapping it to the process space, they can directly perform read and write operations, and the write operations will be directly reflected on the screen.

The frame buffer device is a standard character device. In Linux, the major device number is 29, which is defined in FB_MAJOR in /include/linux/major.h. The minor device number defines the number of frame buffers. The maximum allowed is 32 FrameBuffers, defined FB_MAX in /include/linux/fb.h corresponds to the /dev/fb%d device file in the file system, using the following method (the number in front indicates the minor device number): 0 =
      /dev/fb0 first fb Device
      1 = /dev/fb1 second fb device

fb is also a common memory device. It can read, write, seek and mmap like a memory device (/dev/mem). But the difference is that fb does not use the entire memory area, but part of the video memory.

The typical display mechanism is shown in the figure:

Return to table of contents

FB interaction with applications 

For user programs, there is no difference between it and other devices. Users can regard fb as a piece of memory, and can both write data to the memory and read data. The fb display buffer is located in the kernel space. The application can map this space to its own user space and perform operations.

(1) In the application, the general steps to operate /dev/fbn are as follows:
Open the /dev/fbn device file.

(2) Use ioctl() operation to obtain the parameters of the current display screen, such as screen resolution and the number of bits per pixel. The size of the screen buffer can be calculated based on the screen parameters.

(3) Use the mmap() function to map the screen buffer to user space.

(4) After mapping, you can directly read/write the screen buffer for drawing and picture display.

(5) The frame buffer device needs to be released after use.

(6) Close the file.

 

Return to table of contents

fb control

ioctl is used to control fb with various commands. The implementation of control is defined in <linux/fb.h>. This header file is in the kernel source code. Since it is included in the cross-compiler, we can call it directly at the application layer.

<linux/fb.h>, which defines some ioctl commands

/* ioctls

   0x46 is 'F'                              */

#define FBIOGET_VSCREENINFO 0x4600

#define FBIOPUT_VSCREENINFO 0x4601

#define FBIOGET_FSCREENINFO 0x4602

#define FBIOGETCMAP     0x4604

#define FBIOPUTCMAP     0x4605

#define FBIOPAN_DISPLAY     0x4606

We mainly use the FBIOGET_VSCREENINFO and FBIOGET_FSCREENINFO commands. From the literal meaning, it is not difficult to see that the meanings of these two commands are:

fb's ioctl, to get variable screen info: Get the parameters that the application can change (such as the set resolution)

fb's ioctl, to get fixed screen info: Get fixed parameters (such as screen resolution, usually just for a look)

<linux/fb.h> also provides a special structure type to store the above two parameters.

The structure type that stores variable parameters: struct fb_var_screeninfo. For its detailed definition, please refer to the "Related Structures" section.

The more important variable parameters are:

xres, yres: x- and y-axis resolution of the visible screen (cannot be changed by the application layer)

xres_virtual, yres_virtual: virtual screen (i.e. fb) x, y axis resolution

xoffset, yoffset: x- and y-axis offsets of the visual screen relative to the virtual screen

bits_per_pixel: pixel depth

The virtual screen is generally set to (not necessarily) twice the size of the visible screen by default. This structure is called a "double buffering mechanism". The advantage of this is that it can display the next screen while buffering it.

 

Return to table of contents

Related structures

The relevant structures and their relationships are:

 

fb_var_screeninfo

This structure describes the characteristics of the graphics card.

Copy code

struct fb_var_screeninfo
{
    __u32 xres; /* visible resolution */
    __u32 yres;
    __u32 xres_virtual; /* virtual resolution */
    __u32 yres_virtual;
    __u32 xoffset; /* offset from virtual to visible resolution */
    __u32 yoffset;
    __u32 bits_per_pixel; /* guess what */
    __u32 grayscale; /* != 0 Gray levels instead of colors */
    struct fb_bitfield red; /* bitfield in fb mem if true color, */
    struct fb_bitfield green; /* else only length is significant */
    struct fb_bitfield blue;
    struct fb_bitfield transp; /* transparency */
    __u32 nonstd; /* != 0 Non standard pixel format */
    __u32 activate; /* see FB_ACTIVATE_* */
    __u32 height; /* height of picture in mm */
    __u32 width; /* width of picture in mm */
    __u32 accel_flags; /* acceleration flags (hints) */
    /* Timing: All values in pixclocks, except pixclock (of course) */
    __u32 pixclock; /* pixel clock in ps (pico seconds) */
    __u32 left_margin; /* time from sync to picture */
    __u32 right_margin; /* time from picture to sync */
    __u32 upper_margin; /* time from sync to picture */
    __u32 lower_margin;
    __u32 hsync_len; /* length of horizontal sync */
    __u32 vsync_len; /* length of vertical sync */
    __u32 sync; /* see FB_SYNC_* */
    __u32 vmode; /* see FB_VMODE_* */
    __u32 reserved[6]; /* Reserved for future compatibility */
};

Copy code

fb_fix_screeninfon

This structure is created after the graphics card is set to mode. It describes the properties of the graphics card and cannot be modified while the system is running; such as the starting address of the FrameBuffer memory. It depends on the set mode. When a mode is set, the memory information is given by the display card hardware, and the memory location and other information cannot be modified.

Copy code

struct fb_fix_screeninfo {
    char id[16]; /* identification string eg "TT Builtin" */
    unsigned long smem_start; /* Start of frame buffer mem */
    /* (physical address) */
    __u32 smem_len; /* Length of frame buffer mem */
    __u32 type; /* see FB_TYPE_* */
    __u32 type_aux; /* Interleave for interleaved Planes */
    __u32 visual; /* see FB_VISUAL_* */
    __u16 xpanstep; /* zero if no hardware panning */
    __u16 ypanstep; /* zero if no hardware panning */
    __u16 ywrapstep; /* zero if no hardware ywrap */
    __u32 line_length; /* length of a line in bytes */
    unsigned long mmio_start; /* Start of Memory Mapped I/O */
    /* (physical address) */
    __u32 mmio_len; /* Length of Memory Mapped I/O */
    __u32 accel; /* Type of acceleration available */
    __u16 reserved[3]; /* Reserved for future compatibility */
};

Copy code

fb_ops

User applications can use the ioctl() system call to operate the device. This structure is used to support these operations of ioctl().

Copy code

struct fb_ops { 
/* open/release and usage marking */ 
struct module *owner; 
int (*fb_open)(struct fb_info *info, int user); 
int (*fb_release)(struct fb_info *info, int user); 
/* get non settable parameters */ 
int (*fb_get_fix)(struct fb_fix_screeninfo *fix, int con, 
struct fb_info *info); 
/* get settable parameters */ 
int (*fb_get_var)(struct fb_var_screeninfo *var, int con, 
struct fb_info *info); 
/* set settable parameters */ 
int (*fb_set_var)(struct fb_var_screeninfo *var, int con, 
struct fb_info *info); 
/* get colormap */ 
int (*fb_get_cmap)(struct fb_cmap *cmap, int kspc, int con, 
struct fb_info *info); 
/* set colormap */ 
int (*fb_set_cmap)(struct fb_cmap *cmap, int kspc, int con, 
struct fb_info *info); 
/* pan display (optional) */ 
int (*fb_pan_display)(struct fb_var_screeninfo *var, int con, 
struct fb_info *info); 
/* perform fb specific ioctl (optional) */ 
int (*fb_ioctl)(struct inode *inode, struct file *file, unsigned int cmd, 
unsigned long arg, int con, struct fb_info *info); 
/* perform fb specific mmap */ 
int (*fb_mmap)(struct fb_info *info, struct file *file, struct 
vm_area_struct *vma); 
/* switch to/from raster image mode */ 
int (*fb_rasterimg)(struct fb_info *info, int start); 
};

Copy code

fb_cmap

Describes device-independent color mapping information. Color mapping information can be set or obtained through the ioctl operations corresponding to FBIOGETCMAP and FBIOPUTCMAP.

Copy code

struct fb_cmap { 
__u32 start; /* First entry */ 
__u32 len; /* Number of entries */ 
__u16 *red; /* Red values */ 
__u16 *green; 
__u16 *blue; 
__u16 *transp; /* transparency, can be NULL */ 
};

Copy code

fb_info

Defines the current state of the graphics card; the fb_info structure is only visible in the kernel. In this structure, there is an fb_ops pointer that points to the set of functions required to drive the device.

Copy code

struct fb_info { 
char modename[40]; /* default video mode */ 
kdev_t node; 
int flags; 
int open; /* Has this been open already ? */ 
#define FBINFO_FLAG_MODULE 1 /* Low-level driver is a module */ 
struct fb_var_screeninfo var; /* Current var */ 
struct fb_fix_screeninfo fix; /* Current fix */ 
struct fb_monspecs monspecs; /* Current Monitor specs */ 
struct fb_cmap cmap; /* Current cmap */ 
struct fb_ops *fbops; 
char *screen_base; /* Virtual address */ 
struct display *disp; /* initial display variable */ 
struct vc_data *display_fg; /* Console visible on this display */ 
char fontname[40]; /* default font name */ 
devfs_handle_t devfs_handle; /* Devfs handle for new name */ 
devfs_handle_t devfs_lhandle; /* Devfs handle for compat. symlink */ 
int (*changevar)(int); /* tell console var has changed */ 
int (*switch_con)(int, struct fb_info*); 
/* tell fb to switch consoles */ 
int (*updatevar)(int, struct fb_info*); 
/* tell fb to update the vars */ 
void (*blank)(int, struct fb_info*); /* tell fb to (un)blank the screen */ 
/* arg = 0: unblank */ 
/* arg > 0: VESA level (arg-1) */ 
void *pseudo_palette; /* Fake palette of 16 colors and 
the cursor's color for non 
palette mode */ 
/* From here on everything is device dependent */ 
void *par; 
};

Copy code

Return to table of contents

Usage examples

Copy code

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

#define FBDEVICE "/dev/fb0"
void draw_back(unsigned int *pfb, unsigned int width, unsigned int height, unsigned int color);

void draw_line(unsigned int *pfb, unsigned int width, unsigned int height);

int main(void)
{
    int fd = -1;
    int ret = -1;
    unsigned int *pfb = NULL;
    struct fb_fix_screeninfo finfo;
    struct fb_var_screeninfo vinfo;

    fd = open(FBDEVICE,O_RDWR);
    if (fd < 0)
    {
        perror("open");
        return -1;
    }
    printf("open %s success \n", FBDEVICE);

   
    ret = ioctl(fd, FBIOGET_FSCREENINFO, &finfo);
    if (ret < 0)
    {
        perror("ioctl");
        return -1;
    }

    ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
    if (ret < 0)
    {
        perror("ioctl");
        return -1;
    }
    
    pfb = (unsigned int *)mmap(NULL, finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (NULL == pfb)
    {
        perror("mmap");
        return -1;
    }
    printf("pfb :0x%x \n",*pfb);

    draw_back(pfb, vinfo.xres_virtual, vinfo.yres_virtual, 0xffff0000);
    draw_line(pfb, vinfo.xres_virtual, vinfo.yres_virtual);

    close(fd);
    return 0;
}


void draw_back(unsigned int *pfb, unsigned int width, unsigned int height, unsigned int color)
{
    unsigned int x, y;
    for (y = 0; y < height; y++)
    {
        for (x = 0; x < width; x++)
        {
            *(pfb + y * width + x) = color;
        }
    }
}

void draw_line(unsigned int *pfb, unsigned int width, unsigned int height)
{
    unsigned int x, y;
    for (x = 50; x < width - 50; x++)
    {
        *(pfb + 50 * width + x) = 0xffffff00;
    }
    for (y = 50; y < height -50; y++)
    {
        *(pfb + y * width + 50) = 0xffffff00;
    }
}

Copy code

 

Guess you like

Origin blog.csdn.net/lindonghai/article/details/91797409