It's our wits that make us men.

Android 16 View 模糊完整流程深度分析

Posted on By pengmengxing

基于 Android 16 AOSP 源码(J:\aosp16
覆盖内容:View 绘制 → 模糊渲染 → 纹理关联 → 线程分工 → 跨进程通信 → SF 合成路径


一、整体架构框图

flowchart TB
    subgraph APP["App 进程"]
        subgraph UIThread["UI Thread(主线程)"]
            A1["View.invalidate()"]
            A2["scheduleTraversals()"]
            A3["Choreographer.postCallback(TRAVERSAL)"]
            A4["Vsync 到达 → performTraversals()"]
            A5["performDraw() → ThreadedRenderer.draw()"]
            A6["DrawFrameTask.drawFrame()\npostAndWait() ← 主线程阻塞"]
        end

        subgraph RT["RenderThread(进程单例,持有 EGLContext / VkDevice)"]
            R1["DrawFrameTask::run()"]
            R2["syncFrameState()\n→ prepareTree()\n→ createOrUpdateLayer()\n→ 分配离屏 SkSurface"]
            R3["unblockUiThread() → 主线程恢复"]
            R4["SkiaPipeline::draw()"]
            R5["Pass 1: renderLayersImpl()\nView内容 → 离屏纹理"]
            R6["Pass 2: renderFrameImpl()\nBackdropFilterDrawable\nRenderNodeDrawable + blur合成"]
            R7["swapBuffers()\nGPU命令 → 驱动\nBLASTBufferQueue::queueBuffer()"]
        end
    end

    subgraph IPC["Binder IPC(ISurfaceComposer::setTransactionState)"]
        P1["GraphicBuffer handle(dmabuf,零拷贝)\nacquireFence + Layer属性 + frameNumber"]
    end

    subgraph SFP["SurfaceFlinger 进程"]
        subgraph SFMain["SF 主线程"]
            S1["composite() → CE::present()"]
            S2["① updateCompositionState()"]
            S3["② writeCompositionState()\nwriteStateToHWC()"]
            S4["③ prepareFrame()\nHWC validate"]
            S5["④ composeSurfaces()"]
            S6["⑤ presentFrameAndReleaseLayers()"]
        end
        subgraph REThread["RenderEngine 线程"]
            RE1["drawLayersInternal()\nSkiaRenderEngine GPU合成"]
        end
        subgraph HWCBlock["HWC 硬件"]
            H1["validateDisplay()\nDEVICE / CLIENT 决策"]
            H2["presentDisplay()\nOverlay Plane 扫描屏幕"]
        end
    end

    A1 --> A2 --> A3 --> A4 --> A5 --> A6
    A6 <-->|"同步点"| R1
    R1 --> R2 --> R3 --> R4 --> R5 --> R6 --> R7
    R7 --> P1 --> S1
    S1 --> S2 --> S3 --> S4 --> S5 --> S6
    S3 -->|"Buffer handle + fence"| H1
    H1 -->|"changedTypes"| S4
    S5 -->|"CLIENT: drawLayers().get()"| RE1
    S5 -->|"DEVICE: 直接 return"| H2
    RE1 -->|"set_value(fence)"| S5
    S6 --> H2

二、View 绘制过程:从 invalidate() 到 RenderThread

2.1 主线程驱动链

flowchart TD
    A["View.invalidate()\n标记 View 脏区,请求重绘"]
    B["ViewRootImpl.scheduleTraversals()\n通过 Choreographer 注册回调,等待下一个 Vsync"]
    C["Choreographer.postCallback(TRAVERSAL, mTraversalRunnable)"]
    D["Vsync 信号到达"]
    E["Choreographer.doFrame()"]
    F["ViewRootImpl.performTraversals()"]
    G["performMeasure()  测量"]
    H["performLayout()  布局"]
    I["performDraw()"]
    J["ThreadedRenderer.draw(view, attachInfo)"]
    K["DrawFrameTask.drawFrame()"]

    A --> B --> C --> D --> E --> F
    F --> G
    F --> H
    F --> I --> J --> K

    style D fill:#FF9800,color:#fff
    style K fill:#2196F3,color:#fff

2.2 DrawFrameTask 跨线程同步点

源码:frameworks/base/libs/hwui/renderthread/DrawFrameTask.cpp:72

int DrawFrameTask::drawFrame() {
    LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");

    mSyncResult = SyncResult::OK;
    // 记录 Sync 排队时间,用于后续帧时间统计
    mSyncQueued = systemTime(SYSTEM_TIME_MONOTONIC);

    // 把任务投递到 RenderThread 队列,主线程在此处阻塞等待
    // 阻塞只持续到 syncFrameState() 完成(同步点),不是等整帧渲染完
    postAndWait();

    return mSyncResult;
}

void DrawFrameTask::postAndWait() {
    AutoMutex _lock(mLock);
    // 向 RenderThread 消息队列投递 run() 任务
    mRenderThread->queue().post([this]() { run(); });
    // 主线程条件变量等待,RenderThread 执行 syncFrameState() 完成后 signal
    mSignal.wait(mLock);
}

2.3 RenderThread 执行帧绘制

源码:frameworks/base/libs/hwui/renderthread/DrawFrameTask.cpp:89

void DrawFrameTask::run() {
    // ── Phase 1: Sync(UI线程等待此阶段结束)──
    {
        TreeInfo info(TreeInfo::MODE_FULL, *mContext);
        // syncFrameState: 同步 RenderNode 属性,准备离屏 Layer
        // 重要:setRenderEffect(blur) 导致 mImageFilter != null
        // → promotedToLayer() = true → 为该 RenderNode 分配离屏 SkSurface
        canUnblockUiThread = syncFrameState(info);
        canDrawThisFrame = !info.out.skippedFrameReason.has_value();
    }

    // 同步完成后立刻解锁主线程(主线程恢复运行)
    if (canUnblockUiThread) {
        unblockUiThread();  // mSignal.signal()
    }

    // ── Phase 2: Draw(主线程此时已解锁,两线程并行)──
    if (CC_LIKELY(canDrawThisFrame)) {
        context->draw(solelyTextureViewUpdates);
        // draw() 内部依次执行:
        //   1. SkiaPipeline::draw() → renderLayersImpl() + renderFrameImpl()
        //   2. swapBuffers() → 提交到 BLASTBufferQueue
    }
}

2.4 SkiaPipeline 两 Pass 渲染

源码:frameworks/base/libs/hwui/pipeline/skia/SkiaPipeline.cpp:351

void SkiaPipeline::renderFrame(
        const LayerUpdateQueue& layers,     // 需要更新的离屏 Layer 列表
        const SkRect& clip,
        const std::vector<sp<RenderNode>>& nodes,
        bool opaque,
        const Rect& contentDrawBounds,
        sk_sp<SkSurface> surface,           // 主 Surface(对应 GraphicBuffer)
        const SkMatrix& preTransform) {

    SkCanvas* canvas = tryCapture(surface.get(), nodes[0].get(), layers);

    // ═══ Pass 1:预渲染所有离屏 Layer ═══
    // 把被 setRenderEffect(blur) 提升为 RenderLayer 的 View 内容
    // 渲染到各自的离屏 SkSurface(GPU 纹理)
    renderLayersImpl(layers, opaque);

    // ═══ Pass 2:把所有 RenderNode 合成到主 Surface ═══
    // 此过程中,模糊效果被应用(离屏纹理 → blur → 写入主 Surface)
    renderFrameImpl(clip, nodes, opaque, contentDrawBounds, canvas, preTransform);
}

源码:frameworks/base/libs/hwui/pipeline/skia/SkiaPipeline.cpp:385

void SkiaPipeline::renderFrameImpl(...) {
    canvas->androidFramework_setDeviceClipRestriction(clipRestriction);
    canvas->concat(preTransform);

    if (!opaque) {
        canvas->clear(SK_ColorTRANSPARENT);
    }

    // 从根 RenderNode 开始,递归绘制整棵 View 树
    // 每个 RenderNodeDrawable::onDraw() 会处理对应 View 的内容与模糊
    RenderNodeDrawable root(nodes[0].get(), canvas);
    root.draw(canvas);
    // 内部调用链:
    //   RenderNodeDrawable::forceDraw()
    //   └─ drawContent()
    //       ├─ [有离屏层] makeImageSnapshot() → applyBlur → drawImageRect()
    //       └─ [无离屏层] displayList->draw(canvas) 直接回放绘制指令
}

三、模糊的两条代码路径

路径 A:setRenderEffect(blur) — 内容自身模糊

3A.1 触发 RenderLayer 自动提升

源码:frameworks/base/libs/hwui/RenderProperties.h:552

// 当 mImageFilter != nullptr(即调用了 setRenderEffect(blur)),此函数返回 true
// 意味着这个 RenderNode 虽然 Java 层没设 LAYER_TYPE_HARDWARE,
// 但 Native 层会自动给它分配一块离屏 SkSurface(GPU 纹理),当作硬件 Layer 处理
bool promotedToLayer() const {
    return mLayerProperties.mType == LayerType::None     // 用户没手动设 Layer 类型
           && fitsOnLayer()                               // 尺寸合理,能放入纹理
           && (mComputedFields.mNeedLayerForFunctors      // Functor 特殊需求
               || mLayerProperties.mImageFilter != nullptr  // ← blur 触发此条件
               || mLayerProperties.getStretchEffect().requiresLayer()
               || (alpha < 1 && hasOverlappingRendering));
}

// effectiveLayerType 是判断 Layer 类型的统一入口
// 其他所有地方都调用此函数,而非直接访问 mType
LayerType effectiveLayerType() const {
    return CC_UNLIKELY(promotedToLayer())
               ? LayerType::RenderLayer   // ← 自动提升为 GPU 离屏层
               : mLayerProperties.mType;
}

3A.2 分配离屏 GPU 纹理

源码:frameworks/base/libs/hwui/pipeline/skia/SkiaGpuPipeline.cpp:72

bool SkiaGpuPipeline::createOrUpdateLayer(
        RenderNode* node,
        const DamageAccumulator& damageAccumulator,
        ErrorHandler* errorHandler) {

    // 计算离屏纹理尺寸(对齐到 LAYER_SIZE 边界,通常 64px)
    const int surfaceWidth  = ceilf(node->getWidth()  / float(LAYER_SIZE)) * LAYER_SIZE;
    const int surfaceHeight = ceilf(node->getHeight() / float(LAYER_SIZE)) * LAYER_SIZE;

    SkSurface* layer = node->getLayerSurface();

    // 尺寸变化或第一次分配时,创建新的 GPU 离屏 SkSurface
    if (!layer || layer->width() != surfaceWidth || layer->height() != surfaceHeight) {
        SkImageInfo info = SkImageInfo::Make(
                surfaceWidth, surfaceHeight,
                getSurfaceColorType(),   // RGBA_8888 / RGBA_F16 等
                kPremul_SkAlphaType,
                getSurfaceColorSpace());

        // 在 GPU 上分配一块渲染目标纹理(GrTexture)
        // skgpu::Budgeted::kYes 表示纳入 Skia 的 GPU 资源预算管理
        node->setLayerSurface(
                SkSurfaces::RenderTarget(
                        mRenderThread.getGrContext(),  // Skia GPU 上下文
                        skgpu::Budgeted::kYes,
                        info,
                        0,                             // 采样数(0=不抗锯齿)
                        this->getSurfaceOrigin(),
                        &props));
    }
    return true; // 返回 true 表示需要 damageSelf(全量重绘这个 Layer)
}

3A.3 Pass 1:View 内容渲染进离屏纹理

源码:frameworks/base/libs/hwui/pipeline/skia/SkiaPipeline.cpp:81

bool SkiaPipeline::renderLayerImpl(RenderNode* layerNode, const Rect& layerDamage) {
    // 取出该 RenderNode 专属的离屏 SkSurface
    SkCanvas* layerCanvas = layerNode->getLayerSurface()->getCanvas();

    int saveCount = layerCanvas->save();

    // 设置 Clip 限制,只绘制脏区,避免整帧重绘
    layerCanvas->androidFramework_setDeviceClipRestriction(layerDamage.toSkIRect());

    // 清空离屏纹理(透明背景)
    layerNode->getSkiaLayer()->hasRenderedSinceRepaint = false;
    layerCanvas->clear(SK_ColorTRANSPARENT);

    // mComposeLayer=false:此时不合成,只把 View 的 DisplayList 画到离屏纹理
    // 注意:此处不应用 imageFilter(模糊),只记录原始像素
    RenderNodeDrawable root(layerNode, layerCanvas, /*composeLayer=*/false);
    root.forceDraw(layerCanvas);
    // 执行完后,离屏 SkSurface 里存的是未模糊的 View 原始内容

    layerCanvas->restoreToCount(saveCount);
    return true;
}

Pass 1 完成后立刻 flush GPU 命令:

// frameworks/base/libs/hwui/pipeline/skia/SkiaGpuPipeline.cpp:64
if (cachedContext.get()) {
    // 把所有 Layer 的 GPU 绘制命令提交给驱动(但 GPU 实际执行是异步的)
    // flush 是为了让离屏纹理数据准备好,后续 Pass 2 可以读取
    cachedContext->flushAndSubmit();
}

3A.4 Pass 2:从离屏纹理取快照 → 应用模糊 → 写入主 Surface

源码:frameworks/base/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp:244

void RenderNodeDrawable::drawContent(SkCanvas* canvas) const {
    RenderNode* renderNode = mRenderNode.get();
    const RenderProperties& properties = renderNode->properties();
    const LayerProperties& layerProperties = properties.layerProperties();

    // ── 进入此分支的条件:
    //    1. getLayerSurface() != null  → 有离屏 SkSurface(由 promotedToLayer 创建)
    //    2. mComposeLayer == true       → 当前是"合成"调用,不是"预渲染"调用
    if (renderNode->getLayerSurface() && mComposeLayer) {

        SkPaint paint;
        layerNeedsPaint(layerProperties, alphaMultiplier, &paint);

        // ── Step 1:从离屏 SkSurface 取 GPU 纹理快照
        //    makeImageSnapshot() 返回的 SkImage 内部持有 GrTexture 引用(零拷贝)
        //    此时 snapshotImage 就是 View 原始内容的 GPU 纹理
        sk_sp<SkImage> snapshotImage = renderNode->getLayerSurface()->makeImageSnapshot();

        auto* imageFilter = layerProperties.getImageFilter();  // 即 blur SkImageFilter

        if (imageFilter) {
            auto subset = SkIRect::MakeWH(srcBounds.width(), srcBounds.height());
            auto recordingContext = canvas->recordingContext();

            // ── Step 2:GPU 执行 ImageFilter(高斯模糊)
            //    输入:snapshotImage(View 内容 GPU 纹理 A)
            //    输出:新的 SkImage(模糊后 GPU 纹理 B),仍在 GPU 显存
            //    底层调用 Skia Ganesh 的 GPU ImageFilter 执行路径:
            //    SkImageFilters::Blur → GrBlurUtils → GPU 着色器卷积
            if (recordingContext) {
                snapshotImage = SkImages::MakeWithFilter(
                        recordingContext,       // GPU 上下文(GrDirectContext)
                        snapshotImage,          // 输入:View 内容纹理
                        imageFilter,            // 模糊算子(SkImageFilters::Blur)
                        subset,                 // 输入范围
                        clipBounds.roundOut(),  // clip 范围(限制模糊扩散边界)
                        &srcBounds,             // 输出:实际有效像素范围
                        &offset);               // 输出:相对偏移(模糊后的位置修正)
            }
        }

        // ── Step 3:把模糊后的 GPU 纹理画到父 Canvas
        //    此时父 Canvas 背后是主 SkSurface,对应最终的 GraphicBuffer
        //    drawImageRect = 用 GPU Shader 对纹理采样后写入目标帧缓冲
        canvas->drawImageRect(
                snapshotImage,
                SkRect::Make(srcBounds),   // 源矩形(模糊图像的有效区域)
                SkRect::Make(dstBounds),   // 目标矩形(View 在屏幕上的位置)
                SkSamplingOptions(SkFilterMode::kLinear),
                &paint,
                SkCanvas::kStrict_SrcRectConstraint);
    }
}

路径 B:setBackdropRenderEffect(blur) — 背景模糊

关键区别mBackdropImageFilter 不触发 promotedToLayer(),View 本身不创建离屏纹理

3B.1 录制时写入 DisplayList 的顺序(主线程执行)

源码:frameworks/base/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp:164

void SkiaRecordingCanvas::drawRenderNode(uirenderer::RenderNode* renderNode) {
    // 把 RenderNodeDrawable 加入父 View 的 DisplayList
    mDisplayList->mChildNodes.emplace_back(renderNode, asSkCanvas(), true, mCurrentBarrier);
    auto& renderNodeDrawable = mDisplayList->mChildNodes.back();

    // ── 如果设置了 backdropImageFilter,在 View 内容之前插入 BackdropFilterDrawable
    //    这里是"先记录后执行"的录制模式,顺序决定了后续回放时的绘制顺序
    if (renderNode->stagingProperties().layerProperties().getBackdropImageFilter()) {
        auto* backdropFilterDrawable =
                mDisplayList->allocateDrawable<BackdropFilterDrawable>(renderNode, asSkCanvas());

        // ★ 先记录 BackdropFilterDrawable(运行时先执行:截背景→模糊→画到底部)
        drawDrawable(backdropFilterDrawable);
    }

    // ★ 后记录 RenderNodeDrawable(运行时后执行:View 自身内容画在模糊层上方)
    drawDrawable(&renderNodeDrawable);
}

3B.2 运行时:BackdropFilterDrawable 截背景并模糊

源码:frameworks/base/libs/hwui/pipeline/skia/BackdropFilterDrawable.cpp:32

void BackdropFilterDrawable::onDraw(SkCanvas* canvas) {
    const RenderProperties& properties = mTargetRenderNode->properties();

    // 取出 backdropImageFilter(即 blur SkImageFilter)
    auto* backdropFilter = properties.layerProperties().getBackdropImageFilter();
    auto* surface = canvas->getSurface();  // 当前正在绘制的 SkSurface(主 Surface)

    if (!backdropFilter || !surface) return;

    // 计算 View 在屏幕坐标系中的矩形区域
    SkRect srcBounds = SkRect::MakeWH(properties.getWidth(), properties.getHeight());
    float alphaMultiplier = 1.0f;
    RenderNodeDrawable::setViewProperties(properties, canvas, &alphaMultiplier, true);

    SkRect surfaceSubset;
    // 把 View 的局部坐标映射到 Surface(屏幕)坐标
    canvas->getTotalMatrix().mapRect(&surfaceSubset, srcBounds);
    if (!surfaceSubset.intersect(SkRect::MakeWH(surface->width(), surface->height()))) return;

    // ── Step 1:截取当前 Surface 在 View 位置的快照
    //    此时其他 View 已绘制完(backdrop),但本 View 内容还没画
    //    makeImageSnapshot 是 GPU 纹理的引用,不是 CPU 拷贝
    auto backdropImage = surface->makeImageSnapshot(surfaceSubset.roundOut());

    SkIRect imageBounds = SkIRect::MakeWH(backdropImage->width(), backdropImage->height());
    SkIPoint offset;
    SkIRect imageSubset;

    // ── Step 2:GPU 执行模糊(同路径 A 的 Step 2,但输入是背景快照而非离屏纹理)
    if (canvas->recordingContext()) {
        backdropImage = SkImages::MakeWithFilter(
                canvas->recordingContext(),  // Skia GPU 上下文
                backdropImage,              // 输入:View 后面的背景快照
                backdropFilter,             // 模糊 SkImageFilter
                imageBounds, imageBounds,
                &imageSubset, &offset);
    }

    // ── Step 3:把模糊后的背景画回 Canvas(此时是最底层,View 内容尚未绘制)
    canvas->save();
    canvas->resetMatrix();  // 重置矩阵,避免双重变换
    canvas->drawImageRect(
            backdropImage,
            SkRect::Make(imageSubset),
            surfaceSubset,
            SkSamplingOptions(SkFilterMode::kLinear),
            &paint,
            SkCanvas::kFast_SrcRectConstraint);
    canvas->restore();
    // 执行完后:View 区域的 Surface 上已有模糊背景,等待 View 内容叠加
}

四、纹理 / 模糊 / View 内容三者关系图

路径 A(setRenderEffect)— 内容被模糊

flowchart TD
    subgraph Pass1["Pass 1 — renderLayerImpl()(mComposeLayer=false)"]
        DL["View.DisplayList\n绘制指令集合"]
        OS["离屏 SkSurface\n【GPU 纹理 A】\nView 原始内容,未模糊\nSkSurfaces::RenderTarget 分配"]
        DL -->|"RenderNodeDrawable::forceDraw(layerCanvas)"| OS
    end

    FLUSH["flushAndSubmit()\nGPU 命令提交,纹理 A 数据就绪"]

    subgraph Pass2["Pass 2 — drawContent()(mComposeLayer=true)"]
        SNAP["makeImageSnapshot()\n纹理 A 的 SkImage 引用\n零拷贝,无内存复制"]
        BLUR["SkImages::MakeWithFilter(ctx, SkImage, blurFilter)\nGPU 高斯卷积\nGrBlurUtils::DrawImageWithFilter\n输出【GPU 纹理 B】"]
        MAIN["canvas->drawImageRect(纹理B → 主 Surface)\nGPU 采样纹理 B 写入 GraphicBuffer"]
        RESULT["GraphicBuffer\n此 View 区域 = 模糊后的内容\n原始纹理 A 不出现在最终画面"]

        SNAP -->|"imageFilter != null"| BLUR --> MAIN --> RESULT
    end

    OS --> FLUSH --> SNAP

    style OS fill:#FF9800,color:#fff
    style BLUR fill:#9C27B0,color:#fff
    style RESULT fill:#4CAF50,color:#fff

路径 B(setBackdropRenderEffect)— 背景被模糊,内容叠上去

sequenceDiagram
    participant DL as "父 View DisplayList 回放"
    participant BFD as "BackdropFilterDrawable::onDraw()"
    participant Surface as "主 SkSurface(正在绘制)"
    participant GPU as "GPU(Skia Ganesh)"
    participant RND as "RenderNodeDrawable::drawContent()"

    Note over DL: 录制顺序决定执行顺序:先 BackdropFilter,后 RenderNode

    DL->>BFD: 执行(其他View已绘制完毕)
    BFD->>Surface: makeImageSnapshot(View区域)\n截取背景像素 → 纹理 C
    Surface-->>BFD: sk_sp<SkImage>(纹理 C)
    BFD->>GPU: SkImages::MakeWithFilter(纹理C, blurFilter)
    GPU-->>BFD: 纹理 D(模糊后背景)
    BFD->>Surface: drawImageRect(纹理D)\n模糊背景写回 Surface(View区域底层)

    Note over Surface: 此时 View 区域 = 模糊背景

    DL->>RND: 执行(View自身内容)
    RND->>Surface: displayList->draw(canvas)\n回放 View 绘制指令(文字/图形等)

    Note over Surface: 最终 View 区域 = 模糊背景 + View内容叠加\n叠加顺序由 DisplayList 录制顺序保证

五、线程分工 UML 序列图

sequenceDiagram
    participant UI as "UI Thread"
    participant Choreo as "Choreographer"
    participant RT as "RenderThread"
    participant GPU as "GPU Driver"

    UI->>Choreo: invalidate() → postCallback(TRAVERSAL)
    Note over Choreo: 等待 Vsync 信号
    Choreo->>UI: doFrame() → performTraversals()
    UI->>UI: performMeasure() / performLayout()
    UI->>RT: DrawFrameTask.drawFrame()\npostAndWait() [UI线程阻塞]

    rect rgb(255, 243, 224)
        Note over RT: syncFrameState 阶段(UI线程等待)
        RT->>RT: prepareTree()
        RT->>RT: createOrUpdateLayer()\n分配离屏 SkSurface(promotedToLayer=true时)
    end

    RT->>UI: unblockUiThread() [UI线程恢复]

    par RenderThread 继续渲染 & UI Thread 开始下一帧
        rect rgb(232, 245, 233)
            Note over RT: Pass 1: renderLayersImpl()
            RT->>GPU: View DisplayList → 离屏纹理(GPU 命令)
            RT->>GPU: flushAndSubmit()
        end
        rect rgb(232, 245, 233)
            Note over RT: Pass 2: renderFrameImpl()
            RT->>GPU: makeImageSnapshot() + SkImages::MakeWithFilter(blur)
            RT->>GPU: drawImageRect(模糊纹理 → 主Surface)
        end
        RT->>GPU: swapBuffers() → EGLSwapBuffers
        Note over GPU: GPU 异步执行所有命令\n完成后更新 GraphicBuffer 像素
        RT->>RT: BLASTBufferQueue::queueBuffer()\n附带 acquireFence
    end

六、跨进程通信:BLASTBufferQueue + Binder

6.1 通信架构

flowchart TD
    subgraph AppProc["App 进程 — RenderThread"]
        A1["CanvasContext::swapBuffers()"]
        A2["SkiaOpenGLPipeline::swapBuffers()"]
        A3["eglSwapBuffers(mEglSurface)\nEGL 写入 ANativeWindow 当前 Buffer"]
        A4["Surface::queueBuffer()\nANativeWindow 实现"]
        A5["BLASTBufferQueue::queueBuffer()"]

        D1["数据1:GraphicBuffer\n(dmabuf fd,零拷贝共享内存)\n含完整模糊像素"]
        D2["数据2:SurfaceComposerClient::Transaction\nacquireFence(GPU完成信号)\nframeNumber / timestamp\ncrop / transform 等属性"]

        A1 --> A2 --> A3 --> A4 --> A5
        A5 --> D1
        A5 --> D2
    end

    IPC["Binder IPC\nISurfaceComposer::setTransactionState()\n传输:layer_state_t + Buffer handle + acquireFence fd"]

    subgraph SFProc["SurfaceFlinger 进程"]
        B1["Binder 线程\nSurfaceFlinger::setTransactionState()"]
        B2["applyTransactionState()"]
        B3["Layer::setBuffer(GraphicBuffer, acquireFence)\n存入待显示 Buffer 队列"]

        C1["SF 主线程(Vsync INVALIDATE)"]
        C2["latchBuffer()\n从队列取出最新 Buffer,更新 Layer 状态"]

        B1 --> B2 --> B3 --> C1 --> C2
    end

    D1 -->|"dmabuf fd 传递"| IPC
    D2 -->|"Binder 序列化"| IPC
    IPC --> B1

    style D1 fill:#2196F3,color:#fff
    style D2 fill:#FF9800,color:#fff
    style IPC fill:#9C27B0,color:#fff

6.2 Fence 三件套(保证 Buffer 读写安全)

Fence 类型 语义 使用方
acquireFence App GPU 完成写入 GraphicBuffer 的信号 SF/HWC 拿到 Buffer 后等此 Fence 才能读取像素
releaseFence SF(或 HWC)完成读取 GraphicBuffer 的信号 App 下次 dequeueBuffer 时等此 Fence,确保 SF 不再读
presentFence HWC 把当前帧扫描到屏幕的信号 用于计算实际 present 时间,上报 FrameTimeline

七、SF 合成路径:present() 阶段序列

源码:frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp:440

flowchart TD
    O["Output::present(refreshArgs)\n对每个 Display 调用一次"]
    S1["① updateCompositionState()\n决定每层合成类型初始值\nfindLayerRequestingBackgroundComposition()\n有SF级blur时,其下所有层强制CLIENT"]
    S2["② planComposition()\nPlanner 缓存优化(CachedSet)"]
    S3["③ writeCompositionState()\n向 HWC 写入每层属性\nlayer->writeStateToHWC()\n提交 Buffer Handle / 变换 / 裁切"]
    S4["④ prepareFrame()\nHWC validate + 获取合成策略\nchooseCompositionStrategy() → HWC回报DEVICE/CLIENT决策\napplyCompositionStrategy() → 写入usesClientComposition标志"]
    S5["⑤ finishFrame()\n按策略执行合成\ndequeueRenderBuffer() 申请 ClientTarget Buffer\ncomposeSurfaces() ← 核心:GPU合成或跳过\nqueueBuffer() 把 ClientTarget 提交给 HWC"]
    S6["⑥ presentFrameAndReleaseLayers()\npresentFrame() → HWC::presentDisplay()\n回收 releaseFence"]

    O --> S1 --> S2 --> S3 --> S4 --> S5 --> S6

    style S5 fill:#FF5722,color:#fff
    style S6 fill:#4CAF50,color:#fff

八、HWC 合成类型决策

8.1 HWC validate 流程

源码:frameworks/native/services/surfaceflinger/CompositionEngine/src/Display.cpp:248

bool Display::chooseCompositionStrategy(
        std::optional<HWComposer::DeviceRequestedChanges>* outChanges) {

    auto& hwc = getCompositionEngine().getHwComposer();

    // SF 发送 validateDisplay 到 HWC HAL(通过 AIDL Binder IPC)
    // HWC 硬件根据自身 Overlay Plane 数量、格式支持等决定每层的最终类型
    // 结果放入 outChanges->changedTypes(哪些层需要改成 CLIENT)
    hwc.getDeviceCompositionChanges(
            *halDisplayId,
            requiresClientComposition,  // SF 是否已经强制要求 CLIENT
            getState().earliestPresentTime,
            getState().expectedPresentTime,
            getState().frameInterval,
            outChanges);
}

8.2 应用决策结果

源码:frameworks/native/services/surfaceflinger/CompositionEngine/src/Display.cpp:289

void Display::applyCompositionStrategy(const std::optional<DeviceRequestedChanges>& changes) {
    if (changes) {
        // 把 HWC 回报的变更类型写入各 OutputLayer 的 hwcCompositionType
        applyChangedTypesToLayers(changes->changedTypes);
        applyDisplayRequests(changes->displayRequests);
        applyLayerRequestsToLayers(changes->layerRequests);
    }

    auto& state = editState();
    // 只要有一层是 CLIENT,usesClientComposition = true
    state.usesClientComposition = anyLayersRequireClientComposition();
    // 只要有一层不是 CLIENT,usesDeviceComposition = true
    state.usesDeviceComposition  = !allLayersRequireClientComposition();
}

8.3 每层的判断依据

源码:frameworks/native/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp:941

bool OutputLayer::requiresClientComposition() const {
    const auto& state = getState();
    // 两种情况需要 CLIENT 合成:
    // 1. state.hwc 为空(没有 HWC 支持,如虚拟屏)
    // 2. HWC 回报的 hwcCompositionType == Composition::CLIENT(HWC 放弃该层)
    return !state.hwc || state.hwc->hwcCompositionType == Composition::CLIENT;
}

九、composeSurfaces():GPU 合成的核心决策

源码:frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp:1337

std::optional<base::unique_fd> Output::composeSurfaces(
        const Region& debugRegion,
        std::shared_ptr<renderengine::ExternalTexture> tex,
        base::unique_fd& fd) {

    const auto& outputState = getState();

    // ★ 路径 A:全部 DEVICE 合成 → 不需要 GPU,直接返回空 fd
    //   此时 SF 这一帧完全没有 GPU 工作
    //   HWC 直接读取每个 Layer 的 GraphicBuffer(dmabuf),硬件 Overlay 合成后扫描到屏幕
    if (!outputState.usesClientComposition) {
        setExpensiveRenderingExpected(false);
        return base::unique_fd();   // 返回空 fd,HWC 可直接 present
    }

    // ★ 路径 B:有 CLIENT 合成 → 需要 RenderEngine 执行 GPU 合成
    ALOGV("hasClientComposition");

    renderengine::DisplaySettings clientCompositionDisplay =
            generateClientCompositionDisplaySettings(tex);

    // 收集所有 CLIENT 类型 Layer 的绘制参数(LayerSettings)
    // 包含:Buffer handle / 变换矩阵 / 透明区域 / alpha / dataspace 等
    std::vector<LayerFE::LayerSettings> clientCompositionLayers =
            generateClientCompositionRequests(supportsProtectedContent,
                                              clientCompositionDisplay.outputDataspace,
                                              clientCompositionLayersFE);

    // 判断是否有 SF 级模糊,有则拉高 GPU 频率避免合成超时
    const bool expensiveBlurs = mLayerRequestingBackgroundBlur != nullptr;
    if (expensiveBlurs || /*有色彩空间转换*/) {
        setExpensiveRenderingExpected(true);
    }

    // ★ 关键调用:把 GPU 合成任务投递给 RenderEngine 线程,阻塞等待命令提交完成
    auto fenceResult = renderEngine
                           .drawLayers(clientCompositionDisplay,
                                       clientRenderEngineLayers,
                                       tex,          // ClientTarget Buffer
                                       std::move(fd))
                           .get();                   // ← .get() 阻塞 SF 主线程

    // 返回 GPU fence(GPU 渲染完成信号),给 HWC 用于同步
    const auto fence = std::move(fenceResult).value_or(Fence::NO_FENCE);
    return base::unique_fd(fence->dup());
}

十、RenderEngine 线程模型

10.1 类继承结构

classDiagram
    class RenderEngine {
        <<abstract>>
        +drawLayers() Future~FenceResult~
        +drawLayersInternal() void
        +updateProtectedContext() void
    }

    class RenderEngineThreaded {
        -std::thread mThread
        -std::queue mFunctionCalls
        -std::condition_variable mCondition
        -unique_ptr~RenderEngine~ mRenderEngine
        +drawLayers() Future~FenceResult~
        -threadMain() void
        -getNextTask() optional~function~
    }

    class SkiaRenderEngine {
        <<abstract>>
        +drawLayersInternal() void
    }

    class SkiaGLRenderEngine {
        -EGLContext mEGLContext
        +drawLayersInternal() void
    }

    class SkiaVkRenderEngine {
        -VkDevice mVkDevice
        +drawLayersInternal() void
    }

    RenderEngine <|-- RenderEngineThreaded : 包装(线程隔离)
    RenderEngineThreaded o-- SkiaRenderEngine : mRenderEngine(在mThread上创建和使用)
    SkiaRenderEngine <|-- SkiaGLRenderEngine : GL 后端
    SkiaRenderEngine <|-- SkiaVkRenderEngine : Vulkan 后端

10.2 drawLayers() 任务投递

源码:frameworks/native/libs/renderengine/threaded/RenderEngineThreaded.cpp:262

ftl::Future<FenceResult> RenderEngineThreaded::drawLayers(
        const DisplaySettings& display,
        const std::vector<LayerSettings>& layers,
        const std::shared_ptr<ExternalTexture>& buffer,
        base::unique_fd&& bufferFence) {

    // 创建 promise/future 对,用于跨线程传递结果(GPU fence)
    const auto resultPromise = std::make_shared<std::promise<FenceResult>>();
    std::future<FenceResult> resultFuture = resultPromise->get_future();

    int fd = bufferFence.release();  // 取出原始 fd,避免所有权问题

    {
        std::lock_guard lock(mThreadMutex);
        mNeedsPostRenderCleanup = true;

        // ★ 把真正的 GPU 工作打包成 lambda,推入队列
        //   注意:lambda 按值捕获所有参数,避免悬空引用
        mFunctionCalls.push(
            [resultPromise, display, layers, buffer, fd]
            (renderengine::RenderEngine& instance) {
                SFTRACE_NAME("REThreaded::drawLayers");
                instance.updateProtectedContext(layers, {buffer.get()});

                // ← 在 RenderEngine 线程调用 SkiaRenderEngine::drawLayersInternal()
                //   这里才真正提交 Skia/GPU 命令给驱动
                instance.drawLayersInternal(
                        std::move(resultPromise),  // promise 所有权转移
                        display, layers, buffer,
                        base::unique_fd(fd));
            });
    }

    mCondition.notify_one();  // 唤醒 RenderEngine 线程的 threadMain()
    return resultFuture;      // 立即返回 future,不阻塞调用方
}

10.3 RenderEngine 线程主循环

源码:frameworks/native/libs/renderengine/threaded/RenderEngineThreaded.cpp:100

void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) {
    // 在本线程创建 SkiaRenderEngine(确保 EGLContext/VkDevice 绑定到此线程)
    mRenderEngine = factory();

    while (mRunning) {
        const auto task = getNextTask();

        if (task) {
            // ← 执行任务:调用 drawLayersInternal()
            //   持有 mRenderingMutex,Skia 提交 GL/Vulkan 命令给 GPU 驱动
            (*task)(*mRenderEngine);
            // GPU 驱动将命令放入 GPU 命令队列,实际渲染异步进行
            // drawLayersInternal 在命令提交(不是执行完成)后调用
            // resultPromise->set_value(fence) 解除 SF 主线程的 .get() 阻塞
        }

        // 等待下一个任务(条件变量休眠,被 notify_one() 唤醒)
        std::unique_lock<std::mutex> lock(mThreadMutex);
        mCondition.wait(lock, [this]() REQUIRES(mThreadMutex) {
            return !mRunning || !mFunctionCalls.empty();
        });
    }
}

