OSDN Git Service

Draw textShadow always first.
authorsergeyv <sergeyv@google.com>
Tue, 10 May 2016 20:58:12 +0000 (13:58 -0700)
committersergeyv <sergeyv@google.com>
Wed, 11 May 2016 17:30:14 +0000 (10:30 -0700)
Interleaving text and shadow rendering resulted in issuing draw commands from FontRenderer::renderDropShadow.

bug: 28528923
Change-Id: Ife2677f58180aaf10ec74d7c6efe5c44fe248daa

libs/hwui/BakedOpDispatcher.cpp
libs/hwui/tests/unit/BakedOpDispatcherTests.cpp

index 0f670a8..e98c24e 100644 (file)
@@ -194,8 +194,12 @@ void BakedOpDispatcher::onMergedPatchOps(BakedOpRenderer& renderer,
     renderer.renderGlop(nullptr, clip, glop);
 }
 
-static void renderTextShadow(BakedOpRenderer& renderer, FontRenderer& fontRenderer,
+static void renderTextShadow(BakedOpRenderer& renderer,
         const TextOp& op, const BakedOpState& textOpState) {
+    if (CC_LIKELY(!PaintUtils::hasTextShadow(op.paint))) return;
+
+    FontRenderer& fontRenderer = renderer.caches().fontRenderer.getFontRenderer();
+    fontRenderer.setFont(op.paint, SkMatrix::I());
     renderer.caches().textureState().activateTexture(0);
 
     PaintUtils::TextShadow textShadow;
@@ -258,15 +262,9 @@ enum class TextRenderType {
     Flush
 };
 
-static void renderTextOp(BakedOpRenderer& renderer, const TextOp& op, const BakedOpState& state,
+static void renderText(BakedOpRenderer& renderer, const TextOp& op, const BakedOpState& state,
         const ClipBase* renderClip, TextRenderType renderType) {
     FontRenderer& fontRenderer = renderer.caches().fontRenderer.getFontRenderer();
-
-    if (CC_UNLIKELY(PaintUtils::hasTextShadow(op.paint))) {
-        fontRenderer.setFont(op.paint, SkMatrix::I());
-        renderTextShadow(renderer, fontRenderer, op, state);
-    }
-
     float x = op.x;
     float y = op.y;
     const Matrix4& transform = state.computedState.transform;
@@ -321,6 +319,12 @@ static void renderTextOp(BakedOpRenderer& renderer, const TextOp& op, const Bake
 
 void BakedOpDispatcher::onMergedTextOps(BakedOpRenderer& renderer,
         const MergedBakedOpList& opList) {
+    for (size_t i = 0; i < opList.count; i++) {
+        const BakedOpState& state = *(opList.states[i]);
+        const TextOp& op = *(static_cast<const TextOp*>(state.op));
+        renderTextShadow(renderer, op, state);
+    }
+
     ClipRect renderTargetClip(opList.clip);
     const ClipBase* clip = opList.clipSideFlags ? &renderTargetClip : nullptr;
     for (size_t i = 0; i < opList.count; i++) {
@@ -328,7 +332,7 @@ void BakedOpDispatcher::onMergedTextOps(BakedOpRenderer& renderer,
         const TextOp& op = *(static_cast<const TextOp*>(state.op));
         TextRenderType renderType = (i + 1 == opList.count)
                 ? TextRenderType::Flush : TextRenderType::Defer;
-        renderTextOp(renderer, op, state, clip, renderType);
+        renderText(renderer, op, state, clip, renderType);
     }
 }
 
@@ -739,7 +743,8 @@ void BakedOpDispatcher::onSimpleRectsOp(BakedOpRenderer& renderer, const SimpleR
 }
 
 void BakedOpDispatcher::onTextOp(BakedOpRenderer& renderer, const TextOp& op, const BakedOpState& state) {
-    renderTextOp(renderer, op, state, state.computedState.getClipIfNeeded(), TextRenderType::Flush);
+    renderTextShadow(renderer, op, state);
+    renderText(renderer, op, state, state.computedState.getClipIfNeeded(), TextRenderType::Flush);
 }
 
 void BakedOpDispatcher::onTextOnPathOp(BakedOpRenderer& renderer, const TextOnPathOp& op, const BakedOpState& state) {
index de57cd1..5613f9f 100644 (file)
@@ -19,6 +19,9 @@
 #include <RecordedOp.h>
 #include <BakedOpDispatcher.h>
 #include <BakedOpRenderer.h>
+#include <FrameBuilder.h>
+#include <SkBlurDrawLooper.h>
+#include <hwui/Paint.h>
 #include <tests/common/TestUtils.h>
 
 #include <SkDashPathEffect.h>
@@ -26,6 +29,7 @@
 using namespace android::uirenderer;
 
 static BakedOpRenderer::LightInfo sLightInfo;
+const FrameBuilder::LightGeometry sLightGeometry = { {100, 100, 100}, 50};
 static Rect sBaseClip(100, 100);
 
 class ValidatingBakedOpRenderer : public BakedOpRenderer {
@@ -45,7 +49,7 @@ private:
     std::function<void(const Glop& glop)> mValidator;
 };
 
-typedef void (*BakedOpReceiver)(BakedOpRenderer&, const BakedOpState&);
+typedef void (*TestBakedOpReceiver)(BakedOpRenderer&, const BakedOpState&);
 
 static void testUnmergedGlopDispatch(renderthread::RenderThread& renderThread, RecordedOp* op,
         std::function<void(const Glop& glop)> glopVerifier) {
@@ -67,7 +71,7 @@ static void testUnmergedGlopDispatch(renderthread::RenderThread& renderThread, R
         [](BakedOpRenderer& renderer, const BakedOpState& state) { \
             BakedOpDispatcher::on##Type(renderer, static_cast<const Type&>(*(state.op)), state); \
         },
-    static BakedOpReceiver unmergedReceivers[] = BUILD_RENDERABLE_OP_LUT(X);
+    static TestBakedOpReceiver unmergedReceivers[] = BUILD_RENDERABLE_OP_LUT(X);
 #undef X
     unmergedReceivers[op->opId](renderer, *state);
     ASSERT_EQ(1, glopCount) << "Exactly one Glop expected";
@@ -154,4 +158,40 @@ RENDERTHREAD_TEST(BakedOpDispatcher, offsetFlags) {
     LinesOp linesOp(bounds, Matrix4::identity(), nullptr, &paint, points, 4);
     EXPECT_EQ(TransformFlags::OffsetByFudgeFactor, getGlopTransformFlags(renderThread, &linesOp))
             << "Expect an offset for non-AA lines.";
+}
+
+RENDERTHREAD_TEST(BakedOpDispatcher, renderTextWithShadow) {
+    auto node = TestUtils::createNode(0, 0, 100, 100,
+            [](RenderProperties& props, TestCanvas& canvas) {
+
+        android::Paint shadowPaint;
+        shadowPaint.setColor(SK_ColorRED);
+
+        SkScalar sigma = Blur::convertRadiusToSigma(5);
+        shadowPaint.setLooper(SkBlurDrawLooper::Create(SK_ColorWHITE, sigma, 3, 3))->unref();
+
+        TestUtils::drawUtf8ToCanvas(&canvas, "A", shadowPaint, 25, 25);
+        TestUtils::drawUtf8ToCanvas(&canvas, "B", shadowPaint, 50, 50);
+    });
+
+    int  glopCount = 0;
+    auto glopReceiver = [&glopCount] (const Glop& glop) {
+        if (glopCount < 2) {
+            // two white shadows
+            EXPECT_EQ(FloatColor({1, 1, 1, 1}), glop.fill.color);
+        } else {
+            // two text draws merged into one, drawn after both shadows
+            EXPECT_EQ(FloatColor({1, 0, 0, 1}), glop.fill.color);
+        }
+        glopCount++;
+    };
+
+    ValidatingBakedOpRenderer renderer(renderThread.renderState(), glopReceiver);
+
+    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
+            sLightGeometry, Caches::getInstance());
+    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
+
+    frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
+    ASSERT_EQ(3, glopCount) << "Exactly three glops expected";
 }
\ No newline at end of file