From 9757ac0b9d62f6aea5e47cfb375f445c78bb7897 Mon Sep 17 00:00:00 2001 From: Chris Craik Date: Tue, 25 Feb 2014 18:50:17 -0800 Subject: [PATCH] Fix TextureView texture filtering. bug:11748993 TextureView should always be drawn with linear filtering if drawing a buffer sized differently from the layer. This fixes a bug where TextureViews that were sized differently from their contents wouldn't be drawn with texture filtering, causing visible scaling artifacts. Change-Id: I8a5d27452fe7269ec53896992f37cff51e3ce15a --- libs/hwui/DeferredLayerUpdater.cpp | 13 +++++++++++-- libs/hwui/Layer.cpp | 1 + libs/hwui/Layer.h | 14 ++++++++++++++ libs/hwui/LayerRenderer.cpp | 5 +++-- libs/hwui/LayerRenderer.h | 2 +- libs/hwui/OpenGLRenderer.cpp | 1 + 6 files changed, 31 insertions(+), 5 deletions(-) diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp index 62f6c7636883c..7a2e288af13fd 100644 --- a/libs/hwui/DeferredLayerUpdater.cpp +++ b/libs/hwui/DeferredLayerUpdater.cpp @@ -112,6 +112,15 @@ void DeferredLayerUpdater::doUpdateTexImage() { frameNumber = newFrameNumber; dropCounter++; } + + bool forceFilter = false; + sp buffer = mSurfaceTexture->getCurrentBuffer(); + if (buffer != NULL) { + // force filtration if buffer size != layer size + forceFilter = mWidth != buffer->getWidth() + || mHeight != buffer->getHeight(); + } + #if DEBUG_RENDERER if (dropCounter > 0) { RENDERER_LOGD("Dropped %d frames on texture layer update", dropCounter); @@ -120,8 +129,8 @@ void DeferredLayerUpdater::doUpdateTexImage() { mSurfaceTexture->getTransformMatrix(transform); GLenum renderTarget = mSurfaceTexture->getCurrentTextureTarget(); - LayerRenderer::updateTextureLayer(mLayer, mWidth, mHeight, !mBlend, - renderTarget, transform); + LayerRenderer::updateTextureLayer(mLayer, mWidth, mHeight, + !mBlend, forceFilter, renderTarget, transform); } } diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp index 54ce64f4069da..8992a13a5c91e 100644 --- a/libs/hwui/Layer.cpp +++ b/libs/hwui/Layer.cpp @@ -46,6 +46,7 @@ Layer::Layer(const uint32_t layerWidth, const uint32_t layerHeight): stencil = NULL; debugDrawUpdate = false; hasDrawnSinceUpdate = false; + forceFilter = false; deferredList = NULL; caches.resourceCache.incrementRefcount(this); } diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index 8cc027ae117a3..f6538f29dcc43 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -127,6 +127,14 @@ public: return texture.blend; } + inline void setForceFilter(bool forceFilter) { + this->forceFilter = forceFilter; + } + + inline bool getForceFilter() const { + return forceFilter; + } + inline void setAlpha(int alpha) { this->alpha = alpha; } @@ -342,10 +350,16 @@ private: */ SkColorFilter* colorFilter; + /** + * Indicates raster data backing the layer is scaled, requiring filtration. + */ + bool forceFilter; + /** * Opacity of the layer. */ int alpha; + /** * Blending mode of the layer. */ diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index ea8eb31f84372..e0ac2ba31faa2 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -290,14 +290,15 @@ Layer* LayerRenderer::createTextureLayer() { } void LayerRenderer::updateTextureLayer(Layer* layer, uint32_t width, uint32_t height, - bool isOpaque, GLenum renderTarget, float* transform) { + bool isOpaque, bool forceFilter, GLenum renderTarget, float* textureTransform) { if (layer) { layer->setBlend(!isOpaque); + layer->setForceFilter(forceFilter); layer->setSize(width, height); layer->layer.set(0.0f, 0.0f, width, height); layer->region.set(width, height); layer->regionRect.set(0.0f, 0.0f, width, height); - layer->getTexTransform().load(transform); + layer->getTexTransform().load(textureTransform); if (renderTarget != layer->getRenderTarget()) { layer->setRenderTarget(renderTarget); diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h index 84acd44520000..40e461a345dcf 100644 --- a/libs/hwui/LayerRenderer.h +++ b/libs/hwui/LayerRenderer.h @@ -56,7 +56,7 @@ public: ANDROID_API static Layer* createRenderLayer(uint32_t width, uint32_t height); ANDROID_API static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height); ANDROID_API static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height, - bool isOpaque, GLenum renderTarget, float* transform); + bool isOpaque, bool forceFilter, GLenum renderTarget, float* textureTransform); ANDROID_API static void destroyLayer(Layer* layer); ANDROID_API static void destroyLayerDeferred(Layer* layer); ANDROID_API static bool copyLayer(Layer* layer, SkBitmap* bitmap); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 2da0fd394eeb5..c507c8183048b 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1068,6 +1068,7 @@ void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) { setupDrawExternalTexture(layer->getTexture()); } if (currentTransform()->isPureTranslate() && + !layer->getForceFilter() && layer->getWidth() == (uint32_t) rect.getWidth() && layer->getHeight() == (uint32_t) rect.getHeight()) { const float x = (int) floorf(rect.left + currentTransform()->getTranslateX() + 0.5f);