Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2011 Google Inc. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
| 7 | |
Hal Canary | c640d0d | 2018-06-13 09:59:02 -0400 | [diff] [blame] | 8 | #include "SkTypes.h" |
Florin Malita | f4f3f0f | 2018-01-03 23:53:37 -0500 | [diff] [blame] | 9 | |
| 10 | #if !defined(SK_BUILD_FOR_GOOGLE3) |
| 11 | |
Hal Canary | c640d0d | 2018-06-13 09:59:02 -0400 | [diff] [blame] | 12 | #include "SkRect.h" |
| 13 | #include "SkRectPriv.h" |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 14 | #include "SkSGColor.h" |
| 15 | #include "SkSGDraw.h" |
| 16 | #include "SkSGGroup.h" |
| 17 | #include "SkSGInvalidationController.h" |
| 18 | #include "SkSGRect.h" |
Florin Malita | ef26fcb | 2019-02-10 12:54:20 -0500 | [diff] [blame] | 19 | #include "SkSGRenderEffect.h" |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 20 | #include "SkSGTransform.h" |
Hal Canary | c640d0d | 2018-06-13 09:59:02 -0400 | [diff] [blame] | 21 | #include "SkTo.h" |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 22 | |
| 23 | #include "Test.h" |
| 24 | |
| 25 | #include <vector> |
| 26 | |
| 27 | static void check_inval(skiatest::Reporter* reporter, const sk_sp<sksg::Node>& root, |
| 28 | const SkRect& expected_bounds, |
| 29 | const SkRect& expected_inval_bounds, |
| 30 | const std::vector<SkRect>* expected_damage) { |
| 31 | sksg::InvalidationController ic; |
| 32 | const auto bbox = root->revalidate(&ic, SkMatrix::I()); |
| 33 | |
| 34 | if (0) { |
Florin Malita | 67cd9b2 | 2018-01-03 20:13:34 -0500 | [diff] [blame] | 35 | SkDebugf("** bbox: [%f %f %f %f], ibbox: [%f %f %f %f]\n", |
| 36 | bbox.fLeft, bbox.fTop, bbox.fRight, bbox.fBottom, |
| 37 | ic.bounds().left(), ic.bounds().top(), ic.bounds().right(), ic.bounds().bottom()); |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 38 | } |
| 39 | |
| 40 | REPORTER_ASSERT(reporter, bbox == expected_bounds); |
| 41 | REPORTER_ASSERT(reporter, ic.bounds() == expected_inval_bounds); |
| 42 | |
| 43 | if (expected_damage) { |
Florin Malita | c14f144 | 2018-01-05 11:32:31 -0500 | [diff] [blame] | 44 | const auto damage_count = SkTo<size_t>(ic.end() - ic.begin()); |
| 45 | REPORTER_ASSERT(reporter, expected_damage->size() == damage_count); |
| 46 | for (size_t i = 0; i < std::min(expected_damage->size(), damage_count); ++i) { |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 47 | const auto r1 = (*expected_damage)[i], |
| 48 | r2 = ic.begin()[i]; |
| 49 | if (0) { |
Florin Malita | 67cd9b2 | 2018-01-03 20:13:34 -0500 | [diff] [blame] | 50 | SkDebugf("*** expected inval: [%f %f %f %f], actual: [%f %f %f %f]\n", |
| 51 | r1.left(), r1.top(), r1.right(), r1.bottom(), |
| 52 | r2.left(), r2.top(), r2.right(), r2.bottom()); |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 53 | } |
| 54 | REPORTER_ASSERT(reporter, r1 == r2); |
| 55 | } |
| 56 | } |
| 57 | } |
| 58 | |
Florin Malita | eb46bd8 | 2019-02-12 09:33:21 -0500 | [diff] [blame] | 59 | struct HitTest { |
| 60 | const SkPoint pt; |
| 61 | sk_sp<sksg::RenderNode> node; |
| 62 | }; |
| 63 | |
| 64 | static void check_hittest(skiatest::Reporter* reporter, const sk_sp<sksg::RenderNode>& root, |
| 65 | const std::vector<HitTest>& tests) { |
| 66 | for (const auto& tst : tests) { |
| 67 | const auto* node = root->nodeAt(tst.pt); |
| 68 | if (node != tst.node.get()) { |
| 69 | SkDebugf("*** nodeAt(%f, %f) - expected %p, got %p\n", |
| 70 | tst.pt.x(), tst.pt.y(), tst.node.get(), node); |
| 71 | } |
| 72 | REPORTER_ASSERT(reporter, tst.node.get() == node); |
| 73 | } |
| 74 | } |
| 75 | |
Florin Malita | c14f144 | 2018-01-05 11:32:31 -0500 | [diff] [blame] | 76 | static void inval_test1(skiatest::Reporter* reporter) { |
Florin Malita | 18eafd9 | 2018-01-04 21:11:55 -0500 | [diff] [blame] | 77 | auto color = sksg::Color::Make(0xff000000); |
| 78 | auto r1 = sksg::Rect::Make(SkRect::MakeWH(100, 100)), |
| 79 | r2 = sksg::Rect::Make(SkRect::MakeWH(100, 100)); |
| 80 | auto grp = sksg::Group::Make(); |
Florin Malita | 760a052 | 2019-01-10 15:24:15 -0500 | [diff] [blame] | 81 | auto matrix = sksg::Matrix<SkMatrix>::Make(SkMatrix::I()); |
Florin Malita | 919e209 | 2019-01-09 15:37:57 -0500 | [diff] [blame] | 82 | auto root = sksg::TransformEffect::Make(grp, matrix); |
Florin Malita | eb46bd8 | 2019-02-12 09:33:21 -0500 | [diff] [blame] | 83 | auto d1 = sksg::Draw::Make(r1, color), |
| 84 | d2 = sksg::Draw::Make(r2, color); |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 85 | |
Florin Malita | eb46bd8 | 2019-02-12 09:33:21 -0500 | [diff] [blame] | 86 | grp->addChild(d1); |
| 87 | grp->addChild(d2); |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 88 | |
| 89 | { |
| 90 | // Initial revalidation. |
Florin Malita | 18eafd9 | 2018-01-04 21:11:55 -0500 | [diff] [blame] | 91 | check_inval(reporter, root, |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 92 | SkRect::MakeWH(100, 100), |
Mike Reed | 8008df1 | 2018-01-17 12:20:04 -0500 | [diff] [blame] | 93 | SkRectPriv::MakeLargeS32(), |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 94 | nullptr); |
Florin Malita | eb46bd8 | 2019-02-12 09:33:21 -0500 | [diff] [blame] | 95 | |
| 96 | check_hittest(reporter, root, { |
| 97 | {{ -1, 0 }, nullptr }, |
| 98 | {{ 0, -1 }, nullptr }, |
| 99 | {{ 100, 0 }, nullptr }, |
| 100 | {{ 0, 100 }, nullptr }, |
| 101 | {{ 0, 0 }, d1 }, |
| 102 | {{ 99, 99 }, d1 }, |
| 103 | }); |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 104 | } |
| 105 | |
| 106 | { |
| 107 | // Move r2 to (200 100). |
| 108 | r2->setL(200); r2->setT(100); r2->setR(300); r2->setB(200); |
| 109 | std::vector<SkRect> damage = { {0, 0, 100, 100}, { 200, 100, 300, 200} }; |
Florin Malita | 18eafd9 | 2018-01-04 21:11:55 -0500 | [diff] [blame] | 110 | check_inval(reporter, root, |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 111 | SkRect::MakeWH(300, 200), |
| 112 | SkRect::MakeWH(300, 200), |
| 113 | &damage); |
Florin Malita | eb46bd8 | 2019-02-12 09:33:21 -0500 | [diff] [blame] | 114 | |
| 115 | check_hittest(reporter, root, { |
| 116 | {{ -1, 0 }, nullptr }, |
| 117 | {{ 0, -1 }, nullptr }, |
| 118 | {{ 100, 0 }, nullptr }, |
| 119 | {{ 0, 100 }, nullptr }, |
| 120 | {{ 0, 0 }, d1 }, |
| 121 | {{ 99, 99 }, d1 }, |
| 122 | |
| 123 | {{ 199, 100 }, nullptr }, |
| 124 | {{ 200, 99 }, nullptr }, |
| 125 | {{ 300, 100 }, nullptr }, |
| 126 | {{ 200, 200 }, nullptr }, |
| 127 | {{ 200, 100 }, d2 }, |
| 128 | {{ 299, 199 }, d2 }, |
| 129 | }); |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 130 | } |
| 131 | |
| 132 | { |
| 133 | // Update the common color. |
Florin Malita | 0ebf419 | 2018-01-04 19:21:58 -0500 | [diff] [blame] | 134 | color->setColor(0xffff0000); |
| 135 | std::vector<SkRect> damage = { {0, 0, 100, 100}, { 200, 100, 300, 200} }; |
Florin Malita | 18eafd9 | 2018-01-04 21:11:55 -0500 | [diff] [blame] | 136 | check_inval(reporter, root, |
Florin Malita | 0ebf419 | 2018-01-04 19:21:58 -0500 | [diff] [blame] | 137 | SkRect::MakeWH(300, 200), |
| 138 | SkRect::MakeWH(300, 200), |
| 139 | &damage); |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 140 | } |
| 141 | |
| 142 | { |
| 143 | // Shrink r1. |
| 144 | r1->setR(50); |
| 145 | std::vector<SkRect> damage = { {0, 0, 100, 100}, { 0, 0, 50, 100} }; |
Florin Malita | 18eafd9 | 2018-01-04 21:11:55 -0500 | [diff] [blame] | 146 | check_inval(reporter, root, |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 147 | SkRect::MakeWH(300, 200), |
| 148 | SkRect::MakeWH(100, 100), |
| 149 | &damage); |
Florin Malita | eb46bd8 | 2019-02-12 09:33:21 -0500 | [diff] [blame] | 150 | |
| 151 | check_hittest(reporter, root, { |
| 152 | {{ -1, 0 }, nullptr }, |
| 153 | {{ 0, -1 }, nullptr }, |
| 154 | {{ 50, 0 }, nullptr }, |
| 155 | {{ 0, 100 }, nullptr }, |
| 156 | {{ 0, 0 }, d1 }, |
| 157 | {{ 49, 99 }, d1 }, |
| 158 | |
| 159 | {{ 199, 100 }, nullptr }, |
| 160 | {{ 200, 99 }, nullptr }, |
| 161 | {{ 300, 100 }, nullptr }, |
| 162 | {{ 200, 200 }, nullptr }, |
| 163 | {{ 200, 100 }, d2 }, |
| 164 | {{ 299, 199 }, d2 }, |
| 165 | }); |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 166 | } |
| 167 | |
| 168 | { |
| 169 | // Update transform. |
Florin Malita | 18eafd9 | 2018-01-04 21:11:55 -0500 | [diff] [blame] | 170 | matrix->setMatrix(SkMatrix::MakeScale(2, 2)); |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 171 | std::vector<SkRect> damage = { {0, 0, 300, 200}, { 0, 0, 600, 400} }; |
Florin Malita | 18eafd9 | 2018-01-04 21:11:55 -0500 | [diff] [blame] | 172 | check_inval(reporter, root, |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 173 | SkRect::MakeWH(600, 400), |
| 174 | SkRect::MakeWH(600, 400), |
| 175 | &damage); |
Florin Malita | eb46bd8 | 2019-02-12 09:33:21 -0500 | [diff] [blame] | 176 | |
| 177 | check_hittest(reporter, root, { |
| 178 | {{ -1, 0 }, nullptr }, |
| 179 | {{ 0, -1 }, nullptr }, |
| 180 | {{ 25, 0 }, nullptr }, |
| 181 | {{ 0, 50 }, nullptr }, |
| 182 | {{ 0, 0 }, d1 }, |
| 183 | {{ 24, 49 }, d1 }, |
| 184 | |
| 185 | {{ 99, 50 }, nullptr }, |
| 186 | {{ 100, 49 }, nullptr }, |
| 187 | {{ 150, 50 }, nullptr }, |
| 188 | {{ 100, 100 }, nullptr }, |
| 189 | {{ 100, 50 }, d2 }, |
| 190 | {{ 149, 99 }, d2 }, |
| 191 | }); |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 192 | } |
| 193 | |
| 194 | { |
| 195 | // Shrink r2 under transform. |
| 196 | r2->setR(250); |
| 197 | std::vector<SkRect> damage = { {400, 200, 600, 400}, { 400, 200, 500, 400} }; |
Florin Malita | 18eafd9 | 2018-01-04 21:11:55 -0500 | [diff] [blame] | 198 | check_inval(reporter, root, |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 199 | SkRect::MakeWH(500, 400), |
| 200 | SkRect::MakeLTRB(400, 200, 600, 400), |
| 201 | &damage); |
Florin Malita | eb46bd8 | 2019-02-12 09:33:21 -0500 | [diff] [blame] | 202 | |
| 203 | check_hittest(reporter, root, { |
| 204 | {{ -1, 0 }, nullptr }, |
| 205 | {{ 0, -1 }, nullptr }, |
| 206 | {{ 25, 0 }, nullptr }, |
| 207 | {{ 0, 50 }, nullptr }, |
| 208 | {{ 0, 0 }, d1 }, |
| 209 | {{ 24, 49 }, d1 }, |
| 210 | |
| 211 | {{ 99, 50 }, nullptr }, |
| 212 | {{ 100, 49 }, nullptr }, |
| 213 | {{ 125, 50 }, nullptr }, |
| 214 | {{ 100, 100 }, nullptr }, |
| 215 | {{ 100, 50 }, d2 }, |
| 216 | {{ 124, 99 }, d2 }, |
| 217 | }); |
Florin Malita | c75e240 | 2018-01-03 16:17:29 -0500 | [diff] [blame] | 218 | } |
| 219 | } |
Florin Malita | f4f3f0f | 2018-01-03 23:53:37 -0500 | [diff] [blame] | 220 | |
Florin Malita | c14f144 | 2018-01-05 11:32:31 -0500 | [diff] [blame] | 221 | static void inval_test2(skiatest::Reporter* reporter) { |
| 222 | auto color = sksg::Color::Make(0xff000000); |
| 223 | auto rect = sksg::Rect::Make(SkRect::MakeWH(100, 100)); |
Florin Malita | 760a052 | 2019-01-10 15:24:15 -0500 | [diff] [blame] | 224 | auto m1 = sksg::Matrix<SkMatrix>::Make(SkMatrix::I()), |
| 225 | m2 = sksg::Matrix<SkMatrix>::Make(SkMatrix::I()); |
Florin Malita | 919e209 | 2019-01-09 15:37:57 -0500 | [diff] [blame] | 226 | auto t1 = sksg::TransformEffect::Make(sksg::Draw::Make(rect, color), |
| 227 | sksg::Transform::MakeConcat(m1, m2)), |
| 228 | t2 = sksg::TransformEffect::Make(sksg::Draw::Make(rect, color), m1); |
Florin Malita | c14f144 | 2018-01-05 11:32:31 -0500 | [diff] [blame] | 229 | auto root = sksg::Group::Make(); |
| 230 | root->addChild(t1); |
| 231 | root->addChild(t2); |
| 232 | |
| 233 | { |
| 234 | // Initial revalidation. |
| 235 | check_inval(reporter, root, |
| 236 | SkRect::MakeWH(100, 100), |
Mike Reed | 8008df1 | 2018-01-17 12:20:04 -0500 | [diff] [blame] | 237 | SkRectPriv::MakeLargeS32(), |
Florin Malita | c14f144 | 2018-01-05 11:32:31 -0500 | [diff] [blame] | 238 | nullptr); |
| 239 | } |
| 240 | |
| 241 | { |
| 242 | // Update the shared color. |
| 243 | color->setColor(0xffff0000); |
| 244 | std::vector<SkRect> damage = { {0, 0, 100, 100}, { 0, 0, 100, 100} }; |
| 245 | check_inval(reporter, root, |
| 246 | SkRect::MakeWH(100, 100), |
| 247 | SkRect::MakeWH(100, 100), |
| 248 | &damage); |
| 249 | } |
| 250 | |
| 251 | { |
| 252 | // Update m2. |
| 253 | m2->setMatrix(SkMatrix::MakeScale(2, 2)); |
| 254 | std::vector<SkRect> damage = { {0, 0, 100, 100}, { 0, 0, 200, 200} }; |
| 255 | check_inval(reporter, root, |
| 256 | SkRect::MakeWH(200, 200), |
| 257 | SkRect::MakeWH(200, 200), |
| 258 | &damage); |
| 259 | } |
| 260 | |
| 261 | { |
| 262 | // Update shared m1. |
| 263 | m1->setMatrix(SkMatrix::MakeTrans(100, 100)); |
| 264 | std::vector<SkRect> damage = { { 0, 0, 200, 200}, // draw1 prev bounds |
| 265 | { 100, 100, 300, 300}, // draw1 new bounds |
| 266 | { 0, 0, 100, 100}, // draw2 prev bounds |
| 267 | { 100, 100, 200, 200} }; // draw2 new bounds |
| 268 | check_inval(reporter, root, |
| 269 | SkRect::MakeLTRB(100, 100, 300, 300), |
| 270 | SkRect::MakeLTRB( 0, 0, 300, 300), |
| 271 | &damage); |
| 272 | } |
| 273 | |
| 274 | { |
| 275 | // Update shared rect. |
| 276 | rect->setR(50); |
| 277 | std::vector<SkRect> damage = { { 100, 100, 300, 300}, // draw1 prev bounds |
| 278 | { 100, 100, 200, 300}, // draw1 new bounds |
| 279 | { 100, 100, 200, 200}, // draw2 prev bounds |
| 280 | { 100, 100, 150, 200} }; // draw2 new bounds |
| 281 | check_inval(reporter, root, |
| 282 | SkRect::MakeLTRB(100, 100, 200, 300), |
| 283 | SkRect::MakeLTRB(100, 100, 300, 300), |
| 284 | &damage); |
| 285 | } |
| 286 | } |
| 287 | |
Florin Malita | ef26fcb | 2019-02-10 12:54:20 -0500 | [diff] [blame] | 288 | static void inval_test3(skiatest::Reporter* reporter) { |
| 289 | auto color1 = sksg::Color::Make(0xff000000), |
| 290 | color2 = sksg::Color::Make(0xff000000); |
| 291 | auto group = sksg::Group::Make(); |
| 292 | |
| 293 | group->addChild(sksg::Draw::Make(sksg::Rect::Make(SkRect::MakeWH(100, 100)), |
| 294 | color1)); |
| 295 | group->addChild(sksg::Draw::Make(sksg::Rect::Make(SkRect::MakeXYWH(200, 0, 100, 100)), |
| 296 | color2)); |
| 297 | auto filter = sksg::DropShadowImageFilter::Make(); |
| 298 | filter->setOffset({50, 75}); |
| 299 | auto root = sksg::ImageFilterEffect::Make(group, filter); |
| 300 | |
| 301 | { |
| 302 | // Initial revalidation. |
| 303 | check_inval(reporter, root, |
| 304 | SkRect::MakeXYWH(0, 0, 350, 175), |
| 305 | SkRectPriv::MakeLargeS32(), |
| 306 | nullptr); |
| 307 | } |
| 308 | |
| 309 | { |
| 310 | // Shadow-only. |
| 311 | filter->setMode(sksg::DropShadowImageFilter::Mode::kShadowOnly); |
| 312 | std::vector<SkRect> damage = { {0, 0, 350, 175}, { 50, 75, 350, 175} }; |
| 313 | check_inval(reporter, root, |
| 314 | SkRect::MakeLTRB(50, 75, 350, 175), |
| 315 | SkRect::MakeLTRB(0, 0, 350, 175), |
| 316 | &damage); |
| 317 | } |
| 318 | |
| 319 | { |
| 320 | // Content change -> single/full filter bounds inval. |
| 321 | color1->setColor(0xffff0000); |
| 322 | std::vector<SkRect> damage = { { 50, 75, 350, 175} }; |
| 323 | check_inval(reporter, root, |
| 324 | SkRect::MakeLTRB(50, 75, 350, 175), |
| 325 | SkRect::MakeLTRB(50, 75, 350, 175), |
| 326 | &damage); |
| 327 | } |
| 328 | |
| 329 | } |
| 330 | |
Florin Malita | bee88d4 | 2018-10-02 13:05:39 -0400 | [diff] [blame] | 331 | static void inval_group_remove(skiatest::Reporter* reporter) { |
| 332 | auto draw = sksg::Draw::Make(sksg::Rect::Make(SkRect::MakeWH(100, 100)), |
| 333 | sksg::Color::Make(SK_ColorBLACK)); |
| 334 | auto grp = sksg::Group::Make(); |
| 335 | |
| 336 | // Readding the child should not trigger asserts. |
| 337 | grp->addChild(draw); |
| 338 | grp->removeChild(draw); |
| 339 | grp->addChild(draw); |
| 340 | } |
| 341 | |
Florin Malita | c14f144 | 2018-01-05 11:32:31 -0500 | [diff] [blame] | 342 | DEF_TEST(SGInvalidation, reporter) { |
| 343 | inval_test1(reporter); |
| 344 | inval_test2(reporter); |
Florin Malita | ef26fcb | 2019-02-10 12:54:20 -0500 | [diff] [blame] | 345 | inval_test3(reporter); |
Florin Malita | bee88d4 | 2018-10-02 13:05:39 -0400 | [diff] [blame] | 346 | inval_group_remove(reporter); |
Florin Malita | c14f144 | 2018-01-05 11:32:31 -0500 | [diff] [blame] | 347 | } |
| 348 | |
Florin Malita | f4f3f0f | 2018-01-03 23:53:37 -0500 | [diff] [blame] | 349 | #endif // !defined(SK_BUILD_FOR_GOOGLE3) |