当前位置:   article > 正文

Android4.2.2 SurfaceFlinger之图形缓存区申请与分配dequeueBuffer_怎么debug bufferqueue和sufaceflinger的

怎么debug bufferqueue和sufaceflinger的

本文均属自己阅读源码的点滴总结,转账请注明出处谢谢。

欢迎和大家交流。qq:1037701636 email:gzzaigcn2012@gmail.com

Android源码版本Version:4.2.2; 硬件平台 全志A31

 

接着前面的BootAnimation的启动过程,可以看到内部会涉及很多OpenGL ES的相关操作,OpenGL ES通过之前创建的具备有SurfaceTexture等的Surface类,来操作远端的SF来完成相关的图像渲染。

这里主要涉及到ANativeWindow的2个核心回调函数,OpenGL ES在应用层的eglSwapBuffers就是调用了QueueBuffer和DequeueBuffer两个函数来完成的。

在介绍上面两个函数的实现时,有必要把BufferQueue这个类再提出来。他是由应用程序在客户端通过和服务端的Client交互,提交消息给SurfaceFlinger处理时创建的Layer对象时在SurfaceTextureLayer类构造中创建的:

BufferQueue中有一个成员变量BufferSlot mSlots[NUM_BUFFER_SLOTS];即一个BufferQueue实际上最大可以有32个Buffer,即一个应用程序申请的Surface在SF端的Layer可以有32个图像缓存区。而这32个图形缓存区都有上面的mSlots维护着,每个Buffer有以下几种可变的状态,由BufferState mBufferState维护:

分别是FREE,DEQUEUED,QUEUE,ACQUIRED这4个状态,分别是空闲,出列被填充数据,入列代表有了数据,最终将入列后有了图形数据的缓冲区进行渲染。

 

step1:先来看dequeueBuffer函数,可以理解为生产者,会用来申请Buffer并进行应用程序端的图像绘制。

  1. int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer,
  2. int* fenceFd) {
  3. ATRACE_CALL();
  4. ALOGV("SurfaceTextureClient::dequeueBuffer");
  5. Mutex::Autolock lock(mMutex);
  6. int buf = -1;
  7. int reqW = mReqWidth ? mReqWidth : mUserWidth;
  8. int reqH = mReqHeight ? mReqHeight : mUserHeight;
  9. sp<Fence> fence;
  10. status_t result = mSurfaceTexture->dequeueBuffer(&buf, fence, reqW, reqH,
  11. mReqFormat, mReqUsage);//调用远程的BnSurfaceTexture来完成BufferQueue的操作
  12. if (result < 0) {
  13. ALOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer(%d, %d, %d, %d)"
  14. "failed: %d", mReqWidth, mReqHeight, mReqFormat, mReqUsage,
  15. result);
  16. return result;
  17. }
  18. sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);//对应到客户端的mSlots中,buf为SF侧分配到的id
  19. if (result & ISurfaceTexture::RELEASE_ALL_BUFFERS) {
  20. freeAllBuffers();
  21. }
  22. if ((result & ISurfaceTexture::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
  23. result = mSurfaceTexture->requestBuffer(buf, &gbuf);//返回的result是在重新分配后找到对应的缓冲区信息,需要进行request
  24. if (result != NO_ERROR) {
  25. ALOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed: %d",
  26. result);
  27. return result;
  28. }
  29. }
  30. if (fence.get()) {
  31. *fenceFd = fence->dup();
  32. if (*fenceFd == -1) {
  33. ALOGE("dequeueBuffer: error duping fence: %d", errno);
  34. // dup() should never fail; something is badly wrong. Soldier on
  35. // and hope for the best; the worst that should happen is some
  36. // visible corruption that lasts until the next frame.
  37. }
  38. } else {
  39. *fenceFd = -1;
  40. }
  41. *buffer = gbuf.get();//GraphicBuffer
  42. return OK;
  43. }

上面函数的核心在于status_t result = mSurfaceTexture->dequeueBuffer(&buf, fence, reqW, reqH,mReqFormat, mReqUsage);那么这个应用层即所谓的客户端侧的mSurfaceTexture是什么呢?这个其实就是应用程序侧在创建了SurfaceControl后获得的,即所谓的BufferQueue的Binder匿名代理(继承了BnSurfaceTexture而已)BpSurfaceTexture。从而这样建立起来的Binder通信机制,使得在ANativeWindow将最终的Buffer处理都扔回给了之前由SurfaceFlinger创建的Layer,SurfaceTexture对象中去了。

 

step2:现在回到BufferQueue去吧,看看是如何做调用的。

 通过BpSurfaceTexture来到BnSurfaceTexture,如下:

