Android图形显示系统原理

Android显示系统的原理

android显示系统整体框架:
在这里插入图片描述

HWC介绍

Android图形显示系统之HWC。

HWC概述

HWC(hwcomposer)是Android中进行窗口(Layer)合成和显示的HAL层模块(注意:不是SurfaceFlinger代码中HWcomposer这个类),通常由显示设备制造商 (OEM)实现并完成,为SurfaceFlinger服务提供硬件支持。

为什么使用HWC

Overlay技术简介

HWC流程

显示设备的能力千差万别,很难直接用API表示硬件设备支持合成的Layer数量,Layer是否可以进行旋转和混合模式操作,以及对图层定位和硬件合成的限制等。因此HWC描述上述信息的流程是这样的:

  1. SurfaceFlinger向HWC提供所有Layer的完整列表,让HWC根据其硬件能力,决定如何处理这些Layer。
  2. HWC会为每个Layer标注合成方式,表明是通过GPU还是通过HWC合成。
  3. SurfaceFlinger负责先把所有注明GPU合成的Layer合成到一个输出Buffer,然后把这个输出Buffer和其他Layer(注明HWC合成的Layer)一起交给HWC,让HWC完成剩余Layer的合成和显示。

主要模块介绍

SurfaceFlinger

向HWC提供所有Layer的完整列表,让HWC根据其硬件能力,决定如何合成这些Layer。

HardwareComposer

硬件合成、硬件组合抽象层(HWComposer、Hardware Composer HAL),作为 HAL 硬件抽象层,其实现是基于特定设备的,通常由屏幕硬件设备制造商 (OEM) 完成。主要用于确定合成缓冲区的最有效方式,SurfaceFlinger 在收集可见层的所有缓冲区后,便会询问 HWC 应如何进行合成。如果 HWC 将层合成类型标记为客户端合成(Client合成),则 SurfaceFlinger 会合成这些层,然后 SurfaceFlinger 会将输出缓冲区传递给 HWC。如果标记为Device合成,则由专门的硬件合成器进行合HWComposer,所以硬件合成的能力就取决于硬件的实现。

  • Client合成
    Client合成方式是相对与硬件合成来说的,其合成方式是,将各个Layer的内容用GPU渲染到暂存缓冲区中,最后将暂存缓冲区传送到显示硬件。这个暂存缓冲区,我们称为FBTarget,每个Display设备有各自的FBTarget。Client合成,之前称为GLES合成,我们也可以称之为GPU合成。Client合成,采用RenderEngine进行合成。
  • Device合成
    就是用专门的硬件合成器进行合成HWComposer,所以硬件合成的能力就取决于硬件的实现。其合成方式是将各个Layer的数据全部传给显示硬件,并告知它从不同的缓冲区读取屏幕不同部分的数据。HWComposer是Devicehec的抽象。

所以,整个显示系统的数据流如下图所示,此图来源于Androd 官网:
在这里插入图片描述
GPU合成后数据,作为一个特殊的Layer,传给显示硬件。

FrameBuffer

FrameBuffer中文译名为帧缓冲驱动,它是出现在2.2.xx内核中的一种驱动程序接口。主设备号为29,次设备号递增。
Linux抽象出FrameBuffer这个设备来供用户态进程实现直接写屏。FrameBuffer机制模仿显卡的功能,将显卡硬件结构抽象掉,可以通过FrameBuffer的读写直接对显存进行操作。用户可以将FrameBuffer看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。这种操作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等具体细节,这些都是由FrameBuffer设备驱动来完成的。

FrameBuffer实际上就是嵌入式系统中专门为GPU所保留的一块连续的物理内存,LCD通过专门的总线从framebuffer读取数据,显示到屏幕上。

FrameBuffer本质上是一块显示缓存,往显示缓存中写入特定格式的数据就意味着向屏幕输出内容。所以说FrameBuffer就是一块白板。

屏幕位置从上到下,从左至右与内存地址是顺序的线性关系。

FrameBuffer直接写屏

因为Linux系统是工作在保护模式下,所以用户态进程是无法象DOS系统那样使用显卡BIOS里提供的中断调用来实现直接写屏,故Linux抽象出FrameBuffer这个设备来供用户态进程实现直接写屏。

帧缓冲(framebuffer)是Linux 系统为显示设备提供的一个接口,它将显示缓冲区抽象,屏蔽图像硬件的底层差异,允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。

framebuffer机制模仿显卡的功能,将显卡硬件结构抽象为一系列的数据结构,可以通过framebuffer的读写直接对显存进行操作。用户可以将framebuffer看成是显存的一个映像,将其映射到进程空间后,就可以直接进行读写操作,写操作会直接反映在屏幕上。

