说说Android--显示系统(二)

374 阅读3分钟

书接上文:

Android显示系统是 Canvas OpenGL ES MediaPlayer等生产者生成图像数据放入到BufferQueue中
SurfaceFling ImageReader等消费者从BufferQueue中获取数据,再进行合成并送给屏幕显示出来(送显)。

这期来讲讲 BufferQueue 以及其中的数据

首先我们回顾下这张 生产/消费者 模型图:

image.png

简单解释下生产者/消费者模型(更详细的可以看文章理解):

生产者:只关心数据产生,一旦生成新的数据,它就塞到阻塞队列中
消费者:只关心数据获取,每次都从阻塞队列中获取
如何保证生产和消费的同步呢? 如果生产的很快,不消费,队列是不是就满了
                          如果生产的慢,消费的快,队列就空了。
这就是阻塞队列的特性,他在塞入数据时,如果队列满了,它就会block住,这样生产者生产的快的情况下,就会暂停下来。
消费者获取数据时,如果队列为空时,就会block住,等生产者塞入数据后才能拿到数据返回,通过这样的机制同步速度。

image.png

问题二:图中的BufferQueue是什么?

(这里我们尽量不讲太多代码细节,先理解其中的概念,代码细节分另一个章节展示)

顾名思义:缓存队列 BufferQueue是封装了GraphicBuffer数据的队列。简单理解的话可以类比

ArrayBlockingQueue<GraphicBuffer>

关于BufferQueue的原理这个图更好理解一些:

image.png

BufferQueue为队列中数据GraphicBuffer对象包装了如下状态:

FREE:闲置状态,任何进程都可以获取该buffer进行操作,通常表示为APP进程可以申请使用的内存

DEQUEUED:出列状态,通常是APP进程在绘图,使用者是GPU

QUEUED:入列状态,表示APP绘图已经完成,等待从队列取出执行下一步合成,没有使用者

ACQUIRED:锁定状态,通常表示sf进程从队列取出,正在做合成工作,此时使用者可能是hwc也有可能是GPU

SHARED:共享状态,7.0版本加入的新状态,没找到相关介绍资料,合成工作完成以后共享给录屏软件?

流程梳理:

  1. Producer(比如Surface) 通过dequeueBuffer拿到一个FREE状态下的GraphicBuffer对象 (buffer状态从变化:FREE ---> DEQUEUED)
  2. 一通数据写入后Producer通过queueBuffer将Dequeued状态下的Buffer塞入BufferQueue中(buffer状态变化:DEQUEUE ---> QUEUED
  3. Consumer(比如SurfaceFling) 通过acquireBuffer从队列中拿到一个QUEUED状态的Buffer准备送去合成送显(buffer状态变化:QUEUED ---> ACQUIRED
  4. 这个数据显示完成后,Consumer通过releaseBuffer将GraphicBuffer还给BufferQueue便于重新使用(buffer状态变化:ACQUIRED ---> FREE )
  5. 这样周而复始,完成屏幕内容的展示 (具体的代码分析下回讲解,本期关注流程的理解)

下图为不同状态的字段值(来源BufferSlot.h):

mSharedmDequeueCountmQueueCountmAcquireCount
FREEfalse000
DEQUEUEDfalse100
QUEUEDfalse010
ACQUIREDfalse001
SHAREDtrueanyanyany

总结状态变化图:

image.png

关于 BufferQueue源码解析,GraphicBuffer具体是什么? 我们下回分解