因为BufferQueue继承了BnSurfaceTexture后,故调用BufferQueue的成员函数queueBuffer,其实也就是SurfaceFlinger再操纵着这些个Buffer。

  1. case DEQUEUE_BUFFER: {//图像缓冲区申请
  2. CHECK_INTERFACE(ISurfaceTexture, data, reply);
  3. uint32_t w = data.readInt32();
  4. uint32_t h = data.readInt32();
  5. uint32_t format = data.readInt32();
  6. uint32_t usage = data.readInt32();
  7. int buf;
  8. sp<Fence> fence;
  9. int result = dequeueBuffer(&buf, fence, w, h, format, usage);
  10. bool hasFence = fence.get() && fence->isValid();
  11. reply->writeInt32(buf);
  12. reply->writeInt32(hasFence);
  13. if (hasFence) {
  14. reply->write(*fence.get());
  15. }
  16. reply->writeInt32(result);
  17. return NO_ERROR;
  18. } break;
  1. status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence,
  2. uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
  3. {
  4. ......
  5. { // Scope for the lock
  6. Mutex::Autolock lock(mMutex);
  7. if (format == 0) {
  8. format = mDefaultBufferFormat;
  9. }
  10. // turn on usage bits the consumer requested
  11. usage |= mConsumerUsageBits;
  12. int found = -1;
  13. int dequeuedCount = 0;
  14. bool tryAgain = true;
  15. while (tryAgain) {
  16. if (mAbandoned) {
  17. ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
  18. return NO_INIT;
  19. }
  20. const int maxBufferCount = getMaxBufferCountLocked();
  21. // Free up any buffers that are in slots beyond the max buffer
  22. // count.
  23. for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {//寻找所有的slots
  24. assert(mSlots[i].mBufferState == BufferSlot::FREE);
  25. if (mSlots[i].mGraphicBuffer != NULL) {
  26. freeBufferLocked(i);
  27. returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
  28. }
  29. }
  30. // look for a free buffer to give to the client
  31. found = INVALID_BUFFER_SLOT;
  32. dequeuedCount = 0;
  33. for (int i = 0; i < maxBufferCount; i++) {
  34. const int state = mSlots[i].mBufferState;
  35. if (state == BufferSlot::DEQUEUED) {
  36. dequeuedCount++;//统计已经出列的buffer个数
  37. }
  38. if (state == BufferSlot::FREE) {
  39. /* We return the oldest of the free buffers to avoid
  40. * stalling the producer if possible. This is because
  41. * the consumer may still have pending reads of the
  42. * buffers in flight.
  43. */
  44. if ((found < 0) ||
  45. mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
  46. found = i;//寻址free里面帧号最小的位置Slot
  47. }
  48. }
  49. }
  50. // clients are not allowed to dequeue more than one buffer
  51. // if they didn't set a buffer count.
  52. if (!mOverrideMaxBufferCount && dequeuedCount) {
  53. ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
  54. "setting the buffer count");
  55. return -EINVAL;
  56. }
  57. // See whether a buffer has been queued since the last
  58. // setBufferCount so we know whether to perform the min undequeued
  59. // buffers check below.
  60. if (mBufferHasBeenQueued) {
  61. // make sure the client is not trying to dequeue more buffers
  62. // than allowed.
  63. const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1);
  64. const int minUndequeuedCount = getMinUndequeuedBufferCountLocked();
  65. if (newUndequeuedCount < minUndequeuedCount) {
  66. ST_LOGE("dequeueBuffer: min undequeued buffer count (%d) "
  67. "exceeded (dequeued=%d undequeudCount=%d)",
  68. minUndequeuedCount, dequeuedCount,
  69. newUndequeuedCount);
  70. return -EBUSY;
  71. }
  72. }
  73. // If no buffer is found, wait for a buffer to be released or for
  74. // the max buffer count to change.
  75. tryAgain = found == INVALID_BUFFER_SLOT;
  76. if (tryAgain) {
  77. for (int i = 0; i < maxBufferCount; i++) {
  78. BQ_LOGD("#dequeueBuffer tryAgain buf:%d state:%d", i, mSlots[i].mBufferState);
  79. }
  80. mDequeueCondition.wait(mMutex);//等待有buffer的释放
  81. }
  82. }
  83. if (found == INVALID_BUFFER_SLOT) {
  84. // This should not happen.
  85. ST_LOGE("dequeueBuffer: no available buffer slots");
  86. return -EBUSY;
  87. }
  88. const int buf = found;
  89. *outBuf = found;//找到可以使用的buffer,记录到outBuf里面
  90. ATRACE_BUFFER_INDEX(buf);
  91. const bool useDefaultSize = !w && !h;
  92. if (useDefaultSize) {
  93. // use the default size
  94. w = mDefaultWidth;
  95. h = mDefaultHeight;
  96. }
  97. // buffer is now in DEQUEUED (but can also be current at the same time,
  98. // if we're in synchronous mode)
  99. mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
  100. const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
  101. if ((buffer == NULL) ||
  102. (uint32_t(buffer->width) != w) ||
  103. (uint32_t(buffer->height) != h) ||
  104. (uint32_t(buffer->format) != format) ||
  105. ((uint32_t(buffer->usage) & usage) != usage))//当前找到的slots中的buffer没有缓冲区或者相关属性不匹配则从新申请
  106. {
  107. mSlots[buf].mAcquireCalled = false;
  108. mSlots[buf].mGraphicBuffer = NULL;
  109. mSlots[buf].mRequestBufferCalled = false;
  110. mSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
  111. mSlots[buf].mFence.clear();
  112. mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
  113. returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;//重新申请
  114. }
  115. dpy = mSlots[buf].mEglDisplay;
  116. eglFence = mSlots[buf].mEglFence;
  117. outFence = mSlots[buf].mFence;
  118. mSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
  119. mSlots[buf].mFence.clear();
  120. } // end lock scope
  121. if (returnFlags & ISurfaceTexture::BUFFER_NEEDS_REALLOCATION) {
  122. status_t error;
  123. mGraphicBufferAlloc->acquireBufferReferenceSlot(*outBuf);
  124. sp<GraphicBuffer> graphicBuffer(
  125. mGraphicBufferAlloc->createGraphicBuffer(
  126. w, h, format, usage, &error));//重新请求SF端申请一个buffer
  127. if (graphicBuffer == 0) {
  128. ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
  129. "failed");
  130. return error;
  131. }
  132. { // Scope for the lock
  133. Mutex::Autolock lock(mMutex);
  134. if (mAbandoned) {
  135. ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
  136. return NO_INIT;
  137. }
  138. mSlots[*outBuf].mGraphicBuffer = graphicBuffer;//申请的buffer加入到当前的mSlots的成员mGraphicBuffer中
  139. }
  140. }
  141. if (eglFence != EGL_NO_SYNC_KHR) {
  142. EGLint result = eglClientWaitSyncKHR(dpy, eglFence, 0, 1000000000);
  143. // If something goes wrong, log the error, but return the buffer without
  144. // synchronizing access to it. It's too late at this point to abort the
  145. // dequeue operation.
  146. if (result == EGL_FALSE) {
  147. ST_LOGE("dequeueBuffer: error waiting for fence: %#x", eglGetError());
  148. } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
  149. ST_LOGE("dequeueBuffer: timeout waiting for fence");
  150. }
  151. eglDestroySyncKHR(dpy, eglFence);
  152. }
  153. BQ_LOGD("#dequeueBuffer: returning slot=%d buf=%p flags=%#x %p", *outBuf,
  154. mSlots[*outBuf].mGraphicBuffer->handle, returnFlags, this);
  155. return returnFlags;
  156. }

