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