本文基于 aosp android-14.0.0_r15 版本讲解。
# 1. 引子
示例代码接下来就要 new 一个 BLASTBufferQueue 对象。
mBlastBufferQueue = new BLASTBufferQueue("DemoBLASTBufferQueue", surfaceControl,
resolution.getWidth(), resolution.getHeight(),
PIXEL_FORMAT_RGBA_8888);
2
3
在分析之前我们可以将 BLASTBufferQueue 作为一个黑盒,仅关注整体流程:
- App 调用 dequebuffer 向 BLASTBufferQueue 申请一个 buffer
- App 拿到 buffer 后开始渲染,所谓渲染就是把显示指令转换为内存数据写入 buffer
- 渲染完成后,将写入数据的 buffer 通过事务的方式提交给 SurfaceFligner,SurfaceFlinger 负责 buffer 的合成显示。
了解了整体流程,我们再看代码就能有整体上的把握了。
# 2. 构造函数实现分析
BLASTBufferQueue 是一个非常重要的类,它是帧缓存的大管家。其内部通过 BufferQueueCore BBQBufferQueueProducer BufferQueueConsumer 等类辅助管理帧缓存。
接下来,我们就一步步分析其内部实现。
看下构造函数的实现:
// /frameworks/native/libs/gui/BLASTBufferQueue.cpp
BLASTBufferQueue::BLASTBufferQueue(const std::string& name, const sp<SurfaceControl>& surface,
int width, int height, int32_t format)
: BLASTBufferQueue(name) {
update(surface, width, height, format);
}
2
3
4
5
6
BLASTBufferQueue 构造函数中会先调用另一个构造函数重载,然后调用 update 函数,我们先看构造函数的实现:
// /frameworks/native/libs/gui/include/gui/BLASTBufferQueue.h
sp<IGraphicBufferConsumer> mConsumer;
sp<IGraphicBufferProducer> mProducer;
sp<BLASTBufferItemConsumer> mBufferItemConsumer;
// /frameworks/native/libs/gui/BLASTBufferQueue.cpp
BLASTBufferQueue::BLASTBufferQueue(const std::string& name, bool updateDestinationFrame)
: mSurfaceControl(nullptr),
mSize(1, 1),
mRequestedSize(mSize),
mFormat(PIXEL_FORMAT_RGBA_8888),
mTransactionReadyCallback(nullptr),
mSyncTransaction(nullptr),
mUpdateDestinationFrame(updateDestinationFrame) {
// new 一个 BufferQueueCore 对象
// 初始化 mConsumer 和 mProducer 成员
createBufferQueue(&mProducer, &mConsumer);
// since the adapter is in the client process, set dequeue timeout
// explicitly so that dequeueBuffer will block
mProducer->setDequeueTimeout(std::numeric_limits<int64_t>::max());
// safe default, most producers are expected to override this
// 设置 buffer 数量
mProducer->setMaxDequeuedBufferCount(2);
// 初始化 mBufferItemConsumer 成员
mBufferItemConsumer = new BLASTBufferItemConsumer(mConsumer,
GraphicBuffer::USAGE_HW_COMPOSER |
GraphicBuffer::USAGE_HW_TEXTURE,
1, false, this);
static std::atomic<uint32_t> nextId = 0;
mProducerId = nextId++;
mName = name + "#" + std::to_string(mProducerId);
auto consumerName = mName + "(BLAST Consumer)" + std::to_string(mProducerId);
mQueuedBufferTrace = "QueuedBuffer - " + mName + "BLAST#" + std::to_string(mProducerId);
mBufferItemConsumer->setName(String8(consumerName.c_str()));
// 这里注册了 listener 回调,this 就是 BLASTBufferQueue
mBufferItemConsumer->setFrameAvailableListener(this);
ComposerServiceAIDL::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers);
// ?
mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBuffers);
mCurrentMaxAcquiredBufferCount = mMaxAcquiredBuffers;
mNumAcquired = 0;
mNumFrameAvailable = 0;
TransactionCompletedListener::getInstance()->addQueueStallListener(
[&](const std::string& reason) {
std::function<void(const std::string&)> callbackCopy;
{
std::unique_lock _lock{mMutex};
callbackCopy = mTransactionHangCallback;
}
if (callbackCopy) callbackCopy(reason);
},
this);
BQA_LOGV("BLASTBufferQueue created");
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
构造函数中核心主要两点:
- createBufferQueue 函数中,new 一个 BufferQueueCore 对象,初始化 mConsumer 和 mProducer 成员
- 先 new 一个 BLASTBufferItemConsumer 对象,接着再调用一堆函数配置这个对象
接下来我们详细分析这两步的实现。
# 2.1 BufferQueueCore 的初始化
我们先看 createBufferQueue 函数的实现:
// /frameworks/native/libs/gui/BLASTBufferQueue.cpp
void BLASTBufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer) {
LOG_ALWAYS_FATAL_IF(outProducer == nullptr, "BLASTBufferQueue: outProducer must not be NULL");
LOG_ALWAYS_FATAL_IF(outConsumer == nullptr, "BLASTBufferQueue: outConsumer must not be NULL");
// 创建 BufferQueue 核心类,主要负责缓冲区的调度工作
sp<BufferQueueCore> core(new BufferQueueCore());
LOG_ALWAYS_FATAL_IF(core == nullptr, "BLASTBufferQueue: failed to create BufferQueueCore");
// 创建生产者,用于串联图形生产者流程
sp<IGraphicBufferProducer> producer(new BBQBufferQueueProducer(core, this));
LOG_ALWAYS_FATAL_IF(producer == nullptr,
"BLASTBufferQueue: failed to create BBQBufferQueueProducer");
// 创建消费者,用于串联图形消费者流程
sp<BufferQueueConsumer> consumer(new BufferQueueConsumer(core));
consumer->setAllowExtraAcquire(true);
LOG_ALWAYS_FATAL_IF(consumer == nullptr,
"BLASTBufferQueue: failed to create BufferQueueConsumer");
*outProducer = producer;
*outConsumer = consumer;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
核心的主要三点:
- new 一个 BufferQueueCore 对象
- new 一个 BBQBufferQueueProducer 对象赋值给 producer
- new BufferQueueConsumer 对象赋值给 consumer
一个个看:
BufferQueueCore 的构造函数如下:
BufferQueueCore::BufferQueueCore()
: mMutex(),
mIsAbandoned(false),
mConsumerControlledByApp(false),
mConsumerName(getUniqueName()),
mConsumerListener(),
mConsumerUsageBits(0),
mConsumerIsProtected(false),
mConnectedApi(NO_CONNECTED_API),
mLinkedToDeath(),
mConnectedProducerListener(),
mBufferReleasedCbEnabled(false),
mSlots(),
mQueue(),
mFreeSlots(),
mFreeBuffers(),
mUnusedSlots(),
mActiveBuffers(),
mDequeueCondition(),
mDequeueBufferCannotBlock(false),
mQueueBufferCanDrop(false),
mLegacyBufferDrop(true),
mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
mDefaultWidth(1),
mDefaultHeight(1),
mDefaultBufferDataSpace(HAL_DATASPACE_UNKNOWN),
mMaxBufferCount(BufferQueueDefs::NUM_BUFFER_SLOTS),
mMaxAcquiredBufferCount(1),
mMaxDequeuedBufferCount(1),
mBufferHasBeenQueued(false),
mFrameCounter(0),
mTransformHint(0),
mIsAllocating(false),
mIsAllocatingCondition(),
mAllowAllocation(true),
mBufferAge(0),
mGenerationNumber(0),
mAsyncMode(false),
mSharedBufferMode(false),
mAutoRefresh(false),
mSharedBufferSlot(INVALID_BUFFER_SLOT),
mSharedBufferCache(Rect::INVALID_RECT, 0, NATIVE_WINDOW_SCALING_MODE_FREEZE,
HAL_DATASPACE_UNKNOWN),
mLastQueuedSlot(INVALID_BUFFER_SLOT),
mUniqueId(getUniqueId()),
mAutoPrerotation(false),
mTransformHintInUse(0) {
int numStartingBuffers = getMaxBufferCountLocked();
for (int s = 0; s < numStartingBuffers; s++) {
mFreeSlots.insert(s);
}
for (int s = numStartingBuffers; s < BufferQueueDefs::NUM_BUFFER_SLOTS;
s++) {
mUnusedSlots.push_front(s);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
BufferQueueCore 的构造函数就是给一堆成员变量做初始化,其中比较重要的成员有:
BufferQueueDefs::SlotsType mSlots;
Fifo mQueue;
std::set<int> mFreeSlots;
std::list<int> mFreeBuffers;
std::list<int> mUnusedSlots;
std::set<int> mActiveBuffers;
2
3
4
5
6
接下来一个个看:
mSlots 是一个 BufferSlot 数组,默认大小是 64
// typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS];
// static constexpr int NUM_BUFFER_SLOTS = 64;
BufferQueueDefs::SlotsType mSlots;
2
3
问题来了,BufferSLot 是什么?
BufferSLot 的定义如下:
struct BufferSlot {
BufferSlot()
: mGraphicBuffer(nullptr),
mEglDisplay(EGL_NO_DISPLAY),
mBufferState(),
mRequestBufferCalled(false),
mFrameNumber(0),
mEglFence(EGL_NO_SYNC_KHR),
mFence(Fence::NO_FENCE),
mAcquireCalled(false),
mNeedsReallocation(false) {
}
// mGraphicBuffer points to the buffer allocated for this slot or is NULL
// if no buffer has been allocated.
sp<GraphicBuffer> mGraphicBuffer;
// mEglDisplay is the EGLDisplay used to create EGLSyncKHR objects.
EGLDisplay mEglDisplay;
// mBufferState is the current state of this buffer slot.
BufferState mBufferState;
// mRequestBufferCalled is used for validating that the producer did
// call requestBuffer() when told to do so. Technically this is not
// needed but useful for debugging and catching producer bugs.
bool mRequestBufferCalled;
// mFrameNumber is the number of the queued frame for this slot. This
// is used to dequeue buffers in LRU order (useful because buffers
// may be released before their release fence is signaled).
uint64_t mFrameNumber;
// 用于表示 GPU 是否已经完成了与图形缓冲区相关的渲染操作
// mEglFence is the EGL sync object that must signal before the buffer
// associated with this buffer slot may be dequeued. It is initialized
// to EGL_NO_SYNC_KHR when the buffer is created and may be set to a
// new sync object in releaseBuffer. (This is deprecated in favor of
// mFence, below.)
EGLSyncKHR mEglFence;
// 用于 SurfaceFlinger 内部的图形合成和显示操作
// mFence is a fence which will signal when work initiated by the
// previous owner of the buffer is finished. When the buffer is FREE,
// the fence indicates when the consumer has finished reading
// from the buffer, or when the producer has finished writing if it
// called cancelBuffer after queueing some writes. When the buffer is
// QUEUED, it indicates when the producer has finished filling the
// buffer. When the buffer is DEQUEUED or ACQUIRED, the fence has been
// passed to the consumer or producer along with ownership of the
// buffer, and mFence is set to NO_FENCE.
sp<Fence> mFence;
// Indicates whether this buffer has been seen by a consumer yet
bool mAcquireCalled;
// Indicates whether the buffer was re-allocated without notifying the
// producer. If so, it needs to set the BUFFER_NEEDS_REALLOCATION flag when
// dequeued to prevent the producer from using a stale cached buffer.
bool mNeedsReallocation;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
BufferSlot 可以认为是一个存放帧缓存及其相关信息的地方。
我们主要关注 BufferSlot 的几个重要成员:
sp<GraphicBuffer> mGraphicBuffer
:指向当前 BufferSlot 相关联的 buffer,如果没有 buffer,就是 nullBufferState mBufferState
:当前 Slot 的状态bool mNeedsReallocation;
:是否需要重新分配这个buffer;sp<Fence> mFence
,用于 SurfaceFlinger 内部的图形合成和显示操作EGLSyncKHR mEglFence
,用于表示 GPU 是否已经完成了与图形缓冲区相关的渲染操作
其中 GraphicBuffer 代表一块显示内存,其定义如下:
// /frameworks/native/libs/ui/include/ui/GraphicBuffer.h
class GraphicBuffer
: public ANativeObjectBase<ANativeWindowBuffer, GraphicBuffer, RefBase>,
public Flattenable<GraphicBuffer>
{
// ......
}
2
3
4
5
6
7
8
GraphicBuffer 继承自 Flattenable<GraphicBuffer>
,说明 GraphicBuffer 对象可以通过 Binder 跨进程传输。
GraphicBuffer 继承自 ANativeObjectBase<ANativeWindowBuffer, GraphicBuffer, RefBase>
,它是一个模板类,其定义如下:
template <typename NATIVE_TYPE, typename TYPE, typename REF,
typename NATIVE_BASE = android_native_base_t>
class ANativeObjectBase : public NATIVE_TYPE, public REF
{
// ......
}
2
3
4
5
6
带入泛型后,ANativeObjectBase 继承 ANativeWindowBuffer 和 RefBase
RefBase 可以让 GraphicBuffer 支持引用计数。
ANativeWindowBuffer 的定义如下:
// /frameworks/native/libs/nativebase/include/nativebase/nativebase.h
typedef struct ANativeWindowBuffer
{
#ifdef __cplusplus
ANativeWindowBuffer() {
common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
common.version = sizeof(ANativeWindowBuffer);
memset(common.reserved, 0, sizeof(common.reserved));
}
// Implement the methods that sp<ANativeWindowBuffer> expects so that it
// can be used to automatically refcount ANativeWindowBuffer's.
void incStrong(const void* /*id*/) const {
common.incRef(const_cast<android_native_base_t*>(&common));
}
void decStrong(const void* /*id*/) const {
common.decRef(const_cast<android_native_base_t*>(&common));
}
#endif
struct android_native_base_t common;
int width;
int height;
int stride;
int format;
int usage_deprecated;
uintptr_t layerCount;
void* reserved[1];
const native_handle_t* handle;
uint64_t usage;
// we needed extra space for storing the 64-bits usage flags
// the number of slots to use from reserved_proc depends on the
// architecture.
void* reserved_proc[8 - (sizeof(uint64_t) / sizeof(void*))];
} ANativeWindowBuffer_t;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
ANativeWindowBuffer 用于描述一块 Native Buffer,核心成员是 native_handle_t,其定义如下:
typedef struct native_handle
{
int version; /* sizeof(native_handle_t) */
int numFds; /* number of file-descriptors at &data[0] */
int numInts; /* number of ints at &data[numFds] */
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wzero-length-array"
#endif
int data[0]; /* numFds + numInts ints */
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
} native_handle_t;
2
3
4
5
6
7
8
9
10
11
12
13
14
最后一个指针 data 中指向的就是 fd,这些 fd 就是 buffer 的句柄或者说索引。
可以看出实际在进程间传递的是内存的 fd,而不是 buffer 本身,这个和前文的解析也是一致的。
BufferState 用于描述一个 BufferSlot 的状态,其定义如下:
// /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;
inline bool isFree() const {
return !isAcquired() && !isDequeued() && !isQueued();
}
inline bool isDequeued() const {
return mDequeueCount > 0;
}
inline bool isQueued() const {
return mQueueCount > 0;
}
inline bool isAcquired() const {
return mAcquireCount > 0;
}
inline bool isShared() const {
return mShared;
}
inline void reset() {
*this = BufferState();
}
const char* string() const;
inline void dequeue() {
mDequeueCount++;
}
inline void detachProducer() {
if (mDequeueCount > 0) {
mDequeueCount--;
}
}
inline void attachProducer() {
mDequeueCount++;
}
inline void queue() {
if (mDequeueCount > 0) {
mDequeueCount--;
}
mQueueCount++;
}
inline void cancel() {
if (mDequeueCount > 0) {
mDequeueCount--;
}
}
inline void freeQueued() {
if (mQueueCount > 0) {
mQueueCount--;
}
}
inline void acquire() {
if (mQueueCount > 0) {
mQueueCount--;
}
mAcquireCount++;
}
inline void acquireNotInQueue() {
mAcquireCount++;
}
inline void release() {
if (mAcquireCount > 0) {
mAcquireCount--;
}
}
inline void detachConsumer() {
if (mAcquireCount > 0) {
mAcquireCount--;
}
}
inline void attachConsumer() {
mAcquireCount++;
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
通过四个变量来描述 Slot 的状态,一共有 5 种情况:
// | 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 |
2
3
4
5
6
7
也就是说一个 BufferSlot 可以有 5 种状态:
- FREE
- DEQUEUED
- QUEUED
- ACQUIRED
- SHARED
这几种状态的转换逻辑如下:
- 一个 BufferSlot 对象一开始是 FREE 状态,
- 生产者调用 dequeueBuffer 获取 slot 后就进入 DEQUEUED 状态
- 生产者使用完 buffer 调用 queueBuffer 后把 buffer 放到列表里就进入了 QUEUED 状态
- 消费者使用 acquireBuffer 获取 Buffer 后,就进入ACQUIRED状态
- 消费者使用 releaseBuffer 把 Buffer 释放后,就进入FREE状态
SHARED 状态比较特殊,这里有一个共享 Buffer 模式,看代码实现逻辑就是一直共享复用一个 buffer,这种情况这个 buffer 就是 SHARED 状态,默认情况是不使用这种模式的,一般不用关注。
这些类的关系如下图所示:
接着看 BufferQueueCore 的另一个成员 Fifo mQueue
.
// typedef Vector<BufferItem> Fifo;
Fifo mQueue
2
mQueue 是 BufferItem 类型的 Vector,从名字 Fifo 可以看出,它应该是一个队列,即内部元素先进先出。
BufferItem 的定义如下:
// /frameworks/native/libs/gui/include/gui/BufferItem.h
class BufferItem : public Flattenable<BufferItem> {
friend class Flattenable<BufferItem>;
size_t getPodSize() const;
size_t getFlattenedSize() const;
size_t getFdCount() const;
status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count);
public:
// The default value of mBuf, used to indicate this doesn't correspond to a slot.
enum { INVALID_BUFFER_SLOT = -1 };
BufferItem();
~BufferItem();
BufferItem(const BufferItem&) = default;
BufferItem& operator=(const BufferItem&) = default;
static const char* scalingModeName(uint32_t scalingMode);
// mGraphicBuffer points to the buffer allocated for this slot, or is NULL
// if the buffer in this slot has been acquired in the past (see
// BufferSlot.mAcquireCalled).
sp<GraphicBuffer> mGraphicBuffer;
// mFence is a fence that will signal when the buffer is idle.
sp<Fence> mFence;
// The std::shared_ptr<FenceTime> wrapper around mFence.
std::shared_ptr<FenceTime> mFenceTime{FenceTime::NO_FENCE};
// mCrop is the current crop rectangle for this buffer slot.
Rect mCrop;
// mTransform is the current transform flags for this buffer slot.
// refer to NATIVE_WINDOW_TRANSFORM_* in <window.h>
uint32_t mTransform;
// mScalingMode is the current scaling mode for this buffer slot.
// refer to NATIVE_WINDOW_SCALING_* in <window.h>
uint32_t mScalingMode;
// mTimestamp is the current timestamp for this buffer slot. This gets
// to set by queueBuffer each time this slot is queued. This value
// is guaranteed to be monotonically increasing for each newly
// acquired buffer.
int64_t mTimestamp;
// mIsAutoTimestamp indicates whether mTimestamp was generated
// automatically when the buffer was queued.
bool mIsAutoTimestamp;
// mDataSpace is the current dataSpace value for this buffer slot. This gets
// set by queueBuffer each time this slot is queued. The meaning of the
// dataSpace is format-dependent.
android_dataspace mDataSpace;
// mHdrMetadata is the HDR metadata associated with this buffer slot.
HdrMetadata mHdrMetadata;
// mFrameNumber is the number of the queued frame for this slot.
uint64_t mFrameNumber;
// mSlot is the slot index of this buffer (default INVALID_BUFFER_SLOT).
int mSlot;
// mIsDroppable whether this buffer was queued with the
// property that it can be replaced by a new buffer for the purpose of
// making sure dequeueBuffer() won't block.
// i.e.: was the BufferQueue in "mDequeueBufferCannotBlock" when this buffer
// was queued.
bool mIsDroppable;
// Indicates whether this buffer has been seen by a consumer yet
bool mAcquireCalled;
// Indicates this buffer must be transformed by the inverse transform of the screen
// it is displayed onto. This is applied after mTransform.
bool mTransformToDisplayInverse;
// Describes the portion of the surface that has been modified since the
// previous frame
Region mSurfaceDamage;
// Indicates that the consumer should acquire the next frame as soon as it
// can and not wait for a frame to become available. This is only relevant
// in shared buffer mode.
bool mAutoRefresh;
// Indicates that this buffer was queued by the producer. When in shared
// buffer mode acquire() can return a BufferItem that wasn't in the queue.
bool mQueuedBuffer;
// Indicates that this BufferItem contains a stale buffer which has already
// been released by the BufferQueue.
bool mIsStale;
// Indicates the API (NATIVE_WINDOW_API_xxx) that queues the buffer.
int mApi;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
BufferItem 和 BufferSlot 比较类似,也是帧缓存及其相关信息的集合,它的作用是什么呢?
当 App 想要显示一个图像时,就会从 mSlots
中取出一个 BufferSlot,然后把需要显示的内容写入到 BufferSlot 中的 GraphicBuffer 成员中,接着再把 BufferSlot 转换成 BufferItem 插入 Fifo mQueue
队列中。接着再从队列中取出 BufferItem,转换为 BufferSlot,获取到 Buffer,然后把这个 Buffer 提交给 sf 显示。可以看出 BufferItem 就是一个中间状态的角色,这就它的作用。
我们接着看 BufferQueueCore 的另外一个成员 mFreeSlots:
std::set<int> mFreeSlots;
mFreeSlots 是一个 int 类型的 set,这里的 int 值实际是 mSlots 数组中的索引,代表了一个 BufferSlot 对象。
mFreeSlots 中保存的是没有绑定 GraphicBuffer 且状态为 FREE 的 BufferSlot 集合;
接着看 BufferQueueCore 的另外一个成员 mFreeBuffers:
std::list<int> mFreeBuffers;
mFreeBuffers 是一个 int 类型的 set,这里的 int 值实际是 mSlots 数组中的索引,代表了一个 BufferSlot 对象。 mFreeSlots 中保存的是绑定了 GraphicBuffer 且状态为 FREE 的 BufferSlot 集合;
std::list<int> mUnusedSlots;
mUnusedSlots 表示未参与使用的 slot 集合,由 mMaxBufferCount 决定
std::set<int> mActiveBuffers;
mActiveBuffers 表示绑定了 GraphicBuffer 且状态为非 FREE 的 BufferSlot 集合
另外再强调一下:
mFreeSlots/mFreeBuffers/mUnusedSlots/mActiveBuffers 存储的都是 int 类型的 index,根据这个 index 去 mSlots 中获取对应的 BufferSlot 及 GraphicBuffer。 之所以划分出这么多不同的数组,都是为了给 BufferSlot 分类,以便获取 GraphicBuffer 时更加高效。
这些成员的组成如下图所示:
图片来自:https://blog.csdn.net/hexiaolong2009/article/details/99225637
# 2.2 BBQBufferQueueProducer 与 BufferQueueConsumer 的初始化
完成了 BufferQueueCore 的初始化,接着就是 new BBQBufferQueueProducer。
BBQBufferQueueProducer 的构造函数如下:
class BBQBufferQueueProducer : public BufferQueueProducer {
public:
BBQBufferQueueProducer(const sp<BufferQueueCore>& core, wp<BLASTBufferQueue> bbq)
: BufferQueueProducer(core, false /* consumerIsSurfaceFlinger*/),
mBLASTBufferQueue(std::move(bbq)) {}
// ......
private:
const wp<BLASTBufferQueue> mBLASTBufferQueue;
};
2
3
4
5
6
7
8
9
10
11
调用父类的构造函数,将参数中传入的 bbq 保存到成员变量 mBLASTBufferQueue 中。
父类 BufferQueueProducer 构造函数如下:
BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core,
bool consumerIsSurfaceFlinger) :
mCore(core),
mSlots(core->mSlots),
mConsumerName(),
mStickyTransform(0),
mConsumerIsSurfaceFlinger(consumerIsSurfaceFlinger),
mLastQueueBufferFence(Fence::NO_FENCE),
mLastQueuedTransform(0),
mCallbackMutex(),
mNextCallbackTicket(0),
mCurrentCallbackTicket(0),
mCallbackCondition(),
mDequeueTimeout(-1),
mDequeueWaitingForAllocation(false) {}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
主要就是内部成员的初始化。
BufferQueueConsumer 的构造函数实现如下:
// /frameworks/native/libs/gui/include/gui/BufferQueueConsumer.h
class BufferQueueConsumer : public BnGraphicBufferConsumer {
//......
private:
sp<BufferQueueCore> mCore;
// This references mCore->mSlots. Lock mCore->mMutex while accessing.
BufferQueueDefs::SlotsType& mSlots;
// This is a cached copy of the name stored in the BufferQueueCore.
// It's updated during setConsumerName.
String8 mConsumerName;
}
// /frameworks/native/libs/gui/BufferQueueConsumer.cpp
BufferQueueConsumer::BufferQueueConsumer(const sp<BufferQueueCore>& core) :
mCore(core),
mSlots(core->mSlots),
mConsumerName() {}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
就是在构造函数中使用传入的参数初始化了 mCore mSlots 成员。
# 2.3 BLASTBufferItemConsumer 的初始化与配置
接着看 new BLASTBufferItemConsumer 的过程。
// 参数 mConsumer 类型是 BufferQueueConsumer
mBufferItemConsumer = new BLASTBufferItemConsumer(mConsumer,
GraphicBuffer::USAGE_HW_COMPOSER |
GraphicBuffer::USAGE_HW_TEXTURE,
1, false, this);
2
3
4
5
BLASTBufferItemConsumer 的构造函数实现如下:
class BLASTBufferItemConsumer : public BufferItemConsumer {
public:
BLASTBufferItemConsumer(const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
int bufferCount, bool controlledByApp, wp<BLASTBufferQueue> bbq)
: BufferItemConsumer(consumer, consumerUsage, bufferCount, controlledByApp),
mBLASTBufferQueue(std::move(bbq)),
mCurrentlyConnected(false),
mPreviouslyConnected(false) {}
// ......
};
2
3
4
5
6
7
8
9
10
11
这里会调用到父类 BufferItemConsumer 的构造函数:
BufferItemConsumer::BufferItemConsumer(
const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
int bufferCount, bool controlledByApp) :
ConsumerBase(consumer, controlledByApp)
{
status_t err = mConsumer->setConsumerUsageBits(consumerUsage);
LOG_ALWAYS_FATAL_IF(err != OK,
"Failed to set consumer usage bits to %#" PRIx64, consumerUsage);
if (bufferCount != DEFAULT_MAX_BUFFERS) {
err = mConsumer->setMaxAcquiredBufferCount(bufferCount);
LOG_ALWAYS_FATAL_IF(err != OK,
"Failed to set max acquired buffer count to %d", bufferCount);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
接着调用父类 ConsumerBase 的构造函数
// bufferQueue 的类型是 BufferQueueConsumer
ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
mAbandoned(false),
mConsumer(bufferQueue),
mPrevFinalReleaseFence(Fence::NO_FENCE) {
// Choose a name using the PID and a process-unique ID.
mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
// Note that we can't create an sp<...>(this) in a ctor that will not keep a
// reference once the ctor ends, as that would cause the refcount of 'this'
// dropping to 0 at the end of the ctor. Since all we need is a wp<...>
// that's what we create.
// listener 就是 BLASTBufferItemConsumer 自己
wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
// 重点关注
status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
if (err != NO_ERROR) {
CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
strerror(-err), err);
} else {
mConsumer->setConsumerName(mName);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
这里会把 BLASTBufferItemConsumer 对象转换为一个 IConsumerListener 指针,接着传递给 consumerConnect 函数,consumerConnect 函数的实现如下:
virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,
bool controlledByApp) {
return connect(consumer, controlledByApp);
}
2
3
4
接着调用 connect 函数:
status_t BufferQueueConsumer::connect(
const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
ATRACE_CALL();
if (consumerListener == nullptr) {
BQ_LOGE("connect: consumerListener may not be NULL");
return BAD_VALUE;
}
BQ_LOGV("connect: controlledByApp=%s",
controlledByApp ? "true" : "false");
std::lock_guard<std::mutex> lock(mCore->mMutex);
if (mCore->mIsAbandoned) {
BQ_LOGE("connect: BufferQueue has been abandoned");
return NO_INIT;
}
// 这里的 mConsumerListener 实际就是 BLASTBufferItemConsumer 的包装
mCore->mConsumerListener = consumerListener;
mCore->mConsumerControlledByApp = controlledByApp;
return NO_ERROR;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
mCore->mConsumerListener 的值其实就是之前 new 的 BLASTBufferItemConsumer 对象的包装。这点很重要,后续的代码会调用到这个回调。
小结一下:
new BLASTBufferQueue
createBufferQueue
new BufferQueueCore
new BBQBufferQueueProducer
new BufferQueueConsumer
new BLASTBufferItemConsumer
mCore->mConsumerListener = consumerListener;
2
3
4
5
6
7
- new 了一个 BLASTBufferQueue 对象
- new 了一个 BufferQueueCore 对象
- new 了一个 BBQBufferQueueProducer 对象
- new 了一个 BufferQueueConsumer 对象
- new 了一个 BLASTBufferItemConsumer 对,将 BufferQueueCore 的 mConsumerListener 成员赋值为自己。
这些类的相互关系如下图所示:
到目前为止了,就是把这一堆对象给准备好了,等着后面来操作。
# 2.4 update 函数实现
BLASTBufferQueue 构造函数中接着再调用 update 函数:
void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height,
int32_t format) {
LOG_ALWAYS_FATAL_IF(surface == nullptr, "BLASTBufferQueue: mSurfaceControl must not be NULL");
std::lock_guard _lock{mMutex};
if (mFormat != format) {
mFormat = format;
mBufferItemConsumer->setDefaultBufferFormat(convertBufferFormat(format));
}
const bool surfaceControlChanged = !SurfaceControl::isSameSurface(mSurfaceControl, surface);
if (surfaceControlChanged && mSurfaceControl != nullptr) {
BQA_LOGD("Updating SurfaceControl without recreating BBQ");
}
bool applyTransaction = false;
// Always update the native object even though they might have the same layer handle, so we can
// get the updated transform hint from WM.
mSurfaceControl = surface;
SurfaceComposerClient::Transaction t;
if (surfaceControlChanged) {
t.setFlags(mSurfaceControl, layer_state_t::eEnableBackpressure,
layer_state_t::eEnableBackpressure);
applyTransaction = true;
}
mTransformHint = mSurfaceControl->getTransformHint();
mBufferItemConsumer->setTransformHint(mTransformHint);
BQA_LOGV("update width=%d height=%d format=%d mTransformHint=%d", width, height, format,
mTransformHint);
ui::Size newSize(width, height);
if (mRequestedSize != newSize) {
mRequestedSize.set(newSize);
mBufferItemConsumer->setDefaultBufferSize(mRequestedSize.width, mRequestedSize.height);
if (mLastBufferInfo.scalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
// If the buffer supports scaling, update the frame immediately since the client may
// want to scale the existing buffer to the new size.
mSize = mRequestedSize;
if (mUpdateDestinationFrame) {
t.setDestinationFrame(mSurfaceControl, Rect(newSize));
applyTransaction = true;
}
}
}
if (applyTransaction) {
// All transactions on our apply token are one-way. See comment on mAppliedLastTransaction
t.setApplyToken(mApplyToken).apply(false, true);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
update 主要是给 BLASTBufferQueue 的成员变量赋值。比较重要的是:
- mSurfaceControl 赋值为传入的 surface 参数
- 配置 mBufferItemConsumer
# 3. 总结
在 BLASTBufferQueue 初始化过程中,主要完成了以下工作:
- new 了一个 BufferQueueCore 对象,该对象内部有好几数据结构,用于管理帧缓存
- new 了一个 BBQBufferQueueProducer 对象,该对象用于从 BufferQueueCore 中取出一个 buffer,接着 app 就可以向 buffer 填充要显示的内容
- new 了 BufferQueueConsumer 对象,该对象用于从 BufferQueueCore 中取出一个 buffer,然后提交给 sf 显示