DeQueueuffer的内容比较多,我们分以下几个Step来进行分析。

 

step1:清空超过最大需求的Buffer

  1. // Free up any buffers that are in slots beyond the max buffer
  2. // count.
  3. for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {//寻找所有的slots
  4. assert(mSlots[i].mBufferState == BufferSlot::FREE);
  5. if (mSlots[i].mGraphicBuffer != NULL) {
  6. freeBufferLocked(i);
  7. returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
  8. }
  9. }

这里假设maxBufferCount = 2,对其余的Buffer进行图形缓存区的清除。

 

step2:查找一个合格的Free了的Buffer

  1. found = INVALID_BUFFER_SLOT;
  2. dequeuedCount = 0;
  3. for (int i = 0; i < maxBufferCount; i++) {
  4. const int state = mSlots[i].mBufferState;
  5. if (state == BufferSlot::DEQUEUED) {
  6. dequeuedCount++;//统计已经出列的buffer个数
  7. }
  8. if (state == BufferSlot::FREE) {
  9. /* We return the oldest of the free buffers to avoid
  10. * stalling the producer if possible. This is because
  11. * the consumer may still have pending reads of the
  12. * buffers in flight.
  13. */
  14. if ((found < 0) ||
  15. mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
  16. found = i;//寻址free里面帧号最小的位置Slot
  17. }
  18. }
  19. }

这里可以看到只执行2次循环,因为只需要2个图形缓存区而已。这里找到FREE的BufferSlot后,还需要查看当前的buffer所属于的帧号,这里found最终被定义为帧号小的BufferSlot.

 

step3:找到对应的BufferSlot的索index后,赋值给返回的outbuf参数,并切换当前状态从FREE到DEQUEUED。

 

