文章都是通过阅读源码分析出来的,还在不断完善与改进中,其中难免有些地方理解得不对,欢迎大家批评指正。
转载请注明:From LXS. http://blog.csdn.net/uiop78uiop78/
GUI系统之SurfaceFlinger章节目录:
blog.csdn.net/uiop78uiop78/article/details/8954508
1.1.1 BufferQueue中的缓冲区分配
我们知道,BufferQueue中有一个mSlots数组用于管理其内的各缓冲区,最大容量为32。从它的声明方式来看,这个mSlots在程序一开始就静态分配了32个BufferSlot大小的空间。不过这并不代表缓冲区也是一次性静态分配的,恰恰相反,从BufferSlot的内部变量指针mGraphicBuffer可以看出,缓冲区的空间分配应当是动态的(从下面的注释也能看出一些端倪):
// mGraphicBuffer points to the buffer allocated for this slot or isNULL if no buffer has been allocated.
sp<GraphicBuffer> mGraphicBuffer;
现在的问题就转移为,在什么情况下会给一个Slot实际的分配空间呢?
首先能想到的就是dequeueBuffer。理由如下:
Ø 缓冲区的空间分配应该既要满足使用者的需求,又要防止浪费。后面这一点mSlots已经满足了,因为它并没有采取一开始就静态预分配的方式
Ø 既然Producer对buffer的操作是“主动”的,那么就意味着它是整个需求的发起者。换句话说,只要它没有dequeueBuffer,或者dequeueBuffer时能获取到可用的缓冲区,那当然就没有必要再重新分配空间了
来详细分析下这个函数:
/*frameworks/native/libs/gui/BufferQueue.cpp*/
status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w,uint32_t h, uint32_t format, uint32_t usage) {…
status_t returnFlags(OK);
…
{ // Scope for the lock
Mutex::Autolocklock(mMutex); /*这里采用了自动锁,所以上面需要加个“{”,这样当lock变量生
命期结束后锁也就自动释放了。这种写法非常常见*/
…
int found = -1;
int foundSync = -1;
int dequeuedCount = 0;
bool tryAgain = true;
while (tryAgain) {/*Step1. 循环查找符合要求的slot*/
…
found = INVALID_BUFFER_SLOT;//初始值
foundSync =INVALID_BUFFER_SLOT;
dequeuedCount = 0;
for (int i = 0; i< mBufferCount; i++) {
const intstate = mSlots[i].mBufferState;
/*Step2.统计dequeued buffer数量,后面会用到*/
if (state ==BufferSlot::DEQUEUED) {
dequeuedCount++;
}
if (false) {
//肯定不会走这边
} else {
if (state== BufferSlot::FREE) { /*Step3.寻找符合要求的Slot*/
boolisOlder = mSlots[i].mFrameNumber <mSlots[found].mFrameNumber;
if(found < 0 || isOlder) {
foundSync = i;
found = i; //找到符合要求的Slot
}
}// if