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

Commit 7fe53c1e authored by Derek Sollenberger's avatar Derek Sollenberger
Browse files

Render VectorDrawables in software and then upload to the VDAtlas.

For frames with multiple VDs the context switching involved was causing
worst case frame times of ~40ms to draw all VDs in the frame whereas
this new approach has worst case performance of ~5ms when drawing the
same frame (w/ approximately 26 VDs).

Bug: 64487466
Test: SystemUiJankTests#testGoToFullShade
Change-Id: I5cad0b5df86e5eac3722ee8695fc7511b38b8a7c
parent 9552c2c9
Loading
Loading
Loading
Loading
+15 −28
Original line number Diff line number Diff line
@@ -511,22 +511,16 @@ void Tree::updateCache(sp<skiapipeline::VectorDrawableAtlas>& atlas, GrContext*
        }
    }
    if (!canReuseSurface || mCache.dirty) {
        draw(surface.get(), dst);
        mCache.dirty = false;
        if (surface) {
            Bitmap& bitmap = getBitmapUpdateIfDirty();
            SkBitmap skiaBitmap;
            bitmap.getSkBitmap(&skiaBitmap);
            if (!surface->getCanvas()->writePixels(skiaBitmap, dst.fLeft, dst.fTop)) {
                ALOGD("VectorDrawable caching failed to efficiently upload");
                surface->getCanvas()->drawBitmap(skiaBitmap, dst.fLeft, dst.fTop);
            }
        }

void Tree::draw(SkSurface* surface, const SkRect& dst) {
    if (surface) {
        SkCanvas* canvas = surface->getCanvas();
        float scaleX = dst.width() / mProperties.getViewportWidth();
        float scaleY = dst.height() / mProperties.getViewportHeight();
        SkAutoCanvasRestore acr(canvas, true);
        canvas->translate(dst.fLeft, dst.fTop);
        canvas->clipRect(SkRect::MakeWH(dst.width(), dst.height()));
        canvas->clear(SK_ColorTRANSPARENT);
        canvas->scale(scaleX, scaleY);
        mRootNode->draw(canvas, false);
        mCache.dirty = false;
    }
}

@@ -570,22 +564,15 @@ void Tree::draw(SkCanvas* canvas) {
        // Handle the case when VectorDrawableAtlas has been destroyed, because of memory pressure.
        // We render the VD into a temporary standalone buffer and mark the frame as dirty. Next
        // frame will be cached into the atlas.
        Bitmap& bitmap = getBitmapUpdateIfDirty();
        SkBitmap skiaBitmap;
        bitmap.getSkBitmap(&skiaBitmap);

        int scaledWidth = SkScalarCeilToInt(mProperties.getScaledWidth());
        int scaledHeight = SkScalarCeilToInt(mProperties.getScaledHeight());
        SkRect src = SkRect::MakeWH(scaledWidth, scaledHeight);
#ifndef ANDROID_ENABLE_LINEAR_BLENDING
        sk_sp<SkColorSpace> colorSpace = nullptr;
#else
        sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeSRGB();
#endif
        SkImageInfo info = SkImageInfo::MakeN32(scaledWidth, scaledHeight, kPremul_SkAlphaType,
                colorSpace);
        sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(canvas->getGrContext(),
                SkBudgeted::kYes, info);
        draw(surface.get(), src);
        canvas->drawBitmapRect(skiaBitmap, SkRect::MakeWH(scaledWidth, scaledHeight),
                        mutateProperties()->getBounds(), getPaint(), SkCanvas::kFast_SrcRectConstraint);
        mCache.clear();
        canvas->drawImageRect(surface->makeImageSnapshot().get(), mutateProperties()->getBounds(),
                getPaint(), SkCanvas::kFast_SrcRectConstraint);
        markDirty();
    }
}
+0 −5
Original line number Diff line number Diff line
@@ -738,11 +738,6 @@ private:
    bool canReuseBitmap(Bitmap*, int width, int height);
    void updateBitmapCache(Bitmap& outCache, bool useStagingData);

    /**
     * Draws the root node into "surface" at a given "dst" position.
     */
    void draw(SkSurface* surface, const SkRect& dst);

    // Cap the bitmap size, such that it won't hurt the performance too much
    // and it won't crash due to a very large scale.
    // The drawable will look blurry above this size.
+0 −1
Original line number Diff line number Diff line
@@ -199,7 +199,6 @@ void SkiaPipeline::renderVectorDrawableCache() {
        for (auto vd : mVectorDrawables) {
            vd->updateCache(atlas, grContext);
        }
        grContext->flush();
        mVectorDrawables.clear();
    }
}
+4 −1
Original line number Diff line number Diff line
@@ -270,7 +270,10 @@ sk_sp<SkSurface> VectorDrawableAtlas::createSurface(int width, int height, GrCon
    sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeSRGB();
#endif
    SkImageInfo info = SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType, colorSpace);
    return SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info);
    // This must have a top-left origin so that calls to surface->canvas->writePixels
    // performs a basic texture upload instead of a more complex drawing operation
    return SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0,
            kTopLeft_GrSurfaceOrigin, nullptr);
}

void VectorDrawableAtlas::setStorageMode(StorageMode mode) {