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