SurfaceFlinger草稿

http://gityuan.com/2017/02/05/graphic_arch/ 

SurfaceFlinger服务在启动的过程中,一共涉及到了三种类型的线程,它们分别是Binder线程、UI渲染线程和控制台事件监控线程
两个sceanrio: view控件显示:Activity--wm--1对多--windows--surface--surfaceflinger--hal buffer---display
渲染: surface--surfaceTexture consumer---opengl--surfaceflinger---hal buffer--display
渲染不存在多个surface合并裁剪.
surfaceflinger 合成是使用透明度还是遮挡裁剪合成??

surfaceFlinger定义&作用&所处位置

作用: 分配图形缓冲区;合成图形缓冲区;管理VSync事件

  • App主要是具体的UI业务需求
  • AMS则是管理系统四大组件以及进程管理,尤其是Activity的各种栈以及状态切换等管理;
  • WMS则是管理Activiy所相应的窗口系统(系统窗口以及嵌套的子窗口);
  • SurfaceFlinger则是将应用UI绘制到frameBuffer(帧缓冲区),最终由硬件完成渲染到屏幕上;

当app来到前台的执行流程:

  1. WMS会请求SurfaceFlinger来绘制surface.
  2. SurfaceFlinger创建layer;
  3. 一个生产者的Binder对象通过WMS传递给app, 因此app可以直接向SurfaceFlinger发送帧信息.

对于大多数的app来说都有3个layers: 状态栏,导航栏,应用UI. 每一个layer都是独立更新的.状态栏和导航栏是由系统进程负责渲染, app层是由app自己渲染,两者直接并没有协作.
一个Layer有一个BufferQueue,一个BufferQueue中有多个Buffer,一般是2个或者3个.
一个Layer和一个Surface是一一对应的,和窗口也是一一对应的。
一个Layer有一个Producer,一个Consumer 结合前面的分析.
Surface也是BufferQueue在Producer端的封装,每个窗口都有且只有一个自己的Surface(同一时刻)。可见,BufferQueue就是两个连接纽带,连接着Producer和Consumer
每一个Client可以有多个Surface也就可以有多个Layer,surface=ANativeWindow类=laye(一个显示层)=SurfaceFlinger Layer=内部有一个Producer,一个Consumer+BufferQueue

作用:Android应用程序请求SurfaceFlinger服务为这个Surface分配一个图形缓冲区,以便可以往这个图形缓冲区写入实际的UI数据。

surfaceFlinger 使用:

Android应用程序请求SurfaceFlinger服务渲染自己的UI可以分为三步曲:
1 创建一个到SurfaceFlinger服务的连接
2 再通过这个连接来创建一个Surface
3 SurfaceFlinger服务渲染该Surface

创建一个SurfaceFlinger实例,用来作为系统的SurfaceFlinger服务,并且将这个服务注册到Service Manager中去,这样系统中的其它组件或者进程就可以通过Service Manager来获得SurfaceFlinger服务的Binder代理对象,进而使用它所提供的服务

只需要调用new SurfaceComposerClient()便建立应用程序跟SurfaceFlinger服务建立连接, 获取了其中两个Binder的代理类。
每一个app在SurfaceFlinger中都有一个Client对象相对应。
SurfaceFlinger会为客户端SurfaceComposerClient创建一个Client,可以跨进程通信、提供Surface的创建、销毁的功能
mClient对应着SurfaceComposerClient,mSurfaceData对应着真正的Surface,后续会被Client创建(SurfaceFlinger创建的Client类)

应用程序app界面的绘制和渲染过程来详细说明各个层次的关系

1 获取图形缓冲区
1) 应用程序通过SDK提供的UI类向Java Runtime Framework里面的WindowManagerService(WMS)申请分配一块图形缓冲区。
2) WindowManagerService(WMS)又是通过Binder IPC向C/C++ Runtime Framework里面的SurfaceFlinger申请分配图形缓冲区的。
图形缓冲区实际上不是由SurfaceFlinger分配的,而是由显示系统分配的,可能在显存里面,也有可能在GPU里面。
3) SurfaceFlinger就要通过HAL层次Gralloc模块向Kernel里面的显卡或者GPU驱动申请分配真正的图形缓冲区。
HAL层可以看作是运行在C/C++ Runtime Framework中。

2 使用opengl绘画
应用程序app通过上述方式得到绘制UI所需要的图形缓冲区之后,就开始绘制自己的UI了。
假设应用程序使用的是硬件绘制方式,也就是通过C/C++ Runtime Framework里面的OpenGL来绘制。
这时候SDK的UI类的与绘制相关的函数调用通过Dalvik虚拟机都转化成了C/C++ Runtime Framework里面的OpenGL操作。
应用程序运行在Dalvik虚拟机上,并且通过SDK使用Java Runtime Framework里面的服务,而Java Runtime Framework里面的服务又通过C/C++ Runtime Framework里面的服务来实现自己的功能,
最后C/C++ Runtime Framework里面的服务又会在需要的时候请求Kernel里面的模块或者驱动来为自己服务。