十一、SF 合成 UML 序列图

sequenceDiagram
    participant SFM as "SF 主线程"
    participant HWC as "HWC(HAL)"
    participant RET as "RenderEngine 线程"
    participant GPU as "GPU 驱动"

    SFM->>SFM: composite(pacesetterId)\n→ CE::present(refreshArgs)

    rect rgb(232, 244, 253)
        Note over SFM: ① updateCompositionState
        SFM->>SFM: findLayerRequestingBackgroundComposition()\nlayer->updateCompositionState()
    end

    rect rgb(232, 244, 253)
        Note over SFM: ② writeCompositionState
        SFM->>HWC: layer->writeStateToHWC()\n(Buffer handle / fence / 变换 / 裁切)
    end

    rect rgb(255, 243, 224)
        Note over SFM,HWC: ③ prepareFrame — HWC validate
        SFM->>HWC: chooseCompositionStrategy()\n→ getDeviceCompositionChanges()
        HWC-->>SFM: changedTypes {Layer0:DEVICE, Layer1:CLIENT, ...}\nHWC根据Overlay Plane数量/格式决策
        SFM->>SFM: applyCompositionStrategy()\n→ usesClientComposition = true/false
    end

    rect rgb(255, 235, 238)
        Note over SFM,GPU: ④ finishFrame — composeSurfaces()
        alt 全部 DEVICE 合成
            SFM->>SFM: return empty fd(无GPU工作)
            Note over GPU: HWC 直接读 dmabuf 扫屏,SF不动GPU
        else 有 CLIENT 合成
            SFM->>SFM: generateClientCompositionRequests()
            SFM->>RET: drawLayers(display, layers, tex, fd)\npush lambda 到队列
            SFM->>SFM: .get() [SF主线程阻塞等待]
            RET->>GPU: drawLayersInternal()\nSkiaRenderEngine 提交 GPU 命令
            GPU-->>RET: 命令入队完成(GPU异步执行)
            RET->>SFM: resultPromise.set_value(fence)\n[SF主线程恢复]
            SFM->>HWC: queueBuffer(ClientTarget + clientFence)
        end
    end

    rect rgb(232, 245, 233)
        Note over SFM,HWC: ⑤ presentFrameAndReleaseLayers
        SFM->>HWC: presentFrame() → hwc.presentDisplay()
        HWC->>HWC: 等 acquireFence → Overlay 扫描屏幕
        HWC-->>SFM: layerFences(releaseFence)
        SFM->>SFM: layer->setReleaseFence(fence)\n通知 App Buffer 可复用
    end

