summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Chris Craik <ccraik@google.com> 2016-03-11 19:16:21 -0800
committer Chris Craik <ccraik@google.com> 2016-03-14 13:26:25 -0700
commit02806288d1c56475413888a934c796e6e4eb11c5 (patch)
tree837197b3b31a6d43ed61c141fa4b3a288d9c5a0b
parent481355a45df5a8e5c57b1058f48cb1102b05ebc0 (diff)
Fix flickering when layers resize in-place
bug:27248275 Change-Id: Ia11c93ebc1097f3735071204b6f14ca079bb9fc4
-rw-r--r--libs/hwui/Android.mk1
-rw-r--r--libs/hwui/BakedOpRenderer.cpp10
-rw-r--r--libs/hwui/ClipArea.cpp4
-rw-r--r--libs/hwui/ClipArea.h2
-rw-r--r--libs/hwui/LayerBuilder.cpp5
-rw-r--r--libs/hwui/debug/nullgles.cpp9
-rw-r--r--libs/hwui/renderstate/OffscreenBufferPool.cpp3
-rw-r--r--libs/hwui/tests/unit/BakedOpRendererTests.cpp54
-rw-r--r--libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp6
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());