summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/hwui/DeferredLayerUpdater.cpp21
-rw-r--r--libs/hwui/DeferredLayerUpdater.h2
-rw-r--r--libs/hwui/Layer.cpp2
-rw-r--r--libs/hwui/Layer.h25
-rw-r--r--libs/hwui/Readback.cpp5
-rw-r--r--libs/hwui/pipeline/skia/LayerDrawable.cpp66
-rw-r--r--libs/hwui/tests/common/TestUtils.cpp2
-rw-r--r--libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp9
8 files changed, 62 insertions, 70 deletions
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 6cb53206f60b..8d112d1c64bf 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -21,6 +21,7 @@
// TODO: Use public SurfaceTexture APIs once available and include public NDK header file instead.
#include <surfacetexture/surface_texture_platform.h>
#include "AutoBackendTextureRelease.h"
+#include "Matrix.h"
#include "Properties.h"
#include "renderstate/RenderState.h"
#include "renderthread/EglManager.h"
@@ -144,17 +145,16 @@ void DeferredLayerUpdater::apply() {
}
if (mUpdateTexImage) {
mUpdateTexImage = false;
+ float transformMatrix[16];
android_dataspace dataspace;
int slot;
bool newContent = false;
- ARect rect;
- uint32_t textureTransform;
// Note: ASurfaceTexture_dequeueBuffer discards all but the last frame. This
// is necessary if the SurfaceTexture queue is in synchronous mode, and we
// cannot tell which mode it is in.
AHardwareBuffer* hardwareBuffer = ASurfaceTexture_dequeueBuffer(
- mSurfaceTexture.get(), &slot, &dataspace, &newContent, createReleaseFence,
- fenceWait, this, &rect, &textureTransform);
+ mSurfaceTexture.get(), &slot, &dataspace, transformMatrix, &newContent,
+ createReleaseFence, fenceWait, this);
if (hardwareBuffer) {
mCurrentSlot = slot;
@@ -165,12 +165,12 @@ void DeferredLayerUpdater::apply() {
// (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();
- SkRect cropRect =
- SkRect::MakeLTRB(rect.left, rect.top, rect.right, rect.bottom);
- updateLayer(forceFilter, textureTransform, cropRect, layerImage);
+ updateLayer(forceFilter, textureTransform, layerImage);
}
}
}
@@ -182,13 +182,12 @@ void DeferredLayerUpdater::apply() {
}
}
-void DeferredLayerUpdater::updateLayer(bool forceFilter, const uint32_t textureTransform,
- const SkRect cropRect, const sk_sp<SkImage>& layerImage) {
+void DeferredLayerUpdater::updateLayer(bool forceFilter, const SkMatrix& textureTransform,
+ const sk_sp<SkImage>& layerImage) {
mLayer->setBlend(mBlend);
mLayer->setForceFilter(forceFilter);
mLayer->setSize(mWidth, mHeight);
- mLayer->setTextureTransform(textureTransform);
- mLayer->setCropRect(cropRect);
+ mLayer->getTexTransform() = textureTransform;
mLayer->setImage(layerImage);
}
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 7a63ccd4250d..8f79c4ec97b8 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -90,7 +90,7 @@ public:
void detachSurfaceTexture();
- void updateLayer(bool forceFilter, const uint32_t textureTransform, const SkRect cropRect,
+ void updateLayer(bool forceFilter, const SkMatrix& textureTransform,
const sk_sp<SkImage>& layerImage);
void destroyLayer();
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 9053c1240957..47c47e0427a4 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -35,6 +35,7 @@ Layer::Layer(RenderState& renderState, sk_sp<SkColorFilter> colorFilter, int alp
// preserves the old inc/dec ref locations. This should be changed...
incStrong(nullptr);
renderState.registerLayer(this);
+ texTransform.setIdentity();
transform.setIdentity();
}
@@ -100,6 +101,7 @@ void Layer::draw(SkCanvas* canvas) {
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 656a81783716..e99e76299317 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -74,17 +74,9 @@ public:
void setColorFilter(sk_sp<SkColorFilter> filter) { mColorFilter = filter; };
- inline SkMatrix& getTransform() { return transform; }
-
- inline SkRect getCropRect() { return mCropRect; }
+ inline SkMatrix& getTexTransform() { return texTransform; }
- inline void setCropRect(const SkRect cropRect) { mCropRect = cropRect; }
-
- inline void setTextureTransform(uint32_t textureTransform) {
- mTextureTransform = textureTransform;
- }
-
- inline uint32_t getTextureTransform() { return mTextureTransform; }
+ inline SkMatrix& getTransform() { return transform; }
/**
* Posts a decStrong call to the appropriate thread.
@@ -124,19 +116,14 @@ private:
SkBlendMode mode;
/**
- * Optional transform.
+ * Optional texture coordinates transform.
*/
- SkMatrix transform;
-
- /**
- * Optional crop
- */
- SkRect mCropRect;
+ SkMatrix texTransform;
/**
- * Optional transform
+ * Optional transform.
*/
- uint32_t mTextureTransform;
+ SkMatrix transform;
/**
* An image backing the layer.
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index 386c88a35d85..a743d30939d0 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -251,6 +251,8 @@ CopyResult Readback::copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap) {
Rect srcRect;
Matrix4 transform;
+ transform.loadScale(1, -1, 1);
+ transform.translate(0, -1);
return copyImageInto(hwBitmap->makeImage(), transform, srcRect, bitmap);
}
@@ -278,6 +280,8 @@ CopyResult Readback::copyLayerInto(DeferredLayerUpdater* deferredLayer, SkBitmap
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);
}
@@ -316,6 +320,7 @@ CopyResult Readback::copyImageInto(const sk_sp<SkImage>& image, Matrix4& texTran
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/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index b28277c42cb5..e32788c9ec51 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -18,11 +18,9 @@
#include <utils/MathUtils.h>
#include "GrBackendSurface.h"
-#include "Matrix.h"
#include "SkColorFilter.h"
#include "SkSurface.h"
#include "gl/GrGLTypes.h"
-#include "system/window.h"
namespace android {
namespace uirenderer {
@@ -31,8 +29,7 @@ namespace skiapipeline {
void LayerDrawable::onDraw(SkCanvas* canvas) {
Layer* layer = mLayerUpdater->backingLayer();
if (layer) {
- SkRect srcRect = layer->getCropRect();
- DrawLayer(canvas->recordingContext(), canvas, layer, &srcRect, nullptr, true);
+ DrawLayer(canvas->recordingContext(), canvas, layer, nullptr, nullptr, true);
}
}
@@ -82,16 +79,33 @@ bool LayerDrawable::DrawLayer(GrRecordingContext* context,
return false;
}
// transform the matrix based on the layer
- const uint32_t transform = layer->getTextureTransform();
+ SkMatrix layerTransform = layer->getTransform();
sk_sp<SkImage> layerImage = layer->getImage();
const int layerWidth = layer->getWidth();
const int layerHeight = layer->getHeight();
- SkMatrix layerTransform = layer->getTransform();
+
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;
+ }
+
SkMatrix matrix;
if (useLayerTransform) {
- matrix = layerTransform;
+ matrix = SkMatrix::Concat(layerTransform, textureMatrix);
+ } else {
+ matrix = textureMatrix;
}
+
SkPaint paint;
paint.setAlpha(layer->getAlpha());
paint.setBlendMode(layer->getMode());
@@ -101,54 +115,39 @@ bool LayerDrawable::DrawLayer(GrRecordingContext* context,
canvas->save();
canvas->concat(matrix);
}
- const SkMatrix totalMatrix = canvas->getTotalMatrix();
+ const SkMatrix& totalMatrix = canvas->getTotalMatrix();
if (dstRect || srcRect) {
SkMatrix matrixInv;
if (!matrix.invert(&matrixInv)) {
matrixInv = matrix;
}
SkRect skiaSrcRect;
- if (srcRect && !srcRect->isEmpty()) {
+ if (srcRect) {
skiaSrcRect = *srcRect;
} else {
- skiaSrcRect = (transform & NATIVE_WINDOW_TRANSFORM_ROT_90)
- ? SkRect::MakeIWH(layerHeight, layerWidth)
- : SkRect::MakeIWH(layerWidth, layerHeight);
+ skiaSrcRect = SkRect::MakeIWH(layerWidth, layerHeight);
}
matrixInv.mapRect(&skiaSrcRect);
SkRect skiaDestRect;
- if (dstRect && !dstRect->isEmpty()) {
+ if (dstRect) {
skiaDestRect = *dstRect;
} else {
skiaDestRect = SkRect::MakeIWH(layerWidth, layerHeight);
}
matrixInv.mapRect(&skiaDestRect);
+ // If (matrix is a rect-to-rect transform)
+ // and (src/dst buffers size match in screen coordinates)
+ // and (src/dst corners align fractionally),
+ // then use nearest neighbor, otherwise use bilerp sampling.
+ // Skia TextureOp has the above logic build-in, but not NonAAFillRectOp. TextureOp works
+ // only for SrcOver blending and without color filter (readback uses Src blending).
SkSamplingOptions sampling(SkFilterMode::kNearest);
if (layer->getForceFilter() ||
shouldFilterRect(totalMatrix, skiaSrcRect, skiaDestRect)) {
sampling = SkSamplingOptions(SkFilterMode::kLinear);
}
-
- const float px = skiaDestRect.centerX();
- const float py = skiaDestRect.centerY();
- if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
- matrix.postScale(-1.f, 1.f, px, py);
- }
- if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
- matrix.postScale(1.f, -1.f, px, py);
- }
- if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- matrix.postRotate(90, 0, 0);
- matrix.postTranslate(skiaDestRect.height(), 0);
- }
- auto constraint = SkCanvas::kFast_SrcRectConstraint;
- if (srcRect && srcRect->isEmpty()) {
- constraint = SkCanvas::kStrict_SrcRectConstraint;
- }
- matrix.postConcat(SkMatrix::MakeRectToRect(skiaSrcRect, skiaDestRect,
- SkMatrix::kFill_ScaleToFit));
canvas->drawImageRect(layerImage.get(), skiaSrcRect, skiaDestRect, sampling, &paint,
- constraint);
+ SkCanvas::kFast_SrcRectConstraint);
} else {
SkRect imageRect = SkRect::MakeIWH(layerImage->width(), layerImage->height());
SkSamplingOptions sampling(SkFilterMode::kNearest);
@@ -162,6 +161,7 @@ bool LayerDrawable::DrawLayer(GrRecordingContext* context,
canvas->restore();
}
}
+
return layerImage != nullptr;
}
diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
index 1bfdc47a1d02..e8ba15fe92af 100644
--- a/libs/hwui/tests/common/TestUtils.cpp
+++ b/libs/hwui/tests/common/TestUtils.cpp
@@ -74,7 +74,7 @@ sp<DeferredLayerUpdater> TestUtils::createTextureLayerUpdater(
layerUpdater->setTransform(&transform);
// updateLayer so it's ready to draw
- layerUpdater->updateLayer(true, 0, SkRect::MakeEmpty(), nullptr);
+ layerUpdater->updateLayer(true, SkMatrix::I(), nullptr);
return layerUpdater;
}
diff --git a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
index ca84aeec96a2..955a5e7d8b3a 100644
--- a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
+++ b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
@@ -36,20 +36,19 @@ RENDERTHREAD_TEST(DeferredLayerUpdater, updateLayer) {
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
- uint32_t textureTransform = 1;
+ SkMatrix scaledMatrix = SkMatrix::Scale(0.5, 0.5);
SkBitmap bitmap;
bitmap.allocN32Pixels(16, 16);
- SkRect cropRect = SkRect::MakeIWH(10, 10);
sk_sp<SkImage> layerImage = SkImage::MakeFromBitmap(bitmap);
- layerUpdater->updateLayer(true, textureTransform, cropRect, layerImage);
+ layerUpdater->updateLayer(true, scaledMatrix, layerImage);
// 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(textureTransform, layerUpdater->backingLayer()->getTextureTransform());
- EXPECT_EQ(cropRect, layerUpdater->backingLayer()->getCropRect());
+ EXPECT_EQ(scaledMatrix, layerUpdater->backingLayer()->getTexTransform());
}