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