1419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik/* 2419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * Copyright (C) 2016 The Android Open Source Project 3419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * 4419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * Licensed under the Apache License, Version 2.0 (the "License"); 5419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * you may not use this file except in compliance with the License. 6419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * You may obtain a copy of the License at 7419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * 8419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * http://www.apache.org/licenses/LICENSE-2.0 9419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * 10419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * Unless required by applicable law or agreed to in writing, software 11419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * distributed under the License is distributed on an "AS IS" BASIS, 12419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * See the License for the specific language governing permissions and 14419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik * limitations under the License. 15419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik */ 16419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 17419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik#include <gtest/gtest.h> 18419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 19419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik#include <BakedOpDispatcher.h> 20419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik#include <BakedOpRenderer.h> 21284b765e3c1647859d4dac772744e8859c033216sergeyv#include <FrameBuilder.h> 2237413289478a965336239c731ebfea37ac4dde28Chris Craik#include <LayerUpdateQueue.h> 2337413289478a965336239c731ebfea37ac4dde28Chris Craik#include <RecordedOp.h> 241bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#include <hwui/Paint.h> 25419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik#include <tests/common/TestUtils.h> 2637413289478a965336239c731ebfea37ac4dde28Chris Craik#include <utils/Color.h> 27419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 2837413289478a965336239c731ebfea37ac4dde28Chris Craik#include <SkBlurDrawLooper.h> 29e98a046d3110eb2ff11a17f4ff27764b803a1379Chris Craik#include <SkDashPathEffect.h> 3089561e6e4201aebc78a76ac055071ad2149db704sergeyv#include <SkPath.h> 31e98a046d3110eb2ff11a17f4ff27764b803a1379Chris Craik 32419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craikusing namespace android::uirenderer; 33419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 34419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craikstatic BakedOpRenderer::LightInfo sLightInfo; 351bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckconst FrameBuilder::LightGeometry sLightGeometry = {{100, 100, 100}, 50}; 36419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 37419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craikclass ValidatingBakedOpRenderer : public BakedOpRenderer { 38419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craikpublic: 391bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck ValidatingBakedOpRenderer(RenderState& renderState, 401bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck std::function<void(const Glop& glop)> validator) 4107ae505d4045e2b1ae501e87560984dae06f9dd8Romain Guy : BakedOpRenderer(Caches::getInstance(), renderState, true, false, sLightInfo) 42419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik , mValidator(validator) { 43419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik mGlopReceiver = ValidatingGlopReceiver; 44419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik } 451bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck 46419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craikprivate: 47419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik static void ValidatingGlopReceiver(BakedOpRenderer& renderer, const Rect* dirtyBounds, 481bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const ClipBase* clip, const Glop& glop) { 49419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik auto vbor = reinterpret_cast<ValidatingBakedOpRenderer*>(&renderer); 50419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik vbor->mValidator(glop); 51419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik } 52419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik std::function<void(const Glop& glop)> mValidator; 53419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik}; 54419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 55284b765e3c1647859d4dac772744e8859c033216sergeyvtypedef void (*TestBakedOpReceiver)(BakedOpRenderer&, const BakedOpState&); 56419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 57419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craikstatic void testUnmergedGlopDispatch(renderthread::RenderThread& renderThread, RecordedOp* op, 581bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck std::function<void(const Glop& glop)> glopVerifier, 591bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck int expectedGlopCount = 1) { 60419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik // Create op, and wrap with basic state. 61419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik LinearAllocator allocator; 6237413289478a965336239c731ebfea37ac4dde28Chris Craik auto snapshot = TestUtils::makeSnapshot(Matrix4::identity(), Rect(100, 100)); 63419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik auto state = BakedOpState::tryConstruct(allocator, *snapshot, *op); 64419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik ASSERT_NE(nullptr, state); 65419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 66419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik int glopCount = 0; 671bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck auto glopReceiver = [&glopVerifier, &glopCount, &expectedGlopCount](const Glop& glop) { 68aebbbef5658fea13b06586d39adca351135d9edbsergeyv ASSERT_LE(glopCount++, expectedGlopCount) << expectedGlopCount << "glop(s) expected"; 69419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik glopVerifier(glop); 70419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik }; 71419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik ValidatingBakedOpRenderer renderer(renderThread.renderState(), glopReceiver); 72419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 731bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck// Dispatch based on op type created, similar to Frame/LayerBuilder dispatch behavior 741bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define X(Type) \ 751bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck [](BakedOpRenderer& renderer, const BakedOpState& state) { \ 761bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck BakedOpDispatcher::on##Type(renderer, static_cast<const Type&>(*(state.op)), state); \ 771bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck }, 78284b765e3c1647859d4dac772744e8859c033216sergeyv static TestBakedOpReceiver unmergedReceivers[] = BUILD_RENDERABLE_OP_LUT(X); 79419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik#undef X 80419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik unmergedReceivers[op->opId](renderer, *state); 81aebbbef5658fea13b06586d39adca351135d9edbsergeyv ASSERT_EQ(expectedGlopCount, glopCount) << "Exactly " << expectedGlopCount 821bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck << "Glop(s) expected"; 83419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik} 84419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 8598c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, pathTexture_positionOvalArc) { 86419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik SkPaint strokePaint; 87419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik strokePaint.setStyle(SkPaint::kStroke_Style); 88419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik strokePaint.setStrokeWidth(4); 89e98a046d3110eb2ff11a17f4ff27764b803a1379Chris Craik 90e98a046d3110eb2ff11a17f4ff27764b803a1379Chris Craik float intervals[] = {1.0f, 1.0f}; 91260ab726486317496bc12a57d599ea96dcde3284Mike Reed strokePaint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0)); 92e98a046d3110eb2ff11a17f4ff27764b803a1379Chris Craik 931bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck auto textureGlopVerifier = [](const Glop& glop) { 94419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik // validate glop produced by renderPathTexture (so texture, unit quad) 95419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik auto texture = glop.fill.texture.texture; 96419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik ASSERT_NE(nullptr, texture); 97419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik float expectedOffset = floor(4 * 1.5f + 0.5f); 98419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik EXPECT_EQ(expectedOffset, reinterpret_cast<PathTexture*>(texture)->offset) 99419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik << "Should see conservative offset from PathCache::computeBounds"; 100419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik Rect expectedBounds(10, 15, 20, 25); 101419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik expectedBounds.outset(expectedOffset); 102e98a046d3110eb2ff11a17f4ff27764b803a1379Chris Craik 103419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik Matrix4 expectedModelView; 104419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik expectedModelView.loadTranslate(10 - expectedOffset, 15 - expectedOffset, 0); 105419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik expectedModelView.scale(10 + 2 * expectedOffset, 10 + 2 * expectedOffset, 1); 106419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik EXPECT_EQ(expectedModelView, glop.transform.modelView) 107419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik << "X and Y offsets, and scale both applied to model view"; 108e98a046d3110eb2ff11a17f4ff27764b803a1379Chris Craik }; 109e98a046d3110eb2ff11a17f4ff27764b803a1379Chris Craik 110e98a046d3110eb2ff11a17f4ff27764b803a1379Chris Craik // Arc and Oval will render functionally the same glop, differing only in texture content 111e98a046d3110eb2ff11a17f4ff27764b803a1379Chris Craik ArcOp arcOp(Rect(10, 15, 20, 25), Matrix4::identity(), nullptr, &strokePaint, 0, 270, true); 112e98a046d3110eb2ff11a17f4ff27764b803a1379Chris Craik testUnmergedGlopDispatch(renderThread, &arcOp, textureGlopVerifier); 113e98a046d3110eb2ff11a17f4ff27764b803a1379Chris Craik 114e98a046d3110eb2ff11a17f4ff27764b803a1379Chris Craik OvalOp ovalOp(Rect(10, 15, 20, 25), Matrix4::identity(), nullptr, &strokePaint); 115e98a046d3110eb2ff11a17f4ff27764b803a1379Chris Craik testUnmergedGlopDispatch(renderThread, &ovalOp, textureGlopVerifier); 116419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik} 117419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik 11898c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, onLayerOp_bufferless) { 119419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik SkPaint layerPaint; 120419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik layerPaint.setAlpha(128); 1211bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck OffscreenBuffer* buffer = nullptr; // no providing a buffer, should hit rect fallback case 122419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik LayerOp op(Rect(10, 10), Matrix4::identity(), nullptr, &layerPaint, &buffer); 1231bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck testUnmergedGlopDispatch(renderThread, &op, 1241bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck [](const Glop& glop) { ADD_FAILURE() << "Nothing should happen"; }, 0); 125419a1e7ef53468e494d21c66ea7f63c0c522d208Chris Craik} 12692a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv 12792a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyvstatic int getGlopTransformFlags(renderthread::RenderThread& renderThread, RecordedOp* op) { 12892a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv int result = 0; 1291bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck testUnmergedGlopDispatch(renderThread, op, [&result](const Glop& glop) { 13092a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv result = glop.transform.transformFlags; 13192a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv }); 13292a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv return result; 13392a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv} 13492a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv 13598c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, offsetFlags) { 13692a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv Rect bounds(10, 15, 20, 25); 13792a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv SkPaint paint; 13892a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv SkPaint aaPaint; 13992a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv aaPaint.setAntiAlias(true); 14092a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv 14192a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv RoundRectOp roundRectOp(bounds, Matrix4::identity(), nullptr, &paint, 0, 270); 14292a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv EXPECT_EQ(TransformFlags::None, getGlopTransformFlags(renderThread, &roundRectOp)) 14392a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv << "Expect no offset for round rect op."; 14492a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv 14592a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv const float points[4] = {0.5, 0.5, 1.0, 1.0}; 14692a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv PointsOp antiAliasedPointsOp(bounds, Matrix4::identity(), nullptr, &aaPaint, points, 4); 14792a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv EXPECT_EQ(TransformFlags::None, getGlopTransformFlags(renderThread, &antiAliasedPointsOp)) 1481bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck << "Expect no offset for AA points."; 14992a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv PointsOp pointsOp(bounds, Matrix4::identity(), nullptr, &paint, points, 4); 15092a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv EXPECT_EQ(TransformFlags::OffsetByFudgeFactor, getGlopTransformFlags(renderThread, &pointsOp)) 15192a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv << "Expect an offset for non-AA points."; 15292a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv 15392a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv LinesOp antiAliasedLinesOp(bounds, Matrix4::identity(), nullptr, &aaPaint, points, 4); 15492a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv EXPECT_EQ(TransformFlags::None, getGlopTransformFlags(renderThread, &antiAliasedLinesOp)) 15592a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv << "Expect no offset for AA lines."; 15692a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv LinesOp linesOp(bounds, Matrix4::identity(), nullptr, &paint, points, 4); 15792a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv EXPECT_EQ(TransformFlags::OffsetByFudgeFactor, getGlopTransformFlags(renderThread, &linesOp)) 15892a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv << "Expect an offset for non-AA lines."; 159284b765e3c1647859d4dac772744e8859c033216sergeyv} 160284b765e3c1647859d4dac772744e8859c033216sergeyv 16198c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, renderTextWithShadow) { 1621bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck auto node = TestUtils::createNode<RecordingCanvas>( 1631bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) { 164284b765e3c1647859d4dac772744e8859c033216sergeyv 1651bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck android::Paint shadowPaint; 1661bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck shadowPaint.setColor(SK_ColorRED); 167284b765e3c1647859d4dac772744e8859c033216sergeyv 1681bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck SkScalar sigma = Blur::convertRadiusToSigma(5); 1691bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck shadowPaint.setLooper(SkBlurDrawLooper::Make(SK_ColorWHITE, sigma, 3, 3)); 170284b765e3c1647859d4dac772744e8859c033216sergeyv 1711bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck TestUtils::drawUtf8ToCanvas(&canvas, "A", shadowPaint, 25, 25); 1721bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck TestUtils::drawUtf8ToCanvas(&canvas, "B", shadowPaint, 50, 50); 1731bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck }); 174284b765e3c1647859d4dac772744e8859c033216sergeyv 1751bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck int glopCount = 0; 1761bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck auto glopReceiver = [&glopCount](const Glop& glop) { 177284b765e3c1647859d4dac772744e8859c033216sergeyv if (glopCount < 2) { 178284b765e3c1647859d4dac772744e8859c033216sergeyv // two white shadows 179284b765e3c1647859d4dac772744e8859c033216sergeyv EXPECT_EQ(FloatColor({1, 1, 1, 1}), glop.fill.color); 180284b765e3c1647859d4dac772744e8859c033216sergeyv } else { 181284b765e3c1647859d4dac772744e8859c033216sergeyv // two text draws merged into one, drawn after both shadows 182284b765e3c1647859d4dac772744e8859c033216sergeyv EXPECT_EQ(FloatColor({1, 0, 0, 1}), glop.fill.color); 183284b765e3c1647859d4dac772744e8859c033216sergeyv } 184284b765e3c1647859d4dac772744e8859c033216sergeyv glopCount++; 185284b765e3c1647859d4dac772744e8859c033216sergeyv }; 186284b765e3c1647859d4dac772744e8859c033216sergeyv 187284b765e3c1647859d4dac772744e8859c033216sergeyv ValidatingBakedOpRenderer renderer(renderThread.renderState(), glopReceiver); 188284b765e3c1647859d4dac772744e8859c033216sergeyv 1891bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry, 1901bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck Caches::getInstance()); 191284b765e3c1647859d4dac772744e8859c033216sergeyv frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 192284b765e3c1647859d4dac772744e8859c033216sergeyv 193284b765e3c1647859d4dac772744e8859c033216sergeyv frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer); 194284b765e3c1647859d4dac772744e8859c033216sergeyv ASSERT_EQ(3, glopCount) << "Exactly three glops expected"; 19537413289478a965336239c731ebfea37ac4dde28Chris Craik} 19637413289478a965336239c731ebfea37ac4dde28Chris Craik 19737413289478a965336239c731ebfea37ac4dde28Chris Craikstatic void validateLayerDraw(renderthread::RenderThread& renderThread, 1981bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck std::function<void(const Glop& glop)> validator) { 1991bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck auto node = TestUtils::createNode<RecordingCanvas>( 2001bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck 0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) { 2011bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 2021bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck 2031bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck // provide different blend mode, so decoration draws contrast 2041bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck props.mutateLayerProperties().setXferMode(SkBlendMode::kSrc); 2051bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck canvas.drawColor(Color::Black, SkBlendMode::kSrcOver); 2061bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck }); 20737413289478a965336239c731ebfea37ac4dde28Chris Craik OffscreenBuffer** layerHandle = node->getLayerHandle(); 20837413289478a965336239c731ebfea37ac4dde28Chris Craik 20937413289478a965336239c731ebfea37ac4dde28Chris Craik auto syncedNode = TestUtils::getSyncedNode(node); 21037413289478a965336239c731ebfea37ac4dde28Chris Craik 21137413289478a965336239c731ebfea37ac4dde28Chris Craik // create RenderNode's layer here in same way prepareTree would 21237413289478a965336239c731ebfea37ac4dde28Chris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 21337413289478a965336239c731ebfea37ac4dde28Chris Craik *layerHandle = &layer; 21437413289478a965336239c731ebfea37ac4dde28Chris Craik { 2151bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 21637413289478a965336239c731ebfea37ac4dde28Chris Craik layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(0, 0, 100, 100)); 21737413289478a965336239c731ebfea37ac4dde28Chris Craik 21837413289478a965336239c731ebfea37ac4dde28Chris Craik ValidatingBakedOpRenderer renderer(renderThread.renderState(), validator); 2191bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, sLightGeometry, 2201bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck Caches::getInstance()); 22137413289478a965336239c731ebfea37ac4dde28Chris Craik frameBuilder.deferLayers(layerUpdateQueue); 22237413289478a965336239c731ebfea37ac4dde28Chris Craik frameBuilder.deferRenderNode(*syncedNode); 22337413289478a965336239c731ebfea37ac4dde28Chris Craik frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer); 22437413289478a965336239c731ebfea37ac4dde28Chris Craik } 22537413289478a965336239c731ebfea37ac4dde28Chris Craik 22637413289478a965336239c731ebfea37ac4dde28Chris Craik // clean up layer pointer, so we can safely destruct RenderNode 22737413289478a965336239c731ebfea37ac4dde28Chris Craik *layerHandle = nullptr; 22837413289478a965336239c731ebfea37ac4dde28Chris Craik} 22937413289478a965336239c731ebfea37ac4dde28Chris Craik 23037413289478a965336239c731ebfea37ac4dde28Chris Craikstatic FloatColor makeFloatColor(uint32_t color) { 23137413289478a965336239c731ebfea37ac4dde28Chris Craik FloatColor c; 23237413289478a965336239c731ebfea37ac4dde28Chris Craik c.set(color); 23337413289478a965336239c731ebfea37ac4dde28Chris Craik return c; 23437413289478a965336239c731ebfea37ac4dde28Chris Craik} 23537413289478a965336239c731ebfea37ac4dde28Chris Craik 23698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, layerUpdateProperties) { 2371bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck for (bool debugOverdraw : {false, true}) { 2381bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck for (bool debugLayersUpdates : {false, true}) { 23937413289478a965336239c731ebfea37ac4dde28Chris Craik ScopedProperty<bool> ovdProp(Properties::debugOverdraw, debugOverdraw); 24037413289478a965336239c731ebfea37ac4dde28Chris Craik ScopedProperty<bool> lupProp(Properties::debugLayersUpdates, debugLayersUpdates); 24137413289478a965336239c731ebfea37ac4dde28Chris Craik 24237413289478a965336239c731ebfea37ac4dde28Chris Craik int glopCount = 0; 24337413289478a965336239c731ebfea37ac4dde28Chris Craik validateLayerDraw(renderThread, [&glopCount, &debugLayersUpdates](const Glop& glop) { 24437413289478a965336239c731ebfea37ac4dde28Chris Craik if (glopCount == 0) { 24537413289478a965336239c731ebfea37ac4dde28Chris Craik // 0 - Black layer fill 24637413289478a965336239c731ebfea37ac4dde28Chris Craik EXPECT_TRUE(glop.fill.colorEnabled); 24737413289478a965336239c731ebfea37ac4dde28Chris Craik EXPECT_EQ(makeFloatColor(Color::Black), glop.fill.color); 24837413289478a965336239c731ebfea37ac4dde28Chris Craik } else if (glopCount == 1) { 24937413289478a965336239c731ebfea37ac4dde28Chris Craik // 1 - Uncolored (textured) layer draw 25037413289478a965336239c731ebfea37ac4dde28Chris Craik EXPECT_FALSE(glop.fill.colorEnabled); 25137413289478a965336239c731ebfea37ac4dde28Chris Craik } else if (glopCount == 2) { 25237413289478a965336239c731ebfea37ac4dde28Chris Craik // 2 - layer overlay, if present 25337413289478a965336239c731ebfea37ac4dde28Chris Craik EXPECT_TRUE(glop.fill.colorEnabled); 25437413289478a965336239c731ebfea37ac4dde28Chris Craik // blend srcover, different from that of layer 25537413289478a965336239c731ebfea37ac4dde28Chris Craik EXPECT_EQ(GLenum(GL_ONE), glop.blend.src); 25637413289478a965336239c731ebfea37ac4dde28Chris Craik EXPECT_EQ(GLenum(GL_ONE_MINUS_SRC_ALPHA), glop.blend.dst); 2571bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck EXPECT_EQ(makeFloatColor(debugLayersUpdates ? 0x7f00ff00 : 0), glop.fill.color) 2581bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck << "Should be transparent green if debugLayersUpdates"; 25937413289478a965336239c731ebfea37ac4dde28Chris Craik } else if (glopCount < 7) { 26037413289478a965336239c731ebfea37ac4dde28Chris Craik // 3 - 6 - overdraw indicator overlays, if present 26137413289478a965336239c731ebfea37ac4dde28Chris Craik EXPECT_TRUE(glop.fill.colorEnabled); 26237413289478a965336239c731ebfea37ac4dde28Chris Craik uint32_t expectedColor = Caches::getInstance().getOverdrawColor(glopCount - 2); 26337413289478a965336239c731ebfea37ac4dde28Chris Craik ASSERT_EQ(makeFloatColor(expectedColor), glop.fill.color); 26437413289478a965336239c731ebfea37ac4dde28Chris Craik } else { 26537413289478a965336239c731ebfea37ac4dde28Chris Craik ADD_FAILURE() << "Too many glops observed"; 26637413289478a965336239c731ebfea37ac4dde28Chris Craik } 26737413289478a965336239c731ebfea37ac4dde28Chris Craik glopCount++; 26837413289478a965336239c731ebfea37ac4dde28Chris Craik }); 26937413289478a965336239c731ebfea37ac4dde28Chris Craik int expectedCount = 2; 27037413289478a965336239c731ebfea37ac4dde28Chris Craik if (debugLayersUpdates || debugOverdraw) expectedCount++; 27137413289478a965336239c731ebfea37ac4dde28Chris Craik if (debugOverdraw) expectedCount += 4; 27237413289478a965336239c731ebfea37ac4dde28Chris Craik EXPECT_EQ(expectedCount, glopCount); 27337413289478a965336239c731ebfea37ac4dde28Chris Craik } 27437413289478a965336239c731ebfea37ac4dde28Chris Craik } 27537413289478a965336239c731ebfea37ac4dde28Chris Craik} 27689561e6e4201aebc78a76ac055071ad2149db704sergeyv 27798c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, pathTextureSnapping) { 27889561e6e4201aebc78a76ac055071ad2149db704sergeyv Rect bounds(10, 15, 20, 25); 27989561e6e4201aebc78a76ac055071ad2149db704sergeyv SkPaint paint; 28089561e6e4201aebc78a76ac055071ad2149db704sergeyv SkPath path; 28189561e6e4201aebc78a76ac055071ad2149db704sergeyv path.addRect(SkRect::MakeXYWH(1.5, 3.8, 100, 90)); 28289561e6e4201aebc78a76ac055071ad2149db704sergeyv PathOp op(bounds, Matrix4::identity(), nullptr, &paint, &path); 2831bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck testUnmergedGlopDispatch(renderThread, &op, [](const Glop& glop) { 28489561e6e4201aebc78a76ac055071ad2149db704sergeyv auto texture = glop.fill.texture.texture; 28589561e6e4201aebc78a76ac055071ad2149db704sergeyv ASSERT_NE(nullptr, texture); 28689561e6e4201aebc78a76ac055071ad2149db704sergeyv EXPECT_EQ(1, reinterpret_cast<PathTexture*>(texture)->left); 28789561e6e4201aebc78a76ac055071ad2149db704sergeyv EXPECT_EQ(3, reinterpret_cast<PathTexture*>(texture)->top); 28889561e6e4201aebc78a76ac055071ad2149db704sergeyv }); 289260ab726486317496bc12a57d599ea96dcde3284Mike Reed} 290