android图形系统架构 深入剖析android新特性 第九章 笔记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012654756/article/details/88956686

第九章 图形系统改进

早期android卡顿,jelly bean 4.0后有改进

9.1 图形系统整体架构

AP有两种绘制图形方法,

canvas:

android.graphics.Canvas是2D的图形API,Canvas API的硬件加速通过一个名为OpenGLRenderer的绘图库实现,

它将Canvas操作转换为OpenGL操作,以便可以在GPU上执行。

4.0开始,Canvas默认就会启动硬件加速,所以GPU支持OGLES 2.0是强制性的。

OpenGL:

开发人员渲染图形的另一个主要方式是用OGLES,Android在android.opengl软件包提供OpenGLES接口,开发人员可用SDK或者AndroidNDK提供原生API调用其GL实现。

9.1.1, Android图形组件

无论用什么API,最终都在Surface上渲染,

Surface描述了BufferQueue的生产者,BufferQueue的消费者通常是SurfaceFlinger

Android平台上所有窗口在创建时都伴随这surface,

所有可见的surface由surfaceflinger负责合成并最终显示到显示器上。

Android图形系统的架构与主要组件:

IMAGE STREAM PRODUCERS

Media Player Camera Preview NDK OpenGL ES

WINDOW POSITIONG NATIVE FRAMEWORK(frameworks/native/libs/gui)

WindowManager Surface.cpp

IMAGE STREAM CONSUMERS---------------> GLConsumer.cpp

OpenGLES Apps IGraphicBufferProducer

SurfaceFlinger------------|

|

HAL

Hardware Composer Gralloc

说明:

Image Stream Producers:

图形流生产者,是任何可能产生Graphics Buffer的对象,如OpenGLES,Canvas 2D,或者mediaserver视频解码器

Image Stream Consumers:

图形流消费者,最常见的消费者是SurfaceFlinger,这个系统服务根据当前可见的Surface并且根据WindowManager提供的信息,来将它们合成并且输出到显示屏上。

SurfaceFlinger是唯一可以修改显示屏内容的组件,它使用OpenGL和Hardware Composer来合成Surface。

除了SurfaceFlinger,其他消费者可能是OGLES(如相机),也可能不是OGL应用,如ImageReader。

imageReader是干嘛的?

Window Manager:

窗口管理器,系统中专门用来管理窗口的系统服务。

窗口是View的容器,每个窗口都会包含一个Surface。

WindowManager管理窗口的各方面,包括:生命周期,输入,焦点事件,屏幕旋转,切换动画,位置,转换,Z-order,等。

WindowManager会将Window的这双鞋元数据传递给SurfaceFlinger,

这样SF便知道如何将它们合成并显示出来

Hardware Composer:

硬件合成器,这是显示子系统的硬件抽象。

SF会委派一个合成的工作给Hardware Composer,来减轻OGL和GPU的负载。

这样做比单纯通过GPU去合成消耗更少的电量。

HWComposer的硬件抽象层主导了另外一半的工作,它是Android图形渲染的核心。

HWComposer必须支持事件,如VSYNC事件和hotplug(HDMI即插即用)事件。

Gralloc:

图形内存分配器,Graphics memory allocator,

用来分配图形的内存

Android图形系统的显示流程:

SurfaceFlinger HWCOMPOSER

STATUS BAR ->GPU ------->BUFFER QUEUE -------> GPU->BUFFER QUEUE -------->DISPLAY CONTROLLER

SYSTEM BAR ->GPU ------->BUFFER QUEUE ------->

BACKGROUND RENDERER->GPU ->BUFFERQUEUE

ICONS/WIDGETS REDNERER->GPU->BUFFERQUEUE

左边的对象如Home Screen,Status Bar,SystemUI,是GraphicsBuffer的生产者,

中间的SurfaceFlinger是排版者Compositor,

右边的HardwareComposer是最终的合成者Composer

9.1.2 组件

从Android图形系统的实现来看,整个系统主要包含以下组件,

底层组件:

1,BufferQueue与gralloc:

BufferQueue生成图形数据Buffer(生产者)的内容连接到接收数据进程显示或者进一步处理(消费者)的模块上。

图形数据的Buffer通过图形内存分配器Gralloc进行分配。这些分配器由厂商的HAL接口实现。

2,SF,HWComposer与虚拟显示器:

SF接收来自多个数据源的数据缓冲区,将它们合成并发送到显示器上,

HWComposer HAL(HWC)根据硬件情况决定最高效的缓冲合成方式,虚拟显示使系统内的合成输出可用,

如录制屏幕或者通过网络发送屏幕。

3,Surface,Canvas,SurfaceFlinger:

surface会产生一个被SF使用的缓冲区队列。

当渲染到Surface上时,结果将在缓冲区中被传递给消费者。

Canvas API提供了一个软件实现(具有硬件加速支持),用于直接在Surface(OpenGLES的底层代替)上绘制的方法,

任何与视图相关的内容都涉及SurfaceHolder,它提供API来获取和设置Surface的参数,如尺寸和格式。

4,EGLSurface和OpenGLES

OpenGLES定义了图形渲染API,它与EGL组合,该库通过操作系统来创建和访问窗口(若是绘制纹理多边形,则用GLES调用;若是将渲染结果显示在屏幕上,则用EGL调用)

5,Vulkan

Vulkan是一套跨平台的高性能3D图形API。像OGLES一样,Vulkan提供了在AP中创建高质量、实时图形的工具。

