浅谈Android之SurfaceFlinger相关介绍(一)
SurfaceFlinger是GUI的核心,以系统服务的形式存在,负责将所有App的图形数据按照Z Order顺序混合并输出到FrameBuffer。
根据图中描述,从下到上依次介绍:
1) 这里的FrameBuffer指显示设备驱动和Gralloc帧缓冲区管理
2) 面向SurfaceFlinger的Native Window
3) 通过OpenGl ES图形库来处理图形数据后绘制到NativeWindow
4) SurfaceFlinger,是一个binderservice,用于管理接收各个App传输过来的图形数据
5) 面向App应用窗口绘制的Native Window
6) 采用OpenGL ES或者SKIA将图形数据绘制到Native Window,对于普通应用开发人员来说,使用OpenGLES的门槛相对会比较高,所以SKIA第三方图形库基于OpenGL ES做了封装,提供更加简单的GUI接口供开发人员使用,SKIA是Android应用默认的图形引擎
下面重点介绍下上述第3步和第6步分别都提到的NativeWindow,既然叫窗口,说明它的输入端肯定是图形数据,输出到哪呢?可以是另外一个窗口的输入或者是Framebuffer,总之,对输入方来说,它只需要在NatvieWindow上输入图形数据,至于NativeWindow拿到数据后怎么处理的,它不需要关心。
Android系统为NativeWindow定义了基础结构ANativeWindow
struct ANativeWindow { /* horizontal and vertical resolution in DPI */ const float xdpi; const float ydpi; int (*setSwapInterval)(struct ANativeWindow* window, int interval); int (*dequeueBuffer_DEPRECATED)(struct ANativeWindow* window, struct ANativeWindowBuffer** buffer); int (*lockBuffer_DEPRECATED)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer); int (*queueBuffer_DEPRECATED)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer); int (*query)(const struct ANativeWindow* window, int what, int* value); int (*perform)(struct ANativeWindow* window, int operation, ... ); int (*cancelBuffer_DEPRECATED)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer); int (*dequeueBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer** buffer, int* fenceFd); int (*queueBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer, int fenceFd); int (*cancelBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer, int fenceFd); }; |
这个结构包含窗口最基本的宽高属性外,还定义了一大堆的函数指针,派生自ANavtiveWindow的类在构造时需要对各个函数指针进行赋值,说白了,就是将C++虚函数自己用C语言实现了一遍,这里把ANavtiveWindow
定义成结构体,不知道是历史遗留还是为了兼容性考虑,没去细究过。
ANativeWindow定义的函数名就可以看出,其对象的实现,一定要包含一个buffer queue,然后输入方调用dequeueBuffer获取buffer用于写入图形数据,结束后,调用queueBuffer入列。
App端对应的NativeWindow为Surface:
class Surface : public ANativeObjectBase<ANativeWindow, Surface, RefBase> { |
SurfaceFlinger端对应的NativeWindow为
class FramebufferNativeWindow : public ANativeObjectBase< ANativeWindow, FramebufferNativeWindow, LightRefBase<FramebufferNativeWindow> > { |
二者皆派生实现了ANativeWindow接口。
Surface向上提供buffer供App绘制图形界面,然后将图形数据传到SurfaceFlinger,SurfaceFlinger基于OpenGL ES将数据做混合操作后,输出到FramebufferNativeWindow并最终显示到屏幕上。
接下去重点介绍Surface跟SurfaceFlinger的交互
3.1 建立Surface和SurfaceFlinger连接
SurfaceFlinger服务主要实现了两个Binder service用于App连接:
1) SurfaceFlinger
派生自BnSurfaceComposer,是SurfaceFlinger程序的主服务,在程序启动时就被构造并添加到servicemanager,相关代码在main_surfaceflinger.cpp,服务名为”SurfaceFlinger”
2) Client
派生自BnSurfaceComposerClient,在SurfaceFlinger:: createConnection的时候被创建,对应一个App Client连接
然后App启动后,需要通过如下操作和SurfaceFlinger建立会话:
1)通过servicemanager获取服务SurfaceFlinger的BpBinder,然后转换成BpSurfaceComposer
2)调用BpsurfaceComposer.createConnection建立连接,然后将返回的BpBinder转换成
BpSurfaceComposeClient
Android接着提供了两个类用于简化App端的操作,主要包括:
1)ComposerService
单列类,主要封装跟SurfaceFlinger的连接,在构造时调用connectlocaked成员函数连接
“SurfaceFlinger”然后将BpSurfaceCompose保存到成员变量mComposerService
2)SurfaceComposerClient
封装跟SurfaceFlinger建立会话连接的操作,在onFirstRef时调用createConnection建立
会话并将BpSurfaceComposerClient保存到成员变量mClient
3)Composer
单列类,主要封装对Layer数据配置相关操作
接下去基于代码来分析,封装好后,App初始化连接很简单
sp<SurfaceComposerClient> session= new SurfaceComposerClient(); |
就一行代码,接着看构造函数
SurfaceComposerClient::SurfaceComposerClient() : mStatus(NO_INIT), mComposer(Composer::getInstance()) { } |
获取Composer单例对象并保存到mComposer,由于SurfaceComposerClient派生自RefBase
class SurfaceComposerClient : public RefBase |
所以在其构造时,会调用incStrong第一次增加强引用计数,同时onFirstRef会被调用
void SurfaceComposerClient::onFirstRef() { sp<ISurfaceComposer> sm(ComposerService::getComposerService()); if (sm != 0) { sp<ISurfaceComposerClient> conn = sm->createConnection(); if (conn != 0) { mClient = conn; mStatus = NO_ERROR; } } } |
这个函数完成了连接的最终操作,先是通过ComposerService::getComposerService()生成
ComposeService单列,并调用其connectLocked连接SurfaceFlinger返回BpSurfaceComposer,
接着调用sm->createConnection()创建会话并保存到mClient。
接下来看看SurfaceFlinger.createConnection的代码
sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() { sp<ISurfaceComposerClient> bclient; sp<Client> client(new Client(this)); status_t err = client->initCheck(); if (err == NO_ERROR) { bclient = client; } return bclient; } |
很简单,就是创建Client本地对象并返回
到这里,App跟SurfaceFlinger的初始化连接已经结束,接下去就是基于会话对象,创建绘图表面了
浅谈Android之SurfaceFlinger相关介绍(一)相关推荐
- android fps 垂直同步,浅谈Android流畅度
原标题:浅谈Android流畅度 哈哈 讲个故事 白 1 流畅度 关于流畅度谷歌官方给出的解释为:running at a consistent 60 frames per second, witho ...
- 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路
原文地址: http://blog.csdn.net/luoshengyang/article/details/6627260 在前面一篇文章浅谈Service Manager成为Android进程间 ...
- android分屏模式_浅谈 Android 7.0 多窗口分屏模式的实现
从 Android 7.0 开始,Google 推出了一个名为"多窗口模式"的新功能,也就是我们常说的"分屏模式".那么,这个功能有什么用呢?作为开发者,我们又 ...
- 浅谈Android Architecture Components
浅谈Android Architecture Components 浅谈Android Architecture Components 简介 Android Architecture Componen ...
- 浅谈Android中的MVP与动态代理的结合
浅谈Android中的MVP与动态代理的结合 本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 在Android开发平台上接触MVP足足算起来大概已经有一个年头左右.从最开始到现在经 ...
- 浅谈Android引用计数(2)
在浅谈Android引用计数(1)中讲了LightRefBase实现对象计数管理的原理,这篇文章将要分析重量级的引用基类:RefBase的实现和它的作用. 下面是RefBase和相关类的类图: 图中可 ...
- 浅谈Android onTouchEvent 与 onInterceptTouchEvent的区别详解
浅谈Android onTouchEvent 与 onInterceptTouchEvent的区别详解 本篇文章小编为大家介绍,Android onTouchEvent 与 onInterceptTo ...
- android 存储空间监控,浅谈 Android 内存监控(中)
前言 在上篇 浅谈 Android 内存监控(上) 中,我们聊了 LeakCanary,微信的 Matirx 和美团的 Probe,它们各自有不同的应用场景,例如,在开发测试环境,我们会偏向用 Lea ...
- 浅谈Android文件管理器的几种实现方式(原理篇)--对我有帮助
转自 https://blog.csdn.net/weixin_33698823/article/details/87269955 浅谈Android文件管理器的几种实现方式 为了完成毕业设计,我花费 ...
最新文章
- 安装eclipse for c/c++环境
- C语言数组中找到第一个重复元素的算法(附完整源码)
- sql查询成绩最高分_sql查询各科成绩前三名----详述过程,思路清晰不烧脑!
- leetcode 25. Reverse Nodes in k-Group | 25. K 个一组翻转链表(Java)
- 一文讲清数据治理、数据管理、数据资产管理区别,数据专家必看
- [学习备忘录]编译gdb及gdbserver
- 【软件测试】Homework 1 Briefly describe an error
- 人工智能规模化落地还有哪些坑?阿里副总裁华先胜连麦详解!
- 用C# Regex类实现的一些常规输入判断
- sql常用语句集合(工作总结)
- 《Shell脚本学习指南》学习笔记
- 如何用UE4制作2D游戏文档(五)——战斗篇
- java定时任务 时间_java 定时任务的执行时间表示-
- Socket+华为云 实现广域网五子棋在线对战
- SNDACode介绍
- gee引擎修改UI界面图文教程
- 怎么调整图片大小会不变形?
- knex mysql 操作_mysql – 使用knex.js的我的Sql Alter表
- Count Inversion逆序对数问题
- 排序算法——简单选择排序(PythonJava)
热门文章
- linux字符终端浏览器-----Lynx
- 学习PHP 第七天 die() 函数,及Mysql的操作
- python 人像素描_基于python实现把图片转换成素描
- linux memwatch的内存检测-double-free
- 按键精灵9.5.1.11790秒速启动,多余元素全灭版
- 名片管理系统python详解_详解Python做一个名片管理系统
- HRSID舰船检测数据集标签格式转换,json转为xml
- VUE:自定义指令(directives )选项的用法
- 单行、多行 注释.HTML
- pip命令大全 含换源方法