GUI显示系统之SurfaceFlinger--- Gralloc与Framebuffer

2024-04-22 17:32

本文主要是介绍GUI显示系统之SurfaceFlinger--- Gralloc与Framebuffer,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


GUI显示系统之SurfaceFlinger其它部分完整章节:

http://blog.csdn.net/uiop78uiop78/article/details/8954508



第1章  GUI系统之SurfaceFlinger

在进入GUI系统的学习前,建议大家可以先阅读本书应用篇中的“OpenGLES”章节,并参阅OpenGL ES官方指南。因为Android的GUI系统是基于OpenGL/EGL来实现的,如果没有一定基础的话,分析源码时有可能会“事倍功半”。

1.1 Gralloc与Framebuffer

相信做过Linux开发的人对framebuffer不会太陌生,它是内核系统提供的一个与硬件无关的显示抽象层。之所以称之为buffer,是由于它也是系统存储空间的一部分,是一块包含屏幕显示信息的缓冲区。由此可见,在“一切都是文件”的Linux系统中,Framebuffer被看成了终端monitor的“化身”。它借助于文件系统向上层提供统一而方便的操作接口,从而让用户空间程序可以不用修改就能适应多种屏幕——无论这些屏幕是哪家厂商、什么型号,都由framebuffer内部来兼容。

在Android系统中,framebuffer提供的设备文件节点是/dev/graphics/fb*。因为理论上支持多个屏幕显示,所以fb按数字序号进行排列,即fb0、fb1等等。其中第一个fb0是主显示屏幕,必须存在。如下是某设备的fb设备截图:

 

图 11‑1 fb节点

 

根据前面章节学习过的知识,Android中各子系统通常不会直接基于Linux驱动来实现,而是由HAL层间接引用底层架构,在显示系统中也同样如此——它借助于HAL层来操作帧缓冲区,而完成这一中介任务的就是Gralloc,下面我们分几个方面来介绍。

<1>  Gralloc的加载

Gralloc对应的模块是由FramebufferNativeWindow(OpenGLES的本地窗口之一,后面小节有详细介绍)在构造时加载的,即:

hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule);

这个hw_get_module函数我们在前面已经见过很多次了,它是上层加载HAL库的入口,这里传入的模块ID名为:

#define GRALLOC_HARDWARE_MODULE_ID  "gralloc"

按照hw_get_module的作法,它会在如下路径中查找与ID值匹配的库:

#define HAL_LIBRARY_PATH1 "/system/lib/hw"

#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"

lib库名有如下几种形式:

    gralloc.[ro.hardware].so

    gralloc.[ro.product.board].so

    gralloc.[ro.board.platform].so

    gralloc.[ro.arch].so

或者当上述的系统属性组成的文件名都不存在时,就使用默认的:

    gralloc.default.so

最后这个库是Android原生态的实现,位置在hardware/libhardware/modules/gralloc/中,它由gralloc.cpp、framebuffer.cpp和mapper.cpp三个主要源文件编译生成。

 

<2>  Gralloc提供的接口

Gralloc对应的库被加载后,我们来看下它都提供了哪些接口方法。

由于Gralloc代表的是一个hw_module_t,这是HAL中统一定义的硬件模块描述体,所以和其它module所能提供的接口是完全一致的:

/*hardware/libhardware/include/hardware/Hardware.h*/

typedef struct hw_module_t {…

    structhw_module_methods_t* methods;

                …

} hw_module_t;

 

typedef struct hw_module_methods_t {

    int (*open)(const structhw_module_t* module, const char* id,

            structhw_device_t** device);

} hw_module_methods_t;

这个open接口可以帮助上层打开两个设备,分别是:

       #defineGRALLOC_HARDWARE_FB0   "fb0"

以及   #define GRALLOC_HARDWARE_GPU0  "gpu0"

 

“fb0”就是我们前面说的主屏幕,gpu0负责图形缓冲区的分配和释放。这两个设备将由FramebufferNativeWindow中的fbDev和grDev成员变量来管理。

/*frameworks/native/libs/ui/FramebufferNativeWindow.cpp*/      

FramebufferNativeWindow::FramebufferNativeWindow()

           : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false)

