RenderNodeDrawableTests.cpp revision 2f06e8ad1a1c4d0866bb66854d2759e275898635
1021693b967a2c5556dddd183eb0247df4079e1adStan Iliev/* 2021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * Copyright (C) 2016 The Android Open Source Project 3021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * 4021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * Licensed under the Apache License, Version 2.0 (the "License"); 5021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * you may not use this file except in compliance with the License. 6021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * You may obtain a copy of the License at 7021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * 8021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * http://www.apache.org/licenses/LICENSE-2.0 9021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * 10021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * Unless required by applicable law or agreed to in writing, software 11021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * distributed under the License is distributed on an "AS IS" BASIS, 12021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * See the License for the specific language governing permissions and 14021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * limitations under the License. 15021693b967a2c5556dddd183eb0247df4079e1adStan Iliev */ 16021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 17021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include <gtest/gtest.h> 18021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include <VectorDrawable.h> 19021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 20021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "AnimationContext.h" 21021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "DamageAccumulator.h" 22021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "IContextFactory.h" 23021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "pipeline/skia/SkiaDisplayList.h" 24021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "pipeline/skia/SkiaRecordingCanvas.h" 25021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "renderthread/CanvasContext.h" 26021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "tests/common/TestUtils.h" 27021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "SkiaCanvas.h" 28021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include <SkLiteRecorder.h> 29021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include <string.h> 30021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 31021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 32021693b967a2c5556dddd183eb0247df4079e1adStan Ilievusing namespace android; 33021693b967a2c5556dddd183eb0247df4079e1adStan Ilievusing namespace android::uirenderer; 34021693b967a2c5556dddd183eb0247df4079e1adStan Ilievusing namespace android::uirenderer::renderthread; 35021693b967a2c5556dddd183eb0247df4079e1adStan Ilievusing namespace android::uirenderer::skiapipeline; 36021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 37021693b967a2c5556dddd183eb0247df4079e1adStan IlievTEST(RenderNodeDrawable, create) { 38021693b967a2c5556dddd183eb0247df4079e1adStan Iliev auto rootNode = TestUtils::createNode(0, 0, 200, 400, 39021693b967a2c5556dddd183eb0247df4079e1adStan Iliev [](RenderProperties& props, Canvas& canvas) { 40021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver); 41021693b967a2c5556dddd183eb0247df4079e1adStan Iliev }); 42021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 43021693b967a2c5556dddd183eb0247df4079e1adStan Iliev auto skLiteDL = SkLiteDL::New(SkRect::MakeWH(1, 1)); 44021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkLiteRecorder canvas; 45021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas.reset(skLiteDL.get()); 46021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas.translate(100, 100); 47021693b967a2c5556dddd183eb0247df4079e1adStan Iliev RenderNodeDrawable drawable(rootNode.get(), &canvas); 48021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 49021693b967a2c5556dddd183eb0247df4079e1adStan Iliev ASSERT_EQ(drawable.getRenderNode(), rootNode.get()); 50021693b967a2c5556dddd183eb0247df4079e1adStan Iliev ASSERT_EQ(&drawable.getNodeProperties(), &rootNode->properties()); 51021693b967a2c5556dddd183eb0247df4079e1adStan Iliev ASSERT_EQ(drawable.getRecordedMatrix(), canvas.getTotalMatrix()); 52021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 53021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 542f06e8ad1a1c4d0866bb66854d2759e275898635Stan Ilievstatic void drawOrderedRect(Canvas* canvas, uint8_t expectedDrawOrder) { 552f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev SkPaint paint; 562f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev // order put in blue channel, transparent so overlapped content doesn't get rejected 572f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev paint.setColor(SkColorSetARGB(1, 0, 0, expectedDrawOrder)); 582f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev canvas->drawRect(0, 0, 100, 100, paint); 59021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 60021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 612f06e8ad1a1c4d0866bb66854d2759e275898635Stan Ilievstatic void drawOrderedNode(Canvas* canvas, uint8_t expectedDrawOrder, float z) { 622f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev auto node = TestUtils::createSkiaNode(0, 0, 100, 100, 632f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev [expectedDrawOrder, z](RenderProperties& props, SkiaRecordingCanvas& canvas) { 642f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedRect(&canvas, expectedDrawOrder); 652f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev props.setTranslationZ(z); 662f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev }); 672f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership 682f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev} 69021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 702f06e8ad1a1c4d0866bb66854d2759e275898635Stan IlievTEST(RenderNodeDrawable, zReorder) { 712f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev class ZReorderCanvas : public SkCanvas { 722f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev public: 732f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev ZReorderCanvas(int width, int height) : SkCanvas(width, height) {} 742f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev void onDrawRect(const SkRect& rect, const SkPaint& paint) override { 752f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev int expectedOrder = SkColorGetB(paint.getColor()); // extract order from blue channel 762f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev EXPECT_EQ(expectedOrder, mIndex++) << "An op was drawn out of order"; 772f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev } 782f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev int getIndex() { return mIndex; } 792f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev protected: 802f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev int mIndex = 0; 812f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev }; 822f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev 832f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev auto parent = TestUtils::createSkiaNode(0, 0, 100, 100, 842f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 852f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedNode(&canvas, 0, 10.0f); // in reorder=false at this point, so played inorder 862f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedRect(&canvas, 1); 872f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev canvas.insertReorderBarrier(true); 882f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedNode(&canvas, 6, 2.0f); 892f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedRect(&canvas, 3); 902f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedNode(&canvas, 4, 0.0f); 912f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedRect(&canvas, 5); 922f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedNode(&canvas, 2, -2.0f); 932f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedNode(&canvas, 7, 2.0f); 942f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev canvas.insertReorderBarrier(false); 952f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedRect(&canvas, 8); 962f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder 972f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev }); 982f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev 992f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev //create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection 1002f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev ZReorderCanvas canvas(100, 100); 1012f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev RenderNodeDrawable drawable(parent.get(), &canvas, false); 1022f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev canvas.drawDrawable(&drawable); 1032f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev EXPECT_EQ(10, canvas.getIndex()); 104021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 105021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 106021693b967a2c5556dddd183eb0247df4079e1adStan IlievTEST(RenderNodeDrawable, composeOnLayer) 107021693b967a2c5556dddd183eb0247df4079e1adStan Iliev{ 108021693b967a2c5556dddd183eb0247df4079e1adStan Iliev auto surface = SkSurface::MakeRasterN32Premul(1, 1); 109021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkCanvas& canvas = *surface->getCanvas(); 110021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver); 111021693b967a2c5556dddd183eb0247df4079e1adStan Iliev ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE); 112021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 113500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev auto rootNode = TestUtils::createSkiaNode(0, 0, 1, 1, 114021693b967a2c5556dddd183eb0247df4079e1adStan Iliev [](RenderProperties& props, SkiaRecordingCanvas& recorder) { 115021693b967a2c5556dddd183eb0247df4079e1adStan Iliev recorder.drawColor(SK_ColorRED, SkBlendMode::kSrcOver); 116021693b967a2c5556dddd183eb0247df4079e1adStan Iliev }); 117021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 118021693b967a2c5556dddd183eb0247df4079e1adStan Iliev //attach a layer to the render node 119021693b967a2c5556dddd183eb0247df4079e1adStan Iliev auto surfaceLayer = SkSurface::MakeRasterN32Premul(1, 1); 120021693b967a2c5556dddd183eb0247df4079e1adStan Iliev auto canvas2 = surfaceLayer->getCanvas(); 121021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas2->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver); 122500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev rootNode->setLayerSurface(surfaceLayer); 123021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 124021693b967a2c5556dddd183eb0247df4079e1adStan Iliev RenderNodeDrawable drawable1(rootNode.get(), &canvas, false); 125021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas.drawDrawable(&drawable1); 126021693b967a2c5556dddd183eb0247df4079e1adStan Iliev ASSERT_EQ(SK_ColorRED, TestUtils::getColor(surface, 0, 0)); 127021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 128021693b967a2c5556dddd183eb0247df4079e1adStan Iliev RenderNodeDrawable drawable2(rootNode.get(), &canvas, true); 129021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas.drawDrawable(&drawable2); 130021693b967a2c5556dddd183eb0247df4079e1adStan Iliev ASSERT_EQ(SK_ColorWHITE, TestUtils::getColor(surface, 0, 0)); 131021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 132021693b967a2c5556dddd183eb0247df4079e1adStan Iliev RenderNodeDrawable drawable3(rootNode.get(), &canvas, false); 133021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas.drawDrawable(&drawable3); 134021693b967a2c5556dddd183eb0247df4079e1adStan Iliev ASSERT_EQ(SK_ColorRED, TestUtils::getColor(surface, 0, 0)); 135021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 136500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev rootNode->setLayerSurface(sk_sp<SkSurface>()); 137021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 138021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 139021693b967a2c5556dddd183eb0247df4079e1adStan Iliev//TODO: refactor to cover test cases from FrameBuilderTests_projectionReorder 140021693b967a2c5556dddd183eb0247df4079e1adStan Iliev//validate with bounds and projection path mask. 141021693b967a2c5556dddd183eb0247df4079e1adStan Iliev//TODO: research if we could hook in and mock/validate different aspects of the drawing, 142021693b967a2c5556dddd183eb0247df4079e1adStan Iliev//instead of validating pixels 143021693b967a2c5556dddd183eb0247df4079e1adStan IlievTEST(RenderNodeDrawable, projectDraw) { 144021693b967a2c5556dddd183eb0247df4079e1adStan Iliev auto surface = SkSurface::MakeRasterN32Premul(1, 1); 145021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkCanvas& canvas = *surface->getCanvas(); 146021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver); 147021693b967a2c5556dddd183eb0247df4079e1adStan Iliev ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE); 148021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 149500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev auto redNode = TestUtils::createSkiaNode(0, 0, 1, 1, 150021693b967a2c5556dddd183eb0247df4079e1adStan Iliev [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) { 151021693b967a2c5556dddd183eb0247df4079e1adStan Iliev redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver); 152021693b967a2c5556dddd183eb0247df4079e1adStan Iliev }, "redNode"); 153021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 154500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev auto greenNodeWithRedChild = TestUtils::createSkiaNode(0, 0, 1, 1, 155021693b967a2c5556dddd183eb0247df4079e1adStan Iliev [&](RenderProperties& props, SkiaRecordingCanvas& greenCanvasWithRedChild) { 156021693b967a2c5556dddd183eb0247df4079e1adStan Iliev greenCanvasWithRedChild.drawRenderNode(redNode.get()); 157021693b967a2c5556dddd183eb0247df4079e1adStan Iliev greenCanvasWithRedChild.drawColor(SK_ColorGREEN, SkBlendMode::kSrcOver); 158021693b967a2c5556dddd183eb0247df4079e1adStan Iliev }, "greenNodeWithRedChild"); 159021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 160500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev auto rootNode = TestUtils::createSkiaNode(0, 0, 1, 1, 161021693b967a2c5556dddd183eb0247df4079e1adStan Iliev [&](RenderProperties& props, SkiaRecordingCanvas& rootCanvas) { 162021693b967a2c5556dddd183eb0247df4079e1adStan Iliev rootCanvas.drawRenderNode(greenNodeWithRedChild.get()); 163021693b967a2c5556dddd183eb0247df4079e1adStan Iliev }, "rootNode"); 164021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkiaDisplayList* rootDisplayList = static_cast<SkiaDisplayList*>( 165021693b967a2c5556dddd183eb0247df4079e1adStan Iliev (const_cast<DisplayList*>(rootNode->getDisplayList()))); 166021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 167021693b967a2c5556dddd183eb0247df4079e1adStan Iliev RenderNodeDrawable rootDrawable(rootNode.get(), &canvas, false); 168021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas.drawDrawable(&rootDrawable); 169021693b967a2c5556dddd183eb0247df4079e1adStan Iliev ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorGREEN); 170021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 171021693b967a2c5556dddd183eb0247df4079e1adStan Iliev //project redNode on rootNode, which will change the test outcome, 172021693b967a2c5556dddd183eb0247df4079e1adStan Iliev //because redNode will draw after greenNodeWithRedChild 173021693b967a2c5556dddd183eb0247df4079e1adStan Iliev rootDisplayList->mIsProjectionReceiver = true; 174021693b967a2c5556dddd183eb0247df4079e1adStan Iliev redNode->animatorProperties().setProjectBackwards(true); 175021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas.drawDrawable(&rootDrawable); 176021693b967a2c5556dddd183eb0247df4079e1adStan Iliev ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED); 177021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 178