Android Display System --- Surface Flingerphp
SurfaceFlinger 是Android multimedia 的一个部分,在Android 的实现中它是一个service ,提供系统 范围内的surface composer功能,它可以将各类应用 程序的2D 、3D surface 进行组合。在具体讲SurfaceFlinger 以前,咱们先来看一下有关显示方面的一些基础知识 。java
1 、原理 分析android
让咱们首先看一下下面的屏幕简略图:数据结构
每一个应用程序可能对应着一个或者多个图形界面,而每一个界面咱们就称之为一个surface ,或者说是window ,在上面的图中咱们能看到4 个surface ,一个是home 界面,还有就是红、绿、蓝分别表明的3 个surface ,而两个button 实际是home surface 里面的内容。在这里咱们能看到咱们进行图形显示所须要解决 的问题:composer
a 、首先每一个surface 在屏幕上有它的位置,以及大小,而后每一个surface 里面还有要显示的内容,内容,大小,位置 这些元素 在咱们改变应用程序的时候均可能会改变,改变时应该如何处理 ?ide
b 、而后就各个surface 之间可能有重叠,好比说在上面的简略图中,绿色覆盖了蓝色,而红色又覆盖了绿色和蓝色以及下面的home,并且还具备必定透明度。这种层之间的关系应该如何描述? 函数
咱们首先来看第二个问题,咱们能够想象在屏幕平面的垂直方向还有一个Z 轴,全部的surface 根据在Z 轴上的坐标来肯定先后,这样就能够描述各个surface 之间的上下覆盖关系了,而这个在Z 轴上的顺序,图形上有个专业术语叫Z-order 。 post
对于第一个问题,咱们须要一个结构来记录应用程序界面的位置,大小,以及一个buffer 来记录须要显示的内容,因此这就是咱们surface 的概念,surface 实际咱们能够把它理解成一个容器,这个容器记录着应用程序界面的控制信息,好比说大小啊,位置啊,而它还有buffer 来专门存储须要显示的内容。ui
在这里还存在一个问题,那就是当存在图形重合的时候应该如何处理呢,并且可能有些surface 还带有透明信息,这里就是咱们SurfaceFlinger 须要解决问题,它要把各个surface 组合(compose/merge) 成一个main Surface ,最后将Main Surface 的内容发送给FB/V4l2 Output ,这样屏幕上就能看到咱们想要的效果。spa
在实际中对这些Surface 进行merge 能够采用两种方式,一种就是采用软件的形式来merge ,还一种就是采用硬件的方式,软件的方式就是咱们的SurfaceFlinger ,而硬件的方式就是Overlay 。
2 、OverLay
由于硬件merge 内容相对简单,咱们首先来看overlay 。 Overlay 实现的方式有不少,但都须要硬件的支持。以IMX51 为例子,当IPU向内核申请FB 的时候它会申请3 个FB ,一个是主屏的,还一个是副屏的,还一个就是Overlay 的。 简单地来讲,Overlay就是咱们将硬件所能接受的格式数据 和控制信息送到这个Overlay FrameBuffer,由硬件驱动来负责merge Overlay buffer和主屏buffer中的内容。
通常来讲如今的硬件都只支持一个Overlay,主要用在视频播放以及camera preview上,由于视频内容的不断变化用硬件Merge比用软件Merge要有效率得多,下面就是使用Overlay和不使用Overlay的过程:
SurfaceFlinger中加入了Overlay hal,只要实现这个Overlay hal可使用overlay的功能,这个头文件在:/hardware/libhardware/include/harware/Overlay.h,可使用FB或者V4L2 output来实现,这个多是咱们未来工做的内容。实现Overlay hal之后,使用Overlay接口的sequence就在 : /frameworks/base/libs/surfaceflinger/tests/overlays/Overlays.cpp,这个sequnce是很重要的,后面咱们会讲到。
不 过在实际中咱们不必定须要实现Overlay hal,若是了解硬件的话,能够在驱动中直接把这些信息送到Overlay Buffer,而不须要走上层的Android。Fsl如今的Camera preview就是采用的这种方式,并且我粗略看了r3补丁的内容,应该在opencore的视频播放这块也实现了Overlay。
三、SurfaceFlinger
现 在就来看看最复杂的SurfaceFlinger,首先要明确的是SurfaceFlinger只是负责merge Surface的控制,好比说计算出两个Surface重叠的区域,至于Surface须要显示的内容,则经过skia,opengl和 pixflinger来计算。 因此咱们在介绍SurfaceFlinger 以前先忽略里面存储的内容到底是什么,先弄清楚它对merge 的一系列控制的过程,而后再结合2D ,3D 引擎来看它的处理过程。
3.1 、Surface 的建立过程
前面提到了每一个应用程序可能有一个或者多个Surface , 咱们须要一些数据结构来存储咱们的窗口信息,咱们还须要buffer 来存储咱们的窗口内容, 并且最主要的是咱们应该肯定一个方案 来和SurfaceFlinger 来交互这些信息,让咱们首先看看下面的Surface 建立过程的类图 :
在IBinder 左边的就是客户端部分,也就是须要窗口显示的应用程序,而右边就是咱们的Surface Flinger service 。 建立一个surface 分为两个过程,一个是在SurfaceFlinger 这边为每一个应用程序(Client) 建立一个管理 结构,另外一个就是建立存储内容的buffer ,以及在这个buffer 上的一系列画图之类的操做。
由于SurfaceFlinger 要管理多个应用程序的多个窗口界面,为了进行管理它提供了一个Client 类,每一个来请求服务的应用程序就对应了一个Client 。由于surface 是在SurfaceFlinger 建立的,必须返回一个结构让应用程序知道本身申请的surface 信息,所以SurfaceFlinger 将Client 建立的控制结构per_client_cblk_t 通过BClient 的封装之后返回给SurfaceComposerClient ,并向应用程序提供了一组建立和销毁surface 的操做:
为应用程序建立一个 Client 之后,下面须要作的就是为这个 Client 分配 Surface , Flinger 为每一个 Client 提供了 8M 的空间 ,包括控制信息和存储内容的 buffer 。在说建立 surface 以前首先要理解 layer 这个概念,回到咱们前面看的屏幕简略图,实际上每一个窗口就是 z 轴上的一个 layer , layer 提供了对窗口控制信息的操做,以及内容的处理 ( 调用 opengl 或者 skia) ,也就是说SurfaceFlinger 只是控制何时应该进行这些信息的处理以及处理的过程,全部实际的处理都是在 layer 中进行的,能够理解为建立一个 Surface 就是建立一个 Layer 。不得不说 Android 这些乱七八糟的名字,让我绕了好久……
建立 Layer 的过程,首先是由这个应用程序的 Client 根据应用程序的 pid 生成一个惟一的 layer ID ,而后根据大小,位置,格式啊之类的信息建立出 Layer 。在 Layer 里面有一个嵌套的 Surface 类,它主要包含一个 ISurfaceFlingerClient::Surface_data_t ,包含了这个 Surace 的统一标识符以及 buffer 信息等,提供给应用程序使用。最后应用程序会根据返回来的 ISurface 信息等建立本身的一个 Surface 。
Android 提供了 4 种类型的 layer 供选择,每一个 layer 对应一种类型的窗口,并对应这种窗口相应的操做: Layer , LayerBlur, LayerBuffer , LayerDim 。不得不说再说 Android 起的乱七八糟的名字, LayerBuffer 很容易让人理解成是 Layer 的 Buffer ,它其实是一种 Layer 类型。各个 Layer 的效果你们能够参考 Surface.java 里面的描述:/frameworks/base/core/java/android/view/surface.java 。这里要重点说一下两种 Layer ,一个是 Layer (norm layer) ,另外一个是LayerBuffer 。
Norm Layer 是 Android 种使用最多的一种 Layer ,通常的应用程序在建立 surface 的时候都是采用的这样的 layer ,了解 Normal Layer 可让咱们知道 Android 进行 display 过程当中的一些基础原理。 Normal Layer 为每一个 Surface 分配两个 buffer : front buffer 和 back buffer ,这个先后是相对的概念,他们是能够进行 Flip 的。 Front buffer 用于 SurfaceFlinger 进行显示,而 Back buffer 用于应用程序进行画图,当 Back buffer 填满数据 (dirty) 之后,就会 flip , back buffer 就变成了 front buffer 用于显示,而 front buffer 就变成了 back buffer 用来画图,这两个 buffer 的大小是根据 surface 的大小格式动态变化的。这个动态变化的实现我没仔细看,能够参照 : /frameworks/base/lib/surfaceflinger/layer.cpp 中的 setbuffers() 。
两个 buffer flip 的方式是 Android display 中的一个重要实现方式,不仅是每一个 Surface 这么实现,最后写入 FB 的 main surface 也是采用的这种方式。
LayerBuffer 也是未来一定会用到的一个 Layer ,我的以为也是最复杂的一个 layer ,它不具有 render buffer ,主要用在 camera preview / video playback 上。它提供了两种实现方式,一种就是 post buffer ,另一种就是咱们前面提到的 overlay , Overlay的接口实际上就是在这个 layer 上实现的。不论是 overlay 仍是 post buffer 都是指这个 layer 的数据来源自其余地方,只是 post buffer 是经过软件的方式最后仍是将这个 layer merge 主的 FB ,而 overlay 则是经过硬件 merge 的方式来实现。与这个 layer 紧密联系在一块儿的是 ISurface 这个接口,经过它来注册数据来源,下面我举个例子来讲明这两种方式的使用方法:
前面几个步骤是通用的:
// 要使用 Surfaceflinger 的服务必须先建立一个 client
sp<SurfaceComposerClient> client = new SurfaceComposerClient();
// 而后向 Surfaceflinger 申请一个 Surface , surface 类型为 PushBuffers
sp<Surface> surface = client->createSurface(getpid(), 0, 320, 240,
PIXEL_FORMAT_UNKNOWN, ISurfaceComposer::ePushBuffers);
// 而后取得 ISurface 这个接口, getISurface() 这个函数的调用时具备权限限制的,必须在 Surface.h 中打开:/framewoks/base/include/ui/Surface.h
sp<ISurface> isurface = Test::getISurface(surface);
//overlay 方式下就建立 overlay ,而后就可使用 overlay 的接口了
sp<OverlayRef> ref = isurface->createOverlay(320, 240, PIXEL_FORMAT_RGB_565);
sp<Overlay> verlay = new Overlay(ref);
//post buffer 方式下,首先要建立一个 buffer ,而后将 buffer 注册到 ISurface 上
ISurface::BufferHeap buffers(w, h, w, h,
PIXEL_FORMAT_YCbCr_420_SP,
transform,
0,
mHardware->getPreviewHeap());
mSurface->registerBuffers(buffers);