Android GUI系统之SurfaceFlinger(04)应用端分析3-提交Buffer

该系列文章总纲链接:Android GUI系统之SurfaceFlinger 系列文章目录


本章关键点总结 & 说明:

本章节思维导图如上。主要讲述了surafce测试程序 demo的 第3步中的 提交Buffer 阶段。解锁定(最关键)并提交Buffer的过程。


关键源码说明

该部分代码是在上一章节中 Surface测试程序源码的精简版,保存了最关键的流程,如下所示:

#include <cutils/memory.h>
#include <utils/Log.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <android/native_window.h>

using namespace android;

int main(int argc, char** argv)
{
    //...
    //1 创建surfaceflinger的客户端
    sp<SurfaceComposerClient> client = new SurfaceComposerClient();
    
    //2 获取surface
    sp<SurfaceControl> surfaceControl = client->createSurface(String8("resize"),
            160, 240, PIXEL_FORMAT_RGB_565, 0);
    sp<Surface> surface = surfaceControl->getSurface();

    //设置layer,layer值越大,显示层越靠前
    SurfaceComposerClient::openGlobalTransaction();
    surfaceControl->setLayer(100000);
    SurfaceComposerClient::closeGlobalTransaction();

    //3 获取buffer->锁定buffer->写入buffer->解锁并提交buffer 
    //这里主要关注:申请Buff 和 提交Buff
    ANativeWindow_Buffer outBuffer;
    surface->lock(&outBuffer, NULL);
    ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
    android_memset16((uint16_t*)outBuffer.bits, 0xF800, bpr*outBuffer.height);
    surface->unlockAndPost();
    //...
    
    return 0;
}

主要的步骤为:

  1. 获取SurfaceFlinger(后简称SF)的客户端,通过SF的客户端 获取 SurfaceControl,进而获得Surface
  2. 通过SurfaceControl 设置 Layer层数值(忽略),通过Surface获取Buffer,锁定Buffer并写入Buffer
  3. 提交Buffer

本章节主要关注 第3步中的 提交Buff 阶段。解锁定(最关键)并提交Buffer的过程。

surface->unlockAndPost();

Surface的 unlockAndPost方法 代码实现如下:

status_t Surface::unlockAndPost()
{
    //...
    int fd = -1;
    status_t err = mLockedBuffer->unlockAsync(&fd);
    err = queueBuffer(mLockedBuffer.get(), fd);
    mPostedBuffer = mLockedBuffer;
    mLockedBuffer = 0;
    return err;
}

1 unlockAsync分析

mLockedBuffer->unlockAsync(&fd)的代码实现如下:

status_t GraphicBuffer::unlockAsync(int *fenceFd)
{
    status_t res = getBufferMapper().unlockAsync(handle, fenceFd);
    return res;
}

这里调用了GraphicBufferMapper的unlockAsync方法,内容如下:

status_t GraphicBufferMapper::unlockAsync(buffer_handle_t handle, int *fenceFd)
{
    //...
    if (mAllocMod->common.module_api_version >= GRALLOC_MODULE_API_VERSION_0_3) {
        err = mAllocMod->unlockAsync(mAllocMod, handle, fenceFd);
    } else {
        *fenceFd = -1;
        err = mAllocMod->unlock(mAllocMod, handle);
    }
    return err;
}

再往下就是HAL层Gralloc模块的调用了,接下来最后 调用的是Gralloc的gralloc_unlock方法,代码如下:

int gralloc_unlock(gralloc_module_t const* /*module*/,
        buffer_handle_t handle)
{
    // we're done with a software buffer. nothing to do in this
    // implementation. typically this is used to flush the data cache.

    if (private_handle_t::validate(handle) < 0)
        return -EINVAL;
    return 0;
}

这里是什么都没做,但实际上该是 刷新数据的操作,即确保数据完全写入到缓冲区中。

2 queueBuffer分析

queueBuffer的代码实现如下:

int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
    //...
    //获取Buffer的slots索引值
    int i = getSlotFromBufferLocked(buffer);
    //...
    //根据索引值i执行queueBuffer操作
    status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
    //...
    return err;
}

因为这里涉及 Layer层的消费者部分代码,因此在分析 queueBuffer方法前 我们首先回顾下之前 分析的Layer层初始化关于 消费者部分的代码,之后在此基础上分析mGraphicBufferProducer的queueBuffer方法。

2.1 Layer对象 生产者 消费者 源码分析

