码迷,mamicode.com
首页 > 其他好文 > 详细

从surfaceflinger历史变更谈截屏

时间:2017-11-13 21:21:48      阅读:300      评论:0      收藏:0      [点我收藏+]

标签:参考   消费   文章   ice   驱动   ref   直接   一个   win   

众所周知,有一个程序screencap可以截屏,这个程序十分简单,只是使用了surfaceflinger服务的截屏功能。

所以要了解截屏,看surfaceflinger服务的代码是不二首选。但是surfaceflinger也随android系统显示子系统的变更而变更,网上最容易搜到的android资料都在11-14年的文章,都是4.x时代甚至2.x时代的技术,而android代代变化,有不少文章已经不再适用。

2.3.6之前,surfaceflinger放于base目录。这时候的surfaceflinger使用FramebufferNativeWindow。

技术分享

4.0.x开始,suffaceflinger放于native目录。但仍旧使用FramebufferNativeWindow。

技术分享

技术分享

4.2 开始,DisplayHardware类废除(注意DisplayHardware目录或者说组件没有废除,因为显示系统变更了,不再只有一个Display,取而代之的是DisplayDevice类,这个类不在与DisplayHardware目录同级。换句话说,以前surfaceflinger拥有一个DisplayHardware,现在开始就拥有一组DisplayDevice,这些DisplayDevice只代表某一GL上下文,并且不直接访问Hardware层的fbDev,fbDev由HWComposer管理,DisplayDevice只能通过FramebufferSurface去访问Hardware层),不再使用FramebufferNativeWindow,替而引入了FramebufferSurface。

技术分享

4.3 开始,DisplaySurface,VirutalDisplaySurface。并且废除了libgui中的SurfaceTextureClient。

技术分享

在4.1.x之前,我称为FramebufferNativeWindow时代,surface是直接从FramebufferNativeWindow创建的。

技术分享

技术分享

技术分享

技术分享

可以看到这是很常规的egl初始化。

 

在4.2 开始 FramebufferNativeWindow不再使用,因为在以前单一Display的时代,直接将fbDev和ANativeWindow偶合在一起。现在ANativeWindow和fbDev分离开。SurfaceTextureClient替代了FramebufferNativeWindow,并且不与fbDev偶合(,fbDev由HWComposer接管)。这里必须区分好,android显示系统有一个Surface,而egl也有一个EGLSurface,它们的连结点就是ANavtiveWindow,其定义路径在/system/core/include/system/window.h 。

SurfaceTexture之前是直接继承于BnSurfaceTexture,4.2 开始它与BnSurfaceTexture解偶,转而继承ComsumerBase。ComsumerBase拥有的BufferQueue才是继承于BnSurfaceTexture(,定义在/frameworks/native/include/gui/ISurfaceTexture.h)。SurfaceTexture 与 BnSurfaceTexture生产消费者模式,并只作为消费者。

与此同时,在SurfaceTexture.h同一目录添加了Surface(,定义在/frameworks/native/include/gui ,也就是 libgui.so), 相应地在surfaceflinger目录有另一个对应的FramebufferSurface,是surfaceflinger服务私有的类,它是面向DisplayDevice的,是SurfaceTextureClient与HWComposer的结合点(Framebuffer就是指HWComposer,Surface则是SurfaceTextureClient一侧,以及用于它的ConsumerBase)。这里要注意,Surface继承于(,isa)ANativeWindow,而FramebufferSurface却继承于(,isa)ConsumerBase。SurfaceTextureClient 作为ANativeWindow 依赖 ISurfaceTexture 服务器,去实现 ANativeWindow的hook接口queueBuffer以及dequeueBuffer。

下面是surfaceflinger初始化DisplayDevice数组:

技术分享

以及DisplayDevice初始化:

技术分享

技术分享

每个DisplayDevice使用SurfaceTextureClient这个ANativeWIndow去创建EGLSurface,而且这里的SurfaceTextureClient使用的是FramebufferSurface的BufferQueue。

 

在 FramebufferNativeWindow时代,截屏直接使用FBO(,Frame Buffer Object)。

技术分享

然后每一个layer都绘制一次到framebuffer:

技术分享

最后GL读出像素:

技术分享

 

 

在4.2开始,发生这些变化,首先实现的函数参数变化了

技术分享

技术分享

可以看到display不再以整型来作为标识,而是通过binder来标识。回看上面surfaceflinger在初始化DisplayDevice过程,只是简单地 new BBinder() 来作为一个新的DisplayDevice的token,这个token只在binder驱动设备上建立了一个唯一的路径,作用就是用来系统范围内唯一标识。

所以在4.1.x及以前,screencap的代码是:

技术分享

从4.2开始,screencap的代码是:

技术分享

虽然上面说了一大堆的4.2变化,但是在截屏实现没有变化,然而接下来的4.3就完全变化了。

 

4.2,Surface继承于SurfaceTextureClient,但是4.3后,Surface脱离SurfaceTextureClient继承树,实现成另一个ANativeWindow,依赖 producer。记得上面吗,4.2时,SurfaceTextureClient是一个依赖 FramebufferSurface这个consumer的ANativeWinodw。

下面是surfaceflinger对DisplayDevice的初始化:

技术分享

跟着是DisplayDevice的初始化:

技术分享

技术分享

我们来回顾一下,4.1.x以前使用FramebufferNativeWindow来创建EGLSurface,4.2时候使用SurfaceTextureClient(它使用FramebufferSurface),4.3开始,使用Surface。FramebufferNativeWindow, SurfaceTextureClient, Surface都是ANativeWindow。

4.3开始Surface也另外继承DisplaySurface。(...有时间再补充写)。

最重要是captureScreen接口改了

技术分享

实现上也就使用了BufferQueue,而不是IMemory来接收数据。

最最重要是没有放出screencap的最新代码,只停留在4.2时候的版本,也就是你不可能通过参照screencap.cpp去使用这个功能 。

技术分享

可参考Transaction_test.cpp

技术分享

 

从surfaceflinger历史变更谈截屏

标签:参考   消费   文章   ice   驱动   ref   直接   一个   win   

原文地址:http://www.cnblogs.com/bbqzsl/p/7826141.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!