转: http://blog.csdn.net/yili_xie/article/details/4803527


Android
Display System ---SurfaceFlinger

SurfaceFlingerAndroid multimedia的一个部分,在Android的实现中它是一个service,提供系统范围内的surface composer功能,它能够将各种应用程序的2D3D surface进行组合。在具体讲SurfaceFlinger之前,我们先来看一下有关显示方面的一些基础知识

1原理分析

让我们首先看一下下面的屏幕简略图:


每个应用程序可能对应着一个或者多个图形界面,而每个界面我们就称之为一个surface,或者说是window,在上面的图中我们能看到4surface,一个是home界面,还有就是红、绿、蓝分别代表的3surface,而两个button实际是home surface里面的内容。在这里我们能看到我们进行图形显示所需要解决的问题:

a、首先每个surface在屏幕上有它的位置,以及大小,然后每个surface里面还有要显示的内容,内容,大小,位置这些元素在我们改变应用程序的时候都可能会改变,改变时应该如何处理

b、然后就各个surface之间可能有重叠,比如说在上面的简略图中,绿色覆盖了蓝色,而红色又覆盖了绿色和蓝色以及下面的home,而且还具有一定透明度。这种层之间的关系应该如何描述?

我们首先来看第二个问题,我们可以想象在屏幕平面的垂直方向还有一个Z轴,所有的surface根据在Z轴上的坐标来确定前后,这样就可以描述各个surface之间的上下覆盖关系了,而这个在Z轴上的顺序,图形上有个专业术语叫Z-order

对于第一个问题,我们需要一个结构来记录应用程序界面的位置,大小,以及一个buffer来记录需要显示的内容,所以这就是我们surface的概念,surface实际我们可以把它理解成一个容器,这个容器记录着应用程序界面的控制信息,比如说大小啊,位置啊,而它还有buffer来专门存储需要显示的内容。

在这里还存在一个问题,那就是当存在图形重合的时候应该如何处理呢,而且可能有些surface还带有透明信息,这里就是我们SurfaceFlinger需要解决问题,它要把各个surface组合(compose/merge)成一个main Surface,最后将Main Surface的内容发送给FB/V4l2 Output,这样屏幕上就能看到我们想要的效果。

在实际中对这些Surface进行merge可以采用两种方式,一种就是采用软件的形式来merge,还一种就是采用硬件的方式,软件的方式就是我们的SurfaceFlinger,而硬件的方式就是Overlay

2OverLay

因为硬件merge内容相对简单,我们首先来看overlayOverlay实现的方式有很多,但都需要硬件的支持。以IMX51为例子,当IPU向内核申请FB的时候它会申请3FB,一个是主屏的,还一个是副屏的,还一个就是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。

3、SurfaceFlinger

现 在就来看看最复杂的SurfaceFlinger,首先要明确的是SurfaceFlinger只是负责merge Surface的控制,比如说计算出两个Surface重叠的区域,至于Surface需要显示的内容,则通过skia,opengl和 pixflinger来计算。所以我们在介绍SurfaceFlinger之前先忽略里面存储的内容究竟是什么,先弄清楚它对merge的一系列控制的过程,然后再结合2D3D引擎来看它的处理过程。

3.1Surface的创建过程

前面提到了每个应用程序可能有一个或者多个Surface我们需要一些数据结构来存储我们的窗口信息,我们还需要buffer来存储我们的窗口内容, 而且最主要的是我们应该确定一个方案来和SurfaceFlinger来交互这些信息,让我们首先看看下面的Surface创建过程的类图


IBinder左边的就是客户端部分,也就是需要窗口显示的应用程序,而右边就是我们的Surface Flinger service创建一个surface分为两个过程,一个是在SurfaceFlinger这边为每个应用程序(Client)创建一个管理结构,另一个就是创建存储内容的buffer,以及在这个buffer上的一系列画图之类的操作。

因为SurfaceFlinger要管理多个应用程序的多个窗口界面,为了进行管理它提供了一个Client类,每个来请求服务的应用程序就对应了一个Client。因为surface是在SurfaceFlinger创建的,必须返回一个结构让应用程序知道自己申请的surface信息,因此SurfaceFlingerClient创建的控制结构per_client_cblk_t经过BClient的封装以后返回给SurfaceComposerClient,并向应用程序提供了一组创建和销毁surface的操作:


