xref: /aosp_15_r20/external/skia/tests/BigImageTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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/ganesh/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/graphite/GraphiteToolUtils.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(GPU_TEST_UTILS)
68 extern int gOverrideMaxTextureSizeGanesh;
69 extern std::atomic<int> gNumTilesDrawnGanesh;
70 #endif
71 
72 #if defined(SK_GRAPHITE) && defined(GPU_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     // Max size of created images accounting for 45 degree rotation.
273     static const int kMaxRotatedImageSize = std::ceil(kImageSize * std::sqrt(2.0));
274 
275 #if defined(SK_GANESH)
276     if (dContext && dContext->maxTextureSize() < kMaxRotatedImageSize) {
277         // For the expected images we need to be able to draw w/o tiling
278         return;
279     }
280 #endif
281 
282 #if defined(SK_GRAPHITE)
283     if (recorder) {
284         const skgpu::graphite::Caps* caps = recorder->priv().caps();
285         if (caps->maxTextureSize() < kMaxRotatedImageSize) {
286             return;
287         }
288     }
289 #endif
290 
291     static const int kWhiteBandWidth = 4;
292     const SkRect srcRect = SkRect::MakeIWH(kImageSize, kImageSize).makeInset(kWhiteBandWidth,
293                                                                              kWhiteBandWidth);
294 
295     using GeneratorT = sk_sp<SkImage>(*)(int imgSize, int whiteBandWidth,
296                                          int desiredLineWidth, int desiredDepth);
297 
298     static const struct {
299         GeneratorT fGen;
300         const char* fTag;
301     } kGenerators[] = { { make_big_bitmap_image,  "BM" },
302                         { make_big_picture_image, "Picture" } };
303 
304     static const SkSamplingOptions kSamplingOptions[] = {
305         SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone),
306         SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone),
307         // Note that Mipmapping gets auto-disabled with a strict-constraint
308         SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear),
309         SkSamplingOptions(SkCubicResampler::CatmullRom()),
310     };
311 
312     int numClippedTiles = 9;
313     for (auto gen : kGenerators) {
314         sk_sp<SkImage> img = (*gen.fGen)(kImageSize,
315                                          kWhiteBandWidth,
316                                          /* desiredLineWidth= */ 16,
317                                          /* desiredDepth= */ 7);
318         numClippedTiles = (numClippedTiles == 9) ? 4 : 9;  // alternate to reduce the combinatorics
319 
320         for (int scale : { 1, 4, 8 }) {
321             for (int rot : { 0, 45 }) {
322                 for (int numDesiredTiles : { numClippedTiles, 16 }) {
323                     SkRect destRect = SkRect::MakeWH(srcRect.width()/scale,
324                                                      srcRect.height()/scale);
325 
326                     SkMatrix m = SkMatrix::RotateDeg(rot, destRect.center());
327                     SkIRect rotatedRect = m.mapRect(destRect).roundOut();
328                     rotatedRect.outset(2, 2);   // outset to capture the constraint's effect
329 
330                     SkRect clipRect = clip_rect(destRect, numDesiredTiles);
331 
332                     auto destII = SkImageInfo::Make(rotatedRect.width(),
333                                                     rotatedRect.height(),
334                                                     kRGBA_8888_SkColorType,
335                                                     kPremul_SkAlphaType);
336 
337                     SkBitmap expected, actual;
338                     expected.allocPixels(destII);
339                     actual.allocPixels(destII);
340 
341                     sk_sp<SkSurface> surface;
342 
343 #if defined(SK_GANESH)
344                     if (dContext) {
345                         surface = SkSurfaces::RenderTarget(dContext,
346                                                            skgpu::Budgeted::kNo,
347                                                            destII);
348                     }
349 #endif
350 
351 #if defined(SK_GRAPHITE)
352                     if (recorder) {
353                         surface = SkSurfaces::RenderTarget(recorder, destII);
354                     }
355 #endif
356 
357                     if (!surface) {
358                         ERRORF(reporter, "Failed to create surface");
359                         return;
360                     }
361 
362                     for (auto sampling : kSamplingOptions) {
363                         for (auto constraint : { SkCanvas::kStrict_SrcRectConstraint,
364                                                  SkCanvas::kFast_SrcRectConstraint }) {
365                             if (difficult_case(sampling, scale, rot, constraint)) {
366                                 continue;
367                             }
368 
369                             SkString label = create_label(dContext, gen.fTag, sampling, scale, rot,
370                                                           constraint, numDesiredTiles);
371 
372                             SkCanvas* canvas = surface->getCanvas();
373 
374                             SkAutoCanvasRestore acr(canvas, /* doSave= */ true);
375 
376                             canvas->translate(-rotatedRect.fLeft, -rotatedRect.fTop);
377                             if (sampling.useCubic || sampling.filter != SkFilterMode::kNearest) {
378                                 // NN sampling doesn't deal well w/ the (0.5, 0.5) offset but the
379                                 // other sampling modes need it to exercise strict vs. fast
380                                 // constraint in non-rotated draws
381                                 canvas->translate(0.5f, 0.5f);
382                             }
383                             canvas->concat(m);
384 
385                             // First, draw w/o tiling
386 #if defined(SK_GANESH) && defined(GPU_TEST_UTILS)
387                             gOverrideMaxTextureSizeGanesh = 0;
388 #endif
389 #if defined(SK_GRAPHITE) && defined(GPU_TEST_UTILS)
390                             gOverrideMaxTextureSizeGraphite = 0;
391 #endif
392                             canvas->clear(SK_ColorBLACK);
393                             canvas->save();
394                             canvas->clipRect(clipRect);
395 
396                             SkTiledImageUtils::DrawImageRect(canvas, img, srcRect, destRect,
397                                                              sampling, /* paint= */ nullptr,
398                                                              constraint);
399                             SkAssertResult(surface->readPixels(expected, 0, 0));
400 #if defined(SK_GANESH) && defined(GPU_TEST_UTILS)
401                             if (canvas->recordingContext()) {
402                                 int actualNumTiles =
403                                         gNumTilesDrawnGanesh.load(std::memory_order_acquire);
404                                 REPORTER_ASSERT(reporter, actualNumTiles == 0);
405                             }
406 #endif
407 #if defined(SK_GRAPHITE) && defined(GPU_TEST_UTILS)
408                             if (canvas->recorder()) {
409                                 int actualNumTiles =
410                                         gNumTilesDrawnGraphite.load(std::memory_order_acquire);
411                                 REPORTER_ASSERT(reporter, actualNumTiles == 0);
412                             }
413 #endif
414                             canvas->restore();
415 
416                             // Then, force 4x4 tiling
417 #if defined(SK_GANESH) && defined(GPU_TEST_UTILS)
418                             gOverrideMaxTextureSizeGanesh = kOverrideMaxTextureSize;
419 #endif
420 #if defined(SK_GRAPHITE) && defined(GPU_TEST_UTILS)
421                             gOverrideMaxTextureSizeGraphite = kOverrideMaxTextureSize;
422 #endif
423 
424                             canvas->clear(SK_ColorBLACK);
425                             canvas->save();
426                             canvas->clipRect(clipRect);
427 
428                             SkTiledImageUtils::DrawImageRect(canvas, img, srcRect, destRect,
429                                                              sampling, /* paint= */ nullptr,
430                                                              constraint);
431                             SkAssertResult(surface->readPixels(actual, 0, 0));
432 #if defined(SK_GANESH) && defined(GPU_TEST_UTILS)
433                             if (canvas->recordingContext()) {
434                                 int actualNumTiles =
435                                         gNumTilesDrawnGanesh.load(std::memory_order_acquire);
436                                 REPORTER_ASSERT(reporter,
437                                                 numDesiredTiles == actualNumTiles,
438                                                 "mismatch expected: %d actual: %d\n",
439                                                 numDesiredTiles,
440                                                 actualNumTiles);
441                             }
442 #endif
443 #if defined(SK_GRAPHITE) && defined(GPU_TEST_UTILS)
444                             if (canvas->recorder()) {
445                                 int actualNumTiles =
446                                         gNumTilesDrawnGraphite.load(std::memory_order_acquire);
447                                 REPORTER_ASSERT(reporter,
448                                                 numDesiredTiles == actualNumTiles,
449                                                 "mismatch expected: %d actual: %d\n",
450                                                 numDesiredTiles,
451                                                 actualNumTiles);
452                             }
453 #endif
454 
455                             canvas->restore();
456 
457                             REPORTER_ASSERT(reporter, check_pixels(reporter, expected, actual,
458                                                                    label, rot));
459 
460                             potentially_write_to_png("expected", label, expected);
461                             potentially_write_to_png("actual", label, actual);
462                         }
463                     }
464                 }
465             }
466         }
467     }
468     // Reset tiling behavior
469 #if defined(SK_GANESH) && defined(GPU_TEST_UTILS)
470     gOverrideMaxTextureSizeGanesh = 0;
471 #endif
472 #if defined(SK_GRAPHITE) && defined(GPU_TEST_UTILS)
473     gOverrideMaxTextureSizeGraphite = 0;
474 #endif
475 }
476 
477 // In this test we draw the same bitmap-backed image twice and check that we only upload it once.
478 // 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)479 void tiled_image_caching_test(GrDirectContext* dContext,
480                               skgpu::graphite::Recorder* recorder,
481                               skiatest::Reporter* reporter) {
482     static const int kImageSize = 4096;
483     static const int kOverrideMaxTextureSize = 1024;
484     static const SkISize kExpectedTileSize { kOverrideMaxTextureSize, kOverrideMaxTextureSize };
485 
486     sk_sp<SkImage> img = make_big_bitmap_image(kImageSize,
487                                                /* whiteBandWidth= */ 0,
488                                                /* desiredLineWidth= */ 16,
489                                                /* desiredDepth= */ 7);
490 
491     auto destII = SkImageInfo::Make(kImageSize, kImageSize,
492                                     kRGBA_8888_SkColorType,
493                                     kPremul_SkAlphaType);
494 
495     SkBitmap readback;
496     readback.allocPixels(destII);
497 
498     sk_sp<SkSurface> surface;
499 
500 #if defined(SK_GANESH)
501     if (dContext) {
502         surface = SkSurfaces::RenderTarget(dContext, skgpu::Budgeted::kNo, destII);
503     }
504 #endif
505 
506 #if defined(SK_GRAPHITE)
507     if (recorder) {
508         surface = SkSurfaces::RenderTarget(recorder, destII);
509     }
510 #endif
511 
512     if (!surface) {
513         return;
514     }
515 
516     SkCanvas* canvas = surface->getCanvas();
517 
518 #if defined(SK_GANESH) && defined(GPU_TEST_UTILS)
519     gOverrideMaxTextureSizeGanesh = kOverrideMaxTextureSize;
520 #endif
521 #if defined(SK_GRAPHITE) && defined(GPU_TEST_UTILS)
522     gOverrideMaxTextureSizeGraphite = kOverrideMaxTextureSize;
523 #endif
524     for (int i = 0; i < 2; ++i) {
525         canvas->clear(SK_ColorBLACK);
526 
527         SkTiledImageUtils::DrawImage(canvas, img,
528                                      /* x= */ 0, /* y= */ 0,
529                                      SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone),
530                                      /* paint= */ nullptr,
531                                      SkCanvas::kFast_SrcRectConstraint);
532         SkAssertResult(surface->readPixels(readback, 0, 0));
533     }
534 
535     int numFound = 0;
536 
537 #if defined(SK_GANESH)
538     if (dContext) {
539         GrResourceCache* cache = dContext->priv().getResourceCache();
540 
541         cache->visitSurfaces([&](const GrSurface* surf, bool /* purgeable */) {
542             const GrTexture* tex = surf->asTexture();
543             if (tex && tex->dimensions() == kExpectedTileSize) {
544                 ++numFound;
545             }
546         });
547     }
548 #endif
549 
550 #if defined(SK_GRAPHITE)
551     if (recorder) {
552         skgpu::graphite::ResourceCache* cache = recorder->priv().resourceCache();
553 
554         cache->visitTextures([&](const skgpu::graphite::Texture* tex, bool /* purgeable */) {
555             if (tex->dimensions() == kExpectedTileSize) {
556                 ++numFound;
557             }
558         });
559     }
560 #endif
561 
562     REPORTER_ASSERT(reporter, numFound == 16, "Expected: 16 Actual: %d", numFound);
563 
564     // reset to default behavior
565 #if defined(SK_GANESH) && defined(GPU_TEST_UTILS)
566     gOverrideMaxTextureSizeGanesh = 0;
567 #endif
568 #if defined(SK_GRAPHITE) && defined(GPU_TEST_UTILS)
569     gOverrideMaxTextureSizeGraphite = 0;
570 #endif
571 }
572 
573 } // anonymous namespace
574 
575 #if defined(SK_GANESH)
576 
577 // TODO(b/306005622): fix in SkQP and move to CtsEnforcement::kNextRelease
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(BigImageTest_Ganesh,reporter,ctxInfo,CtsEnforcement::kNever)578 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(BigImageTest_Ganesh,
579                                        reporter,
580                                        ctxInfo,
581                                        CtsEnforcement::kNever) {
582     auto dContext = ctxInfo.directContext();
583 
584     tiling_comparison_test(dContext, /* recorder= */ nullptr, reporter);
585 }
586 
587 // TODO(b/306005622): fix in SkQP and move to CtsEnforcement::kNextRelease
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(TiledDrawCacheTest_Ganesh,reporter,ctxInfo,CtsEnforcement::kNever)588 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(TiledDrawCacheTest_Ganesh,
589                                        reporter,
590                                        ctxInfo,
591                                        CtsEnforcement::kNever) {
592     auto dContext = ctxInfo.directContext();
593 
594     tiled_image_caching_test(dContext, /* recorder= */ nullptr, reporter);
595 }
596 
597 #endif // SK_GANESH
598 
599 #if defined(SK_GRAPHITE)
600 
601 // TODO(b/306005622): fix in SkQP and move to CtsEnforcement::kNextRelease
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(BigImageTest_Graphite,reporter,context,CtsEnforcement::kNever)602 DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(BigImageTest_Graphite,
603                                          reporter,
604                                          context,
605                                          CtsEnforcement::kNever) {
606     std::unique_ptr<skgpu::graphite::Recorder> recorder =
607             context->makeRecorder(ToolUtils::CreateTestingRecorderOptions());
608 
609     tiling_comparison_test(/* dContext= */ nullptr, recorder.get(), reporter);
610 }
611 
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(TiledDrawCacheTest_Graphite,reporter,context,CtsEnforcement::kApiLevel_V)612 DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(TiledDrawCacheTest_Graphite,
613                                          reporter,
614                                          context,
615                                          CtsEnforcement::kApiLevel_V) {
616     std::unique_ptr<skgpu::graphite::Recorder> recorder =
617             context->makeRecorder(ToolUtils::CreateTestingRecorderOptions());
618 
619     tiled_image_caching_test(/* dContext= */ nullptr, recorder.get(), reporter);
620 }
621 
622 #endif // SK_GRAPHITE
623