android 显示系统 surfaceflinger 分析

 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);

相关文章
相关标签/搜索