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