好,现在可以让我们开始实现直接写屏:
1、打开一个FrameBuffer设备
2、通过mmap调用把显卡的物理内存空间映射到用户空间
3、直接写内存。

好象很简单哦~

FrameBuffer与应用程序的交互

对于用户程序而言,它和其他的设备并没有什么区别,用户可以把fb看成是一块内存,既可以向内存中写数据,也可以读数据。fb的显示缓冲区位于内核空间,应用程序可以把此空间映射到自己的用户空间,在进行操作。

在应用程序中,操作/dev/fbn的一般步骤如下:
(1)打开/dev/fbn设备文件。
(2)用ioctl()操作取得当前显示屏幕的参数,如屏幕分辨率、每个像素点的比特数。根据屏幕参数可计算屏幕缓冲区的大小。
(3)用mmap()函数,将屏幕缓冲区映射到用户空间。
(4)映射后就可以直接读/写屏幕缓冲区,进行绘图和图片显示了。

FrameBuffer相关结构体

在linux中,fb设备驱动的源码主要在Fb.h (linux2.6.28\include\linux)和Fbmem.c(linux2.6.28\drivers\video)两个文件中,它们是fb设备驱动的中间层,为上层提供系统调用,为底层驱动提供接口。
在这里插入图片描述
在fb.h文件中有fb驱动需要使用的很多结构,我们先对这些结构体进行说明:
1.帧缓冲区描述符fb_info
一个帧缓冲区对应一个struct fb_info结构,它包括了帧缓冲设备的属性和操作的完整集合,每个帧设备都有一个fb_info结构体。源码如下:

struct fb_info {
	int node;
	int flags;
	struct mutex lock;/* Lock for open/release/ioctl funcs */互斥锁
	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 */图像硬件mapper
	struct fb_pixmap sprite;/* Cursor hardware mapper */光标硬件mapper
	struct fb_cmap cmap;/* Current cmap */当前的调色板
	struct list_head modelist;      /* mode list */
	struct fb_videomode *mode;/* current mode */当前的视频模式
 
 
	#ifdef CONFIG_FB_BACKLIGHT如果配置了LCD支持背光灯
	/* 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 */fb设备
	int class_flag;                    /* private sysfs flags */私有的sysfs标志
	#ifdef CONFIG_FB_TILEBLITTING
	struct fb_tile_ops *tileops;    /* Tile Blitting */图块blitting
	#endif
	char __iomem *screen_base;/* Virtual address */虚拟基地址
	unsigned long screen_size;/* Amount of ioremapped VRAM or 0 */ ioremap的虚拟内存大小
	void *pseudo_palette;/* Fake palette of 16 colors */16位调色板
	#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;
};

2.帧缓冲区操作符表fb_ops
fb_ops结构体用来实现对帧缓冲设备的操作,这些函数需要驱动开发人员编写。
3.帧缓冲区固定参数描述符
fb_fix_screeninfo结构体中,记录了用户不能修改的固定显示控制器参数。这些固定的参数如缓冲区的物理地址、缓冲区的长度等等。
4.帧缓冲区可变参数描述符
fb_var_screeninfo结构体中存储了用户可以修改的显示器控制参数,例如屏幕分辨率、透明度等等

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 */
 
	//每像素位数,BPP
	__u32 bits_per_pixel;/* guess what */
 
	//非0时指灰度
	__u32 grayscale;/* != 0 Graylevels instead of colors */
 
	//fb缓存的R\G\B位域
	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 */
 
	// != 0 非标准像素格式
	__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     */
 
	//fb_info的标志		 
	__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 reserved[5];/* Reserved for future compatibility */
};

参考:
Android9配置nativeUI为720p
HDMI(一):adb 查看HDMI信息

android的hwc浅析
Android图形系统系统篇之HWC
android的hwc浅析【转】
Android P 图形显示系统(一)硬件合成HWC2
android多媒体框架介绍(四)显示图形系统之hwc叠加器

7.1.1显示系统框架_framebuffer原理及改进
Android显示系统框架_framebuffer原理及改进
Android图形显示系统的改进研究与实现

Android GUI 系统综述

专题分纲目录 Android GUI系统之SurfaceFlinger
Android显示系统框架原理介绍

Android Framebuffer介绍及使用
FrameBuffer驱动程序分析

Linux下FrameBuffer直接写屏
framebuffer 帧缓冲
利用framebuffer,命令行显示图片
FrameBuffer系列 之 相关结构与结构体

boardconfig百科
AndroidBoard.mk与BoardConfig.mk之间的区别

  • 6
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值