3 输出到屏幕
应用程序app UI绘制完成之后,结果就保存上述的图形缓冲区中。
这时候如果要将该图形缓冲区渲染到手机屏幕上,那么还需要通过Binder IPC将该图形缓冲区发送给C/C++ Runtime Framework里面的SurfaceFlinger。
SurfaceFlinger通过使用OpenGL或者HWComposer将所有请求要渲染到手机屏幕上的图形缓冲区合成之后,得到一个主图形缓冲区。
最后这个图形缓冲区又会被SurfaceFlinger提交给Kernel的显卡驱动,并且在手机屏幕上进行显示。

surfaceFlinger设计:

从图中可以看出,surface和elgsurface之间还有一层,就是surfaceFlinger.
流程App--opengl--wms(java surface--c++ surface)---surfaceFlinger--EGLsurface--window
WMS和surface关系? an: WMS为所有窗口分配Surface,掌管Surface的显示顺序(Z-order)
surfaceFlinger将多个surface做裁剪合成一个窗体

SurfaceFlinger服务创建一个Surface:
1) 在SurfaceFlinger服务这一侧创建1个Layer对象、和1个SharedBufferServer对象,
2) 在Android应用程序   这一侧创建1个SurfaceControl对象、1个Surface对象和1个SharedBufferClient对象

《卷I》第8章曾详细介绍了一个Activity通过Surface来显示自己的过程:

  • Surface是一块画布,应用可以随心所欲地通过Canvas或者OpenGL在其上作画。
  • 然后通过SurfaceFlinger将多块Surface的内容按照特定的顺序(Z-order)进行混合并输出到FrameBuffer,从而将Android“漂亮的脸蛋”显示给用户。

surfceFlinger 启动:

SurfaceFlinger服务由System进程的主线程来启动,它运行在一个独立的线程中。因为它负责渲染系统的UI,称为UI渲染线程.
SurfaceFlinger服务的UI渲染线程启动的时候,会对系统的硬件帧缓冲区进行初始化。
---在初始化的过程,又会创建另外一个线程来监控硬件帧缓冲区的睡眠/唤醒状态切换事件。这个线程称为控制台事件监控线程。
在SurfaceFlinger服务中,每一个Surface,或者说每一个Layer,都有自己的一系列图形缓冲区。而对于每一个Surface来说,它们各自需要渲染的图形缓冲区都保存在内部的一个UI元数据缓冲区堆栈的待渲染队列中。
--当SurfaceFlinger服务需要渲染系统的UI时,
 1) 将各个Surface的UI元数据缓冲区堆栈的待渲染队列的缓冲区逐个取出来,并且找到对应的图形缓冲区.
 2) 将这些图形缓冲区合成在一起渲染到硬件帧缓冲区fb上
 3) 我们就可以在设备显示屏上看到系统的UI了

,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

Android系统的GUI设计的两种本地窗口:
SurfaceFlinger管理系统中所有UI界面,它需要直接或间接地持有“本地窗口”,这个窗口就是FramebufferNativeWindow
应用程序持有窗口是SurfaceTextureClient

场景1: view 到surfaceFlinger到windows

WMS 为每个Activity创建一个java surface,Activity 组件使用这个java surface 画图,数据流程java surface-->native surface-->surfaceFlinger layer-->

分配图形缓冲区                                                                   合成图形缓冲区

 

 场景2: opengl到surfaceFlinger到windows

                                                                                        渲染流程

数据流程: opengl filter--surface--surfaceFinger--eglsurface--framebuffer(ANativeWindow_Buffer=windows)--display硬件中;surface是双缓冲
双缓冲的时间效率可以参见:https://blog.csdn.net/xuesen_lin/article/details/8954748
下面的内容引自:GUI系统之SurfaceFlinger(1)OpenGLES与EGL https://blog.csdn.net/xuesen_lin/article/details/8954553

       由底层往上层来逐步分析整个架构    

