BufferQueue



1.BufferQueue内部原理

BufferQueueIGraphicBufferProducer服务器端的实现;所以BufferQueue会重载IGraphicBufferProducer接口中的各个虚函数queueBuffer,requesBuffer,dequeueBuffer等,该类内部还有一个mSlots[NUM_BUFFER_SLOTS];

1.1 mSlots[NUM_BUFFER_SLOTS]

BufferQueueBufferSlot的定义:

struct BufferSlot{

    //用于记录缓冲区

   sp<GraphicBuffer> mGraphicBuffer;

    //用于记录缓冲区状态

    BufferStatemBuffreState;

    ...

}

 

1.2  缓冲区状态

//缓冲区状态

enum BufferState {

//Buffer当前可用,也就是可以被dequeued,此时Buffer的拥有者可以认为是BufferQueue

       FREE = 0,

//Buffer已经被dequeued,还没被queued或者canceld

//此时Buffer的拥有者是应用程序,此时BufferQueueSurfaceFlinger都不可以操作这块缓冲区

       DEQUEUED = 1,

//Buffer被客户端程序queued,不过还不能对它进行dequeue,但可以acquire

//此时拥有者还是BufferQueue

       QUEUED = 2,

//Buffer的拥有者是Consumer,可以被release然后状态回到FREE

       ACQUIRED = 3

    };

    BufferStatemBufferState;

};

 

1.3 缓冲区状态迁移

BufferQueue :可以认为BufferQueue是一个服务中心,其他两个Owner必须通过它来管理Buffer Producer :生产者就是填充Buffer的,通常情况下就是应用程序,应用程序不断刷新UI,从而将产生的数据源源不断的写到Buffer中,当Producer需要一块Buffer时,首先回向中介BufferQueue发起dequeue请求,然后才能对指定的缓冲区进行操作,经过dequeue后的buffer就属于producer了,它可以对缓冲区进行任何操作,而其他Owner不能插手。当producer认为一块Buffer已经写入完成后,将进一步调用BufferQueuequeue接口,把Buffer归还到BufferQueue中,一旦入列成功,Owner就变成了BufferQueue Consumer :当一块Buffer就绪之后,Consumer就可以开始工作了。

总结:BufferQueue是中介,Producer是内容的产出方,它对Buffer的操作是主动的,ConsumerBuffer的操作是被动的,它必须等到Buffer填充完成之后才工作(其中ready之后通知Consumer的工作是ConsumerListener来完成的),当数据准备就绪后,通过onFrameAvailable通知Consumer来进行消费

class ConsumerListener : public virtualRefBase {

  //当一块Buffer可以被消费时,这个函数会被调用

  virtual voidonFrameAvailable(const BufferItem& item) = 0;

  //BufferQueue通知Cosumer它已经释放slot中一个或多个GraphicBuffer引用

  virtual void onBuffersReleased()= 0;

}

 

2.BufferQueue中缓冲区的分配

2.1 缓冲区分配简略

缓冲区的分配应该既要满足使用者的需求,又要防止浪费。 既然Producer对缓冲区的操作时主动的,那么就意味着它是整个需求的发起者;也就是说只要Producer没有执行dequeueBuffer或者dequeueBuffer时能获取到可用的缓冲区,那就没有必要重新分配空间。

 

2.2 缓冲区分配的起点Surface::dequeueBuffer

 

intSurface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {

   

    int buf = -1;

    //宽高计算

    int reqW = mReqWidth? mReqWidth : mUserWidth;

    int reqH =mReqHeight ? mReqHeight : mUserHeight;

    sp<Fence>fence;

    //dequeueBuffer得到一个缓冲区

    status_t result =mGraphicBufferProducer->dequeueBuffer(&buf, &fence,mSwapIntervalZero,reqW, reqH, mReqFormat, mReqUsage);

    //buf是一个int值,代表mSlots数组序号

   sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);

 

    if (result& IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {

       freeAllBuffers();

    }

    //需要重新分配

    if ((result &IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {

       result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);

       if (result != NO_ERROR) {

            returnresult;

       }

    } 

    *buffer =gbuf.get();

    return OK;

}

 

2.3 BpGraphicBufferProducer调用远程服务

class BpGraphicBufferProducer : publicBpInterface<IGraphicBufferProducer>

{

public:

   BpGraphicBufferProducer(const sp<IBinder>& impl)

       : BpInterface<IGraphicBufferProducer>(impl)

    {

       

    }

    

    virtualstatus_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());

       //只写进去5个参数,这是入参,buffence是出参

       data.writeInt32(async);

       data.writeInt32(w);

       data.writeInt32(h);

       data.writeInt32(format);

       data.writeInt32(usage);

       //远程调用

       status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply);

       if (result != NO_ERROR) {

           return result;

       }

       

        *buf= reply.readInt32();//slot编号

       bool nonNull = reply.readInt32();

       if (nonNull) {

           *fence = new Fence();

           reply.read(**fence);//reply中读取数据填充fence

       }

       result = reply.readInt32();

       return result;

    }

       

    //这里bufferIdx是入参,传给了服务端,buf是出参

    virtual status_trequestBuffer(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) {

           *buf = new GraphicBuffer();

           reply.read(**buf);//reply中读取数据填充buf

       }

       result = reply.readInt32();

       return result;

    }

 

