SurfaceFlinger -- FramebufferSurface 详解

来源:互联网 发布:js添加节点 编辑:程序博客网 时间:2024/06/16 09:12

1: FramebufferSurface 概述

FramebufferSurface 根据名字解析:
1: Surface 说明它是一个Surface, 那么它就会拥有一个 BufferQuere, 用于显示。
2: FrameBuffer 这和 Linux 的 framebuffer 是完全不同的。 但是作用有些类似, SurfaceFlinger 在上面作画, 并把它交给HWC, 最终由HWC负责真正的显示。


2: SurfaceFlinger 如何驱动 FramebufferSurface

2-1: FramebufferSurface 与 DisplayDevice 的关系

FramebufferSurface 作为 BufferQueue 的 Consumer 端
DisplayDevice 中的 EGLSurface 作为 BufferQueue 的Producer

2-2: SurfaceFlinger 是如何驱动 FramebufferSurface

void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,        const Region& inDirtyRegion){    <span style="color:#ff0000;">doComposeSurfaces</span>(hw, dirtyRegion);    // swap buffers (presentation)    hw-><span style="color:#ff0000;">swapBuffers</span>(getHwComposer());}void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty){    RenderEngine& engine(getRenderEngine());    const int32_t id = hw->getHwcDisplayId();    HWComposer& hwc(getHwComposer());    HWComposer::LayerListIterator cur = hwc.begin(id);    const HWComposer::LayerListIterator end = hwc.end(id);    bool hasGlesComposition = hwc.hasGlesComposition(id);    if (hasGlesComposition) {        if (!hw-><span style="color:#ff0000;">makeCurrent</span>(mEGLDisplay, mEGLContext)) {            ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",                  hw->getDisplayName().string());            return;        }    }    /*     * and then, render the layers targeted at the framebuffer     */    const Vector< sp<Layer> >& layers(hw->getVisibleLayersSortedByZ());    const size_t count = layers.size();    const Transform& tr = hw->getTransform();    if (cur != end) {        // we're using h/w composer        for (size_t i=0 ; i<count && cur!=end ; ++i, ++cur) {            const sp<Layer>& layer(layers[i]);            const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));            if (!clip.isEmpty()) {                switch (cur->getCompositionType()) {                    case <span style="color:#ff0000;">HWC_OVERLAY</span>: {                        const Layer::State& state(layer->getDrawingState());                        if ((cur->getHints() & HWC_HINT_CLEAR_FB)                                && i                                && layer->isOpaque() && (state.alpha == 0xFF)                                && hasGlesComposition) {                            // never clear the very first layer since we're                            // guaranteed the FB is already cleared                            layer->clearWithOpenGL(hw, clip);                        }                        break;                    }                    case <span style="color:#ff0000;">HWC_FRAMEBUFFER</span>: {                        layer-><span style="color:#ff0000;">draw</span>(hw, clip);                        break;                    }                    case HWC_FRAMEBUFFER_TARGET: {                        // this should not happen as the iterator shouldn't                        // let us get there.                        ALOGW("HWC_FRAMEBUFFER_TARGET found in hwc list (index=%zu)", i);                        break;                    }                }            }            layer->setAcquireFence(hw, *cur);        }    } }

SufraceFlinger 的最终调用 doDisplayComposition 来混合指定的硬件显示设备(例如:手机屏幕)

2-2-1: 各图层的操作

HWC_OVERLAY: 由HWC负责
HWC_FRAMEBUFFER由SurfaceFlinger负责,通过调用 Layer 的 draw 方法, 把各个Layer的信息绘制到 DisplayDevice 的 EGLSufrace 中。

2-2-2: 通过 DisplayDevice 的 swapBuffers 方法来驱动显示

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 = <span style="color:#ff0000;">eglSwapBuffers</span>(mDisplay, mSurface);    }}

这里通过 eglSwapBuffers 方法, 把刚才绘制好的 EGLSufrace 中的新的 GraphicBuffer 入队。

根据BufferQueue的特性, 这里进行 queue 操作, 那么 FramebufferSurface 的 onFrameAvailable 会被回调。
可以联想到接下来的操作有两个:
1: 释放老的 buffer
2: 更新新的 buffer

