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 29 using namespace android; 30 using namespace android::uirenderer; 31 using namespace android::uirenderer::renderthread; 32 33 class ContextFactory : public android::uirenderer::IContextFactory { 34 public: 35 android::uirenderer::AnimationContext* createAnimationContext 36 (android::uirenderer::renderthread::TimeLord& clock) override { 37 return new android::uirenderer::AnimationContext(clock); 38 } 39 }; 40 41 TEST(RenderNode, hasParents) { 42 auto child = TestUtils::createNode(0, 0, 200, 400, 43 [](RenderProperties& props, Canvas& canvas) { 44 canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver); 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, SkBlendMode::kSrcOver); 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 69 TEST(RenderNode, validity) { 70 auto child = TestUtils::createNode(0, 0, 200, 400, 71 [](RenderProperties& props, Canvas& canvas) { 72 canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver); 73 }); 74 auto parent = TestUtils::createNode(0, 0, 200, 400, 75 [&child](RenderProperties& props, Canvas& canvas) { 76 canvas.drawRenderNode(child.get()); 77 }); 78 79 EXPECT_TRUE(child->isValid()); 80 EXPECT_TRUE(parent->isValid()); 81 EXPECT_TRUE(child->nothingToDraw()); 82 EXPECT_TRUE(parent->nothingToDraw()); 83 84 TestUtils::syncHierarchyPropertiesAndDisplayList(parent); 85 86 EXPECT_TRUE(child->isValid()); 87 EXPECT_TRUE(parent->isValid()); 88 EXPECT_FALSE(child->nothingToDraw()); 89 EXPECT_FALSE(parent->nothingToDraw()); 90 91 TestUtils::recordNode(*parent, [](Canvas& canvas) { 92 canvas.drawColor(Color::Amber_500, SkBlendMode::kSrcOver); 93 }); 94 95 EXPECT_TRUE(child->isValid()); 96 EXPECT_TRUE(parent->isValid()); 97 EXPECT_FALSE(child->nothingToDraw()); 98 EXPECT_FALSE(parent->nothingToDraw()); 99 100 TestUtils::syncHierarchyPropertiesAndDisplayList(parent); 101 102 EXPECT_FALSE(child->isValid()); 103 EXPECT_TRUE(parent->isValid()); 104 EXPECT_TRUE(child->nothingToDraw()); 105 EXPECT_FALSE(parent->nothingToDraw()); 106 107 TestUtils::recordNode(*child, [](Canvas& canvas) { 108 canvas.drawColor(Color::Amber_500, SkBlendMode::kSrcOver); 109 }); 110 111 EXPECT_TRUE(child->isValid()); 112 EXPECT_TRUE(child->nothingToDraw()); 113 114 TestUtils::recordNode(*parent, [&child](Canvas& canvas) { 115 canvas.drawRenderNode(child.get()); 116 }); 117 118 TestUtils::syncHierarchyPropertiesAndDisplayList(parent); 119 120 EXPECT_TRUE(child->isValid()); 121 EXPECT_TRUE(parent->isValid()); 122 EXPECT_FALSE(child->nothingToDraw()); 123 EXPECT_FALSE(parent->nothingToDraw()); 124 125 parent->destroyHardwareResources(); 126 127 EXPECT_FALSE(child->isValid()); 128 EXPECT_FALSE(parent->isValid()); 129 EXPECT_TRUE(child->nothingToDraw()); 130 EXPECT_TRUE(parent->nothingToDraw()); 131 } 132 133 TEST(RenderNode, multiTreeValidity) { 134 auto child = TestUtils::createNode(0, 0, 200, 400, 135 [](RenderProperties& props, Canvas& canvas) { 136 canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver); 137 }); 138 auto parent1 = TestUtils::createNode(0, 0, 200, 400, 139 [&child](RenderProperties& props, Canvas& canvas) { 140 canvas.drawRenderNode(child.get()); 141 }); 142 auto parent2 = TestUtils::createNode(0, 0, 200, 400, 143 [&child](RenderProperties& props, Canvas& canvas) { 144 canvas.drawRenderNode(child.get()); 145 }); 146 147 EXPECT_TRUE(child->isValid()); 148 EXPECT_TRUE(parent1->isValid()); 149 EXPECT_TRUE(parent2->isValid()); 150 EXPECT_TRUE(child->nothingToDraw()); 151 EXPECT_TRUE(parent1->nothingToDraw()); 152 EXPECT_TRUE(parent2->nothingToDraw()); 153 154 TestUtils::syncHierarchyPropertiesAndDisplayList(parent1); 155 156 EXPECT_TRUE(child->isValid()); 157 EXPECT_TRUE(parent1->isValid()); 158 EXPECT_TRUE(parent2->isValid()); 159 EXPECT_FALSE(child->nothingToDraw()); 160 EXPECT_FALSE(parent1->nothingToDraw()); 161 EXPECT_TRUE(parent2->nothingToDraw()); 162 163 TestUtils::syncHierarchyPropertiesAndDisplayList(parent2); 164 165 EXPECT_TRUE(child->isValid()); 166 EXPECT_TRUE(parent1->isValid()); 167 EXPECT_TRUE(parent2->isValid()); 168 EXPECT_FALSE(child->nothingToDraw()); 169 EXPECT_FALSE(parent1->nothingToDraw()); 170 EXPECT_FALSE(parent2->nothingToDraw()); 171 172 TestUtils::recordNode(*parent1, [](Canvas& canvas) { 173 canvas.drawColor(Color::Amber_500, SkBlendMode::kSrcOver); 174 }); 175 176 TestUtils::syncHierarchyPropertiesAndDisplayList(parent1); 177 178 EXPECT_TRUE(child->isValid()); 179 EXPECT_TRUE(parent1->isValid()); 180 EXPECT_TRUE(parent2->isValid()); 181 EXPECT_FALSE(child->nothingToDraw()); 182 EXPECT_FALSE(parent1->nothingToDraw()); 183 EXPECT_FALSE(parent2->nothingToDraw()); 184 185 TestUtils::recordNode(*parent2, [](Canvas& canvas) { 186 canvas.drawColor(Color::Amber_500, SkBlendMode::kSrcOver); 187 }); 188 189 TestUtils::syncHierarchyPropertiesAndDisplayList(parent2); 190 191 EXPECT_FALSE(child->isValid()); 192 EXPECT_TRUE(parent1->isValid()); 193 EXPECT_TRUE(parent2->isValid()); 194 EXPECT_TRUE(child->nothingToDraw()); 195 EXPECT_FALSE(parent1->nothingToDraw()); 196 EXPECT_FALSE(parent2->nothingToDraw()); 197 198 TestUtils::recordNode(*child, [](Canvas& canvas) { 199 canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver); 200 }); 201 TestUtils::syncHierarchyPropertiesAndDisplayList(child); 202 203 TestUtils::recordNode(*parent1, [&child](Canvas& canvas) { 204 canvas.drawRenderNode(child.get()); 205 }); 206 TestUtils::syncHierarchyPropertiesAndDisplayList(parent1); 207 208 TestUtils::recordNode(*parent2, [&child](Canvas& canvas) { 209 canvas.drawRenderNode(child.get()); 210 }); 211 TestUtils::syncHierarchyPropertiesAndDisplayList(parent2); 212 213 EXPECT_TRUE(child->isValid()); 214 EXPECT_TRUE(parent1->isValid()); 215 EXPECT_TRUE(parent2->isValid()); 216 EXPECT_FALSE(child->nothingToDraw()); 217 EXPECT_FALSE(parent1->nothingToDraw()); 218 EXPECT_FALSE(parent2->nothingToDraw()); 219 220 parent1->destroyHardwareResources(); 221 222 EXPECT_TRUE(child->isValid()); 223 EXPECT_FALSE(parent1->isValid()); 224 EXPECT_TRUE(parent2->isValid()); 225 EXPECT_FALSE(child->nothingToDraw()); 226 EXPECT_TRUE(parent1->nothingToDraw()); 227 EXPECT_FALSE(parent2->nothingToDraw()); 228 229 parent2->destroyHardwareResources(); 230 231 EXPECT_FALSE(child->isValid()); 232 EXPECT_FALSE(parent1->isValid()); 233 EXPECT_FALSE(parent2->isValid()); 234 EXPECT_TRUE(child->nothingToDraw()); 235 EXPECT_TRUE(parent1->nothingToDraw()); 236 EXPECT_TRUE(parent2->nothingToDraw()); 237 } 238 239 TEST(RenderNode, releasedCallback) { 240 class DecRefOnReleased : public GlFunctorLifecycleListener { 241 public: 242 explicit DecRefOnReleased(int* refcnt) : mRefCnt(refcnt) {} 243 void onGlFunctorReleased(Functor* functor) override { 244 *mRefCnt -= 1; 245 } 246 private: 247 int* mRefCnt; 248 }; 249 250 int refcnt = 0; 251 sp<DecRefOnReleased> listener(new DecRefOnReleased(&refcnt)); 252 Functor noopFunctor; 253 254 auto node = TestUtils::createNode(0, 0, 200, 400, 255 [&](RenderProperties& props, Canvas& canvas) { 256 refcnt++; 257 canvas.callDrawGLFunction(&noopFunctor, listener.get()); 258 }); 259 TestUtils::syncHierarchyPropertiesAndDisplayList(node); 260 EXPECT_EQ(1, refcnt); 261 262 TestUtils::recordNode(*node, [&](Canvas& canvas) { 263 refcnt++; 264 canvas.callDrawGLFunction(&noopFunctor, listener.get()); 265 }); 266 EXPECT_EQ(2, refcnt); 267 268 TestUtils::syncHierarchyPropertiesAndDisplayList(node); 269 EXPECT_EQ(1, refcnt); 270 271 TestUtils::recordNode(*node, [](Canvas& canvas) {}); 272 EXPECT_EQ(1, refcnt); 273 TestUtils::syncHierarchyPropertiesAndDisplayList(node); 274 EXPECT_EQ(0, refcnt); 275 } 276 277 RENDERTHREAD_TEST(RenderNode, prepareTree_nullableDisplayList) { 278 auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr); 279 ContextFactory contextFactory; 280 std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create( 281 renderThread, false, rootNode.get(), &contextFactory)); 282 TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get()); 283 DamageAccumulator damageAccumulator; 284 info.damageAccumulator = &damageAccumulator; 285 286 { 287 auto nonNullDLNode = TestUtils::createNode(0, 0, 200, 400, 288 [](RenderProperties& props, Canvas& canvas) { 289 canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver); 290 }); 291 TestUtils::syncHierarchyPropertiesAndDisplayList(nonNullDLNode); 292 EXPECT_TRUE(nonNullDLNode->getDisplayList()); 293 nonNullDLNode->prepareTree(info); 294 } 295 296 { 297 auto nullDLNode = TestUtils::createNode(0, 0, 200, 400, nullptr); 298 TestUtils::syncHierarchyPropertiesAndDisplayList(nullDLNode); 299 EXPECT_FALSE(nullDLNode->getDisplayList()); 300 nullDLNode->prepareTree(info); 301 } 302 303 canvasContext->destroy(); 304 } 305 306 RENDERTHREAD_TEST(RenderNode, prepareTree_HwLayer_AVD_enqueueDamage) { 307 308 VectorDrawable::Group* group = new VectorDrawable::Group(); 309 sp<VectorDrawableRoot> vectorDrawable(new VectorDrawableRoot(group)); 310 311 auto rootNode = TestUtils::createNode(0, 0, 200, 400, 312 [&](RenderProperties& props, Canvas& canvas) { 313 canvas.drawVectorDrawable(vectorDrawable.get()); 314 }); 315 ContextFactory contextFactory; 316 std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create( 317 renderThread, false, rootNode.get(), &contextFactory)); 318 TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get()); 319 DamageAccumulator damageAccumulator; 320 LayerUpdateQueue layerUpdateQueue; 321 info.damageAccumulator = &damageAccumulator; 322 info.layerUpdateQueue = &layerUpdateQueue; 323 324 // Put node on HW layer 325 rootNode->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer); 326 327 TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode); 328 rootNode->prepareTree(info); 329 330 // Check that the VD is in the dislay list, and the layer update queue contains the correct 331 // damage rect. 332 EXPECT_TRUE(rootNode->getDisplayList()->hasVectorDrawables()); 333 EXPECT_FALSE(info.layerUpdateQueue->entries().empty()); 334 EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode.get()); 335 EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage); 336 canvasContext->destroy(); 337 } 338