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