您的位置:首页 > 产品设计 > UI/UE

BufferQueue原理

2016-04-28 17:49 337 查看
BufferQueue.cpp

class BufferQueue : public BnGraphicBufferProducer,
                    public BnGraphicBufferConsumer,
                    private IBinder::DeathRecipient
从继承关系来看,是生产者,也是消费者,还关心的一个Binder的生死

主功能分成3个部分
1.生产者
 IGraphicBufferProducer
  dequeueBuffer
  queueBuffer

2.消费者
IGraphicBufferConsumer
  acquireBuffer
  releaseBuffer

3.数据
BufferQueue
  BufferSlot mSlots[32];
  Vector<BufferItem> mQueue;

工作原理

数据部分:(共享内存
  struct BufferSlot {
        //图像缓冲区
        sp<GraphicBuffer> mGraphicBuffer;
       //buffer的状态,表示当的状态,是否可以dequue,queue,acquire等
        BufferState mBufferState;   
  }

  class BufferItem : public Flattenable<BufferItem> {     
        //图像缓冲区
        sp<GraphicBuffer> mGraphicBuffer;
        //在slot数组中的索引
        int mBuf;
    ...
  }

  BufferQueue中的  mSlots[32],mQueue都是指向GraphicBuffer的,只是应用的地方不一样
     mQueue:是加工好的数据,Consumer可以消耗了
     mSlots:所有的缓冲 Producer在里面找合适的空闲buffer,其实我感觉也可以用一个freeQueue.

 生产者(app端)

   //要缓冲区,
  BufferQueue ::dequeueBuffer()从mSlots中获取一段空闲的buffer
   {
      //统计一下正在dequeue中  正acquired中的
      for (int i = 0; i < maxBufferCount; i++) {
    const int state = mSlots[i].mBufferState;
    switch (state) {
        case BufferSlot::DEQUEUED:
        dequeuedCount++;
        break;
        case BufferSlot::ACQUIRED:
        acquiredCount++;
        break;
        case BufferSlot::FREE:
        //选择最早(mFrameNumber最小)queue的buffer,这种buffer其他硬件已经用完的可能性最大了
        if ((found < 0) || mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
            found = i;
        }
        break;
    }

        if(found<0){ 可能找不到buffer需要等待空闲buffer
       DequeueCondition.wait(mMutex)
    }
     }
   }

   //数据填充进去了,通知consumer消费把
     BufferQueue :: queueBuffer 把加工好的buffer推到mQueue中
   {   
        找到buf索引位置的buffer,以前dequeue出的索引

        BufferItem item;
        item.mAcquireCalled = mSlots[buf].mAcquireCalled;
        item.mGraphicBuffer = mSlots[buf].mGraphicBuffer;
        item.mFrameNumber = mFrameCounter;  //每次加1,最小的肯定是最早推进去的
        item.mBuf = buf;

        if (mQueue.empty()) {           
            mQueue.push_back(item);
    }
        //通知dequeue中等待的,dequeue可能没有缓存了,在等待呢
    mDequeueCondition.broadcast();
        //通知Consumer数据准备好了
    listener->onFrameAvailable();
   }

   消费者 (SurfaceFlinger服务)
    //要数据
     BufferQueue :: acquireBuffer(BufferItem *buffer, nsecs_t expectedPresent)   从mQueue中获取一段加工好的buffer
    { 
       //获取队列头的,别设置一系列状态
       Fifo::iterator front(mQueue.begin());
       int buf = front->mBuf; //solt中的索引
       *buffer = *front;   
        mQueue.erase(front);
        mDequeueCondition.broadcast();
    }

    //数据用完了,归还回去
    BufferQueue::releaseBuffer( int buf, const sp<Fence>& fence,....) {
      if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {//验证一下状态,然后归还,就是修改写一下slot的状态
         mSlots[buf].mFence = fence; //这个是为了与其他硬件同步的
         mSlots[buf].mBufferState = BufferSlot::FREE;
      }
      mDequeueCondition.broadcast();
      return NO_ERROR;
    }

BufferQueue对谁的生死那么关心呢

    IBinder::DeathRecipient
    void BufferQueue::binderDied(const wp<IBinder>& who) {//binder死掉后回调这个的
       int api = mConnectedApi;
       this->disconnect(api);
    }

   disconnect(){
     //把所有的buffer全清掉
     freeAllBuffersLocked();
     sp<IBinder> token = mConnectedProducerToken;
     token->unlinkToDeath(static_cast<IBinder::DeathRecipient*>(this));
     mDequeueCondition.broadcast();
     //消费者关心这个,肯定是不要绘制了
     mConsumerListener->onBuffersReleased();
    }

   connect(){//连接的时候,建立关联
      status_t err = token->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
      mConnectedProducerToken = token;
   }

    //surface中进行了connect
   int Surface::connect(int api) {
    //这个binder在这呢,看着没什么用处,但是当这个进程关掉的时候这个binder就会死掉
    static sp<BBinder> sLife = new BBinder();
    IGraphicBufferProducer::QueueBufferOutput output;
    int err = mGraphicBufferProducer->connect(sLife, api, mProducerControlledByApp, &output);
   }

   //surface 的lock调用connect
   status_t Surface::lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
   { 
       if (!mConnectedToCpu) {
            int err = Surface::connect(NATIVE_WINDOW_API_CPU);
       }
   }

   以前分析过当java层的Surface.lockcanvas的时候会调用c++层surface的lock.
   所以BufferQueue跟app的生死绑定到了一起,当app莫名其妙的死掉以后,flinger服务中的BufferQueue就知道,会做一些清理工作。

总结:
   BufferQueue集成了生产者,消费者,数据的逻辑,搞得有点复杂,感觉这3个应该分开。
   BufferQueue与app的生死绑定在一起。
   BufferQueue的数据具体消费在Consumer的Callback回调中.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: