SurfaceFlinger -- FramebufferSurface 详解

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 中的 E GLSurface 作为 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。


  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值