十二、全 DEVICE 合成时 GraphicBuffer 的流向

flowchart TD
    A["App RenderThread\n含模糊像素写入 GraphicBuffer\nEGLSwapBuffers 触发"]

    B["BLASTBufferQueue::queueBuffer()\nattach acquireFence(App GPU写完信号)"]

    C["SurfaceFlinger Layer::setBuffer(GraphicBuffer handle, acquireFence)\n存入 Layer 的待显示 Buffer 队列"]

    D["SF主线程 latchBuffer()\n更新 Layer 当前显示 Buffer"]

    E["writeStateToHWC()\nBuffer handle + acquireFence → HWC"]

    subgraph HWCPresent["HWC::presentDisplay()"]
        F1["等待 acquireFence 信号\nApp GPU 已完成写入"]
        F2["通过 DRM/Kernel 把 GraphicBuffer(dmabuf)\n直接映射到 Overlay Plane 扫描源\n零拷贝:HWC硬件直读App GPU写入的内存"]
        F3["Display Engine 以 Vsync 频率\n扫描 Overlay Plane → 输出屏幕"]
        F4["返回 releaseFence\nHWC已扫描完该帧,Buffer可复用"]

        F1 --> F2 --> F3 --> F4
    end

    G["SF → App: dequeueBuffer() 等待 releaseFence\n复用该 Buffer 绘制下一帧"]

    A --> B --> C --> D --> E --> HWCPresent
    F4 --> G

    style A fill:#2196F3,color:#fff
    style F2 fill:#FF9800,color:#fff
    style G fill:#4CAF50,color:#fff