step4: 实际图形缓存区的分配和申请,是实际DEqueuebuffer的重点所在

  1. mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
  2. const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
  3. if ((buffer == NULL) ||
  4. (uint32_t(buffer->width) != w) ||
  5. (uint32_t(buffer->height) != h) ||
  6. (uint32_t(buffer->format) != format) ||
  7. ((uint32_t(buffer->usage) & usage) != usage))//当前找到的slots中的buffer没有缓冲区或者相关属性不匹配则从新申请
  8. {
  9. mSlots[buf].mAcquireCalled = false;
  10. mSlots[buf].mGraphicBuffer = NULL;
  11. mSlots[buf].mRequestBufferCalled = false;
  12. mSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
  13. mSlots[buf].mFence.clear();
  14. mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
  15. returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;//重新申请
  16. }
  17. dpy = mSlots[buf].mEglDisplay;
  18. eglFence = mSlots[buf].mEglFence;
  19. outFence = mSlots[buf].mFence;
  20. mSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
  21. mSlots[buf].mFence.clear();
  22. } // end lock scope
  23. if (returnFlags & ISurfaceTexture::BUFFER_NEEDS_REALLOCATION) {
  24. status_t error;
  25. mGraphicBufferAlloc->acquireBufferReferenceSlot(*outBuf);
  26. sp<GraphicBuffer> graphicBuffer(
  27. mGraphicBufferAlloc->createGraphicBuffer(
  28. w, h, format, usage, &error));//重新请求SF端申请一个buffer
  29. if (graphicBuffer == 0) {
  30. ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
  31. "failed");
  32. return error;
  33. }
  34. { // Scope for the lock
  35. Mutex::Autolock lock(mMutex);
  36. if (mAbandoned) {
  37. ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
  38. return NO_INIT;
  39. }
  40. mSlots[*outBuf].mGraphicBuffer = graphicBuffer;//申请的buffer加入到当前的mSlots的成员mGraphicBuffer中
  41. }
  42. }

这里都是在对查找到的BufferSlot进行初始化操作,可以看到只要buffer(sp<GraphicBuffer> mGraphicBuffer;是一个图形缓存类),或者需要的图形缓存的大小、格式、使用形式等与当前的BufferSlot不一样就有必要重新分配图形缓存了。

 

step6:图形缓存申请的实现mGraphicBufferAlloc->createGraphicBuffer()

那么这个函数是如何实现的呢?回来看看BufferQueue当初创建的时候把,在BufferQueue的构造函数里面,有一个图形缓存区分配的成员对象,他最终是由SurfaceFlinger来实现的。

  1. sp<ISurfaceComposer> composer(ComposerService::getComposerService());
  2. mGraphicBufferAlloc = composer->createGraphicBufferAlloc();//创建GraphicBuffer
  1.     virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc()
  2.     {
  3.         uint32_t n;
  4.         Parcel data, reply;
  5.         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
  6.         remote()->transact(BnSurfaceComposer::CREATE_GRAPHIC_BUFFER_ALLOC, data, &reply);//
  7.         return interface_cast<IGraphicBufferAlloc>(reply.readStrongBinder());//BpGraphicBufferAlloc
  8.     }
  1. status_t BnSurfaceComposer::onTransact(//内部函数由继承类SF来完成
  2.     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
  3. {        case CREATE_GRAPHIC_BUFFER_ALLOC: {
  4.             CHECK_INTERFACE(ISurfaceComposer, data, reply);
  5.             sp<IBinder> b = createGraphicBufferAlloc()->asBinder();//创建图像缓存
  6.             reply->writeStrongBinder(b);
  7.         } break;
  1. sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
  2. {
  3. sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());//图形缓存的申请
  4. return gba;
  5. }

在上述典型的Binder交互完成后,SF在服务端侧新建了一个图形缓存分配类对象后,将新建的gba写入Binder驱动,返回到客户端益BpBinder的形式存在
实际返回的是BpGraphicBufferAlloc的Binder代理,而

 

因此这里通过这个匿名的Binder代理,去请求BnGraphicBufferAlloc来完成

  1. status_t BnGraphicBufferAlloc::onTransact(
  2. uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
  3. {
  4. case CREATE_GRAPHIC_BUFFER: {
  5. CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);
  6. uint32_t w = data.readInt32();
  7. uint32_t h = data.readInt32();
  8. PixelFormat format = data.readInt32();
  9. uint32_t usage = data.readInt32();
  10. status_t error;
  11. sp<GraphicBuffer> result =
  12. createGraphicBuffer(w, h, format, usage, &error);
  13. reply->writeInt32(error);
  14. if (result != 0) {
  15. reply->write(*result);
  16. // We add a BufferReference to this parcel to make sure the
  17. // buffer stays alive until the GraphicBuffer object on
  18. // the other side has been created.
  19. // This is needed so that the buffer handle can be
  20. // registered before the buffer is destroyed on implementations
  21. // that do not use file-descriptors to track their buffers.
  22. reply->writeStrongBinder( new BufferReference(result) );
  23. }
  24. return NO_ERROR;
  25. } break;
  26. ....
  27. }

而之前存入的匿名binder对就是上述SF新建的GraphicBufferAlloc gba;而该类也正好继承了BpGraphicBufferAlloc这个对象,故有GraphicBufferAlloc::createGraphicBuffer来实现:

  1. sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h,
  2. PixelFormat format, uint32_t usage, status_t* error) {
  3. sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
  4. status_t err = graphicBuffer->initCheck();
  5. *error = err;
  6. if (err != 0 || graphicBuffer->handle == 0) {
  7. if (err == NO_MEMORY) {
  8. GraphicBuffer::dumpAllocationsToSystemLog();
  9. }
  10. ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "
  11. "failed (%s), handle=%p",
  12. w, h, strerror(-err), graphicBuffer->handle);
  13. return 0;
  14. }
  15. return graphicBuffer;
  16. }

