RenderNodeTests.cpp revision 0df6209a02d0ea99d2dff3a46ed9febd5925df4b
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#include <VectorDrawable.h> 19 20#include "AnimationContext.h" 21#include "DamageAccumulator.h" 22#include "IContextFactory.h" 23#include "RenderNode.h" 24#include "TreeInfo.h" 25#include "renderthread/CanvasContext.h" 26#include "tests/common/TestUtils.h" 27#include "utils/Color.h" 28 29using namespace android; 30using namespace android::uirenderer; 31using namespace android::uirenderer::renderthread; 32 33class ContextFactory : public android::uirenderer::IContextFactory { 34public: 35 android::uirenderer::AnimationContext* createAnimationContext 36 (android::uirenderer::renderthread::TimeLord& clock) override { 37 return new android::uirenderer::AnimationContext(clock); 38 } 39}; 40 41TEST(RenderNode, hasParents) { 42 auto child = TestUtils::createNode(0, 0, 200, 400, 43 [](RenderProperties& props, Canvas& canvas) { 44 canvas.drawColor(Color::Red_500, SkXfermode::kSrcOver_Mode); 45 }); 46 auto parent = TestUtils::createNode(0, 0, 200, 400, 47 [&child](RenderProperties& props, Canvas& canvas) { 48 canvas.drawRenderNode(child.get()); 49 }); 50 51 TestUtils::syncHierarchyPropertiesAndDisplayList(parent); 52 53 EXPECT_TRUE(child->hasParents()) << "Child node has no parent"; 54 EXPECT_FALSE(parent->hasParents()) << "Root node shouldn't have any parents"; 55 56 TestUtils::recordNode(*parent, [](Canvas& canvas) { 57 canvas.drawColor(Color::Amber_500, SkXfermode::kSrcOver_Mode); 58 }); 59 60 EXPECT_TRUE(child->hasParents()) << "Child should still have a parent"; 61 EXPECT_FALSE(parent->hasParents()) << "Root node shouldn't have any parents"; 62 63 TestUtils::syncHierarchyPropertiesAndDisplayList(parent); 64 65 EXPECT_FALSE(child->hasParents()) << "Child should be removed"; 66 EXPECT_FALSE(parent->hasParents()) << "Root node shouldn't have any parents"; 67} 68 69TEST(RenderNode, releasedCallback) { 70 class DecRefOnReleased : public GlFunctorLifecycleListener { 71 public: 72 explicit DecRefOnReleased(int* refcnt) : mRefCnt(refcnt) {} 73 void onGlFunctorReleased(Functor* functor) override { 74 *mRefCnt -= 1; 75 } 76 private: 77 int* mRefCnt; 78 }; 79 80 int refcnt = 0; 81 sp<DecRefOnReleased> listener(new DecRefOnReleased(&refcnt)); 82 Functor noopFunctor; 83 84 auto node = TestUtils::createNode(0, 0, 200, 400, 85 [&](RenderProperties& props, Canvas& canvas) { 86 refcnt++; 87 canvas.callDrawGLFunction(&noopFunctor, listener.get()); 88 }); 89 TestUtils::syncHierarchyPropertiesAndDisplayList(node); 90 EXPECT_EQ(1, refcnt); 91 92 TestUtils::recordNode(*node, [&](Canvas& canvas) { 93 refcnt++; 94 canvas.callDrawGLFunction(&noopFunctor, listener.get()); 95 }); 96 EXPECT_EQ(2, refcnt); 97 98 TestUtils::syncHierarchyPropertiesAndDisplayList(node); 99 EXPECT_EQ(1, refcnt); 100 101 TestUtils::recordNode(*node, [](Canvas& canvas) {}); 102 EXPECT_EQ(1, refcnt); 103 TestUtils::syncHierarchyPropertiesAndDisplayList(node); 104 EXPECT_EQ(0, refcnt); 105} 106 107RENDERTHREAD_TEST(RenderNode, prepareTree_nullableDisplayList) { 108 auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr); 109 ContextFactory contextFactory; 110 std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create( 111 renderThread, false, rootNode.get(), &contextFactory)); 112 TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get()); 113 DamageAccumulator damageAccumulator; 114 info.damageAccumulator = &damageAccumulator; 115 info.observer = nullptr; 116 117 { 118 auto nonNullDLNode = TestUtils::createNode(0, 0, 200, 400, 119 [](RenderProperties& props, Canvas& canvas) { 120 canvas.drawColor(Color::Red_500, SkXfermode::kSrcOver_Mode); 121 }); 122 TestUtils::syncHierarchyPropertiesAndDisplayList(nonNullDLNode); 123 EXPECT_TRUE(nonNullDLNode->getDisplayList()); 124 nonNullDLNode->prepareTree(info); 125 } 126 127 { 128 auto nullDLNode = TestUtils::createNode(0, 0, 200, 400, nullptr); 129 TestUtils::syncHierarchyPropertiesAndDisplayList(nullDLNode); 130 EXPECT_FALSE(nullDLNode->getDisplayList()); 131 nullDLNode->prepareTree(info); 132 } 133 134 canvasContext->destroy(nullptr); 135} 136 137RENDERTHREAD_TEST(RenderNode, prepareTree_HwLayer_AVD_enqueueDamage) { 138 139 VectorDrawable::Group* group = new VectorDrawable::Group(); 140 VectorDrawableRoot* vectorDrawable = new VectorDrawableRoot(group); 141 auto rootNode = TestUtils::createNode(0, 0, 200, 400, 142 [&](RenderProperties& props, Canvas& canvas) { 143 canvas.drawVectorDrawable(vectorDrawable); 144 }); 145 ContextFactory contextFactory; 146 std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create( 147 renderThread, false, rootNode.get(), &contextFactory)); 148 TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get()); 149 DamageAccumulator damageAccumulator; 150 LayerUpdateQueue layerUpdateQueue; 151 info.damageAccumulator = &damageAccumulator; 152 info.layerUpdateQueue = &layerUpdateQueue; 153 info.observer = nullptr; 154 155 // Put node on HW layer 156 rootNode->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer); 157 158 TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode); 159 rootNode->prepareTree(info); 160 161 // Check that the VD is in the dislay list, and the layer update queue contains the correct 162 // damage rect. 163 EXPECT_TRUE(rootNode->getDisplayList()->hasVectorDrawables()); 164 EXPECT_FALSE(info.layerUpdateQueue->entries().empty()); 165 EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode); 166 EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage); 167 168 delete vectorDrawable; 169 canvasContext->destroy(nullptr); 170} 171