• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 Google LLC
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 
8 #include "include/core/SkAlphaType.h"
9 #include "include/core/SkBitmap.h"
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkColor.h"
12 #include "include/core/SkColorSpace.h"
13 #include "include/core/SkColorType.h"
14 #include "include/core/SkImage.h"
15 #include "include/core/SkImageInfo.h"
16 #include "include/core/SkMatrix.h"
17 #include "include/core/SkPaint.h"
18 #include "include/core/SkPicture.h"
19 #include "include/core/SkPictureRecorder.h"
20 #include "include/core/SkPoint.h"
21 #include "include/core/SkRect.h"
22 #include "include/core/SkRefCnt.h"
23 #include "include/core/SkSamplingOptions.h"
24 #include "include/core/SkScalar.h"
25 #include "include/core/SkSize.h"
26 #include "include/core/SkStream.h"
27 #include "include/core/SkString.h"
28 #include "include/core/SkSurface.h"
29 #include "include/core/SkTiledImageUtils.h"
30 #include "include/encode/SkPngEncoder.h"
31 #include "include/gpu/GpuTypes.h"
32 #include "include/private/base/SkAssert.h"
33 #include "src/core/SkSamplingPriv.h"
34 #include "tests/Test.h"
35 #include "tests/TestUtils.h"
36 #include "tools/ToolUtils.h"
37 
38 #if defined(SK_GANESH)
39 #include "include/gpu/GrDirectContext.h"
40 #include "include/gpu/ganesh/SkSurfaceGanesh.h"
41 #include "src/gpu/ganesh/GrDirectContextPriv.h"
42 #include "src/gpu/ganesh/GrResourceCache.h"
43 #include "src/gpu/ganesh/GrSurface.h"
44 #include "src/gpu/ganesh/GrTexture.h"
45 #include "tests/CtsEnforcement.h"
46 struct GrContextOptions;
47 #endif
48 
49 #if defined(SK_GRAPHITE)
50 #include "include/gpu/graphite/Context.h"
51 #include "include/gpu/graphite/Recorder.h"
52 #include "include/gpu/graphite/Surface.h"
53 #include "src/gpu/graphite/Caps.h"
54 #include "src/gpu/graphite/RecorderPriv.h"
55 #include "src/gpu/graphite/Texture.h"
56 #include "tools/GpuToolUtils.h"
57 #else
58 namespace skgpu { namespace graphite { class Recorder; } }
59 #endif
60 
61 #include <atomic>
62 #include <functional>
63 #include <initializer_list>
64 #include <string.h>
65 #include <utility>
66 
67 #if defined(SK_GANESH) && defined(GR_TEST_UTILS)
68 extern int gOverrideMaxTextureSizeGanesh;
69 extern std::atomic<int> gNumTilesDrawnGanesh;
70 #endif
71 
72 #if defined(SK_GRAPHITE) && defined(GRAPHITE_TEST_UTILS)
73 extern int gOverrideMaxTextureSizeGraphite;
74 extern std::atomic<int> gNumTilesDrawnGraphite;
75 #endif
76 
77 namespace {
78 
79 // Draw a white border around the edge (to test strict constraints) and
80 // a Hilbert curve inside of that (so the effects of (mis) sampling are evident).
draw(SkCanvas * canvas,int imgSize,int whiteBandWidth,int desiredLineWidth,int desiredDepth)81  void draw(SkCanvas* canvas, int imgSize, int whiteBandWidth,
82            int desiredLineWidth, int desiredDepth) {
83     const int kPad = desiredLineWidth;
84 
85     canvas->clear(SK_ColorWHITE);
86 
87     SkPaint innerRect;
88     innerRect.setColor(SK_ColorDKGRAY);
89     canvas->drawRect(SkRect::MakeIWH(imgSize, imgSize).makeInset(whiteBandWidth, whiteBandWidth),
90                      innerRect);
91 
92     int desiredDrawSize = imgSize - 2 * kPad - 2 * whiteBandWidth;
93     ToolUtils::HilbertGenerator gen(desiredDrawSize, desiredLineWidth, desiredDepth);
94 
95     canvas->translate(kPad + whiteBandWidth, imgSize - kPad - whiteBandWidth);
96     gen.draw(canvas);
97 }
98 
99 
make_big_bitmap_image(int imgSize,int whiteBandWidth,int desiredLineWidth,int desiredDepth)100 sk_sp<SkImage> make_big_bitmap_image(int imgSize, int whiteBandWidth,
101                                      int desiredLineWidth, int desiredDepth) {
102     SkBitmap bm;
103 
104     bm.allocN32Pixels(imgSize, imgSize, /* isOpaque= */ true);
105     SkCanvas canvas(bm);
106 
107     draw(&canvas, imgSize, whiteBandWidth, desiredLineWidth, desiredDepth);
108 
109     bm.setImmutable();
110     return bm.asImage();
111 }
112 
make_big_picture_image(int imgSize,int whiteBandWidth,int desiredLineWidth,int desiredDepth)113 sk_sp<SkImage> make_big_picture_image(int imgSize, int whiteBandWidth,
114                                       int desiredLineWidth, int desiredDepth) {
115     sk_sp<SkPicture> pic;
116 
117     {
118         SkPictureRecorder recorder;
119         SkCanvas* canvas = recorder.beginRecording(SkRect::MakeIWH(imgSize, imgSize));
120         draw(canvas, imgSize, whiteBandWidth, desiredLineWidth, desiredDepth);
121         pic = recorder.finishRecordingAsPicture();
122     }
123 
124     return SkImages::DeferredFromPicture(std::move(pic),
125                                          { imgSize, imgSize },
126                                          /* matrix= */ nullptr,
127                                          /* paint= */ nullptr,
128                                          SkImages::BitDepth::kU8,
129                                          SkColorSpace::MakeSRGB());
130 }
131 
132 
get_sampling_str(const SkSamplingOptions & sampling)133 const char* get_sampling_str(const SkSamplingOptions& sampling) {
134     if (sampling.isAniso()) {
135         return "Aniso";
136     } else if (sampling.useCubic) {
137         return "Cubic";
138     } else if (sampling.mipmap != SkMipmapMode::kNone) {
139         return "Mipmap";
140     } else if (sampling.filter == SkFilterMode::kLinear) {
141         return "Linear";
142     } else {
143         return "NN";
144     }
145 }
146 
create_label(GrDirectContext * dContext,const char * generator,const SkSamplingOptions & sampling,int scale,int rot,SkCanvas::SrcRectConstraint constraint,int numTiles)147 SkString create_label(GrDirectContext* dContext,
148                       const char* generator,
149                       const SkSamplingOptions& sampling,
150                       int scale,
151                       int rot,
152                       SkCanvas::SrcRectConstraint constraint,
153                       int numTiles) {
154     SkString label;
155     label.appendf("%s-%s-%s-%d-%d-%s-%d",
156                   dContext ? "ganesh" : "graphite",
157                   generator,
158                   get_sampling_str(sampling),
159                   scale,
160                   rot,
161                   constraint == SkCanvas::kFast_SrcRectConstraint ? "fast" : "strict",
162                   numTiles);
163     return label;
164  }
165 
potentially_write_to_png(const char * directory,const SkString & label,const SkBitmap & bm)166 void potentially_write_to_png(const char* directory,
167                               const SkString& label,
168                               const SkBitmap& bm) {
169     constexpr bool kWriteOutImages = false;
170 
171     if constexpr(kWriteOutImages) {
172         SkString filename;
173         filename.appendf("//%s//%s.png", directory, label.c_str());
174 
175         SkFILEWStream file(filename.c_str());
176         SkAssertResult(file.isValid());
177 
178         SkAssertResult(SkPngEncoder::Encode(&file, bm.pixmap(), {}));
179     }
180 }
181 
check_pixels(skiatest::Reporter * reporter,const SkBitmap & expected,const SkBitmap & actual,const SkString & label,int rot)182 bool check_pixels(skiatest::Reporter* reporter,
183                   const SkBitmap& expected,
184                   const SkBitmap& actual,
185                   const SkString& label,
186                   int rot) {
187     static const float kTols[4]    = { 0.008f, 0.008f, 0.008f, 0.008f };   // ~ 2/255
188     static const float kRotTols[4] = { 0.024f, 0.024f, 0.024f, 0.024f };   // ~ 6/255
189 
190     auto error = std::function<ComparePixmapsErrorReporter>(
191             [&](int x, int y, const float diffs[4]) {
192                 SkASSERT(x >= 0 && y >= 0);
193                 ERRORF(reporter, "%s: mismatch at %d, %d (%f, %f, %f %f)",
194                        label.c_str(), x, y, diffs[0], diffs[1], diffs[2], diffs[3]);
195             });
196 
197     return ComparePixels(expected.pixmap(), actual.pixmap(), rot ? kRotTols : kTols, error);
198 }
199 
200 // Return a clip rect that will result in the number of desired tiles being used. The trick
201 // is that the clip rect also has to work when rotated.
clip_rect(SkRect dstRect,int numDesiredTiles)202 SkRect clip_rect(SkRect dstRect, int numDesiredTiles) {
203     dstRect.outset(5, 5);
204 
205     switch (numDesiredTiles) {
206         case 0:
207             return { dstRect.fLeft-64, dstRect.fTop-64, dstRect.fLeft-63, dstRect.fTop-63 };
208         case 4: {
209             // Upper left 4x4
210             float outset = 0.125f * dstRect.width() * SK_ScalarRoot2Over2;
211             SkPoint center = dstRect.center();
212             return { center.fX - outset, center.fY - outset,
213                      center.fX + outset, center.fY + outset };
214         }
215         case 9: {
216             // Upper left 3x3
217             float outset = 0.25f * dstRect.width() * SK_ScalarRoot2Over2;
218             SkPoint center = dstRect.center();
219             center.offset(-dstRect.width()/8.0f, -dstRect.height()/8.0f);
220             return { center.fX - outset, center.fY - outset,
221                      center.fX + outset, center.fY + outset };
222         }
223     }
224 
225     return dstRect; // all 16 tiles
226 }
227 
difficult_case(const SkSamplingOptions & sampling,int scale,int rot,SkCanvas::SrcRectConstraint constraint)228 bool difficult_case(const SkSamplingOptions& sampling,
229                     int scale,
230                     int rot,
231                     SkCanvas::SrcRectConstraint constraint) {
232     if (sampling.useCubic) {
233         return false;  // cubic never causes any issues
234     }
235 
236     if (constraint == SkCanvas::kStrict_SrcRectConstraint &&
237             (sampling.mipmap != SkMipmapMode::kNone || sampling.filter == SkFilterMode::kLinear)) {
238         // linear-filtered strict big image drawing is currently broken (b/286239467). The issue
239         // is that the strict constraint is propagated to the child tiles which breaks the
240         // interpolation expected in the middle of the large image.
241         // Note that strict mipmapping is auto-downgraded to strict linear sampling.
242         return true;
243     }
244 
245     if (sampling.mipmap == SkMipmapMode::kLinear) {
246         // Mipmapping is broken for anything other that 1-to-1 draws (b/286256104). The issue
247         // is that the mipmaps are created for each tile individually so the higher levels differ
248         // from what would be generated with the entire image. Mipmapped draws are off by ~20/255
249         // at 4x and ~64/255 at 8x)
250         return scale > 1;
251     }
252 
253     if (sampling.filter == SkFilterMode::kNearest) {
254         // Perhaps unsurprisingly, NN only passes on un-rotated 1-to-1 draws (off by ~187/255 at
255         // different scales).
256         return scale > 1 || rot > 0;
257     }
258 
259     return false;
260 }
261 
262 // compare tiled and untiled draws - varying the parameters (e.g., sampling, rotation, fast vs.
263 // strict, etc).
tiling_comparison_test(GrDirectContext * dContext,skgpu::graphite::Recorder * recorder,skiatest::Reporter * reporter)264 void tiling_comparison_test(GrDirectContext* dContext,
265                             skgpu::graphite::Recorder* recorder,
266                             skiatest::Reporter* reporter) {
267     // We're using the knowledge that the internal tile size is 1024. By creating kImageSize
268     // sized images we know we'll get a 4x4 tiling regardless of the sampling.
269     static const int kImageSize = 4096 - 4 * 2 * kBicubicFilterTexelPad;
270     static const int kOverrideMaxTextureSize = 1024;
271 
272 #if defined(SK_GANESH)
273     if (dContext && dContext->maxTextureSize() < kImageSize) {
274         // For the expected images we need to be able to draw w/o tiling
275         return;
276     }
277 #endif
278 
279 #if defined(SK_GRAPHITE)
280     if (recorder) {
281         const skgpu::graphite::Caps* caps = recorder->priv().caps();
282         if (caps->maxTextureSize() < kImageSize) {
283             return;
284         }
285     }
286 #endif
287 
288     static const int kWhiteBandWidth = 4;
289     const SkRect srcRect = SkRect::MakeIWH(kImageSize, kImageSize).makeInset(kWhiteBandWidth,
290                                                                              kWhiteBandWidth);
291 
292     using GeneratorT = sk_sp<SkImage>(*)(int imgSize, int whiteBandWidth,
293                                          int desiredLineWidth, int desiredDepth);
294 
295     static const struct {
296         GeneratorT fGen;
297         const char* fTag;
298     } kGenerators[] = { { make_big_bitmap_image,  "BM" },
299                         { make_big_picture_image, "Picture" } };
300 
301     static const SkSamplingOptions kSamplingOptions[] = {
302         SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone),
303         SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone),
304         // Note that Mipmapping gets auto-disabled with a strict-constraint
305         SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear),
306         SkSamplingOptions(SkCubicResampler::CatmullRom()),
307     };
308 
309     int numClippedTiles = 9;
310     for (auto gen : kGenerators) {
311         if (recorder && !strcmp(gen.fTag, "Picture")) {
312             // In the picture-image case, the non-tiled code path draws the picture directly into a
313             // gpu-backed surface while the tiled code path the picture is draws the picture into
314             // a raster-backed surface. For Ganesh this works out, since both Ganesh and Raster
315             // support non-AA rect draws. For Graphite the results are very different (since
316             // Graphite always anti-aliases. Forcing all the rect draws to be AA doesn't work out
317             // since AA introduces too much variance between both of the gpu backends and Raster -
318             // which would obscure any errors introduced by tiling.
319             continue;
320         }
321 
322         sk_sp<SkImage> img = (*gen.fGen)(kImageSize,
323                                          kWhiteBandWidth,
324                                          /* desiredLineWidth= */ 16,
325                                          /* desiredDepth= */ 7);
326         numClippedTiles = (numClippedTiles == 9) ? 4 : 9;  // alternate to reduce the combinatorics
327 
328         for (int scale : { 1, 4, 8 }) {
329             for (int rot : { 0, 45 }) {
330                 for (int numDesiredTiles : { numClippedTiles, 16 }) {
331                     SkRect destRect = SkRect::MakeWH(srcRect.width()/scale,
332                                                      srcRect.height()/scale);
333 
334                     SkMatrix m = SkMatrix::RotateDeg(rot, destRect.center());
335                     SkIRect rotatedRect = m.mapRect(destRect).roundOut();
336                     rotatedRect.outset(2, 2);   // outset to capture the constraint's effect
337 
338                     SkRect clipRect = clip_rect(destRect, numDesiredTiles);
339 
340                     auto destII = SkImageInfo::Make(rotatedRect.width(),
341                                                     rotatedRect.height(),
342                                                     kRGBA_8888_SkColorType,
343                                                     kPremul_SkAlphaType);
344 
345                     SkBitmap expected, actual;
346                     expected.allocPixels(destII);
347                     actual.allocPixels(destII);
348 
349                     sk_sp<SkSurface> surface;
350 
351 #if defined(SK_GANESH)
352                     if (dContext) {
353                         surface = SkSurfaces::RenderTarget(dContext,
354                                                            skgpu::Budgeted::kNo,
355                                                            destII);
356                     }
357 #endif
358 
359 #if defined(SK_GRAPHITE)
360                     if (recorder) {
361                         surface = SkSurfaces::RenderTarget(recorder, destII);
362                     }
363 #endif
364 
365                     for (auto sampling : kSamplingOptions) {
366                         for (auto constraint : { SkCanvas::kStrict_SrcRectConstraint,
367                                                  SkCanvas::kFast_SrcRectConstraint }) {
368                             if (difficult_case(sampling, scale, rot, constraint)) {
369                                 continue;
370                             }
371 
372                             SkString label = create_label(dContext, gen.fTag, sampling, scale, rot,
373                                                           constraint, numDesiredTiles);
374 
375                             SkCanvas* canvas = surface->getCanvas();
376 
377                             SkAutoCanvasRestore acr(canvas, /* doSave= */ true);
378 
379                             canvas->translate(-rotatedRect.fLeft, -rotatedRect.fTop);
380                             if (sampling.useCubic || sampling.filter != SkFilterMode::kNearest) {
381                                 // NN sampling doesn't deal well w/ the (0.5, 0.5) offset but the
382                                 // other sampling modes need it to exercise strict vs. fast
383                                 // constraint in non-rotated draws
384                                 canvas->translate(0.5f, 0.5f);
385                             }
386                             canvas->concat(m);
387 
388                             // First, draw w/o tiling
389 #if defined(SK_GANESH) && defined(GR_TEST_UTILS)
390                             gOverrideMaxTextureSizeGanesh = 0;
391 #endif
392 #if defined(SK_GRAPHITE) && defined(GRAPHITE_TEST_UTILS)
393                             gOverrideMaxTextureSizeGraphite = 0;
394 #endif
395                             canvas->clear(SK_ColorBLACK);
396                             canvas->save();
397                             canvas->clipRect(clipRect);
398 
399                             SkTiledImageUtils::DrawImageRect(canvas, img, srcRect, destRect,
400                                                              sampling, /* paint= */ nullptr,
401                                                              constraint);
402                             SkAssertResult(surface->readPixels(expected, 0, 0));
403 #if defined(SK_GANESH) && defined(GR_TEST_UTILS)
404                             int actualNumTiles =
405                                     gNumTilesDrawnGanesh.load(std::memory_order_acquire);
406                             REPORTER_ASSERT(reporter, actualNumTiles == 0);
407 #endif
408 #if defined(SK_GRAPHITE) && defined(GRAPHITE_TEST_UTILS)
409                             int actualNumTiles2 =
410                                     gNumTilesDrawnGraphite.load(std::memory_order_acquire);
411                             REPORTER_ASSERT(reporter, actualNumTiles2 == 0);
412 #endif
413                             canvas->restore();
414 
415                             // Then, force 4x4 tiling
416 #if defined(SK_GANESH) && defined(GR_TEST_UTILS)
417                             gOverrideMaxTextureSizeGanesh = kOverrideMaxTextureSize;
418 #endif
419 #if defined(SK_GRAPHITE) && defined(GRAPHITE_TEST_UTILS)
420                             gOverrideMaxTextureSizeGraphite = kOverrideMaxTextureSize;
421 #endif
422 
423                             canvas->clear(SK_ColorBLACK);
424                             canvas->save();
425                             canvas->clipRect(clipRect);
426 
427                             SkTiledImageUtils::DrawImageRect(canvas, img, srcRect, destRect,
428                                                              sampling, /* paint= */ nullptr,
429                                                              constraint);
430                             SkAssertResult(surface->readPixels(actual, 0, 0));
431 #if defined(SK_GANESH) && defined(GR_TEST_UTILS)
432                             if (canvas->recordingContext()) {
433                                 actualNumTiles =
434                                         gNumTilesDrawnGanesh.load(std::memory_order_acquire);
435                                 REPORTER_ASSERT(reporter,
436                                                 numDesiredTiles == actualNumTiles,
437                                                 "mismatch expected: %d actual: %d\n",
438                                                 numDesiredTiles,
439                                                 actualNumTiles);
440                             }
441 #endif
442 #if defined(SK_GRAPHITE) && defined(GRAPHITE_TEST_UTILS)
443                             if (canvas->recorder()) {
444                                 actualNumTiles2 =
445                                         gNumTilesDrawnGraphite.load(std::memory_order_acquire);
446                                 REPORTER_ASSERT(reporter,
447                                                 numDesiredTiles == actualNumTiles2,
448                                                 "mismatch expected: %d actual: %d\n",
449                                                 numDesiredTiles,
450                                                 actualNumTiles2);
451                             }
452 #endif
453 
454                             canvas->restore();
455 
456                             REPORTER_ASSERT(reporter, check_pixels(reporter, expected, actual,
457                                                                    label, rot));
458 
459                             potentially_write_to_png("expected", label, expected);
460                             potentially_write_to_png("actual", label, actual);
461                         }
462                     }
463                 }
464             }
465         }
466     }
467     // Reset tiling behavior
468 #if defined(SK_GANESH) && defined(GR_TEST_UTILS)
469     gOverrideMaxTextureSizeGanesh = 0;
470 #endif
471 #if defined(SK_GRAPHITE) && defined(GRAPHITE_TEST_UTILS)
472     gOverrideMaxTextureSizeGraphite = 0;
473 #endif
474 }
475 
476 // In this test we draw the same bitmap-backed image twice and check that we only upload it once.
477 // Everything is set up for the bitmap-backed image to be split into 16 1024x1024 tiles.
tiled_image_caching_test(GrDirectContext * dContext,skgpu::graphite::Recorder * recorder,skiatest::Reporter * reporter)478 void tiled_image_caching_test(GrDirectContext* dContext,
479                               skgpu::graphite::Recorder* recorder,
480                               skiatest::Reporter* reporter) {
481     static const int kImageSize = 4096;
482     static const int kOverrideMaxTextureSize = 1024;
483     static const SkISize kExpectedTileSize { kOverrideMaxTextureSize, kOverrideMaxTextureSize };
484 
485     sk_sp<SkImage> img = make_big_bitmap_image(kImageSize,
486                                                /* whiteBandWidth= */ 0,
487                                                /* desiredLineWidth= */ 16,
488                                                /* desiredDepth= */ 7);
489 
490     auto destII = SkImageInfo::Make(kImageSize, kImageSize,
491                                     kRGBA_8888_SkColorType,
492                                     kPremul_SkAlphaType);
493 
494     SkBitmap readback;
495     readback.allocPixels(destII);
496 
497     sk_sp<SkSurface> surface;
498 
499 #if defined(SK_GANESH)
500     if (dContext) {
501         surface = SkSurfaces::RenderTarget(dContext, skgpu::Budgeted::kNo, destII);
502     }
503 #endif
504 
505 #if defined(SK_GRAPHITE)
506     if (recorder) {
507         surface = SkSurfaces::RenderTarget(recorder, destII);
508     }
509 #endif
510 
511     if (!surface) {
512         return;
513     }
514 
515     SkCanvas* canvas = surface->getCanvas();
516 
517 #if defined(SK_GANESH) && defined(GR_TEST_UTILS)
518     gOverrideMaxTextureSizeGanesh = kOverrideMaxTextureSize;
519 #endif
520 #if defined(SK_GRAPHITE) && defined(GRAPHITE_TEST_UTILS)
521     gOverrideMaxTextureSizeGraphite = kOverrideMaxTextureSize;
522 #endif
523     for (int i = 0; i < 2; ++i) {
524         canvas->clear(SK_ColorBLACK);
525 
526         SkTiledImageUtils::DrawImage(canvas, img,
527                                      /* x= */ 0, /* y= */ 0,
528                                      SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone),
529                                      /* paint= */ nullptr,
530                                      SkCanvas::kFast_SrcRectConstraint);
531         SkAssertResult(surface->readPixels(readback, 0, 0));
532     }
533 
534     int numFound = 0;
535 
536 #if defined(SK_GANESH)
537     if (dContext) {
538         GrResourceCache* cache = dContext->priv().getResourceCache();
539 
540         cache->visitSurfaces([&](const GrSurface* surf, bool /* purgeable */) {
541             const GrTexture* tex = surf->asTexture();
542             if (tex && tex->dimensions() == kExpectedTileSize) {
543                 ++numFound;
544             }
545         });
546     }
547 #endif
548 
549 #if defined(SK_GRAPHITE)
550     if (recorder) {
551         skgpu::graphite::ResourceCache* cache = recorder->priv().resourceCache();
552 
553         cache->visitTextures([&](const skgpu::graphite::Texture* tex, bool /* purgeable */) {
554             if (tex->dimensions() == kExpectedTileSize) {
555                 ++numFound;
556             }
557         });
558     }
559 #endif
560 
561     REPORTER_ASSERT(reporter, numFound == 16, "Expected: 16 Actual: %d", numFound);
562 
563     // reset to default behavior
564 #if defined(SK_GANESH) && defined(GR_TEST_UTILS)
565     gOverrideMaxTextureSizeGanesh = 0;
566 #endif
567 #if defined(SK_GRAPHITE) && defined(GRAPHITE_TEST_UTILS)
568     gOverrideMaxTextureSizeGraphite = 0;
569 #endif
570 }
571 
572 } // anonymous namespace
573 
574 #if defined(SK_GANESH)
575 
576 // TODO(b/306005622): fix in SkQP and move to CtsEnforcement::kNextRelease
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(BigImageTest_Ganesh,reporter,ctxInfo,CtsEnforcement::kNever)577 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(BigImageTest_Ganesh,
578                                        reporter,
579                                        ctxInfo,
580                                        CtsEnforcement::kNever) {
581     auto dContext = ctxInfo.directContext();
582 
583     tiling_comparison_test(dContext, /* recorder= */ nullptr, reporter);
584 }
585 
586 // TODO(b/306005622): fix in SkQP and move to CtsEnforcement::kNextRelease
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(TiledDrawCacheTest_Ganesh,reporter,ctxInfo,CtsEnforcement::kNever)587 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(TiledDrawCacheTest_Ganesh,
588                                        reporter,
589                                        ctxInfo,
590                                        CtsEnforcement::kNever) {
591     auto dContext = ctxInfo.directContext();
592 
593     tiled_image_caching_test(dContext, /* recorder= */ nullptr, reporter);
594 }
595 
596 #endif // SK_GANESH
597 
598 #if defined(SK_GRAPHITE)
599 
600 // TODO(b/306005622): fix in SkQP and move to CtsEnforcement::kNextRelease
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(BigImageTest_Graphite,reporter,context,CtsEnforcement::kNever)601 DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(BigImageTest_Graphite,
602                                          reporter,
603                                          context,
604                                          CtsEnforcement::kNever) {
605     std::unique_ptr<skgpu::graphite::Recorder> recorder =
606             context->makeRecorder(ToolUtils::CreateTestingRecorderOptions());
607 
608     tiling_comparison_test(/* dContext= */ nullptr, recorder.get(), reporter);
609 }
610 
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(TiledDrawCacheTest_Graphite,reporter,context,CtsEnforcement::kNextRelease)611 DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(TiledDrawCacheTest_Graphite,
612                                          reporter,
613                                          context,
614                                          CtsEnforcement::kNextRelease) {
615     std::unique_ptr<skgpu::graphite::Recorder> recorder =
616             context->makeRecorder(ToolUtils::CreateTestingRecorderOptions());
617 
618     tiled_image_caching_test(/* dContext= */ nullptr, recorder.get(), reporter);
619 }
620 
621 #endif // SK_GRAPHITE
622