Vulkan优势包括降低GPU开销,支持SPIR-V二进制中间语言。

上层组件:

1,SurfaceView和GLSurfaceView

SurfaceView结合了Surface和View,

SurfaceView的View组件由SurfaceFlinger(而不是APP)合成,可以从单独的线程/进程渲染,并与AP的UI呈现隔离。

GLSurfaceView提供帮助类来管理EGL上下文,跨线程通信以及与Activity生命周期的交互(但不需要使用GLES)

2,SurfaceTexture:

SurfaceTexture结合了一个Sureface和GLES纹理来创建一个BufferQueue,APP是消费者。

当生产者将新的缓冲区排入队列时,它会通知APP,APP会依次释放先前占有的缓冲区,

从队列中获取新缓冲区并执行EGL调用,从而使GLES可将此缓冲区作为外部纹理。

Android7增加了对保护视频内容进行GPU后处理的安全纹理视频播放的支持。

3,TextureView

TextureView将View与SurfaceTexture结合在一起

TextureView包装一个SurfaceTexture,并且负责响应回调和获取新的缓冲区,

绘图时,TextureView使用最近收到的缓冲区的内容作为其数据源,根据View状态指示,

在它应该渲染的位置和以它应该渲染的方式进行渲染,View合成始终通过GLES执行,这意味着内容更新可能导致其他Vie元素重绘。

9.1.3 Android如何绘制视图

当Activity接收到焦点时,系统将会对其布局进行进行绘制,

Android框架将处理绘图过程,但是Activity必须提供其布局层次结构的根节点,

绘制从布局的根节点开始,绘制过程遍历整个ViewTree结构并渲染每一个View,

相应的,每个ViewGroup负责请求每个子项被绘制(通过draw()方法),

每个View负责绘制其本身。

因为ViewTree被顺序的遍历,这意味着父母将在他们的孩子之前(即后面)被绘制,同一个层次的View将按照他们出现在树中的顺序进程绘制。

绘制ViewTree包含两步骤:测量和布局

测量

测量由measure(int, int)实现,按照ViewTree自顶向下遍历。

在地柜期间,每个View在树上报告其自身的尺寸。

在测量结束时,每个View都存储了策略结果。

布局

布局通过layout(int, int, int)实现,也是自顶向下的。在此过程中,每个父元素通过在前一步得到的每个子元素的尺寸来布局。

开发者可以通过invalidate()对View进程强制绘制。

当View对象的measure()方法返回时,必须设置其getMeasuredWidth()和getMeasuredHeight()以及所有View子元素的值。

View对象的宽度和高度值必须遵守View对象的父元素施加的约束。

这保证了测量结束时,所欲父元素都接受所有子元素的尺寸。

父View可能会在其子元素上多次调用measure(),如,父元素可以用未指定的尺寸度量每个子元素一次,以找出他们想要多大,若所有孩子的无约束大小的总和太大或者太小,再用实际数据调用measure()(也就是说子元素不同意他们各自获得的多数空间,父元素将介入并在第二步时设定规则)

策略通过两个类表达维度:ViewGroup.LayoutParams和MeasureSpec

LayoutParams类告诉他们的父元素他们自身如何被测量和定位。三种:

一个确切数字

MATCH_PARENT,View要和其父元素一样大

WRAP_CONTENT,View想要足够大以包含其内容

MeasureEpec对象用于从父元素推送要求到子对象。三种模式:

UNSPCIFIED:用于父View确定子View的所需尺寸,

EXACTLY:父View使用这个方式对子View施加确切的大小

AT_MOST:父View对子View限制最大的大小。

9.1.4 硬件加速

Android从3.0(API level 11)开始2D图形渲染支持硬件加速,

从4.0(API Level>14)开始则默认打开

不使用硬件加速的情况下,所有渲染工作通过软件实现,最终由CPU完成。

而在使用硬件加速的情况下,通过OpenGLREdnerer由GPU进行渲染。

软件渲染,与 使用硬件加速渲染的流程:

SoftWare rendering:

View.onDraw() -> Canvas.draw() -> Rasterizer -> Display

HardwareRendering:

View.onDraw() -> Canvas.draw() -> OpenGLRenderer -> GPU -> Display

对开发者来说,硬件加速可以下四个层次进行控制:

App,Activity,Window,View

App与Acitivty的硬件加速控制直接在AndroidManifest.xml设置:

<application android:hardwareAccelerated="ture">

<acitivyt .../>

<activity android:hardwareAccelerated="false" />

</application>

Window的硬件加速开关通过代码设置:

getWindow().setFlags(

WindowManager.LayoutParams.FLAG_HARDWER_ACCELERATED,

WindowManager.LayoutPraams.FLAG_HARDWER_ACCELERATED

);

View的硬件加速开关也是通过代码:

view.setLayerTYpe(View.LAYER_TYPE_SOFTWAER, null);

另外,框架还提供了接口来查询是否启用了硬件加速

View.siHardwareAccelerated();

Canvas.isHardwareAccelerated();

推荐资料:

https://source.android.com/devices/graphics/

https://developer.android.coim/guide/topics/ui/how-android-draws.html

https://developer.android.com/guide/topics/graphics/2d-graphics.html

https://developer.android.com/guide/topics/graphics/hardware-accel.html

猜你喜欢

转载自blog.csdn.net/u012654756/article/details/88956686