这里看到了一个图像缓存类GraphicBuffer,在这里所谓的图像缓存创建就是构造了这个对象

  1. class GraphicBuffer
  2. : public ANativeObjectBase<
  3. ANativeWindowBuffer,
  4. GraphicBuffer,
  5. LightRefBase<GraphicBuffer> >, public Flattenable
  6. {

该类继承了本地窗口缓存ANativeWindowBuffer;

  1. GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
  2. PixelFormat reqFormat, uint32_t reqUsage)
  3. : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
  4. mInitCheck(NO_ERROR), mIndex(-1)
  5. {
  6. width =
  7. height =
  8. stride =
  9. format =
  10. usage = 0;
  11. handle = NULL;
  12. mInitCheck = initSize(w, h, reqFormat, reqUsage);//内部实现缓存的申请
  13. }

GraphicBuffer有一个mBufferMapper对象,缓存的映射,看看他的初始化:

  1. class GraphicBufferMapper : public Singleton<GraphicBufferMapper>
  2. {
  3. public:
  4. static inline GraphicBufferMapper& get() { return getInstance(); }
  5. status_t registerBuffer(buffer_handle_t handle);
  6. status_t unregisterBuffer(buffer_handle_t handle);
  7. status_t lock(buffer_handle_t handle,
  8. int usage, const Rect& bounds, void** vaddr);
  9. status_t unlock(buffer_handle_t handle);
  10. // dumps information about the mapping of this handle
  11. void dump(buffer_handle_t handle);
  12. status_t get_phy_addess(buffer_handle_t handle, void** vaddr);
  13. private:
  14. friend class Singleton<GraphicBufferMapper>;
  15. GraphicBufferMapper();
  16. gralloc_module_t const *mAllocMod;
  17. };

这个的get()返回的是一个GraphicBufferMapper对象,且为单列模式。

 

step7: 该对象将来完成图形缓存的映射,也就是图形缓存区内存映射到应用程序。看她的构造函数:

  1. GraphicBufferMapper::GraphicBufferMapper()
  2. : mAllocMod(0)
  3. {
  4. hw_module_t const* module;
  5. int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
  6. ALOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
  7. if (err == 0) {
  8. mAllocMod = (gralloc_module_t const *)module;
  9. }
  10. }

很清楚这个是获取FrameBuffer的HAL模块gralloc的handle到module中,重点来看构造函数里的initSize函数:

  1. status_t GraphicBuffer::initSize(uint32_t w, uint32_t h, PixelFormat format,
  2. uint32_t reqUsage)
  3. {
  4. GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
  5. status_t err = allocator.alloc(w, h, format, reqUsage, &handle, &stride);//图像缓冲区的分配
  6. if (err == NO_ERROR) {
  7. this->width = w;
  8. this->height = h;
  9. this->format = format;
  10. this->usage = reqUsage;
  11. }
  12. return err;
  13. }

这里又出现了一个图形缓存分配器的类,类似于GraphicBufferMapper函数,来看他的构造过程:

  1. GraphicBufferAllocator::GraphicBufferAllocator()
  2. : mAllocDev(0)
  3. {
  4. hw_module_t const* module;
  5. int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);//调用HAL层
  6. ALOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
  7. if (err == 0) {
  8. gralloc_open(module, &mAllocDev);//获得buffer分配模块mAllocDev,使用的是GPU这个模块ID
  9. }
  10. }

这里是打开了HAL层的gralloc模块到mAllocDev中,调用alloc函数,看看他完成了什么?

  1. status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format,
  2. int usage, buffer_handle_t* handle, int32_t* stride)
  3. {
  4. ......
  5. BufferLiberatorThread::maybeWaitForLiberation();
  6. err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride);
  7. if (err != NO_ERROR) {
  8. ALOGW("WOW! gralloc alloc failed, waiting for pending frees!");
  9. BufferLiberatorThread::waitForLiberation();
  10. err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride);
  11. }
  12. ALOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)",
  13. w, h, format, usage, err, strerror(-err));
  14. if (err == NO_ERROR) {
  15. Mutex::Autolock _l(sLock);
  16. KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
  17. int bpp = bytesPerPixel(format);
  18. if (bpp < 0) {
  19. // probably a HAL custom format. in any case, we don't know
  20. // what its pixel size is.
  21. bpp = 0;
  22. }
  23. alloc_rec_t rec;
  24. rec.w = w;
  25. rec.h = h;
  26. rec.s = *stride;
  27. rec.format = format;
  28. rec.usage = usage;
  29. rec.size = h * stride[0] * bpp;
  30. list.add(*handle, rec);
  31. }
  32. return err;
  33. }

