diff options
author | 2021-07-16 22:33:25 +0000 | |
---|---|---|
committer | 2021-08-03 20:32:16 +0000 | |
commit | ef54c038e1d650c000ee97fd5652eee98e9b8c32 (patch) | |
tree | 3ea1ba5a36c58da2da9b68af03f27d5be68a7a57 | |
parent | 3daec282d77c293774f28de766bb7b1aeadfb294 (diff) |
Added crop rect to LayerDrawable to not crop TextureView.
Verified manually with ExoPlayer that TextureView isn't cropping.
Test: Did the manual test and
atest TextureViewCameraTest
atest TextureViewSnapshotTest
atest TextureViewStressTest
atest TextureViewTest
atest PixelCopyTest
atest BitmapTest
atest HardwareBitmapTests
and with HwAccelerationTest
Added crop test at ag/15430851
BUG=152621633
Change-Id: If1f448a94908cbf51272bc0d1bbbe1e113fd15f3
-rw-r--r-- | libs/hwui/DeferredLayerUpdater.cpp | 21 | ||||
-rw-r--r-- | libs/hwui/DeferredLayerUpdater.h | 2 | ||||
-rw-r--r-- | libs/hwui/Layer.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/Layer.h | 25 | ||||
-rw-r--r-- | libs/hwui/Readback.cpp | 5 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/LayerDrawable.cpp | 66 | ||||
-rw-r--r-- | libs/hwui/tests/common/TestUtils.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp | 9 |
8 files changed, 70 insertions, 62 deletions
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp index 8d112d1c64bf..6cb53206f60b 100644 --- a/libs/hwui/DeferredLayerUpdater.cpp +++ b/libs/hwui/DeferredLayerUpdater.cpp @@ -21,7 +21,6 @@ // 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" @@ -145,16 +144,17 @@ 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, transformMatrix, &newContent, - createReleaseFence, fenceWait, this); + mSurfaceTexture.get(), &slot, &dataspace, &newContent, createReleaseFence, + fenceWait, this, &rect, &textureTransform); 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(); - updateLayer(forceFilter, textureTransform, layerImage); + SkRect cropRect = + SkRect::MakeLTRB(rect.left, rect.top, rect.right, rect.bottom); + updateLayer(forceFilter, textureTransform, cropRect, layerImage); } } } @@ -182,12 +182,13 @@ void DeferredLayerUpdater::apply() { } } -void DeferredLayerUpdater::updateLayer(bool forceFilter, const SkMatrix& textureTransform, - const sk_sp<SkImage>& layerImage) { +void DeferredLayerUpdater::updateLayer(bool forceFilter, const uint32_t textureTransform, + const SkRect cropRect, const sk_sp<SkImage>& layerImage) { mLayer->setBlend(mBlend); mLayer->setForceFilter(forceFilter); mLayer->setSize(mWidth, mHeight); - mLayer->getTexTransform() = textureTransform; + mLayer->setTextureTransform(textureTransform); + mLayer->setCropRect(cropRect); mLayer->setImage(layerImage); } diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h index 8f79c4ec97b8..7a63ccd4250d 100644 --- a/libs/hwui/DeferredLayerUpdater.h +++ b/libs/hwui/DeferredLayerUpdater.h @@ -90,7 +90,7 @@ public: void detachSurfaceTexture(); - void updateLayer(bool forceFilter, const SkMatrix& textureTransform, + void updateLayer(bool forceFilter, const uint32_t textureTransform, const SkRect cropRect, const sk_sp<SkImage>& layerImage); void destroyLayer(); diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp index 47c47e0427a4..9053c1240957 100644 --- a/libs/hwui/Layer.cpp +++ b/libs/hwui/Layer.cpp @@ -35,7 +35,6 @@ 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(); } @@ -101,7 +100,6 @@ 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 e99e76299317..656a81783716 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -74,10 +74,18 @@ public: void setColorFilter(sk_sp<SkColorFilter> filter) { mColorFilter = filter; }; - inline SkMatrix& getTexTransform() { return texTransform; } - inline SkMatrix& getTransform() { return transform; } + inline SkRect getCropRect() { return mCropRect; } + + inline void setCropRect(const SkRect cropRect) { mCropRect = cropRect; } + + inline void setTextureTransform(uint32_t textureTransform) { + mTextureTransform = textureTransform; + } + + inline uint32_t getTextureTransform() { return mTextureTransform; } + /** * Posts a decStrong call to the appropriate thread. * Thread-safe. @@ -116,14 +124,19 @@ private: SkBlendMode mode; /** - * Optional texture coordinates transform. + * Optional transform. */ - SkMatrix texTransform; + SkMatrix transform; /** - * Optional transform. + * Optional crop */ - SkMatrix transform; + SkRect mCropRect; + + /** + * Optional transform + */ + uint32_t mTextureTransform; /** * An image backing the layer. diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp index a743d30939d0..386c88a35d85 100644 --- a/libs/hwui/Readback.cpp +++ b/libs/hwui/Readback.cpp @@ -251,8 +251,6 @@ 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); } @@ -280,8 +278,6 @@ 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); } @@ -320,7 +316,6 @@ 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 e32788c9ec51..b28277c42cb5 100644 --- a/libs/hwui/pipeline/skia/LayerDrawable.cpp +++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp @@ -18,9 +18,11 @@ #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 { @@ -29,7 +31,8 @@ namespace skiapipeline { void LayerDrawable::onDraw(SkCanvas* canvas) { Layer* layer = mLayerUpdater->backingLayer(); if (layer) { - DrawLayer(canvas->recordingContext(), canvas, layer, nullptr, nullptr, true); + SkRect srcRect = layer->getCropRect(); + DrawLayer(canvas->recordingContext(), canvas, layer, &srcRect, nullptr, true); } } @@ -79,33 +82,16 @@ bool LayerDrawable::DrawLayer(GrRecordingContext* context, return false; } // transform the matrix based on the layer - SkMatrix layerTransform = layer->getTransform(); + const uint32_t transform = layer->getTextureTransform(); 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 = SkMatrix::Concat(layerTransform, textureMatrix); - } else { - matrix = textureMatrix; + matrix = layerTransform; } - SkPaint paint; paint.setAlpha(layer->getAlpha()); paint.setBlendMode(layer->getMode()); @@ -115,39 +101,54 @@ 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) { + if (srcRect && !srcRect->isEmpty()) { skiaSrcRect = *srcRect; } else { - skiaSrcRect = SkRect::MakeIWH(layerWidth, layerHeight); + skiaSrcRect = (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) + ? SkRect::MakeIWH(layerHeight, layerWidth) + : SkRect::MakeIWH(layerWidth, layerHeight); } matrixInv.mapRect(&skiaSrcRect); SkRect skiaDestRect; - if (dstRect) { + if (dstRect && !dstRect->isEmpty()) { 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, - SkCanvas::kFast_SrcRectConstraint); + constraint); } else { SkRect imageRect = SkRect::MakeIWH(layerImage->width(), layerImage->height()); SkSamplingOptions sampling(SkFilterMode::kNearest); @@ -161,7 +162,6 @@ 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 e8ba15fe92af..1bfdc47a1d02 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, SkMatrix::I(), nullptr); + layerUpdater->updateLayer(true, 0, SkRect::MakeEmpty(), nullptr); return layerUpdater; } diff --git a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp index 955a5e7d8b3a..ca84aeec96a2 100644 --- a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp +++ b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp @@ -36,19 +36,20 @@ 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 - SkMatrix scaledMatrix = SkMatrix::Scale(0.5, 0.5); + uint32_t textureTransform = 1; SkBitmap bitmap; bitmap.allocN32Pixels(16, 16); + SkRect cropRect = SkRect::MakeIWH(10, 10); sk_sp<SkImage> layerImage = SkImage::MakeFromBitmap(bitmap); - layerUpdater->updateLayer(true, scaledMatrix, layerImage); + layerUpdater->updateLayer(true, textureTransform, cropRect, 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(scaledMatrix, layerUpdater->backingLayer()->getTexTransform()); + EXPECT_EQ(textureTransform, layerUpdater->backingLayer()->getTextureTransform()); + EXPECT_EQ(cropRect, layerUpdater->backingLayer()->getCropRect()); } |