Android TV 视图体系分析-笔记SurfaceFlinger

首先可以梳理出SurfaceFlinger的类图

然后可以看下这些类大致是干嘛的,梳理出主要的类

===========先看主文件夹下的类================

1.Barrier

用于控制互斥访问的

2.Colorizer

用户颜色转换

3.DisplayDevice(重要类)

显示设备类

4.DispSync(重要类)

DispSync维护了显示设备基于硬件的vsync事件的周期性模型,并用这个模型周期性的在特定的硬件vsync事件相位来执行回调

这个模型的通过addResyncSample函数连续传递硬件事件时间戳进行构造

这个模型通过addPresentFence函数使用传递到DispSync对象的Fence对象的时间戳来进行验证

这些fence时间戳应该对应硬件vsync事件,但他们不需要是连续的硬件vsync时间。如果这个函数确定当前的模型准确地反应了硬件事件的时间

那么就会返回false来表明不需要resyncchronization(通过addResyncSample)。

所以这个类就是用来判定和调节sync周期的,如果周期正确就不调节。

5.DdmConnection

只有一个start函数

6.FrameTracker

信息跟踪类,用于跟踪最近渲染的一些帧的信息,主要记录在mFrameRecords中

7.transform

是一个工具类

8.MessageQueue(重要类)

是SurfaceFlinger的基础

9.MonitoredProducer

封装了一个IGraphicBufferProducer(libgui.so中的类)用于保证当其被销毁时SurfaceFlinger会收到通知

多数是一些对GraphicBuffer的操作及断开连接操作。

10.Client(重要类)

SurfaceComposerClient的一个实现

看实现是用于操作SurfaceFlinger类来创建和销毁Surface的,并且有一个向量以wp<IBinder>为索引存储了多个wp<Layer>对象进行管理

11.SurfaceFlingerConsumer(重要类)

对GLConsumer的简单封装,我们可以看下GLConsumer这个类的注释

GLConsumer消费BufferQueue中的图形数据buffer,并使其变成texture可以被OpenGL使用

 

一个典型的用例模式时设置GLConsumer以期望的选项,然后在需要一个新的frame的时候调用updateTexImage()

如果这个新的frame可用,那么这个texure就被更新,如果不是,那么就会保持前面的内容。

 

默认情况下,texture在第一个调用updateTexImage()的线程中被绑定到一个GL_TEXTURE_EXTERNAL_OES纹理目标

GLConsumer类在先前的Android版本中是叫SurfaceTexture的(= =)

12.EventThread

事件线程

13.EventControlThread

事件管理线程

14.SurfaceFlinger(重要类)

===========然后看下RenderEngine文件夹下的类================

15.RenderEngine

看实现可以知道是对ligegl.so的一层封装,封装EGL调用的一个引擎,如上图,依赖于libegl.so

16.ProgramCache

17.Texture

纹理类

18.Program

操作GLSL脚本着色器的辅助类

19.Description

这个类持有RenderEngine的状态。这个类用于产生一个对应的GLSLprogram并且设置合适的uniform

Program和ProgramChache是其友元

20.Mesh

工具类

21.GLExtensions

工具类,将一些信息转成字符串形式方便打印

===========最后看下DisplayHardware文件夹中的类================

22.DisplaySurface(重要类)

这里关注DisplaySurface的生命周期

beginFrame在获知composition configuration之前,composition loop开始的时候被调用。DisplaySurface应该做任何需要做的事情来使HWComposer

决定如何copose一帧。我们传递mustRecompose参数,我们可以保持VirtualDisplaySurface的状态机,所以在没有任何东西被改变的时候,实际上可以不入队一个buffer

 

prepareFrame在composition  configuration已知但合成发生之前被调用。DisplaySurface可以用composition type来决定如何管理GLES和HWC之间的这一帧的buffer流

 

compositioncomplete应该在composition 渲染完成的时候调用(但并不一定要调用eglSwapbuffers).部分老驱动需要这个函数来保持同步

 

advanceFrame通知surface 这一帧的ELES合成操作已经完成,并且surface需要保证HWComposer拥有这一帧的正确buffer。部分实现可能仅仅在GLES合成发生的时候

将新buffer push到HWComposer,其余的可能需要每一帧都push一个新的buffer。当advanceFrame可能会被再次调用的时候,其后必须跟随一个onFrameCommitted调用

 

onFrameCommitted在frame已经被提交给hardware composer后调用,surface回收这一帧buffer的release fence

 

23.FramebufferSurface(重要类)

继承了DisplaySurface的生命周期,并多了一些能力

 

nextBuffer等待并附着从BufferQueue中过来的下一个buffer并释放先前已经附着的buffer。新buffer会在参数'buffer'中被返回

mDisplayType必须符合HWC显示类型中的一种

mCurrentBufferSlot是当前buffer的slot index或者INVALID_BUFFER_SLOT,用来标明当前buffer是否不存在或者buffer没有关联到一个slot

mCurrentBuffer是当前buffer或者Null,用来标明当前buffer是否不存在

