diff options
Diffstat (limited to 'libs')
-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, 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()); } |