Buffer状态
对于生产者这边,BufferQueue的流程基本讲完了。简单说来,首先提需求,告诉BufferQueue需要什么样的Buffer,大小,格式,usage等等;然后dequeue Buffer出来,往Buffer里面绘制显示数据;绘制完成后,queue到BufferQueue里面,并通知消费者进行消费。如此不断的的dequeue,绘制,queue。
消费者这边的流程,我们还没有讲到。对于消费者来说,收到通知后,将从BufferQueue里面取queue过来的Buffer进行合成,合成完的Buffer再释放掉,这里的释放,是概念上的,并没有真正释放内存,只是让其返回队列,可以被再次dequeue。消费者这边也是不断的接通知,取buffer合成,然后释放,不断循环。
此图是Android官网对BufferQueue通信过程的描述,这很好的描述这个过程。
在Android 6.0及之前的版本,在这些通信过程中,都将Buffer的状态标记为具体的状态。这四个过程Buffer分别对应不同的四个状态:
-
DEQUEUED 状态
Producer dequeue一个Buffer后,这个Buffer就变为DEQUEUED状态,release Fence发信号后,Producer就可以修改Buffer的内容,我们称为release Fence。此时Buffer被Producer占用。DEQUEUED状态的Buffer可以迁移到 QUEUED 状态,通过queueBuffer或attachBuffer流程。也可以迁移到FREE装,通过cancelBuffer或detachBuffer流程。 -
QUEUED 状态
Buffer绘制完后,queue到BufferQueue中,给Consumer进行消费。此时Buffer可能还没有真正绘制完成,必现要等对应的Fence发信号出来后,才真正完成。此时Buffer是BufferQueue持有,可以迁移到ACQUIRED状态,通过acquireBuffer流程。而已可以迁移到FREE状态,如果另外一个Buffer被异步的queue进来。 -
ACQUIRED 状态
Buffer已经被Consumer获取,但是也必须要等对应的Fence发信号才能被Consumer读写,找个Fence是从Producer那边,queueBuffer的时候传过来的。我们将其称为acquire fence。此时,Buffer被Consumer持有。状态可以迁移到FREE状态,通过releaseBuffer或detachBuffer流程。除了从acquireBuffer流程可以迁移到ACQUIRED状态,attachBuffer流程也可以迁移到ACQUIRED状态。 -
FREE 状态
FREE状态,说明Buffer被BufferQueue持有,可以被Producer dequeue,它将迁移到DEQUEUED状态,通过dequeueBuffer流程。 -
SHARED状态
SHARED状态是一个特殊的状态,SHARED的Buffer并不参与前面所说的状态迁移。它说明Buffer被用与共享Buffer模式。除了FREE状态,它可以是其他的任何状态。它可以被多次dequeued, queued, 或者 acquired。这中共享Buffer的模式,主要用于VR等低延迟要求的场合。
目前,Buffer的状态,都是通过各个状态的Buffer的量来表示状态,对应的关系如下:
Buffer状态 | mShared | mDequeueCount | mQueueCount | mAcquireCount |
---|---|---|---|---|
FREE | false | 0 | 0 | 0 |
DEQUEUED | false | 1 | 0 | 0 |
QUEUED | false | 0 | 1 | 0 |
ACQUIRED | false | 0 | 0 | 1 |
SHARED | true | any | any | any |
Buffer的状态在代码中用BufferState描述,BufferState的定义如下:
* frameworks/native/libs/gui/include/gui/BufferSlot.h
struct BufferState {
BufferState()
: mDequeueCount(0),
mQueueCount(0),
mAcquireCount(0),
mShared(false) {
}
uint32_t mDequeueCount;
uint32_t mQueueCount;
uint32_t mAcquireCount;
bool mShared;
... ...
};
前面讲解dequeueBuffer和queueBuffer流程时,BufferQueue有很多个队列,我们再来看一下BufferQueue中,几个队列间的关系。
BufferQueueCore中的定义如下:
* frameworks/native/libs/gui/include/gui/BufferQueueCore.h
class BufferQueueCore : public virtual RefBase {
... ...
typedef Vector<BufferItem> Fifo;
... ...
// mSlots is an array of buffer slots that must be mirrored on the producer
// side. This allows buffer ownership to be transferred between the producer
// and consumer without sending a GraphicBuffer over Binder. The entire
// array is initialized to NULL at construction time, and buffers are
// allocated for a slot when requestBuffer is called with that slot's index.
BufferQueueDefs::SlotsType mSlots;
// mQueue is a FIFO of queued buffers used in synchronous mode.
Fifo mQueue;
// mFreeSlots contains all of the slots which are FREE and do not currently
// have a buffer attached.
std::set<int> mFreeSlots;
// mFreeBuffers contains all of the slots which are FREE and currently have
// a buffer attached.
std::list<int> mFreeBuffers;
// mUnusedSlots contains all slots that are currently unused. They should be
// free and not have a buffer attached.
std::list<int> mUnusedSlots;
// mActiveBuffers contains all slots which have a non-FREE buffer attached.
std::set<int> mActiveBuffers;
-
mSlots
mSlots 是Buffer序号的一个