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