1 /*
2  * Copyright 2019 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/core/SkCanvas.h"
9 #include "include/core/SkSurface.h"
10 #include "include/core/SkSurfaceCharacterization.h"
11 #include "include/gpu/GrDirectContext.h"
12 #include "src/core/SkAutoPixmapStorage.h"
13 #include "src/gpu/GrDirectContextPriv.h"
14 #include "src/image/SkImage_Base.h"
15 #include "tests/Test.h"
16 #include "tests/TestUtils.h"
17 #include "tools/ToolUtils.h"
18 
19 #ifdef SK_GL
20 #include "src/gpu/gl/GrGLCaps.h"
21 #include "src/gpu/gl/GrGLDefines.h"
22 #include "src/gpu/gl/GrGLGpu.h"
23 #include "src/gpu/gl/GrGLUtil.h"
24 #endif
25 
26 #ifdef SK_METAL
27 #include "include/gpu/mtl/GrMtlTypes.h"
28 #include "src/gpu/mtl/GrMtlCppUtil.h"
29 #endif
30 
wait_on_backend_work_to_finish(GrDirectContext * dContext,bool * finishedCreate)31 static void wait_on_backend_work_to_finish(GrDirectContext* dContext, bool* finishedCreate) {
32     dContext->submit();
33     while (finishedCreate && !(*finishedCreate)) {
34         dContext->checkAsyncWorkCompletion();
35     }
36     if (finishedCreate) {
37         // The same boolean (pointed to by finishedCreate) is often used multiply and sequentially
38         // throughout our tests to create different backend textures.
39         // Reset it here so that it can be use to signal a future backend texture's creation
40         *finishedCreate = false;
41     }
42 }
43 
delete_backend_texture(GrDirectContext * dContext,const GrBackendTexture & backendTexture,bool * finishedCreate)44 static void delete_backend_texture(GrDirectContext* dContext,
45                                    const GrBackendTexture& backendTexture,
46                                    bool* finishedCreate) {
47     wait_on_backend_work_to_finish(dContext, finishedCreate);
48     dContext->deleteBackendTexture(backendTexture);
49 }
50 
mark_signaled(void * context)51 static void mark_signaled(void* context) {
52     *(bool*)context = true;
53 }
54 
55 // Test wrapping of GrBackendObjects in SkSurfaces and SkImages (non-static since used in Mtl test)
test_wrapping(GrDirectContext * dContext,skiatest::Reporter * reporter,std::function<GrBackendTexture (GrDirectContext *,GrMipmapped,GrRenderable)> create,GrColorType grColorType,GrMipmapped mipMapped,GrRenderable renderable,bool * finishedBECreate)56 void test_wrapping(GrDirectContext* dContext,
57                    skiatest::Reporter* reporter,
58                    std::function<GrBackendTexture (GrDirectContext*,
59                                                    GrMipmapped,
60                                                    GrRenderable)> create,
61                    GrColorType grColorType,
62                    GrMipmapped mipMapped,
63                    GrRenderable renderable,
64                    bool* finishedBECreate) {
65     GrResourceCache* cache = dContext->priv().getResourceCache();
66 
67     const int initialCount = cache->getResourceCount();
68 
69     GrBackendTexture backendTex = create(dContext, mipMapped, renderable);
70     if (!backendTex.isValid()) {
71         ERRORF(reporter, "Couldn't create backendTexture for grColorType %d renderable %s\n",
72                grColorType,
73                GrRenderable::kYes == renderable ? "yes" : "no");
74         return;
75     }
76 
77     // Skia proper should know nothing about the new backend object
78     REPORTER_ASSERT(reporter, initialCount == cache->getResourceCount());
79 
80     SkColorType skColorType = GrColorTypeToSkColorType(grColorType);
81 
82     // Wrapping a backendTexture in an image requires an SkColorType
83     if (kUnknown_SkColorType == skColorType) {
84         delete_backend_texture(dContext, backendTex, finishedBECreate);
85         return;
86     }
87 
88     if (GrRenderable::kYes == renderable && dContext->colorTypeSupportedAsSurface(skColorType)) {
89         sk_sp<SkSurface> surf = SkSurface::MakeFromBackendTexture(dContext,
90                                                                   backendTex,
91                                                                   kTopLeft_GrSurfaceOrigin,
92                                                                   0,
93                                                                   skColorType,
94                                                                   nullptr, nullptr);
95         if (!surf) {
96             ERRORF(reporter, "Couldn't make surface from backendTexture for %s\n",
97                    ToolUtils::colortype_name(skColorType));
98         } else {
99             REPORTER_ASSERT(reporter, initialCount+1 == cache->getResourceCount());
100         }
101     }
102 
103     {
104         sk_sp<SkImage> img = SkImage::MakeFromTexture(dContext,
105                                                       backendTex,
106                                                       kTopLeft_GrSurfaceOrigin,
107                                                       skColorType,
108                                                       kPremul_SkAlphaType,
109                                                       nullptr);
110         if (!img) {
111             ERRORF(reporter, "Couldn't make image from backendTexture for %s\n",
112                    ToolUtils::colortype_name(skColorType));
113         } else {
114             SkImage_Base* ib = as_IB(img);
115 
116             GrTextureProxy* proxy = ib->peekProxy();
117             REPORTER_ASSERT(reporter, proxy);
118 
119             REPORTER_ASSERT(reporter, mipMapped == proxy->proxyMipmapped());
120             REPORTER_ASSERT(reporter, proxy->isInstantiated());
121             REPORTER_ASSERT(reporter, mipMapped == proxy->mipmapped());
122 
123             REPORTER_ASSERT(reporter, initialCount+1 == cache->getResourceCount());
124         }
125     }
126 
127     REPORTER_ASSERT(reporter, initialCount == cache->getResourceCount());
128 
129     delete_backend_texture(dContext, backendTex, finishedBECreate);
130 }
131 
isBGRA8(const GrBackendFormat & format)132 static bool isBGRA8(const GrBackendFormat& format) {
133     switch (format.backend()) {
134         case GrBackendApi::kOpenGL:
135 #ifdef SK_GL
136             return format.asGLFormat() == GrGLFormat::kBGRA8;
137 #else
138             return false;
139 #endif
140         case GrBackendApi::kVulkan: {
141 #ifdef SK_VULKAN
142             VkFormat vkFormat;
143             format.asVkFormat(&vkFormat);
144             return vkFormat == VK_FORMAT_B8G8R8A8_UNORM;
145 #else
146             return false;
147 #endif
148         }
149         case GrBackendApi::kMetal:
150 #ifdef SK_METAL
151             return GrMtlFormatIsBGRA8(format.asMtlFormat());
152 #else
153             return false;
154 #endif
155         case GrBackendApi::kDirect3D:
156 #ifdef SK_DIRECT3D
157             return false; // TODO
158 #else
159             return false;
160 #endif
161         case GrBackendApi::kDawn:
162 #ifdef SK_DAWN
163             wgpu::TextureFormat dawnFormat;
164             format.asDawnFormat(&dawnFormat);
165             return dawnFormat == wgpu::TextureFormat::BGRA8Unorm;
166 #else
167             return false;
168 #endif
169         case GrBackendApi::kMock: {
170             SkImage::CompressionType compression = format.asMockCompressionType();
171             if (compression != SkImage::CompressionType::kNone) {
172                 return false; // No compressed formats are BGRA
173             }
174 
175             return format.asMockColorType() == GrColorType::kBGRA_8888;
176         }
177     }
178     SkUNREACHABLE;
179 }
180 
isRGB(const GrBackendFormat & format)181 static bool isRGB(const GrBackendFormat& format) {
182     switch (format.backend()) {
183         case GrBackendApi::kOpenGL:
184 #ifdef SK_GL
185             return format.asGLFormat() == GrGLFormat::kRGB8;
186 #else
187             return false;
188 #endif
189         case GrBackendApi::kVulkan: {
190 #ifdef SK_VULKAN
191             VkFormat vkFormat;
192             format.asVkFormat(&vkFormat);
193             return vkFormat == VK_FORMAT_R8G8B8_UNORM;
194 #else
195             return false;
196 #endif
197         }
198         case GrBackendApi::kMetal:
199             return false;  // Metal doesn't even pretend to support this
200         case GrBackendApi::kDirect3D:
201             return false;  // Not supported in Direct3D 12
202         case GrBackendApi::kDawn:
203             return false;
204         case GrBackendApi::kMock:
205             return false;  // No GrColorType::kRGB_888
206     }
207     SkUNREACHABLE;
208 }
209 
check_solid_pixmap(skiatest::Reporter * reporter,const SkColor4f & expected,const SkPixmap & actual,SkColorType ct,const char * label1,const char * label2)210 static void check_solid_pixmap(skiatest::Reporter* reporter,
211                                const SkColor4f& expected, const SkPixmap& actual,
212                                SkColorType ct, const char* label1, const char* label2) {
213     // we need 0.001f across the board just for noise
214     // we need 0.01f across the board for 1010102
215     const float tols[4] = { 0.01f, 0.01f, 0.01f, 0.01f };
216 
217     auto error = std::function<ComparePixmapsErrorReporter>(
218         [reporter, ct, label1, label2](int x, int y, const float diffs[4]) {
219             SkASSERT(x >= 0 && y >= 0);
220             ERRORF(reporter, "%s %s %s - mismatch at %d, %d (%f, %f, %f %f)",
221                    ToolUtils::colortype_name(ct), label1, label2, x, y,
222                    diffs[0], diffs[1], diffs[2], diffs[3]);
223         });
224 
225     CheckSolidPixels(expected, actual, tols, error);
226 }
227 
228 // What would raster do?
get_expected_color(SkColor4f orig,SkColorType ct)229 static SkColor4f get_expected_color(SkColor4f orig, SkColorType ct) {
230     SkAlphaType at = SkColorTypeIsAlwaysOpaque(ct) ? kOpaque_SkAlphaType
231                                                    : kPremul_SkAlphaType;
232 
233     SkImageInfo ii = SkImageInfo::Make(2, 2, ct, at);
234     SkAutoPixmapStorage pm;
235     pm.alloc(ii);
236     pm.erase(orig);
237     SkColor tmp = pm.getColor(0, 0);
238     return SkColor4f::FromColor(tmp);
239 }
240 
241 static void check_mipmaps(GrDirectContext*, const GrBackendTexture&,
242                           SkColorType, const SkColor4f expectedColors[6],
243                           skiatest::Reporter*, const char* label);
244 
check_base_readbacks(GrDirectContext * dContext,const GrBackendTexture & backendTex,SkColorType skColorType,GrRenderable renderable,const SkColor4f & color,skiatest::Reporter * reporter,const char * label)245 static void check_base_readbacks(GrDirectContext* dContext, const GrBackendTexture& backendTex,
246                                  SkColorType skColorType, GrRenderable renderable,
247                                  const SkColor4f& color, skiatest::Reporter* reporter,
248                                  const char* label) {
249     if (isRGB(backendTex.getBackendFormat())) {
250         // readPixels is busted for the RGB backend format (skbug.com/8862)
251         // TODO: add a GrColorType::kRGB_888 to fix the situation
252         return;
253     }
254 
255     SkAlphaType at = SkColorTypeIsAlwaysOpaque(skColorType) ? kOpaque_SkAlphaType
256                                                             : kPremul_SkAlphaType;
257 
258     SkColor4f expectedColor = get_expected_color(color, skColorType);
259 
260     SkAutoPixmapStorage actual;
261 
262     {
263         SkImageInfo readBackII = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType,
264                                                    kUnpremul_SkAlphaType);
265 
266         SkAssertResult(actual.tryAlloc(readBackII));
267     }
268 
269     {
270         sk_sp<SkImage> img = SkImage::MakeFromTexture(dContext,
271                                                       backendTex,
272                                                       kTopLeft_GrSurfaceOrigin,
273                                                       skColorType,
274                                                       at,
275                                                       nullptr);
276         if (img) {
277             actual.erase(SkColors::kTransparent);
278             bool result = img->readPixels(dContext, actual, 0, 0);
279             if (!result) {
280                 // TODO: we need a better way to tell a priori if readPixels will work for an
281                 // arbitrary colorType
282 #if 0
283                 ERRORF(reporter, "Couldn't readback from SkImage for colorType: %d\n", colorType);
284 #endif
285             } else {
286                 check_solid_pixmap(reporter, expectedColor, actual, skColorType,
287                                    label, "SkImage::readPixels");
288             }
289         }
290     }
291 
292     // This will mark any mipmaps as dirty (bc that is what we do when we wrap a renderable
293     // backend texture) so it must be done last!
294     if (GrRenderable::kYes == renderable && dContext->colorTypeSupportedAsSurface(skColorType)) {
295         sk_sp<SkSurface> surf = SkSurface::MakeFromBackendTexture(dContext,
296                                                                   backendTex,
297                                                                   kTopLeft_GrSurfaceOrigin,
298                                                                   0,
299                                                                   skColorType,
300                                                                   nullptr, nullptr);
301         if (surf) {
302             actual.erase(SkColors::kTransparent);
303             bool result = surf->readPixels(actual, 0, 0);
304             REPORTER_ASSERT(reporter, result);
305 
306             check_solid_pixmap(reporter, expectedColor, actual, skColorType,
307                                label, "SkSurface::readPixels");
308         }
309     }
310 }
311 
312 // Test initialization of GrBackendObjects to a specific color (non-static since used in Mtl test)
test_color_init(GrDirectContext * dContext,skiatest::Reporter * reporter,std::function<GrBackendTexture (GrDirectContext *,const SkColor4f &,GrMipmapped,GrRenderable)> create,GrColorType grColorType,const SkColor4f & color,GrMipmapped mipMapped,GrRenderable renderable,bool * finishedBECreate)313 void test_color_init(GrDirectContext* dContext,
314                      skiatest::Reporter* reporter,
315                      std::function<GrBackendTexture (GrDirectContext*,
316                                                      const SkColor4f&,
317                                                      GrMipmapped,
318                                                      GrRenderable)> create,
319                      GrColorType grColorType,
320                      const SkColor4f& color,
321                      GrMipmapped mipMapped,
322                      GrRenderable renderable,
323                      bool* finishedBECreate) {
324     GrBackendTexture backendTex = create(dContext, color, mipMapped, renderable);
325     if (!backendTex.isValid()) {
326         // errors here should be reported by the test_wrapping test
327         return;
328     }
329 
330     SkColorType skColorType = GrColorTypeToSkColorType(grColorType);
331 
332     // Can't wrap backend textures in images and surfaces w/o an SkColorType
333     if (kUnknown_SkColorType == skColorType) {
334         // TODO: burrow in and scrappily check that data was uploaded!
335         delete_backend_texture(dContext, backendTex, finishedBECreate);
336         return;
337     }
338 
339     auto checkBackendTexture = [&](const SkColor4f& testColor) {
340         if (mipMapped == GrMipmapped::kYes) {
341             SkColor4f expectedColor = get_expected_color(testColor, skColorType);
342             SkColor4f expectedColors[6] = {expectedColor, expectedColor, expectedColor,
343                                            expectedColor, expectedColor, expectedColor};
344             check_mipmaps(dContext, backendTex, skColorType, expectedColors,
345                           reporter, "colorinit");
346         }
347 
348         // The last step in this test will dirty the mipmaps so do it last
349         check_base_readbacks(dContext, backendTex, skColorType, renderable, testColor,
350                              reporter, "colorinit");
351     };
352 
353     checkBackendTexture(color);
354 
355     // Make sure the initial create work has finished so we can test the update independently.
356     wait_on_backend_work_to_finish(dContext, finishedBECreate);
357 
358     SkColor4f newColor = {color.fB , color.fR, color.fG, color.fA };
359 
360     dContext->updateBackendTexture(backendTex, skColorType, newColor, mark_signaled,
361                                    finishedBECreate);
362 
363     checkBackendTexture(newColor);
364 
365     delete_backend_texture(dContext, backendTex, finishedBECreate);
366 }
367 
368 // Draw the backend texture (wrapped in an SkImage) into an RGBA surface, attempting to access
369 // all the mipMap levels.
check_mipmaps(GrDirectContext * dContext,const GrBackendTexture & backendTex,SkColorType skColorType,const SkColor4f expectedColors[6],skiatest::Reporter * reporter,const char * label)370 static void check_mipmaps(GrDirectContext* dContext, const GrBackendTexture& backendTex,
371                           SkColorType skColorType, const SkColor4f expectedColors[6],
372                           skiatest::Reporter* reporter, const char* label) {
373 
374 #ifdef SK_GL
375     // skbug.com/9141 (RGBA_F32 mipmaps appear to be broken on some Mali devices)
376     if (GrBackendApi::kOpenGL == dContext->backend()) {
377         GrGLGpu* glGPU = static_cast<GrGLGpu*>(dContext->priv().getGpu());
378 
379         if (kRGBA_F32_SkColorType == skColorType &&
380             kGLES_GrGLStandard == glGPU->ctxInfo().standard()) {
381             return;
382         }
383     }
384 #endif
385 
386     if (isRGB(backendTex.getBackendFormat())) {
387         // readPixels is busted for the RGB backend format (skbug.com/8862)
388         // TODO: add a GrColorType::kRGB_888 to fix the situation
389         return;
390     }
391 
392     SkAlphaType at = SkColorTypeIsAlwaysOpaque(skColorType) ? kOpaque_SkAlphaType
393                                                             : kPremul_SkAlphaType;
394 
395     sk_sp<SkImage> img = SkImage::MakeFromTexture(dContext,
396                                                   backendTex,
397                                                   kTopLeft_GrSurfaceOrigin,
398                                                   skColorType,
399                                                   at,
400                                                   nullptr);
401     if (!img) {
402         return;
403     }
404 
405     SkImageInfo readbackSurfaceII = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType,
406                                                       kPremul_SkAlphaType);
407 
408     sk_sp<SkSurface> surf = SkSurface::MakeRenderTarget(dContext,
409                                                         SkBudgeted::kNo,
410                                                         readbackSurfaceII, 1,
411                                                         kTopLeft_GrSurfaceOrigin,
412                                                         nullptr);
413     if (!surf) {
414         return;
415     }
416 
417     SkCanvas* canvas = surf->getCanvas();
418 
419     SkPaint p;
420     p.setFilterQuality(kHigh_SkFilterQuality);
421 
422     int numMipLevels = 6;
423 
424     for (int i = 0, rectSize = 32; i < numMipLevels; ++i, rectSize /= 2) {
425         SkASSERT(rectSize >= 1);
426 
427         SkRect r = SkRect::MakeWH(rectSize, rectSize);
428         canvas->clear(SK_ColorTRANSPARENT);
429         canvas->drawImageRect(img, r, &p);
430 
431         SkImageInfo readbackII = SkImageInfo::Make(rectSize, rectSize,
432                                                    kRGBA_8888_SkColorType,
433                                                    kUnpremul_SkAlphaType);
434         SkAutoPixmapStorage actual2;
435         SkAssertResult(actual2.tryAlloc(readbackII));
436         actual2.erase(SkColors::kTransparent);
437 
438         bool result = surf->readPixels(actual2, 0, 0);
439         REPORTER_ASSERT(reporter, result);
440 
441         SkString str;
442         str.appendf("mip-level %d", i);
443 
444         check_solid_pixmap(reporter, expectedColors[i], actual2, skColorType,
445                            label, str.c_str());
446     }
447 }
448 
make_pixmaps(SkColorType skColorType,GrMipmapped mipMapped,const SkColor4f colors[6],SkAutoPixmapStorage pixmaps[6])449 static int make_pixmaps(SkColorType skColorType, GrMipmapped mipMapped,
450                         const SkColor4f colors[6], SkAutoPixmapStorage pixmaps[6]) {
451     int levelSize = 32;
452     int numMipLevels = mipMapped == GrMipmapped::kYes ? 6 : 1;
453     SkAlphaType at = SkColorTypeIsAlwaysOpaque(skColorType) ? kOpaque_SkAlphaType
454                                                             : kPremul_SkAlphaType;
455     for (int level = 0; level < numMipLevels; ++level) {
456         SkImageInfo ii = SkImageInfo::Make(levelSize, levelSize, skColorType, at);
457         pixmaps[level].alloc(ii);
458         pixmaps[level].erase(colors[level]);
459         levelSize /= 2;
460     }
461     return numMipLevels;
462 }
463 
464 // Test initialization of GrBackendObjects using SkPixmaps
test_pixmap_init(GrDirectContext * dContext,skiatest::Reporter * reporter,std::function<GrBackendTexture (GrDirectContext *,const SkPixmap srcData[],int numLevels,GrRenderable)> create,SkColorType skColorType,GrMipmapped mipMapped,GrRenderable renderable,bool * finishedBECreate)465 static void test_pixmap_init(GrDirectContext* dContext,
466                              skiatest::Reporter* reporter,
467                              std::function<GrBackendTexture (GrDirectContext*,
468                                                              const SkPixmap srcData[],
469                                                              int numLevels,
470                                                              GrRenderable)> create,
471                              SkColorType skColorType,
472                              GrMipmapped mipMapped,
473                              GrRenderable renderable,
474                              bool* finishedBECreate) {
475     SkAutoPixmapStorage pixmapMem[6];
476     SkColor4f colors[6] = {
477         { 1.0f, 0.0f, 0.0f, 1.0f }, // R
478         { 0.0f, 1.0f, 0.0f, 0.9f }, // G
479         { 0.0f, 0.0f, 1.0f, 0.7f }, // B
480         { 0.0f, 1.0f, 1.0f, 0.5f }, // C
481         { 1.0f, 0.0f, 1.0f, 0.3f }, // M
482         { 1.0f, 1.0f, 0.0f, 0.2f }, // Y
483     };
484 
485     int numMipLevels = make_pixmaps(skColorType, mipMapped, colors, pixmapMem);
486     SkASSERT(numMipLevels);
487 
488     // TODO: this is tedious. Should we pass in an array of SkBitmaps instead?
489     SkPixmap pixmaps[6];
490     for (int i = 0; i < numMipLevels; ++i) {
491         pixmaps[i].reset(pixmapMem[i].info(), pixmapMem[i].addr(), pixmapMem[i].rowBytes());
492     }
493 
494     GrBackendTexture backendTex = create(dContext, pixmaps, numMipLevels, renderable);
495     if (!backendTex.isValid()) {
496         // errors here should be reported by the test_wrapping test
497         return;
498     }
499 
500     if (skColorType == kBGRA_8888_SkColorType && !isBGRA8(backendTex.getBackendFormat())) {
501         // When kBGRA is backed by an RGBA something goes wrong in the swizzling
502         delete_backend_texture(dContext, backendTex, finishedBECreate);
503         return;
504     }
505 
506     auto checkBackendTexture = [&](SkColor4f colors[6]) {
507         if (mipMapped == GrMipmapped::kYes) {
508             SkColor4f expectedColors[6] = {
509                     get_expected_color(colors[0], skColorType),
510                     get_expected_color(colors[1], skColorType),
511                     get_expected_color(colors[2], skColorType),
512                     get_expected_color(colors[3], skColorType),
513                     get_expected_color(colors[4], skColorType),
514                     get_expected_color(colors[5], skColorType),
515             };
516 
517             check_mipmaps(dContext, backendTex, skColorType, expectedColors, reporter, "pixmap");
518         }
519 
520         // The last step in this test will dirty the mipmaps so do it last
521         check_base_readbacks(dContext, backendTex, skColorType, renderable, colors[0], reporter,
522                              "pixmap");
523     };
524 
525     checkBackendTexture(colors);
526 
527     // Make sure the initial create work has finished so we can test the update independently.
528     wait_on_backend_work_to_finish(dContext, finishedBECreate);
529 
530     SkColor4f colorsNew[6] = {
531         {1.0f, 1.0f, 0.0f, 0.2f},  // Y
532         {1.0f, 0.0f, 0.0f, 1.0f},  // R
533         {0.0f, 1.0f, 0.0f, 0.9f},  // G
534         {0.0f, 0.0f, 1.0f, 0.7f},  // B
535         {0.0f, 1.0f, 1.0f, 0.5f},  // C
536         {1.0f, 0.0f, 1.0f, 0.3f},  // M
537     };
538     make_pixmaps(skColorType, mipMapped, colorsNew, pixmapMem);
539     for (int i = 0; i < numMipLevels; ++i) {
540         pixmaps[i].reset(pixmapMem[i].info(), pixmapMem[i].addr(), pixmapMem[i].rowBytes());
541     }
542 
543     // Upload new data and make sure everything still works
544     dContext->updateBackendTexture(backendTex, pixmaps, numMipLevels, mark_signaled,
545                                    finishedBECreate);
546 
547     checkBackendTexture(colorsNew);
548 
549     delete_backend_texture(dContext, backendTex, finishedBECreate);
550 }
551 
552 enum class VkLayout {
553     kUndefined,
554     kReadOnlyOptimal,
555 };
556 
check_vk_layout(const GrBackendTexture & backendTex,VkLayout layout)557 void check_vk_layout(const GrBackendTexture& backendTex, VkLayout layout) {
558 #if defined(SK_VULKAN) && defined(SK_DEBUG)
559     VkImageLayout expected;
560 
561     switch (layout) {
562         case VkLayout::kUndefined:
563             expected = VK_IMAGE_LAYOUT_UNDEFINED;
564             break;
565         case VkLayout::kReadOnlyOptimal:
566             expected = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
567             break;
568         default:
569             SkUNREACHABLE;
570     }
571 
572     GrVkImageInfo vkII;
573 
574     if (backendTex.getVkImageInfo(&vkII)) {
575         SkASSERT(expected == vkII.fImageLayout);
576         SkASSERT(VK_IMAGE_TILING_OPTIMAL == vkII.fImageTiling);
577     }
578 #endif
579 }
580 
581 ///////////////////////////////////////////////////////////////////////////////
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ColorTypeBackendAllocationTest,reporter,ctxInfo)582 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ColorTypeBackendAllocationTest, reporter, ctxInfo) {
583     auto context = ctxInfo.directContext();
584     const GrCaps* caps = context->priv().caps();
585 
586     constexpr SkColor4f kTransCol { 0, 0.25f, 0.75f, 0.5f };
587     constexpr SkColor4f kGrayCol { 0.75f, 0.75f, 0.75f, 0.75f };
588 
589     struct {
590         SkColorType   fColorType;
591         SkColor4f     fColor;
592     } combinations[] = {
593         { kAlpha_8_SkColorType,           kTransCol                },
594         { kRGB_565_SkColorType,           SkColors::kRed           },
595         { kARGB_4444_SkColorType,         SkColors::kGreen         },
596         { kRGBA_8888_SkColorType,         SkColors::kBlue          },
597         { kRGB_888x_SkColorType,          SkColors::kCyan          },
598         // TODO: readback is busted when alpha = 0.5f (perhaps premul vs. unpremul)
599         { kBGRA_8888_SkColorType,         { 1, 0, 0, 1.0f }        },
600         // TODO: readback is busted for *10A2 when alpha = 0.5f (perhaps premul vs. unpremul)
601         { kRGBA_1010102_SkColorType,      { 0.25f, 0.5f, 0.75f, 1.0f }},
602         { kBGRA_1010102_SkColorType,      { 0.25f, 0.5f, 0.75f, 1.0f }},
603         // RGB/BGR 101010x have no Ganesh correlate
604         { kRGB_101010x_SkColorType,       { 0, 0.5f, 0, 0.5f }     },
605         { kBGR_101010x_SkColorType,       { 0, 0.5f, 0, 0.5f }     },
606         { kGray_8_SkColorType,            kGrayCol                 },
607         { kRGBA_F16Norm_SkColorType,      SkColors::kLtGray        },
608         { kRGBA_F16_SkColorType,          SkColors::kYellow        },
609         { kRGBA_F32_SkColorType,          SkColors::kGray          },
610         { kR8G8_unorm_SkColorType,        { .25f, .75f, 0, 1 }     },
611         { kR16G16_unorm_SkColorType,      SkColors::kGreen         },
612         { kA16_unorm_SkColorType,         kTransCol                },
613         { kA16_float_SkColorType,         kTransCol                },
614         { kR16G16_float_SkColorType,      { .25f, .75f, 0, 1 }     },
615         { kR16G16B16A16_unorm_SkColorType,{ .25f, .5f, .75f, 1 }   },
616     };
617 
618     static_assert(kLastEnum_SkColorType == SK_ARRAY_COUNT(combinations));
619 
620     for (auto combo : combinations) {
621         SkColorType colorType = combo.fColorType;
622 
623         if (GrBackendApi::kMetal == context->backend()) {
624             // skbug.com/9086 (Metal caps may not be handling RGBA32 correctly)
625             if (kRGBA_F32_SkColorType == combo.fColorType) {
626                 continue;
627             }
628         }
629 
630         for (auto mipMapped : { GrMipmapped::kNo, GrMipmapped::kYes }) {
631             if (GrMipmapped::kYes == mipMapped && !caps->mipmapSupport()) {
632                 continue;
633             }
634 
635             for (auto renderable : { GrRenderable::kNo, GrRenderable::kYes }) {
636                 if (!caps->getDefaultBackendFormat(SkColorTypeToGrColorType(colorType),
637                                                    renderable).isValid()) {
638                     continue;
639                 }
640 
641                 if (GrRenderable::kYes == renderable) {
642                     if (kRGB_888x_SkColorType == combo.fColorType) {
643                         // Ganesh can't perform the blends correctly when rendering this format
644                         continue;
645                     }
646                 }
647 
648                 {
649                     auto uninitCreateMtd = [colorType](GrDirectContext* dContext,
650                                                        GrMipmapped mipMapped,
651                                                        GrRenderable renderable) {
652                         auto result = dContext->createBackendTexture(32, 32, colorType,
653                                                                      mipMapped, renderable,
654                                                                      GrProtected::kNo);
655                         check_vk_layout(result, VkLayout::kUndefined);
656 
657 #ifdef SK_DEBUG
658                         {
659                             GrBackendFormat format = dContext->defaultBackendFormat(colorType,
660                                                                                     renderable);
661                             SkASSERT(format == result.getBackendFormat());
662                         }
663 #endif
664 
665                         return result;
666                     };
667 
668                     test_wrapping(context, reporter, uninitCreateMtd,
669                                   SkColorTypeToGrColorType(colorType), mipMapped, renderable,
670                                   nullptr);
671                 }
672 
673                 bool finishedBackendCreation = false;
674                 bool* finishedPtr = &finishedBackendCreation;
675 
676                 {
677 
678                     auto createWithColorMtd = [colorType, finishedPtr](GrDirectContext* dContext,
679                                                                        const SkColor4f& color,
680                                                                        GrMipmapped mipMapped,
681                                                                        GrRenderable renderable) {
682                         auto result = dContext->createBackendTexture(32, 32, colorType, color,
683                                                                      mipMapped, renderable,
684                                                                      GrProtected::kNo,
685                                                                      mark_signaled, finishedPtr);
686                         check_vk_layout(result, VkLayout::kReadOnlyOptimal);
687 
688 #ifdef SK_DEBUG
689                         {
690                             GrBackendFormat format = dContext->defaultBackendFormat(colorType,
691                                                                                    renderable);
692                             SkASSERT(format == result.getBackendFormat());
693                         }
694 #endif
695 
696                         return result;
697                     };
698                     // We make our comparison color using SkPixmap::erase(color) on a pixmap of
699                     // combo.fColorType and then calling SkPixmap::readPixels(). erase() will premul
700                     // the color passed to it. However, createBackendTexture() that takes a
701                     // SkColor4f is color type / alpha type unaware and will simply compute
702                     // luminance from the r, g, b, channels.
703                     SkColor4f color = combo.fColor;
704                     if (colorType == kGray_8_SkColorType) {
705                         color = {color.fR * color.fA,
706                                  color.fG * color.fA,
707                                  color.fB * color.fA,
708                                  1.f};
709                     }
710                     test_color_init(context, reporter, createWithColorMtd,
711                                     SkColorTypeToGrColorType(colorType), color, mipMapped,
712                                     renderable, finishedPtr);
713                 }
714 
715                 {
716                     auto createWithSrcDataMtd = [finishedPtr](GrDirectContext* dContext,
717                                                               const SkPixmap srcData[],
718                                                               int numLevels,
719                                                               GrRenderable renderable) {
720                         SkASSERT(srcData && numLevels);
721                         auto result = dContext->createBackendTexture(srcData, numLevels, renderable,
722                                                                      GrProtected::kNo, mark_signaled,
723                                                                      finishedPtr);
724                         check_vk_layout(result, VkLayout::kReadOnlyOptimal);
725 #ifdef SK_DEBUG
726                         {
727                             auto format = dContext->defaultBackendFormat(srcData[0].colorType(),
728                                                                          renderable);
729                             SkASSERT(format == result.getBackendFormat());
730                         }
731 #endif
732                         return result;
733                     };
734 
735                     test_pixmap_init(context, reporter, createWithSrcDataMtd, colorType, mipMapped,
736                                      renderable, finishedPtr);
737                 }
738             }
739         }
740     }
741 }
742 
743 ///////////////////////////////////////////////////////////////////////////////
744 #ifdef SK_GL
745 
DEF_GPUTEST_FOR_ALL_GL_CONTEXTS(GLBackendAllocationTest,reporter,ctxInfo)746 DEF_GPUTEST_FOR_ALL_GL_CONTEXTS(GLBackendAllocationTest, reporter, ctxInfo) {
747     sk_gpu_test::GLTestContext* glCtx = ctxInfo.glContext();
748     GrGLStandard standard = glCtx->gl()->fStandard;
749     auto context = ctxInfo.directContext();
750     const GrGLCaps* glCaps = static_cast<const GrGLCaps*>(context->priv().caps());
751 
752     constexpr SkColor4f kTransCol { 0, 0.25f, 0.75f, 0.5f };
753     constexpr SkColor4f kGrayCol { 0.75f, 0.75f, 0.75f, 0.75f };
754 
755     struct {
756         GrColorType   fColorType;
757         GrGLenum      fFormat;
758         SkColor4f     fColor;
759     } combinations[] = {
760         { GrColorType::kRGBA_8888,        GR_GL_RGBA8,                SkColors::kRed       },
761         { GrColorType::kRGBA_8888_SRGB,   GR_GL_SRGB8_ALPHA8,         SkColors::kRed       },
762 
763         { GrColorType::kRGB_888x,         GR_GL_RGBA8,                SkColors::kYellow    },
764         { GrColorType::kRGB_888x,         GR_GL_RGB8,                 SkColors::kCyan      },
765 
766         { GrColorType::kBGRA_8888,        GR_GL_RGBA8,                SkColors::kBlue      },
767         { GrColorType::kBGRA_8888,        GR_GL_BGRA8,                SkColors::kBlue      },
768         // TODO: readback is busted when alpha = 0.5f (perhaps premul vs. unpremul)
769         { GrColorType::kRGBA_1010102,     GR_GL_RGB10_A2,             { 0.25f, 0.5f, 0.75f, 1.f }},
770         { GrColorType::kBGRA_1010102,     GR_GL_RGB10_A2,             { 0.25f, 0.5f, 0.75f, 1.f }},
771         { GrColorType::kBGR_565,          GR_GL_RGB565,               SkColors::kRed       },
772         { GrColorType::kABGR_4444,        GR_GL_RGBA4,                SkColors::kGreen     },
773 
774         { GrColorType::kAlpha_8,          GR_GL_ALPHA8,               kTransCol            },
775         { GrColorType::kAlpha_8,          GR_GL_R8,                   kTransCol            },
776 
777         { GrColorType::kGray_8,           GR_GL_LUMINANCE8,           kGrayCol             },
778         { GrColorType::kGray_8,           GR_GL_R8,                   kGrayCol             },
779 
780         { GrColorType::kRGBA_F32,         GR_GL_RGBA32F,              SkColors::kRed       },
781 
782         { GrColorType::kRGBA_F16_Clamped, GR_GL_RGBA16F,              SkColors::kLtGray    },
783         { GrColorType::kRGBA_F16,         GR_GL_RGBA16F,              SkColors::kYellow    },
784 
785         { GrColorType::kRG_88,            GR_GL_RG8,                  { 1, 0.5f, 0, 1 }    },
786         { GrColorType::kAlpha_F16,        GR_GL_R16F,                 { 1.0f, 0, 0, 0.5f } },
787         { GrColorType::kAlpha_F16,        GR_GL_LUMINANCE16F,         kGrayCol             },
788 
789         { GrColorType::kAlpha_16,         GR_GL_R16,                  kTransCol            },
790         { GrColorType::kRG_1616,          GR_GL_RG16,                 SkColors::kYellow    },
791 
792         { GrColorType::kRGBA_16161616,    GR_GL_RGBA16,               SkColors::kLtGray    },
793         { GrColorType::kRG_F16,           GR_GL_RG16F,                SkColors::kYellow    },
794     };
795 
796     for (auto combo : combinations) {
797         for (GrGLenum target : {GR_GL_TEXTURE_2D, GR_GL_TEXTURE_RECTANGLE}) {
798             GrBackendFormat format = GrBackendFormat::MakeGL(combo.fFormat, target);
799 
800             if (!glCaps->isFormatTexturable(format)) {
801                 continue;
802             }
803 
804             if (GrColorType::kBGRA_8888 == combo.fColorType ||
805                 GrColorType::kBGRA_1010102 == combo.fColorType) {
806                 // We allow using a GL_RGBA8 or GR_GL_RGB10_A2 texture as BGRA on desktop GL but not
807                 // ES
808                 if (kGL_GrGLStandard != standard &&
809                     (GR_GL_RGBA8 == combo.fFormat || GR_GL_RGB10_A2 == combo.fFormat)) {
810                     continue;
811                 }
812             }
813 
814             for (auto mipMapped : {GrMipmapped::kNo, GrMipmapped::kYes}) {
815                 if (GrMipmapped::kYes == mipMapped &&
816                     (!glCaps->mipmapSupport() || target == GR_GL_TEXTURE_RECTANGLE)) {
817                     continue;
818                 }
819 
820                 for (auto renderable : {GrRenderable::kNo, GrRenderable::kYes}) {
821                     if (GrRenderable::kYes == renderable) {
822                         if (!glCaps->isFormatAsColorTypeRenderable(combo.fColorType, format)) {
823                             continue;
824                         }
825                     }
826 
827                     {
828                         auto uninitCreateMtd = [format](GrDirectContext* dContext,
829                                                         GrMipmapped mipMapped,
830                                                         GrRenderable renderable) {
831                             return dContext->createBackendTexture(32, 32, format, mipMapped,
832                                                                   renderable, GrProtected::kNo);
833                         };
834 
835                         test_wrapping(context, reporter, uninitCreateMtd, combo.fColorType,
836                                       mipMapped, renderable, nullptr);
837                     }
838 
839                     {
840                         // We're creating backend textures without specifying a color type "view" of
841                         // them at the public API level. Therefore, Ganesh will not apply any
842                         // swizzles before writing the color to the texture. However, our validation
843                         // code does rely on interpreting the texture contents via a SkColorType and
844                         // therefore swizzles may be applied during the read step. Ideally we'd
845                         // update our validation code to use a "raw" read that doesn't impose a
846                         // color type but for now we just munge the data we upload to match the
847                         // expectation.
848                         GrSwizzle swizzle;
849                         switch (combo.fColorType) {
850                             case GrColorType::kAlpha_8:
851                                 swizzle = GrSwizzle("aaaa");
852                                 break;
853                             case GrColorType::kAlpha_16:
854                                 swizzle = GrSwizzle("aaaa");
855                                 break;
856                             case GrColorType::kAlpha_F16:
857                                 swizzle = GrSwizzle("aaaa");
858                                 break;
859                             default:
860                                 break;
861                         }
862 
863                         bool finishedBackendCreation = false;
864                         bool* finishedPtr = &finishedBackendCreation;
865 
866                         auto createWithColorMtd = [format, swizzle, finishedPtr](
867                                                           GrDirectContext* dContext,
868                                                           const SkColor4f& color,
869                                                           GrMipmapped mipMapped,
870                                                           GrRenderable renderable) {
871                             auto swizzledColor = swizzle.applyTo(color);
872                             return dContext->createBackendTexture(
873                                     32, 32, format, swizzledColor, mipMapped, renderable,
874                                     GrProtected::kNo, mark_signaled, finishedPtr);
875                         };
876                         // We make our comparison color using SkPixmap::erase(color) on a pixmap of
877                         // combo.fColorType and then calling SkPixmap::readPixels(). erase() will
878                         // premul the color passed to it. However, createBackendTexture() that takes
879                         // a SkColor4f is color type/alpha type unaware and will simply compute
880                         // luminance from the r, g, b, channels.
881                         SkColor4f color = combo.fColor;
882                         if (combo.fColorType == GrColorType::kGray_8) {
883                             color = {color.fR * color.fA,
884                                      color.fG * color.fA,
885                                      color.fB * color.fA,
886                                      1.f};
887                         }
888 
889                         test_color_init(context, reporter, createWithColorMtd, combo.fColorType,
890                                         color, mipMapped, renderable, finishedPtr);
891                     }
892                 }
893             }
894         }
895     }
896 }
897 
898 #endif
899 
900 ///////////////////////////////////////////////////////////////////////////////
901 
902 #ifdef SK_VULKAN
903 
904 #include "src/gpu/vk/GrVkCaps.h"
905 
DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkBackendAllocationTest,reporter,ctxInfo)906 DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkBackendAllocationTest, reporter, ctxInfo) {
907     auto context = ctxInfo.directContext();
908     const GrVkCaps* vkCaps = static_cast<const GrVkCaps*>(context->priv().caps());
909 
910     constexpr SkColor4f kTransCol { 0, 0.25f, 0.75f, 0.5f };
911     constexpr SkColor4f kGrayCol { 0.75f, 0.75f, 0.75f, 1 };
912 
913     struct {
914         GrColorType fColorType;
915         VkFormat    fFormat;
916         SkColor4f   fColor;
917     } combinations[] = {
918         { GrColorType::kRGBA_8888,        VK_FORMAT_R8G8B8A8_UNORM,           SkColors::kRed      },
919         { GrColorType::kRGBA_8888_SRGB,   VK_FORMAT_R8G8B8A8_SRGB,            SkColors::kRed      },
920 
921         // In this configuration (i.e., an RGB_888x colortype with an RGBA8 backing format),
922         // there is nothing to tell Skia to make the provided color opaque. Clients will need
923         // to provide an opaque initialization color in this case.
924         { GrColorType::kRGB_888x,         VK_FORMAT_R8G8B8A8_UNORM,           SkColors::kYellow   },
925         { GrColorType::kRGB_888x,         VK_FORMAT_R8G8B8_UNORM,             SkColors::kCyan     },
926 
927         { GrColorType::kBGRA_8888,        VK_FORMAT_B8G8R8A8_UNORM,           SkColors::kBlue     },
928 
929         { GrColorType::kRGBA_1010102,     VK_FORMAT_A2B10G10R10_UNORM_PACK32,
930                                                                       { 0.25f, 0.5f, 0.75f, 1.0f }},
931         { GrColorType::kBGRA_1010102,     VK_FORMAT_A2R10G10B10_UNORM_PACK32,
932                                                                       { 0.25f, 0.5f, 0.75f, 1.0f }},
933         { GrColorType::kBGR_565,          VK_FORMAT_R5G6B5_UNORM_PACK16,      SkColors::kRed      },
934 
935         { GrColorType::kABGR_4444,        VK_FORMAT_R4G4B4A4_UNORM_PACK16,    SkColors::kCyan     },
936         { GrColorType::kABGR_4444,        VK_FORMAT_B4G4R4A4_UNORM_PACK16,    SkColors::kYellow   },
937 
938         { GrColorType::kAlpha_8,          VK_FORMAT_R8_UNORM,                 kTransCol           },
939         // In this config (i.e., a Gray8 color type with an R8 backing format), there is nothing
940         // to tell Skia this isn't an Alpha8 color type (so it will initialize the texture with
941         // the alpha channel of the color). Clients should, in general, fill all the channels
942         // of the provided color with the same value in such cases.
943         { GrColorType::kGray_8,           VK_FORMAT_R8_UNORM,                 kGrayCol            },
944 
945         { GrColorType::kRGBA_F16_Clamped, VK_FORMAT_R16G16B16A16_SFLOAT,      SkColors::kLtGray   },
946         { GrColorType::kRGBA_F16,         VK_FORMAT_R16G16B16A16_SFLOAT,      SkColors::kYellow   },
947 
948         { GrColorType::kRG_88,            VK_FORMAT_R8G8_UNORM,               { 1, 0.5f, 0, 1 }   },
949         { GrColorType::kAlpha_F16,        VK_FORMAT_R16_SFLOAT,               { 1.0f, 0, 0, 0.5f }},
950 
951         { GrColorType::kAlpha_16,         VK_FORMAT_R16_UNORM,                kTransCol           },
952         { GrColorType::kRG_1616,          VK_FORMAT_R16G16_UNORM,             SkColors::kYellow   },
953         { GrColorType::kRGBA_16161616,    VK_FORMAT_R16G16B16A16_UNORM,       SkColors::kLtGray   },
954         { GrColorType::kRG_F16,           VK_FORMAT_R16G16_SFLOAT,            SkColors::kYellow   },
955     };
956 
957     for (auto combo : combinations) {
958         if (!vkCaps->isVkFormatTexturable(combo.fFormat)) {
959             continue;
960         }
961 
962         GrBackendFormat format = GrBackendFormat::MakeVk(combo.fFormat);
963 
964         for (auto mipMapped : { GrMipmapped::kNo, GrMipmapped::kYes }) {
965             if (GrMipmapped::kYes == mipMapped && !vkCaps->mipmapSupport()) {
966                 continue;
967             }
968 
969             for (auto renderable : { GrRenderable::kNo, GrRenderable::kYes }) {
970 
971                 if (GrRenderable::kYes == renderable) {
972                     // We must also check whether we allow rendering to the format using the
973                     // color type.
974                     if (!vkCaps->isFormatAsColorTypeRenderable(
975                             combo.fColorType, GrBackendFormat::MakeVk(combo.fFormat), 1)) {
976                         continue;
977                     }
978                 }
979 
980                 {
981                     auto uninitCreateMtd = [format](GrDirectContext* dContext,
982                                                     GrMipmapped mipMapped,
983                                                     GrRenderable renderable) {
984                         GrBackendTexture beTex = dContext->createBackendTexture(32, 32, format,
985                                                                                 mipMapped,
986                                                                                 renderable,
987                                                                                 GrProtected::kNo);
988                         check_vk_layout(beTex, VkLayout::kUndefined);
989                         return beTex;
990                     };
991 
992                     test_wrapping(context, reporter, uninitCreateMtd,
993                                   combo.fColorType, mipMapped, renderable, nullptr);
994                 }
995 
996                 {
997                     // We're creating backend textures without specifying a color type "view" of
998                     // them at the public API level. Therefore, Ganesh will not apply any swizzles
999                     // before writing the color to the texture. However, our validation code does
1000                     // rely on interpreting the texture contents via a SkColorType and therefore
1001                     // swizzles may be applied during the read step.
1002                     // Ideally we'd update our validation code to use a "raw" read that doesn't
1003                     // impose a color type but for now we just munge the data we upload to match the
1004                     // expectation.
1005                     GrSwizzle swizzle;
1006                     switch (combo.fColorType) {
1007                         case GrColorType::kAlpha_8:
1008                             SkASSERT(combo.fFormat == VK_FORMAT_R8_UNORM);
1009                             swizzle = GrSwizzle("aaaa");
1010                             break;
1011                         case GrColorType::kAlpha_16:
1012                             SkASSERT(combo.fFormat == VK_FORMAT_R16_UNORM);
1013                             swizzle = GrSwizzle("aaaa");
1014                             break;
1015                         case GrColorType::kAlpha_F16:
1016                             SkASSERT(combo.fFormat == VK_FORMAT_R16_SFLOAT);
1017                             swizzle = GrSwizzle("aaaa");
1018                             break;
1019                         case GrColorType::kABGR_4444:
1020                             if (combo.fFormat == VK_FORMAT_B4G4R4A4_UNORM_PACK16) {
1021                                 swizzle = GrSwizzle("bgra");
1022                             }
1023                             break;
1024                         default:
1025                             swizzle = GrSwizzle("rgba");
1026                             break;
1027                     }
1028 
1029                     bool finishedBackendCreation = false;
1030                     bool* finishedPtr = &finishedBackendCreation;
1031 
1032                     auto createWithColorMtd = [format, swizzle, finishedPtr](
1033                             GrDirectContext* dContext,
1034                             const SkColor4f& color,
1035                             GrMipmapped mipMapped,
1036                             GrRenderable renderable) {
1037                         auto swizzledColor = swizzle.applyTo(color);
1038                         GrBackendTexture beTex = dContext->createBackendTexture(32, 32, format,
1039                                                                                 swizzledColor,
1040                                                                                 mipMapped,
1041                                                                                 renderable,
1042                                                                                 GrProtected::kNo,
1043                                                                                 mark_signaled,
1044                                                                                 finishedPtr);
1045                         check_vk_layout(beTex, VkLayout::kReadOnlyOptimal);
1046                         return beTex;
1047                     };
1048                     test_color_init(context, reporter, createWithColorMtd,
1049                                     combo.fColorType, combo.fColor, mipMapped, renderable,
1050                                     finishedPtr);
1051                 }
1052             }
1053         }
1054     }
1055 }
1056 
1057 #endif
1058