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