diff options
author | 2016-03-30 18:09:17 -0700 | |
---|---|---|
committer | 2016-03-30 18:09:18 -0700 | |
commit | 70969ccde405ea410fc7ccfe869999a03f056686 (patch) | |
tree | 03bb598f1e1de33746703cfc3cb221bda902c3ac | |
parent | af64f6341bdbca93aff3d68264af48e74faa9e58 (diff) |
Fix layer damage and clipping for Text shadows
Fixes: 27787426
Change-Id: I4c65cca0cfcd343a9cfbaedd3a32b83f90df2ecf
-rw-r--r-- | libs/hwui/BakedOpDispatcher.cpp | 38 | ||||
-rw-r--r-- | libs/hwui/Glop.h | 2 | ||||
-rw-r--r-- | libs/hwui/GlopBuilder.cpp | 12 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/tests/unit/BakedOpDispatcherTests.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/tests/unit/GlopBuilderTests.cpp | 4 |
6 files changed, 55 insertions, 5 deletions
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp index ea4f4eb98f36..f43bf860946b 100644 --- a/libs/hwui/BakedOpDispatcher.cpp +++ b/libs/hwui/BakedOpDispatcher.cpp @@ -195,7 +195,7 @@ void BakedOpDispatcher::onMergedPatchOps(BakedOpRenderer& renderer, } static void renderTextShadow(BakedOpRenderer& renderer, FontRenderer& fontRenderer, - const TextOp& op, const BakedOpState& state) { + const TextOp& op, const BakedOpState& textOpState) { renderer.caches().textureState().activateTexture(0); PaintUtils::TextShadow textShadow; @@ -216,13 +216,41 @@ static void renderTextShadow(BakedOpRenderer& renderer, FontRenderer& fontRender Glop glop; GlopBuilder(renderer.renderState(), renderer.caches(), &glop) - .setRoundRectClipState(state.roundRectClipState) + .setRoundRectClipState(textOpState.roundRectClipState) .setMeshTexturedUnitQuad(nullptr) - .setFillShadowTexturePaint(*texture, textShadow.color, *op.paint, state.alpha) - .setTransform(state.computedState.transform, TransformFlags::None) + .setFillShadowTexturePaint(*texture, textShadow.color, *op.paint, textOpState.alpha) + .setTransform(textOpState.computedState.transform, TransformFlags::None) .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width(), sy + texture->height())) .build(); - renderer.renderGlop(state, glop); + + // Compute damage bounds and clip (since may differ from those in textOpState). + // Bounds should be same as text op, but with dx/dy offset and radius outset + // applied in local space. + auto& transform = textOpState.computedState.transform; + Rect shadowBounds = op.unmappedBounds; // STROKE + const bool expandForStroke = op.paint->getStyle() != SkPaint::kFill_Style; + if (expandForStroke) { + shadowBounds.outset(op.paint->getStrokeWidth() * 0.5f); + } + shadowBounds.translate(textShadow.dx, textShadow.dy); + shadowBounds.outset(textShadow.radius, textShadow.radius); + transform.mapRect(shadowBounds); + if (CC_UNLIKELY(expandForStroke && + (!transform.isPureTranslate() || op.paint->getStrokeWidth() < 1.0f))) { + shadowBounds.outset(0.5f); + } + + auto clipState = textOpState.computedState.clipState; + if (clipState->mode != ClipMode::Rectangle + || !clipState->rect.contains(shadowBounds)) { + // need clip, so pass it and clip bounds + shadowBounds.doIntersect(clipState->rect); + } else { + // don't need clip, ignore + clipState = nullptr; + } + + renderer.renderGlop(&shadowBounds, clipState, glop); } enum class TextRenderType { diff --git a/libs/hwui/Glop.h b/libs/hwui/Glop.h index 704bd69056fe..6a9663412a00 100644 --- a/libs/hwui/Glop.h +++ b/libs/hwui/Glop.h @@ -163,11 +163,13 @@ public: GLenum dst; } blend; +#if !HWUI_NEW_OPS /** * Bounds of the drawing command in layer space. Only mapped into layer * space once GlopBuilder::build() is called. */ Rect bounds; // TODO: remove for HWUI_NEW_OPS +#endif /** * Additional render state to enumerate: diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp index 2799def16b98..7d4f4100313f 100644 --- a/libs/hwui/GlopBuilder.cpp +++ b/libs/hwui/GlopBuilder.cpp @@ -492,7 +492,9 @@ GlopBuilder& GlopBuilder::setModelViewMapUnitToRect(const Rect destination) { mOutGlop->transform.modelView.loadTranslate(destination.left, destination.top, 0.0f); mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f); +#if !HWUI_NEW_OPS mOutGlop->bounds = destination; +#endif return *this; } @@ -516,7 +518,9 @@ GlopBuilder& GlopBuilder::setModelViewMapUnitToRectSnap(const Rect destination) mOutGlop->transform.modelView.loadTranslate(left, top, 0.0f); mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f); +#if !HWUI_NEW_OPS mOutGlop->bounds = destination; +#endif return *this; } @@ -524,8 +528,10 @@ GlopBuilder& GlopBuilder::setModelViewOffsetRect(float offsetX, float offsetY, c TRIGGER_STAGE(kModelViewStage); mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f); +#if !HWUI_NEW_OPS mOutGlop->bounds = source; mOutGlop->bounds.translate(offsetX, offsetY); +#endif return *this; } @@ -545,8 +551,10 @@ GlopBuilder& GlopBuilder::setModelViewOffsetRectSnap(float offsetX, float offset } mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f); +#if !HWUI_NEW_OPS mOutGlop->bounds = source; mOutGlop->bounds.translate(offsetX, offsetY); +#endif return *this; } @@ -643,7 +651,9 @@ void GlopBuilder::build() { // Final step: populate program and map bounds into render target space mOutGlop->fill.program = mCaches.programCache.get(mDescription); +#if !HWUI_NEW_OPS mOutGlop->transform.meshTransform().mapRect(mOutGlop->bounds); +#endif } void GlopBuilder::dump(const Glop& glop) { @@ -683,7 +693,9 @@ void GlopBuilder::dump(const Glop& glop) { ALOGD_IF(glop.roundRectClipState, "Glop RRCS %p", glop.roundRectClipState); ALOGD("Glop blend %d %d", glop.blend.src, glop.blend.dst); +#if !HWUI_NEW_OPS ALOGD("Glop bounds " RECT_STRING, RECT_ARGS(glop.bounds)); +#endif } } /* namespace uirenderer */ diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index c0994272c964..53ea7fa6f77d 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1413,7 +1413,9 @@ void OpenGLRenderer::renderGlop(const Glop& glop, GlopRenderType type) { if (type == GlopRenderType::Standard && !mRenderState.stencil().isWriteEnabled()) { // TODO: specify more clearly when a draw should dirty the layer. // is writing to the stencil the only time we should ignore this? +#if !HWUI_NEW_OPS dirtyLayer(glop.bounds.left, glop.bounds.top, glop.bounds.right, glop.bounds.bottom); +#endif mDirty = true; } } diff --git a/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp b/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp index 654ddc6a28e5..54714860c19d 100644 --- a/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp +++ b/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp @@ -85,7 +85,9 @@ RENDERTHREAD_TEST(BakedOpDispatcher, onArc_position) { << "Should see conservative offset from PathCache::computeBounds"; Rect expectedBounds(10, 15, 20, 25); expectedBounds.outset(expectedOffset); +#if !HWUI_NEW_OPS EXPECT_EQ(expectedBounds, glop.bounds) << "bounds outset by stroke 'offset'"; +#endif Matrix4 expectedModelView; expectedModelView.loadTranslate(10 - expectedOffset, 15 - expectedOffset, 0); expectedModelView.scale(10 + 2 * expectedOffset, 10 + 2 * expectedOffset, 1); diff --git a/libs/hwui/tests/unit/GlopBuilderTests.cpp b/libs/hwui/tests/unit/GlopBuilderTests.cpp index 454011fa47f0..95543d33b1ef 100644 --- a/libs/hwui/tests/unit/GlopBuilderTests.cpp +++ b/libs/hwui/tests/unit/GlopBuilderTests.cpp @@ -85,7 +85,9 @@ static void expectTransformEq(Glop::Transform& expectedTransform, Glop::Transfor } static void expectGlopEq(Glop& expectedGlop, Glop& builtGlop) { +#if !HWUI_NEW_OPS EXPECT_EQ(expectedGlop.bounds, builtGlop.bounds); +#endif expectBlendEq(expectedGlop.blend, builtGlop.blend); expectFillEq(expectedGlop.fill, builtGlop.fill); expectMeshEq(expectedGlop.mesh, builtGlop.mesh); @@ -136,7 +138,9 @@ RENDERTHREAD_TEST(GlopBuilder, rectSnapTest) { // unit quad also should be translate by additional (0.3, 0.3) to snap to exact pixels. goldenGlop->transform.modelView.loadTranslate(1.3, 1.3, 0); goldenGlop->transform.modelView.scale(99, 99, 1); +#if !HWUI_NEW_OPS goldenGlop->bounds = android::uirenderer::Rect(1.70, 1.70, 100.70, 100.70); +#endif goldenGlop->transform.canvas = simpleTranslate; goldenGlop->fill.texture.filter = GL_NEAREST; expectGlopEq(*goldenGlop, glop); |