Android SurfaceFlinger服务(八) ----- 图像的输出

匿名 (未验证) 提交于 2019-12-03 00:43:02

SurfaceFlinger合成后就进行图像的输出的工作。在图像输出时,存在硬件合成器与不存在的情况有些差别。软件合成时用到图像缓冲区生产者与消费者模型。首先来看看图像缓冲区的初始化。

void SurfaceFlinger::init() {     ALOGI(  "SurfaceFlinger‘s main thread ready to run. "             "Initializing graphics H/W...");      ......      // initialize our non-virtual displays     for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {         DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);         // set-up the displays that are already connected         if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {             // All non-virtual displays are currently considered secure.             bool isSecure = true;             createBuiltinDisplayLocked(type);             wp<IBinder> token = mBuiltinDisplays[i];              sp<IGraphicBufferProducer> producer;             sp<IGraphicBufferConsumer> consumer;             BufferQueue::createBufferQueue(&producer, &consumer,                     new GraphicBufferAlloc());              sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,                     consumer);             int32_t hwcId = allocateHwcDisplayId(type);             sp<DisplayDevice> hw = new DisplayDevice(this,                     type, hwcId, mHwc->getFormat(hwcId), isSecure, token,                     fbs, producer,                     mRenderEngine->getEGLConfig());             if (i > DisplayDevice::DISPLAY_PRIMARY) {                 // FIXME: currently we don‘t get blank/unblank requests                 // for displays other than the main display, so we always                 // assume a connected display is unblanked.                 ALOGD("marking display %zu as acquired/unblanked", i);                 hw->setPowerMode(HWC_POWER_MODE_NORMAL);             }             mDisplays.add(token, hw);         }     }     ...... } 
  • 调用BufferQueue::createBufferQueue创建图像缓冲区,并得到其生产者和消费者接口
  • 利用上面得到的consumer消费者接口创建FramebufferSurface
  • 利用上面得到的producer生产者接口创建DisplayDevice
  • DisplayDevice软件合成的图像在FramebufferSurface中得以消费处理
DisplayDevice::DisplayDevice(         const sp<SurfaceFlinger>& flinger,         DisplayType type,         int32_t hwcId,         int format,         bool isSecure,         const wp<IBinder>& displayToken,         const sp<DisplaySurface>& displaySurface,         const sp<IGraphicBufferProducer>& producer,         EGLConfig config)     : lastCompositionHadVisibleLayers(false),       mFlinger(flinger),       mType(type), mHwcDisplayId(hwcId),       mDisplayToken(displayToken),       mDisplaySurface(displaySurface),       mDisplay(EGL_NO_DISPLAY),       mSurface(EGL_NO_SURFACE),       mDisplayWidth(), mDisplayHeight(), mFormat(),       mFlags(),       mPageFlipCount(),       mIsSecure(isSecure),       mSecureLayerVisible(false),       mLayerStack(NO_LAYER_STACK),       mOrientation(),       mPowerMode(HWC_POWER_MODE_OFF),       mActiveConfig(0) {     mNativeWindow = new Surface(producer, false);     ANativeWindow* const window = mNativeWindow.get();      /*      * Create our display‘s surface      */      EGLSurface surface;     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);     if (config == EGL_NO_CONFIG) {         config = RenderEngine::chooseEglConfig(display, format);     }     surface = eglCreateWindowSurface(display, config, window, NULL);     eglQuerySurface(display, surface, EGL_WIDTH,  &mDisplayWidth);     eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);      // Make sure that composition can never be stalled by a virtual display     // consumer that isn‘t processing buffers fast enough. We have to do this     // in two places:     // * Here, in case the display is composed entirely by HWC.     // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the     //   window‘s swap interval in eglMakeCurrent, so they‘ll override the     //   interval we set here.     if (mType >= DisplayDevice::DISPLAY_VIRTUAL)         window->setSwapInterval(window, 0);      mConfig = config;     mDisplay = display;     mSurface = surface;     mFormat  = format;     mPageFlipCount = 0;     mViewport.makeInvalid();     mFrame.makeInvalid();      // virtual displays are always considered enabled     mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ?                   HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;      // Name the display.  The name will be replaced shortly if the display     // was created with createDisplay().     switch (mType) {         case DISPLAY_PRIMARY:             mDisplayName = "Built-in Screen";             break;         case DISPLAY_EXTERNAL:             mDisplayName = "HDMI Screen";             break;         default:             mDisplayName = "Virtual Screen";    // e.g. Overlay #n             break;     }      // initialize the display orientation transform.     setProjection(DisplayState::eOrientationDefault, mViewport, mFrame); }
  • 使用生产者接口初始化egl图形库
  • 软件绘制图层时就会调用EGL图形库,间接调用生产者接口

