当前位置:文档之家› Android6.0显示系统(三)管理图像缓冲区

Android6.0显示系统(三)管理图像缓冲区

Android6.0 显示系统(三)管理图像缓冲区一、BufferQueueCore BufferQueueProducer BufferQueueConsumer上篇博客在Layer的onFirstRef函数中,调用了下面函数,创建了3个对象BufferQueueCore BufferQueueProducer BufferQueueConsumer。

其中BufferCore是核心,把BufferQueueProducer 和BufferQueueConsumer对象连接在一起。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,sp<IGraphicBufferConsumer>* outConsumer,const sp<IGraphicBufferAlloc>& allocator) {sp<BufferQueueCore> core(new BufferQueueCore(allocator));sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core));sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));*outProducer = producer;*outConsumer = consumer;}1.1 生产者和core的联系IGraphicBufferProducer 的大致接口如下,BufferQueueProducer类是接口IGraphicBufferProducer 的实现,使用BufferQueueProducer之前先要调用connect函数,使用结束后调用disconnect断开连接。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片class IGraphicBufferProducer : public IInterface{public:virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) = 0;virtual status_t setBufferCount(int bufferCount) = 0;virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, bool async,uint32_t w, uint32_t h, PixelFormat format, uint32_t usage) = 0;virtual status_t detachBuffer(int slot) = 0;virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,sp<Fence>* outFence) = 0;virtual status_t attachBuffer(int* outSlot,const sp<GraphicBuffer>& buffer) = 0;virtual status_t queueBuffer(int slot,const QueueBufferInput& input, QueueBufferOutput* output) = 0;virtual void cancelBuffer(int slot, const sp<Fence>& fence) = 0;virtual int query(int what, int* value) = 0;virtual status_t connect(const sp<IProducerListener>& listener,int api, bool producerControlledByApp, QueueBufferOutput* output) = 0;virtual status_t disconnect(int api) = 0;virtual status_t setSidebandStream(const sp<NativeHandle>& stream) = 0;virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,PixelFormat format, uint32_t usage) = 0;virtual status_t allowAllocation(bool allow) = 0;virtual status_t setGenerationNumber(uint32_t generationNumber) = 0;virtual String8 getConsumerName() const = 0;};在BufferQueueCore类中定义了一个64项的数据mSlots。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片BufferQueueDefs::SlotsType mSlots;[cpp] view plain copy 在CODE上查看代码片派生到我的代码片typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS];每个缓冲区的类型是BufferSlot类型。

它有两个重要的成员变量,mGraphicBuffer是指向图像缓冲区GraphicBuffer的指针,mBufferState表示图像缓冲区的状态。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片sp<GraphicBuffer> mGraphicBuffer;......BufferState mBufferState;BufferState的状态有下面几个[cpp] view plain copy 在CODE上查看代码片派生到我的代码片enum BufferState {FREE = 0,//空闲DEQUEUED = 1,//生产状态,被生产者拥有QUEUED = 2,//保存数据状态,被BufferQueue拥有ACQUIRED = 3//消费状态,被消费者拥有};BufferQueueProducer的dequeueBuffer函数用来向BufferQueueCore申请一个空闲的slot,这个slot可能已经有缓冲区,也可能没有,如果没有缓冲区,dequeueBuffer函数会分配一块新的缓冲区。

得到空闲的slot后,还需要调用requestBuffer函数来取得一块缓冲区。

得到缓冲区,如果不需要了,可以使用cancelBuffer函数来释放这个slot。

调用dequeueBuffer函数之后,缓冲区的拥有者是生产者,缓冲区处于DEQUEUED状态。

一旦缓冲区复制数据完成,通过queueBuffer函数把缓冲区的控制权交还给BufferQueueCore,这时候缓冲区将处于QUEUED状态。

1.2 消费者和core的联系下面是IGraphicBufferComsumer接口的几个主要函数:[cpp] view plain copy 在CODE上查看代码片派生到我的代码片virtual status_t acquireBuffer(BufferItem* outBuffer,nsecs_t expectedPresent, uint64_t maxFrameNumber = 0) override;......virtual status_t releaseBuffer(int slot, uint64_t frameNumber,const sp<Fence>& releaseFence, EGLDisplay display,EGLSyncKHR fence);virtual status_t connect(const sp<IConsumerListener>& consumerListener,bool controlledByApp);virtual status_t disconnect();BufferQueueConsumer类是接口IGraphicBufferComsumer的实现,在使用它之前,先要调用connect函数建立联系,这里传递的参数是IConsumerListener对象,是一个回调接口,如果BufferQueue中有数据准备好了就会调用它的onFrameAvailable函数来通知消费者取走数据。

取走数据的时候,需要调用acquireBuffer函数,将缓冲区状态变成ACQUIRED,使用完之后调用releaseBuffer函数可以吧缓冲区数据归还给BufferQueueCore,这样缓冲区就变成FREE。

1.3 三者联系对象BufferQueueProducer和BufferQueueConsumer好像没有直接联系,其实都是通过共同的BufferQueueCore对象连接在一起的,很多操作时直接使用BufferQueueCore对象的成员变量而不是函数来完成的。

二、GraphicBuffer对象的创建对Surface而言,图像缓冲区是一个重要的数据结构,它是用户进程和图像显示器之间的纽带,下面我们来看看Surface的图像缓冲区是如何创建的。

2.1 内存缓冲区的创建前面介绍了过dequeueBuffer函数,图像缓冲区GraphicBuffer就是在这个函数中创建的,当从BufferQueueCore中获取到空间的slot时,如果这个slot没有缓冲区就要新建一个。

下面是dequeueBuffer函数的部分代码,在从BufferQueueCore中获取到slot的时候,如果需要重新分配图像缓冲区就会调用mCore->mAllocator->createGraphicBuffer函数来重新创建一个图像缓冲区。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片......*outSlot = found;//found复制到outslotA TRACE_BUFFER_INDEX(found);attachedByConsumer = mSlots[found].mAttachedByConsumer;mSlots[found].mBufferState = BufferSlot::DEQUEUED;//slot的状态修改变成生产状态const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);if ((buffer == NULL) ||//为空,或者需要重新分配buffer->needsReallocation(width, height, format, usage)){mSlots[found].mAcquireCalled = false;mSlots[found].mGraphicBuffer = NULL;mSlots[found].mRequestBufferCalled = false;mSlots[found].mEglDisplay = EGL_NO_DISPLAY;mSlots[found].mEglFence = EGL_NO_SYNC_KHR;mSlots[found].mFence = Fence::NO_FENCE;mCore->mBufferAge = 0;returnFlags |= BUFFER_NEEDS_REALLOCATION;//需要重启分配缓冲区} else {// We add 1 because that will be the frame number when this buffer// is queuedmCore->mBufferAge =mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber;}BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64,mCore->mBufferAge);。

相关主题