这里是调用了Gralloc模块的alloc回调函数来完成对内存图形缓存区的申请。

 

step8:回到HAL层看看gralloc模块做了什么?

  1. static int gralloc_alloc(alloc_device_t* dev,
  2. int w, int h, int format, int usage,
  3. buffer_handle_t* pHandle, int* pStride)
  4. {
  5. if (!pHandle || !pStride)
  6. return -EINVAL;
  7. size_t size, stride;
  8. int align = 4;
  9. int bpp = 0;
  10. switch (format) {
  11. case HAL_PIXEL_FORMAT_RGBA_8888:
  12. case HAL_PIXEL_FORMAT_RGBX_8888:
  13. case HAL_PIXEL_FORMAT_BGRA_8888:
  14. bpp = 4;
  15. break;
  16. case HAL_PIXEL_FORMAT_RGB_888:
  17. bpp = 3;
  18. break;
  19. case HAL_PIXEL_FORMAT_RGB_565:
  20. case HAL_PIXEL_FORMAT_RGBA_5551:
  21. case HAL_PIXEL_FORMAT_RGBA_4444:
  22. case HAL_PIXEL_FORMAT_RAW_SENSOR:
  23. bpp = 2;
  24. break;
  25. default:
  26. return -EINVAL;
  27. }
  28. size_t bpr = (w*bpp + (align-1)) & ~(align-1);
  29. size = bpr * h;
  30. stride = bpr / bpp;
  31. int err;
  32. if (usage & GRALLOC_USAGE_HW_FB) {
  33. err = gralloc_alloc_framebuffer(dev, size, usage, pHandle);//分配系统缓存帧
  34. } else {
  35. err = gralloc_alloc_buffer(dev, size, usage, pHandle);//分配的是内存缓存
  36. }
  37. if (err < 0) {
  38. return err;
  39. }
  40. *pStride = stride;
  41. return 0;
  42. }

这里看到usage有一种是硬件帧缓存,另一个是开辟单独的匿名内存块。当然数据直接写入FramerBuffer是最快的,但往往一个帧缓存是远远不够的,故而这里将还会创建匿名的pmem来作为图像缓冲区,但帧缓存只有一个。这里的buffer_handle_t *pHandle最终可以理解为是图形缓存在当前应用程序mmap后的用户空间地址。使得后续的图像渲染等直接对用户空间操作即可。

 

到这里我们返回到了SurfaceTextureClient::dequeueBuffer函数中去,完成mSurfaceTexture->dequeueBuffer函数返回后,可以看到如果当前的在服务端从新分配了图像缓存后ISurfaceTexture::BUFFER_NEEDS_REALLOCATION,将调用requestBuffer函数,来看看为何还要这么处理?

依旧是BpSurfaceTexture来处理

  1. virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
  2. Parcel data, reply;
  3. data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
  4. data.writeInt32(bufferIdx);
  5. status_t result =remote()->transact(REQUEST_BUFFER, data, &reply);
  6. if (result != NO_ERROR) {
  7. return result;
  8. }
  9. bool nonNull = reply.readInt32();
  10. if (nonNull) {
  11. *buf = new GraphicBuffer();//应用程序侧也新建一个图形缓存
  12. reply.read(**buf);//buf生成
  13. }
  14. result = reply.readInt32();
  15. return result;
  16. }

对应在BnSurfaceTexture侧的响应如下:

  1. status_t BnSurfaceTexture::onTransact(
  2. uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
  3. {
  4. switch(code) {
  5. case REQUEST_BUFFER: {
  6. CHECK_INTERFACE(ISurfaceTexture, data, reply);
  7. int bufferIdx = data.readInt32();
  8. sp<GraphicBuffer> buffer;
  9. int result = requestBuffer(bufferIdx, &buffer);
  10. reply->writeInt32(buffer != 0);
  11. if (buffer != 0) {
  12. reply->write(*buffer);
  13. }
  14. reply->writeInt32(result);
  15. return NO_ERROR;
  16. } break;

通过客户端传递过来的数据,即一个buffer的索引id,在BufferQueue里调用requestBuffer函数

  1. status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
  2. int maxBufferCount = getMaxBufferCountLocked();
  3. if (slot < 0 || maxBufferCount <= slot) {
  4. ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
  5. maxBufferCount, slot);
  6. return BAD_VALUE;
  7. } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
  8. // XXX: I vaguely recall there was some reason this can be valid, but
  9. // for the life of me I can't recall under what circumstances that's
  10. // the case.
  11. ST_LOGE("requestBuffer: slot %d is not owned by the client (state=%d)",
  12. slot, mSlots[slot].mBufferState);
  13. return BAD_VALUE;
  14. }
  15. mSlots[slot].mRequestBufferCalled = true;
  16. *buf = mSlots[slot].mGraphicBuffer;
  17. return NO_ERROR;
  18. }