SurfaceFlinger服务通过一个GraphicPlane对象来描述系统的显示屏,即系统的硬件帧缓冲区。
--GraphicPlane类内部聚合了一个DisplayHardware对象,通过这个DisplayHardware对象就可以访问系统的硬件帧缓冲区。
--DisplayHardware类内部又包含了一个FramebufferNativeWindow对象,这个FramebufferNativeWindow对象才是真正用来描述系统的硬件帧缓冲区的。
--FramebufferNativeWindow类的作用是连接OpenGL库和Android的UI系统的一个桥梁,OpenGL库就是通过这个桥梁来将Android系统的UI渲染到硬件帧缓冲区中去的。
--GraphicPlane、DisplayHardware和FramebufferNativeWindow这三个类的关系如图1所示。
--函数首先设置显示屏的初始大小和旋转方向。
--GraphicPlane类有三个成员变量mDisplayWidth、mDisplayHeight和mDisplayTransform,前两者的类型为float,分别用描述显示屏的初始宽度和高度,而后者的类型为Transform,用来描述显示屏的初始旋转矩阵。
--Transform类的作用是来描述变换矩阵,以便后面在渲染UI时可以用来动态地计算显示屏的大小和旋转方向等。
--调用函数eglCreateWindowSurface来创建系统的主绘图表面。系统的主绘图表面是直接在硬件帧缓冲区上创建的,用来渲染系统的UI,即负责合成和渲染所有应用程序的UI
将UI数据写入到这个空闲的图形缓冲区中去,最后再渲染到硬件帧缓冲区中去
--Surface类使用的图形缓冲区一般是在匿名共享内存中分配的,并且是由SurfaceFlinger服务来负责分配,然后再传递给应用程序进程使用的。
--而FramebufferNativeWindow类使用的图形缓冲区是直接在硬件帧缓冲区分配的,并且它可以直接将这些图形缓冲区渲染到硬件帧缓冲区中去。
--要从硬件帧缓冲区(只有一个)中分配和渲染图形缓冲区,就必须要将HAL层中的Gralloc模块加载到当前的进程空间来,并且打开里面的gralloc设备和fb设备,其中,gralloc设备用来分配图形缓冲区,而fb设备用来渲染图形缓冲区
,,,,,,,,,,,,,,,,

1. Linux内核提供了统一的framebuffer显示驱动,设备节点/dev/graphics/fb*或者/dev/fb*,以fb0表示第一个Monitor,当前实现中只用到了一个显示屏
2. Android的HAL层提供了Gralloc,分为fb和gralloc两个设备。前者负责打开内核中的framebuffer、初始化配置,以及提供post、setSwapInterval等操作,后者则管理帧缓冲区的分配和释放。上层只能通过Gralloc访问帧缓冲区,这样一来就实现了有序的封装保护
3. 由于OpenGL ES是一个通用的函数库,在不同的平台系统上需要被“本地化”——即把它与具体平台上的窗口系统建立起关联,这样才能保证它正常工作。从FramebufferNativeWindow这个名称就能判断出来,它就是将OpenGL ES在Android平台上本地化的中介之一。后面我们还会看到应用程序端所使用的另一个“本地窗口”。为OpengGL ES配置本地窗口的是EGL
4. OpenGL或者OpenGL ES 更多的只是一个接口协议,实现上既可以采用软件,也能依托于硬件。这一方面给产品开发带来了灵活性,我们可以根据成本与市场定位来决定具体的硬件设计,从而达到很好的定制需求;另一方面,既然有多种实现的可能,那么OpenGL ES在运行时是如何取舍的呢?这也是EGL的作用之一。它会去读取egl.cfg这个配置文件,然后根据用户的设定来动态加载libagl(软件实现)或者libhgl(硬件实现)。然后上层才可以正常使用各种glXXX接口
5. SurfaceFlinger中持有一个GraphicPlane成员变量mGraphicPlanes来描述“显示屏”;GraphicPlane类中又包含了一个DisplayHardware对象实例(mHw)。具体是在SurfaceFlinger::readyToRun中,完成对它们的创建与初始化。并且DisplayHardware在初始化时还将调用eglInitialize、eglCreateWindowSurface等接口,利用EGL来完成对OpenGLES环境的搭建。其中:
surface =eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
mNativeWindow 就是一个FramebufferNativeWindow对象。DisplayHardware为OpenGL ES设置了“本地化”所需的窗口
6. 很多模块都可以调用OpenGLES提供的API(这些接口以“gl”为前缀,比如glViewport、glClear、glMatrixMode、glLoadIdentity等等),包括SurfaceFlinger、DisplayHardware等
7. 与OpenGL ES相关的模块,可以分为如下几类:
Ø  配置类:即帮助OpenGL ES完成配置的,包括EGL、DisplayHardware都可以认为是这一类
Ø  依赖类:也就是OpenGL ES要正常运行起来所依赖的“本地化”的东西,上图中是指FramebufferNativeWindow
Ø  使用类:使用者也可能是配置者,比如DisplayHardware既扮演了“帮助”OpenGL的角色,同时它也是其使用方。另外只要处在与OpenGL ES同一个环境(Context)中的模块,都可以使用它来完成操作,比如SurfaceFlinger 

