Android Display Graphics #BufferQueue与Gralloc

Android智能座舱系列

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

1、BufferQueue

下面这个图片是Google的官方示例,描述了BufferQueue生产者消费者模型。

Android S 版本引入了BLAST Buffer Queue,BLAST主要解决:

1、应用程序在缓冲区的提交中灵活性不足;2、窗口与应用绘制之间无法做到同步,多进程数据无法做到同步;3、简化 SF 中的模型。

Android S 版本之前

  • Producer一般是app,Consumer一般指SurfaceFlinger。
  • 应用绘制缓冲区仅能通过 BufferQueue IGBP(IGraphicBufferProducer) 提交;
  • 应用窗口Geometry的改变仅能通过事务(Transaction)提交;
  • 通过合并事务(Transaction.merge())或延迟事务来更改应用窗口间的Geometry;
  • 多进程缓冲区之间无法做到同步。

Android S 或更高版本

  •  BufferQueue 完全存在于 App 进程,dequeue,queue,acquire,release Buffer 的操作均由 App 进行。
  • 应用绘制缓冲区可以通过事务Transaction.setBuffer()进行提交;
  • 应用窗口Geometry的改变可以通过BlastBufferQueue进行提交;
  • 应用绘制的缓冲区和应用窗口Geometry可以进行同步;
  • 多应用绘制的缓冲区之间可以进行同步。


2、BlustBufferQueue初始化

在ViewRootImpl的performTraversals方法中,如果App层使用BLASTBufferQueue,会在relayoutWindow()时,构造new BLASTBufferQueue对象,进而一步步调用到BLASTBufferQueue.cpp的BLASTBufferQueue构造函数。

CreateBufferQueue()函数中构造了BufferQueueCore、IGraphicBufferProducer、BufferQueueConsumer。

从ViewrootImpl到BlastBufferQueue的调用流程大致如下:

3、Consumer的绑定

BLASTBufferQueue::BLASTBufferQueue()构造函数中,在

createBufferQueue(&mProducer, &mConsumer)后,又初始化图形缓冲区消费者

mBufferItemConsumer = new BLASTBufferItemConsumer();

BLASTBufferItemConsumer继承BufferItemConsumerBufferItemConsumer继承自ConsumerBase

创建BLASTBufferItemConsumer时,ConsumerBase的构造函数中实现了如下功能:

1)将ConsumerBase转换为ConsumerListener。

2)将ConsumerListener封装为ProxyConsumerListener。

3)向Consumer注册回调。

 IGraphicBufferConsumer的cosumerConnect方法是一个跨进程调。最终会调用BufferQueueConsumer的connect方法。

这一步也就让 BLASTBufferItemConsumer 建立了对Buffer状态的监听。

调用流程如下:

4、设置图形缓冲区监听器

BLASTBufferItemConsumer 具有监听Buffer所有状态的能力,BBQ对Buffer特定状态的监听离不开 BLASTBufferItemConsumer ,因此,BBQ 继承了两个抽象类 ConsumerBase 与 BufferItemConsumer,分别针对 Buffer 消费状态与生产状态进行监听。

BBQ初始化完成,消费者模型建立完成,由于BBQ动态监听缓冲区的状态,如果有可消费的缓冲区,BBQ会触发缓冲区的事务提交:


如下的调用栈可以看出调用关系:

  1. Producer的绑定

前面文章《从Activity看surface的创建》中介绍了Surface的创建过程,创建BBQ的流程,在ViewRootImpl.getOrCreateBLASTSurface方法中,创建完BBQ,紧接着会创建Surface对象,直接看Native 对象的构造函数:

Surface的构造函数会传入生产者模型 GraphicBufferProducer,这使Surface对象拥有了操作缓冲区的能力。构造函数中Surface也提供了一系列hook为首的函数,连接到ANativeWindow的函数指针,为的是给EGL模块提供对缓冲区操作的入口。而hook函数会直接调用内部的本地函数。

APP绘制不需要通过hook函数来中转,当上层通过Surface.lockCanvas方法获取画布时会直接调用本地函数函数 Surface::dequeueBuffer

  1. 数据流

下图是BufferQueue机制的数据流,根据代码分析下各自调用流程:

Buffer有5中状态,定义如下:

FREE:表示Buffer可以被producer在dequeue时获取它的slot由BufferQueue持有当调用dequeueBuffer时,buffer转换为DEQUEUED。

DEQUEUED:表示buffer已被producer从Bufferqueue中取出,但还未QUEUED或CANCEL。当这个Buffer的释放栅栏发出信号(release fence is signaled)时,producer就可以修改Buffer的内容。Slot由producer持有。它通过queueBuffer或attachBuffer可以转换到QUEUED或通过cancelBuffer或detachBuffer转换成FREE。

QUEUED表示缓冲区已被Producer填充,并入队Consumer使用。Buffer内容可以在有限的时间内继续被修改,在相关的fence 被signaled前不能访问内容。该Slot由BufferQueue持有它通过acquireBuffer可以转换到ACQUIRED,如果另一个缓冲区以异步模式排队则转换成FREE。

ACQUIRED表示Buffer已被Consumer获取。与QUEUED一样,在获取栅栏(acquire fence)发出信号(is signaled)之前,Consumer不能访问内容。 SlotConsumer持有通过releaseBuffer或detachBuffer转换为FREE。detached buffer 可以通过attachBuffer()进入ACQUIRED状态。

SHARED:表示buffer正以共享缓冲区模式使用。它可以是除FREE外,同时处于其他状态的任何组合。 也可以多次DequeuedQueuedAcquired

6.1 DequeueBuffer

。。。。。。

6.2 QueueBuffer

。。。。。。

6.3 onFrameAvailable和AcquireBuffer

。。。。。。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值