diff options
author | 2016-03-11 19:16:21 -0800 | |
---|---|---|
committer | 2016-03-14 13:26:25 -0700 | |
commit | 02806288d1c56475413888a934c796e6e4eb11c5 (patch) | |
tree | 837197b3b31a6d43ed61c141fa4b3a288d9c5a0b | |
parent | 481355a45df5a8e5c57b1058f48cb1102b05ebc0 (diff) |
Fix flickering when layers resize in-place
bug:27248275
Change-Id: Ia11c93ebc1097f3735071204b6f14ca079bb9fc4
-rw-r--r-- | libs/hwui/Android.mk | 1 | ||||
-rw-r--r-- | libs/hwui/BakedOpRenderer.cpp | 10 | ||||
-rw-r--r-- | libs/hwui/ClipArea.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/ClipArea.h | 2 | ||||
-rw-r--r-- | libs/hwui/LayerBuilder.cpp | 5 | ||||
-rw-r--r-- | libs/hwui/debug/nullgles.cpp | 9 | ||||
-rw-r--r-- | libs/hwui/renderstate/OffscreenBufferPool.cpp | 3 | ||||
-rw-r--r-- | libs/hwui/tests/unit/BakedOpRendererTests.cpp | 54 | ||||
-rw-r--r-- | libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp | 6 |
9 files changed, 92 insertions, 2 deletions
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index f6e3b5035be2..ca077389b629 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -255,6 +255,7 @@ LOCAL_SRC_FILES += \ ifeq (true, $(HWUI_NEW_OPS)) LOCAL_SRC_FILES += \ tests/unit/BakedOpDispatcherTests.cpp \ + tests/unit/BakedOpRendererTests.cpp \ tests/unit/BakedOpStateTests.cpp \ tests/unit/FrameBuilderTests.cpp \ tests/unit/LeakCheckTests.cpp \ diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp index da5eccaf1c12..bb3ea3fa6b54 100644 --- a/libs/hwui/BakedOpRenderer.cpp +++ b/libs/hwui/BakedOpRenderer.cpp @@ -40,6 +40,16 @@ OffscreenBuffer* BakedOpRenderer::startTemporaryLayer(uint32_t width, uint32_t h void BakedOpRenderer::startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) { LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer..."); + // subtract repaintRect from region, since it will be regenerated + if (repaintRect.contains(0, 0, + offscreenBuffer->viewportWidth, offscreenBuffer->viewportHeight)) { + // repaint full layer, so throw away entire region + offscreenBuffer->region.clear(); + } else { + offscreenBuffer->region.subtractSelf(android::Rect(repaintRect.left, repaintRect.top, + repaintRect.right, repaintRect.bottom)); + } + mRenderTarget.offscreenBuffer = offscreenBuffer; // create and bind framebuffer diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp index afe980712d81..f886dda86deb 100644 --- a/libs/hwui/ClipArea.cpp +++ b/libs/hwui/ClipArea.cpp @@ -41,6 +41,10 @@ Rect transformAndCalculateBounds(const Rect& r, const Matrix4& transform) { return transformedBounds; } +void ClipBase::dump() const { + ALOGD("mode %d" RECT_STRING, mode, RECT_ARGS(rect)); +} + /* * TransformedRectangle */ diff --git a/libs/hwui/ClipArea.h b/libs/hwui/ClipArea.h index 479796db042a..1654eb8f02e4 100644 --- a/libs/hwui/ClipArea.h +++ b/libs/hwui/ClipArea.h @@ -106,6 +106,8 @@ struct ClipBase { // Bounds of the clipping area, used to define the scissor, and define which // portion of the stencil is updated/used Rect rect; + + void dump() const; }; struct ClipRect : ClipBase { diff --git a/libs/hwui/LayerBuilder.cpp b/libs/hwui/LayerBuilder.cpp index c5af279653d9..e6a95ff177a4 100644 --- a/libs/hwui/LayerBuilder.cpp +++ b/libs/hwui/LayerBuilder.cpp @@ -349,8 +349,9 @@ void LayerBuilder::replayBakedOpsImpl(void* arg, } void LayerBuilder::dump() const { - ALOGD("LayerBuilder %p, %ux%u buffer %p, blo %p, rn %p", - this, width, height, offscreenBuffer, beginLayerOp, renderNode); + ALOGD("LayerBuilder %p, %ux%u buffer %p, blo %p, rn %p (%s)", + this, width, height, offscreenBuffer, beginLayerOp, + renderNode, renderNode ? renderNode->getName() : "-"); for (const BatchBase* batch : mBatches) { batch->dump(); } diff --git a/libs/hwui/debug/nullgles.cpp b/libs/hwui/debug/nullgles.cpp index ffb064942911..8689f9814f7b 100644 --- a/libs/hwui/debug/nullgles.cpp +++ b/libs/hwui/debug/nullgles.cpp @@ -133,6 +133,15 @@ void glGetIntegerv(GLenum pname, GLint *data) { } } +GLenum glCheckFramebufferStatus(GLenum target) { + switch (target) { + case GL_FRAMEBUFFER: + return GL_FRAMEBUFFER_COMPLETE; + default: + return 0; // error case + } +} + const char* getString(GLenum name) { switch (name) { case GL_VENDOR: diff --git a/libs/hwui/renderstate/OffscreenBufferPool.cpp b/libs/hwui/renderstate/OffscreenBufferPool.cpp index 5f984b59ebd9..bb1a044a8369 100644 --- a/libs/hwui/renderstate/OffscreenBufferPool.cpp +++ b/libs/hwui/renderstate/OffscreenBufferPool.cpp @@ -164,6 +164,9 @@ OffscreenBuffer* OffscreenBufferPool::resize(OffscreenBuffer* layer, // resize in place layer->viewportWidth = width; layer->viewportHeight = height; + + // entire area will be repainted (and may be smaller) so clear usage region + layer->region.clear(); return layer; } putOrDelete(layer); diff --git a/libs/hwui/tests/unit/BakedOpRendererTests.cpp b/libs/hwui/tests/unit/BakedOpRendererTests.cpp new file mode 100644 index 000000000000..59bd75ef6f62 --- /dev/null +++ b/libs/hwui/tests/unit/BakedOpRendererTests.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> + +#include <BakedOpRenderer.h> +#include <tests/common/TestUtils.h> + +using namespace android::uirenderer; + +const BakedOpRenderer::LightInfo sLightInfo = { 128, 128 }; + +RENDERTHREAD_TEST(BakedOpRenderer, startRepaintLayer_clear) { + BakedOpRenderer renderer(Caches::getInstance(), renderThread.renderState(), true, sLightInfo); + OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 200u, 200u); + + layer.dirty(Rect(200, 200)); + { + renderer.startRepaintLayer(&layer, Rect(200, 200)); + EXPECT_TRUE(layer.region.isEmpty()) << "Repaint full layer should clear region"; + renderer.endLayer(); + } + + layer.dirty(Rect(200, 200)); + { + renderer.startRepaintLayer(&layer, Rect(100, 200)); // repainting left side + EXPECT_TRUE(layer.region.isRect()); + //ALOGD("bounds %d %d %d %d", RECT_ARGS(layer.region.getBounds())); + EXPECT_EQ(android::Rect(100, 0, 200, 200), layer.region.getBounds()) + << "Left side being repainted, so right side should be clear"; + renderer.endLayer(); + } + + // right side is now only dirty portion + { + renderer.startRepaintLayer(&layer, Rect(100, 0, 200, 200)); // repainting right side + EXPECT_TRUE(layer.region.isEmpty()) + << "Now right side being repainted, so region should be entirely clear"; + renderer.endLayer(); + } +} diff --git a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp index 0c6eb571b9b4..37a485e3a9ac 100644 --- a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp +++ b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp @@ -103,9 +103,11 @@ TEST(OffscreenBufferPool, resize) { OffscreenBufferPool pool; auto layer = pool.get(thread.renderState(), 64u, 64u); + layer->dirty(Rect(64, 64)); // resize in place ASSERT_EQ(layer, pool.resize(layer, 60u, 55u)); + EXPECT_TRUE(layer->region.isEmpty()) << "In place resize should clear usage region"; EXPECT_EQ(60u, layer->viewportWidth); EXPECT_EQ(55u, layer->viewportHeight); EXPECT_EQ(64u, layer->texture.width()); @@ -113,9 +115,13 @@ TEST(OffscreenBufferPool, resize) { // resized to use different object in pool auto layer2 = pool.get(thread.renderState(), 128u, 128u); + layer2->dirty(Rect(128, 128)); + EXPECT_FALSE(layer2->region.isEmpty()); pool.putOrDelete(layer2); ASSERT_EQ(1u, pool.getCount()); + ASSERT_EQ(layer2, pool.resize(layer, 120u, 125u)); + EXPECT_TRUE(layer2->region.isEmpty()) << "Swap resize should clear usage region"; EXPECT_EQ(120u, layer2->viewportWidth); EXPECT_EQ(125u, layer2->viewportHeight); EXPECT_EQ(128u, layer2->texture.width()); |