十三、关键类/方法完整调用链

flowchart TD
    subgraph Java["Java 层"]
        J1["View.setRenderEffect(RenderEffect)"]
        J2["RenderNode.setRenderEffect()"]
        J3["JNI: nSetRenderEffect()"]
        J4["mutateLayerProperties().setImageFilter(SkImageFilter*)"]

        J1a["View.setBackdropRenderEffect(RenderEffect)"]
        J2a["RenderNode.setBackdropRenderEffect()"]
        J3a["JNI: nSetBackdropRenderEffect()"]
        J4a["mutateLayerProperties().setBackdropImageFilter(SkImageFilter*)"]

        JB["RenderEffect.createBlurEffect(radiusX, radiusY, tileMode)"]
        JB1["JNI: nativeCreateBlurEffect()"]
        JB2["SkImageFilters::Blur(\n  convertRadiusToSigma(r),\n  SkTileMode, inputFilter)"]

        J1 --> J2 --> J3 --> J4
        J1a --> J2a --> J3a --> J4a
        JB --> JB1 --> JB2
    end

    subgraph HWUI["Native HWUI 层"]
        H1["DrawFrameTask::drawFrame()\npostAndWait() ← UI线程阻塞"]
        H2["DrawFrameTask::run()\n[RenderThread]"]
        H3["syncFrameState(info)\n└ CanvasContext::prepareTree()\n  └ RenderNode::prepareTreeImpl()\n    └ prepareLayer() ← 检查effectiveLayerType()\n    └ pushLayerUpdate()"]
        H4["SkiaGpuPipeline::createOrUpdateLayer()\n└ SkSurfaces::RenderTarget() ← 分配离屏GPU纹理"]
        H5["[unblockUiThread()] ← UI线程恢复"]
        H6["CanvasContext::draw()\n└ SkiaOpenGLPipeline::draw()\n  └ SkiaPipeline::renderFrame()"]

        P1["Pass 1: renderLayersImpl()\n└ renderLayerImpl()\n  └ RenderNodeDrawable(mComposeLayer=false)\n    └ displayList->draw(layerCanvas)\n      ← View内容→离屏纹理"]
        P2a["Pass 2: renderFrameImpl()\n└ RenderNodeDrawable(mComposeLayer=true)\n  └ drawContent()"]
        P2b["[setBackdropRenderEffect]\nBackdropFilterDrawable::onDraw()\n├ surface->makeImageSnapshot() ← 截背景\n├ SkImages::MakeWithFilter() ← GPU模糊\n└ canvas->drawImageRect() ← 写回底层"]
        P2c["[setRenderEffect]\ngetLayerSurface()->makeImageSnapshot()\nSkImages::MakeWithFilter() ← GPU模糊\ncanvas->drawImageRect() ← 写入主Surface"]

        H1 --> H2 --> H3 --> H4 --> H5 --> H6
        H6 --> P1
        H6 --> P2a
        P2a --> P2b
        P2a --> P2c
    end

    subgraph SF["Native SurfaceFlinger 层"]
        SF1["SurfaceFlinger::composite()\n└ CompositionEngine::present(refreshArgs)\n  └ Output::present()"]
        SF2["updateCompositionState()\n└ findLayerRequestingBackgroundComposition()"]
        SF3["writeCompositionState()\n└ OutputLayer::writeStateToHWC()"]
        SF4["prepareFrame()\n└ chooseCompositionStrategy()\n  └ HWComposer::getDeviceCompositionChanges()\n└ applyCompositionStrategy()\n  └ usesClientComposition = any..."]
        SF5a["[全DEVICE] composeSurfaces() return immediately\n← 无GPU工作"]
        SF5b["[有CLIENT] composeSurfaces()\ngenerateClientCompositionRequests()\nRenderEngineThreaded::drawLayers() ← 投RE线程\n.get() ← SF主线程阻塞"]
        SF6["RE线程: SkiaRenderEngine::drawLayersInternal()\n└ GPU合成CLIENT层\n└ resultPromise.set_value(fence)"]
        SF7["mRenderSurface->queueBuffer(clientFence)"]
        SF8["presentFrameAndReleaseLayers()\n└ presentFrame()\n  └ HWComposer::presentAndGetReleaseFences()\n└ layer->setReleaseFence(releaseFence)"]

        SF1 --> SF2 --> SF3 --> SF4
        SF4 --> SF5a
        SF4 --> SF5b --> SF6 --> SF7
        SF5a --> SF8
        SF7 --> SF8
    end

    J4 & J4a -.->|"录制到 DisplayList"| H1
    H6 -.->|"swapBuffers → BLASTBufferQueue"| SF1

    style H4 fill:#FF9800,color:#fff
    style P2b fill:#9C27B0,color:#fff
    style P2c fill:#9C27B0,color:#fff
    style SF6 fill:#F44336,color:#fff

