Merge "Fix flickering when layers resize in-place" into nyc-dev

This commit is contained in:
Chris Craik
2016-03-14 22:48:50 +00:00
committed by Android (Google) Code Review
9 changed files with 92 additions and 2 deletions

View File

@@ -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 \

View File

@@ -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

View File

@@ -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
*/

View File

@@ -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 {

View File

@@ -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();
}

View File

@@ -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:

View File

@@ -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);

View File

@@ -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();
}
}

View File

@@ -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());