Android Display Graphics #2 整体框架介绍二

如果图片链接失败,请扫码查看文章详情。

Android Display Graphics系列文章-汇总

系列文章请扫关注公众号!

目录

1、Android 图形元素

不管开发的小伙伴使用系统的哪个API显示内容,最终都会将显示内容渲染到surface上。前面说了,Surface理解为存储数据的内存块,实际上Surface表示缓冲区队列BufferQueue的生产者角色,而缓冲区队列BufferQueue一般被SurfaceFlinger消费掉,也就是说SurfaceFlinger扮演的是缓冲区队列BufferQueue的消费者。

Android平台上创建的每一个窗口都由Surface提供支持的。所有被渲染的可见的Surface都被SurfaceFlinger合成并送显到Display上。

协作图如下:

上图的系统架构是生产者-消费者模式,从上到下的层次:

Image Stream Producers

•  图像数据的生产者,可以是Media Player视频解码器,Camera预览,NDK调用,OpenGL ES接口。可以分为两类数据的传输,一个是真正的显示帧数据BufferData,即Surface,通过BufferQueue的方式调用libgui的接口入队。一个是窗口信息的传递WindowMetadata,即窗口的大小,位置等。

•  例如view每次执行lockCanvas->draw->unlockCanvas,会存入一帧数据进入BufferQueue中。

Native Framework

•  Framework对上层提供的接口在libgui中,frameworks/native/libs/gui。在这里可以操作Surface出队入队Buffer队列BufferQueue。实现Buffer的生成和BufferQueue数据跨进程之间的传递。

WindowManager

• 计算窗口大小,位置等,并传递相应的参数到SurfaceFlinger,SurfaceFlinger根据这些Window Metadata信息,设置窗口Window的大小、z-order等。

Image Stream Consumers

• 代表的是图像数据的消费者。SurfaceFlinger消耗的是BufferQueue中visible的Surface,并使用WindowManager中的Metadata信息对这些Surface进行合成。SurfaceFlinger是可以修改显示内容的唯一服务,也是显示系统中承上启下的核心服务。

•  SurfaceFlinger 使用 OpenGL 和 Hardware Composer 来合成一组 Surface。OpenGL ES 应用也可以消耗图像流,例如相机应用会消耗相机预览图像流。非 GL 应用也可以是消费者,例如 ImageReader。

HAL 硬件混合渲染器

•  这块主要如前一节介绍的HWC,DPU相关。一块是Hardware Composer也用于合成和送显。当SurfaceFlinger中合成的图层时,会请求composer合成,因为它合成的快,功耗又低。如果合成的layer数大于composer支持的最大数了,那剩下的就让SurfaceFlinger通过GPU合成,最后统一送给HardwareComposer送显。

•  SurfaceFlinger在请求HWC Composer合成时,本身充当了一个OpenGL ES的client端。

•  Gralloc 是系统图像显示的内存分配器,用来分配图像生产者请求的内存。和系统的ION是有关的。

GraphicBuffer介绍

应用有显示需求时,应用会向系统申请一块GraphicBuffer内存,这块内存将会共享给GPU用于执行渲染工作,接着会同步给HWC用于合成和显示。

GraphicBuffer是Display系统中的显示内存管理类,在APP、SurfaceFlinger、HardwareComposer之间传递。渲染和合成操作都将在GraphicBuffer上进行的。

定义在/frameworks/native/libs/ui/include/ui/GraphicBuffer.h

class GraphicBuffer

     : public ANativeObjectBase<ANativeWindowBuffer, GraphicBuffer, RefBase>,

       public Flattenable<GraphicBuffer>

{

    friend class Flattenable<GraphicBuffer>;

public:

......

static sp<GraphicBuffer> from(ANativeWindowBuffer *);

static GraphicBuffer* fromAHardwareBuffer(AHardwareBuffer*);

static GraphicBuffer const* fromAHardwareBuffer(AHardwareBuffer const*);

     AHardwareBuffer* toAHardwareBuffer();

     AHardwareBuffer const* toAHardwareBuffer() const;

     // Create a GraphicBuffer to be unflatten'ed into or be reallocated.

     GraphicBuffer();

    // Create a GraphicBuffer by allocating and managing a buffer internally.

     // This function is privileged.  See reallocate for details.

     GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,

             uint32_t inLayerCount, uint64_t inUsage,

             std::string requestorName = "<Unknown>");

......

}

可以与ANativeWindowBufferAHardwareBuffer相互转换。上层JNI的调用封装在android_hardware_HardwareBuffer.cppandroid_graphics_GraphicBuffer.cpp 

Libgui.so中有广泛使用这个对象,并将封装在一个Surface中,例如

/frameworks/native/libs/gui/Surface.cpp

Surface::attachBuffer函数将Surface与GraphicBuffer attached。

GraphicBuffer 的分配和回收由gralloc管理。

Fence机制

