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