• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/SkSurface.h"
9 #include "include/core/SkSurfaceCharacterization.h"
10 #include "include/gpu/GrContext.h"
11 #include "src/core/SkAutoPixmapStorage.h"
12 #include "src/gpu/GrContextPriv.h"
13 #include "src/image/SkImage_Base.h"
14 #include "tests/Test.h"
15 
16 #ifdef SK_GL
17 #include "src/gpu/gl/GrGLGpu.h"
18 #include "src/gpu/gl/GrGLUtil.h"
19 #endif
20 
21 // Test wrapping of GrBackendObjects in SkSurfaces and SkImages
test_wrapping(GrContext * context,skiatest::Reporter * reporter,std::function<GrBackendTexture (GrContext *,GrMipMapped,GrRenderable)> create,GrColorType grColorType,GrMipMapped mipMapped,GrRenderable renderable)22 void test_wrapping(GrContext* context, skiatest::Reporter* reporter,
23                    std::function<GrBackendTexture (GrContext*,
24                                                    GrMipMapped,
25                                                    GrRenderable)> create,
26                    GrColorType grColorType, GrMipMapped mipMapped, GrRenderable renderable) {
27     GrResourceCache* cache = context->priv().getResourceCache();
28 
29     const int initialCount = cache->getResourceCount();
30 
31     GrBackendTexture backendTex = create(context, mipMapped, renderable);
32     if (!backendTex.isValid()) {
33         ERRORF(reporter, "Couldn't create backendTexture for grColorType %d renderable %s\n",
34                grColorType,
35                GrRenderable::kYes == renderable ? "yes" : "no");
36         return;
37     }
38 
39     // Skia proper should know nothing about the new backend object
40     REPORTER_ASSERT(reporter, initialCount == cache->getResourceCount());
41 
42     SkColorType skColorType = GrColorTypeToSkColorType(grColorType);
43 
44     // Wrapping a backendTexture in an image requires an SkColorType
45     if (kUnknown_SkColorType == skColorType) {
46         context->deleteBackendTexture(backendTex);
47         return;
48     }
49 
50     if (GrRenderable::kYes == renderable) {
51         sk_sp<SkSurface> surf = SkSurface::MakeFromBackendTexture(context,
52                                                                   backendTex,
53                                                                   kTopLeft_GrSurfaceOrigin,
54                                                                   0,
55                                                                   skColorType,
56                                                                   nullptr, nullptr);
57         if (!surf) {
58             ERRORF(reporter, "Couldn't make surface from backendTexture for colorType %d\n",
59                    skColorType);
60         } else {
61             REPORTER_ASSERT(reporter, initialCount+1 == cache->getResourceCount());
62         }
63     }
64 
65     {
66         sk_sp<SkImage> img = SkImage::MakeFromTexture(context,
67                                                       backendTex,
68                                                       kTopLeft_GrSurfaceOrigin,
69                                                       skColorType,
70                                                       kPremul_SkAlphaType,
71                                                       nullptr);
72         if (!img) {
73             ERRORF(reporter, "Couldn't make image from backendTexture for skColorType %d\n",
74                    skColorType);
75         } else {
76             SkImage_Base* ib = as_IB(img);
77 
78             GrTextureProxy* proxy = ib->peekProxy();
79             REPORTER_ASSERT(reporter, proxy);
80 
81             REPORTER_ASSERT(reporter, mipMapped == proxy->proxyMipMapped());
82             REPORTER_ASSERT(reporter, proxy->isInstantiated());
83             REPORTER_ASSERT(reporter, mipMapped == proxy->mipMapped());
84 
85             REPORTER_ASSERT(reporter, initialCount+1 == cache->getResourceCount());
86         }
87     }
88 
89     REPORTER_ASSERT(reporter, initialCount == cache->getResourceCount());
90 
91     context->deleteBackendTexture(backendTex);
92 }
93 
colors_eq(SkColor colA,SkColor colB,int tol)94 static bool colors_eq(SkColor colA, SkColor colB, int tol) {
95     int maxDiff = 0;
96     for (int i = 0; i < 4; ++i) {
97         int diff = SkTAbs<int>((0xFF & (colA >> i*8)) - (0xFF & (colB >> i*8)));
98         if (maxDiff < diff) {
99             maxDiff = diff;
100         }
101     }
102 
103     return maxDiff <= tol;
104 }
105 
compare_pixmaps(const SkPixmap & expected,const SkPixmap & actual,SkColorType colorType,skiatest::Reporter * reporter)106 static void compare_pixmaps(const SkPixmap& expected, const SkPixmap& actual,
107                             SkColorType colorType, skiatest::Reporter* reporter) {
108     SkASSERT(expected.info() == actual.info());
109     for (int y = 0; y < expected.height(); ++y) {
110         for (int x = 0; x < expected.width(); ++x) {
111 
112             SkColor expectedCol = expected.getColor(x, y);
113             SkColor actualCol = actual.getColor(x, y);
114 
115             // GPU and raster differ a bit on kGray_8_SkColorType and kRGBA_1010102_SkColorType
116             if (colors_eq(actualCol, expectedCol, 12)) {
117                 continue;
118             }
119 
120             ERRORF(reporter,
121                    "Mismatched pixels at %d %d ct: %d expected: 0x%x actual: 0x%x\n",
122                    x, y, colorType, expectedCol, actualCol);
123             return;
124         }
125     }
126 }
127 
128 // Test initialization of GrBackendObjects to a specific color
test_color_init(GrContext * context,skiatest::Reporter * reporter,std::function<GrBackendTexture (GrContext *,const SkColor4f &,GrMipMapped,GrRenderable)> create,GrColorType grColorType,const SkColor4f & color,GrMipMapped mipMapped,GrRenderable renderable)129 void test_color_init(GrContext* context, skiatest::Reporter* reporter,
130                      std::function<GrBackendTexture (GrContext*,
131                                                      const SkColor4f&,
132                                                      GrMipMapped,
133                                                      GrRenderable)> create,
134                      GrColorType grColorType, const SkColor4f& color,
135                      GrMipMapped mipMapped, GrRenderable renderable) {
136     GrBackendTexture backendTex = create(context, color, mipMapped, renderable);
137     if (!backendTex.isValid()) {
138         // errors here should be reported by the test_wrapping test
139         return;
140     }
141 
142     SkColorType skColorType = GrColorTypeToSkColorType(grColorType);
143 
144     // Can't wrap backend textures in images and surfaces w/o an SkColorType
145     if (kUnknown_SkColorType == skColorType) {
146         // TODO: burrow in and scrappily check that data was uploaded!
147         context->deleteBackendTexture(backendTex);
148         return;
149     }
150 
151     SkAlphaType at = SkColorTypeIsAlwaysOpaque(skColorType) ? kOpaque_SkAlphaType
152                                                             : kPremul_SkAlphaType;
153 
154     SkImageInfo ii = SkImageInfo::Make(32, 32, skColorType, at);
155 
156     SkColor4f rasterColor = color;
157     if (kGray_8_SkColorType == skColorType) {
158         // For the GPU backends, gray implies a single channel which is opaque.
159         rasterColor.fR = color.fA;
160         rasterColor.fG = color.fA;
161         rasterColor.fB = color.fA;
162         rasterColor.fA = 1.0f;
163     } else if (kAlpha_8_SkColorType == skColorType) {
164         // For the GPU backends, alpha implies a single alpha channel.
165         rasterColor.fR = 0;
166         rasterColor.fG = 0;
167         rasterColor.fB = 0;
168         rasterColor.fA = color.fA;
169     }
170 
171     SkAutoPixmapStorage expected;
172     SkAssertResult(expected.tryAlloc(ii));
173     expected.erase(rasterColor);
174 
175     SkAutoPixmapStorage actual;
176     SkAssertResult(actual.tryAlloc(ii));
177     actual.erase(SkColors::kTransparent);
178 
179     if (GrRenderable::kYes == renderable) {
180         sk_sp<SkSurface> surf = SkSurface::MakeFromBackendTexture(context,
181                                                                   backendTex,
182                                                                   kTopLeft_GrSurfaceOrigin,
183                                                                   0,
184                                                                   skColorType,
185                                                                   nullptr, nullptr);
186         if (surf) {
187             bool result = surf->readPixels(actual, 0, 0);
188             REPORTER_ASSERT(reporter, result);
189 
190             compare_pixmaps(expected, actual, skColorType, reporter);
191 
192             actual.erase(SkColors::kTransparent);
193         }
194     }
195 
196     {
197         sk_sp<SkImage> img = SkImage::MakeFromTexture(context,
198                                                       backendTex,
199                                                       kTopLeft_GrSurfaceOrigin,
200                                                       skColorType,
201                                                       at,
202                                                       nullptr);
203         if (img) {
204             // If possible, read back the pixels and check that they're correct
205             {
206                 bool result = img->readPixels(actual, 0, 0);
207                 if (!result) {
208                     // TODO: we need a better way to tell a priori if readPixels will work for an
209                     // arbitrary colorType
210 #if 0
211                     ERRORF(reporter, "Couldn't readback from SkImage for colorType: %d\n",
212                             colorType);
213 #endif
214                 } else {
215                     compare_pixmaps(expected, actual, skColorType, reporter);
216                 }
217             }
218 
219             // Draw the wrapped image into an RGBA surface attempting to access all the
220             // mipMap levels.
221             {
222 #ifdef SK_GL
223                 // skbug.com/9141 (RGBA_F32 mipmaps appear to be broken on some Mali devices)
224                 if (GrBackendApi::kOpenGL == context->backend()) {
225                     GrGLGpu* glGPU = static_cast<GrGLGpu*>(context->priv().getGpu());
226 
227                     if (kRGBA_F32_SkColorType == skColorType && GrMipMapped::kYes == mipMapped &&
228                         kGLES_GrGLStandard == glGPU->ctxInfo().standard()) {
229                         context->deleteBackendTexture(backendTex);
230                         return;
231                     }
232                 }
233 #endif
234 
235                 SkImageInfo newII = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType,
236                                                       kPremul_SkAlphaType);
237 
238                 SkAutoPixmapStorage actual2;
239                 SkAssertResult(actual2.tryAlloc(newII));
240                 actual2.erase(SkColors::kTransparent);
241 
242                 sk_sp<SkSurface> surf = SkSurface::MakeRenderTarget(context,
243                                                                     SkBudgeted::kNo,
244                                                                     newII, 1,
245                                                                     kTopLeft_GrSurfaceOrigin,
246                                                                     nullptr);
247                 if (!surf) {
248                     context->deleteBackendTexture(backendTex);
249                     return;
250                 }
251 
252                 SkCanvas* canvas = surf->getCanvas();
253 
254                 SkPaint p;
255                 p.setFilterQuality(kHigh_SkFilterQuality);
256 
257                 int numMipLevels = (GrMipMapped::kYes == mipMapped) ? 6 : 1;
258 
259                 for (int i = 0, rectSize = 32; i < numMipLevels; ++i, rectSize /= 2) {
260                     SkASSERT(rectSize >= 1);
261 
262                     SkRect r = SkRect::MakeWH(rectSize, rectSize);
263                     canvas->clear(SK_ColorTRANSPARENT);
264                     canvas->drawImageRect(img, r, &p);
265 
266                     bool result = surf->readPixels(actual2, 0, 0);
267                     REPORTER_ASSERT(reporter, result);
268 
269                     SkColor actualColor = actual2.getColor(0, 0);
270 
271                     if (!colors_eq(actualColor, rasterColor.toSkColor(), 1)) {
272                         ERRORF(reporter, "Pixel mismatch colorType %d: level: %d e: 0x%x a: 0x%x\n",
273                                skColorType, i, rasterColor.toSkColor(), actualColor);
274                     }
275                 }
276             }
277         }
278     }
279 
280     context->deleteBackendTexture(backendTex);
281 }
282 
283 enum class VkLayout {
284     kUndefined,
285     kReadOnlyOptimal,
286     kColorAttachmentOptimal
287 };
288 
check_vk_layout(const GrBackendTexture & backendTex,VkLayout layout)289 void check_vk_layout(const GrBackendTexture& backendTex, VkLayout layout) {
290 #if defined(SK_VULKAN) && defined(SK_DEBUG)
291     VkImageLayout expected;
292 
293     switch (layout) {
294         case VkLayout::kUndefined:
295             expected = VK_IMAGE_LAYOUT_UNDEFINED;
296             break;
297         case VkLayout::kReadOnlyOptimal:
298             expected = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
299             break;
300         case VkLayout::kColorAttachmentOptimal:
301             expected = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
302             break;
303         default:
304             SkUNREACHABLE;
305     }
306 
307     GrVkImageInfo vkII;
308 
309     if (backendTex.getVkImageInfo(&vkII)) {
310         SkASSERT(expected == vkII.fImageLayout);
311         SkASSERT(VK_IMAGE_TILING_OPTIMAL == vkII.fImageTiling);
312     }
313 #endif
314 }
315 
316 ///////////////////////////////////////////////////////////////////////////////
317 // This test is a bit different from the others in this file. It is mainly checking that, for any
318 // SkSurface we can create in Ganesh, we can also create a backend texture that is compatible with
319 // its characterization and then create a new surface that wraps that backend texture.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(CharacterizationBackendAllocationTest,reporter,ctxInfo)320 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(CharacterizationBackendAllocationTest, reporter, ctxInfo) {
321     GrContext* context = ctxInfo.grContext();
322 
323     for (int ct = 0; ct <= kLastEnum_SkColorType; ++ct) {
324         SkColorType colorType = static_cast<SkColorType>(ct);
325 
326         SkImageInfo ii = SkImageInfo::Make(32, 32, colorType, kPremul_SkAlphaType);
327 
328         for (auto origin : { kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin } ) {
329             for (bool mipMaps : { true, false } ) {
330                 for (int sampleCount : {1, 2}) {
331                     SkSurfaceCharacterization c;
332 
333                     // Get a characterization, if possible
334                     {
335                         sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo,
336                                                                          ii, sampleCount,
337                                                                          origin, nullptr, mipMaps);
338                         if (!s) {
339                             continue;
340                         }
341 
342                         if (!s->characterize(&c)) {
343                             continue;
344                         }
345 
346                         REPORTER_ASSERT(reporter, s->isCompatible(c));
347                     }
348 
349                     // Test out uninitialized path
350                     {
351                         GrBackendTexture backendTex = context->createBackendTexture(c);
352                         check_vk_layout(backendTex, VkLayout::kUndefined);
353                         REPORTER_ASSERT(reporter, backendTex.isValid());
354                         REPORTER_ASSERT(reporter, c.isCompatible(backendTex));
355 
356                         {
357                             GrBackendFormat format = context->defaultBackendFormat(
358                                                                     c.imageInfo().colorType(),
359                                                                     GrRenderable::kYes);
360                             REPORTER_ASSERT(reporter, format == backendTex.getBackendFormat());
361                         }
362 
363                         sk_sp<SkSurface> s2 = SkSurface::MakeFromBackendTexture(context, c,
364                                                                                 backendTex);
365                         REPORTER_ASSERT(reporter, s2);
366                         REPORTER_ASSERT(reporter, s2->isCompatible(c));
367 
368                         s2 = nullptr;
369                         context->deleteBackendTexture(backendTex);
370                     }
371 
372                     // Test out color-initialized path
373                     {
374                         GrBackendTexture backendTex = context->createBackendTexture(c,
375                                                                                     SkColors::kRed);
376                         check_vk_layout(backendTex, VkLayout::kColorAttachmentOptimal);
377                         REPORTER_ASSERT(reporter, backendTex.isValid());
378                         REPORTER_ASSERT(reporter, c.isCompatible(backendTex));
379 
380                         {
381                             GrBackendFormat format = context->defaultBackendFormat(
382                                                                     c.imageInfo().colorType(),
383                                                                     GrRenderable::kYes);
384                             REPORTER_ASSERT(reporter, format == backendTex.getBackendFormat());
385                         }
386 
387                         sk_sp<SkSurface> s2 = SkSurface::MakeFromBackendTexture(context, c,
388                                                                                 backendTex);
389                         REPORTER_ASSERT(reporter, s2);
390                         REPORTER_ASSERT(reporter, s2->isCompatible(c));
391 
392                         s2 = nullptr;
393                         context->deleteBackendTexture(backendTex);
394                     }
395                 }
396             }
397         }
398     }
399 }
400 
401 ///////////////////////////////////////////////////////////////////////////////
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ColorTypeBackendAllocationTest,reporter,ctxInfo)402 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ColorTypeBackendAllocationTest, reporter, ctxInfo) {
403     GrContext* context = ctxInfo.grContext();
404     const GrCaps* caps = context->priv().caps();
405 
406     constexpr SkColor4f kTransCol { 0, 0.25f, 0.75f, 0.5f };
407     constexpr SkColor4f kGrayCol { 0.75f, 0.75f, 0.75f, 0.75f };
408 
409     struct {
410         SkColorType   fColorType;
411         GrPixelConfig fConfig;
412         SkColor4f     fColor;
413     } combinations[] = {
414         { kAlpha_8_SkColorType,      kAlpha_8_GrPixelConfig,           kTransCol           },
415         { kRGB_565_SkColorType,      kRGB_565_GrPixelConfig,           SkColors::kRed      },
416         { kARGB_4444_SkColorType,    kRGBA_4444_GrPixelConfig,         SkColors::kGreen    },
417         { kRGBA_8888_SkColorType,    kRGBA_8888_GrPixelConfig,         SkColors::kBlue     },
418         { kRGB_888x_SkColorType,     kRGB_888_GrPixelConfig,           SkColors::kCyan     },
419         // TODO: readback is busted when alpha = 0.5f (perhaps premul vs. unpremul)
420         { kBGRA_8888_SkColorType,    kBGRA_8888_GrPixelConfig,         { 1, 0, 0, 1.0f }   },
421         // TODO: readback is busted when alpha = 0.5f (perhaps premul vs. unpremul)
422         { kRGBA_1010102_SkColorType, kRGBA_1010102_GrPixelConfig,      { 0.5f, 0, 0, 1.0f }},
423         // The kRGB_101010x_SkColorType has no Ganesh correlate
424         { kRGB_101010x_SkColorType,  kUnknown_GrPixelConfig,           { 0, 0.5f, 0, 0.5f }},
425         { kGray_8_SkColorType,       kGray_8_GrPixelConfig,            kGrayCol            },
426         { kRGBA_F16Norm_SkColorType, kRGBA_half_Clamped_GrPixelConfig, SkColors::kLtGray   },
427         { kRGBA_F16_SkColorType,     kRGBA_half_GrPixelConfig,         SkColors::kYellow   },
428         { kRGBA_F32_SkColorType,     kRGBA_float_GrPixelConfig,        SkColors::kGray     },
429     };
430 
431     GR_STATIC_ASSERT(kLastEnum_SkColorType == SK_ARRAY_COUNT(combinations));
432 
433     for (auto combo : combinations) {
434         SkColorType colorType = combo.fColorType;
435 
436         if (GrBackendApi::kMetal == context->backend()) {
437             // skbug.com/9086 (Metal caps may not be handling RGBA32 correctly)
438             if (kRGBA_F32_SkColorType == combo.fColorType) {
439                 continue;
440             }
441         }
442 
443         for (auto mipMapped : { GrMipMapped::kNo, GrMipMapped::kYes }) {
444             if (GrMipMapped::kYes == mipMapped && !caps->mipMapSupport()) {
445                 continue;
446             }
447 
448             for (auto renderable : { GrRenderable::kNo, GrRenderable::kYes }) {
449                 if (!caps->getDefaultBackendFormat(SkColorTypeToGrColorType(colorType),
450                                                    renderable).isValid()) {
451                     continue;
452                 }
453                 if (GrRenderable::kYes == renderable) {
454                     if (kRGB_888x_SkColorType == combo.fColorType) {
455                         // Ganesh can't perform the blends correctly when rendering this format
456                         continue;
457                     }
458                 }
459 
460                 {
461                     auto uninitCreateMtd = [colorType](GrContext* context,
462                                                        GrMipMapped mipMapped,
463                                                        GrRenderable renderable) {
464                         auto result = context->createBackendTexture(32, 32, colorType,
465                                                                     mipMapped, renderable,
466                                                                     GrProtected::kNo);
467                         check_vk_layout(result, VkLayout::kUndefined);
468 
469 #ifdef SK_DEBUG
470                         {
471                             GrBackendFormat format = context->defaultBackendFormat(colorType,
472                                                                                    renderable);
473                             SkASSERT(format == result.getBackendFormat());
474                         }
475 #endif
476 
477                         return result;
478                     };
479 
480                     test_wrapping(context, reporter, uninitCreateMtd,
481                                   SkColorTypeToGrColorType(colorType), mipMapped, renderable);
482                 }
483 
484                 {
485                     // GL has difficulties reading back from these combinations. In particular,
486                     // reading back kGray_8 is a mess.
487                     if (GrBackendApi::kOpenGL == context->backend()) {
488                         if (kAlpha_8_SkColorType == combo.fColorType ||
489                             kGray_8_SkColorType == combo.fColorType) {
490                             continue;
491                         }
492                     } else if (GrBackendApi::kMetal == context->backend()) {
493                         // Not yet implemented for Metal
494                         continue;
495                     }
496 
497                     auto createWithColorMtd = [colorType](GrContext* context,
498                                                           const SkColor4f& color,
499                                                           GrMipMapped mipMapped,
500                                                           GrRenderable renderable) {
501                         auto result = context->createBackendTexture(32, 32, colorType, color,
502                                                                     mipMapped, renderable,
503                                                                     GrProtected::kNo);
504                         check_vk_layout(result, GrRenderable::kYes == renderable
505                                                         ? VkLayout::kColorAttachmentOptimal
506                                                         : VkLayout::kReadOnlyOptimal);
507 
508 #ifdef SK_DEBUG
509                         {
510                             GrBackendFormat format = context->defaultBackendFormat(colorType,
511                                                                                    renderable);
512                             SkASSERT(format == result.getBackendFormat());
513                         }
514 #endif
515 
516                         return result;
517                     };
518 
519                     test_color_init(context, reporter, createWithColorMtd,
520                                     SkColorTypeToGrColorType(colorType),
521                                     combo.fColor, mipMapped, renderable);
522                 }
523             }
524         }
525     }
526 
527 }
528 
529 ///////////////////////////////////////////////////////////////////////////////
530 #ifdef SK_GL
531 
532 #include "src/gpu/gl/GrGLCaps.h"
533 #include "src/gpu/gl/GrGLDefines.h"
534 #include "src/gpu/gl/GrGLUtil.h"
535 
DEF_GPUTEST_FOR_ALL_GL_CONTEXTS(GLBackendAllocationTest,reporter,ctxInfo)536 DEF_GPUTEST_FOR_ALL_GL_CONTEXTS(GLBackendAllocationTest, reporter, ctxInfo) {
537     sk_gpu_test::GLTestContext* glCtx = ctxInfo.glContext();
538     GrGLStandard standard = glCtx->gl()->fStandard;
539     GrContext* context = ctxInfo.grContext();
540     const GrGLCaps* glCaps = static_cast<const GrGLCaps*>(context->priv().caps());
541 
542     constexpr SkColor4f kTransCol { 0, 0.25f, 0.75f, 0.5f };
543     constexpr SkColor4f kGrayCol { 0.75f, 0.75f, 0.75f, 0.75f };
544 
545     struct {
546         GrColorType   fColorType;
547         GrGLenum      fFormat;
548         SkColor4f     fColor;
549     } combinations[] = {
550         { GrColorType::kRGBA_8888,        GR_GL_RGBA8,                SkColors::kRed       },
551         { GrColorType::kRGBA_8888_SRGB,   GR_GL_SRGB8_ALPHA8,         SkColors::kRed       },
552 
553         { GrColorType::kRGB_888x,         GR_GL_RGBA8,                SkColors::kYellow    },
554         { GrColorType::kRGB_888x,         GR_GL_RGB8,                 SkColors::kCyan      },
555 
556         { GrColorType::kBGRA_8888,        GR_GL_RGBA8,                SkColors::kBlue      },
557         { GrColorType::kBGRA_8888,        GR_GL_BGRA8,                SkColors::kBlue      },
558         // TODO: readback is busted when alpha = 0.5f (perhaps premul vs. unpremul)
559         { GrColorType::kRGBA_1010102,     GR_GL_RGB10_A2,             { 0.5f, 0, 0, 1.0f } },
560         { GrColorType::kBGR_565,          GR_GL_RGB565,               SkColors::kRed       },
561         { GrColorType::kABGR_4444,        GR_GL_RGBA4,                SkColors::kGreen     },
562 
563         { GrColorType::kAlpha_8,          GR_GL_ALPHA8,               kTransCol            },
564         { GrColorType::kAlpha_8,          GR_GL_R8,                   kTransCol            },
565 
566         { GrColorType::kGray_8,           GR_GL_LUMINANCE8,           kGrayCol             },
567         { GrColorType::kGray_8,           GR_GL_R8,                   kGrayCol             },
568 
569         { GrColorType::kRGBA_F32,         GR_GL_RGBA32F,              SkColors::kRed       },
570 
571         { GrColorType::kRGBA_F16_Clamped, GR_GL_RGBA16F,              SkColors::kLtGray    },
572         { GrColorType::kRGBA_F16,         GR_GL_RGBA16F,              SkColors::kYellow    },
573 
574         { GrColorType::kRG_88,            GR_GL_RG8,                  { 0.5f, 0.5f, 0, 0 } },
575         { GrColorType::kAlpha_F16,        GR_GL_R16F,                 { 1.0f, 0, 0, 0.5f } },
576         { GrColorType::kAlpha_F16,        GR_GL_LUMINANCE16F,         kGrayCol             },
577 
578         { GrColorType::kR_16,             GR_GL_R16,                  SkColors::kRed       },
579         { GrColorType::kRG_1616,          GR_GL_RG16,                 SkColors::kYellow    },
580 
581         // Experimental (for Y416 and mutant P016/P010)
582         { GrColorType::kRGBA_16161616,    GR_GL_RGBA16,               SkColors::kLtGray    },
583         { GrColorType::kRG_F16,           GR_GL_RG16F,                SkColors::kYellow    },
584 
585         { GrColorType::kUnknown,          GR_GL_COMPRESSED_RGB8_ETC2, SkColors::kRed      },
586         { GrColorType::kUnknown,          GR_GL_COMPRESSED_ETC1_RGB8, SkColors::kRed      },
587     };
588 
589     for (auto combo : combinations) {
590         GrBackendFormat format = GrBackendFormat::MakeGL(combo.fFormat, GR_GL_TEXTURE_2D);
591 
592         if (!glCaps->isFormatTexturable(format)) {
593             continue;
594         }
595 
596         if (GrColorType::kBGRA_8888 == combo.fColorType) {
597             if (GR_GL_RGBA8 == combo.fFormat && kGL_GrGLStandard != standard) {
598                 continue;
599             }
600             if (GR_GL_BGRA8 == combo.fFormat && kGL_GrGLStandard == standard) {
601                 continue;
602             }
603         }
604 
605         for (auto mipMapped : { GrMipMapped::kNo, GrMipMapped::kYes }) {
606             if (GrMipMapped::kYes == mipMapped && !glCaps->mipMapSupport()) {
607                 continue;
608             }
609 
610             for (auto renderable : { GrRenderable::kNo, GrRenderable::kYes }) {
611 
612                 if (GrRenderable::kYes == renderable) {
613                     if (!glCaps->isFormatAsColorTypeRenderable(combo.fColorType, format)) {
614                         continue;
615                     }
616                 }
617 
618 
619                 // We current disallow uninitialized compressed textures in the GL backend
620                 if (GR_GL_COMPRESSED_RGB8_ETC2 != combo.fFormat &&
621                     GR_GL_COMPRESSED_ETC1_RGB8 != combo.fFormat) {
622                     auto uninitCreateMtd = [format](GrContext* context,
623                                                     GrMipMapped mipMapped,
624                                                     GrRenderable renderable) {
625                         return context->createBackendTexture(32, 32, format,
626                                                              mipMapped, renderable,
627                                                              GrProtected::kNo);
628                     };
629 
630                     test_wrapping(context, reporter, uninitCreateMtd,
631                                   combo.fColorType, mipMapped, renderable);
632                 }
633 
634                 {
635                     // GL has difficulties reading back from these combinations
636                     if (GrColorType::kAlpha_8 == combo.fColorType) {
637                         continue;
638                     }
639                     if (GrRenderable::kYes != renderable) {
640                         continue;
641                     }
642 
643                     auto createWithColorMtd = [format](GrContext* context,
644                                                        const SkColor4f& color,
645                                                        GrMipMapped mipMapped,
646                                                        GrRenderable renderable) {
647                         return context->createBackendTexture(32, 32, format, color,
648                                                              mipMapped, renderable,
649                                                              GrProtected::kNo);
650                     };
651 
652                     test_color_init(context, reporter, createWithColorMtd,
653                                     combo.fColorType, combo.fColor, mipMapped, renderable);
654                 }
655             }
656         }
657     }
658 }
659 
660 #endif
661 
662 ///////////////////////////////////////////////////////////////////////////////
663 
664 #ifdef SK_VULKAN
665 
666 #include "src/gpu/vk/GrVkCaps.h"
667 
DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkBackendAllocationTest,reporter,ctxInfo)668 DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkBackendAllocationTest, reporter, ctxInfo) {
669     GrContext* context = ctxInfo.grContext();
670     const GrVkCaps* vkCaps = static_cast<const GrVkCaps*>(context->priv().caps());
671 
672     constexpr SkColor4f kTransCol { 0, 0.25f, 0.75f, 0.5f };
673     constexpr SkColor4f kGrayCol { 0.75f, 0.75f, 0.75f, 0.75f };
674 
675     struct {
676         GrColorType fColorType;
677         VkFormat    fFormat;
678         SkColor4f   fColor;
679     } combinations[] = {
680         { GrColorType::kRGBA_8888,        VK_FORMAT_R8G8B8A8_UNORM,           SkColors::kRed      },
681         { GrColorType::kRGBA_8888_SRGB,   VK_FORMAT_R8G8B8A8_SRGB,            SkColors::kRed      },
682 
683         // In this configuration (i.e., an RGB_888x colortype with an RGBA8 backing format),
684         // there is nothing to tell Skia to make the provided color opaque. Clients will need
685         // to provide an opaque initialization color in this case.
686         { GrColorType::kRGB_888x,         VK_FORMAT_R8G8B8A8_UNORM,           SkColors::kYellow   },
687         { GrColorType::kRGB_888x,         VK_FORMAT_R8G8B8_UNORM,             SkColors::kCyan     },
688 
689         { GrColorType::kBGRA_8888,        VK_FORMAT_B8G8R8A8_UNORM,           SkColors::kBlue     },
690 
691         { GrColorType::kRGBA_1010102,     VK_FORMAT_A2B10G10R10_UNORM_PACK32, { 0.5f, 0, 0, 1.0f }},
692         { GrColorType::kBGR_565,          VK_FORMAT_R5G6B5_UNORM_PACK16,      SkColors::kRed      },
693 
694         { GrColorType::kABGR_4444,        VK_FORMAT_R4G4B4A4_UNORM_PACK16,    SkColors::kCyan     },
695         { GrColorType::kABGR_4444,        VK_FORMAT_B4G4R4A4_UNORM_PACK16,    SkColors::kYellow   },
696 
697         { GrColorType::kAlpha_8,          VK_FORMAT_R8_UNORM,                 kTransCol           },
698         // In this config (i.e., a Gray8 color type with an R8 backing format), there is nothing
699         // to tell Skia this isn't an Alpha8 color type (so it will initialize the texture with
700         // the alpha channel of the color). Clients should, in general, fill all the channels
701         // of the provided color with the same value in such cases.
702         { GrColorType::kGray_8,           VK_FORMAT_R8_UNORM,                 kGrayCol            },
703 
704         { GrColorType::kRGBA_F32,         VK_FORMAT_R32G32B32A32_SFLOAT,      SkColors::kRed      },
705 
706         { GrColorType::kRGBA_F16_Clamped, VK_FORMAT_R16G16B16A16_SFLOAT,      SkColors::kLtGray   },
707         { GrColorType::kRGBA_F16,         VK_FORMAT_R16G16B16A16_SFLOAT,      SkColors::kYellow   },
708 
709         // These backend formats don't have SkColorType equivalents
710         { GrColorType::kRG_88,            VK_FORMAT_R8G8_UNORM,               { 0.5f, 0.5f, 0, 0 }},
711         { GrColorType::kAlpha_F16,        VK_FORMAT_R16_SFLOAT,               { 1.0f, 0, 0, 0.5f }},
712 
713         { GrColorType::kR_16,             VK_FORMAT_R16_UNORM,                SkColors::kRed      },
714         { GrColorType::kRG_1616,          VK_FORMAT_R16G16_UNORM,             SkColors::kYellow   },
715 
716         // Experimental (for Y416 and mutant P016/P010)
717         { GrColorType::kRGBA_16161616,    VK_FORMAT_R16G16B16A16_UNORM,       SkColors::kLtGray   },
718         { GrColorType::kRG_F16,           VK_FORMAT_R16G16_SFLOAT,            SkColors::kYellow   },
719 
720         { GrColorType::kUnknown,          VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,  SkColors::kRed      },
721     };
722 
723     for (auto combo : combinations) {
724         if (!vkCaps->isVkFormatTexturable(combo.fFormat)) {
725             continue;
726         }
727 
728         GrBackendFormat format = GrBackendFormat::MakeVk(combo.fFormat);
729 
730         for (auto mipMapped : { GrMipMapped::kNo, GrMipMapped::kYes }) {
731             if (GrMipMapped::kYes == mipMapped && !vkCaps->mipMapSupport()) {
732                 continue;
733             }
734 
735             for (auto renderable : { GrRenderable::kNo, GrRenderable::kYes }) {
736 
737                 if (GrRenderable::kYes == renderable) {
738                     // We must also check whether we allow rendering to the format using the
739                     // color type.
740                     if (!vkCaps->isFormatAsColorTypeRenderable(
741                             combo.fColorType, GrBackendFormat::MakeVk(combo.fFormat), 1)) {
742                         continue;
743                     }
744                 }
745 
746                 // We current disallow uninitialized compressed textures in the Vulkan backend
747                 if (combo.fFormat != VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK) {
748                     auto uninitCreateMtd = [format](GrContext* context,
749                                                     GrMipMapped mipMapped,
750                                                     GrRenderable renderable) {
751                         GrBackendTexture beTex = context->createBackendTexture(32, 32, format,
752                                                                                mipMapped,
753                                                                                renderable,
754                                                                                GrProtected::kNo);
755                         check_vk_layout(beTex, VkLayout::kUndefined);
756                         return beTex;
757                     };
758 
759                     test_wrapping(context, reporter, uninitCreateMtd,
760                                   combo.fColorType, mipMapped, renderable);
761                 }
762 
763                 {
764                     // We're creating backend textures without specifying a color type "view" of
765                     // them at the public API level. Therefore, Ganesh will not apply any swizzles
766                     // before writing the color to the texture. However, our validation code does
767                     // rely on interpreting the texture contents via a SkColorType and therefore
768                     // swizzles may be applied during the read step.
769                     // Ideally we'd update our validation code to use a "raw" read that doesn't
770                     // impose a color type but for now we just munge the data we upload to match the
771                     // expectation.
772                     GrSwizzle swizzle;
773                     switch (combo.fColorType) {
774                         case GrColorType::kAlpha_8:
775                             SkASSERT(combo.fFormat == VK_FORMAT_R8_UNORM);
776                             swizzle = GrSwizzle("aaaa");
777                             break;
778                         case GrColorType::kABGR_4444:
779                             if (combo.fFormat == VK_FORMAT_B4G4R4A4_UNORM_PACK16) {
780                                 swizzle = GrSwizzle("bgra");
781                             }
782                             break;
783                         default:
784                             swizzle = GrSwizzle("rgba");
785                             break;
786                     }
787                     auto createWithColorMtd = [format, swizzle](GrContext* context,
788                                                                 const SkColor4f& color,
789                                                                 GrMipMapped mipMapped,
790                                                                 GrRenderable renderable) {
791                         auto swizzledColor = swizzle.applyTo(color);
792                         GrBackendTexture beTex = context->createBackendTexture(32, 32, format,
793                                                                                swizzledColor,
794                                                                                mipMapped,
795                                                                                renderable,
796                                                                                GrProtected::kNo);
797                         check_vk_layout(beTex, GrRenderable::kYes == renderable
798                                                         ? VkLayout::kColorAttachmentOptimal
799                                                         : VkLayout::kReadOnlyOptimal);
800                         return beTex;
801                     };
802                     test_color_init(context, reporter, createWithColorMtd,
803                                     combo.fColorType, combo.fColor, mipMapped, renderable);
804                 }
805             }
806         }
807     }
808 }
809 
810 #endif
811