美文网首页
BufferQueue介绍

BufferQueue介绍

作者: 新进取者 | 来源:发表于2024-07-05 18:32 被阅读0次

    我们从下面几个文件开始分析Surface相关知识

    1. frameworks/native/libs/gui/tests/
    2. frameworks/native/opengl/tests/EGLTest/
    3. frameworks/native/libs/nativedisplay/surfacetexture/

    一. 基本知识

    先看下继承关系:

    74  class Surface
    75      : public ANativeObjectBase<ANativeWindow, Surface, RefBase>
    76  {
    

    Surface继承ANativeWindow和RefBase
    再看下构造函数:

    99      explicit Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp = false,
    100                       const sp<IBinder>& surfaceControlHandle = nullptr);
    

    可以看到new Surface的时候就会指定producer是谁。一般都是通过下面方式传入的:

    148      sp<IGraphicBufferProducer> producer;
    149      sp<IGraphicBufferConsumer> consumer;
    150      BufferQueue::createBufferQueue(&producer, &consumer);
    152      sp<Surface> mSTC = new Surface(producer);
    

    1.先看下BufferQueue的创建

    101  void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
    102          sp<IGraphicBufferConsumer>* outConsumer,
    103          bool consumerIsSurfaceFlinger) {  //默认false
    109      sp<BufferQueueCore> core(new BufferQueueCore());
     
    113      sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger));
    
    117      sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
    
    121      *outProducer = producer;
    122      *outConsumer = consumer;
    123  }
    

    三个对象:BufferQueueCore、BufferQueueProducer、BufferQueueConsumer

    1)BufferQueueCore

    构造的时候几个关键的变量
    ️mConsumerName:
    String8::format("unnamed-%d-%d", getpid(),
    63 android_atomic_inc(&counter));
    当然后期也可以通过函数接口重新设置:

    719  status_t BufferQueueConsumer::setConsumerName(const String8& name) {
    720      ATRACE_CALL();
    721      BQ_LOGV("setConsumerName: '%s'", name.string());
    722      std::lock_guard<std::mutex> lock(mCore->mMutex);
    723      mCore->mConsumerName = name;
    724      mConsumerName = name;
    725      return NO_ERROR;
    726  }
    

    ️mFreeSlots

    134      int numStartingBuffers = getMaxBufferCountLocked();
    135      for (int s = 0; s < numStartingBuffers; s++) {
    136          mFreeSlots.insert(s);
    137      }
    

    可以看到初始化时mFreeSlots数量由getMaxBufferCountLocked函数决定。

    246  int BufferQueueCore::getMaxBufferCountLocked() const {
    247      int maxBufferCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
    248              ((mAsyncMode || mDequeueBufferCannotBlock) ? 1 : 0);
    249  
    250      // limit maxBufferCount by mMaxBufferCount always
    251      maxBufferCount = std::min(mMaxBufferCount, maxBufferCount);
    252  
    253      return maxBufferCount;
    254  }
    

    由于mMaxBufferCount基本等于BufferQueueDefs::NUM_BUFFER_SLOTS,当然也可以调用consumer的BufferQueueConsumer::setMaxBufferCount函数重新设置,因此可以看出getMaxBufferCountLocked由mMaxAcquiredBufferCount和mMaxDequeuedBufferCount以及+1(mAsyncMode/mDequeueBufferCannotBlock)决定。
    mMaxAcquiredBufferCount在BufferQueueCore初始化为1,也可以通过BufferQueueConsumer::setMaxAcquiredBufferCount函数重新设置。
    mMaxDequeuedBufferCount在BufferQueueCore初始化为1,也可以通过 BufferQueueProducer::setMaxDequeuedBufferCount函数重新设置。
    通过mMaxDequeuedBufferCount名字上可以看出由producer设置,而mMaxBufferCount/mMaxAcquiredBufferCount 是由consumer设置。
    而mAsyncMode默认是false,也可以由producer端的BufferQueueProducer::setAsyncMode函数进行设置。
    mDequeueBufferCannotBlock默认也是false,这个变量容易出问题会使得总buffer数量+1,值得注意下!在producer端connect时:mDequeueBufferCannotBlock默认是false,但是如果producer和consumer端由app控制的话那么下面判断会进入:

    1311      if (mCore->mConsumerControlledByApp && producerControlledByApp) {
    1312          mCore->mDequeueBufferCannotBlock = mDequeueTimeout < 0;
    1313          mCore->mQueueBufferCanDrop = mDequeueTimeout <= 0;
    1314      }
    

    会根据mDequeueTimeout变量(默认为-1)决定mDequeueBufferCannotBlock的值,如果是surfaceTexture,那么该判断会进入,但是如果没有调用BufferQueueProducer::setDequeueTimeout,那么mDequeueTimeout为-1,mDequeueBufferCannotBlock值会为true。因此,如果发现buffer多了一个,看下dump信息,是不是这个变量为true了。

    ️mUnusedSlots
    mUnusedSlots表示目前没有使用的buffer,也就是用64-当前buffer数量

    138      for (int s = numStartingBuffers; s < BufferQueueDefs::NUM_BUFFER_SLOTS;
    139              s++) {
    140          mUnusedSlots.push_front(s);
    141      }
    

    ️mDefaultWidth/mDefaultHeight
    默认为1,可以通过下面的consumer端重新设置,记得和producer端的函数有区是分的哦。Surface.cpp中也有同样的变量,是从当前BufferQueueCore中取的。

    595  status_t BufferQueueConsumer::setDefaultBufferSize(uint32_t width,
    596          uint32_t height) {
    597      ATRACE_CALL();
    608      mCore->mDefaultWidth = width;
    609      mCore->mDefaultHeight = height;
    610      return NO_ERROR;
    611  }
    

    对应其他模块调用:mConsumer->setDefaultBufferSize(w, h)
    如:frameworks/native/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp

    ️ mConsumerControlledByApp
    既有producer端的也有consumer端的,共同决定前面说的mDequeueBufferCannotBlock变量。
    如:SurfaceTexture设置过程如下:

    frameworks/base/core/jni/android_graphics_SurfaceTexture.cpp
    234  static void SurfaceTexture_init(JNIEnv* env, jobject thiz, jboolean isDetached,
    235          jint texName, jboolean singleBufferMode, jobject weakThiz)
    236  {
    237      sp<IGraphicBufferProducer> producer;
    238      sp<IGraphicBufferConsumer> consumer;
    239      BufferQueue::createBufferQueue(&producer, &consumer);
    245      sp<SurfaceTexture> surfaceTexture;
    246      if (isDetached) {
    247          surfaceTexture = new SurfaceTexture(consumer, GL_TEXTURE_EXTERNAL_OES,  //根据singleBuffer确认mConsumerControlledByApp
    248                  true, !singleBufferMode);
    249      } else {
    250          surfaceTexture = new SurfaceTexture(consumer, texName,
    251                  GL_TEXTURE_EXTERNAL_OES, true, !singleBufferMode); //根据singleBuffer确认mConsumerControlledByApp
    252      }
    
    frameworks/native/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
    36  SurfaceTexture::SurfaceTexture(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
    37                                 uint32_t texTarget, bool useFenceSync, bool isControlledByApp)
    38        : ConsumerBase(bq, isControlledByApp),
    
    frameworks/native/libs/gui/ConsumerBase.cpp
    58  ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) {
    72      status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
    
    frameworks/native/libs/gui/include/gui/BufferQueueConsumer.h
    165      virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,
    166              bool controlledByApp) {
    167          return connect(consumer, controlledByApp);
    168      }
    
    frameworks/native/libs/gui/BufferQueueConsumer.cpp
    511  status_t BufferQueueConsumer::connect(
    512          const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
    513      ATRACE_CALL();
    531      mCore->mConsumerControlledByApp = controlledByApp;
    532  
    533      return NO_ERROR;
    534  }
    

    2)BufferQueueProducer

    ️ mSlots
    取的是BufferQueueCore中的mSlots
    mSlots(core->mSlots)

    3)BufferQueueConsumer

    ️ mSlots
    取的是BufferQueueCore中的mSlots
    mSlots(core->mSlots)

    2. 回到主线上去看Surface中的成员变量

    ️mGraphicBufferProducer
    指向BufferQueueProducer

    ️ mProducerControlledByApp
    在new Surface的时候传入,这个值会被设置到BufferQueueProducer用于判断上面说的mDequeueBufferCannotBlock值。需要注意哦!
    mProducerControlledByApp = controlledByApp
    如:
    TextureView:

    frameworks/base/core/jni/android_view_TextureView.cpp
    sp<ANativeWindow> window = new Surface(producer, true);
    

    SurfaceTexture:

    frameworks/base/core/jni/com_google_android_gles_jni_EGLImpl.cpp
    301      sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(_env, native_window));
    302      window = new Surface(producer, true);
    frameworks/base/core/jni/android_view_Surface.cpp
    android_view_Surface_createFromIGraphicBufferProducer
    135      sp<Surface> surface(new Surface(bufferProducer, true));
    nativeCreateFromSurfaceTexture
    156      sp<Surface> surface(new Surface(producer, true));
    

    ️mReqWidth/mReqHeight

    2079  int Surface::setBuffersDimensions(uint32_t width, uint32_t height)
    2080  {
    2081      ATRACE_CALL();        //有trace标签
    2082      ALOGV("Surface::setBuffersDimensions");  //有log
    2091      mReqWidth = width;
    2092      mReqHeight = height;
    2093      return NO_ERROR;
    2094  }
    

    对应其他模块调用:native_window_set_buffers_dimensions

    ️ mUserWidth/mUserHeight
    Surface::setBuffersUserDimensions
    对应其他模块调用:native_window_set_buffers_user_dimensions
    可以看到和req的有点类似,使用时二者选1,首选req的:

    157 uint32_t reqHeight = mReqHeight ? mReqHeight : mUserHeight; // in allocateBuffers()
    554 dequeueInput->height = mReqHeight ? mReqHeight : mUserHeight; //in getDequeueBufferInputLocked()
    

    query时查询方式:

    1234              case NATIVE_WINDOW_DEFAULT_WIDTH:
    1235                  *value = static_cast<int>(
    1236                          mUserWidth ? mUserWidth : mDefaultWidth);
    1237                  return NO_ERROR;
    1238              case NATIVE_WINDOW_DEFAULT_HEIGHT:
    1239                  *value = static_cast<int>(
    1240                          mUserHeight ? mUserHeight : mDefaultHeight);
    1241                  return NO_ERROR;
    

    一般user的很少设置,目前没有碰到过这类问题。

    ️mDefaultWidth/mDefaultHeight
    来源于BufferQueue中queueBuffer,取自BufferQueueCore。
    1029 output->width = mCore->mDefaultWidth;
    1030 output->height = mCore->mDefaultHeight;

    ️mReqFormat
    Surface::setBuffersFormat(PixelFormat format)
    对应其他模块调用:native_window_set_buffers_format

    ️mReqUsage
    Surface::setUsage(uint64_t reqUsage)
    对应其他模块调用:native_window_set_usage

    二.BLASTBufferQueue

    147  BLASTBufferQueue::BLASTBufferQueue(const std::string& name, bool updateDestinationFrame) {
    155      createBufferQueue(&mProducer, &mConsumer);  //保存起来
    156      // since the adapter is in the client process, set dequeue timeout
    157      // explicitly so that dequeueBuffer will block
    158      mProducer->setDequeueTimeout(std::numeric_limits<int64_t>::max());//那么mDequeueBufferCannotBlock就不会true了
    159  
    160      // safe default, most producers are expected to override this
    161      mProducer->setMaxDequeuedBufferCount(2);     //设置dequeuecount=2
    162      mBufferItemConsumer = new BLASTBufferItemConsumer(mConsumer,
    163                                                        GraphicBuffer::USAGE_HW_COMPOSER |
    164                                                                GraphicBuffer::USAGE_HW_TEXTURE,
    165                                                        1, false, this);  //有usage哦!
    166      static std::atomic<uint32_t> nextId = 0;
    167      mProducerId = nextId++;
    168      mName = name + "#" + std::to_string(mProducerId);
    169      auto consumerName = mName + "(BLAST Consumer)" + std::to_string(mProducerId);
    170      mQueuedBufferTrace = "QueuedBuffer - " + mName + "BLAST#" + std::to_string(mProducerId);//perfetto名字
    171      mBufferItemConsumer->setName(String8(consumerName.c_str()));  //设置consumerName
    172      mBufferItemConsumer->setFrameAvailableListener(this);
    173  
    174      ComposerServiceAIDL::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers);//高刷一般2个,低刷1个
    175      mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBuffers);  //设置acquirecount
    176      mCurrentMaxAcquiredBufferCount = mMaxAcquiredBuffers;
    
    1133  void BLASTBufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
    1134                                           sp<IGraphicBufferConsumer>* outConsumer) {
    1138      sp<BufferQueueCore> core(new BufferQueueCore());
    1141      sp<IGraphicBufferProducer> producer(new BBQBufferQueueProducer(core, this));
    1145      sp<BufferQueueConsumer> consumer(new BufferQueueConsumer(core));
    1146      consumer->setAllowExtraAcquire(true);
    1150      *outProducer = producer;
    1151      *outConsumer = consumer;
    1152  }
    

    可以看出,和普通BufferQueue的区别是producer换成了BBQBufferQueueProducer,多调用了setAllowExtraAcquire函数。
    看下继承关系就一目了然了:

    1081  class BBQBufferQueueProducer : public BufferQueueProducer {
    1082  public:
    1083      BBQBufferQueueProducer(const sp<BufferQueueCore>& core, wp<BLASTBufferQueue> bbq)
    1084            : BufferQueueProducer(core, false /* consumerIsSurfaceFlinger*/),  //可以看到此处为false
    1085              mBLASTBufferQueue(std::move(bbq)) {}
    

    为什么consumerIsSurfaceFlinger为false呢?
    我们知道从BLASTBufferQueue出现后buffer的dequeue/queue动作都发生在APP进程了,之前都是发生在SF进程,所以可想而知,此变量就应该是false的。目前代码中好像没有看到有设置true的地方。

    再回到BLASTBufferQueue 中看下BLASTBufferItemConsumer

    38  class BLASTBufferItemConsumer : public BufferItemConsumer {
    39  public:
    40      BLASTBufferItemConsumer(const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
    41                              int bufferCount, bool controlledByApp, wp<BLASTBufferQueue> bbq)
    42            : BufferItemConsumer(consumer, consumerUsage, bufferCount, controlledByApp),
    43              mBLASTBufferQueue(std::move(bbq)),
    
    class BufferItemConsumer: public ConsumerBase
    35  BufferItemConsumer::BufferItemConsumer(
    36          const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
    37          int bufferCount, bool controlledByApp) :
    38      ConsumerBase(consumer, controlledByApp) //构建consumerBase
    39  {
    40      status_t err = mConsumer->setConsumerUsageBits(consumerUsage);//设置BufferQueueConsumer的usage
    43      if (bufferCount != DEFAULT_MAX_BUFFERS) {
    44          err = mConsumer->setMaxAcquiredBufferCount(bufferCount);//设置acquireBufferCount,后面会被覆盖重写
    47      }
    48  }
    
    58  ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
    59          mAbandoned(false),
    60          mConsumer(bufferQueue),
    61          mPrevFinalReleaseFence(Fence::NO_FENCE) {
    62      // Choose a name using the PID and a process-unique ID.
    63      mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
    64  
    69      wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
    70      sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
    71  
    72      status_t err = mConsumer->consumerConnect(proxy, controlledByApp);  //connect,设置consumerControlByApp为false
    73      if (err != NO_ERROR) {
    74          CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
    75                  strerror(-err), err);
    76      } else {
    77          mConsumer->setConsumerName(mName);  //setName,后面会被重写
    78      }
    79  }
    

    以上mConsumer均为BufferQueueConsumer对象!!!!;
    usage为GraphicBuffer::USAGE_HW_COMPOSER | GraphicBuffer::USAGE_HW_TEXTURE;bufferCount为1;controlledByApp为false。

    再回到BLASTBufferQueue中可以看到后面又重新调用
    setName、setMaxAcquiredBufferCount,覆盖了之前new BLASTBufferItemConsumer阶段覆的值,但是usage没有重新赋值。

    再看看对应的Surface:

    953  sp<Surface> BLASTBufferQueue::getSurface(bool includeSurfaceControlHandle) {
    954      std::lock_guard _lock{mMutex};
    955      sp<IBinder> scHandle = nullptr;
    956      if (includeSurfaceControlHandle && mSurfaceControl) {
    957          scHandle = mSurfaceControl->getHandle();
    958      }
    959      return new BBQSurface(mProducer, true, scHandle, this);//记住此处mProducerControlledByApp为true哦。
    960  }
    
    873  class BBQSurface : public Surface {
    880      BBQSurface(const sp<IGraphicBufferProducer>& igbp, bool controlledByApp,
    881                 const sp<IBinder>& scHandle, const sp<BLASTBufferQueue>& bbq)
    882            : Surface(igbp, controlledByApp, scHandle), mBbq(bbq) {}
    
    884      void allocateBuffers() override {
    885          uint32_t reqWidth = mReqWidth ? mReqWidth : mUserWidth;
    886          uint32_t reqHeight = mReqHeight ? mReqHeight : mUserHeight;
    887          auto gbp = getIGraphicBufferProducer();
    888          std::thread ([reqWidth, reqHeight, gbp=getIGraphicBufferProducer(),
    889                        reqFormat=mReqFormat, reqUsage=mReqUsage] () {
    890              gbp->allocateBuffers(reqWidth, reqHeight,
    891                                   reqFormat, reqUsage);  //起单独线程做
    892  
    893          }).detach();
    894      }
    
    80      sp<IGraphicBufferProducer> getIGraphicBufferProducer() const {
    81          return mProducer;  //拿BBQBufferQueueProducer
    82      }
    

    可以看出来通过拿到BBQSurface来进行buffer申请,而且是启用单独的线程做分配buffer的动作,从perfetto中可以看出来哦。
    allocateBuffers在APP冷启动的时候调用,如果后面width/height/usage/format等变化会重新dequeueBuffer,如:旋转。

    相关文章

      网友评论

          本文标题:BufferQueue介绍

          本文链接:https://www.haomeiwen.com/subject/drgwcjtx.html