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
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index f4ce864..e0373ca 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -511,25 +511,19 @@
         }
     }
     if (!canReuseSurface || mCache.dirty) {
-        draw(surface.get(), dst);
+        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);
+            }
+        }
         mCache.dirty = false;
     }
 }
 
-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);
-    }
-}
-
 void Tree::Cache::setAtlas(sp<skiapipeline::VectorDrawableAtlas> newAtlas,
         skiapipeline::AtlasKey newAtlasKey) {
     LOG_ALWAYS_FATAL_IF(newAtlasKey == INVALID_ATLAS_KEY);
@@ -570,22 +564,15 @@
         // 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();
     }
 }