十四、关键结论速查表

问题 结论 关键代码位置
setRenderEffect(blur) 是否创建离屏纹理? mImageFilter != null → promotedToLayer() = true → SkSurfaces::RenderTarget() RenderProperties.h:552 / SkiaGpuPipeline.cpp:72
setBackdropRenderEffect(blur) 是否创建离屏纹理? ,只在 DisplayList 插入 BackdropFilterDrawable SkiaRecordingCanvas.cpp:174
模糊在哪个线程执行? App 的 RenderThread,调用 Skia GPU ImageFilter RenderNodeDrawable.cpp:265 / BackdropFilterDrawable.cpp:62
“模糊在内容底部”怎么实现的? 录制顺序决定:BackdropFilterDrawable 先于 RenderNodeDrawable 写入 DisplayList SkiaRecordingCanvas.cpp:175-180
App 到 SF 传输了什么? 像素数据:GraphicBuffer(dmabuf,零拷贝);属性:Transaction(Binder IPC) BLASTBufferQueue.cpp / LayerState.h
SF 主线程执行 GPU 合成吗? 不执行,GPU 工作在独立 RenderEngine 线程;SF 主线程 .get() 等待命令提交完成 RenderEngineThreaded.cpp:262
全 DEVICE 合成时 SF 做什么? composeSurfaces() 直接 return,SF 不动 GPU,HWC 硬件直接读 dmabuf 扫描屏幕 Output.cpp:1347
Fence 的作用? acquireFence:App GPU 写完信号;releaseFence:SF 读完信号;presentFence:扫描完成信号 OutputLayer.cpp:1663