为应用程序创建一个Client以后,下面需要做的就是为这个Client分配SurfaceFlinger为每个Client提供了8M空间,包括控制信息和存储内容的buffer。在说创建surface之前首先要理解layer这个概念,回到我们前面看的屏幕简略图,实际上每个窗口就是z轴上的一个layerlayer提供了对窗口控制信息的操作,以及内容的处理(调用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对应一种类型的窗口,并对应这种窗口相应的操作:LayerLayerBlurLayerBufferLayerDim。不得不说再说Android起的乱七八糟的名字,LayerBuffer很容易让人理解成是LayerBuffer,它实际上是一种Layer类型。各个Layer的效果大家可以参考Surface.java里面的描述:/frameworks/base/core/java/android/view/surface.java。这里要重点说一下两种Layer,一个是Layer (norm layer),另一个是LayerBuffer

Norm LayerAndroid种使用最多的一种Layer,一般的应用程序在创建surface的时候都是采用的这样的layer,了解Normal Layer可以让我们知道Android进行display过程中的一些基础原理。Normal Layer为每个Surface分配两个bufferfront bufferback buffer,这个前后是相对的概念,他们是可以进行Flip的。Front buffer用于SurfaceFlinger进行显示,而Back buffer用于应用程序进行画图,当Back buffer填满数据(dirty)以后,就会flipback buffer就变成了front buffer用于显示,而front buffer就变成了back buffer用来画图,这两个buffer的大小是根据surface的大小格式动态变化的。这个动态变化的实现我没仔细看,可以参照/frameworks/base/lib/surfaceflinger/layer.cpp中的setbuffers()

两个buffer flip的方式是Android display中的一个重要实现方式,不只是每个Surface这么实现,最后写入FBmain surface也是采用的这种方式。

LayerBuffer也是将来必定会用到的一个Layer,个人觉得也是最复杂的一个layer,它不具备render buffer,主要用在camera preview / video playback上。它提供了两种实现方式,一种就是post buffer,另外一种就是我们前面提到的overlayOverlay的接口实际上就是在这个layer上实现的。不管是overlay还是post buffer都是指这个layer的数据来源自其他地方,只是post buffer是通过软件的方式最后还是将这个layer merge主的FB,而overlay则是通过硬件merge的方式来实现。与这个layer紧密联系在一起的是ISurface这个接口,通过它来注册数据来源,下面我举个例子来说明这两种方式的使用方法:

前面几个步骤是通用的:

//要使用Surfaceflinger的服务必须先创建一个client

sp<SurfaceComposerClient> client = new SurfaceComposerClient();

//然后向Surfaceflinger申请一个Surfacesurface类型为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);

3.2应用程序对窗口的控制和画图

Surface创建以后,应用程序就可以在buffer中画图了,这里就面对着两个问题了,一个是怎么知道在哪个buffer上来画图,还一个就是画图以后如何通知SurfaceFlinger来进行flip。除了画图之外,如果我们移动窗口以及改变窗口大小的时候,如何告诉SurfaceFlinger来进行处理呢?在明白这些问题之前,首先我们要了解SurfaceFlinger这个服务是如何运作的:

从类图中可以看到SurfaceFlinger是一个线程类,它继承了Thread类。当创建SurfaceFlinger这个服务的时候会启动一个SurfaceFlinger监听线程,这个线程会一直等待事件的发生,比如说需要进行sruface flip,或者说窗口位置大小发生了变化等等,一旦产生这些事件,SurfaceComposerClient就会通过IBinder发出信号,这个线程就会结束等待处理这些事件,处理完成以后会继续等待,如此循环。

SurfaceComposerClientSurfaceFlinger是通过SurfaceFlingerSynchro这个类来同步信号的,其实说穿了就是一个条件变量。监听线程等待条件的值变成OPEN,一旦变成OPEN就结束等待并将条件置成CLOSE然后进行事件处理,处理完成以后再继续等待条件的值变成OPEN,而ClientSurface一旦改变就通过IBinder通知SurfaceFlinger将条件变量的值变成OPEN,并唤醒等待的线程,这样就通过线程类和条件变量实现了一个动态处理机制。

了解了SurfaceFlinger的事件机制我们再回头看看前面提到的问题了。首先在对Surface进行画图之前必须锁定Surfacelayer,实际上就是锁定了Layer_cblk_t里的swapstate这个变量。SurfaceComposerClient通过swapsate的值来确定要使用哪个buffer画图,如果swapstate是下面的值就会阻塞Client,就不翻译了直接copy过来:

// We block the client if:

// eNextFlipPending:we've used both buffers already, so we need to

//wait for one to become availlable.

// eResizeRequested:the buffer we're going to acquire is being

//resized. Block until it is done.

// eFlipRequested && eBusy: the buffer we're going to acquire is

//currently in use by the server.

// eInvalidSurface:this is a special case, we don't block in this

//case, we just return an error.

所以应用程序先调用lockSurface()锁定layerswapstate,并获得画图的buffer然后就可以在上面进行画图了,完成以后就会调用unlockSurfaceAndPost()来通知SurfaceFlinger进行Flip。或者仅仅调用unlockSurface()而不通知SurfaceFlinger

一般来说画图的过程需要重绘Surface上的所有像素,因为一般情况下显示过后的像素是不做保存的,不过也可以通过设定来保存一些像素,而只绘制部分像素,这里就涉及到像素的拷贝了,需要将Front buffer的内容拷贝到Back buffer。在SurfaceFlinger服务实现中像素的拷贝是经常需要进行的操作,而且还可能涉及拷贝过程的转换,比如说屏幕的旋转,翻转等一系列操作。因此Android提供了拷贝像素的hal,这个也可能是我们将来需要实现的,因为用硬件完成像素的拷贝,以及拷贝过程中可能的矩阵变换等操作,比用memcpy要有效率而且节省资源。这个HAL文件在:/hardware/libhardware/hardware/include/copybit.h

窗口状态变化的处理是一个很复杂的过程,首先要说明一下,SurfaceFlinger只是执行Windowsmanager的指令,由Windows manager来决定什么是偶改变大小,位置,设置透明度,以及如何调整layer之间的顺序,SurfaceFlinger仅仅只是执行它的指令。PSWindows Managerjava层的一个服务,提供对所有窗口的管理功能,这部分的内容我没细看过,觉得是将来需要了解的内容。

窗口状态的变化包括位置的移动,窗口大小,透明度,z-order等等,首先我们来了解一下SurfaceComposerClient是如何和SurfaceFlinger来交互这些信息的。当应用程序需要改变窗口状态的时候它将所有的状态改变信息打包,然后一起发送给SurfaceFlingerSurfaceFlinger改变这些状态信息以后,就会唤醒等待的监听线程,并设置一个标志位告诉监听线程窗口的状态已经改变了,必须要进行处理,在Android的实现中,这个打包的过程就是一个Transaction,所有对窗口状态(layer_state_t)的改变都必须在一个Transaction中。

到这里应用程序客户端的处理过程已经说完了,基本分为两个部分,一个就是在窗口画图,还一个就是窗口状态改变的处理。

更多相关文章

  1. android webview点击返回键回到上一个html
  2. activity属性设置大全
  3. 教你如何更改android应用的包名
  4. [Android(安卓)Pro] android Flag介绍
  5. 一、 Android(安卓)应用程序概述
  6. Android—自动弹出软键盘
  7. Android(安卓)消息处理机制
  8. Android消息处理机制
  9. Dojo mobile TweetView 系列教程之五 —— TweetView: Android,打

随机推荐

  1. VisionMobile:Google博士和Android先生
  2. android中的目录结构
  3. android sdk离线升级方法
  4. AndroidManifest配置文件介绍
  5. Android异步消息处理机制(源码分析+面试题
  6. [置顶] Android平板、TV中对GridView的优
  7. android 快速入门
  8. Android应用的基本原理
  9. INSTALL_FAILED_NO_MATCHING_ABIS 的解决
  10. android平台移植valgrind