Loading libs/hwui/BakedOpDispatcher.cpp +33 −5 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 { Loading libs/hwui/Glop.h +2 −0 Original line number Diff line number Diff line Loading @@ -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: Loading libs/hwui/GlopBuilder.cpp +12 −0 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading Loading @@ -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) { Loading Loading @@ -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 */ Loading libs/hwui/OpenGLRenderer.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -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; } } Loading libs/hwui/tests/unit/BakedOpDispatcherTests.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading
libs/hwui/BakedOpDispatcher.cpp +33 −5 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 { Loading
libs/hwui/Glop.h +2 −0 Original line number Diff line number Diff line Loading @@ -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: Loading
libs/hwui/GlopBuilder.cpp +12 −0 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading Loading @@ -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) { Loading Loading @@ -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 */ Loading
libs/hwui/OpenGLRenderer.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -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; } } Loading
libs/hwui/tests/unit/BakedOpDispatcherTests.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -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); Loading