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