blob: 785e2869d15e1215aea2045e38eda8c19a108f85 [file] [log] [blame]
Stan Iliev500a0c32016-10-26 10:30:09 -04001/*
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
Stan Iliev500a0c32016-10-26 10:30:09 -040017#include <VectorDrawable.h>
John Reck1bcacfd2017-11-03 10:12:19 -070018#include <gtest/gtest.h>
Stan Iliev500a0c32016-10-26 10:30:09 -040019
Kevin Lubick4e8ce462022-12-01 20:29:16 +000020#include <SkBlendMode.h>
Stan Iliev52771272016-11-17 09:54:38 -050021#include <SkClipStack.h>
Stan Iliev52771272016-11-17 09:54:38 -050022#include <SkSurface_Base.h>
Stan Iliev500a0c32016-10-26 10:30:09 -040023#include <string.h>
John Reck1bcacfd2017-11-03 10:12:19 -070024#include "AnimationContext.h"
25#include "DamageAccumulator.h"
26#include "IContextFactory.h"
Mike Reedc2dbc032019-07-25 12:28:29 -040027#include "hwui/Paint.h"
John Reck1bcacfd2017-11-03 10:12:19 -070028#include "SkiaCanvas.h"
29#include "pipeline/skia/SkiaDisplayList.h"
30#include "pipeline/skia/SkiaOpenGLPipeline.h"
31#include "pipeline/skia/SkiaRecordingCanvas.h"
John Reck283bb462018-12-13 16:40:14 -080032#include "pipeline/skia/SkiaUtils.h"
John Reck1bcacfd2017-11-03 10:12:19 -070033#include "renderthread/CanvasContext.h"
John Reck23462d82019-05-29 16:55:06 -070034#include "tests/common/TestContext.h"
John Reck1bcacfd2017-11-03 10:12:19 -070035#include "tests/common/TestUtils.h"
Stan Iliev500a0c32016-10-26 10:30:09 -040036
John Reck0fa0cbc2019-04-05 16:57:46 -070037#include <gui/BufferItemConsumer.h>
38#include <gui/Surface.h>
39
Stan Iliev500a0c32016-10-26 10:30:09 -040040using namespace android;
41using namespace android::uirenderer;
42using namespace android::uirenderer::renderthread;
43using namespace android::uirenderer::skiapipeline;
44
John Reck1efef7b2023-07-17 23:29:30 -040045RENDERTHREAD_TEST(SkiaPipeline, renderFrame) {
John Reck1bcacfd2017-11-03 10:12:19 -070046 auto redNode = TestUtils::createSkiaNode(
47 0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
48 redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
49 });
Stan Iliev500a0c32016-10-26 10:30:09 -040050 LayerUpdateQueue layerUpdateQueue;
Mike Reedf3338bd2018-10-09 11:54:39 -040051 SkRect dirty = SkRectMakeLargest();
Stan Iliev500a0c32016-10-26 10:30:09 -040052 std::vector<sp<RenderNode>> renderNodes;
53 renderNodes.push_back(redNode);
54 bool opaque = true;
55 android::uirenderer::Rect contentDrawBounds(0, 0, 1, 1);
56 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
Kevin Lubick6817fc42023-05-12 19:27:20 +000057 auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(1, 1));
Stan Iliev500a0c32016-10-26 10:30:09 -040058 surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
59 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
Greg Danielc4076782019-01-08 16:01:18 -050060 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
61 SkMatrix::I());
Stan Iliev500a0c32016-10-26 10:30:09 -040062 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED);
63}
64
John Reck1efef7b2023-07-17 23:29:30 -040065RENDERTHREAD_TEST(SkiaPipeline, renderFrameCheckOpaque) {
John Reck1bcacfd2017-11-03 10:12:19 -070066 auto halfGreenNode = TestUtils::createSkiaNode(
67 0, 0, 2, 2, [](RenderProperties& props, SkiaRecordingCanvas& bottomHalfGreenCanvas) {
Mike Reedc2dbc032019-07-25 12:28:29 -040068 Paint greenPaint;
John Reck1bcacfd2017-11-03 10:12:19 -070069 greenPaint.setColor(SK_ColorGREEN);
70 greenPaint.setStyle(SkPaint::kFill_Style);
71 bottomHalfGreenCanvas.drawRect(0, 1, 2, 2, greenPaint);
72 });
Stan Iliev500a0c32016-10-26 10:30:09 -040073 LayerUpdateQueue layerUpdateQueue;
Mike Reedf3338bd2018-10-09 11:54:39 -040074 SkRect dirty = SkRectMakeLargest();
Stan Iliev500a0c32016-10-26 10:30:09 -040075 std::vector<sp<RenderNode>> renderNodes;
76 renderNodes.push_back(halfGreenNode);
77 android::uirenderer::Rect contentDrawBounds(0, 0, 2, 2);
78 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
Kevin Lubick6817fc42023-05-12 19:27:20 +000079 auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(2, 2));
Stan Iliev500a0c32016-10-26 10:30:09 -040080 surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
81 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
Greg Danielc4076782019-01-08 16:01:18 -050082 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface,
83 SkMatrix::I());
Stan Iliev500a0c32016-10-26 10:30:09 -040084 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
85 ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorGREEN);
Greg Danielc4076782019-01-08 16:01:18 -050086 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, false, contentDrawBounds, surface,
87 SkMatrix::I());
Stan Iliev500a0c32016-10-26 10:30:09 -040088 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned int)SK_ColorTRANSPARENT);
89 ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorGREEN);
90}
91
John Reck1efef7b2023-07-17 23:29:30 -040092RENDERTHREAD_TEST(SkiaPipeline, renderFrameCheckDirtyRect) {
John Reck1bcacfd2017-11-03 10:12:19 -070093 auto redNode = TestUtils::createSkiaNode(
94 0, 0, 2, 2, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
95 redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
96 });
Stan Iliev500a0c32016-10-26 10:30:09 -040097 LayerUpdateQueue layerUpdateQueue;
98 SkRect dirty = SkRect::MakeXYWH(0, 1, 2, 1);
99 std::vector<sp<RenderNode>> renderNodes;
100 renderNodes.push_back(redNode);
101 android::uirenderer::Rect contentDrawBounds(0, 0, 2, 2);
102 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
Kevin Lubick6817fc42023-05-12 19:27:20 +0000103 auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(2, 2));
Stan Iliev500a0c32016-10-26 10:30:09 -0400104 surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
105 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
Greg Danielc4076782019-01-08 16:01:18 -0500106 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface,
107 SkMatrix::I());
Stan Iliev500a0c32016-10-26 10:30:09 -0400108 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
109 ASSERT_EQ(TestUtils::getColor(surface, 1, 0), SK_ColorBLUE);
110 ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorRED);
111 ASSERT_EQ(TestUtils::getColor(surface, 1, 1), SK_ColorRED);
112}
113
John Reck1efef7b2023-07-17 23:29:30 -0400114RENDERTHREAD_TEST(SkiaPipeline, renderLayer) {
John Reck1bcacfd2017-11-03 10:12:19 -0700115 auto redNode = TestUtils::createSkiaNode(
116 0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
117 redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
118 });
Kevin Lubick6817fc42023-05-12 19:27:20 +0000119 auto surfaceLayer1 = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(1, 1));
Stan Iliev500a0c32016-10-26 10:30:09 -0400120 surfaceLayer1->getCanvas()->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
121 ASSERT_EQ(TestUtils::getColor(surfaceLayer1, 0, 0), SK_ColorWHITE);
122 redNode->setLayerSurface(surfaceLayer1);
123
John Reck1bcacfd2017-11-03 10:12:19 -0700124 // create a 2nd 2x2 layer and add it to the queue as well.
125 // make the layer's dirty area one half of the layer and verify only the dirty half is updated.
126 auto blueNode = TestUtils::createSkiaNode(
127 0, 0, 2, 2, [](RenderProperties& props, SkiaRecordingCanvas& blueCanvas) {
128 blueCanvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
129 });
Kevin Lubick6817fc42023-05-12 19:27:20 +0000130 auto surfaceLayer2 = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(2, 2));
Stan Iliev500a0c32016-10-26 10:30:09 -0400131 surfaceLayer2->getCanvas()->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
132 ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 0), SK_ColorWHITE);
133 blueNode->setLayerSurface(surfaceLayer2);
134
John Reck1bcacfd2017-11-03 10:12:19 -0700135 // attach both layers to the update queue
Stan Iliev500a0c32016-10-26 10:30:09 -0400136 LayerUpdateQueue layerUpdateQueue;
Mike Reedf3338bd2018-10-09 11:54:39 -0400137 SkRect dirty = SkRectMakeLargest();
Stan Iliev500a0c32016-10-26 10:30:09 -0400138 layerUpdateQueue.enqueueLayerWithDamage(redNode.get(), dirty);
139 layerUpdateQueue.enqueueLayerWithDamage(blueNode.get(), SkRect::MakeWH(2, 1));
140 ASSERT_EQ(layerUpdateQueue.entries().size(), 2UL);
141
142 bool opaque = true;
John Reckd9d7f122018-05-03 14:40:56 -0700143 LightGeometry lightGeometry;
Stan Iliev500a0c32016-10-26 10:30:09 -0400144 lightGeometry.radius = 1.0f;
John Reck1bcacfd2017-11-03 10:12:19 -0700145 lightGeometry.center = {0.0f, 0.0f, 0.0f};
John Reckd9d7f122018-05-03 14:40:56 -0700146 LightInfo lightInfo;
Stan Iliev500a0c32016-10-26 10:30:09 -0400147 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
Peiyong Lin1f6aa122018-09-10 16:28:08 -0700148 pipeline->renderLayers(lightGeometry, &layerUpdateQueue, opaque, lightInfo);
Stan Iliev500a0c32016-10-26 10:30:09 -0400149 ASSERT_EQ(TestUtils::getColor(surfaceLayer1, 0, 0), SK_ColorRED);
150 ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 0), SK_ColorBLUE);
151 ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 1), SK_ColorWHITE);
152 ASSERT_TRUE(layerUpdateQueue.entries().empty());
153 redNode->setLayerSurface(sk_sp<SkSurface>());
154 blueNode->setLayerSurface(sk_sp<SkSurface>());
155}
Matt Sarettf58cc922016-11-14 18:33:38 -0500156
John Reck1efef7b2023-07-17 23:29:30 -0400157RENDERTHREAD_TEST(SkiaPipeline, renderOverdraw) {
Matt Sarettf58cc922016-11-14 18:33:38 -0500158 ScopedProperty<bool> prop(Properties::debugOverdraw, true);
159
John Reck1bcacfd2017-11-03 10:12:19 -0700160 auto whiteNode = TestUtils::createSkiaNode(
161 0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
162 canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
163 });
Matt Sarettf58cc922016-11-14 18:33:38 -0500164 LayerUpdateQueue layerUpdateQueue;
165 SkRect dirty = SkRect::MakeXYWH(0, 0, 1, 1);
166 std::vector<sp<RenderNode>> renderNodes;
167 renderNodes.push_back(whiteNode);
168 bool opaque = true;
John Reck1bcacfd2017-11-03 10:12:19 -0700169 // empty contentDrawBounds is avoiding backdrop/content logic, which would lead to less overdraw
Stan Iliev52771272016-11-17 09:54:38 -0500170 android::uirenderer::Rect contentDrawBounds(0, 0, 0, 0);
Matt Sarettf58cc922016-11-14 18:33:38 -0500171 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
Kevin Lubick6817fc42023-05-12 19:27:20 +0000172 auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(1, 1));
Matt Sarettf58cc922016-11-14 18:33:38 -0500173
174 // Initialize the canvas to blue.
175 surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
176 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
177
178 // Single draw, should be white.
Greg Danielc4076782019-01-08 16:01:18 -0500179 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
180 SkMatrix::I());
Matt Sarettf58cc922016-11-14 18:33:38 -0500181 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE);
182
183 // 1 Overdraw, should be blue blended onto white.
Matt Sarett341480b2017-01-23 19:45:42 -0500184 renderNodes.push_back(whiteNode);
Greg Danielc4076782019-01-08 16:01:18 -0500185 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
186 SkMatrix::I());
John Reck1bcacfd2017-11-03 10:12:19 -0700187 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffd0d0ff);
Matt Sarettf58cc922016-11-14 18:33:38 -0500188
189 // 2 Overdraw, should be green blended onto white
190 renderNodes.push_back(whiteNode);
Greg Danielc4076782019-01-08 16:01:18 -0500191 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
192 SkMatrix::I());
John Reck1bcacfd2017-11-03 10:12:19 -0700193 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffd0ffd0);
Matt Sarettf58cc922016-11-14 18:33:38 -0500194
195 // 3 Overdraw, should be pink blended onto white.
196 renderNodes.push_back(whiteNode);
Greg Danielc4076782019-01-08 16:01:18 -0500197 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
198 SkMatrix::I());
John Reck1bcacfd2017-11-03 10:12:19 -0700199 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffffc0c0);
Matt Sarettf58cc922016-11-14 18:33:38 -0500200
201 // 4 Overdraw, should be red blended onto white.
202 renderNodes.push_back(whiteNode);
Greg Danielc4076782019-01-08 16:01:18 -0500203 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
204 SkMatrix::I());
John Reck1bcacfd2017-11-03 10:12:19 -0700205 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffff8080);
Matt Sarettf58cc922016-11-14 18:33:38 -0500206
207 // 5 Overdraw, should be red blended onto white.
208 renderNodes.push_back(whiteNode);
Greg Danielc4076782019-01-08 16:01:18 -0500209 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
210 SkMatrix::I());
John Reck1bcacfd2017-11-03 10:12:19 -0700211 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffff8080);
Matt Sarettf58cc922016-11-14 18:33:38 -0500212}
Stan Iliev52771272016-11-17 09:54:38 -0500213
214namespace {
215template <typename T>
216class DeferLayer : public SkSurface_Base {
217public:
Derek Sollenberger624ad832017-01-11 11:09:48 -0500218 DeferLayer() : SkSurface_Base(T().imageInfo(), nullptr) {}
219 virtual ~DeferLayer() {}
220
John Reck1bcacfd2017-11-03 10:12:19 -0700221 SkCanvas* onNewCanvas() override { return new T(); }
222 sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override { return nullptr; }
Derek Sollenbergerdbb4bc82018-11-21 08:47:31 -0500223 sk_sp<SkImage> onNewImageSnapshot(const SkIRect* bounds) override { return nullptr; }
Stan Ilieved4d58c2016-12-14 14:05:04 -0500224 T* canvas() { return static_cast<T*>(getCanvas()); }
Ben Wagner9b875562021-10-28 21:42:35 +0000225 bool onCopyOnWrite(ContentChangeMode) override { return true; }
Leon Scroggins III71195ab2018-02-08 17:14:28 -0500226 void onWritePixels(const SkPixmap&, int x, int y) override {}
Stan Iliev52771272016-11-17 09:54:38 -0500227};
228}
229
John Reck1efef7b2023-07-17 23:29:30 -0400230RENDERTHREAD_TEST(SkiaPipeline, deferRenderNodeScene) {
Stan Iliev52771272016-11-17 09:54:38 -0500231 class DeferTestCanvas : public SkCanvas {
232 public:
233 DeferTestCanvas() : SkCanvas(800, 600) {}
234 void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
235 SkMatrix expected;
236 switch (mDrawCounter++) {
John Reck1bcacfd2017-11-03 10:12:19 -0700237 case 0:
238 // background - left side
239 EXPECT_EQ(SkRect::MakeLTRB(600, 100, 700, 500), TestUtils::getClipBounds(this));
240 expected.setTranslate(100, 100);
241 break;
242 case 1:
243 // background - top side
244 EXPECT_EQ(SkRect::MakeLTRB(100, 400, 600, 500), TestUtils::getClipBounds(this));
245 expected.setTranslate(100, 100);
246 break;
247 case 2:
248 // content
249 EXPECT_EQ(SkRect::MakeLTRB(100, 100, 700, 500), TestUtils::getClipBounds(this));
250 expected.setTranslate(-50, -50);
251 break;
252 case 3:
253 // overlay
254 EXPECT_EQ(SkRect::MakeLTRB(0, 0, 800, 600), TestUtils::getClipBounds(this));
255 expected.reset();
256 break;
257 default:
258 ADD_FAILURE() << "Too many rects observed";
Stan Iliev52771272016-11-17 09:54:38 -0500259 }
260 EXPECT_EQ(expected, getTotalMatrix());
261 }
262 int mDrawCounter = 0;
263 };
264
265 std::vector<sp<RenderNode>> nodes;
Mike Reedc2dbc032019-07-25 12:28:29 -0400266 Paint transparentPaint;
Stan Iliev52771272016-11-17 09:54:38 -0500267 transparentPaint.setAlpha(128);
268
269 // backdrop
John Reck1bcacfd2017-11-03 10:12:19 -0700270 nodes.push_back(TestUtils::createSkiaNode(
271 100, 100, 700, 500, // 600x400
Stan Iliev52771272016-11-17 09:54:38 -0500272 [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
John Reck1bcacfd2017-11-03 10:12:19 -0700273 canvas.drawRect(0, 0, 600, 400, transparentPaint);
274 }));
Stan Iliev52771272016-11-17 09:54:38 -0500275
276 // content
John Reck1bcacfd2017-11-03 10:12:19 -0700277 android::uirenderer::Rect contentDrawBounds(150, 150, 650, 450); // 500x300
278 nodes.push_back(TestUtils::createSkiaNode(
279 0, 0, 800, 600,
Stan Iliev52771272016-11-17 09:54:38 -0500280 [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
John Reck1bcacfd2017-11-03 10:12:19 -0700281 canvas.drawRect(0, 0, 800, 600, transparentPaint);
282 }));
Stan Iliev52771272016-11-17 09:54:38 -0500283
284 // overlay
John Reck1bcacfd2017-11-03 10:12:19 -0700285 nodes.push_back(TestUtils::createSkiaNode(
286 0, 0, 800, 600,
Stan Iliev52771272016-11-17 09:54:38 -0500287 [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
John Reck1bcacfd2017-11-03 10:12:19 -0700288 canvas.drawRect(0, 0, 800, 200, transparentPaint);
289 }));
Stan Iliev52771272016-11-17 09:54:38 -0500290
291 LayerUpdateQueue layerUpdateQueue;
292 SkRect dirty = SkRect::MakeWH(800, 600);
293 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
Stan Ilieved4d58c2016-12-14 14:05:04 -0500294 sk_sp<DeferLayer<DeferTestCanvas>> surface(new DeferLayer<DeferTestCanvas>());
Greg Danielc4076782019-01-08 16:01:18 -0500295 pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, contentDrawBounds, surface,
296 SkMatrix::I());
Stan Ilieved4d58c2016-12-14 14:05:04 -0500297 EXPECT_EQ(4, surface->canvas()->mDrawCounter);
Stan Iliev52771272016-11-17 09:54:38 -0500298}
299
John Reck1efef7b2023-07-17 23:29:30 -0400300RENDERTHREAD_TEST(SkiaPipeline, clipped) {
Stan Iliev52771272016-11-17 09:54:38 -0500301 static const int CANVAS_WIDTH = 200;
302 static const int CANVAS_HEIGHT = 200;
303 class ClippedTestCanvas : public SkCanvas {
304 public:
John Reck1bcacfd2017-11-03 10:12:19 -0700305 ClippedTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {}
Michael Ludwig1544ba92024-01-02 15:26:37 +0000306 void onDrawImageRect2(const SkImage*, const SkRect&, const SkRect&,
307 const SkSamplingOptions&, const SkPaint*,
308 SrcRectConstraint) override {
Stan Iliev52771272016-11-17 09:54:38 -0500309 EXPECT_EQ(0, mDrawCounter++);
310 EXPECT_EQ(SkRect::MakeLTRB(10, 20, 30, 40), TestUtils::getClipBounds(this));
311 EXPECT_TRUE(getTotalMatrix().isIdentity());
312 }
313 int mDrawCounter = 0;
314 };
315
316 std::vector<sp<RenderNode>> nodes;
John Reck1bcacfd2017-11-03 10:12:19 -0700317 nodes.push_back(TestUtils::createSkiaNode(
318 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
Stan Iliev52771272016-11-17 09:54:38 -0500319 [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
John Reck1bcacfd2017-11-03 10:12:19 -0700320 sk_sp<Bitmap> bitmap(TestUtils::createBitmap(CANVAS_WIDTH, CANVAS_HEIGHT));
321 canvas.drawBitmap(*bitmap, 0, 0, nullptr);
322 }));
Stan Iliev52771272016-11-17 09:54:38 -0500323
324 LayerUpdateQueue layerUpdateQueue;
325 SkRect dirty = SkRect::MakeLTRB(10, 20, 30, 40);
326 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
Stan Ilieved4d58c2016-12-14 14:05:04 -0500327 sk_sp<DeferLayer<ClippedTestCanvas>> surface(new DeferLayer<ClippedTestCanvas>());
Peiyong Lin1f6aa122018-09-10 16:28:08 -0700328 pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true,
Greg Danielc4076782019-01-08 16:01:18 -0500329 SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface, SkMatrix::I());
330 EXPECT_EQ(1, surface->canvas()->mDrawCounter);
331}
332
333// Test renderFrame with a dirty clip and a pre-transform matrix.
John Reck1efef7b2023-07-17 23:29:30 -0400334RENDERTHREAD_TEST(SkiaPipeline, clipped_rotated) {
Greg Danielc4076782019-01-08 16:01:18 -0500335 static const int CANVAS_WIDTH = 200;
336 static const int CANVAS_HEIGHT = 100;
337 static const SkMatrix rotateMatrix = SkMatrix::MakeAll(0, -1, CANVAS_HEIGHT, 1, 0, 0, 0, 0, 1);
338 static const SkRect dirty = SkRect::MakeLTRB(10, 20, 20, 40);
339 class ClippedTestCanvas : public SkCanvas {
340 public:
341 ClippedTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {}
Michael Ludwig1544ba92024-01-02 15:26:37 +0000342 void onDrawImageRect2(const SkImage*, const SkRect&, const SkRect&,
343 const SkSamplingOptions&, const SkPaint*,
344 SrcRectConstraint) override {
Greg Danielc4076782019-01-08 16:01:18 -0500345 EXPECT_EQ(0, mDrawCounter++);
346 // Expect clip to be rotated.
347 EXPECT_EQ(SkRect::MakeLTRB(CANVAS_HEIGHT - dirty.fTop - dirty.height(), dirty.fLeft,
348 CANVAS_HEIGHT - dirty.fTop, dirty.fLeft + dirty.width()),
349 TestUtils::getClipBounds(this));
350 EXPECT_EQ(rotateMatrix, getTotalMatrix());
351 }
352 int mDrawCounter = 0;
353 };
354
355 std::vector<sp<RenderNode>> nodes;
356 nodes.push_back(TestUtils::createSkiaNode(
357 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
358 [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
359 sk_sp<Bitmap> bitmap(TestUtils::createBitmap(CANVAS_WIDTH, CANVAS_HEIGHT));
360 canvas.drawBitmap(*bitmap, 0, 0, nullptr);
361 }));
362
363 LayerUpdateQueue layerUpdateQueue;
364 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
365 sk_sp<DeferLayer<ClippedTestCanvas>> surface(new DeferLayer<ClippedTestCanvas>());
366 pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true,
367 SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface, rotateMatrix);
Stan Ilieved4d58c2016-12-14 14:05:04 -0500368 EXPECT_EQ(1, surface->canvas()->mDrawCounter);
Stan Iliev52771272016-11-17 09:54:38 -0500369}
370
John Reck1efef7b2023-07-17 23:29:30 -0400371RENDERTHREAD_TEST(SkiaPipeline, clip_replace) {
Stan Iliev52771272016-11-17 09:54:38 -0500372 static const int CANVAS_WIDTH = 50;
373 static const int CANVAS_HEIGHT = 50;
374 class ClipReplaceTestCanvas : public SkCanvas {
375 public:
John Reck1bcacfd2017-11-03 10:12:19 -0700376 ClipReplaceTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {}
Stan Iliev52771272016-11-17 09:54:38 -0500377 void onDrawPaint(const SkPaint&) {
378 EXPECT_EQ(0, mDrawCounter++);
Stan Ilievb66b8bb2016-12-15 18:17:42 -0500379 EXPECT_EQ(SkRect::MakeLTRB(20, 10, 30, 40), TestUtils::getClipBounds(this))
380 << "Expect resolved clip to be intersection of viewport clip and clip op";
Stan Iliev52771272016-11-17 09:54:38 -0500381 }
382 int mDrawCounter = 0;
383 };
384
385 std::vector<sp<RenderNode>> nodes;
John Reck1bcacfd2017-11-03 10:12:19 -0700386 nodes.push_back(TestUtils::createSkiaNode(
387 20, 20, 30, 30, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
Michael Ludwig70cf50c22021-07-21 17:02:39 +0000388 canvas.replaceClipRect_deprecated(0, -20, 10, 30);
John Reck1bcacfd2017-11-03 10:12:19 -0700389 canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
390 }));
Stan Iliev52771272016-11-17 09:54:38 -0500391
392 LayerUpdateQueue layerUpdateQueue;
393 SkRect dirty = SkRect::MakeLTRB(10, 10, 40, 40);
394 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
Stan Ilieved4d58c2016-12-14 14:05:04 -0500395 sk_sp<DeferLayer<ClipReplaceTestCanvas>> surface(new DeferLayer<ClipReplaceTestCanvas>());
Peiyong Lin1f6aa122018-09-10 16:28:08 -0700396 pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true,
Greg Danielc4076782019-01-08 16:01:18 -0500397 SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface, SkMatrix::I());
Stan Ilieved4d58c2016-12-14 14:05:04 -0500398 EXPECT_EQ(1, surface->canvas()->mDrawCounter);
Stan Iliev52771272016-11-17 09:54:38 -0500399}
Derek Sollenberger5a5a6482018-09-19 13:52:13 -0400400
John Reck1efef7b2023-07-17 23:29:30 -0400401RENDERTHREAD_TEST(SkiaPipeline, context_lost) {
John Reck23462d82019-05-29 16:55:06 -0700402 test::TestContext context;
403 auto surface = context.surface();
Derek Sollenberger5a5a6482018-09-19 13:52:13 -0400404 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
405 EXPECT_FALSE(pipeline->isSurfaceReady());
John Reck8ddbc592020-05-07 16:11:18 -0700406 EXPECT_TRUE(pipeline->setSurface(surface.get(), SwapBehavior::kSwap_default));
Derek Sollenberger5a5a6482018-09-19 13:52:13 -0400407 EXPECT_TRUE(pipeline->isSurfaceReady());
John Reck283bb462018-12-13 16:40:14 -0800408 renderThread.destroyRenderingContext();
Derek Sollenberger5a5a6482018-09-19 13:52:13 -0400409 EXPECT_FALSE(pipeline->isSurfaceReady());
Derek Sollenbergerb8307722022-08-30 14:24:22 -0400410
411 pipeline->makeCurrent();
412 EXPECT_TRUE(pipeline->isSurfaceReady());
Derek Sollenberger5a5a6482018-09-19 13:52:13 -0400413}
Derek Sollenberger5f9753d2020-04-01 15:59:02 -0400414
John Reck1efef7b2023-07-17 23:29:30 -0400415RENDERTHREAD_TEST(SkiaPipeline, pictureCallback) {
Derek Sollenberger5f9753d2020-04-01 15:59:02 -0400416 // create a pipeline and add a picture callback
417 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
418 int callbackCount = 0;
419 pipeline->setPictureCapturedCallback(
420 [&callbackCount](sk_sp<SkPicture>&& picture) { callbackCount += 1; });
421
422 // create basic red frame and render it
423 auto redNode = TestUtils::createSkiaNode(
424 0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
425 redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
426 });
427 LayerUpdateQueue layerUpdateQueue;
428 SkRect dirty = SkRectMakeLargest();
429 std::vector<sp<RenderNode>> renderNodes;
430 renderNodes.push_back(redNode);
431 bool opaque = true;
432 android::uirenderer::Rect contentDrawBounds(0, 0, 1, 1);
Kevin Lubick6817fc42023-05-12 19:27:20 +0000433 auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(1, 1));
Derek Sollenberger5f9753d2020-04-01 15:59:02 -0400434 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
435 SkMatrix::I());
436
437 // verify the callback was called
438 EXPECT_EQ(1, callbackCount);
439
440 // render a second frame and check the callback count
441 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
442 SkMatrix::I());
443 EXPECT_EQ(2, callbackCount);
444
445 // unset the callback, render another frame, check callback was not invoked
446 pipeline->setPictureCapturedCallback(nullptr);
447 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
448 SkMatrix::I());
449 EXPECT_EQ(2, callbackCount);
450}