• Linux驱动之Framebuffer子系统基础知识


    1、Linux Framebuffer概述

    Framebuffer驱动在Linux内核中用于子系统最重要的显示输出,以该驱动为基础,Linux设备才能向用户展现一个色彩斑斓的世界,对于PC而言,就是显卡驱动,对于嵌入式设备,就是显示控制器和LCD模组驱动。

    Framebuffer设备是一个字符设备,在文件系统中的设备节点通常为/dev/fbX,当一个系统中有多个显示设备时,依次使用/de/fb0、/dev/fb1等来表示。在Android系统中,该类设备的主设备号是29,Framebuffer设备也叫做"帧缓冲设备"。

    Frambuffer的显示框架如下所示:

    2、Framebuffer数据结构

    (1)fb_info结构体

    fb_info结构体是最重要的结构体,它代表着Framebuffer驱动,该结构体的定义如下:

    struct fb_info {
        atomic_t count;
        int node;
        int flags;
        struct mutex lock;        /* Lock for open/release/ioctl funcs */
        struct mutex mm_lock;        /* Lock for fb_mmap and smem_* fields */
        struct fb_var_screeninfo var;    /* Current var */
        struct fb_fix_screeninfo fix;    /* Current fix */
        struct fb_monspecs monspecs;    /* Current Monitor specs */
        struct work_struct queue;    /* Framebuffer event queue */
        struct fb_pixmap pixmap;    /* Image hardware mapper */
        struct fb_pixmap sprite;    /* Cursor hardware mapper */
        struct fb_cmap cmap;        /* Current cmap */
        struct list_head modelist;      /* mode list */
        struct fb_videomode *mode;    /* current mode */
    
    #ifdef CONFIG_FB_BACKLIGHT
        /* assigned backlight device */
        /* set before framebuffer registration, 
           remove after unregister */
        struct backlight_device *bl_dev;
    
        /* Backlight level curve */
        struct mutex bl_curve_mutex;    
        u8 bl_curve[FB_BACKLIGHT_LEVELS];
    #endif
    #ifdef CONFIG_FB_DEFERRED_IO
        struct delayed_work deferred_work;
        struct fb_deferred_io *fbdefio;
    #endif
    
        struct fb_ops *fbops;
        struct device *device;        /* This is the parent */
        struct device *dev;        /* This is this fb device */
        int class_flag;                    /* private sysfs flags */
    #ifdef CONFIG_FB_TILEBLITTING
        struct fb_tile_ops *tileops;    /* Tile Blitting */
    #endif
        union {
            char __iomem *screen_base;    /* Virtual address */
            char *screen_buffer;
        };
        unsigned long screen_size;    /* Amount of ioremapped VRAM or 0 */ 
        void *pseudo_palette;        /* Fake palette of 16 colors */ 
    #define FBINFO_STATE_RUNNING    0
    #define FBINFO_STATE_SUSPENDED    1
        u32 state;            /* Hardware state i.e suspend */
        void *fbcon_par;                /* fbcon use-only private area */
        /* From here on everything is device dependent */
        void *par;
        /* we need the PCI or similar aperture base/size not
           smem_start/size as smem_start may just be an object
           allocated inside the aperture so may not actually overlap */
        struct apertures_struct {
            unsigned int count;
            struct aperture {
                resource_size_t base;
                resource_size_t size;
            } ranges[0];
        } *apertures;
    
        bool skip_vt_switch; /* no VT switch on suspend/resume required */
    };

    fb_info结构体记录了帧缓冲设备的全部信息,包括设备的设置参数、状态以及操作函数指针,对于每一个帧缓冲设备都必须对应一个fb_info结构体实例。

    (2)fb_ops结构体

    该结构体是fb_info结构体中的一个成员变量,指向显示操作的函数指针,这些函数需要驱动程序开发人去编写实现,该结构体的定义如下:

    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);
    
        /* For framebuffers with strange non linear layouts or that do not
         * work with normal memory mapped access
         */
        ssize_t (*fb_read)(struct fb_info *info, char __user *buf,
                   size_t count, loff_t *ppos);
        ssize_t (*fb_write)(struct fb_info *info, const char __user *buf,
                    size_t count, loff_t *ppos);
    
        /* checks var and eventually tweaks it to something supported,
         * DO NOT MODIFY PAR */
        int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
    
        /* set the video mode according to info->var */
        int (*fb_set_par)(struct fb_info *info);
    
        /* set color register */
        int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
                    unsigned blue, unsigned transp, struct fb_info *info);
    
        /* set color registers in batch */
        int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
    
        /* blank display */
        int (*fb_blank)(int blank, struct fb_info *info);
    
        /* pan display */
        int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
    
        /* Draws a rectangle */
        void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
        /* Copy data from area to another */
        void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
        /* Draws a image to the display */
        void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
    
        /* Draws cursor */
        int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
    
        /* wait for blit idle, optional */
        int (*fb_sync)(struct fb_info *info);
    
        /* perform fb specific ioctl (optional) */
        int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
                unsigned long arg);
    
        /* Handle 32bit compat ioctl (optional) */
        int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd,
                unsigned long arg);
    
        /* perform fb specific mmap */
        int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
    
        /* get capability given var */
        void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,
                    struct fb_var_screeninfo *var);
    
        /* teardown any resources to do with this framebuffer */
        void (*fb_destroy)(struct fb_info *info);
    
        /* called at KDB enter and leave time to prepare the console */
        int (*fb_debug_enter)(struct fb_info *info);
        int (*fb_debug_leave)(struct fb_info *info);
    #ifdef CONFIG_ARCH_HISI_BVT
    #ifdef CONFIG_DMA_SHARED_BUFFER
        /* Export the frame buffer as a dmabuf object */
        struct dma_buf *(*fb_dmabuf_export)(struct fb_info *info);
    #endif
    #endif
    };

    (3)fb_var_screeninfo结构体

    fb_var_screeninfo结构体也是fb_info结构体的成员变量,该结构体记录用户可修改的显示控制器参数,包括了屏幕的分辨率和每个像素点的比特数,该结构体的定义如下:

    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 */
        __u32 yoffset;            /* resolution            */
    
        __u32 bits_per_pixel;        /* guess what            */
        __u32 grayscale;        /* 0 = color, 1 = grayscale,    */
                        /* >1 = FOURCC            */
        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;        /* (OBSOLETE) see fb_info.flags */
    
        /* 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 rotate;            /* angle we rotate counter clockwise */
        __u32 colorspace;        /* colorspace for FOURCC-based modes */
        __u32 reserved[4];        /* Reserved for future compatibility */
    };

    (4)fb_fix_screeninfo结构体

    fb_fix_screeninfo结构体也是fb_info结构体的成员,该结构体中记录了用户不能修改的显示控制器的参数,比如说屏幕缓冲区的物理地址、长度等,当使用帧缓冲设备进行映射操作的时候,就是从fb_fix_screeninfo结构体中获取缓冲区物理地址,该结构体的定义如下:

    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;            /* Indicate to driver which    */
                        /*  specific chip/card we have    */
        __u16 capabilities;        /* see FB_CAP_*            */
        __u16 reserved[2];        /* Reserved for future compatibility */
    };

    (5)fb_bitfield结构体

    fb_bitfield结构体描述每一像素缓冲区的组织方式,包括域偏移、位域长度和MSB指示,该结构体的定义如下:

    struct fb_bitfield {
        __u32 offset;            /* beginning of bitfield    */
        __u32 length;            /* length of bitfield        */
        __u32 msb_right;        /* != 0 : Most significant bit is */ 
                        /* right */ 
    };

    (6)文件操作结构体

    帧缓冲设备作为一种字符设备,文件操作结构体定义于/linux/drivers/fbmem.c文件中,代码如下所示:

    static const struct file_operations fb_fops = {
        .owner =    THIS_MODULE,
        .read =        fb_read,
        .write =    fb_write,
        .unlocked_ioctl = fb_ioctl,
    #ifdef CONFIG_COMPAT
        .compat_ioctl = fb_compat_ioctl,
    #endif
        .mmap =        fb_mmap,
        .open =        fb_open,
        .release =    fb_release,
    #ifdef HAVE_ARCH_FB_UNMAPPED_AREA
        .get_unmapped_area = get_fb_unmapped_area,
    #endif
    #ifdef CONFIG_FB_DEFERRED_IO
        .fsync =    fb_deferred_io_fsync,
    #endif
        .llseek =    default_llseek,
    };

    帧缓冲设备驱动的文件操作接口函数已经在fbmem.c中被统一实现了,一般不需要驱动工程师再编写。

    3、Framebuffer驱动

    Framebuffer驱动的程序结构如下所示:

    Framebuffe的设备文件操作函数在fbmem.c中实现,而特定于帧缓冲设备fb_info结构体的注册、注销以及fb_info成员的维护,尤其是fb_ops成员函数的实现,则是在特定的xxxfb.c源码中去实现,其中,fb_ops中的成员函数最终会操作显示控制器以及LCD模组上的寄存器,进而实现对显示设备的控制以及数据的显示。

    在嵌入式系统中,常在RAM中分配一块显示缓冲区,也就是常说的显存,用来存放要输出到显示设备上的显示数据,显示数据一般会采用DMA的方式来传输。

    4、Android系统对Framebuffer的使用

    Android系统上层应用要想使用Framebuffer子系统硬件,需要符合HAL架构的,Android显示子系统的架构如下:

    显示子系统的HAL层有三个模板,其中Gralloc模块是显示子系统的主模块,主要负责往Framebuffer显存传送数据,Graphics driver模块是3D显示HAL模块,其负责调用3D引擎计算处理3D图像数据,Overlay HAL模块负责视频动态图像数据的处理。

    在Android Framebuffer显示子系统中,有一个核心组件SurfaceFlinger,它是显示子系统的Service进程,它将各种应用程序的2D和3D surface进行组合、合并,最终得到一个main surface数据送入显存,简单来说,SurfaceFlinger就像是画布,它并不关心画上去的内容,只是执行合成功能,当然需要根据画的位置、大小以及效果等参数。

    接下来,应了解Android显示子系统的Client/Server架构,服务端(SurfaceFlinger)负责surface的合成等处理工作,客户端根据SurfaceFlinger所提供的接口给上层各自操作surface,并向服务端发送消息完成实际显示工作,服务端主要由C++代码编写而成,客户端代码分成两部分,一部分由Java提供的供应用程序使用的API,另一部分则是由C++编写的底层实现,架构如下所示:

    在架构图可以看到有一个Binder组件,其底层技术是Android系统专有的Binder驱动,是Android进程间通信机制,在这里,主要是负责调用显示功能的客户进程与SurfaceFlinger服务进程之间的通信。

    参考:

    《Android驱动开发权威指南》

  • 相关阅读:
    浏览器环境下JavaScript脚本加载与执行探析之代码执行顺序
    DOM扩展:DOM API的进一步增强[总结篇-下]
    DOM扩展:DOM API的进一步增强[总结篇-上]
    Network 第九篇
    Network 第八篇 – 动态路由-OSPF
    Network 第七篇
    Network 第六篇
    Network 第五篇
    Network 第四篇
    Network 第三篇
  • 原文地址:https://www.cnblogs.com/Cqlismy/p/14403773.html
Copyright © 2020-2023  润新知