在SurfaceFlinger::doDisplayComposition函数中调用doComposeSurfaces函数合成图层,然后调用hw->swapBuffers。对于没有HWComper存在时,直接提交显示。若存在HWComper时,将软件合成的图层交由HWComper处理。

void DisplayDevice::swapBuffers(HWComposer& hwc) const {         // We need to call eglSwapBuffers() if:                      //  (1) we don‘t have a hardware composer, or                //  (2) we did GLES composition this frame, and either       //    (a) we have framebuffer target support (not present on legacy     //        devices, where HWComposer::commit() handles things); or     //    (b) this is a virtual display     if (hwc.initCheck() != NO_ERROR ||                                   (hwc.hasGlesComposition(mHwcDisplayId) &&                     (hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) {         EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);              if (!success) {             EGLint error = eglGetError();                                if (error == EGL_CONTEXT_LOST ||                                     mType == DisplayDevice::DISPLAY_PRIMARY) {                                LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",                                 mDisplay, mSurface, error);                      } else {                 ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x",                                            mDisplay, mSurface, error);                      }         }     }        status_t result = mDisplaySurface->advanceFrame();           if (result != NO_ERROR) {         ALOGE("[%s] failed pushing new frame to HWC: %d",                    mDisplayName.string(), result);                  }   }
  • 在不存在HWComposer或存在HWComposer但使用gles合成时调用eglSwapBuffers提交gles合成的缓冲区
  • 其它情况对图层合层不作处理

eglSwapBuffers提交gles合成的缓冲区后交由图层消费者去处理,前文中提到消费者是FramebufferSurface。看看其处理函数:

void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) {     sp<GraphicBuffer> buf;     sp<Fence> acquireFence;     status_t err = nextBuffer(buf, acquireFence);     if (err != NO_ERROR) {         ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)",                 strerror(-err), err);         return;     }     err = mHwc.fbPost(mDisplayType, acquireFence, buf);     if (err != NO_ERROR) {         ALOGE("error posting framebuffer: %d", err);     } }
  • 调用mHwc.fbPost提交buffer到HWComposer函数
int HWComposer::fbPost(int32_t id,         const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) {     if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {         return setFramebufferTarget(id, acquireFence, buffer);     } else {         acquireFence->waitForever("HWComposer::fbPost");         return mFbDev->post(mFbDev, buffer->handle);     } }
  • 存在硬件合成器时,调用setFramebufferTarget函数将软件合成的结果提交给硬件合成器去混合图层输出
  • 不存在硬件合成器时,直接调用mFbDev->post将软件合成的结果提交到framebuffer进去输出

在SurfaceFlinger中执行完doDisplayComposition进行图层处理后会调用postFramebuffer提交图层到HWComposer中。

void SurfaceFlinger::postFramebuffer() {     ATRACE_CALL();      ......      HWComposer& hwc(getHwComposer());     if (hwc.initCheck() == NO_ERROR) {         if (!hwc.supportsFramebufferTarget()) {             // EGL spec says:             //   "surface must be bound to the calling thread‘s current context,             //    for the current rendering API."             getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);                                                                                                                         }         hwc.commit();     }        ...... }
  • 存在HWComposer时调用hwc.commit()提交图层。
status_t HWComposer::commit() {     int err = NO_ERROR;     if (mHwc) {         if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {                    // On version 1.0, the OpenGL ES target surface is communicated             // by the (dpy, sur) fields and we are guaranteed to have only             // a single display.             mLists[0]->dpy = eglGetCurrentDisplay();                     mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW);         }          for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) {                 DisplayData& disp(mDisplayData[i]);             if (disp.outbufHandle) {                                         mLists[i]->outbuf = disp.outbufHandle;                       mLists[i]->outbufAcquireFenceFd =                                    disp.outbufAcquireFence->dup();                  }         }          err = mHwc->set(mHwc, mNumDisplays, mLists);          for (size_t i=0 ; i<mNumDisplays ; i++) {             DisplayData& disp(mDisplayData[i]);             disp.lastDisplayFence = disp.lastRetireFence;             disp.lastRetireFence = Fence::NO_FENCE;                      if (disp.list) {                 if (disp.list->retireFenceFd != -1) {                            disp.lastRetireFence = new Fence(disp.list->retireFenceFd);                       disp.list->retireFenceFd = -1;                           }                 disp.list->flags &= ~HWC_GEOMETRY_CHANGED;               }         }     }       return (status_t)err; }
  • 调用mHwc->set使用硬件对层图进行合成并输出到显示设备

原文:https://www.cnblogs.com/qzhang1535/p/9359056.html

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!