Fix Skia's impl for TextureView.getBitmap

Bug: 73392905
Test: New test added with I2d4ef440f943a50b9367976ba1444f4350071bfd

When providing a width and height, getBitmap should scale to the
destination. Add a parameter to LayerDrawable::DrawLayer for a
destination rectangle to scale to. Pass the size of the bitmap in
SkiaOpenGLPipeline::copyLayerInto down to DrawLayer. The only other
caller of DrawLayer is unaffected.

Change-Id: I7aa192181c2d15bc8fd4de2fb15c4d276b05d2ac
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index d9584db..293e45f 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -34,7 +34,8 @@
     }
 }
 
-bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer) {
+bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer,
+                              const SkRect* dstRect) {
     if (context == nullptr) {
         SkDEBUGF(("Attempting to draw LayerDrawable into an unsupported surface"));
         return false;
@@ -43,8 +44,8 @@
     SkMatrix layerTransform;
     layer->getTransform().copyTo(layerTransform);
     sk_sp<SkImage> layerImage;
-    int layerWidth = layer->getWidth();
-    int layerHeight = layer->getHeight();
+    const int layerWidth = layer->getWidth();
+    const int layerHeight = layer->getHeight();
     if (layer->getApi() == Layer::Api::OpenGL) {
         GlLayer* glLayer = static_cast<GlLayer*>(layer);
         GrGLTextureInfo externalTexture;
@@ -62,21 +63,21 @@
     }
 
     if (layerImage) {
-        SkMatrix textureMatrix;
-        layer->getTexTransform().copyTo(textureMatrix);
+        SkMatrix textureMatrixInv;
+        layer->getTexTransform().copyTo(textureMatrixInv);
         // TODO: after skia bug https://bugs.chromium.org/p/skia/issues/detail?id=7075 is fixed
         // use bottom left origin and remove flipV and invert transformations.
         SkMatrix flipV;
         flipV.setAll(1, 0, 0, 0, -1, 1, 0, 0, 1);
-        textureMatrix.preConcat(flipV);
-        textureMatrix.preScale(1.0f / layerWidth, 1.0f / layerHeight);
-        textureMatrix.postScale(layerWidth, layerHeight);
-        SkMatrix textureMatrixInv;
-        if (!textureMatrix.invert(&textureMatrixInv)) {
-            textureMatrixInv = textureMatrix;
+        textureMatrixInv.preConcat(flipV);
+        textureMatrixInv.preScale(1.0f / layerWidth, 1.0f / layerHeight);
+        textureMatrixInv.postScale(layerWidth, layerHeight);
+        SkMatrix textureMatrix;
+        if (!textureMatrixInv.invert(&textureMatrix)) {
+            textureMatrix = textureMatrixInv;
         }
 
-        SkMatrix matrix = SkMatrix::Concat(layerTransform, textureMatrixInv);
+        SkMatrix matrix = SkMatrix::Concat(layerTransform, textureMatrix);
 
         SkPaint paint;
         paint.setAlpha(layer->getAlpha());
@@ -88,7 +89,20 @@
             canvas->save();
             canvas->concat(matrix);
         }
-        canvas->drawImage(layerImage.get(), 0, 0, &paint);
+        if (dstRect) {
+            SkMatrix matrixInv;
+            if (!matrix.invert(&matrixInv)) {
+                matrixInv = matrix;
+            }
+            SkRect srcRect = SkRect::MakeIWH(layerWidth, layerHeight);
+            matrixInv.mapRect(&srcRect);
+            SkRect skiaDestRect = *dstRect;
+            matrixInv.mapRect(&skiaDestRect);
+            canvas->drawImageRect(layerImage.get(), srcRect, skiaDestRect, &paint,
+                                  SkCanvas::kFast_SrcRectConstraint);
+        } else {
+            canvas->drawImage(layerImage.get(), 0, 0, &paint);
+        }
         // restore the original matrix
         if (nonIdentityMatrix) {
             canvas->restore();