一个GraphicBuffer对象完整的生命周期大概是这样:

  • 渲染阶段:应用有绘图需求了,由GPU分配一块内存给应用,应用调用GPU执行绘图,此时使用者是GPU
  • 合成阶段:GPU渲染完成后将图层传递给sf进程,sf进程决定由谁来合成,hwc或者GPU 
    • 如果使用GPU合成,那么此时buffer的使用者依旧是GPU
    • 如果使用hwc合成,那么此时buffer的使用者是hwc
  • 显示阶段:所有的buffer在此阶段的使用者都是hwc,因为hwc控制着显示芯片

从生命周期可以看出GraphicBuffer对象在流转的过程中,会被GPU、CPU、DPU三个不同的硬件访问,此时需要一个同步机制。用来保证跨硬件访问时的数据安全。可以把Fence理解为一把硬件的互斥锁。

每个需要访问GraphicBuffer的角色,在使用前都要检查这把锁是否signaled了才能进行安全的操作,否则就要等待。

  • active状态,该GraphicBuffer正在被占用
  • signaled状态,表明不再控制buffer

BufferQueue

GraphicBuffer的queue队列,BufferQueue的引入是为了解决性能问题。如果只有一个Buffer,是不合理的,因为在渲染、合成、送显这个相当于线性执行,效率太低。所以就有了double和triple缓冲机制,相当于有的Buffer在渲染的同事,另外Buffer可以合成、送显。这样就提高了效率。

Surface的概念是对APP进程讲的,Layer是对系统进程讲的,例如SurfaceFlinger。

前面说的生产者-消费者模型,对于BufferQueue来说就是

这里的producer就是前面说的各app,当app create一个Surface时就向BufferQueue队列申请一个buffer,这个过程称为dequeue。当app绘制(渲染)好这个Surface后就放入BufferQueue中,这个过程称为queue。

这里的Consumer如上面说的,对于可见layer,它就是SurfaceFlinger。当buffer 放入BufferQueue后,通知SurfaceFlinger消费。SurfaceFlinger从BufferQueue拿buffer的过程称为acquire。当SurfaceFlinger合成完后,就将buffer释放并放回BufferQueue中,这个过程称为release。

声明和定义在libgui.so中 /frameworks/native/libs/gui/include/gui/BufferQueue.h

class BufferQueue {

static void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,

            sp<IGraphicBufferConsumer>* outConsumer,

            bool consumerIsSurfaceFlinger = false);

}

创建BufferQueue时需要传入producer和Consumer。

GraphicBuffer在producer、BufferQueue、Consumer之间传递,是有状态的。GraphicBuffer就是在不断地循环FREE->DEQUEUED->QUEUED->ACQUIRED->FREE这个过程。

数据流

Android数据流的经典图如下

重点是深刻理解这张图:

  1. 我们看到的手机界面一般是有4个及以上Surface组成的;例子见上篇文章GPU部分;
  2. 这里也是4个Surface,左侧黄色部分,layer1 Status Bar,layer2 System Bar Renderer,layer3 Background Renderer,layer4 Icons/Widgets renderer;所有layer都是通过GPU(硬件加速)渲染;
  3. 每个layer使用GPU渲染后将Buffer入队queue到BufferQueue,所以每个layer都有自己的BufferQueue
  4. 合成时SurfaceFlinger询问HWComposer,哪些layer给它。随后将layer3,layer4给到HWComposer去合成了;
  5. Layer1、layer2由SurfaceFlinger合成为layer12,layer12又通过BufferQueue机制给到HWComposer;
  6. 最后由HWComposer统一合成到一起再送显。

详细流程可见下图:

2、Google组件库

Andorid Graphic中低级别组件库用来控制图形内存的流转、封装Buffer结构。比如CPU、GPU和HWC要共享同一块内存,需要一种格式让它们都能识别这块内存并且还要互斥访问。

Android Graphic中包含了[libui.so]和[libgui.so]两个低级别组件库。

libui.so

其中GraphicBuffer,GraphicBufferAllocator, Fence都定义在libui库中。应用开发者通常不会直接使用libui.so中的接口,因为它们比较底层。相反,这些接口被封装在更高级别的API中

libgui.so

libgui.so库在libui.so的基础上提供了更高级的图形界面功能。它主要负责图形缓冲区的管理和传输,以及与SurfaceFlinger的交互。包含:

  1. BufferQueue:管理图形缓冲区的生产和消费。生产者(如相机或视频解码器)生成图形数据,消费者(如SurfaceFlinger)使用这些数据进行显示。
  2. SurfaceComposerClient:提供与SurfaceFlinger交互的接口,允许应用程序创建和管理窗口。
  3. IGraphicBufferProducerIGraphicBufferConsumer:定义了生产者和消费者之间的接口,用于图形缓冲区的传输。
  4. DisplayEventReceiver:处理显示事件,如VSync信号,用于同步显示更新。

开发者通常不会直接使用libgui.so中的接口,而是通过Android框架提供的更高级别的API来间接使用。例如,开发者通过SurfaceView、TextureView等类来使用这些底层功能。

  • 8
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dwyane05

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值