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