mHwc是一个HardwareComposer,由SurfaceFlinger拥有。

24.VirtualDisplaySurface

支持虚拟显示的一种实现,比如GLES和/或 HWC合成到一个buffer,然后传递给跑在另一个进程中的任意一个消费者

 

最简单的用例是当虚拟显示器不使用h/w composer -h/w composer不支持写buffer,或者有比它能够支持的更多数量的显示器。在这种情况下,GLES驱动直接工作在output buffer queue上,并且从SurfaceFlinger上直接调用虚拟显示器,DisplayHardware不做任何事情。

如果h/w composer可能会被使用,那么每一帧都会是三种配置中的一种:GLES-only,HWC-only,MIXED composition。在所有这些配置中,我们必须为HWC 的set()调用提供一个FrameBuffer和output buffer

 

在ELES-only合成中,GLES 驱动会从sink中给一个buffer给渲染。当GLES驱动将这些buffer以队列形式发送给VirtualDisplaySurface,VirtualdisplaySurface会持有这些buffer而非立即将其压入sink。buffer被HWC同时作为FB target和output buffer使用,尽管在这些帧上HWC没有为这个显示做任何事情,也没有写任何东西到output buffer中。在合成完成后,buffer被入队到sink中。

 

在HWC-only 合成中,VirturalDisplaySurface 将一个buffer 从sink中dequeue 并传递给HWC,同时作为FB target和output buffer。HWC不需要从FB target buffer中读取,单需要向output buffer中写入。在合成完成后,buffer被入队到sink中。

 

在MIXED frames,事情会变得更加复杂,既然一些h/w composer实现不能向同一个buffer中读和写。这个类拥有一个内部BufferQueue作为一个临时buffer 池。GLES驱动被给予一个临时buffer用来渲染。当渲染完成时,buffer入队并且立即被VirtualDisplaySurface获取。这个临时buffer然后被HWC当做FB target buffer,另一个独立的buffer从sink中出队并被当做HWC的outputbuffer。当HWC合成完成时,这个临时buffer被释放而output buffer被入队到sink中。

 

mapSource2ProducerSlot(Source source, int sslot)

mapProducer2SourceSlot(Source source, int pslot)

sink和临时缓冲区池都拥有各自的slot集合("source slots"或"sslot")。我们需要将这些分发到被GLES生产者使用的slot集合中("producer slots"或“pslot”),为了减小生产者slot在他们源slot集合中切换的次数,我们为每个资源将源slot的数量映射到生产者slot的数量

这用的是

 

    uint32_t mOutputFormat;

    uint32_t mOutputUsage;

为了避免重复分配buffer,我们跟踪buffer在前一帧的使用标识及格式并在新的一帧再次使用。如果合成类型改变或者GLES驱动开始请求不同的使用标识或者格式,我们就获取一个新buffer

 

 

25.HWComposer(重要类)

硬件合成类

 

分析完类的作用和角色,我们现在分析一下这些重要类在架构设计上的关系。

 

只保留了一些主要的类,总结如下:

1.三个主要的类是SurfaceFlinger HWcomposer和RenderEngine

2.部分做成员变量的类简化到了成员变量中

3.SurfaceFlingerComsumer在Layer类中被使用

4.整个SurfaceFlinger模块主要依赖外部libgui.so和libegl.so

 

在deleteTextureAsync的时候会调用到RenderEngine的deleteTextures函数

 

 

分析完重要类在架构上的关系之后,详细分析一下SurfaceFlinger的原理,尤其VirtualDisplaySurface的用法。

 

 

通过分析得知,最后绘制的目标为Layer类中的mTexture,参见Layer::onDraw()的实现

所以现在想办法把这个mTexture绘制到Unity中即可

 

mTexture来自于DisplayDevice中的mSecureLayerVisible

 

 

1.SurfaceFlinger中DisplayDevice封装了部分对EGL函数的调用,比如eglSwapBuffers

=============================实现分析=============================================

 

写了demo,应用可以取出SurfaceFlinger中的mTexture并绘制,但是绘制的时候会不停闪烁。

1.绘制的时候不停闪烁

 

2.当前是在TextureObtain中创建了一个Surface,然后取出来显示,但现在是要取到其他进程中的Surface

第一个问题继续调查,可能和刷新周期有关

第二个问题,应该可以通过更改TextureObtain的代码,改成跨进程获取。这里又有两个条件,第一是将自身应用的图像

 

1.任意app的图像可以通过SurfaceFlinger渲染到屏幕上

2.目标效果,要确保LauncherApp仍然正常渲染,只不过在Launcher应用中有一个线程从系统中取出系统屏幕图像来显示

这就要确保,取屏幕的线程取得图像应该不包括Launcher应用的图像,因为如果包含的话,就会出现在Launcher中显示Launcher的情况了。

所以,这个线程应该是取非Launcher的图像显示,其他什么都不动。

 

3.现在确认可以将SurfaceFlinger中的图像取到应用中出来显示。所以现在要考虑的是如何取到其他应用的UI画面。

 

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值