xref: /aosp_15_r20/external/skia/tests/graphite/ImageProviderTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2022 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 "tests/Test.h"
9 
10 #include "include/core/SkBitmap.h"
11 #include "include/core/SkColorSpace.h"
12 #include "include/core/SkImageGenerator.h"
13 #include "include/core/SkPicture.h"
14 #include "include/core/SkPictureRecorder.h"
15 #include "include/core/SkSpan.h"
16 #include "include/gpu/graphite/Context.h"
17 #include "include/gpu/graphite/Image.h"
18 #include "include/gpu/graphite/Recording.h"
19 #include "include/gpu/graphite/Surface.h"
20 #include "include/private/base/SkTo.h"
21 #include "src/core/SkMipmapBuilder.h"
22 #include "src/gpu/graphite/Caps.h"
23 #include "src/gpu/graphite/RecorderPriv.h"
24 #include "src/gpu/graphite/Surface_Graphite.h"
25 #include "src/image/SkImage_Base.h"
26 #include "tests/TestUtils.h"
27 #include "tools/ToolUtils.h"
28 #include "tools/graphite/GraphiteToolUtils.h"
29 
30 using namespace skgpu::graphite;
31 using Mipmapped = skgpu::Mipmapped;
32 
33 namespace {
34 
35 const SkISize kSurfaceSize = { 16, 16 };
36 const SkISize kImageSize = { 32, 32 };
37 
38 constexpr SkColor4f kBaseImageColor = SkColors::kYellow;
39 constexpr SkColor4f kFirstMipLevelColor = SkColors::kRed;
40 constexpr SkColor4f kBackgroundColor = SkColors::kBlue;
41 
create_and_attach_mipmaps(sk_sp<SkImage> img)42 sk_sp<SkImage> create_and_attach_mipmaps(sk_sp<SkImage> img) {
43     constexpr SkColor4f mipLevelColors[] = {
44             kFirstMipLevelColor,
45             SkColors::kGreen,
46             SkColors::kMagenta,
47             SkColors::kCyan,
48             SkColors::kWhite,
49     };
50 
51     SkMipmapBuilder builder(img->imageInfo());
52 
53     int count = builder.countLevels();
54 
55     SkASSERT_RELEASE(count == SkToInt(std::size(mipLevelColors)));
56 
57     for (int i = 0; i < count; ++i) {
58         SkPixmap pm = builder.level(i);
59         pm.erase(mipLevelColors[i]);
60     }
61 
62     return builder.attachTo(img);
63 }
64 
create_raster(Mipmapped mipmapped)65 sk_sp<SkImage> create_raster(Mipmapped mipmapped) {
66     SkImageInfo ii = SkImageInfo::Make(kImageSize.width(),
67                                        kImageSize.height(),
68                                        kRGBA_8888_SkColorType,
69                                        kPremul_SkAlphaType);
70     SkBitmap bm;
71     if (!bm.tryAllocPixels(ii)) {
72         return nullptr;
73     }
74 
75     bm.eraseColor(kBaseImageColor);
76 
77     sk_sp<SkImage> img = SkImages::RasterFromBitmap(bm);
78 
79     if (mipmapped == Mipmapped::kYes) {
80         img = create_and_attach_mipmaps(std::move(img));
81     }
82 
83     return img;
84 }
85 
86 /* 0 */
create_raster_backed_image_no_mipmaps(Recorder *)87 sk_sp<SkImage> create_raster_backed_image_no_mipmaps(Recorder*) {
88     return create_raster(Mipmapped::kNo);
89 }
90 
91 /* 1 */
create_raster_backed_image_with_mipmaps(Recorder *)92 sk_sp<SkImage> create_raster_backed_image_with_mipmaps(Recorder*) {
93     return create_raster(Mipmapped::kYes);
94 }
95 
96 /* 2 */
create_gpu_backed_image_no_mipmaps(Recorder * recorder)97 sk_sp<SkImage> create_gpu_backed_image_no_mipmaps(Recorder* recorder) {
98     sk_sp<SkImage> raster = create_raster(Mipmapped::kNo);
99     return SkImages::TextureFromImage(recorder, raster, {false});
100 }
101 
102 /* 3 */
create_gpu_backed_image_with_mipmaps(Recorder * recorder)103 sk_sp<SkImage> create_gpu_backed_image_with_mipmaps(Recorder* recorder) {
104     sk_sp<SkImage> raster = create_raster(Mipmapped::kYes);
105     return SkImages::TextureFromImage(recorder, raster, {true});
106 }
107 
108 /* 4 */
create_picture_backed_image(Recorder *)109 sk_sp<SkImage> create_picture_backed_image(Recorder*) {
110     SkIRect r = SkIRect::MakeWH(kImageSize.width(), kImageSize.height());
111     SkPaint paint;
112     paint.setColor(kBaseImageColor);
113 
114     SkPictureRecorder recorder;
115     SkCanvas* canvas = recorder.beginRecording(SkRect::Make(r));
116     canvas->drawIRect(r, paint);
117     sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
118 
119     return SkImages::DeferredFromPicture(std::move(picture),
120                                          r.size(),
121                                          /* matrix= */ nullptr,
122                                          /* paint= */ nullptr,
123                                          SkImages::BitDepth::kU8,
124                                          SkColorSpace::MakeSRGB());
125 }
126 
127 /* 5 */
create_bitmap_generator_backed_image(Recorder *)128 sk_sp<SkImage> create_bitmap_generator_backed_image(Recorder*) {
129 
130     class BitmapBackedGenerator final : public SkImageGenerator {
131     public:
132         BitmapBackedGenerator()
133                 : SkImageGenerator(SkImageInfo::Make(kImageSize.width(),
134                                                      kImageSize.height(),
135                                                      kRGBA_8888_SkColorType,
136                                                      kPremul_SkAlphaType)) {
137         }
138 
139         bool onGetPixels(const SkImageInfo& dstInfo,
140                          void* pixels,
141                          size_t rowBytes,
142                          const Options&) override {
143 
144             if (dstInfo.dimensions() != kImageSize) {
145                 return false;
146             }
147 
148             SkBitmap bm;
149             if (!bm.tryAllocPixels(dstInfo)) {
150                 return false;
151             }
152 
153             bm.eraseColor(kBaseImageColor);
154 
155             return bm.readPixels(dstInfo, pixels, rowBytes, 0, 0);
156         }
157     };
158 
159     std::unique_ptr<SkImageGenerator> gen(new BitmapBackedGenerator());
160 
161     return SkImages::DeferredFromGenerator(std::move(gen));
162 }
163 
check_img(skiatest::Reporter * reporter,Context * context,Recorder * recorder,SkImage * imageToDraw,Mipmapped mipmapped,const char * testcase,const SkColor4f & expectedColor)164 bool check_img(skiatest::Reporter* reporter,
165                Context* context,
166                Recorder* recorder,
167                SkImage* imageToDraw,
168                Mipmapped mipmapped,
169                const char* testcase,
170                const SkColor4f& expectedColor) {
171     SkImageInfo ii = SkImageInfo::Make(kSurfaceSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
172 
173     SkBitmap result;
174     result.allocPixels(ii);
175     SkPixmap pm;
176 
177     SkAssertResult(result.peekPixels(&pm));
178 
179     {
180         sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(recorder, ii);
181         if (!surface) {
182             ERRORF(reporter, "Surface creation failed");
183             return false;
184         }
185 
186         SkCanvas* canvas = surface->getCanvas();
187 
188         canvas->clear(kBackgroundColor);
189 
190         SkSamplingOptions sampling = (mipmapped == Mipmapped::kYes)
191                 ? SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNearest)
192                 : SkSamplingOptions(SkFilterMode::kLinear);
193 
194         canvas->drawImageRect(imageToDraw,
195                               SkRect::MakeWH(kSurfaceSize.width(), kSurfaceSize.height()),
196                               sampling);
197 
198         if (!surface->readPixels(pm, 0, 0)) {
199             ERRORF(reporter, "readPixels failed");
200             return false;
201         }
202     }
203 
204     auto error = std::function<ComparePixmapsErrorReporter>(
205             [&](int x, int y, const float diffs[4]) {
206                 ERRORF(reporter,
207                        "case %s %s: expected (%.1f %.1f %.1f %.1f) got (%.1f, %.1f, %.1f, %.1f)",
208                        testcase,
209                        (mipmapped == Mipmapped::kYes) ? "w/ mipmaps" : "w/o mipmaps",
210                        expectedColor.fR, expectedColor.fG, expectedColor.fB, expectedColor.fA,
211                        expectedColor.fR-diffs[0], expectedColor.fG-diffs[1],
212                        expectedColor.fB-diffs[2], expectedColor.fA-diffs[3]);
213             });
214     static constexpr float kTol[] = {0, 0, 0, 0};
215     CheckSolidPixels(expectedColor, pm, kTol, error);
216 
217     return true;
218 }
219 
220 using FactoryT = sk_sp<SkImage> (*)(Recorder*);
221 
222 struct TestCase {
223     const char* fTestCase;
224     FactoryT    fFactory;
225     SkColor4f   fExpectedColors[2];   /* [ w/o mipmaps, w/ mipmaps ] */
226 };
227 
run_test(skiatest::Reporter * reporter,Context * context,Recorder * recorder,SkSpan<const TestCase> testcases)228 void run_test(skiatest::Reporter* reporter,
229               Context* context,
230               Recorder* recorder,
231               SkSpan<const TestCase> testcases) {
232 
233     for (auto t : testcases) {
234         for (auto mm : { Mipmapped::kNo, Mipmapped::kYes }) {
235             sk_sp<SkImage> image = t.fFactory(recorder);
236 
237             check_img(reporter, context, recorder, image.get(), mm,
238                       t.fTestCase, t.fExpectedColors[static_cast<int>(mm)]);
239         }
240     }
241 }
242 
243 } // anonymous namespace
244 
245 // This test creates a bunch of solid yellow images in different ways and then draws them into a
246 // smaller surface (w/ src mode) that has been initialized to solid blue. When mipmap levels
247 // are possible to be specified the first mipmap level is made red. Thus, when mipmapping
248 // is allowed and it is specified as the sample mode, the drawn image will be red.
249 
250 // For the Default ImageProvider (which does _no_ caching and conversion) the expectations are:
251 //
252 //    0) raster-backed image w/o mipmaps
253 //                    drawn w/o mipmapping    --> dropped draw (blue)
254 //                    drawn w/ mipmapping     --> dropped draw (blue)
255 //
256 //    1) raster-backed image w/ mipmaps
257 //                    drawn w/o mipmapping    --> dropped draw (blue)
258 //                    drawn w/ mipmapping     --> dropped draw (blue)
259 //
260 //    2) Graphite-backed w/o mipmaps
261 //                    drawn w/o mipmapping    --> drawn (yellow)
262 //                    drawn w/ mipmapping     --> drawn (yellow) - mipmap filtering is dropped
263 //
264 //    3) Graphite-backed w/ mipmaps
265 //                    drawn w/o mipmapping    --> drawn (yellow)
266 //                    drawn w/ mipmapping     --> drawn (red)
267 //
268 //    4) picture-backed image
269 //                    drawn w/o mipmapping    --> dropped draw (blue)
270 //                    drawn w/ mipmapping     --> dropped draw (blue)
271 //
272 //    5) bitmap-backed-generator based image
273 //                    drawn w/o mipmapping    --> dropped draw (blue)
274 //                    drawn w/ mipmapping     --> dropped draw (blue)
275 //
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(ImageProviderTest_Graphite_Default,reporter,context,CtsEnforcement::kApiLevel_V)276 DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(ImageProviderTest_Graphite_Default, reporter, context,
277                                          CtsEnforcement::kApiLevel_V) {
278     TestCase testcases[] = {
279         { "0", create_raster_backed_image_no_mipmaps,   { kBackgroundColor, kBackgroundColor } },
280         { "1", create_raster_backed_image_with_mipmaps, { kBackgroundColor, kBackgroundColor } },
281         { "2", create_gpu_backed_image_no_mipmaps,      { kBaseImageColor,  kBaseImageColor } },
282         { "3", create_gpu_backed_image_with_mipmaps,    { kBaseImageColor,  kFirstMipLevelColor } },
283         { "4", create_picture_backed_image,             { kBackgroundColor, kBackgroundColor } },
284         { "5", create_bitmap_generator_backed_image,    { kBackgroundColor, kBackgroundColor }  },
285     };
286 
287     std::unique_ptr<Recorder> recorder = context->makeRecorder();
288 
289     run_test(reporter, context, recorder.get(), testcases);
290 }
291 
292 // For the Testing ImageProvider (which does some caching and conversion) the expectations are:
293 //
294 //    0) raster-backed image w/o mipmaps
295 //                    drawn w/o mipmapping    --> drawn (yellow) - auto-converted
296 //                    drawn w/ mipmapping     --> drawn (yellow) - auto-converted
297 //
298 //    1) raster-backed image w/ mipmaps
299 //                    drawn w/o mipmapping    --> drawn (yellow) - auto-converted
300 //                    drawn w/ mipmapping     --> drawn (red) - auto-converted
301 //
302 //    2) Graphite-backed w/o mipmaps
303 //                    drawn w/o mipmapping    --> drawn (yellow)
304 //                    drawn w/ mipmapping     --> drawn (yellow) - mipmap filtering is dropped
305 //
306 //    3) Graphite-backed w/ mipmaps
307 //                    drawn w/o mipmapping    --> drawn (yellow)
308 //                    drawn w/ mipmapping     --> drawn (red)
309 //
310 //    4) picture-backed image
311 //                    drawn w/o mipmapping    --> drawn (yellow) - auto-converted
312 //                    drawn w/ mipmapping     --> drawn (yellow) - mipmaps auto generated
313 //
314 //    5) bitmap-backed-generator based image
315 //                    drawn w/o mipmapping    --> drawn (yellow) - auto-converted
316 //                    drawn w/ mipmapping     --> drawn (yellow) - auto-converted
317 //
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(ImageProviderTest_Graphite_Testing,reporter,context,CtsEnforcement::kApiLevel_V)318 DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(ImageProviderTest_Graphite_Testing, reporter, context,
319                                          CtsEnforcement::kApiLevel_V) {
320     static const TestCase testcases[] = {
321         { "0", create_raster_backed_image_no_mipmaps,   { kBaseImageColor, kBaseImageColor } },
322         { "1", create_raster_backed_image_with_mipmaps, { kBaseImageColor, kFirstMipLevelColor } },
323         { "2", create_gpu_backed_image_no_mipmaps,      { kBaseImageColor, kBaseImageColor } },
324         { "3", create_gpu_backed_image_with_mipmaps,    { kBaseImageColor, kFirstMipLevelColor } },
325         { "4", create_picture_backed_image,             { kBaseImageColor, kBaseImageColor } },
326         { "5", create_bitmap_generator_backed_image,    { kBaseImageColor, kBaseImageColor } },
327     };
328 
329     RecorderOptions options = ToolUtils::CreateTestingRecorderOptions();
330     std::unique_ptr<skgpu::graphite::Recorder> recorder = context->makeRecorder(options);
331 
332     run_test(reporter, context, recorder.get(), testcases);
333 }
334 
335 // Here we're testing that the RequiredProperties parameter to makeTextureImage and makeSubset
336 // works as expected.
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(Make_TextureImage_Subset_Test,reporter,context,CtsEnforcement::kApiLevel_V)337 DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(Make_TextureImage_Subset_Test, reporter, context,
338                                          CtsEnforcement::kApiLevel_V) {
339     static const struct {
340         std::string name;
341         FactoryT fFactory;
342     } testcases[] = {
343         { "raster_no_mips",    create_raster_backed_image_no_mipmaps   },
344         { "raster_with_mips",  create_raster_backed_image_with_mipmaps },
345         { "texture_no_mips",   create_gpu_backed_image_no_mipmaps      },
346         { "texture_with_mips", create_gpu_backed_image_with_mipmaps    },
347         { "picture_backed",    create_picture_backed_image             },
348         { "image_generator",   create_bitmap_generator_backed_image    },
349     };
350 
351     const SkIRect kFakeSubset = SkIRect::MakeWH(kImageSize.width(), kImageSize.height());
352     const SkIRect kTrueSubset = kFakeSubset.makeInset(4, 4);
353 
354     std::unique_ptr<Recorder> recorderUP = context->makeRecorder();
355     auto recorder = recorderUP.get();
356 
357     for (const auto& test : testcases) {
358         sk_sp<SkImage> orig = test.fFactory(recorder);
359         skiatest::ReporterContext subtest(reporter, test.name);
360         for (bool mipmapped : {false, true}) {
361             skiatest::ReporterContext subtest2(reporter,
362                                                SkStringPrintf("mipmaps: %d", (int)mipmapped));
363             sk_sp<SkImage> i = SkImages::TextureFromImage(recorder, orig, {mipmapped});
364 
365             // makeTextureImage has an optimization which allows Mipmaps on an Image if it
366             // would take extra work to remove them.
367             bool mipmapOptAllowed = orig->hasMipmaps() && !mipmapped;
368 
369             REPORTER_ASSERT(reporter, i->isTextureBacked());
370             REPORTER_ASSERT(
371                     reporter,
372                     (i->hasMipmaps() == mipmapped) || (i->hasMipmaps() && mipmapOptAllowed));
373 
374             // SkImage::makeSubset should "leave an image where it is", that is, return a
375             // texture backed image iff the original image was texture backed. Otherwise,
376             // it will return a raster image.
377             i = orig->makeSubset(recorder, kTrueSubset, {mipmapped});
378             REPORTER_ASSERT(reporter, orig->isTextureBacked() == i->isTextureBacked(),
379                             "orig texture status %d != subset texture status %d",
380                             orig->isTextureBacked(), i->isTextureBacked());
381             if (i->isTextureBacked()) {
382                 REPORTER_ASSERT(reporter, i->dimensions() == kTrueSubset.size());
383                 REPORTER_ASSERT(reporter, i->hasMipmaps() == mipmapped);
384             }
385 
386             i = orig->makeSubset(recorder, kFakeSubset, {mipmapped});
387             REPORTER_ASSERT(reporter, orig->isTextureBacked() == i->isTextureBacked(),
388                             "orig texture status %d != subset texture status %d",
389                             orig->isTextureBacked(), i->isTextureBacked());
390             if (i->isTextureBacked()) {
391                 REPORTER_ASSERT(reporter, i->dimensions() == kFakeSubset.size());
392                 REPORTER_ASSERT(
393                         reporter,
394                         i->hasMipmaps() == mipmapped || (i->hasMipmaps() && mipmapOptAllowed));
395             }
396 
397             // SubsetTextureFrom should always return a texture-backed image
398             i = SkImages::SubsetTextureFrom(recorder, orig.get(), kTrueSubset, {mipmapped});
399             REPORTER_ASSERT(reporter, i->isTextureBacked());
400             REPORTER_ASSERT(reporter, i->dimensions() == kTrueSubset.size());
401             REPORTER_ASSERT(reporter, i->hasMipmaps() == mipmapped);
402 
403             if (!orig->isTextureBacked()) {
404                 i = SkImages::TextureFromImage(nullptr, orig, {mipmapped});
405                 REPORTER_ASSERT(reporter, !i);
406 
407                 // Make sure makeSubset w/o a recorder works as expected
408                 i = orig->makeSubset(nullptr, kTrueSubset, {mipmapped});
409                 REPORTER_ASSERT(reporter, !i->isTextureBacked());
410                 REPORTER_ASSERT(reporter, i->dimensions() == kTrueSubset.size());
411                 // Picture-backed images don't support mipmaps but check the other types.
412                 if (as_IB(i)->type() != SkImage_Base::Type::kLazyPicture) {
413                     REPORTER_ASSERT(reporter, i->hasMipmaps() == mipmapped);
414                 }
415 
416                 i = orig->makeSubset(nullptr, kFakeSubset, {mipmapped});
417                 REPORTER_ASSERT(reporter, !i->isTextureBacked());
418                 REPORTER_ASSERT(reporter, i->dimensions() == kFakeSubset.size());
419                 // Picture-backed images don't support mipmaps but check the other types.
420                 if (as_IB(i)->type() != SkImage_Base::Type::kLazyPicture) {
421                     REPORTER_ASSERT(reporter, i->hasMipmaps() == mipmapped);
422                 }
423             }
424         }
425     }
426 }
427 
428 namespace {
429 
pick_colortype(const Caps * caps,bool mipmapped)430 SkColorType pick_colortype(const Caps* caps, bool mipmapped) {
431     auto mm = mipmapped ? skgpu::Mipmapped::kYes : skgpu::Mipmapped::kNo;
432     TextureInfo info = caps->getDefaultSampledTextureInfo(
433             kRGB_565_SkColorType, mm, skgpu::Protected::kNo, skgpu::Renderable::kYes);
434     if (info.isValid()) {
435         return kRGB_565_SkColorType;
436     }
437 
438     info = caps->getDefaultSampledTextureInfo(
439             kRGBA_F16_SkColorType, mm, skgpu::Protected::kNo, skgpu::Renderable::kYes);
440     if (info.isValid()) {
441         return kRGBA_F16_SkColorType;
442     }
443 
444     return kUnknown_SkColorType;
445 }
446 
447 } // anonymous namespace
448 
449 // Here we're testing that the RequiredProperties parameter of:
450 //    SkImage::makeColorSpace and
451 //    SkImage::makeColorTypeAndColorSpace
452 // works as expected.
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(MakeColorSpace_Test,reporter,context,CtsEnforcement::kApiLevel_V)453 DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(MakeColorSpace_Test, reporter, context,
454                                          CtsEnforcement::kApiLevel_V) {
455     static const struct {
456         std::string name;
457         FactoryT fFactory;
458         bool     fTextureBacked;
459     } testcases[] = {
460             { "raster_no_mips",    create_raster_backed_image_no_mipmaps,   false },
461             { "raster_with_mips",  create_raster_backed_image_with_mipmaps, false },
462             { "texture_no_mips",   create_gpu_backed_image_no_mipmaps,      true  },
463             { "texture_with_mips", create_gpu_backed_image_with_mipmaps,    true  },
464             { "picture_backed",    create_picture_backed_image,             false },
465             { "image_generator",   create_bitmap_generator_backed_image,    false },
466     };
467 
468     sk_sp<SkColorSpace> spin = SkColorSpace::MakeSRGB()->makeColorSpin();
469 
470     std::unique_ptr<Recorder> recorder = context->makeRecorder();
471 
472     const Caps* caps = recorder->priv().caps();
473 
474     for (const auto& testcase : testcases) {
475         skiatest::ReporterContext subtest(reporter, testcase.name);
476         sk_sp<SkImage> orig = testcase.fFactory(recorder.get());
477 
478         SkASSERT(orig->colorType() == kRGBA_8888_SkColorType ||
479                  orig->colorType() == kBGRA_8888_SkColorType);
480         SkASSERT(!orig->colorSpace() || orig->colorSpace() == SkColorSpace::MakeSRGB().get());
481 
482         for (bool mipmapped : {false, true}) {
483             skiatest::ReporterContext subtest2(reporter,
484                                                SkStringPrintf("mipmaps: %d", (int)mipmapped));
485             sk_sp<SkImage> i = orig->makeColorSpace(recorder.get(), spin, {mipmapped});
486 
487             REPORTER_ASSERT(reporter, i != nullptr);
488             REPORTER_ASSERT(reporter, i->isTextureBacked() == testcase.fTextureBacked);
489             REPORTER_ASSERT(reporter, i->colorSpace() == spin.get());
490             if (testcase.fTextureBacked) {
491                 REPORTER_ASSERT(reporter, i->hasMipmaps() == mipmapped);
492             } else {
493                 REPORTER_ASSERT(reporter, !i->hasMipmaps());
494             }
495 
496             SkColorType altCT = pick_colortype(caps, mipmapped);
497             i = orig->makeColorTypeAndColorSpace(recorder.get(), altCT, spin, {mipmapped});
498 
499             REPORTER_ASSERT(reporter, i != nullptr);
500             REPORTER_ASSERT(reporter, i->isTextureBacked() == testcase.fTextureBacked);
501             REPORTER_ASSERT(reporter, i->colorType() == altCT);
502             REPORTER_ASSERT(reporter, i->colorSpace() == spin.get());
503             if (testcase.fTextureBacked) {
504                 REPORTER_ASSERT(reporter, i->hasMipmaps() == mipmapped);
505             } else {
506                 REPORTER_ASSERT(reporter, !i->hasMipmaps());
507             }
508         }
509     }
510 }
511