{…

    err =framebuffer_open(module, &fbDev);

    err =gralloc_open(module, &grDev);

这两个open函数分别是由hardware/libhardware/include/hardware目录下的Fb.h和Gralloc.h头文件提供的打开fb及gralloc设备的便捷实现。其中fb对应的设备名为GRALLOC_HARDWARE_FB0,gralloc则是GRALLOC_HARDWARE_GPU0。各硬件生产商可以根据自己的平台配置来实现fb和gralloc的打开、关闭以及管理,比如hardware/msm7k/libgralloc就是一个很好的参考例子。

原生态的实现在hardware/libhardware/modules/gralloc中,对应的是gralloc_device_open@Gralloc.cpp。在这个函数中,根据设备名来判断是打开fb或者gralloc。

/*hardware/libhardware/modules/gralloc/Gralloc.cpp*/

int gralloc_device_open(const hw_module_t*module, const char* name, hw_device_t** device)

{

    intstatus = -EINVAL;

    if(!strcmp(name, GRALLOC_HARDWARE_GPU0)) {//打开gralloc设备

        …

    } else{

       status = fb_device_open(module, name, device);//否则就是fb设备

    }

    returnstatus;

}

先来大概看下framebuffer设备的打开过程:

/*hardware/libhardware/modules/gralloc/Framebuffer.cpp*/

int fb_device_open(hw_module_t const* module, const char* name,hw_device_t** device)

{

    int status = -EINVAL;

    if (!strcmp(name, GRALLOC_HARDWARE_FB0)){//设备名是否正确

        fb_context_t *dev =(fb_context_t*)malloc(sizeof(*dev));//分配hw_device_t空间,这是一个“壳”

        memset(dev, 0,sizeof(*dev));//初始化,良好的编程习惯

                   …

       dev->device.common.close = fb_close;//这几个接口是fb设备的核心

       dev->device.setSwapInterval = fb_setSwapInterval;

        dev->device.post          = fb_post;

                   …

        private_module_t* m =(private_module_t*)module;

        status = mapFrameBuffer(m);//内存映射,以及参数配置

        if (status >= 0) {

            …

            *device =&dev->device.common;//“壳”和“核心”的关系

        }

    }

    return status;

}

其中fb_context_t是framebuffer内部使用的一个类,它包含了众多信息,而最终返回的device只是其内部的device.common。这种“通用和差异”并存的编码风格在HAL层非常常见,大家要做到习以为常。

Struct类型fb_context_t里的唯一成员就是framebuffer_device_t,这是对frambuffer设备的统一描述。一个标准的fb设备通常要提供如下的函数实现:

l  int(*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer);

将buffer数据post到显示屏上。要求buffer必须与屏幕尺寸一致,并且没有被locked。这样的话buffer内容将在下一次VSYNC中被显示出来

l  int(*setSwapInterval)(struct framebuffer_device_t* window, int interval);

设置两个缓冲区交换的时间间隔

l  int(*setUpdateRect)(struct framebuffer_device_t* window, int left, int top,

                 int width, int height);

设置刷新区域,需要framebuffer驱动支持“update-on-demand”。也就是说在这个区域外的数据很可能被认为无效

 

我们再来解释下framebuffer_device_t中一些重要的成员变量,如下表:

表格 11‑1 framebuffer_device_t中的重要成员变量

变量

描述

uint32_t  flags

标志位,指示framebuffer的属性配置

uint32_t  width;

uint32_t  height;

framebuffer的宽和高,以像素为单位

int       format

framebuffer的像素格式,比如:HAL_PIXEL_FORMAT_RGBA_8888 HAL_PIXEL_FORMAT_RGBX_8888

HAL_PIXEL_FORMAT_RGB_888

HAL_PIXEL_FORMAT_RGB_565等等

float     xdpi;

float     ydpi;

x和y轴的密度(pixel per inch)

float     fps

屏幕的每秒刷新频率,假如无法正常从设备获取的话,默认设置为60Hz

int       minSwapInterval;

int       maxSwapInterval;

该framebuffer支持的最小和最大缓冲交换时间

 

到目前为止,我们还没看到系统是如何打开具体的fb设备、以及如何对fb进行配置,这些工作都是在mapFrameBuffer()完成的。这个函数首先尝试打开(调用open,权限为O_RDWR)如下路径中的fb设备:

"/dev/graphics/fb%u"或者 "/dev/fb%u",其中%u当前的实现中只用了“0”,也就是只会打开一个fb,虽然Android从趋势上看是要支持多屏幕的。成功打开fb后,我们通过:

ioctl(fd, FBIOGET_FSCREENINFO, &finfo);

ioctl(fd, FBIOGET_VSCREENINFO, &info)

来得到显示屏的一系列参数,同时通过

ioctl(fd, FBIOPUT_VSCREENINFO, &info)来对底层fb进行配置。

这个函数的另一重要任务,就是对fb做内存映射,主要语句如下:

    void* vaddr = mmap(0,fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);   

   module->framebuffer->base = intptr_t(vaddr);

    memset(vaddr, 0, fbSize);

所以映射地址是module->framebuffer->base,这个module对应的是前面hw_get_module(GRALLOC_HARDWARE_MODULE_ID,&module)得到的hw_module_t(被强制类型转化为private_module_t,大家可以自己看下这个struct)。

 

接下来再看下对gralloc设备的打开操作,它相对fb简单些,如下所示:

/*hardware/libhardware/modules/gralloc/Gralloc.cpp*/

int gralloc_device_open(const hw_module_t* module, const char* name,hw_device_t** device)

{

    int status = -EINVAL;

    if (!strcmp(name,GRALLOC_HARDWARE_GPU0)) {

        gralloc_context_t*dev;//做法和fb类似

        dev =(gralloc_context_t*)malloc(sizeof(*dev));//分配空间

        /* initialize ourstate here */

        memset(dev, 0,sizeof(*dev));

                   …

       dev->device.alloc   =gralloc_alloc; //从提供的接口来看,gralloc和分配/释放有关系

       dev->device.free    =gralloc_free;

}

与fb相似的部分我们就不多做介绍了。因为gralloc担负着图形缓冲区的分配与释放,所以它提供了两个最重要的实现即alloc和free。这里我们先不深入分析了,只要知道gralloc所提供的功能就可以了。

我们以下面简图来小结对Gralloc的分析。


 

图 11‑2 Gralloc简图

 


这篇关于GUI显示系统之SurfaceFlinger--- Gralloc与Framebuffer的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/926410

相关文章

JAVA读取MongoDB中的二进制图片并显示在页面上

1:Jsp页面: <td><img src="${ctx}/mongoImg/show"></td> 2:xml配置: <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001

通信系统网络架构_2.广域网网络架构

1.概述          通俗来讲,广域网是将分布于相比局域网络更广区域的计算机设备联接起来的网络。广域网由通信子网于资源子网组成。通信子网可以利用公用分组交换网、卫星通信网和无线分组交换网构建,将分布在不同地区的局域网或计算机系统互连起来,实现资源子网的共享。 2.网络组成          广域网属于多级网络,通常由骨干网、分布网、接入网组成。在网络规模较小时,可仅由骨干网和接入网组成

据阿谱尔APO Research调研显示,2023年全球髓内钉市场销售额约为4.7亿美元

根据阿谱尔 (APO Research)的统计及预测,2023年全球髓内钉市场销售额约为4.7亿美元,预计在2024-2030年预测期内将以超过3.82%的CAGR(年复合增长率)增长。 髓内钉市场是指涉及髓内钉制造、分销和销售的行业。髓内钉是一种用于整形外科手术的医疗器械,用于稳定长骨骨折,特别是股骨、胫骨和肱骨。髓内钉通常由不銹钢或钛等材料制成,并插入骨的髓管中,以在愈合过程中提供结构支

vue+elementUI下拉框联动显示

<el-row><el-col :span="12"><el-form-item label="主账号:" prop="partyAccountId" :rules="[ { required: true, message: '主账号不能为空'}]"><el-select v-model="detailForm.partyAccountId" filterable placeholder="

Linux系统稳定性的奥秘:探究其背后的机制与哲学

在计算机操作系统的世界里,Linux以其卓越的稳定性和可靠性著称,成为服务器、嵌入式系统乃至个人电脑用户的首选。那么,是什么造就了Linux如此之高的稳定性呢?本文将深入解析Linux系统稳定性的几个关键因素,揭示其背后的技术哲学与实践。 1. 开源协作的力量Linux是一个开源项目,意味着任何人都可以查看、修改和贡献其源代码。这种开放性吸引了全球成千上万的开发者参与到内核的维护与优化中,形成了

Android SurfaceFlinger——图形内存分配器(十一)

前面的文章中的图层合成器(HWC),这里我们接着看一下 SurfaceFlinger 中的另一个重要服务——图形内存分配器。 一、简介         android.hardware.graphics.allocator@2.0 是 Android 系统中硬件抽象层(HAL)的一个组件,专门用于图形内存的分配和管理。它是 SurfaceFlinger 在处理图形数据时所依赖的

PS系统教程25

介绍软件 BR(bridge) PS 配套软件,方便素材整理、管理素材 作用:起到桥梁作用 注意:PS和BR尽量保持版本一致 下载和安装可通过CSDN社区搜索,有免费安装指导。 安装之后,我们打开照片只需双击照片,就自动在Ps软件中打开。 前提:电脑上有PS软件 三种预览格式 全屏预览 评星级 直接按数字键就可以 方向键可以更换图片 esc退出 幻灯片放

风水研究会官网源码系统-可展示自己的领域内容-商品售卖等

一款用于展示风水行业,周易测算行业,玄学行业的系统,并支持售卖自己的商品。 整洁大气,非常漂亮,前端内容均可通过后台修改。 大致功能: 支持前端内容通过后端自定义支持开启关闭会员功能,会员等级设置支持对接官方支付支持添加商品类支持添加虚拟下载类支持自定义其他类型字段支持生成虚拟激活卡支持采集其他站点文章支持对接收益广告支持文章评论支持积分功能支持推广功能更多功能,搭建完成自行体验吧! 原文

温湿度采集及OLED显示

目录 软件I2C和硬件I2C每隔2秒钟采集一次温湿度数据,显示到OLED上,同时通过串口发送到上位机的“串口助手”软件 软件I2C和硬件I2C "I2C"代表Inter-Integrated Circuit,是一种用于在数字电路之间进行通信的串行通信协议。软件I2C和硬件I2C是两种实现这种协议的方式。 软件I2C是通过软件来模拟I2C通信协议的实现方式。在这种情况下,微控制

Django 路由系统详解

Django 路由系统详解 引言 Django 是一个高级 Python Web 框架,它鼓励快速开发和干净、实用的设计。在 Django 中,路由系统是其核心组件之一,负责将用户的请求映射到相应的视图函数或类。本文将深入探讨 Django 的路由系统,包括其工作原理、配置方式以及高级功能。 目录 路由基础URL 映射路由参数命名空间URL 反向解析路由分发include 路由路由修饰符自