// updateTexImage acquires the most recently queued buffer, and sets the
// image contents of the target texture to it.
//
// This call may only be made while RenderEngine is current.
//
// This calls doFenceWait to ensure proper synchronization unless native
// fence is supported.
//
// Unlike the GLConsumer version, this version takes a functor that may be
// used to reject the newly acquired buffer. It also does not bind the
// RenderEngine texture until bindTextureImage is called.
status_t updateTexImage(BufferRejecter* rejecter, nsecs_t expectedPresentTime,
bool* autoRefresh, bool* queuedBuffer, uint64_t maxFrameNumber);
updateTexImage()
请求最后一个入队的 buffer。注释没看懂,直接看实现。
BufferItem item;
// Acquire the next buffer.
// In asynchronous mode the list is guaranteed to be one buffer
// deep, while in synchronous mode we use the oldest buffer.
status_t err = acquireBufferLocked(&item, expectedPresentTime, maxFrameNumber);
if (err != NO_ERROR) {
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
err = NO_ERROR;
} else if (err == BufferQueue::PRESENT_LATER) {
// return the error, without logging
} else {
BLC_LOGE("updateTexImage: acquire failed: %s (%d)", strerror(-err), err);
}
return err;
}
调用 BufferLayerConsumer::acquireBufferLocked() 获取 buffer。如果 BufferItem::mGraphicBuffer
不是空,则更新 BufferLayerConsumer::Image 数组。
如果返回 NO_BUFFER_AVAILABLE
,则返回 NO_ERROR
。如果返回 PRESENT_LATER
则直接返回,说明要延迟显示。
// We call the rejecter here, in case the caller has a reason to
// not accept this buffer. This is used by SurfaceFlinger to
// reject buffers which have the wrong size
int slot = item.mSlot;
if (rejecter && rejecter->reject(mSlots[slot].mGraphicBuffer, item)) {
releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
return BUFFER_REJECTED;
}
reject()
对宽高的执行复杂的检查,具体实现不看了。如果要拒绝则调用 ConsumerBase::releaseBufferLocked() 释放引用,并返回 BUFFER_REJECTED
。
// Release the previous buffer.
err = updateAndReleaseLocked(item, &mPendingRelease);
if (err != NO_ERROR) {
return err;
}
如果没有拒绝,则调用 BufferLayerConsumer::updateAndReleaseLocked() 释放上一个 buffer 并更新成员,其中有 mCurrentTextureBuffer
,它是 BufferLayerConsumer::Image 类型,会在绑定 texture 时使用。
if (!mRE.useNativeFenceSync()) {
// Bind the new buffer to the GL texture.
//
// Older devices require the "implicit" synchronization provided
// by glEGLImageTargetTexture2DOES, which this method calls. Newer
// devices will either call this in Layer::onDraw, or (if it's not
// a GL-composited layer) not at all.
err = bindTextureImageLocked();
}
最后,根据 RenderEngine 状态调用 BufferLayerConsumer::bindTextureImageLocked() 绑定 texture。