用户空间的应用程序在使用帧缓冲区之前,首先要加载Gralloc模块,并且获得一个gralloc设备和一个fb设备。
有了gralloc设备之后,用户空间中的应用程序就可以申请分配一块图形缓冲区,并且将这块图形缓冲区映射到应用程序的地址空间来,以便可以向里面写入要绘制的画面的内容.
最后,用户空间中的应用程序就通过fb设备来将前面已经准备好了的图形缓冲区渲染到帧缓冲区中去,即将图形缓冲区的内容绘制到显示屏中去。

,,,,,,,,,,,,,,,,,,,,,,,

SurfaceFlinger创建BufferLayer,BufferLayer创建BufferQueue,BufferQueue为BufferLayer管理GrapicBuffer。
1)app需要绘制到surface中,绘制UI内容都需要一个GraphicBuffer.
GraphicBuffer是需要Surface去申请和绘制、而由SurfaceFlinger消费和合成,这套生产消费者机制就是BufferQueue机制,平衡协调SurfaceFlinger和Surface。
2)IGraphicBufferProducer就是Surface和BufferQueue交流的渠道,他也是一个binder对象。
--Surface通过IGraphicBufferProducer跟BufferQueue申请和填充GraphicBuffer,根据java层的Surface在SurfaceFlinger创建对应的Layer.
Client创建GraphicBufferProducer跟BufferQueue交互、创建native层的Surface并赋值给java层的Surface。
,,,,,,,,,,,,,,,,,,,,,

组件介绍
SurfaceFlinger:系统服务,接收多个源的数据,对它们进行合成,然后发送到显示设备进行显示。
HWComposer:
Gralloc:
而mGraphicBufferProducer是什么?

surfaceFlinger 源码

 开机显示桌面、从桌面点击 App 图标到 Activity显示在屏幕上的过程又是怎样的呢?下面介绍Android系统中的“画家” - SurfaceFlinger.
  SurfaceFlinger 启动过程:

FramebufferNativeWindow=ANativeWindow类

surfaceFlinger两个类成员FramebufferNativeWindow类和DisplayHardware类:
FramebufferNativeWindow类是用来描述一个Android系统本地窗口,而这个窗口代表的是系统的硬件帧缓冲区。
DisplayHardware类的成员函数flip是用来渲染系统UI的,即将后端的图形缓冲区翻转为前端的图形缓冲区,并且渲染在硬件帧缓冲区去。    
--FramebufferNativeWindow类=Surface类,即它是OpenGL库和Android的UI系统之间的一个桥梁。
OpenGL库正是通过它的成员函数dequeueBuffer来获得一个用来填充UI数据的图形缓冲区,然后通过它的成员函数queueBuffer来将一个已经填充好UI数据的图形缓冲区渲染到系统的帧缓冲区中去。

Android系统是通过OpenGL库来绘制UI的。OpenGL库在绘制UI的时候,需要底层的系统提供一个本地窗口给它,以便它可以将UI绘制在这个本地窗口上。
Android系统为OpenGL库定提供的本地窗口使用ANativeWindow类来描述,Surface类通过EGLNativeBase类间接地继承了ANativeWindow类,因此,Surface类也是用来描述OpenGL绘图所需要的一个本地窗口的。
surface=ANativeWindow类=layer=内部有一个Producer,一个Consumer+BufferQueue
opengl-->ANativeWindow=surface-->UI

OpenGL“本地窗口”(NativeWindow),Android系统通过ANativeWindow实现OpenGL ES的本地化, 而FramebufferNativeWindow是ANativeWindow子类,对应的是真实的物理屏幕。OpenGL ES ->ANativeWindow->FramebufferNativeWindow

这个函数定义在文件frameworks/base/libs/surfaceflinger_client/Surface.cpp中。
这个函数的初始化工作分为两部分。
第一部分初始化工作是与OpenGL库相关的,主要就是设置OpenGL指定的一系列回调接口,以及设置设备显示屏信息。前面提到,Surface类是从ANativeWindow类继承下来的,作为OpenGL库与Android系统的本地窗口的连接桥梁。
第二部分初始化工作是与UI元数据缓冲区相关。

Surface类的成员变量mNextBufferTransform、mSwapRectangle和mNextBufferCrop分别用来描述下一个要渲染的图形缓冲区的旋转方向、裁剪区域和纹理坐标。
Surface类的成员变量mBuffers用来描述一个类型为sp<GraphicBuffer>的Vector,主要是用来保存一个Surface所使用的图形缓冲区(GraphicBuffer)的。一开始的时候,这个向量的大小被设置为2,后面会根据实际需要来增加容量

定义在文件frameworks/base/core/java/android/view/Surface.java
这些JNI方法是由C++层中的函数Surface_show、Surface_hide、Surface_setSize、Surface_setPosition、Surface_setLayer、Surface_setAlpha和Surface_setMatrix来实现的
 

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值