本节分析surface向Buffer Queue申请GraphicBuffer的过程(这里的surface是native的surface,不是java中的),在此过程中还会涉及利用Flattenable协议对对象序列化,binder传递文件描述符等概念。
surface的dequeueBuffer函数
Surface调用hook_dequeueBuffer()去申请图形缓冲区,
int Surface::hook_dequeueBuffer(ANativeWindow* window,
ANativeWindowBuffer** buffer, int* fenceFd) {
Surface* c = getSelf(window);
return c->dequeueBuffer(buffer, fenceFd);
}
其中,
typedef struct android_native_base_t
{
/* a magic value defined by the actual EGL native type */
int magic;
/* the sizeof() of the actual EGL native type */
int version;
void* reserved[4];
/* reference-counting interface */
void (*incRef)(struct android_native_base_t* base);
void (*decRef)(struct android_native_base_t* base);
} android_native_base_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] */
int data[0]; /* numFds + numInts ints */
} native_handle_t;
typedef const native_handle_t* buffer_handle_t;
typedef struct ANativeWindowBuffer
{
struct android_native_base_t common;
int width;
int height;
int stride;
int format;
int usage;
void* reserved[2];
//图形缓冲区
buffer_handle_t handle;
void* reserved_proc[8];
} ANativeWindowBuffer_t;
图形的buffer其实核心就是buffer_handle_t handle;
这个handle,上节分析过,就是通过mmap返回的fd,size,map到进程中内存的起始地址。
int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
ATRACE_CALL();
ALOGV("Surface::dequeueBuffer");
Mutex::Autolock lock(mMutex);
int buf = -1;
int reqW = mReqWidth ? mReqWidth : mUserWidth;
int reqH = mReqHeight ? mReqHeight : mUserHeight;
sp<Fence> fence;
//① 申请buffer
// mGraphicBufferProducer是BufferQueue的Bp对象
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, mSwapIntervalZero,
reqW, reqH, mReqFormat, mReqUsage);
if (result < 0) {
ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d)"
"failed: %d", mReqWidth, mReqHeight, mReqFormat, mReqUsage,
result);
return result;
}
sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
// this should never happen
ALOGE_IF(fence == NULL, "Surface::dequeueBuffer: received null Fence! buf=%d", buf);
if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
freeAllBuffers();
}
if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
//②
//由于申请的内存是在surfaceflinger进程中,BufferQueue中的图形缓冲区也是通过
// 匿名共享内存和binder传递描述符映射过去的,Surface通过调用
// requestBuffer将图形缓冲区映射到Surface所在进程
result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
if (result != NO_ERROR) {
ALOGE("dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: %d", result);
return result;
}
}
if (fence->isValid()) {
*fenceFd = fence->dup();
if (*fenceFd == -1) {
ALOGE("dequeueBuffer: error duping fence: %d", errno);
// dup() should never fail; something is badly wrong. Soldier on
// and hope for the best; the worst that should happen is some
// visible corruption that lasts until the next frame.
}
} else {
*fenceFd = -1;
}
//sp<>智能指针的get返回真是对象的指针
*buffer = gbuf.get();
return OK;
}
上面dequeueBuffer()主要包括2部分:
1. 向BufferQueue申请缓冲区;
2. 由于BufferQueue和Surface不在同一进程,需要用requestBuffer将映射在BufferQueue进程的图形缓冲区同时映射到surface所在的进程(匿名共享内存)。
向BufferQueue申请内存
在Surface类中,有个成员mSlots数组,即有32个BufferSlot。
//NUM_BUFFER_SLOTS为32
BufferSlot mSlots[NUM_BUFFER_SLOTS];
而BufferSlot结构如下,保存申请到的图形缓冲区。
struct BufferSlot {
//保存缓冲区
sp<GraphicBuffer> buffer;
Region dirtyRegion;
};
//int buf = -1;
// buf是个int值,是上面mSlots数组的下标
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, mSwapIntervalZero,
reqW, reqH, mReqFormat, mReqUsage);
mGraphicBufferProducer->dequeueBuffer
进而会去调用BpGraphicBufferProducer
的dequeueBuffer
函数,
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
{
virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async,
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
data.writeInt32(async);
data.writeInt32(w);
data.writeInt32(h);
data.writeInt32(format);
data.writeInt32(usage);
//通过BpBinder将要什么的buffer的相关参数保存到data,发送给BBinder
status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply);
if (result != NO_ERROR) {
return result;
}
//BBinder给BpBinder返回了一个int,并不是缓冲区的内存,例如前面介绍的handle啥的
*buf = reply.readInt32();
bool nonNull = reply.readInt32();
if (nonNull) {
*fence = new Fence();
reply.read(**fence);
}
result = reply.readInt32();
return result;
}
}
在client侧,也就是BpGraphicBufferProducer侧,通过DEQUEUE_BUFFER后核心只返回了一个*buf = reply.readInt32();
(先不管fence),也就是数组mSlots的下标。看来,BufferQueue中应该也有个和mSlots对应的数组,也是32个,一一对应,继续分析server侧,即Bn侧,
status_t BnGraphicBufferProducer::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
case DEQUEUE_BUFFER: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
bool async = data.readInt32();
uint32_t w = data.readInt32();
uint32_t h = data.readInt32();
uint32_t format = data.readInt32();
uint32_t usage = data.readInt32();
int buf;
sp<Fence> fence;
//调用BufferQueue的dequeueBuffer
//也返回一个int的buf
int result = dequeueBuffer(&buf, &fence, async, w, h, format, usage);
//将buf和fence写入parcel,通过binder传给client
reply->writeInt32(buf);
reply->writeInt32(fence != NULL);
if (fence != NULL) {
reply->write(*fence);
}
reply->writeInt32(result);
return NO_ERROR;
}
在BufferQueue中果然也有个mSlots数组,32个BufferSlot,
BufferSlot mSlots[NUM_BUFFER_SLOTS];
但是BufferSlot 结构不同于Surface中的,由于BufferQueue的核心职责就是管理图形缓冲区,需要记录每个缓冲区的状态(FREE,DEQUEUED,QUEUED,ACQUIRED)等,关于生产者消费者这里不细述了,
struct BufferSlot {
BufferSlot()
: mEglDisplay(EGL_NO_DISPLAY),
mBufferState(BufferSlot::FREE),
mRequestBufferCalled(false),
mFrameNumber(0),
mEglFence(EGL_NO_SYNC_KHR),
mAcquireCalled(false),
mNeedsCleanupOnRelease(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;
// BufferState represents the different states in which a buffer slot
// can be. All slots are initially FREE.
enum BufferState {
// FREE indicates that the buffer is available to be dequeued
// by the producer. The buffer may be in use by the consumer for
// a finite time, so the buffer must not be modified until the
// associated fence is signaled.
//
// The slot is "owned" by BufferQueue. It transitions to DEQUEUED
// when dequeueBuffer is called.
FREE = 0,
// DEQUEUED indicates that the buffer has been dequeued by the
// producer, but has not yet been queued or canceled. The
// producer may modify the buffer's contents as soon as the
// associated ready fence is signaled.
//
// The slot is "owned" by the producer. It can transition to
// QUEUED (via queueBuffer) or back to FREE (via cancelBuffer).
DEQUEUED = 1,
// QUEUED indicates that the buffer has been filled by the
// producer and queued for use by the consumer. The buffer
// contents may continue to be modified for a finite time, so
// the contents must not be accessed until the associated fence
// is signaled.
//
// The slot is "owned" by BufferQueue. It can transition to
// ACQUIRED (via acquireBuffer) or to FREE (if another buffer is
// queued in asynchronous mode).
QUEUED = 2,
// ACQUIRED indicates that the buffer has been acquired by the
// consumer. As with QUEUED, the contents must not be accessed
// by the consumer until the fence is signaled.
//
// The slot is "owned" by the consumer. It transitions to FREE
// when releaseBuffer is called.
ACQUIRED = 3
};
// 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;
// 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;
// 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 this buffer needs to be cleaned up by the
// consumer. This is set when a buffer in ACQUIRED state is freed.
// It causes releaseBuffer to return STALE_BUFFER_SLOT.
bool mNeedsCleanupOnRelease;
};
BufferQueue的dequeueBuffer函数,
status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, bool async,
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
ATRACE_CALL();
ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
status_t returnFlags(OK);
EGLDisplay dpy = EGL_NO_DISPLAY;
EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
{ // Scope for the lock
Mutex::Autolock lock(mMutex);
if (format == 0) {
format = mDefaultBufferFormat;
}
// turn on usage bits the consumer requested
usage |= mConsumerUsageBits;
int found = -1;
bool tryAgain = true;
while (tryAgain) {
if (mAbandoned) {
ST_LOGE("dequeueBuffer: BufferQueue has been abandoned!");
return NO_INIT;
}
const int maxBufferCount = getMaxBufferCountLocked(async);
if (async && mOverrideMaxBufferCount) {
// FIXME: some drivers are manually setting the buffer-count (which they
// shouldn't), so we do this extra test here to handle that case.
// This is TEMPORARY, until we get this fixed.
if (mOverrideMaxBufferCount < maxBufferCount) {
ST_LOGE("dequeueBuffer: async mode is invalid with buffercount override");
return BAD_VALUE;
}
}
// Free up any buffers that are in slots beyond the max buffer
// count.
for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {
assert(mSlots[i].mBufferState == BufferSlot::FREE);
if (mSlots[i].mGraphicBuffer != NULL) {
freeBufferLocked(i);
returnFlags |= IGraphicBufferProducer::RELEASE_ALL_BUFFERS;
}
}
// look for a free buffer to give to the client
found = INVALID_BUFFER_SLOT;
int dequeuedCount = 0;
int acquiredCount = 0;
//① 找mSlots中状态是FREE的,而且同时要选择mFrameNumber值最小的那个
for (int i = 0; i < maxBufferCount; i++) {
const int state = mSlots[i].mBufferState;
switch (state) {
case BufferSlot::DEQUEUED:
dequeuedCount++;
break;
case BufferSlot::ACQUIRED:
acquiredCount++;
break;
case BufferSlot::FREE:
/* We return the oldest of the free buffers to avoid
* stalling the producer if possible. This is because
* the consumer may still have pending reads of the
* buffers in flight.
*/
if ((found < 0) ||
mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
found = i;
}
break;
}
}
// clients are not allowed to dequeue more than one buffer
// if they didn't set a buffer count.
if (!mOverrideMaxBufferCount && dequeuedCount) {
ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
"setting the buffer count");
return -EINVAL;
}
// See whether a buffer has been queued since the last
// setBufferCount so we know whether to perform the min undequeued
// buffers check below.
if (mBufferHasBeenQueued) {
// make sure the client is not trying to dequeue more buffers
// than allowed.
const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1);
const int minUndequeuedCount = getMinUndequeuedBufferCount(async);
if (newUndequeuedCount < minUndequeuedCount) {
ST_LOGE("dequeueBuffer: min undequeued buffer count (%d) "
"exceeded (dequeued=%d undequeudCount=%d)",
minUndequeuedCount, dequeuedCount,
newUndequeuedCount);
return -EBUSY;
}
}
// If no buffer is found, wait for a buffer to be released or for
// the max buffer count to change.
tryAgain = found == INVALID_BUFFER_SLOT;
//② 如果所有的buffer都不是free的,则等待
if (tryAgain) {
// return an error if we're in "cannot block" mode (producer and consumer
// are controlled by the application) -- however, the consumer is allowed
// to acquire briefly an extra buffer (which could cause us to have to wait here)
// and that's okay because we know the wait will be brief (it happens
// if we dequeue a buffer while the consumer has acquired one but not released
// the old one yet -- for e.g.: see GLConsumer::updateTexImage()).
if (mDequeueBufferCannotBlock && (acquiredCount <= mMaxAcquiredBufferCount)) {
ST_LOGE("dequeueBuffer: would block! returning an error instead.");
return WOULD_BLOCK;
}
mDequeueCondition.wait(mMutex);
}
}
if (found == INVALID_BUFFER_SLOT) {
// This should not happen.
ST_LOGE("dequeueBuffer: no available buffer slots");
return -EBUSY;
}
const int buf = found;
*outBuf = found;
ATRACE_BUFFER_INDEX(buf);
const bool useDefaultSize = !w && !h;
if (useDefaultSize) {
// use the default size
w = mDefaultWidth;
h = mDefaultHeight;
}
//③ 将找到的buf所对应的状态修改为DEQUEUED
mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
//④ 如果buffer为空,或者非空,但是buffer的尺寸有变化,
//将returnFlags添加BUFFER_NEEDS_REALLOCATION重新申请标志
if ((buffer == NULL) ||
(uint32_t(buffer->width) != w) ||
(uint32_t(buffer->height) != h) ||
(uint32_t(buffer->format) != format) ||
((uint32_t(buffer->usage) & usage) != usage))
{
mSlots[buf].mAcquireCalled = false;
mSlots[buf].mGraphicBuffer = NULL;
mSlots[buf].mRequestBufferCalled = false;
mSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
mSlots[buf].mFence = Fence::NO_FENCE;
mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
returnFlags |= IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION;
}
if (CC_UNLIKELY(mSlots[buf].mFence == NULL)) {
ST_LOGE("dequeueBuffer: about to return a NULL fence from mSlot. "
"buf=%d, w=%d, h=%d, format=%d",
buf, buffer->width, buffer->height, buffer->format);
}
dpy = mSlots[buf].mEglDisplay;
eglFence = mSlots[buf].mEglFence;
*outFence = mSlots[buf].mFence;
mSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
mSlots[buf].mFence = Fence::NO_FENCE;
} // end lock scope
//⑤ buffer需要重新申请,则调用mGraphicBufferAlloc去创建buffer
if (returnFlags & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
status_t error;
sp<GraphicBuffer> graphicBuffer(
mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage, &error));
if (graphicBuffer == 0) {
ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed");
return error;
}
{ // Scope for the lock
Mutex::Autolock lock(mMutex);
if (mAbandoned) {
ST_LOGE("dequeueBuffer: BufferQueue has been abandoned!");
return NO_INIT;
}
mSlots[*outBuf].mFrameNumber = ~0;
mSlots[*outBuf].mGraphicBuffer = graphicBuffer;
}
}
if (eglFence != EGL_NO_SYNC_KHR) {
EGLint result = eglClientWaitSyncKHR(dpy, eglFence, 0, 1000000000);
// If something goes wrong, log the error, but return the buffer without
// synchronizing access to it. It's too late at this point to abort the
// dequeue operation.
if (result == EGL_FALSE) {
ST_LOGE("dequeueBuffer: error waiting for fence: %#x", eglGetError());
} else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
ST_LOGE("dequeueBuffer: timeout waiting for fence");
}
eglDestroySyncKHR(dpy, eglFence);
}
ST_LOGV("dequeueBuffer: returning slot=%d/%llu buf=%p flags=%#x", *outBuf,
mSlots[*outBuf].mFrameNumber,
mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);
return returnFlags;
}
上面函数主要包括5部分:
1.首先找空闲的buffer,在mSlots中状态是FREE的,而且同时要选择mFrameNumber值最小的那个;
2.如果所有的buffer都不是free的,则等待;
3.将找到的buf所对应的状态修改为DEQUEUED;
4.const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer)
,取找到的buf中的mGraphicBuffer,如果buffer为空,或者非空,但是buffer的尺寸有变化,将returnFlags添加BUFFER_NEEDS_REALLOCATION重新申请标志;
5.如果buffer需要重新申请,则调用mGraphicBufferAlloc去创建buffer,关于mGraphicBufferAlloc的创建在前面的《android—匿名binder 》中有介绍,继续分析mGraphicBufferAlloc去创建缓冲区的过程,
sp<GraphicBuffer> graphicBuffer(
mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage, &error));
BpGraphicBufferAlloc ,
class BpGraphicBufferAlloc : public BpInterface<IGraphicBufferAlloc>
{
virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
PixelFormat format, uint32_t usage, status_t* error) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferAlloc::getInterfaceDescriptor());
data.writeInt32(w);
data.writeInt32(h);
data.writeInt32(format);
data.writeInt32(usage);
remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply);
sp<GraphicBuffer> graphicBuffer;
status_t result = reply.readInt32();
if (result == NO_ERROR) {
//client从replay中反序列化出surfaceflinger中创建的GraphicBuffer对象
graphicBuffer = new GraphicBuffer();
result = reply.read(*graphicBuffer);
// reply.readStrongBinder();
// here we don't even have to read the BufferReference from
// the parcel, it'll die with the parcel.
}
*error = result;
return graphicBuffer;
}
}
BnGraphicBufferAlloc,
status_t BnGraphicBufferAlloc::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
case CREATE_GRAPHIC_BUFFER: {
CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);
uint32_t w = data.readInt32();
uint32_t h = data.readInt32();
PixelFormat format = data.readInt32();
uint32_t usage = data.readInt32();
status_t error;
//调用GraphicBufferAlloc的createGraphicBuffer函数,
sp<GraphicBuffer> result =
createGraphicBuffer(w, h, format, usage, &error);
reply->writeInt32(error);
if (result != 0) {
//GraphicBuffer进行序列化,传给client
reply->write(*result);
// We add a BufferReference to this parcel to make sure the
// buffer stays alive until the GraphicBuffer object on
// the other side has been created.
// This is needed so that the buffer handle can be
// registered before the buffer is destroyed on implementations
// that do not use file-descriptors to track their buffers.
reply->writeStrongBinder( new BufferReference(result) );
}
return NO_ERROR;
} break;
}
sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h,
PixelFormat format, uint32_t usage, status_t* error) {
sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
status_t err = graphicBuffer->initCheck();
*error = err;
if (err != 0 || graphicBuffer->handle == 0) {
if (err == NO_MEMORY) {
GraphicBuffer::dumpAllocationsToSystemLog();
}
ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "
"failed (%s), handle=%p",
w, h, strerror(-err), graphicBuffer->handle);
return 0;
}
return graphicBuffer;
}
GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
PixelFormat reqFormat, uint32_t reqUsage)
: BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
mInitCheck(NO_ERROR)
{
width =
height =
stride =
format =
usage = 0;
handle = NULL;
mInitCheck = initSize(w, h, reqFormat, reqUsage);
}
上面的函数主要就是利用GraphicBufferAlloc去分配图形缓冲区的过程,中间会用到gralloc模块,以及GraphicBuffer的序列化和反序列化,反序列化unflatten()时还会调用gralloc在BufferQueue所在的进程将在surfaceflinger中申请的内存map注册过来(匿名共享内存)。
到此,BufferQueue中已经申请到了内存,返回给Surface一个int的数组下标,看来这时候Surface还没有获取到任何图形缓冲区相关的东西。
由于申请的内存是在BufferQueue所在的进程,接下来需要调用requestBuffer将buffer映射到Surface所在的进程
result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
Surface去requestBuffer
int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
..........
sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
//传入数组下标,返回从BufferQueue中映射的GraphicBuffer
result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
if (result != NO_ERROR) {
ALOGE("dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: %d", result);
return result;
}
}
......
}
上面调用了mGraphicBufferProducer->requestBuffer(buf, &gbuf)
,
BpGraphicBufferProducer,
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
{
virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
data.writeInt32(bufferIdx);
//传入数组下标
status_t result =remote()->transact(REQUEST_BUFFER, data, &reply);
if (result != NO_ERROR) {
return result;
}
bool nonNull = reply.readInt32();
if (nonNull) {
//GraphicBuffer的反序列化,在Surface所在进程map映射真实的图形缓冲区
*buf = new GraphicBuffer();
reply.read(**buf);
}
result = reply.readInt32();
return result;
}
}
从上面的代码能够看出,requestBuffer的核心就是:Surface传一个数组下标,然后去将BufferQueue中对应的数组下标中的GraphicBuffer对象映射到Surface中,然后保存在对应的数组中,这两个数组一一对应。
综上,真正申请图形缓冲区是在surface flinger进程中,因为GraphicBufferAlloc对象是在surface flinger中new出来的,然后BufferQueue和Surface中的图形缓冲区都是通过GraphicBuffer的序列化和反序列化新映射出来的。
来源:CSDN
作者:lyf5231
链接:https://blog.csdn.net/lewif/article/details/50703679