Added crop rect and removed inverse of the texture matrix.
BUG=152621633
Test: Verified manually and with
atest TextureViewCameraTest
atest TextureViewTest
atest TextureViewSnapshotTest
atest TextureViewStressTest
atest PixelCopyTest
atest BitmapTest
atest HardwareBitmapTests
Change-Id: Ie993a18fd3511576617a1eb859bf228c33d12f78
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 2b86b1e..0b3b393 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -167,12 +167,13 @@
// (invoked by createIfNeeded) will add a ref to the AHardwareBuffer.
AHardwareBuffer_release(hardwareBuffer);
if (layerImage.get()) {
- SkMatrix textureTransform;
- mat4(transformMatrix).copyTo(textureTransform);
// force filtration if buffer size != layer size
bool forceFilter =
mWidth != layerImage->width() || mHeight != layerImage->height();
- updateLayer(forceFilter, textureTransform, layerImage);
+ SkRect currentCropRect =
+ SkRect::MakeLTRB(currentCrop.left, currentCrop.top, currentCrop.right,
+ currentCrop.bottom);
+ updateLayer(forceFilter, layerImage, outTransform, currentCropRect);
}
}
}
@@ -184,12 +185,13 @@
}
}
-void DeferredLayerUpdater::updateLayer(bool forceFilter, const SkMatrix& textureTransform,
- const sk_sp<SkImage>& layerImage) {
+void DeferredLayerUpdater::updateLayer(bool forceFilter, const sk_sp<SkImage>& layerImage,
+ const uint32_t transform, SkRect currentCrop) {
mLayer->setBlend(mBlend);
mLayer->setForceFilter(forceFilter);
mLayer->setSize(mWidth, mHeight);
- mLayer->getTexTransform() = textureTransform;
+ mLayer->setCurrentCropRect(currentCrop);
+ mLayer->setWindowTransform(transform);
mLayer->setImage(layerImage);
}
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 8f79c4e..da8041f 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -90,8 +90,8 @@
void detachSurfaceTexture();
- void updateLayer(bool forceFilter, const SkMatrix& textureTransform,
- const sk_sp<SkImage>& layerImage);
+ void updateLayer(bool forceFilter, const sk_sp<SkImage>& layerImage, const uint32_t transform,
+ SkRect currentCrop);
void destroyLayer();
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 47c47e0..9053c12 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -35,7 +35,6 @@
// preserves the old inc/dec ref locations. This should be changed...
incStrong(nullptr);
renderState.registerLayer(this);
- texTransform.setIdentity();
transform.setIdentity();
}
@@ -101,7 +100,6 @@
const int layerHeight = getHeight();
if (layerImage) {
SkMatrix textureMatrixInv;
- textureMatrixInv = getTexTransform();
// 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;
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index e99e762..0789344 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -74,10 +74,18 @@
void setColorFilter(sk_sp<SkColorFilter> filter) { mColorFilter = filter; };
- inline SkMatrix& getTexTransform() { return texTransform; }
-
inline SkMatrix& getTransform() { return transform; }
+ inline SkRect getCurrentCropRect() { return mCurrentCropRect; }
+
+ inline void setCurrentCropRect(const SkRect currentCropRect) {
+ mCurrentCropRect = currentCropRect;
+ }
+
+ inline void setWindowTransform(uint32_t windowTransform) { mWindowTransform = windowTransform; }
+
+ inline uint32_t getWindowTransform() { return mWindowTransform; }
+
/**
* Posts a decStrong call to the appropriate thread.
* Thread-safe.
@@ -116,16 +124,21 @@
SkBlendMode mode;
/**
- * Optional texture coordinates transform.
- */
- SkMatrix texTransform;
-
- /**
* Optional transform.
*/
SkMatrix transform;
/**
+ * Optional crop
+ */
+ SkRect mCurrentCropRect;
+
+ /**
+ * Optional transform
+ */
+ uint32_t mWindowTransform;
+
+ /**
* An image backing the layer.
*/
sk_sp<SkImage> layerImage;
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index a743d30..4cce87a 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -243,18 +243,14 @@
static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(window)));
sk_sp<SkImage> image =
SkImage::MakeFromAHardwareBuffer(sourceBuffer.get(), kPremul_SkAlphaType, colorSpace);
- return copyImageInto(image, texTransform, srcRect, bitmap);
+ return copyImageInto(image, srcRect, bitmap);
}
CopyResult Readback::copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap) {
LOG_ALWAYS_FATAL_IF(!hwBitmap->isHardware());
Rect srcRect;
- Matrix4 transform;
- transform.loadScale(1, -1, 1);
- transform.translate(0, -1);
-
- return copyImageInto(hwBitmap->makeImage(), transform, srcRect, bitmap);
+ return copyImageInto(hwBitmap->makeImage(), srcRect, bitmap);
}
CopyResult Readback::copyLayerInto(DeferredLayerUpdater* deferredLayer, SkBitmap* bitmap) {
@@ -279,14 +275,11 @@
CopyResult Readback::copyImageInto(const sk_sp<SkImage>& image, SkBitmap* bitmap) {
Rect srcRect;
- Matrix4 transform;
- transform.loadScale(1, -1, 1);
- transform.translate(0, -1);
- return copyImageInto(image, transform, srcRect, bitmap);
+ return copyImageInto(image, srcRect, bitmap);
}
-CopyResult Readback::copyImageInto(const sk_sp<SkImage>& image, Matrix4& texTransform,
- const Rect& srcRect, SkBitmap* bitmap) {
+CopyResult Readback::copyImageInto(const sk_sp<SkImage>& image, const Rect& srcRect,
+ SkBitmap* bitmap) {
ATRACE_CALL();
if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
mRenderThread.requireGlContext();
@@ -303,11 +296,6 @@
CopyResult copyResult = CopyResult::UnknownError;
int displayedWidth = imgWidth, displayedHeight = imgHeight;
- // If this is a 90 or 270 degree rotation we need to swap width/height to get the device
- // size.
- if (texTransform[Matrix4::kSkewX] >= 0.5f || texTransform[Matrix4::kSkewX] <= -0.5f) {
- std::swap(displayedWidth, displayedHeight);
- }
SkRect skiaDestRect = SkRect::MakeWH(bitmap->width(), bitmap->height());
SkRect skiaSrcRect = srcRect.toSkRect();
if (skiaSrcRect.isEmpty()) {
@@ -320,7 +308,6 @@
Layer layer(mRenderThread.renderState(), nullptr, 255, SkBlendMode::kSrc);
layer.setSize(displayedWidth, displayedHeight);
- texTransform.copyTo(layer.getTexTransform());
layer.setImage(image);
// Scaling filter is not explicitly set here, because it is done inside copyLayerInfo
// after checking the necessity based on the src/dest rect size and the transformation.
diff --git a/libs/hwui/Readback.h b/libs/hwui/Readback.h
index da25269..d0d748f 100644
--- a/libs/hwui/Readback.h
+++ b/libs/hwui/Readback.h
@@ -56,8 +56,7 @@
private:
CopyResult copySurfaceIntoLegacy(ANativeWindow* window, const Rect& srcRect, SkBitmap* bitmap);
- CopyResult copyImageInto(const sk_sp<SkImage>& image, Matrix4& texTransform,
- const Rect& srcRect, SkBitmap* bitmap);
+ CopyResult copyImageInto(const sk_sp<SkImage>& image, const Rect& srcRect, SkBitmap* bitmap);
bool copyLayerInto(Layer* layer, const SkRect* srcRect, const SkRect* dstRect,
SkBitmap* bitmap);
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index e32788c..6db7170 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -21,6 +21,7 @@
#include "SkColorFilter.h"
#include "SkSurface.h"
#include "gl/GrGLTypes.h"
+#include "system/window.h"
namespace android {
namespace uirenderer {
@@ -29,7 +30,8 @@
void LayerDrawable::onDraw(SkCanvas* canvas) {
Layer* layer = mLayerUpdater->backingLayer();
if (layer) {
- DrawLayer(canvas->recordingContext(), canvas, layer, nullptr, nullptr, true);
+ SkRect srcRect = layer->getCurrentCropRect();
+ DrawLayer(canvas->recordingContext(), canvas, layer, &srcRect, nullptr, true);
}
}
@@ -79,62 +81,63 @@
return false;
}
// transform the matrix based on the layer
- SkMatrix layerTransform = layer->getTransform();
+ // SkMatrix layerTransform = layer->getTransform();
+ const uint32_t windowTransform = layer->getWindowTransform();
sk_sp<SkImage> layerImage = layer->getImage();
const int layerWidth = layer->getWidth();
const int layerHeight = layer->getHeight();
if (layerImage) {
- SkMatrix textureMatrixInv;
- textureMatrixInv = layer->getTexTransform();
- // 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);
- textureMatrixInv.preConcat(flipV);
- textureMatrixInv.preScale(1.0f / layerWidth, 1.0f / layerHeight);
- textureMatrixInv.postScale(layerImage->width(), layerImage->height());
- SkMatrix textureMatrix;
- if (!textureMatrixInv.invert(&textureMatrix)) {
- textureMatrix = textureMatrixInv;
- }
+ const int imageWidth = layerImage->width();
+ const int imageHeight = layerImage->height();
- SkMatrix matrix;
if (useLayerTransform) {
- matrix = SkMatrix::Concat(layerTransform, textureMatrix);
- } else {
- matrix = textureMatrix;
+ canvas->save();
+ canvas->concat(layer->getTransform());
}
SkPaint paint;
paint.setAlpha(layer->getAlpha());
paint.setBlendMode(layer->getMode());
paint.setColorFilter(layer->getColorFilter());
- const bool nonIdentityMatrix = !matrix.isIdentity();
- if (nonIdentityMatrix) {
- canvas->save();
- canvas->concat(matrix);
- }
const SkMatrix& totalMatrix = canvas->getTotalMatrix();
- if (dstRect || srcRect) {
- SkMatrix matrixInv;
- if (!matrix.invert(&matrixInv)) {
- matrixInv = matrix;
- }
+ if (srcRect || dstRect) {
SkRect skiaSrcRect;
- if (srcRect) {
+ if (srcRect && !srcRect->isEmpty()) {
skiaSrcRect = *srcRect;
} else {
- skiaSrcRect = SkRect::MakeIWH(layerWidth, layerHeight);
+ skiaSrcRect = SkRect::MakeIWH(imageWidth, imageHeight);
}
- matrixInv.mapRect(&skiaSrcRect);
SkRect skiaDestRect;
- if (dstRect) {
+ if (dstRect && !dstRect->isEmpty()) {
skiaDestRect = *dstRect;
} else {
- skiaDestRect = SkRect::MakeIWH(layerWidth, layerHeight);
+ skiaDestRect = (windowTransform & NATIVE_WINDOW_TRANSFORM_ROT_90)
+ ? SkRect::MakeIWH(layerHeight, layerWidth)
+ : SkRect::MakeIWH(layerWidth, layerHeight);
}
- matrixInv.mapRect(&skiaDestRect);
+
+ const float px = skiaDestRect.centerX();
+ const float py = skiaDestRect.centerY();
+ SkMatrix m;
+ if (windowTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
+ m.postScale(-1.f, 1.f, px, py);
+ }
+ if (windowTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
+ m.postScale(1.f, -1.f, px, py);
+ }
+ if (windowTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+ m.postRotate(90, 0, 0);
+ m.postTranslate(skiaDestRect.height(), 0);
+ }
+ auto constraint = SkCanvas::kFast_SrcRectConstraint;
+ if (srcRect && !srcRect->isEmpty()) {
+ constraint = SkCanvas::kStrict_SrcRectConstraint;
+ }
+
+ canvas->save();
+ canvas->concat(m);
+
// If (matrix is a rect-to-rect transform)
// and (src/dst buffers size match in screen coordinates)
// and (src/dst corners align fractionally),
@@ -146,18 +149,13 @@
shouldFilterRect(totalMatrix, skiaSrcRect, skiaDestRect)) {
sampling = SkSamplingOptions(SkFilterMode::kLinear);
}
+
canvas->drawImageRect(layerImage.get(), skiaSrcRect, skiaDestRect, sampling, &paint,
- SkCanvas::kFast_SrcRectConstraint);
- } else {
- SkRect imageRect = SkRect::MakeIWH(layerImage->width(), layerImage->height());
- SkSamplingOptions sampling(SkFilterMode::kNearest);
- if (layer->getForceFilter() || shouldFilterRect(totalMatrix, imageRect, imageRect)) {
- sampling = SkSamplingOptions(SkFilterMode::kLinear);
- }
- canvas->drawImage(layerImage.get(), 0, 0, sampling, &paint);
+ constraint);
+ canvas->restore();
}
// restore the original matrix
- if (nonIdentityMatrix) {
+ if (useLayerTransform) {
canvas->restore();
}
}
diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
index e8ba15f..491af43 100644
--- a/libs/hwui/tests/common/TestUtils.cpp
+++ b/libs/hwui/tests/common/TestUtils.cpp
@@ -74,7 +74,7 @@
layerUpdater->setTransform(&transform);
// updateLayer so it's ready to draw
- layerUpdater->updateLayer(true, SkMatrix::I(), nullptr);
+ layerUpdater->updateLayer(true, nullptr, 0, SkRect::MakeEmpty());
return layerUpdater;
}
diff --git a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
index 955a5e7..0c389bfe8 100644
--- a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
+++ b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
@@ -36,19 +36,16 @@
EXPECT_EQ(0u, layerUpdater->backingLayer()->getHeight());
EXPECT_FALSE(layerUpdater->backingLayer()->getForceFilter());
EXPECT_FALSE(layerUpdater->backingLayer()->isBlend());
- EXPECT_EQ(Matrix4::identity(), layerUpdater->backingLayer()->getTexTransform());
// push the deferred updates to the layer
- SkMatrix scaledMatrix = SkMatrix::Scale(0.5, 0.5);
SkBitmap bitmap;
bitmap.allocN32Pixels(16, 16);
sk_sp<SkImage> layerImage = SkImage::MakeFromBitmap(bitmap);
- layerUpdater->updateLayer(true, scaledMatrix, layerImage);
+ layerUpdater->updateLayer(true, layerImage, 0, SkRect::MakeEmpty());
// the backing layer should now have all the properties applied.
EXPECT_EQ(100u, layerUpdater->backingLayer()->getWidth());
EXPECT_EQ(100u, layerUpdater->backingLayer()->getHeight());
EXPECT_TRUE(layerUpdater->backingLayer()->getForceFilter());
EXPECT_TRUE(layerUpdater->backingLayer()->isBlend());
- EXPECT_EQ(scaledMatrix, layerUpdater->backingLayer()->getTexTransform());
}