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 <SkClipStack.h> 21 #include <SkLiteRecorder.h> 22 #include <SkSurface_Base.h> 23 #include <string.h> 24 #include "AnimationContext.h" 25 #include "DamageAccumulator.h" 26 #include "IContextFactory.h" 27 #include "SkiaCanvas.h" 28 #include "pipeline/skia/SkiaDisplayList.h" 29 #include "pipeline/skia/SkiaOpenGLPipeline.h" 30 #include "pipeline/skia/SkiaRecordingCanvas.h" 31 #include "renderthread/CanvasContext.h" 32 #include "tests/common/TestUtils.h" 33 34 using namespace android; 35 using namespace android::uirenderer; 36 using namespace android::uirenderer::renderthread; 37 using namespace android::uirenderer::skiapipeline; 38 39 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrame) { 40 auto redNode = TestUtils::createSkiaNode( 41 0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) { 42 redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver); 43 }); 44 LayerUpdateQueue layerUpdateQueue; 45 SkRect dirty = SkRect::MakeLargest(); 46 std::vector<sp<RenderNode>> renderNodes; 47 renderNodes.push_back(redNode); 48 bool opaque = true; 49 android::uirenderer::Rect contentDrawBounds(0, 0, 1, 1); 50 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread); 51 auto surface = SkSurface::MakeRasterN32Premul(1, 1); 52 surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver); 53 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE); 54 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds, 55 surface); 56 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED); 57 } 58 59 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, testOnPrepareTree) { 60 auto redNode = TestUtils::createSkiaNode( 61 0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) { 62 redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver); 63 }); 64 65 LayerUpdateQueue layerUpdateQueue; 66 SkRect dirty = SkRect::MakeLargest(); 67 std::vector<sp<RenderNode>> renderNodes; 68 renderNodes.push_back(redNode); 69 bool opaque = true; 70 android::uirenderer::Rect contentDrawBounds(0, 0, 1, 1); 71 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread); 72 { 73 // add a pointer to a deleted vector drawable object in the pipeline 74 sp<VectorDrawableRoot> dirtyVD(new VectorDrawableRoot(new VectorDrawable::Group())); 75 dirtyVD->mutateProperties()->setScaledSize(5, 5); 76 pipeline->getVectorDrawables()->push_back(dirtyVD.get()); 77 } 78 79 // pipeline should clean list of dirty vector drawables before prepare tree 80 pipeline->onPrepareTree(); 81 82 auto surface = SkSurface::MakeRasterN32Premul(1, 1); 83 surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver); 84 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE); 85 86 // drawFrame will crash if "SkiaPipeline::onPrepareTree" did not clean invalid VD pointer 87 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds, 88 surface); 89 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED); 90 } 91 92 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrameCheckOpaque) { 93 auto halfGreenNode = TestUtils::createSkiaNode( 94 0, 0, 2, 2, [](RenderProperties& props, SkiaRecordingCanvas& bottomHalfGreenCanvas) { 95 SkPaint greenPaint; 96 greenPaint.setColor(SK_ColorGREEN); 97 greenPaint.setStyle(SkPaint::kFill_Style); 98 bottomHalfGreenCanvas.drawRect(0, 1, 2, 2, greenPaint); 99 }); 100 LayerUpdateQueue layerUpdateQueue; 101 SkRect dirty = SkRect::MakeLargest(); 102 std::vector<sp<RenderNode>> renderNodes; 103 renderNodes.push_back(halfGreenNode); 104 android::uirenderer::Rect contentDrawBounds(0, 0, 2, 2); 105 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread); 106 auto surface = SkSurface::MakeRasterN32Premul(2, 2); 107 surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver); 108 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE); 109 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, false, contentDrawBounds, 110 surface); 111 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE); 112 ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorGREEN); 113 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, false, false, contentDrawBounds, 114 surface); 115 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned int)SK_ColorTRANSPARENT); 116 ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorGREEN); 117 } 118 119 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrameCheckDirtyRect) { 120 auto redNode = TestUtils::createSkiaNode( 121 0, 0, 2, 2, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) { 122 redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver); 123 }); 124 LayerUpdateQueue layerUpdateQueue; 125 SkRect dirty = SkRect::MakeXYWH(0, 1, 2, 1); 126 std::vector<sp<RenderNode>> renderNodes; 127 renderNodes.push_back(redNode); 128 android::uirenderer::Rect contentDrawBounds(0, 0, 2, 2); 129 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread); 130 auto surface = SkSurface::MakeRasterN32Premul(2, 2); 131 surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver); 132 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE); 133 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, false, contentDrawBounds, 134 surface); 135 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE); 136 ASSERT_EQ(TestUtils::getColor(surface, 1, 0), SK_ColorBLUE); 137 ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorRED); 138 ASSERT_EQ(TestUtils::getColor(surface, 1, 1), SK_ColorRED); 139 } 140 141 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderLayer) { 142 auto redNode = TestUtils::createSkiaNode( 143 0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) { 144 redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver); 145 }); 146 auto surfaceLayer1 = SkSurface::MakeRasterN32Premul(1, 1); 147 surfaceLayer1->getCanvas()->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver); 148 ASSERT_EQ(TestUtils::getColor(surfaceLayer1, 0, 0), SK_ColorWHITE); 149 redNode->setLayerSurface(surfaceLayer1); 150 151 // create a 2nd 2x2 layer and add it to the queue as well. 152 // make the layer's dirty area one half of the layer and verify only the dirty half is updated. 153 auto blueNode = TestUtils::createSkiaNode( 154 0, 0, 2, 2, [](RenderProperties& props, SkiaRecordingCanvas& blueCanvas) { 155 blueCanvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver); 156 }); 157 auto surfaceLayer2 = SkSurface::MakeRasterN32Premul(2, 2); 158 surfaceLayer2->getCanvas()->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver); 159 ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 0), SK_ColorWHITE); 160 blueNode->setLayerSurface(surfaceLayer2); 161 162 // attach both layers to the update queue 163 LayerUpdateQueue layerUpdateQueue; 164 SkRect dirty = SkRect::MakeLargest(); 165 layerUpdateQueue.enqueueLayerWithDamage(redNode.get(), dirty); 166 layerUpdateQueue.enqueueLayerWithDamage(blueNode.get(), SkRect::MakeWH(2, 1)); 167 ASSERT_EQ(layerUpdateQueue.entries().size(), 2UL); 168 169 bool opaque = true; 170 FrameBuilder::LightGeometry lightGeometry; 171 lightGeometry.radius = 1.0f; 172 lightGeometry.center = {0.0f, 0.0f, 0.0f}; 173 BakedOpRenderer::LightInfo lightInfo; 174 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread); 175 pipeline->renderLayers(lightGeometry, &layerUpdateQueue, opaque, false, lightInfo); 176 ASSERT_EQ(TestUtils::getColor(surfaceLayer1, 0, 0), SK_ColorRED); 177 ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 0), SK_ColorBLUE); 178 ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 1), SK_ColorWHITE); 179 ASSERT_TRUE(layerUpdateQueue.entries().empty()); 180 redNode->setLayerSurface(sk_sp<SkSurface>()); 181 blueNode->setLayerSurface(sk_sp<SkSurface>()); 182 } 183 184 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderOverdraw) { 185 ScopedProperty<bool> prop(Properties::debugOverdraw, true); 186 187 auto whiteNode = TestUtils::createSkiaNode( 188 0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 189 canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver); 190 }); 191 LayerUpdateQueue layerUpdateQueue; 192 SkRect dirty = SkRect::MakeXYWH(0, 0, 1, 1); 193 std::vector<sp<RenderNode>> renderNodes; 194 renderNodes.push_back(whiteNode); 195 bool opaque = true; 196 // empty contentDrawBounds is avoiding backdrop/content logic, which would lead to less overdraw 197 android::uirenderer::Rect contentDrawBounds(0, 0, 0, 0); 198 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread); 199 auto surface = SkSurface::MakeRasterN32Premul(1, 1); 200 201 // Initialize the canvas to blue. 202 surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver); 203 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE); 204 205 // Single draw, should be white. 206 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds, 207 surface); 208 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE); 209 210 // 1 Overdraw, should be blue blended onto white. 211 renderNodes.push_back(whiteNode); 212 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds, 213 surface); 214 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffd0d0ff); 215 216 // 2 Overdraw, should be green blended onto white 217 renderNodes.push_back(whiteNode); 218 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds, 219 surface); 220 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffd0ffd0); 221 222 // 3 Overdraw, should be pink blended onto white. 223 renderNodes.push_back(whiteNode); 224 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds, 225 surface); 226 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffffc0c0); 227 228 // 4 Overdraw, should be red blended onto white. 229 renderNodes.push_back(whiteNode); 230 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds, 231 surface); 232 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffff8080); 233 234 // 5 Overdraw, should be red blended onto white. 235 renderNodes.push_back(whiteNode); 236 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds, 237 surface); 238 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffff8080); 239 } 240 241 namespace { 242 template <typename T> 243 class DeferLayer : public SkSurface_Base { 244 public: 245 DeferLayer() : SkSurface_Base(T().imageInfo(), nullptr) {} 246 virtual ~DeferLayer() {} 247 248 SkCanvas* onNewCanvas() override { return new T(); } 249 sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override { return nullptr; } 250 sk_sp<SkImage> onNewImageSnapshot() override { return nullptr; } 251 T* canvas() { return static_cast<T*>(getCanvas()); } 252 void onCopyOnWrite(ContentChangeMode) override {} 253 void onWritePixels(const SkPixmap&, int x, int y) override {} 254 }; 255 } 256 257 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, deferRenderNodeScene) { 258 class DeferTestCanvas : public SkCanvas { 259 public: 260 DeferTestCanvas() : SkCanvas(800, 600) {} 261 void onDrawRect(const SkRect& rect, const SkPaint& paint) override { 262 SkMatrix expected; 263 switch (mDrawCounter++) { 264 case 0: 265 // background - left side 266 EXPECT_EQ(SkRect::MakeLTRB(600, 100, 700, 500), TestUtils::getClipBounds(this)); 267 expected.setTranslate(100, 100); 268 break; 269 case 1: 270 // background - top side 271 EXPECT_EQ(SkRect::MakeLTRB(100, 400, 600, 500), TestUtils::getClipBounds(this)); 272 expected.setTranslate(100, 100); 273 break; 274 case 2: 275 // content 276 EXPECT_EQ(SkRect::MakeLTRB(100, 100, 700, 500), TestUtils::getClipBounds(this)); 277 expected.setTranslate(-50, -50); 278 break; 279 case 3: 280 // overlay 281 EXPECT_EQ(SkRect::MakeLTRB(0, 0, 800, 600), TestUtils::getClipBounds(this)); 282 expected.reset(); 283 break; 284 default: 285 ADD_FAILURE() << "Too many rects observed"; 286 } 287 EXPECT_EQ(expected, getTotalMatrix()); 288 } 289 int mDrawCounter = 0; 290 }; 291 292 std::vector<sp<RenderNode>> nodes; 293 SkPaint transparentPaint; 294 transparentPaint.setAlpha(128); 295 296 // backdrop 297 nodes.push_back(TestUtils::createSkiaNode( 298 100, 100, 700, 500, // 600x400 299 [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) { 300 canvas.drawRect(0, 0, 600, 400, transparentPaint); 301 })); 302 303 // content 304 android::uirenderer::Rect contentDrawBounds(150, 150, 650, 450); // 500x300 305 nodes.push_back(TestUtils::createSkiaNode( 306 0, 0, 800, 600, 307 [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) { 308 canvas.drawRect(0, 0, 800, 600, transparentPaint); 309 })); 310 311 // overlay 312 nodes.push_back(TestUtils::createSkiaNode( 313 0, 0, 800, 600, 314 [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) { 315 canvas.drawRect(0, 0, 800, 200, transparentPaint); 316 })); 317 318 LayerUpdateQueue layerUpdateQueue; 319 SkRect dirty = SkRect::MakeWH(800, 600); 320 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread); 321 sk_sp<DeferLayer<DeferTestCanvas>> surface(new DeferLayer<DeferTestCanvas>()); 322 pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, false, contentDrawBounds, surface); 323 EXPECT_EQ(4, surface->canvas()->mDrawCounter); 324 } 325 326 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clipped) { 327 static const int CANVAS_WIDTH = 200; 328 static const int CANVAS_HEIGHT = 200; 329 class ClippedTestCanvas : public SkCanvas { 330 public: 331 ClippedTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {} 332 void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*) override { 333 EXPECT_EQ(0, mDrawCounter++); 334 EXPECT_EQ(SkRect::MakeLTRB(10, 20, 30, 40), TestUtils::getClipBounds(this)); 335 EXPECT_TRUE(getTotalMatrix().isIdentity()); 336 } 337 int mDrawCounter = 0; 338 }; 339 340 std::vector<sp<RenderNode>> nodes; 341 nodes.push_back(TestUtils::createSkiaNode( 342 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, 343 [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 344 sk_sp<Bitmap> bitmap(TestUtils::createBitmap(CANVAS_WIDTH, CANVAS_HEIGHT)); 345 canvas.drawBitmap(*bitmap, 0, 0, nullptr); 346 })); 347 348 LayerUpdateQueue layerUpdateQueue; 349 SkRect dirty = SkRect::MakeLTRB(10, 20, 30, 40); 350 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread); 351 sk_sp<DeferLayer<ClippedTestCanvas>> surface(new DeferLayer<ClippedTestCanvas>()); 352 pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, false, 353 SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface); 354 EXPECT_EQ(1, surface->canvas()->mDrawCounter); 355 } 356 357 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clip_replace) { 358 static const int CANVAS_WIDTH = 50; 359 static const int CANVAS_HEIGHT = 50; 360 class ClipReplaceTestCanvas : public SkCanvas { 361 public: 362 ClipReplaceTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {} 363 void onDrawPaint(const SkPaint&) { 364 EXPECT_EQ(0, mDrawCounter++); 365 EXPECT_EQ(SkRect::MakeLTRB(20, 10, 30, 40), TestUtils::getClipBounds(this)) 366 << "Expect resolved clip to be intersection of viewport clip and clip op"; 367 } 368 int mDrawCounter = 0; 369 }; 370 371 std::vector<sp<RenderNode>> nodes; 372 nodes.push_back(TestUtils::createSkiaNode( 373 20, 20, 30, 30, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 374 canvas.clipRect(0, -20, 10, 30, SkClipOp::kReplace_deprecated); 375 canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver); 376 })); 377 378 LayerUpdateQueue layerUpdateQueue; 379 SkRect dirty = SkRect::MakeLTRB(10, 10, 40, 40); 380 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread); 381 sk_sp<DeferLayer<ClipReplaceTestCanvas>> surface(new DeferLayer<ClipReplaceTestCanvas>()); 382 pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, false, 383 SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface); 384 EXPECT_EQ(1, surface->canvas()->mDrawCounter); 385 } 386