十五、关键源文件速查

文件路径 核心职责
frameworks/base/libs/hwui/RenderProperties.h:552 promotedToLayer() — 决定是否创建离屏纹理
frameworks/base/libs/hwui/pipeline/skia/SkiaGpuPipeline.cpp:72 createOrUpdateLayer() — 分配 GPU 离屏 SkSurface
frameworks/base/libs/hwui/pipeline/skia/SkiaPipeline.cpp:81 renderLayerImpl() — Pass 1:View 内容渲染到离屏纹理
frameworks/base/libs/hwui/pipeline/skia/SkiaPipeline.cpp:351 renderFrame() — 协调 Pass 1 + Pass 2
frameworks/base/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp:220 drawContent() — Pass 2:应用 ImageFilter 并合成
frameworks/base/libs/hwui/pipeline/skia/BackdropFilterDrawable.cpp:32 onDraw() — 截背景 → GPU 模糊 → 写底层
frameworks/base/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp:164 drawRenderNode() — 录制 Drawable 顺序
frameworks/base/libs/hwui/jni/RenderEffect.cpp:39 createBlurEffect() — 创建 SkImageFilter
frameworks/base/libs/hwui/renderthread/DrawFrameTask.cpp:72 drawFrame() — UI/RT 同步点
frameworks/native/libs/gui/BLASTBufferQueue.cpp App → SF Buffer 提交
frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp:1337 composeSurfaces() — GPU 合成决策
frameworks/native/services/surfaceflinger/CompositionEngine/src/Display.cpp:248 chooseCompositionStrategy() — HWC validate
frameworks/native/libs/renderengine/threaded/RenderEngineThreaded.cpp:262 drawLayers() — RE 线程任务投递