//...

}

2.4 BnGraphicBufferProducer的响应

status_tBnGraphicBufferProducer::onTransact(

    uint32_t code, constParcel& data, Parcel* reply, uint32_t flags)

{

    switch(code) {

       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;

           //调用dequeueBuffer

           int result = dequeueBuffer(&buf, &fence, async, w, h, format, usage);

           //注意写入的顺序,客户端读取的顺序与这个一致

           reply->writeInt32(buf);

           reply->writeInt32(fence != NULL);

           if (fence != NULL) {

               reply->write(*fence);

           }

           reply->writeInt32(result);

           return NO_ERROR;

       } break;

 

       

        caseREQUEST_BUFFER: {

           CHECK_INTERFACE(IGraphicBufferProducer, data, reply);

           int bufferIdx   = data.readInt32();

           sp<GraphicBuffer> buffer;

           //调用requestBuffer

           int result = requestBuffer(bufferIdx, &buffer);

           reply->writeInt32(buffer != 0);

           if (buffer != 0) {

               reply->write(*buffer);

           }

           reply->writeInt32(result);

           return NO_ERROR;

       } break;

 

 

       

        //......

    }

}

 

2.5 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) {

 

    { 

        Mutex::Autolocklock(mMutex);

        intfound = -1;

       bool tryAgain = true;

       while (tryAgain) {//查询符合要求的slot

           //......

           found = INVALID_BUFFER_SLOT;//初始值

           int dequeuedCount = 0;

           int acquiredCount = 0;

           for (int i = 0; i < maxBufferCount; i++) {

               const int state = mSlots[i].mBufferState;//slot的状态

               switch (state) {

                   case BufferSlot::DEQUEUED:

                       dequeuedCount++;//统计DEQUEUEDslot个数

                       break;

                   case BufferSlot::ACQUIRED:

                       acquiredCount++;

                       break;

                   case BufferSlot::FREE: //找到处于空闲状态的slot

                       if ((found < 0) ||

                               mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {

                           found = i;

                       }

                       break;

               }

           }

 

            if(!mOverrideMaxBufferCount && dequeuedCount) {

               //如果client没有设置buffer count的话,就不允许dequeue一个以上buffer

               return -EINVAL;

           }

 

           //是否需要重试

           tryAgain = found == INVALID_BUFFER_SLOT;

           if (tryAgain) {

               //如果需要重试的话,就等待,因为如果这时候直接开始也是拿不到的               

                mDequeueCondition.wait(mMutex);

           }

       }

        

        constint buf = found;

       *outBuf = found;//返回值

 

        //成功找到可用序号,接下来就是进行初始化操作以及状态变迁

       //BuffreSlot的一个成员mBufferState的赋值

       mSlots[buf].mBufferState = BufferSlot::DEQUEUED;

 

       const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);

       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;

           //如果需要重新分配的话,返回值里有BUFFER_NEEDS_REALLOCATION

           returnFlags |= IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION;

       }

    }  // endlock scope

    //如果需要重新分配的话

    if (returnFlags& IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {

       status_t error;

       sp<GraphicBuffer> graphicBuffer(

               mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage, &error));

       if (graphicBuffer == 0) {

            returnerror;

       }

        

        {// Scope for the lock

           Mutex::Autolock lock(mMutex);

            mSlots[*outBuf].mFrameNumber= ~0;

           //BufferSlot的另一个重要成员mGraphicBuffer赋值

           mSlots[*outBuf].mGraphicBuffer = graphicBuffer;

       }

    }

    returnreturnFlags;

}

 

分配空间会调用mGraphicBufferAlloc->createGraphicBuffer,如果重新分配了空间,那么需要加上BUFFER_NEEDS_REALLOCATION标志。客户端在使用的时候发现这个标志会调用requestBuffer来取得最新的buffer地址。

2.6 BufferQueue::requestBuffer

 

status_t BufferQueue::requestBuffer(intslot, sp<GraphicBuffer>* buf) {

    //根据索引和状态判断

    if (slot < 0 ||slot >= NUM_BUFFER_SLOTS) {

        returnBAD_VALUE;

    } else if(mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {

        returnBAD_VALUE;

    }

   mSlots[slot].mRequestBufferCalled = true;

    *buf =mSlots[slot].mGraphicBuffer;//注意buf

    return NO_ERROR;

}

requestBuffer后,通过Binder的传递,就把这个buf传给了Surfacegbuf,然后又通过*buffer = gbuf.get();就把这块缓冲区也给了Surface里的buffer

2.7总结

Surface通过dequeueBuffer来申请一块缓冲区,该操作会通过客户端的mGraphicBufferProducerBinder调用到服务端的BufferQueue(IGraphicBufferProducer的服务端)BufferQueue通过找到一个合适的slot序号并为BufferSlot分配空间,然后通过Binder返回给客户端,客户端通过读取将值传递过去。客户端对缓冲区的操作会通过到服务端使用的是共享内存ashmem

猜你喜欢

转载自blog.csdn.net/qwaszx523/article/details/79013018