代码也验证了这两部操作:
// Overrides ConsumerBase::onFrameAvailable(), does not call base class impl.void FramebufferSurface::onFrameAvailable() {    sp<GraphicBuffer> buf;    sp<Fence> acquireFence;    status_t err = <span style="color:#ff0000;">nextBuffer</span>(buf, acquireFence);    err = mHwc.<span style="color:#ff0000;">fbPost</span>(mDisplayType, acquireFence, buf);}status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {    Mutex::Autolock lock(mMutex);    BufferQueue::BufferItem item;    status_t err = <span style="color:#ff0000;">acquireBufferLocked</span>(&item, 0);    if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT &&        item.mBuf != mCurrentBufferSlot) {        // Release the previous buffer.        err = <span style="color:#ff0000;">releaseBufferLocked</span>(mCurrentBufferSlot, mCurrentBuffer,                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);        if (err < NO_ERROR) {            ALOGE("error releasing buffer: %s (%d)", strerror(-err), err);            return err;        }    }    mCurrentBufferSlot = item.mBuf;    mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;    outFence = item.mFence;    outBuffer = mCurrentBuffer;    return NO_ERROR;}

2-2-3: 最终 FramebufferSurface 的显示也是由 HWC 来控制的

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 <span style="color:#ff0000;">setFramebufferTarget</span>(id, acquireFence, buffer);    }}status_t HWComposer::setFramebufferTarget(int32_t id,        const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf) {    DisplayData& <span style="color:#ff0000;">disp</span>(mDisplayData[id]);    int acquireFenceFd = -1;    if (acquireFence->isValid()) {        acquireFenceFd = acquireFence->dup();    }    // ALOGD("fbPost: handle=%p, fence=%d", buf->handle, acquireFenceFd);    disp.<span style="color:#ff0000;">fbTargetHandle </span>= buf->handle;    disp.<span style="color:#ff0000;">framebufferTarget</span>->handle = disp.fbTargetHandle;    disp.<span style="color:#ff0000;">framebufferTarget</span>->acquireFenceFd = acquireFenceFd;    return NO_ERROR;}

可以看到 FramebufferSurface 中的 buf 赋值给了 DisplayData 的 framebufferTarget (至此整个GLES操作结束, 最终通过 hwc 的 commit 输出到物理显示设备)。

2-2-4:DisplayData 的 framebufferTarget 如何创建的

SurfaceFlinger::setUpHWComposer 调用 HWComposer::createWorkList
status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {    if (mHwc) {        DisplayData& disp(mDisplayData[id]);        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {            <span style="color:#ff0000;">disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1];</span>            memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t));            const hwc_rect_t r = { 0, 0, (int) disp.width, (int) disp.height };            disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;            disp.framebufferTarget->hints = 0;            disp.framebufferTarget->flags = 0;            disp.framebufferTarget->handle = disp.fbTargetHandle;            disp.framebufferTarget->transform = 0;            disp.framebufferTarget->blending = HWC_BLENDING_PREMULT;            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {                disp.framebufferTarget->sourceCropf.left = 0;                disp.framebufferTarget->sourceCropf.top = 0;                disp.framebufferTarget->sourceCropf.right = disp.width;                disp.framebufferTarget->sourceCropf.bottom = disp.height;            } else {                disp.framebufferTarget->sourceCrop = r;            }            disp.framebufferTarget->displayFrame = r;            disp.framebufferTarget->visibleRegionScreen.numRects = 1;            disp.framebufferTarget->visibleRegionScreen.rects =                &disp.framebufferTarget->displayFrame;            disp.framebufferTarget->acquireFenceFd = -1;            disp.framebufferTarget->releaseFenceFd = -1;            disp.framebufferTarget->planeAlpha = 0xFF;        }        disp.list->retireFenceFd = -1;        disp.list->flags = HWC_GEOMETRY_CHANGED;        disp.list->numHwLayers = numLayers;    }    return NO_ERROR;}

从代码中看出, framebufferTarget 其实就是 hwclayers 的最后一个 layer。


0 0
原创粉丝点击