关于 Layer层的生产者 和 消费者,主要分析Layer的onFirstRef方法,代码如下:

void Layer::onFirstRef() {
    // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
    sp<IGraphicBufferProducer> producer;
    sp<IGraphicBufferConsumer> consumer;
    BufferQueue::createBufferQueue(&producer, &consumer);
    mProducer = new MonitoredProducer(producer, mFlinger);
    //关键点1
    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName);
    mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
    //关键点2
    mSurfaceFlingerConsumer->setContentsChangedListener(this);
    mSurfaceFlingerConsumer->setName(mName);

#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
#warning "disabling triple buffering"
    mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2);
#else
    mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3);
#endif

    const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
    updateTransformHint(hw);
}

2.1.1 SurfaceFlingerConsumer对象分析

这里专注分析SurfaceFlingerConsumer类构造器代码如下:

SurfaceFlingerConsumer(const sp<IGraphicBufferConsumer>& consumer,
        uint32_t tex)
    : GLConsumer(consumer, tex, GLConsumer::TEXTURE_EXTERNAL, false, false),
      mTransformToDisplayInverse(false)
{}

它是继承GLConsumer的,继续分析GLConsumer的构造器,代码如下:

GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
        uint32_t texTarget, bool useFenceSync, bool isControlledByApp) :
    ConsumerBase(bq, isControlledByApp),
    //...
    mAttached(true)
{
    ST_LOGV("GLConsumer");
    memcpy(mCurrentTransformMatrix, mtxIdentity,
            sizeof(mCurrentTransformMatrix));
    mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
}

GLConsumer是继承ConsumerBase的,这里继续分析ConsumerBase的构造器,代码如下:

ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
        mAbandoned(false),
        mConsumer(bufferQueue) {
    // Choose a name using the PID and a process-unique ID.
    mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
    //这里的this就是SurfaceFlingerConsumer对象
    wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
    //使用listener初始化BufferQueue内部的mConsumerListener成员变量
    sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
    //使用proxy 初始化BufferQueueConsumer内部的mConsumerListener成员变量
    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);
    }
}

这里主要看下BufferQueue::ProxyConsumerListener 和 mConsumer->consumerConnect的实现。

@1 BufferQueue::ProxyConsumerListener实现

BufferQueue的ProxyConsumerListener构造器代码实现如下:

BufferQueue::ProxyConsumerListener::ProxyConsumerListener(
        const wp<ConsumerListener>& consumerListener):
        mConsumerListener(consumerListener) {}

仔细分析会得出:主要是将SurfaceFlingerConsumer的mConsumerListener对象 赋值给 Proxy的mConsumerListener对象。

@2 mConsumer->consumerConnect实现

consumerConnect的代码实现如下:

virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,
        bool controlledByApp) {
    return connect(consumer, controlledByApp);
}

继续分析connect,代码如下:

status_t BufferQueueConsumer::connect(
        const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
    //...
    Mutex::Autolock lock(mCore->mMutex);
    //...
    mCore->mConsumerListener = consumerListener;
    mCore->mConsumerControlledByApp = controlledByApp;
    return NO_ERROR;
}

仔细分析会得出:主要是将Proxy的mConsumerListener对象 赋值给BufferQueueConsumer的mConsumerListener对象。

2.2.2 SurfaceFlingerConsumer的setContentsChangedListener分析

这里setContentsChangedListener的代码实现如下:

void SurfaceFlingerConsumer::setContentsChangedListener(
        const wp<ContentsChangedListener>& listener) {
    setFrameAvailableListener(listener);
    Mutex::Autolock lock(mMutex);
    mContentsChangedListener = listener;
}

继续分析setFrameAvailableListener,代码实现如下:

void ConsumerBase::setFrameAvailableListener(
        const wp<FrameAvailableListener>& listener) {
    Mutex::Autolock lock(mMutex);
    mFrameAvailableListener = listener;
}

这里主要是把SurfaceFlingerConsumer的mFrameAvailableListener 设置为 Layer(上面的listener就是Layer对象)。

2.1.3 总结

  • SurfaceFlingerConsumer的mConsumerListener对象 赋值给 ProxyConsumerListener的mConsumerListener对象
  • ProxyConsumerListener的mConsumerListener对象 赋值给BufferQueueConsumer的mConsumerListener对象
  • SurfaceFlingerConsumer的mFrameAvailableListener 设置为 Layer对象

