Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2016 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #include <gtest/gtest.h> |
| 18 | |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 19 | #include <BakedOpDispatcher.h> |
| 20 | #include <BakedOpRenderer.h> |
sergeyv | 284b765 | 2016-05-10 13:58:12 -0700 | [diff] [blame] | 21 | #include <FrameBuilder.h> |
Chris Craik | 3741328 | 2016-05-12 17:48:51 -0700 | [diff] [blame] | 22 | #include <LayerUpdateQueue.h> |
Chris Craik | 3741328 | 2016-05-12 17:48:51 -0700 | [diff] [blame] | 23 | #include <RecordedOp.h> |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 24 | #include <hwui/Paint.h> |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 25 | #include <tests/common/TestUtils.h> |
Chris Craik | 3741328 | 2016-05-12 17:48:51 -0700 | [diff] [blame] | 26 | #include <utils/Color.h> |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 27 | |
Chris Craik | 3741328 | 2016-05-12 17:48:51 -0700 | [diff] [blame] | 28 | #include <SkBlurDrawLooper.h> |
Chris Craik | e98a046 | 2016-04-26 15:35:20 -0700 | [diff] [blame] | 29 | #include <SkDashPathEffect.h> |
sergeyv | 89561e6 | 2016-08-04 16:21:07 -0700 | [diff] [blame] | 30 | #include <SkPath.h> |
Chris Craik | e98a046 | 2016-04-26 15:35:20 -0700 | [diff] [blame] | 31 | |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 32 | using namespace android::uirenderer; |
| 33 | |
| 34 | static BakedOpRenderer::LightInfo sLightInfo; |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 35 | const FrameBuilder::LightGeometry sLightGeometry = {{100, 100, 100}, 50}; |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 36 | |
| 37 | class ValidatingBakedOpRenderer : public BakedOpRenderer { |
| 38 | public: |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 39 | ValidatingBakedOpRenderer(RenderState& renderState, |
| 40 | std::function<void(const Glop& glop)> validator) |
Romain Guy | 07ae505 | 2017-06-13 18:25:32 -0700 | [diff] [blame] | 41 | : BakedOpRenderer(Caches::getInstance(), renderState, true, false, sLightInfo) |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 42 | , mValidator(validator) { |
| 43 | mGlopReceiver = ValidatingGlopReceiver; |
| 44 | } |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 45 | |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 46 | private: |
| 47 | static void ValidatingGlopReceiver(BakedOpRenderer& renderer, const Rect* dirtyBounds, |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 48 | const ClipBase* clip, const Glop& glop) { |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 49 | auto vbor = reinterpret_cast<ValidatingBakedOpRenderer*>(&renderer); |
| 50 | vbor->mValidator(glop); |
| 51 | } |
| 52 | std::function<void(const Glop& glop)> mValidator; |
| 53 | }; |
| 54 | |
sergeyv | 284b765 | 2016-05-10 13:58:12 -0700 | [diff] [blame] | 55 | typedef void (*TestBakedOpReceiver)(BakedOpRenderer&, const BakedOpState&); |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 56 | |
| 57 | static void testUnmergedGlopDispatch(renderthread::RenderThread& renderThread, RecordedOp* op, |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 58 | std::function<void(const Glop& glop)> glopVerifier, |
| 59 | int expectedGlopCount = 1) { |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 60 | // Create op, and wrap with basic state. |
| 61 | LinearAllocator allocator; |
Chris Craik | 3741328 | 2016-05-12 17:48:51 -0700 | [diff] [blame] | 62 | auto snapshot = TestUtils::makeSnapshot(Matrix4::identity(), Rect(100, 100)); |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 63 | auto state = BakedOpState::tryConstruct(allocator, *snapshot, *op); |
| 64 | ASSERT_NE(nullptr, state); |
| 65 | |
| 66 | int glopCount = 0; |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 67 | auto glopReceiver = [&glopVerifier, &glopCount, &expectedGlopCount](const Glop& glop) { |
sergeyv | aebbbef | 2016-05-31 14:18:02 -0700 | [diff] [blame] | 68 | ASSERT_LE(glopCount++, expectedGlopCount) << expectedGlopCount << "glop(s) expected"; |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 69 | glopVerifier(glop); |
| 70 | }; |
| 71 | ValidatingBakedOpRenderer renderer(renderThread.renderState(), glopReceiver); |
| 72 | |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 73 | // Dispatch based on op type created, similar to Frame/LayerBuilder dispatch behavior |
| 74 | #define X(Type) \ |
| 75 | [](BakedOpRenderer& renderer, const BakedOpState& state) { \ |
| 76 | BakedOpDispatcher::on##Type(renderer, static_cast<const Type&>(*(state.op)), state); \ |
| 77 | }, |
sergeyv | 284b765 | 2016-05-10 13:58:12 -0700 | [diff] [blame] | 78 | static TestBakedOpReceiver unmergedReceivers[] = BUILD_RENDERABLE_OP_LUT(X); |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 79 | #undef X |
| 80 | unmergedReceivers[op->opId](renderer, *state); |
sergeyv | aebbbef | 2016-05-31 14:18:02 -0700 | [diff] [blame] | 81 | ASSERT_EQ(expectedGlopCount, glopCount) << "Exactly " << expectedGlopCount |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 82 | << "Glop(s) expected"; |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 83 | } |
| 84 | |
Greg Daniel | 98c78dad | 2017-01-04 14:45:56 -0500 | [diff] [blame] | 85 | RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, pathTexture_positionOvalArc) { |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 86 | SkPaint strokePaint; |
| 87 | strokePaint.setStyle(SkPaint::kStroke_Style); |
| 88 | strokePaint.setStrokeWidth(4); |
Chris Craik | e98a046 | 2016-04-26 15:35:20 -0700 | [diff] [blame] | 89 | |
| 90 | float intervals[] = {1.0f, 1.0f}; |
Mike Reed | 260ab72 | 2016-10-07 15:59:20 -0400 | [diff] [blame] | 91 | strokePaint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0)); |
Chris Craik | e98a046 | 2016-04-26 15:35:20 -0700 | [diff] [blame] | 92 | |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 93 | auto textureGlopVerifier = [](const Glop& glop) { |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 94 | // validate glop produced by renderPathTexture (so texture, unit quad) |
| 95 | auto texture = glop.fill.texture.texture; |
| 96 | ASSERT_NE(nullptr, texture); |
| 97 | float expectedOffset = floor(4 * 1.5f + 0.5f); |
| 98 | EXPECT_EQ(expectedOffset, reinterpret_cast<PathTexture*>(texture)->offset) |
| 99 | << "Should see conservative offset from PathCache::computeBounds"; |
| 100 | Rect expectedBounds(10, 15, 20, 25); |
| 101 | expectedBounds.outset(expectedOffset); |
Chris Craik | e98a046 | 2016-04-26 15:35:20 -0700 | [diff] [blame] | 102 | |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 103 | Matrix4 expectedModelView; |
| 104 | expectedModelView.loadTranslate(10 - expectedOffset, 15 - expectedOffset, 0); |
| 105 | expectedModelView.scale(10 + 2 * expectedOffset, 10 + 2 * expectedOffset, 1); |
| 106 | EXPECT_EQ(expectedModelView, glop.transform.modelView) |
| 107 | << "X and Y offsets, and scale both applied to model view"; |
Chris Craik | e98a046 | 2016-04-26 15:35:20 -0700 | [diff] [blame] | 108 | }; |
| 109 | |
| 110 | // Arc and Oval will render functionally the same glop, differing only in texture content |
| 111 | ArcOp arcOp(Rect(10, 15, 20, 25), Matrix4::identity(), nullptr, &strokePaint, 0, 270, true); |
| 112 | testUnmergedGlopDispatch(renderThread, &arcOp, textureGlopVerifier); |
| 113 | |
| 114 | OvalOp ovalOp(Rect(10, 15, 20, 25), Matrix4::identity(), nullptr, &strokePaint); |
| 115 | testUnmergedGlopDispatch(renderThread, &ovalOp, textureGlopVerifier); |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 116 | } |
| 117 | |
Greg Daniel | 98c78dad | 2017-01-04 14:45:56 -0500 | [diff] [blame] | 118 | RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, onLayerOp_bufferless) { |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 119 | SkPaint layerPaint; |
| 120 | layerPaint.setAlpha(128); |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 121 | OffscreenBuffer* buffer = nullptr; // no providing a buffer, should hit rect fallback case |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 122 | LayerOp op(Rect(10, 10), Matrix4::identity(), nullptr, &layerPaint, &buffer); |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 123 | testUnmergedGlopDispatch(renderThread, &op, |
| 124 | [](const Glop& glop) { ADD_FAILURE() << "Nothing should happen"; }, 0); |
Chris Craik | 419a1e7 | 2016-03-08 16:24:12 -0800 | [diff] [blame] | 125 | } |
sergeyv | 92a5d4b | 2016-04-20 14:20:18 -0700 | [diff] [blame] | 126 | |
| 127 | static int getGlopTransformFlags(renderthread::RenderThread& renderThread, RecordedOp* op) { |
| 128 | int result = 0; |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 129 | testUnmergedGlopDispatch(renderThread, op, [&result](const Glop& glop) { |
sergeyv | 92a5d4b | 2016-04-20 14:20:18 -0700 | [diff] [blame] | 130 | result = glop.transform.transformFlags; |
| 131 | }); |
| 132 | return result; |
| 133 | } |
| 134 | |
Greg Daniel | 98c78dad | 2017-01-04 14:45:56 -0500 | [diff] [blame] | 135 | RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, offsetFlags) { |
sergeyv | 92a5d4b | 2016-04-20 14:20:18 -0700 | [diff] [blame] | 136 | Rect bounds(10, 15, 20, 25); |
| 137 | SkPaint paint; |
| 138 | SkPaint aaPaint; |
| 139 | aaPaint.setAntiAlias(true); |
| 140 | |
| 141 | RoundRectOp roundRectOp(bounds, Matrix4::identity(), nullptr, &paint, 0, 270); |
| 142 | EXPECT_EQ(TransformFlags::None, getGlopTransformFlags(renderThread, &roundRectOp)) |
| 143 | << "Expect no offset for round rect op."; |
| 144 | |
| 145 | const float points[4] = {0.5, 0.5, 1.0, 1.0}; |
| 146 | PointsOp antiAliasedPointsOp(bounds, Matrix4::identity(), nullptr, &aaPaint, points, 4); |
| 147 | EXPECT_EQ(TransformFlags::None, getGlopTransformFlags(renderThread, &antiAliasedPointsOp)) |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 148 | << "Expect no offset for AA points."; |
sergeyv | 92a5d4b | 2016-04-20 14:20:18 -0700 | [diff] [blame] | 149 | PointsOp pointsOp(bounds, Matrix4::identity(), nullptr, &paint, points, 4); |
| 150 | EXPECT_EQ(TransformFlags::OffsetByFudgeFactor, getGlopTransformFlags(renderThread, &pointsOp)) |
| 151 | << "Expect an offset for non-AA points."; |
| 152 | |
| 153 | LinesOp antiAliasedLinesOp(bounds, Matrix4::identity(), nullptr, &aaPaint, points, 4); |
| 154 | EXPECT_EQ(TransformFlags::None, getGlopTransformFlags(renderThread, &antiAliasedLinesOp)) |
| 155 | << "Expect no offset for AA lines."; |
| 156 | LinesOp linesOp(bounds, Matrix4::identity(), nullptr, &paint, points, 4); |
| 157 | EXPECT_EQ(TransformFlags::OffsetByFudgeFactor, getGlopTransformFlags(renderThread, &linesOp)) |
| 158 | << "Expect an offset for non-AA lines."; |
sergeyv | 284b765 | 2016-05-10 13:58:12 -0700 | [diff] [blame] | 159 | } |
| 160 | |
Greg Daniel | 98c78dad | 2017-01-04 14:45:56 -0500 | [diff] [blame] | 161 | RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, renderTextWithShadow) { |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 162 | auto node = TestUtils::createNode<RecordingCanvas>( |
| 163 | 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) { |
sergeyv | 284b765 | 2016-05-10 13:58:12 -0700 | [diff] [blame] | 164 | |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 165 | android::Paint shadowPaint; |
| 166 | shadowPaint.setColor(SK_ColorRED); |
sergeyv | 284b765 | 2016-05-10 13:58:12 -0700 | [diff] [blame] | 167 | |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 168 | SkScalar sigma = Blur::convertRadiusToSigma(5); |
| 169 | shadowPaint.setLooper(SkBlurDrawLooper::Make(SK_ColorWHITE, sigma, 3, 3)); |
sergeyv | 284b765 | 2016-05-10 13:58:12 -0700 | [diff] [blame] | 170 | |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 171 | TestUtils::drawUtf8ToCanvas(&canvas, "A", shadowPaint, 25, 25); |
| 172 | TestUtils::drawUtf8ToCanvas(&canvas, "B", shadowPaint, 50, 50); |
| 173 | }); |
sergeyv | 284b765 | 2016-05-10 13:58:12 -0700 | [diff] [blame] | 174 | |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 175 | int glopCount = 0; |
| 176 | auto glopReceiver = [&glopCount](const Glop& glop) { |
sergeyv | 284b765 | 2016-05-10 13:58:12 -0700 | [diff] [blame] | 177 | if (glopCount < 2) { |
| 178 | // two white shadows |
| 179 | EXPECT_EQ(FloatColor({1, 1, 1, 1}), glop.fill.color); |
| 180 | } else { |
| 181 | // two text draws merged into one, drawn after both shadows |
| 182 | EXPECT_EQ(FloatColor({1, 0, 0, 1}), glop.fill.color); |
| 183 | } |
| 184 | glopCount++; |
| 185 | }; |
| 186 | |
| 187 | ValidatingBakedOpRenderer renderer(renderThread.renderState(), glopReceiver); |
| 188 | |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 189 | FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry, |
| 190 | Caches::getInstance()); |
sergeyv | 284b765 | 2016-05-10 13:58:12 -0700 | [diff] [blame] | 191 | frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); |
| 192 | |
| 193 | frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer); |
| 194 | ASSERT_EQ(3, glopCount) << "Exactly three glops expected"; |
Chris Craik | 3741328 | 2016-05-12 17:48:51 -0700 | [diff] [blame] | 195 | } |
| 196 | |
| 197 | static void validateLayerDraw(renderthread::RenderThread& renderThread, |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 198 | std::function<void(const Glop& glop)> validator) { |
| 199 | auto node = TestUtils::createNode<RecordingCanvas>( |
| 200 | 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) { |
| 201 | props.mutateLayerProperties().setType(LayerType::RenderLayer); |
Chris Craik | 3741328 | 2016-05-12 17:48:51 -0700 | [diff] [blame] | 202 | |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 203 | // provide different blend mode, so decoration draws contrast |
| 204 | props.mutateLayerProperties().setXferMode(SkBlendMode::kSrc); |
| 205 | canvas.drawColor(Color::Black, SkBlendMode::kSrcOver); |
| 206 | }); |
Chris Craik | 3741328 | 2016-05-12 17:48:51 -0700 | [diff] [blame] | 207 | OffscreenBuffer** layerHandle = node->getLayerHandle(); |
| 208 | |
| 209 | auto syncedNode = TestUtils::getSyncedNode(node); |
| 210 | |
| 211 | // create RenderNode's layer here in same way prepareTree would |
| 212 | OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); |
| 213 | *layerHandle = &layer; |
| 214 | { |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 215 | LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid |
Chris Craik | 3741328 | 2016-05-12 17:48:51 -0700 | [diff] [blame] | 216 | layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(0, 0, 100, 100)); |
| 217 | |
| 218 | ValidatingBakedOpRenderer renderer(renderThread.renderState(), validator); |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 219 | FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry, |
| 220 | Caches::getInstance()); |
Chris Craik | 3741328 | 2016-05-12 17:48:51 -0700 | [diff] [blame] | 221 | frameBuilder.deferLayers(layerUpdateQueue); |
| 222 | frameBuilder.deferRenderNode(*syncedNode); |
| 223 | frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer); |
| 224 | } |
| 225 | |
| 226 | // clean up layer pointer, so we can safely destruct RenderNode |
| 227 | *layerHandle = nullptr; |
| 228 | } |
| 229 | |
| 230 | static FloatColor makeFloatColor(uint32_t color) { |
| 231 | FloatColor c; |
| 232 | c.set(color); |
| 233 | return c; |
| 234 | } |
| 235 | |
Greg Daniel | 98c78dad | 2017-01-04 14:45:56 -0500 | [diff] [blame] | 236 | RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, layerUpdateProperties) { |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 237 | for (bool debugOverdraw : {false, true}) { |
| 238 | for (bool debugLayersUpdates : {false, true}) { |
Chris Craik | 3741328 | 2016-05-12 17:48:51 -0700 | [diff] [blame] | 239 | ScopedProperty<bool> ovdProp(Properties::debugOverdraw, debugOverdraw); |
| 240 | ScopedProperty<bool> lupProp(Properties::debugLayersUpdates, debugLayersUpdates); |
| 241 | |
| 242 | int glopCount = 0; |
| 243 | validateLayerDraw(renderThread, [&glopCount, &debugLayersUpdates](const Glop& glop) { |
| 244 | if (glopCount == 0) { |
| 245 | // 0 - Black layer fill |
| 246 | EXPECT_TRUE(glop.fill.colorEnabled); |
| 247 | EXPECT_EQ(makeFloatColor(Color::Black), glop.fill.color); |
| 248 | } else if (glopCount == 1) { |
| 249 | // 1 - Uncolored (textured) layer draw |
| 250 | EXPECT_FALSE(glop.fill.colorEnabled); |
| 251 | } else if (glopCount == 2) { |
| 252 | // 2 - layer overlay, if present |
| 253 | EXPECT_TRUE(glop.fill.colorEnabled); |
| 254 | // blend srcover, different from that of layer |
| 255 | EXPECT_EQ(GLenum(GL_ONE), glop.blend.src); |
| 256 | EXPECT_EQ(GLenum(GL_ONE_MINUS_SRC_ALPHA), glop.blend.dst); |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 257 | EXPECT_EQ(makeFloatColor(debugLayersUpdates ? 0x7f00ff00 : 0), glop.fill.color) |
| 258 | << "Should be transparent green if debugLayersUpdates"; |
Chris Craik | 3741328 | 2016-05-12 17:48:51 -0700 | [diff] [blame] | 259 | } else if (glopCount < 7) { |
| 260 | // 3 - 6 - overdraw indicator overlays, if present |
| 261 | EXPECT_TRUE(glop.fill.colorEnabled); |
| 262 | uint32_t expectedColor = Caches::getInstance().getOverdrawColor(glopCount - 2); |
| 263 | ASSERT_EQ(makeFloatColor(expectedColor), glop.fill.color); |
| 264 | } else { |
| 265 | ADD_FAILURE() << "Too many glops observed"; |
| 266 | } |
| 267 | glopCount++; |
| 268 | }); |
| 269 | int expectedCount = 2; |
| 270 | if (debugLayersUpdates || debugOverdraw) expectedCount++; |
| 271 | if (debugOverdraw) expectedCount += 4; |
| 272 | EXPECT_EQ(expectedCount, glopCount); |
| 273 | } |
| 274 | } |
| 275 | } |
sergeyv | 89561e6 | 2016-08-04 16:21:07 -0700 | [diff] [blame] | 276 | |
Greg Daniel | 98c78dad | 2017-01-04 14:45:56 -0500 | [diff] [blame] | 277 | RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, pathTextureSnapping) { |
sergeyv | 89561e6 | 2016-08-04 16:21:07 -0700 | [diff] [blame] | 278 | Rect bounds(10, 15, 20, 25); |
| 279 | SkPaint paint; |
| 280 | SkPath path; |
| 281 | path.addRect(SkRect::MakeXYWH(1.5, 3.8, 100, 90)); |
| 282 | PathOp op(bounds, Matrix4::identity(), nullptr, &paint, &path); |
John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 283 | testUnmergedGlopDispatch(renderThread, &op, [](const Glop& glop) { |
sergeyv | 89561e6 | 2016-08-04 16:21:07 -0700 | [diff] [blame] | 284 | auto texture = glop.fill.texture.texture; |
| 285 | ASSERT_NE(nullptr, texture); |
| 286 | EXPECT_EQ(1, reinterpret_cast<PathTexture*>(texture)->left); |
| 287 | EXPECT_EQ(3, reinterpret_cast<PathTexture*>(texture)->top); |
| 288 | }); |
Mike Reed | 260ab72 | 2016-10-07 15:59:20 -0400 | [diff] [blame] | 289 | } |