From 93ac4012f2453e9a68a554ebba266f3ddd03d9f0 Mon Sep 17 00:00:00 2001 From: Stan Iliev Date: Mon, 10 Sep 2018 14:48:38 -0400 Subject: DO NOT MERGE: Use GL_LINEAR filter when drawing scaled TextureView Use GL_LINEAR instead of GL_NEAREST sampling, when drawing a TextureView, which has a buffer size that does not match layer size. Scale SkImage to layer size with a matrix, instead of passing wrong size to MakeFromTexture. This CL must not be merged in master, becase this issue has been fixed already by ag/4936023. Bug: 114324288 Test: Passed CtsViewTestCases and CtsUiRenderingTestCases Test: Ran apps using scaled TextureView including Instagram Change-Id: I9ee659d08998c932d8b708a64f3c879ab696fd9e --- libs/hwui/DeferredLayerUpdater.cpp | 5 +++-- libs/hwui/Layer.h | 12 ++++++++++++ libs/hwui/pipeline/skia/LayerDrawable.cpp | 12 ++++++++++-- 3 files changed, 25 insertions(+), 4 deletions(-) (limited to 'libs') diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp index 569de76f294e..c060740dc9a4 100644 --- a/libs/hwui/DeferredLayerUpdater.cpp +++ b/libs/hwui/DeferredLayerUpdater.cpp @@ -133,9 +133,10 @@ void DeferredLayerUpdater::doUpdateTexImage() { bool forceFilter = false; sp buffer = mSurfaceTexture->getCurrentBuffer(); if (buffer != nullptr) { + mLayer->setBufferSize(buffer->getWidth(), buffer->getHeight()); // force filtration if buffer size != layer size - forceFilter = mWidth != static_cast(buffer->getWidth()) || - mHeight != static_cast(buffer->getHeight()); + forceFilter = mWidth != static_cast(mLayer->getBufferWidth()) || + mHeight != static_cast(mLayer->getBufferHeight()); } #if DEBUG_RENDERER diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index 89bcddcc96d0..acaeab1b0068 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -94,6 +94,15 @@ public: */ void postDecStrong(); + inline void setBufferSize(uint32_t width, uint32_t height) { + mBufferWidth = width; + mBufferHeight = height; + } + + inline uint32_t getBufferWidth() const { return mBufferWidth; } + + inline uint32_t getBufferHeight() const { return mBufferHeight; } + protected: Layer(RenderState& renderState, Api api, sk_sp, int alpha, SkBlendMode mode); @@ -145,6 +154,9 @@ private: */ mat4 transform; + uint32_t mBufferWidth = 0; + + uint32_t mBufferHeight = 0; }; // struct Layer }; // namespace uirenderer diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp index 6e7511da07ff..093c7cf62cd2 100644 --- a/libs/hwui/pipeline/skia/LayerDrawable.cpp +++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp @@ -46,6 +46,11 @@ bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer sk_sp layerImage; const int layerWidth = layer->getWidth(); const int layerHeight = layer->getHeight(); + const int bufferWidth = layer->getBufferWidth(); + const int bufferHeight = layer->getBufferHeight(); + if (bufferWidth <= 0 || bufferHeight <=0) { + return false; + } if (layer->getApi() == Layer::Api::OpenGL) { GlLayer* glLayer = static_cast(layer); GrGLTextureInfo externalTexture; @@ -57,7 +62,7 @@ bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer // this is anticipated to have is that for some format types if we are not bound as an OES // texture we may get invalid results for SKP capture if we read back the texture. externalTexture.fFormat = GL_RGBA8; - GrBackendTexture backendTexture(layerWidth, layerHeight, GrMipMapped::kNo, externalTexture); + GrBackendTexture backendTexture(bufferWidth, bufferHeight, GrMipMapped::kNo, externalTexture); layerImage = SkImage::MakeFromTexture(context, backendTexture, kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, nullptr); } else { @@ -76,7 +81,7 @@ bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer flipV.setAll(1, 0, 0, 0, -1, 1, 0, 0, 1); textureMatrixInv.preConcat(flipV); textureMatrixInv.preScale(1.0f / layerWidth, 1.0f / layerHeight); - textureMatrixInv.postScale(layerWidth, layerHeight); + textureMatrixInv.postScale(bufferWidth, bufferHeight); SkMatrix textureMatrix; if (!textureMatrixInv.invert(&textureMatrix)) { textureMatrix = textureMatrixInv; @@ -95,6 +100,9 @@ bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer paint.setAlpha(layer->getAlpha()); paint.setBlendMode(layer->getMode()); paint.setColorFilter(layer->getColorSpaceWithFilter()); + if (layer->getForceFilter()) { + paint.setFilterQuality(kLow_SkFilterQuality); + } const bool nonIdentityMatrix = !matrix.isIdentity(); if (nonIdentityMatrix) { -- cgit v1.2.3-59-g8ed1b From 9b7887736a2af9806e30447453b22b86c12969e5 Mon Sep 17 00:00:00 2001 From: Stan Iliev Date: Fri, 28 Sep 2018 18:44:26 -0400 Subject: Disable blending for opaque TextureView Opaque TextureView set by TextureView.setOpaque(true), should draw with SRC blending, which in practice disables GL blending. Test: Ran Naver app, which is using opaque TextureView Bug: 113845024 Change-Id: I5daa455a72b0ded50d6f9578f3b8a8701532f9d4 Merged-In: I5daa455a72b0ded50d6f9578f3b8a8701532f9d4 (cherry picked from commit 8fc3d8e09d7788a96559d31dc502e99fce4f1378) --- libs/hwui/GlLayer.cpp | 8 ++++++++ libs/hwui/GlLayer.h | 2 ++ libs/hwui/Layer.cpp | 4 ++-- libs/hwui/Layer.h | 12 ++++++------ 4 files changed, 18 insertions(+), 8 deletions(-) (limited to 'libs') diff --git a/libs/hwui/GlLayer.cpp b/libs/hwui/GlLayer.cpp index 42ae29d76898..8357f8ebde2e 100644 --- a/libs/hwui/GlLayer.cpp +++ b/libs/hwui/GlLayer.cpp @@ -72,5 +72,13 @@ void GlLayer::generateTexture() { } } +SkBlendMode GlLayer::getMode() const { + if (texture.blend || mode != SkBlendMode::kSrcOver) { + return mode; + } else { + return SkBlendMode::kSrc; + } +} + }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/GlLayer.h b/libs/hwui/GlLayer.h index 28749a0d125c..4cf8f2522ff9 100644 --- a/libs/hwui/GlLayer.h +++ b/libs/hwui/GlLayer.h @@ -66,6 +66,8 @@ public: */ void onGlContextLost(); + SkBlendMode getMode() const override; + private: Caches& caches; diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp index fb8f0337c95e..b86ae121af55 100644 --- a/libs/hwui/Layer.cpp +++ b/libs/hwui/Layer.cpp @@ -27,10 +27,10 @@ Layer::Layer(RenderState& renderState, Api api, sk_sp colorFilter SkBlendMode mode) : GpuMemoryTracker(GpuObjectType::Layer) , mRenderState(renderState) + , mode(mode) , mApi(api) , mColorFilter(colorFilter) - , alpha(alpha) - , mode(mode) { + , alpha(alpha) { // TODO: This is a violation of Android's typical ref counting, but it // preserves the old inc/dec ref locations. This should be changed... incStrong(nullptr); diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index 89bcddcc96d0..d2736adf2f56 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -72,7 +72,7 @@ public: inline int getAlpha() const { return alpha; } - inline SkBlendMode getMode() const { return mode; } + virtual SkBlendMode getMode() const { return mode; } inline SkColorFilter* getColorFilter() const { return mColorFilter.get(); } @@ -100,6 +100,11 @@ protected: RenderState& mRenderState; + /** + * Blending mode of the layer. + */ + SkBlendMode mode; + private: void buildColorSpaceWithFilter(); @@ -130,11 +135,6 @@ private: */ int alpha; - /** - * Blending mode of the layer. - */ - SkBlendMode mode; - /** * Optional texture coordinates transform. */ -- cgit v1.2.3-59-g8ed1b From 535fae32e597445a480896ea8e01662ada444c0c Mon Sep 17 00:00:00 2001 From: Tim Murray Date: Mon, 15 Oct 2018 16:29:15 -0700 Subject: hwui: purge malloc pages on bitmap destruction Immediately purge malloc pages on bitmap destruction. Bitmaps are often big and can cause memory to stay high for much longer than it should. Test: boots and works bug 117795621 Merged-in: If2e8c5f1fc07039cf3dc3edcd3dc06861dbce1a1 Change-Id: If2e8c5f1fc07039cf3dc3edcd3dc06861dbce1a1 --- libs/hwui/hwui/Bitmap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libs') diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp index 263d249d20e9..c6ef090c1f76 100644 --- a/libs/hwui/hwui/Bitmap.cpp +++ b/libs/hwui/hwui/Bitmap.cpp @@ -223,6 +223,7 @@ Bitmap::~Bitmap() { break; case PixelStorageType::Heap: free(mPixelStorage.heap.address); + mallopt(M_PURGE, 0); break; case PixelStorageType::Hardware: auto buffer = mPixelStorage.hardware.buffer; @@ -230,7 +231,6 @@ Bitmap::~Bitmap() { mPixelStorage.hardware.buffer = nullptr; break; } - android::uirenderer::renderthread::RenderProxy::onBitmapDestroyed(getStableID()); } -- cgit v1.2.3-59-g8ed1b From 402fff12596fdf6cc270f5ce74029563a863127d Mon Sep 17 00:00:00 2001 From: Stan Iliev Date: Thu, 25 Oct 2018 16:28:27 -0400 Subject: Use bilerp sampling when drawing TextureView with non-translate matrix Draw TextureView with bilerp sampling, when the matrix is not integer translate or identity. For example scaling matrix or translation on X by 0.4f will draw with GL_LINEAR on OpenGL pipeline. Translation on X by 3.0f will draw TextureView with GL_NEAREST. Bug: 117890671 Test: Passed CtsViewTestCases and CtsUiRenderingTestCases Change-Id: I72033410c8b0ab637c2e6b816ac9b04434286fbb Merged-In: I3acd710ff2cb4ee7b14dd4b7d9227842187130c9 --- libs/hwui/pipeline/skia/LayerDrawable.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'libs') diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp index 093c7cf62cd2..ab1d5c2546ed 100644 --- a/libs/hwui/pipeline/skia/LayerDrawable.cpp +++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp @@ -100,15 +100,13 @@ bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer paint.setAlpha(layer->getAlpha()); paint.setBlendMode(layer->getMode()); paint.setColorFilter(layer->getColorSpaceWithFilter()); - if (layer->getForceFilter()) { - paint.setFilterQuality(kLow_SkFilterQuality); - } const bool nonIdentityMatrix = !matrix.isIdentity(); if (nonIdentityMatrix) { canvas->save(); canvas->concat(matrix); } + const SkMatrix& totalMatrix = canvas->getTotalMatrix(); if (dstRect) { SkMatrix matrixInv; if (!matrix.invert(&matrixInv)) { @@ -118,9 +116,28 @@ bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer matrixInv.mapRect(&srcRect); SkRect skiaDestRect = *dstRect; matrixInv.mapRect(&skiaDestRect); + // If (matrix is identity or an integer translation) and (src/dst buffers size match), + // then use nearest neighbor, otherwise use bilerp sampling. + // Integer translation is defined as when src rect and dst rect align fractionally. + // 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). + bool isIntegerTranslate = totalMatrix.isTranslate() + && SkScalarFraction(skiaDestRect.fLeft + totalMatrix[SkMatrix::kMTransX]) + == SkScalarFraction(srcRect.fLeft) + && SkScalarFraction(skiaDestRect.fTop + totalMatrix[SkMatrix::kMTransY]) + == SkScalarFraction(srcRect.fTop); + if (layer->getForceFilter() || !isIntegerTranslate) { + paint.setFilterQuality(kLow_SkFilterQuality); + } canvas->drawImageRect(layerImage.get(), srcRect, skiaDestRect, &paint, SkCanvas::kFast_SrcRectConstraint); } else { + bool isIntegerTranslate = totalMatrix.isTranslate() + && SkScalarIsInt(totalMatrix[SkMatrix::kMTransX]) + && SkScalarIsInt(totalMatrix[SkMatrix::kMTransY]); + if (layer->getForceFilter() || !isIntegerTranslate) { + paint.setFilterQuality(kLow_SkFilterQuality); + } canvas->drawImage(layerImage.get(), 0, 0, &paint); } // restore the original matrix -- cgit v1.2.3-59-g8ed1b