Android显示系统(01)- 架构分析
Android显示系统(02)- OpenGL ES - 概述
Android显示系统(03)- OpenGL ES - GLSurfaceView的使用
Android显示系统(04)- OpenGL ES - Shader绘制三角形
Android显示系统(05)- OpenGL ES - Shader绘制三角形(使用glsl文件)
Android显示系统(06)- OpenGL ES - VBO和EBO和VAO
Android显示系统(07)- OpenGL ES - 纹理Texture
Android显示系统(08)- OpenGL ES - 图片拉伸
Android显示系统(09)- SurfaceFlinger的使用
Android显示系统(10)- SurfaceFlinger内部结构
Android显示系统(11)- 向SurfaceFlinger申请Surface
Android显示系统(12)- 向SurfaceFlinger申请Buffer
Android显示系统(13)- 向SurfaceFlinger提交Buffer
一、前言:
前面获取了Surface,并且为Surface申请了Buffer,然后通过EGL的往这Buffer里头渲染数据,完成之后,我们就需要去提交这个Buffer。
二、回顾流程图:
- 首先,SF会创建一个Client代表着App;
- App调用
createSurface
得到一个SurfaceControl
,同时,SF会创建一个Layer,代表APP端的SurfaceControl
; - 同时,SF端的Layer会有生产者和消费者,两者都有成员变量
mCore
(代表BufferQueueCore
)和mSlots
数组,而App端会有一个生产者代理,代表SF那边的Layer中的生产者。(中间通过binder通信) - App端的
SurfaceControl
可以通过getSurface
获得Surface,Surface当中也有mSlots和生产者代理。 - App端想要往Surface里面填充数据,首先得通过lock申请buffer,通过dequeueBuffer返回一个buffer,如果SF侧分配的buffer已经用完了,就通过
Gralloc
模块向匿名内存Ashmem
申请一个buffer,并且填入自己的mSlots
当中,同时返回给APP,需要重新分配Buffer,APP侧会重新调用requestBuffer
让SF侧重新关联这个Buffer,然后进行mmap,并且将fd返回给APP; - App收到binder过来的fd之后(其实binder转换成fd’了),进行
mmap(fd')
得到虚拟地址vaddr
,然后填入自己的mSlots
当中; - 最后App填充数据到vaddr当中之后,通过
unlockAndPost
提交给SF。
三、unlockAndPost:
3.1、总体思路:
- Surface->lock被调用获取Buffer之后,生产者的dequeueBuffer调用。
- 获得buffer之后,App侧通过Surface->unlockAndPost提交填充数据的Buffer,也就是调用queueBuffer。
- 那么queueBuffer调用之后,主要做两件事入队列,并且通知消费者取数据,通知顺序是:
- 通知Layer的消费者;
- 通知SurfaceFlinger;
3.2、代码走读:
入口在这儿:
status_t Surface::unlockAndPost()
{
if (mLockedBuffer == nullptr) {
ALOGE("Surface::unlockAndPost failed, no locked buffer");
return INVALID_OPERATION;
}
int fd = -1;
// 解锁当前被锁的缓冲区(异步)
status_t err = mLockedBuffer->unlockAsync(&fd);
ALOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
// 提交缓冲区
err = queueBuffer(mLockedBuffer.get(), fd);
ALOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
mLockedBuffer->handle, strerror(-err));
mPostedBuffer = mLockedBuffer;
mLockedBuffer = nullptr;
return err;
}
3.3、Layer的消费者:
1)为Layer创建消费者:
看代码之前,我们先看下这个Layer第一次被引用时候:
void BufferQueueLayer::onFirstRef() {
BufferLayer::onFirstRef();
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
// 创建BufferQueue的时候,里面会创建生产者和消费者
BufferQueue::createBufferQueue(&producer, &consumer, true);
// 将消费者做一次封装
mProducer = new MonitoredProducer(producer, mFlinger, this);
{
// Grab the SF state lock during this since it's the only safe way to access RenderEngine
// 同样,将生产者做一次封装
Mutex::Autolock lock(mFlinger->mStateLock);
mConsumer =
new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this);
}
// 。。。
}
看在这里面创建了生产者和消费者。我们看下这个消费者BufferLayerConsumer
:
BufferLayerConsumer::BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq,
renderengine::RenderEngine& engine, uint32_t tex,
Layer* layer)
: ConsumerBase(bq, false), // 调用了父类构造函数
//。。。
mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT) {
// 。。。
}
发现构造函数中首先调用了父类构造函数:
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.
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);
}
}
构造函数主要完成以下工作:
- 接受一个指向
IGraphicBufferConsumer
类型的缓冲队列接口和一个控制标志(是否由应用程序控制)。 - 初始化成员变量,例如放弃状态、消费者句柄等。
- 创建并绑定
ConsumerListener
,监听缓冲区的操作事件。 - 通过
BufferQueue
的consumerConnect
方法,将当前消费端与缓冲队列连接。 - 设置消费端名称,以便开发时调试和跟踪。
进去看看consumerConnect:
// 代码路径:native\libs\gui\include\gui\BufferQueueConsumer.h
virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,
bool controlledByApp) {
return connect(consumer, controlledByApp);
}
调用这个connect就将consumer保存到Layer当中了:
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;
}
// 将Consumer赋值给mCore
mCore->mConsumerListener = consumerListener;
mCore->mConsumerControlledByApp = controlledByApp;
return NO_ERROR;
}
其中sp<BufferQueueCore> mCore;
2)给Consumer设置监听者:
void BufferQueueLayer::onFirstRef() {
// ...
// 给Consumer设置一个Listener
mConsumer->setContentsChangedListener(this);
mConsumer->setName(mName);
// ...
}
稍微进去看看:
void BufferLayerConsumer::setContentsChangedListener(const wp<ContentsChangedListener>& listener) {
setFrameAvailableListener(listener);
Mutex::Autolock lock(mMutex);
mContentsChangedListener = listener;
}
这个会走到父类:
void ConsumerBase::setFrameAvailableListener(
const wp<FrameAvailableListener>& listener) {
CB_LOGV("setFrameAvailableListener");
Mutex::Autolock lock(mFrameAvailableMutex);
mFrameAvailableListener = listener;
}
发现Listener最终保存到父类的成员变量mFrameAvailableListener
以及BufferLayerConsumer
的mContentsChangedListener
,以后Consumer有变化,就通过这个通知给监听者。
3.3、queueBuffer
入口函数:
int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
// ...
nsecs_t now = systemTime();
// 调用生产者代理的queueBuffer,导致Binder调用
status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
mLastQueueDuration = systemTime() - now;
if (err != OK) {
ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
}
// ...
}
调用代理对象的函数:
然后就是调用了QueueBuffer的生产者代理提交buffer。中间一堆binder调用我们省略了,直接看子类BufferQueueProducer
。
status_t BufferQueueProducer::queueBuffer(int slot,
const QueueBufferInput &input, QueueBufferOutput *output) {
BufferItem item;
// 。。。
// 取出要提交的那一项,用取出的项构造一个BufferItem对象;
item.mAcquireCalled = mSlots[slot].mAcquireCalled;
item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
item.mCrop = crop;
item.mTransform = transform &
~static_cast<uint32_t>(NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
item.mTransformToDisplayInverse =
(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0;
item.mScalingMode = static_cast<uint32_t>(scalingMode);
item.mTimestamp = requestedPresentTimestamp;
item.mIsAutoTimestamp = isAutoTimestamp;
item.mDataSpace = dataSpace;
item.mHdrMetadata = hdrMetadata;
item.mFrameNumber = currentFrameNumber;
item.mSlot = slot;
item.mFence = acquireFence;
item.mFenceTime = acquireFenceTime;
item.mIsDroppable = mCore->mAsyncMode ||
(mConsumerIsSurfaceFlinger && mCore->mQueueBufferCanDrop) ||
(mCore->mLegacyBufferDrop && mCore->mQueueBufferCanDrop) ||
(mCore->mSharedBufferMode && mCore->mSharedBufferSlot == slot);
item.mSurfaceDamage = surfaceDamage;
item.mQueuedBuffer = true;
item.mAutoRefresh = mCore->mSharedBufferMode && mCore->mAutoRefresh;
item.mApi = mCore->mConnectedApi;
// 。。。
output->bufferReplaced = false;
if (mCore->mQueue.empty()) {
// When the queue is empty, we can ignore mDequeueBufferCannotBlock
// and simply queue this buffer
mCore->mQueue.push_back(item);
frameAvailableListener = mCore->mConsumerListener;
} else {
// ...
mCore->mQueue.push_back(item);
frameAvailableListener = mCore->mConsumerListener;
}
}
其实不管队列空不空,最终都会push_back进去;
同时,记录了一下listener,这个listener前面已经分析过了,是一个proxy,也就是BufferQueue::ProxyConsumerListener
对象。
通知观察者:
status_t BufferQueueProducer::queueBuffer(int slot,
const QueueBufferInput &input, QueueBufferOutput *output) {
// ...
{ // scope for the lock
std::unique_lock<std::mutex> lock(mCallbackMutex);
while (callbackTicket != mCurrentCallbackTicket) {
mCallbackCondition.wait(lock);
}
// 通知监听者,有数据了
if (frameAvailableListener != nullptr) {
frameAvailableListener->onFrameAvailable(item);
} else if (frameReplacedListener != nullptr) {
frameReplacedListener->onFrameReplaced(item);
}
// ...
}
// ...
}
就是通知监听者有数据了,这个监听者是谁呢?上面我们说了,是Queue的消费者,以及SurfaceFlinger。所以,我们到了消费者的代理类:
void BufferQueue::ProxyConsumerListener::onFrameAvailable(
const BufferItem& item) {
sp<ConsumerListener> listener(mConsumerListener.promote());
if (listener != nullptr) {
listener->onFrameAvailable(item);
}
}
这个listener是ConsumerBase
,于是我们看看消费者的onFrameAvailable
函数:
void ConsumerBase::onFrameAvailable(const BufferItem& item) {
CB_LOGV("onFrameAvailable");
sp<FrameAvailableListener> listener;
{ // scope for the lock
Mutex::Autolock lock(mFrameAvailableMutex);
// 通过调用 promote() 方法,将弱引用 mFrameAvailableListener 提升为强引用 listener
listener = mFrameAvailableListener.promote();
}
if (listener != nullptr) {
CB_LOGV("actually calling onFrameAvailable");
listener->onFrameAvailable(item);
}
}
当然,mFrameAvailableListener
这个就是Layer:
void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
// ...
// If this layer is orphaned, then we run a fake vsync pulse so that
// dequeueBuffer doesn't block indefinitely.
if (isRemovedFromCurrentState()) {
fakeVsync();
} else {
// 通知Layer已经更新
mFlinger->signalLayerUpdate();
}
mConsumer->onBufferAvailable(item);
}
通过SurfaceFlinger来通知Layer已经更新:
// 通知Layer已经更新
void SurfaceFlinger::signalLayerUpdate() {
mScheduler->resetIdleTimer();
mEventQueue->invalidate();
}
这个invalidate()
会导致另外一个很重要的线程被唤醒,后面文章再分析。
四、总结:
Buffer被填充完渲染数据之后,通过Binder告诉SF端对应的消费者,后续通知流程:生产者->进入了消费者->Layer->SurfaceFlinger。就进入了视频显示的主流程,具体如何显示,且听下回分解。