Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1d602a11 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Improve RenderEngine's blur performance."

parents 97a4f38d 545ec44c
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -619,6 +619,7 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display,
    // view is still on-screen. The clear region could be re-specified as a black color layer,
    // however.
    if (!display.clearRegion.isEmpty()) {
        ATRACE_NAME("ClearRegion");
        size_t numRects = 0;
        Rect const* rects = display.clearRegion.getArray(&numRects);
        SkIRect skRects[numRects];
@@ -638,6 +639,7 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display,
    }

    for (const auto& layer : layers) {
        ATRACE_NAME("DrawLayer");
        canvas->save();

        if (mCapture->isCaptureRunning()) {
@@ -656,7 +658,7 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display,
        const auto& bounds = layer->geometry.boundaries;
        const auto dest = getSkRect(bounds);
        const auto layerRect = canvas->getTotalMatrix().mapRect(dest);
        std::unordered_map<uint32_t, sk_sp<SkSurface>> cachedBlurs;
        std::unordered_map<uint32_t, sk_sp<SkImage>> cachedBlurs;
        if (mBlurFilter) {
            if (layer->backgroundBlurRadius > 0) {
                ATRACE_NAME("BackgroundBlur");
@@ -908,16 +910,14 @@ void SkiaGLRenderEngine::drawShadow(SkCanvas* canvas, const SkRect& casterRect,
}

void SkiaGLRenderEngine::drawBlurRegion(SkCanvas* canvas, const BlurRegion& effectRegion,
                                        const SkRect& layerRect, sk_sp<SkSurface> blurredSurface) {
                                        const SkRect& layerRect, sk_sp<SkImage> blurredImage) {
    ATRACE_CALL();

    SkPaint paint;
    paint.setAlpha(static_cast<int>(effectRegion.alpha * 255));
    const auto matrix = getBlurShaderTransform(canvas, layerRect);
    paint.setShader(blurredSurface->makeImageSnapshot()->makeShader(
            SkTileMode::kClamp,
            SkTileMode::kClamp,
            SkSamplingOptions({SkFilterMode::kLinear, SkMipmapMode::kNone}),
    SkSamplingOptions linearSampling(SkFilterMode::kLinear, SkMipmapMode::kNone);
    paint.setShader(blurredImage->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, linearSampling,
                                             &matrix));

    auto rect = SkRect::MakeLTRB(effectRegion.left, effectRegion.top, effectRegion.right,
+1 −1
Original line number Diff line number Diff line
@@ -90,7 +90,7 @@ private:
    void drawShadow(SkCanvas* canvas, const SkRect& casterRect, float casterCornerRadius,
                    const ShadowSettings& shadowSettings);
    void drawBlurRegion(SkCanvas* canvas, const BlurRegion& blurRegion, const SkRect& layerRect,
                        sk_sp<SkSurface> blurredSurface);
                        sk_sp<SkImage> blurredImage);
    SkMatrix getBlurShaderTransform(const SkCanvas* canvas, const SkRect& layerRect);
    // If mUseColorManagement is correct and layer needsLinearEffect, it returns a linear runtime
    // shader. Otherwise it returns the input shader.
+14 −46
Original line number Diff line number Diff line
@@ -57,7 +57,7 @@ BlurFilter::BlurFilter() {
    mBlurEffect = std::move(blurEffect);
}

sk_sp<SkSurface> BlurFilter::generate(SkCanvas* canvas, const sk_sp<SkSurface> input,
sk_sp<SkImage> BlurFilter::generate(SkCanvas* canvas, const sk_sp<SkSurface> input,
                                    const uint32_t blurRadius, SkRect rect) const {
    // Kawase is an approximation of Gaussian, but it behaves differently from it.
    // A radius transformation is required for approximating them, and also to introduce
@@ -68,9 +68,6 @@ sk_sp<SkSurface> BlurFilter::generate(SkCanvas* canvas, const sk_sp<SkSurface> i

    SkImageInfo scaledInfo = SkImageInfo::MakeN32Premul((float)rect.width() * kInputScale,
                                                        (float)rect.height() * kInputScale);
    SkRect scaledRect = SkRect::MakeWH(scaledInfo.width(), scaledInfo.height());

    auto drawSurface = canvas->makeSurface(scaledInfo);

    const float stepX = radiusByPasses;
    const float stepY = radiusByPasses;
@@ -85,49 +82,20 @@ sk_sp<SkSurface> BlurFilter::generate(SkCanvas* canvas, const sk_sp<SkSurface> i
    blurBuilder.uniform("in_blurOffset") =
            SkV2{stepX * kInverseInputScale, stepY * kInverseInputScale};

    {
        // limit the lifetime of the input surface's snapshot to ensure that it goes out of
        // scope before the surface is written into to avoid any copy-on-write behavior.
        SkPaint paint;
        paint.setShader(blurBuilder.makeShader(nullptr, false));
        paint.setFilterQuality(kLow_SkFilterQuality);

        drawSurface->getCanvas()->drawRect(scaledRect, paint);

        blurBuilder.child("input") = nullptr;
    }

    // And now we'll ping pong between our surfaces, to accumulate the result of various offsets.
    auto lastDrawTarget = drawSurface;
    if (numberOfPasses > 1) {
        auto readSurface = drawSurface;
        drawSurface = canvas->makeSurface(scaledInfo);
    sk_sp<SkImage> tmpBlur(
            blurBuilder.makeImage(canvas->recordingContext(), nullptr, scaledInfo, false));

    // And now we'll build our chain of scaled blur stages
    blurBuilder.uniform("in_inverseScale") = 1.0f;
    for (auto i = 1; i < numberOfPasses; i++) {
        const float stepScale = (float)i * kInputScale;

        blurBuilder.child("input") =
                    readSurface->makeImageSnapshot()->makeShader(SkTileMode::kClamp,
                                                                 SkTileMode::kClamp, linear);
            blurBuilder.uniform("in_inverseScale") = 1.0f;
                tmpBlur->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, linear);
        blurBuilder.uniform("in_blurOffset") = SkV2{stepX * stepScale, stepY * stepScale};

            SkPaint paint;
            paint.setShader(blurBuilder.makeShader(nullptr, false));
            paint.setFilterQuality(kLow_SkFilterQuality);

            drawSurface->getCanvas()->drawRect(scaledRect, paint);

            // Swap buffers for next iteration
            const auto tmp = drawSurface;
            drawSurface = readSurface;
            readSurface = tmp;
            blurBuilder.child("input") = nullptr;
        }
        lastDrawTarget = readSurface;
        tmpBlur = blurBuilder.makeImage(canvas->recordingContext(), nullptr, scaledInfo, false);
    }

    return lastDrawTarget;
    return tmpBlur;
}

SkMatrix BlurFilter::getShaderMatrix() const {
+2 −2
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@ public:
    virtual ~BlurFilter(){};

    // Execute blur, saving it to a texture
    sk_sp<SkSurface> generate(SkCanvas* canvas, const sk_sp<SkSurface> input, const uint32_t radius,
    sk_sp<SkImage> generate(SkCanvas* canvas, const sk_sp<SkSurface> input, const uint32_t radius,
                            SkRect rect) const;
    // Returns a matrix that should be applied to the blur shader
    SkMatrix getShaderMatrix() const;