上述函数通过这个buffer的索引值,找到对应的BufferSlot后,返回的是这个他维护着的服务端的sp<GraphicBuffer> mGraphicBuffer成员,这里有必要看下最终的                reply->write(*buffer);写入过程,他的实现如下:

  1. status_t Parcel::write(const Flattenable& val)
  2. { err = val.flatten(buf, len, fds, fd_count);//对buffer进行写入调用,GraphicBuffer::flatten
  3. .............
  4. }

之所以哪呢过将这个buffer写入在于GraphicBuffer的特殊性,该类继承了一个Flattenable类,最终调用下面的函数

  1. status_t GraphicBuffer::flatten(void* buffer, size_t size,//发送端打包
  2. int fds[], size_t count) const
  3. {
  4. size_t sizeNeeded = GraphicBuffer::getFlattenedSize();
  5. if (size < sizeNeeded) return NO_MEMORY;
  6. size_t fdCountNeeded = GraphicBuffer::getFdCount();
  7. if (count < fdCountNeeded) return NO_MEMORY;
  8. int* buf = static_cast<int*>(buffer);
  9. buf[0] = 'GBFR';
  10. buf[1] = width;
  11. buf[2] = height;
  12. buf[3] = stride;
  13. buf[4] = format;
  14. buf[5] = usage;
  15. buf[6] = 0;
  16. buf[7] = 0;
  17. if (handle) {
  18. buf[6] = handle->numFds;
  19. buf[7] = handle->numInts;
  20. native_handle_t const* const h = handle;
  21. memcpy(fds, h->data, h->numFds*sizeof(int));
  22. memcpy(&buf[8], h->data + h->numFds, h->numInts*sizeof(int));
  23. }
  24. return NO_ERROR;
  25. }

上述函数将GraphicBuffer的信息初始化到buf数组里面,最终数据都写入到reply中返回。

而同样在requestbuffer的客户端处,是对接收到的数据的解析,解析使用下面的过程实现:

  1. BpSurfaceTexture(const sp<IBinder>& impl)
  2. : BpInterface<ISurfaceTexture>(impl)
  3. {
  4. }
  5. virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
  6. Parcel data, reply;
  7. data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
  8. data.writeInt32(bufferIdx);
  9. status_t result =remote()->transact(REQUEST_BUFFER, data, &reply);
  10. if (result != NO_ERROR) {
  11. return result;
  12. }
  13. bool nonNull = reply.readInt32();
  14. if (nonNull) {
  15. *buf = new GraphicBuffer();//应用程序侧也新建一个图形缓存
  16. reply.read(**buf);//buf生成
  17. }
  18. result = reply.readInt32();
  19. return result;
  20. }

首先是新建一个应用程序客户端侧的一个GraphicBuffer对象,然后利用服务端返回的reply信息填充并初始化GraphicBuffer

  1. status_t Parcel::read(Flattenable& val) const
  2. {
  3. // size
  4. if (err == NO_ERROR) {
  5. err = val.unflatten(buf, len, fds, fd_count);//解析出信息到buffer
  6. }
  7. ...
  8. }
  1. status_t GraphicBuffer::unflatten(void const* buffer, size_t size,
  2. int fds[], size_t count)//接收端解析
  3. {
  4. if (size < 8*sizeof(int)) return NO_MEMORY;
  5. int const* buf = static_cast<int const*>(buffer);
  6. if (buf[0] != 'GBFR') return BAD_TYPE;
  7. const size_t numFds = buf[6];
  8. const size_t numInts = buf[7];
  9. const size_t sizeNeeded = (8 + numInts) * sizeof(int);
  10. if (size < sizeNeeded) return NO_MEMORY;
  11. size_t fdCountNeeded = 0;
  12. if (count < fdCountNeeded) return NO_MEMORY;
  13. if (handle) {
  14. // free previous handle if any
  15. free_handle();
  16. }
  17. if (numFds || numInts) {
  18. width = buf[1];
  19. height = buf[2];
  20. stride = buf[3];
  21. format = buf[4];
  22. usage = buf[5];
  23. native_handle* h = native_handle_create(numFds, numInts);//创建本地的图像缓存buffer
  24. memcpy(h->data, fds, numFds*sizeof(int));//文件描述符
  25. memcpy(h->data + numFds, &buf[8], numInts*sizeof(int));//数据
  26. handle = h;
  27. } else {
  28. width = height = stride = format = usage = 0;
  29. handle = NULL;
  30. }
  31. mOwner = ownHandle;
  32. if (handle != 0) {
  33. status_t err = mBufferMapper.registerBuffer(handle);//buffer注册,即将这个图像缓存mmap映射到当前的用户进程
  34. if (err != NO_ERROR) {
  35. ALOGE("unflatten: registerBuffer failed: %s (%d)",
  36. strerror(-err), err);
  37. return err;
  38. }
  39. }
  40. return NO_ERROR;
  41. }

