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

Commit 60ed54d8 authored by Derek Sollenberger's avatar Derek Sollenberger Committed by Luca Stefani
Browse files

Improve performance of unclipped save layers.

Instead of allocating a separate renderTarget and switching
between them on each draw the new implementation follows the same
pattern that the old HWUI renderer used. The area of the layer is
now copied to a buffer on the GPU, the area is then cleared, rendered
as normal, and finally the texture is redrawn using dst_over blending.

This results in no render target switches and is considerably faster
on most hardware.

This CL also addresses initial bugs where the fading edge effect was
impacting neighboring pixels when the matrix contained fractional
values.

Bug: 129117085
Test: skia unit tests and test cases described in the bug
Change-Id: I9d898faf12fadc2a99d57de513d6a96d42733cdb
parent dfe3a8a0
Loading
Loading
Loading
Loading
+42 −21
Original line number Diff line number Diff line
@@ -20295,23 +20295,27 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        }
        saveCount = canvas.getSaveCount();
        int topSaveCount = -1;
        int bottomSaveCount = -1;
        int leftSaveCount = -1;
        int rightSaveCount = -1;
        int solidColor = getSolidColor();
        if (solidColor == 0) {
            if (drawTop) {
                canvas.saveUnclippedLayer(left, top, right, top + length);
                topSaveCount = canvas.saveUnclippedLayer(left, top, right, top + length);
            }
            if (drawBottom) {
                canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
                bottomSaveCount = canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
            }
            if (drawLeft) {
                canvas.saveUnclippedLayer(left, top, left + length, bottom);
                leftSaveCount = canvas.saveUnclippedLayer(left, top, left + length, bottom);
            }
            if (drawRight) {
                canvas.saveUnclippedLayer(right - length, top, right, bottom);
                rightSaveCount = canvas.saveUnclippedLayer(right - length, top, right, bottom);
            }
        } else {
            scrollabilityCache.setFadeColor(solidColor);
@@ -20328,12 +20332,31 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        final Matrix matrix = scrollabilityCache.matrix;
        final Shader fade = scrollabilityCache.shader;
        if (drawTop) {
            matrix.setScale(1, fadeHeight * topFadeStrength);
        // must be restored in the reverse order that they were saved
        if (drawRight) {
            matrix.setScale(1, fadeHeight * rightFadeStrength);
            matrix.postRotate(90);
            matrix.postTranslate(right, top);
            fade.setLocalMatrix(matrix);
            p.setShader(fade);
            if (solidColor == 0) {
                canvas.restoreUnclippedLayer(rightSaveCount, p);
            } else {
                canvas.drawRect(right - length, top, right, bottom, p);
            }
        }
        if (drawLeft) {
            matrix.setScale(1, fadeHeight * leftFadeStrength);
            matrix.postRotate(-90);
            matrix.postTranslate(left, top);
            fade.setLocalMatrix(matrix);
            p.setShader(fade);
            canvas.drawRect(left, top, right, top + length, p);
            if (solidColor == 0) {
                canvas.restoreUnclippedLayer(leftSaveCount, p);
            } else {
                canvas.drawRect(left, top, left + length, bottom, p);
            }
        }
        if (drawBottom) {
@@ -20342,25 +20365,23 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            matrix.postTranslate(left, bottom);
            fade.setLocalMatrix(matrix);
            p.setShader(fade);
            if (solidColor == 0) {
                canvas.restoreUnclippedLayer(bottomSaveCount, p);
            } else {
                canvas.drawRect(left, bottom - length, right, bottom, p);
            }
        }
        if (drawLeft) {
            matrix.setScale(1, fadeHeight * leftFadeStrength);
            matrix.postRotate(-90);
        if (drawTop) {
            matrix.setScale(1, fadeHeight * topFadeStrength);
            matrix.postTranslate(left, top);
            fade.setLocalMatrix(matrix);
            p.setShader(fade);
            canvas.drawRect(left, top, left + length, bottom, p);
            if (solidColor == 0) {
                canvas.restoreUnclippedLayer(topSaveCount, p);
            } else {
                canvas.drawRect(left, top, right, top + length, p);
            }
        if (drawRight) {
            matrix.setScale(1, fadeHeight * rightFadeStrength);
            matrix.postRotate(90);
            matrix.postTranslate(right, top);
            fade.setLocalMatrix(matrix);
            p.setShader(fade);
            canvas.drawRect(right - length, top, right, bottom, p);
        }
        canvas.restoreToCount(saveCount);
+6 −0
Original line number Diff line number Diff line
@@ -100,6 +100,11 @@ static jint saveLayerAlpha(jlong canvasHandle, jfloat l, jfloat t,
    return static_cast<jint>(get_canvas(canvasHandle)->saveLayerAlpha(l, t, r, b, alpha, flags));
}

static void restoreUnclippedLayer(jlong canvasHandle, jint saveCount, jlong paintHandle) {
    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
    get_canvas(canvasHandle)->restoreUnclippedLayer(saveCount, *paint);
}

static bool restore(jlong canvasHandle) {
    Canvas* canvas = get_canvas(canvasHandle);
    if (canvas->getSaveCount() <= 1) {
@@ -607,6 +612,7 @@ static const JNINativeMethod gMethods[] = {
    {"nSave","(JI)I", (void*) CanvasJNI::save},
    {"nSaveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
    {"nSaveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
    {"nRestoreUnclippedLayer","(JIJ)V", (void*) CanvasJNI::restoreUnclippedLayer},
    {"nGetSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
    {"nRestore","(J)Z", (void*) CanvasJNI::restore},
    {"nRestoreToCount","(JI)V", (void*) CanvasJNI::restoreToCount},
+13 −0
Original line number Diff line number Diff line
@@ -494,6 +494,16 @@ public class Canvas extends BaseCanvas {
        return nSaveLayer(mNativeCanvasWrapper, left, top, right, bottom, 0, 0);
    }

    /**
     * @hide
     * @param saveCount The save level to restore to.
     * @param paint     This is copied and is applied to the area within the unclipped layer's
     *                  bounds (e.g. equivalent to a drawPaint()) before restore() is called.
     */
    public void restoreUnclippedLayer(int saveCount, Paint paint) {
        nRestoreUnclippedLayer(mNativeCanvasWrapper, saveCount, paint.getNativeInstance());
    }

    /**
     * Helper version of saveLayer() that takes 4 values rather than a RectF.
     *
@@ -1327,6 +1337,9 @@ public class Canvas extends BaseCanvas {
    private static native int nSaveLayerAlpha(long nativeCanvas, float l, float t, float r, float b,
            int alpha, int layerFlags);
    @CriticalNative
    private static native void nRestoreUnclippedLayer(long nativeCanvas, int saveCount,
            long nativePaint);
    @CriticalNative
    private static native boolean nRestore(long canvasHandle);
    @CriticalNative
    private static native void nRestoreToCount(long canvasHandle, int saveCount);
+5 −0
Original line number Diff line number Diff line
@@ -110,6 +110,11 @@ void RecordingCanvas::restoreToCount(int saveCount) {
    mState.restoreToCount(saveCount);
}

void RecordingCanvas::restoreUnclippedLayer(int saveCount, const SkPaint& paint) {
    // This feature is unimplemented for the legacyGL backend
    restoreToCount(saveCount);
}

int RecordingCanvas::saveLayer(float left, float top, float right, float bottom,
                               const SkPaint* paint, SaveFlags::Flags flags) {
    // force matrix/clip isolation for layer
+1 −0
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@ public:
    virtual int save(SaveFlags::Flags flags) override;
    virtual void restore() override;
    virtual void restoreToCount(int saveCount) override;
    virtual void restoreUnclippedLayer(int saveCount, const SkPaint& paint) override;

    virtual int saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
                          SaveFlags::Flags flags) override;
Loading