2.2 mGraphicBufferProducer的queueBuffer方法分析

这里继续分析mGraphicBufferProducer的queueBuffer方法,代码如下:

status_t BufferQueueProducer::queueBuffer(int slot,
        const QueueBufferInput &input, QueueBufferOutput *output) {
    //...
    sp<IConsumerListener> frameAvailableListener;
    sp<IConsumerListener> frameReplacedListener;
    int callbackTicket = 0;
    BufferItem item;
    { // Autolock scope
        //...
        const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
        Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
        Rect croppedRect;
        crop.intersect(bufferRect, &croppedRect);
        //mSlots item 初始化...

        if (mCore->mQueue.empty()) {
            //将构造的item放入队列mQueue中
            mCore->mQueue.push_back(item);
            //将之前分析的proxy的Listener赋值给frameAvailableListener
            frameAvailableListener = mCore->mConsumerListener;
        } else {
            // When the queue is not empty, we need to look at the front buffer
            // state to see if we need to replace it
            BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
            if (front->mIsDroppable) {
                if (mCore->stillTracking(front)) {
                    mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
                    mSlots[front->mSlot].mFrameNumber = 0;
                }
                // Overwrite the droppable buffer with the incoming one
                *front = item;
                frameReplacedListener = mCore->mConsumerListener;
            } else {
                mCore->mQueue.push_back(item);
                frameAvailableListener = mCore->mConsumerListener;
            }
        }

        mCore->mBufferHasBeenQueued = true;
        mCore->mDequeueCondition.broadcast();
        output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
                mCore->mTransformHint, mCore->mQueue.size());
        callbackTicket = mNextCallbackTicket++;
    } // Autolock scope

    //...
    // Call back without the main BufferQueue lock held, but with the callback
    // lock held so we can ensure that callbacks occur in order
    {
        Mutex::Autolock lock(mCallbackMutex);
        while (callbackTicket != mCurrentCallbackTicket) {
            mCallbackCondition.wait(mCallbackMutex);
        }

        if (frameAvailableListener != NULL) {
            //关键方法
            frameAvailableListener->onFrameAvailable(item);
        } else if (frameReplacedListener != NULL) {
            frameReplacedListener->onFrameReplaced(item);
        }

        ++mCurrentCallbackTicket;
        mCallbackCondition.broadcast();
    }

    return NO_ERROR;
}

这里关注 frameAvailableListener->onFrameAvailable(item)的实现,通过前面的分析可知listener是proxyConsumerListener 类对象,因此代码如下:

void BufferQueue::ProxyConsumerListener::onFrameAvailable(
        const android::BufferItem& item) {
    sp<ConsumerListener> listener(mConsumerListener.promote());
    if (listener != NULL) {
        listener->onFrameAvailable(item);
    }
}

这里的listener是SurfaceFlingerConsumer类的对象(继承 GLConsumer->继承ConsumerBase),代码实现如下:

void ConsumerBase::onFrameAvailable(const BufferItem& item) {
    sp<FrameAvailableListener> listener;
    { // scope for the lock
        Mutex::Autolock lock(mMutex);
        listener = mFrameAvailableListener.promote();
    }

    if (listener != NULL) {
        listener->onFrameAvailable(item);
    }
}

这里的mFrameAvailableListener.promote()返回的是Layer对象,Layer的onFrameAvailable方法实现如下:

void Layer::onFrameAvailable(const BufferItem& item) {
    // Add this buffer from our internal queue tracker
    { // Autolock scope
        Mutex::Autolock lock(mQueueItemLock);
        mQueueItems.push_back(item);
    }

    android_atomic_inc(&mQueuedFrames);
    mFlinger->signalLayerUpdate();
}

这里调用了SF相关操作,继续分析 mFlinger->signalLayerUpdate(),代码如下:

void SurfaceFlinger::signalLayerUpdate() {
    mEventQueue.invalidate();
}

这里就是 唤醒 另外一个线程了,本章节的分析就先到这里。该系列文章 第6节(Android GUI系统之SurfaceFlinger(06)服务端分析1-处理VSYNC)会继续分析。

2.3 总结

listener的监听通知顺序从下到上依次是:生产者->消费者->Layer->SF。即queueBuffer的流程是将加入队列的Buffer 的消息通知proxyConsumerListener,进而通知消费者SurafceFlingerConsumer,进而通知Layer,通知SF。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图王大胜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值