在flatten和unflatten函数其实就是为了满足Binder数据的通信协议Parcel而设计的(用于传输对象变量),在unflatten函数中完成了对数据的解析后获得了一个handle,利用这个handle进行了registerBuffer的操作。

  1. status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
  2. {
  3. ATRACE_CALL();
  4. status_t err;
  5. err = mAllocMod->registerBuffer(mAllocMod, handle);//Client端可以将指定的内存区域映射到自己的进程空间
  6. ALOGW_IF(err, "registerBuffer(%p) failed %d (%s)",
  7. handle, err, strerror(-err));
  8. return err;
  9. }

这里又回到了客户端侧的,的确这里很好奇的是在服务端侧也有过GraphicBuffer的存在,而客户端侧却还要创建一个GraphicBuffer,这个原因是什么呢?

来看看Gralloc模块对registerBuffer的实现吧:

  1. int gralloc_register_buffer(gralloc_module_t const* module,
  2. buffer_handle_t handle)
  3. {
  4. if (private_handle_t::validate(handle) < 0)
  5. return -EINVAL;
  6. // if this handle was created in this process, then we keep it as is.
  7. int err = 0;
  8. private_handle_t* hnd = (private_handle_t*)handle;
  9. if (hnd->pid != getpid()) {
  10. void *vaddr;
  11. err = gralloc_map(module, handle, &vaddr);
  12. }
  13. return err;
  14. }

调用gralloc模块中的gralloc_map完成mmap的相关操作:

  1. static int gralloc_map(gralloc_module_t const* module,
  2. buffer_handle_t handle,
  3. void** vaddr)
  4. {
  5. private_handle_t* hnd = (private_handle_t*)handle;
  6. if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
  7. size_t size = hnd->size;
  8. void* mappedAddress = mmap(0, size,
  9. PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);//将匿名共享内存mmap到用户空间
  10. if (mappedAddress == MAP_FAILED) {
  11. ALOGE("Could not mmap %s", strerror(errno));
  12. return -errno;
  13. }
  14. hnd->base = intptr_t(mappedAddress) + hnd->offset;
  15. //ALOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",
  16. // hnd->fd, hnd->offset, hnd->size, mappedAddress);
  17. }
  18. *vaddr = (void*)hnd->base;
  19. return 0;
  20. }

这里的逻辑应该是handle维护着映射到用户空间的虚拟地址,hnd->base就包含了这个信息,而hnd->fd应该是一个内存设备的描述符。最终这里就通过这个handle将服务端申请并分配的图形内存缓冲区(无论是帧缓存还是匿名的ashmem)共享到客户端,两者都以GrallocBuffer对象的形式存在。

 

到此为止分析基于OpenGL ES的ANativeWindow和ANativeWindowBuffer的dequeueBuffer的分析基本完成了,下面以2个简易的流程图来进行总结,方便自己理解,图1是OpenGL ES所需要的在应用层的Surface创建的一个过程,如果图片看不清,可以下载地址SurfaceFlinger应用端创建surface的过程图



 

  


 

图2: 图形缓存GraphicBuffer的申请与分配图
 

 

这里继续补充在应用程序侧和服务侧的GraphicBuffer,这两个图形缓存区的区别与联系:

1.在BufferQueue的构造函数中有mGraphicBufferAlloc = composer->createGraphicBufferAlloc(),显然是由SF进程来完成这个对象的创建的,故SF维护着mGraphicBufferAlloc这个匿名的本地Binder服务,并传递给BufferQueue维护。

2.BufferQueue中请求createGraphicBuffer时,还是有SF来完成,故缓存的实际创建还是有SF进程来完成的,由createGraphicBuffer里的new GraphicBuffer();在SF侧创建实际的图形缓存。

3.交给GraphicBufferAllocator来完成gralloc的图形缓存的申请并完成映射。分为gralloc_alloc_framebuffer和gralloc_alloc_buffer两种,前者是直接在帧缓存中分配出图像缓存,后者是直接申请一个匿名共享内存来做为图形缓存区。最终申请并完成映射到SF处的图像缓存以buffer_handle_t的类型维护着。

4.在服务端SF那里有了图像缓存后,应用端势必也需要有服务端图像缓冲区的信息,将实际的图像内存维护到应用侧的用户空间。这个过程是在requestBuffer来完成的:

实际是有GraphicBuffer来完成,其中GraphicBufferMapper来维护Gralloc模块的打开,以及gralloc_module_t回调registerBuffer。gralloc的registerBuffer实际就是用来用户空间注册缓存,而注册实际只是一个mmap的过程,映射到用户空间。

 

这样在内核中开辟的一个内存空间,在服务端被映射,在应用端也完成映射,故使得最终的操作都是同一块内存图形区域,建立了紧密的联系。

 


 

 

 


 


 

 


 


 


 

 


 

 


 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/899548
推荐阅读
相关标签
  

闽ICP备14008679号