HWC blending mode
Android图形显示系统——下层显示4:图层合成下(硬件合成器)
发表于2015/6/8 3:19:47 2960人阅读
分类: Android图形显示
硬件合成器-HwComposer
使用3D合成,需要大面积的像素混合计算和大量的内存传输(GPU读写GraphicBuffer所需),对GPU和DDR来说是一个巨大的负担。在GPU/DDR重度使用的场景(比如玩游戏),会造成发热、卡顿等。
为了提升性能,减少功耗,可以将合成这个过程交由另一个芯片完成,减轻GPU负担。进一步,直接让这个芯片连LCD,在LCD需要显示某一行时在线合成。
HwComposer便是这一个/多个专用合成芯片的驱动HAL层。
驱动由集成芯片系统的厂商自行设计,但需要遵循一定的标准,这个标准就是Android规定的HwComposer接口。
接口定义
hwcomposer的接口定义位于此文件:
hardware/libhardware/include/hardware/hwcomposer.h
其中部分宏定义在:
hardware/libhardware/include/hardware/hwcomposer_defs.h
Layer
在SurfaceFlinger中,Layer对应于window表示一个Buffer循环体系,对HwComposer而言,Layer仅指代当前Buffer,也即SurfaceFlinger中的Layer的当前帧。
typedef struct hwc_layer_1 {int32_t compositionType;//合成类型,SurfaceFlinger将合成目标Framebuffer的合成类型设为HWC_FRAMEBUFFER_TARGET,其他hwcomposer在prepare时根据实际情况修改/** HWC_FRAMEBUFFER_TARGET:该Layer是3D合成的目标Layer* HWC_FRAMEBUFFER:hwcomposer无法处理此Layer,该Layer需要走3D合成流程,用OpenGL绘制* HWC_OVERLAY:该Layer为硬件合成器所处理,不需要OpenGLES去渲染* HWC_SIDEBAND:该Layer为视频的边频带,需要硬件合成器作特殊处理,若不支持,OpenGL方式只能以一个色块替代,这个标志是外界(应用/驱动)调用窗口系统的perform方法配置的* HWC_CURSOR_OVERLAY:该Layer可通过setCursorPositionAsync 方法改变坐标*/uint32_t hints;//hwcomposer设置,通知SurfaceFlinger需要修改的配置/*HWC_HINT_TRIPLE_BUFFER = 0x00000001:表示需要SurfaceFlinger将此Layer改成3Buffer循环HWC_HINT_CLEAR_FB = 0x00000002:要求SurfaceFlinger清空该Layer位置的FrameBuffer数据(即置0)*/uint32_t flags;//SurfaceFlinger设置,hwcomposer作处理/*HWC_SKIP_LAYER = 0x00000001:此Layer不参与合成,应当忽略HWC_IS_CURSOR_LAYER = 0x00000002:此Layer建议设定为一个CURSOR_LAYER,hwcomposer能处理的话将其合成类型改为HWC_CURSOR_OVERLAY*//*该Layer的颜色/Buffer信息*/union {hwc_color_t backgroundColor;//背景颜色,适用于纯色Layer,hwc_color_t 为一个 argb 结构体struct {union {buffer_handle_t handle;//此即之间提到的GraphicBufferconst native_handle_t* sidebandStream;//HWC_SIDEBAND类型Layer的buffer};uint32_t transform;//该Layer所需要作的变换,具体为:/*HWC_TRANSFORM_FLIP_H = HAL_TRANSFORM_FLIP_H//水平翻转HWC_TRANSFORM_FLIP_V = HAL_TRANSFORM_FLIP_V//垂直翻转HWC_TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90,//需要旋转90度HWC_TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180,//需要旋转180度HWC_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270,//需要旋转270度*/int32_t blending;//当前Layer绘制时,和底色/目标色的混合方式//HWC_BLENDING_NONE = 0x100:不混合,直接覆盖//HWC_BLENDING_PREMULT = 0x105:该Layer的颜色已经做过alpha预乘,因此混合方式为 src + (1-src.a)*dst//HWC_BLENDING_COVERAGE = 0x405:该Layer的颜色未做过预乘,按 src.a * src + (1-src.a) * dst 的方式混合union {// crop rectangle in integer (pre HWC_DEVICE_API_VERSION_1_3)hwc_rect_t sourceCropi;hwc_rect_t sourceCrop; // just for source compatibility// crop rectangle in floats (as of HWC_DEVICE_API_VERSION_1_3)hwc_frect_t sourceCropf;};//该Layer取哪一个区域进行合成hwc_rect_t displayFrame;//该Layer合成的目标区域hwc_region_t visibleRegionScreen;//该Layer的可见区域,该区域必然是displayFrame的子集。这个区域由SurfaceFlinger计算而得,用于提示hwcomposer不去合成该Layer的不可见区域,hwcomposer中应当以这个为基准,对应计算该Layer相应的sourcecrop。int acquireFenceFd;//由Buffer生产者创建,SurfaceFlinger传递进来,hwcomposer在使用该Layer的Buffer之前,需要等这个fenceint releaseFenceFd;//由hwcomposer创建,生产者在使用该Buffer之前需要等此fenceuint8_t planeAlpha;//整个Layer的alpha值,在取Layer的像素作运算之前,需要先乘 planeAlpha/255。/* Pad to 32 bits */uint8_t _pad[3];//用于结构体对齐,占位用hwc_region_t surfaceDamage;//记录相对上一次合成而言,发生了改变的source区域};};//保留位,用于驱动层自行设计
#ifdef __LP64__uint8_t reserved[120 - 112];
#elseuint8_t reserved[96 - 84];
#endif} hwc_layer_1_t;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
这里面最难理解和最易出错的是 SourceCrop、DisplayFrame和VisibleRegion,在处理SOC上的显示问题时,这往往是首先考虑的因素:
如图所示,该Layer的显示区域部分被L2完全挡住,source crop 为该Layer参与合成的范围,display frame 为该Layer合成的目标区域,visibleRegion为该Layer被挡住后,剩余的可见区域集。
看完了这个结构体,上一篇
http://blog.csdn.net/jxt1234and2010/article/details/46057267
所提到的adb shell dumpsys SurfaceFlinger 所得到的表格,各参数表示什么意思自然一下就清楚了。
Display
typedef struct hwc_display_contents_1 {/* hwcomposer设置,surfaceflinger去等的fence。对于物理屏(实际上是使用在线合成方式的物理屏),对于虚拟屏/离线合成,此fence在离线合成的目标buffer完成全部写入后解除。*/int retireFenceFd;union {struct {/* HWC_DEVICE_VERSION_1_0 使用,dpy和sur对应于EGLDisplay 和 EGLSurface*/hwc_display_t dpy;hwc_surface_t sur;};//HWC_DEVICE_VERSION_1_0struct {/*HWC_DEVICE_VERSION_1_3 之后支持 hwcomposer合成多屏,这里是指虚拟屏的输出buffer和对应的fence*/buffer_handle_t outbuf;int outbufAcquireFenceFd;};};/*合成该显示屏的所有Layer*/uint32_t flags;size_t numHwLayers;hwc_layer_1_t hwLayers[0];} hwc_display_contents_1_t;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
关于物理显示屏(physical display)和虚拟显示屏(virtual display)
物理显示屏表示连接实际的显示仪器如LCD,目的是产生显示效果,可以使用在线合成。
虚拟显示屏表示目的是合成一个Buffer,不需要理会这个Buffer后续如何产生显示效果,这时需要把所有图层合成到指定的Buffer上。这种情况下必须离线合成。典型场景是手机连WFD/hdmi,手机合成好的Buffer通过wifi/hdmi传输到电视上显示。
Device
最后是device的函数指针定义
typedef struct hwc_composer_device_1 {struct hw_device_t common;//这种方式相当于C语言的继承实现,理解为 hwc_composer_device_1 继承于 hw_device_t 就可以了。//hw_device_t 包含一个基本信息 version(版本号),下面会提到/*对所有显示屏中所有Layer作合成准备(此时也可以开始发送合成的命令码下去,启动硬件合成,但不需要等待完成),hwcomposer需要正确汇报每个Layer的composetype,以告知SurfaceFlinger是否需要额外处理。version 为 1.0 的驱动,只支持一个显示屏version 为 1.1 的驱动,只支持物理显示屏version 为 1.3 及以上的驱动,支持物理和虚拟显示屏*/int (*prepare)(struct hwc_composer_device_1 *dev,size_t numDisplays, hwc_display_contents_1_t** displays);/*此方法将完成各个图层的合成与显示,等效于EGL标准里面的eglSwapBuffers,不过eglSwapBuffers是对OpenGL标准/GPU有效,此方法是对硬件合成器有效*/int (*set)(struct hwc_composer_device_1 *dev,size_t numDisplays, hwc_display_contents_1_t** displays);/*这个接口一般只用于开启hwcomposer的vsync,在线合成触发vsync的机制较离线合成的设计会麻烦一些*/int (*eventControl)(struct hwc_composer_device_1* dev, int disp,int event, int enabled);//控制屏幕状态的方法union {/* HWC 1.3及之前版本,采用 blank 方式,开关某个显示屏 */int (*blank)(struct hwc_composer_device_1* dev, int disp, int blank);/* HWC 1.4及之后,提供更精细的 setPowerMode ,支持显示屏以较低功耗(但不关)的状态显示*/int (*setPowerMode)(struct hwc_composer_device_1* dev, int disp,int mode);};/*查询Hwcomposer的信息*/int (*query)(struct hwc_composer_device_1* dev, int what, int* value);/*注册*invalidate:屏幕刷新时触发*vsync:hwcomopser中的vsync事件产生时触发*hotplug:显示屏连接/断开时触发* 三个回调函数*/void (*registerProcs)(struct hwc_composer_device_1* dev,hwc_procs_t const* procs);/*打印信息,调试用*/void (*dump)(struct hwc_composer_device_1* dev, char *buff, int buff_len);/*获取显示屏配置、属性*/int (*getDisplayConfigs)(struct hwc_composer_device_1* dev, int disp,uint32_t* configs, size_t* numConfigs);int (*getDisplayAttributes)(struct hwc_composer_device_1* dev, int disp,uint32_t config, const uint32_t* attributes, int32_t* values);int (*getActiveConfig)(struct hwc_composer_device_1* dev, int disp);/*配置属性,index表示有效属性的编号*/int (*setActiveConfig)(struct hwc_composer_device_1* dev, int disp,int index);/*更改游标层的坐标*/int (*setCursorPositionAsync)(struct hwc_composer_device_1 *dev, int disp, int x_pos, int y_pos);/*自行添加的保留函数*/void* reserved_proc[1];} hwc_composer_device_1_t;
HWC blending mode相关推荐
- 显示HWC合成(hwc_display_contents_1_t,hwc_layer_1_t数据结构关系)
在之前的博客中,分析了SurfaceFlinger的流程,以及hwc和Gralloc模块的大致功能,但是对其中一些数据结构不是很清楚. 这篇博客我们主要从创建hwc_display_contents_ ...
- 集成学习VotingClassifier、HistGradientBoostingClassifier、Stacking、Blending
集成学习VotingClassifier.HistGradientBoostingClassifier.Stacking.Blending 目录 集成学习VotingClassifier.HistGr ...
- Stacking+Blending
Stacking+Blending 一.Stacking思想简介 1.Stacking的思想是一种有层次的融合模型,比如我们将用不同特征训练出来的三个GBDT模型进行融合时,我们会将三个GBDT作为基 ...
- OpenGL中的混合(Blending)
这篇是在上一篇的基础上修改而来的,对应着Nehe教程的第8课,代码仍然采用MFC框架来实现. 其中InitGL需要做些修改,加入混合操作所需要的代码: BOOLCOpenGLDemoView::Ini ...
- Multi-band Blending
Multi-band Blending from: http://aboutdada.com/?p=29 Posted on November 26, 2014 Multi-Band Blending ...
- OpenCV之core 模块. 核心功能(1)Mat - 基本图像容器 OpenCV如何扫描图像、利用查找表和计时 矩阵的掩码操作 使用OpenCV对两幅图像求和(求混合(blending))
Mat - 基本图像容器 目的 从真实世界中获取数字图像有很多方法,比如数码相机.扫描仪.CT或者磁共振成像.无论哪种方法,我们(人类)看到的是图像,而让数字设备来"看"的时候,则 ...
- Blending and Bagging
Blending and Bagging 目录(?)[+] 第七讲:Blending and Bagging 1.Motivation of Aggregation(融合的动机) 恰当的融合可以得到更 ...
- stacking与blending的区别
网上通用的解释: stacking是k折交叉验证,元模型的训练数据等同于基于模型的训练数据,该方法为每个样本都生成了元特征,每生成元特征的模型不一样(k是多少,每个模型的数量就是多少):测试集生成元特 ...
- OpenGL blending sort 混合排序(前后)的实例
OpenGL blending sort 混合排序 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <glad/glad.h> #in ...
最新文章
- Git-TortoiseGit完整配置流程
- spring使用回顾
- Matlab画三维曲线入门
- 转:让 ThinkPad 的中键加小红帽模拟鼠标滚轮
- python里有常量吗?(没有,但可自行定义)
- 蚁群算法,PSO算法以及两种算法可以融合的几种方法
- P4111 [HEOI2015]小Z的房间
- html5 漂亮的左右布局_2020年庚子年风水布局,2020年家居风水布局汇总 | 影楼
- Apache Mail 发送带附件的邮件
- nginx完全关闭log
- CISA已遭利用漏洞列表新增15个漏洞
- 光电转换模块_针对100G QSFP28 SR4光模块的特征及工作原理进行分析
- 计算机组成原理知识点
- matlab LSB算法的三种改进
- html语言单个单元格背景颜色,html如何设置表格和单元格的背景颜色
- KNN和Kmeans
- 使用Vue快速开发单页应用
- 针对自动跳转到2345导航页流氓行为的解决办法
- 拇指大的真无线耳机不仅续航长,音质也很强,Jeet Air 2体验
- 小程序加入阿拉丁统计
热门文章
- MSP432库函数输出多路任意占空比PWM波
- cordic算法反正切c语言,Cordic 算法之 反正切
- 用户信息管理系统总结
- 2021年安全员-B证考试技巧及安全员-B证操作证考试
- 参加2021年CSDN博客专家颁奖仪式的收获
- 常用国内pip镜像源
- git.exe 启动 慢_一起绿色出行,2019年“公交出行宣传周”正式启动啦!还有一大波福利正在路上!...
- 微信小程序|动态时钟
- 【PC大变身】Android+Win8.1双系统
- python 取字符串的最后一位_python如何截取字符串最后的几位数字