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