Add mipmap support to SkPixmap flavor of createBackendTexture
Change-Id: I7a2dea9b0b8e6b985f2d56e587939266022c19e1
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/234664
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp
index 353c252af..3da7c1f 100644
--- a/src/core/SkPixmap.cpp
+++ b/src/core/SkPixmap.cpp
@@ -341,9 +341,9 @@
b = ((value >> 20) & 0x3ff) * (1/1023.0f),
a = ((value >> 30) & 0x3 ) * (1/ 3.0f);
if (a != 0 && needsUnpremul) {
- r *= (1.0f/a);
- g *= (1.0f/a);
- b *= (1.0f/a);
+ r = SkTPin(r/a, 0.0f, 1.0f);
+ g = SkTPin(g/a, 0.0f, 1.0f);
+ b = SkTPin(b/a, 0.0f, 1.0f);
}
return (uint32_t)( r * 255.0f ) << 16
| (uint32_t)( g * 255.0f ) << 8
diff --git a/src/gpu/GrContextPriv.h b/src/gpu/GrContextPriv.h
index ede9ea0..0fbec0f 100644
--- a/src/gpu/GrContextPriv.h
+++ b/src/gpu/GrContextPriv.h
@@ -267,6 +267,9 @@
// pixmap(s).
// If numLevels is 1 a non-mipMapped texture will result. If a mipMapped texture is desired
// the data for all the mipmap levels must be provided.
+ // For the Vulkan backend the layout of the created VkImage will be:
+ // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
+ // regardless of the renderability setting
GrBackendTexture createBackendTexture(const SkPixmap srcData[], int numLevels,
GrRenderable, GrProtected);
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 632f82f..c982a0f 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -3553,11 +3553,6 @@
return GrBackendTexture(); // invalid
}
- // Currently we don't support uploading pixel data when mipped.
- if (srcData && GrMipMapped::kYes == mipMapped) {
- return GrBackendTexture(); // invalid
- }
-
GrGLTextureInfo info;
GrGLTextureParameters::SamplerOverriddenState initialState;
@@ -3596,6 +3591,7 @@
texels[i] = {&(tmpPixels[offset]), currentWidth * bytesPerPixel};
}
}
+
GrSurfaceDesc desc;
desc.fWidth = w;
desc.fHeight = h;
diff --git a/src/gpu/mtl/GrMtlCppUtil.h b/src/gpu/mtl/GrMtlCppUtil.h
index 9e55204..47c6eb5 100644
--- a/src/gpu/mtl/GrMtlCppUtil.h
+++ b/src/gpu/mtl/GrMtlCppUtil.h
@@ -16,6 +16,7 @@
#if GR_TEST_UTILS
const char* GrMtlFormatToStr(GrMTLPixelFormat mtlFormat);
+bool GrMtlFormatIsBGRA(GrMTLPixelFormat mtlFormat);
#endif
#endif
diff --git a/src/gpu/mtl/GrMtlGpu.mm b/src/gpu/mtl/GrMtlGpu.mm
index 10666a4..16d0d42 100644
--- a/src/gpu/mtl/GrMtlGpu.mm
+++ b/src/gpu/mtl/GrMtlGpu.mm
@@ -712,6 +712,20 @@
SkUNREACHABLE;
}
+void copy_src_data(char* dst, size_t bytesPerPixel, const SkTArray<size_t>& individualMipOffsets,
+ const SkPixmap srcData[], int numMipLevels, size_t bufferSize) {
+ SkASSERT(srcData && numMipLevels);
+ SkASSERT(individualMipOffsets.count() == numMipLevels);
+
+ for (int level = 0; level < numMipLevels; ++level) {
+ const size_t trimRB = srcData[level].width() * bytesPerPixel;
+ SkASSERT(individualMipOffsets[level] + trimRB * srcData[level].height() <= bufferSize);
+ SkRectMemcpy(dst + individualMipOffsets[level], trimRB,
+ srcData[level].addr(), srcData[level].rowBytes(),
+ trimRB, srcData[level].height());
+ }
+}
+
bool GrMtlGpu::createMtlTextureForBackendSurface(MTLPixelFormat format,
int w, int h, bool texturable,
bool renderable, GrMipMapped mipMapped,
@@ -734,11 +748,8 @@
if (renderable && !fMtlCaps->isFormatRenderable(format, 1)) {
return false;
}
- // Currently we don't support uploading pixel data when mipped.
- if (srcData && GrMipMapped::kYes == mipMapped) {
- return false;
- }
- if(!check_max_blit_width(w)) {
+
+ if (!check_max_blit_width(w)) {
return false;
}
@@ -793,14 +804,8 @@
// Fill buffer with data
if (srcData) {
- const size_t trimRowBytes = w * bytesPerPixel;
-
- // TODO: support mipmapping
- SkASSERT(1 == mipLevelCount);
-
- // copy data into the buffer, skipping the trailing bytes
- const char* src = (const char*) srcData->addr();
- SkRectMemcpy(buffer, trimRowBytes, src, srcData->rowBytes(), trimRowBytes, h);
+ copy_src_data(buffer, bytesPerPixel, individualMipOffsets,
+ srcData, numMipLevels, combinedBufferSize);
} else if (color) {
GrPixelConfig config = mtl_format_to_pixelconfig(format);
SkASSERT(kUnknown_GrPixelConfig != config);
diff --git a/src/gpu/mtl/GrMtlUtil.mm b/src/gpu/mtl/GrMtlUtil.mm
index 045bf02..e0de7d5 100644
--- a/src/gpu/mtl/GrMtlUtil.mm
+++ b/src/gpu/mtl/GrMtlUtil.mm
@@ -353,6 +353,10 @@
}
#if GR_TEST_UTILS
+bool GrMtlFormatIsBGRA(GrMTLPixelFormat mtlFormat) {
+ return mtlFormat == MTLPixelFormatBGRA8Unorm;
+}
+
const char* GrMtlFormatToStr(GrMTLPixelFormat mtlFormat) {
switch (mtlFormat) {
case MTLPixelFormatInvalid: return "Invalid";
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index a5577a8..899360e 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -1448,23 +1448,26 @@
////////////////////////////////////////////////////////////////////////////////
bool copy_src_data(GrVkGpu* gpu, const GrVkAlloc& alloc, VkFormat vkFormat,
- int width, int height,
- const void* srcData, size_t srcRowBytes) {
- SkASSERT(srcData);
+ const SkTArray<size_t>& individualMipOffsets,
+ const SkPixmap srcData[], int numMipLevels) {
+ SkASSERT(srcData && numMipLevels);
SkASSERT(!GrVkFormatIsCompressed(vkFormat));
+ SkASSERT(individualMipOffsets.count() == numMipLevels);
- void* mapPtr = GrVkMemory::MapAlloc(gpu, alloc);
+ char* mapPtr = (char*) GrVkMemory::MapAlloc(gpu, alloc);
if (!mapPtr) {
return false;
}
size_t bytesPerPixel = GrVkBytesPerFormat(vkFormat);
- const size_t trimRowBytes = width * bytesPerPixel;
- if (!srcRowBytes) {
- srcRowBytes = trimRowBytes;
- }
- SkASSERT(trimRowBytes * height <= alloc.fSize);
- SkRectMemcpy(mapPtr, trimRowBytes, srcData, srcRowBytes, trimRowBytes, height);
+ for (int level = 0; level < numMipLevels; ++level) {
+ const size_t trimRB = srcData[level].width() * bytesPerPixel;
+ SkASSERT(individualMipOffsets[level] + trimRB * srcData[level].height() <= alloc.fSize);
+
+ SkRectMemcpy(mapPtr + individualMipOffsets[level], trimRB,
+ srcData[level].addr(), srcData[level].rowBytes(),
+ trimRB, srcData[level].height());
+ }
GrVkMemory::FlushMappedAlloc(gpu, alloc, 0, alloc.fSize);
GrVkMemory::UnmapAlloc(gpu, alloc);
@@ -1527,11 +1530,6 @@
return false;
}
- // Currently we don't support uploading pixel data when mipped.
- if (srcData && GrMipMapped::kYes == mipMapped) {
- return false;
- }
-
VkImageUsageFlags usageFlags = 0;
usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
usageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
@@ -1644,9 +1642,8 @@
return false;
}
- SkASSERT(1 == mipLevelCount);
- bool result = copy_src_data(this, bufferAlloc, vkFormat, w, h,
- srcData->addr(), srcData->rowBytes());
+ bool result = copy_src_data(this, bufferAlloc, vkFormat, individualMipOffsets,
+ srcData, numMipLevels);
if (!result) {
GrVkImage::DestroyImageInfo(this, info);
GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
diff --git a/tests/BackendAllocationTest.cpp b/tests/BackendAllocationTest.cpp
index acd2507..9d61535 100644
--- a/tests/BackendAllocationTest.cpp
+++ b/tests/BackendAllocationTest.cpp
@@ -20,6 +20,11 @@
#include "src/gpu/gl/GrGLUtil.h"
#endif
+#ifdef SK_METAL
+#include "include/gpu/mtl/GrMtlTypes.h"
+#include "src/gpu/mtl/GrMtlCppUtil.h"
+#endif
+
// Test wrapping of GrBackendObjects in SkSurfaces and SkImages (non-static since used in Mtl test)
void test_wrapping(GrContext* context, skiatest::Reporter* reporter,
std::function<GrBackendTexture (GrContext*,
@@ -93,60 +98,113 @@
context->deleteBackendTexture(backendTex);
}
+static bool isBGRA(const GrBackendFormat& format) {
+ switch (format.backend()) {
+ case GrBackendApi::kMetal:
+#ifdef SK_METAL
+ return GrMtlFormatIsBGRA(format.asMtlFormat());
+#else
+ return false;
+#endif
+ case GrBackendApi::kDawn:
+ return false;
+ case GrBackendApi::kOpenGL:
+#ifdef SK_GL
+ return format.asGLFormat() == GrGLFormat::kBGRA8;
+#else
+ return false;
+#endif
+ case GrBackendApi::kVulkan: {
+#ifdef SK_VULKAN
+ VkFormat vkFormat;
+ format.asVkFormat(&vkFormat);
+ return vkFormat == VK_FORMAT_B8G8R8A8_UNORM;
+#else
+ return false;
+#endif
+ }
+ case GrBackendApi::kMock:
+ return format.asMockColorType() == GrColorType::kBGRA_8888;
+ }
+ SkUNREACHABLE;
+}
+
+static bool isRGB(const GrBackendFormat& format) {
+ switch (format.backend()) {
+ case GrBackendApi::kMetal:
+ return false; // Metal doesn't even pretend to support this
+ case GrBackendApi::kDawn:
+ return false;
+ case GrBackendApi::kOpenGL:
+#ifdef SK_GL
+ return format.asGLFormat() == GrGLFormat::kRGB8;
+#else
+ return false;
+#endif
+ case GrBackendApi::kVulkan: {
+#ifdef SK_VULKAN
+ VkFormat vkFormat;
+ format.asVkFormat(&vkFormat);
+ return vkFormat == VK_FORMAT_R8G8B8_UNORM;
+#else
+ return false;
+#endif
+ }
+ case GrBackendApi::kMock:
+ return false; // No GrColorType::kRGB_888
+ }
+ SkUNREACHABLE;
+}
+
static void check_solid_pixmap(skiatest::Reporter* reporter,
const SkColor4f& expected, const SkPixmap& actual,
- SkColorType ct, const char* label) {
+ SkColorType ct, const char* label1, const char* label2) {
// we need 0.001f across the board just for noise
// we need 0.01f across the board for 1010102
- const float tols[4] = {0.01f, 0.01f, 0.01f, 0.01f};
+ const float tols[4] = { 0.01f, 0.01f, 0.01f, 0.01f };
auto error = std::function<ComparePixmapsErrorReporter>(
- [reporter, ct, label](int x, int y, const float diffs[4]) {
+ [reporter, ct, label1, label2](int x, int y, const float diffs[4]) {
SkASSERT(x >= 0 && y >= 0);
- ERRORF(reporter, "%s %s - mismatch at %d, %d (%f, %f, %f %f)",
- ToolUtils::colortype_name(ct), label, x, y,
+ ERRORF(reporter, "%s %s %s - mismatch at %d, %d (%f, %f, %f %f)",
+ ToolUtils::colortype_name(ct), label1, label2, x, y,
diffs[0], diffs[1], diffs[2], diffs[3]);
});
check_solid_pixels(expected, actual, tols, error);
}
+// What would raster do?
static SkColor4f get_expected_color(SkColor4f orig, SkColorType ct) {
-
- uint32_t components = SkColorTypeComponentFlags(ct);
-
- if (components & kGray_SkColorTypeComponentFlag) {
- // For the GPU backends, gray implies a single channel which is opaque.
- return { orig.fA, orig.fA, orig.fA, 1 };
+ if (ct == kGray_8_SkColorType) {
+ // Prevent the premul raster graciously applies in this case
+ orig.fA = 1.0;
}
- float r = orig.fR, g = orig.fG, b = orig.fB, a = orig.fA;
+ SkAlphaType at = SkColorTypeIsAlwaysOpaque(ct) ? kOpaque_SkAlphaType
+ : kPremul_SkAlphaType;
- // Missing channels are set to 0
- if (!(components & kRed_SkColorTypeComponentFlag)) {
- r = 0;
- }
- if (!(components & kGreen_SkColorTypeComponentFlag)) {
- g = 0;
- }
- if (!(components & kBlue_SkColorTypeComponentFlag)) {
- b = 0;
- }
- // except for missing alpha - which gets set to 1
- if (!(components & kAlpha_SkColorTypeComponentFlag)) {
- a = 1;
- }
-
- return { r, g, b, a };
+ SkImageInfo ii = SkImageInfo::Make(2, 2, ct, at);
+ SkAutoPixmapStorage pm;
+ pm.alloc(ii);
+ pm.erase(orig);
+ SkColor tmp = pm.getColor(0, 0);
+ return SkColor4f::FromColor(tmp);
}
static void check_mipmaps(GrContext* context, const GrBackendTexture& backendTex,
SkColorType skColorType, const SkColor4f expectedColors[6],
- skiatest::Reporter* reporter);
+ skiatest::Reporter* reporter, const char* label);
static void check_base_readbacks(GrContext* context, const GrBackendTexture& backendTex,
SkColorType skColorType, GrRenderable renderable,
- const SkColor4f& color, skiatest::Reporter* reporter) {
+ const SkColor4f& color, skiatest::Reporter* reporter,
+ const char* label) {
+ if (isRGB(backendTex.getBackendFormat())) {
+ // readPixels is busted for the RGB backend format (skbug.com/8862)
+ // TODO: add a GrColorType::kRGB_888 to fix the situation
+ return;
+ }
SkAlphaType at = SkColorTypeIsAlwaysOpaque(skColorType) ? kOpaque_SkAlphaType
: kPremul_SkAlphaType;
@@ -157,28 +215,11 @@
{
SkImageInfo readBackII = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType,
- kPremul_SkAlphaType);
+ kUnpremul_SkAlphaType);
SkAssertResult(actual.tryAlloc(readBackII));
}
- if (GrRenderable::kYes == renderable && context->colorTypeSupportedAsSurface(skColorType)) {
- sk_sp<SkSurface> surf = SkSurface::MakeFromBackendTexture(context,
- backendTex,
- kTopLeft_GrSurfaceOrigin,
- 0,
- skColorType,
- nullptr, nullptr);
- if (surf) {
- actual.erase(SkColors::kTransparent);
- bool result = surf->readPixels(actual, 0, 0);
- REPORTER_ASSERT(reporter, result);
-
- check_solid_pixmap(reporter, expectedColor, actual, skColorType,
- "SkSurface::readPixels");
- }
- }
-
{
sk_sp<SkImage> img = SkImage::MakeFromTexture(context,
backendTex,
@@ -197,10 +238,29 @@
#endif
} else {
check_solid_pixmap(reporter, expectedColor, actual, skColorType,
- "SkImage::readPixels");
+ label, "SkImage::readPixels");
}
}
}
+
+ // This will mark any mipmaps as dirty (bc that is what we do when we wrap a renderable
+ // backend texture) so it must be done last!
+ if (GrRenderable::kYes == renderable && context->colorTypeSupportedAsSurface(skColorType)) {
+ sk_sp<SkSurface> surf = SkSurface::MakeFromBackendTexture(context,
+ backendTex,
+ kTopLeft_GrSurfaceOrigin,
+ 0,
+ skColorType,
+ nullptr, nullptr);
+ if (surf) {
+ actual.erase(SkColors::kTransparent);
+ bool result = surf->readPixels(actual, 0, 0);
+ REPORTER_ASSERT(reporter, result);
+
+ check_solid_pixmap(reporter, expectedColor, actual, skColorType,
+ label, "SkSurface::readPixels");
+ }
+ }
}
// Test initialization of GrBackendObjects to a specific color (non-static since used in Mtl test)
@@ -226,15 +286,16 @@
return;
}
- check_base_readbacks(context, backendTex, skColorType, renderable, color, reporter);
-
if (mipMapped == GrMipMapped::kYes) {
SkColor4f expectedColor = get_expected_color(color, skColorType);
SkColor4f expectedColors[6] = { expectedColor, expectedColor, expectedColor,
expectedColor, expectedColor, expectedColor };
- check_mipmaps(context, backendTex, skColorType, expectedColors, reporter);
+ check_mipmaps(context, backendTex, skColorType, expectedColors, reporter, "colorinit");
}
+ // The last step in this test will dirty the mipmaps so do it last
+ check_base_readbacks(context, backendTex, skColorType, renderable, color,
+ reporter, "colorinit");
context->deleteBackendTexture(backendTex);
}
@@ -242,7 +303,7 @@
// all the mipMap levels.
static void check_mipmaps(GrContext* context, const GrBackendTexture& backendTex,
SkColorType skColorType, const SkColor4f expectedColors[6],
- skiatest::Reporter* reporter) {
+ skiatest::Reporter* reporter, const char* label) {
#ifdef SK_GL
// skbug.com/9141 (RGBA_F32 mipmaps appear to be broken on some Mali devices)
@@ -256,8 +317,15 @@
}
#endif
+ if (isRGB(backendTex.getBackendFormat())) {
+ // readPixels is busted for the RGB backend format (skbug.com/8862)
+ // TODO: add a GrColorType::kRGB_888 to fix the situation
+ return;
+ }
+
SkAlphaType at = SkColorTypeIsAlwaysOpaque(skColorType) ? kOpaque_SkAlphaType
: kPremul_SkAlphaType;
+
sk_sp<SkImage> img = SkImage::MakeFromTexture(context,
backendTex,
kTopLeft_GrSurfaceOrigin,
@@ -268,11 +336,12 @@
return;
}
- SkImageInfo newII = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
+ SkImageInfo readbackSurfaceII = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType,
+ kPremul_SkAlphaType);
sk_sp<SkSurface> surf = SkSurface::MakeRenderTarget(context,
SkBudgeted::kNo,
- newII, 1,
+ readbackSurfaceII, 1,
kTopLeft_GrSurfaceOrigin,
nullptr);
if (!surf) {
@@ -295,7 +364,7 @@
SkImageInfo readbackII = SkImageInfo::Make(rectSize, rectSize,
kRGBA_8888_SkColorType,
- kPremul_SkAlphaType);
+ kUnpremul_SkAlphaType);
SkAutoPixmapStorage actual2;
SkAssertResult(actual2.tryAlloc(readbackII));
actual2.erase(SkColors::kTransparent);
@@ -303,10 +372,83 @@
bool result = surf->readPixels(actual2, 0, 0);
REPORTER_ASSERT(reporter, result);
- check_solid_pixmap(reporter, expectedColors[i], actual2, skColorType, "mip-level failure");
+ check_solid_pixmap(reporter, expectedColors[i], actual2, skColorType,
+ label, "mip-level failure");
}
}
+static int make_pixmaps(SkColorType skColorType, GrMipMapped mipMapped,
+ const SkColor4f colors[6], SkAutoPixmapStorage pixmaps[6]) {
+ int levelSize = 32;
+ int numMipLevels = mipMapped == GrMipMapped::kYes ? 6 : 1;
+ SkAlphaType at = SkColorTypeIsAlwaysOpaque(skColorType) ? kOpaque_SkAlphaType
+ : kPremul_SkAlphaType;
+ for (int level = 0; level < numMipLevels; ++level) {
+ SkImageInfo ii = SkImageInfo::Make(levelSize, levelSize, skColorType, at);
+ pixmaps[level].alloc(ii);
+ pixmaps[level].erase(colors[level]);
+ levelSize /= 2;
+ }
+ return numMipLevels;
+}
+
+// Test initialization of GrBackendObjects using SkPixmaps
+static void test_pixmap_init(GrContext* context, skiatest::Reporter* reporter,
+ std::function<GrBackendTexture (GrContext*,
+ const SkPixmap srcData[],
+ int numLevels,
+ GrRenderable)> create,
+ SkColorType skColorType, GrMipMapped mipMapped,
+ GrRenderable renderable) {
+ SkAutoPixmapStorage pixmapMem[6];
+ SkColor4f colors[6] = {
+ { 1.0f, 0.0f, 0.0f, 1.0f }, // R
+ { 0.0f, 1.0f, 0.0f, 0.9f }, // G
+ { 0.0f, 0.0f, 1.0f, 0.7f }, // B
+ { 0.0f, 1.0f, 1.0f, 0.5f }, // C
+ { 1.0f, 0.0f, 1.0f, 0.3f }, // M
+ { 1.0f, 1.0f, 0.0f, 0.2f }, // Y
+ };
+
+ int numMipLevels = make_pixmaps(skColorType, mipMapped, colors, pixmapMem);
+ SkASSERT(numMipLevels);
+
+ // TODO: this is tedious. Should we pass in an array of SkBitmaps instead?
+ SkPixmap pixmaps[6];
+ for (int i = 0; i < numMipLevels; ++i) {
+ pixmaps[i].reset(pixmapMem[i].info(), pixmapMem[i].addr(), pixmapMem[i].rowBytes());
+ }
+
+ GrBackendTexture backendTex = create(context, pixmaps, numMipLevels, renderable);
+ if (!backendTex.isValid()) {
+ // errors here should be reported by the test_wrapping test
+ return;
+ }
+
+ if (skColorType == kBGRA_8888_SkColorType && !isBGRA(backendTex.getBackendFormat())) {
+ // When kBGRA is backed by an RGBA something goes wrong in the swizzling
+ return;
+ }
+
+ if (mipMapped == GrMipMapped::kYes) {
+ SkColor4f expectedColors[6] = {
+ get_expected_color(colors[0], skColorType),
+ get_expected_color(colors[1], skColorType),
+ get_expected_color(colors[2], skColorType),
+ get_expected_color(colors[3], skColorType),
+ get_expected_color(colors[4], skColorType),
+ get_expected_color(colors[5], skColorType),
+ };
+
+ check_mipmaps(context, backendTex, skColorType, expectedColors, reporter, "pixmap");
+ }
+
+ // The last step in this test will dirty the mipmaps so do it last
+ check_base_readbacks(context, backendTex, skColorType, renderable, colors[0],
+ reporter, "pixmap");
+ context->deleteBackendTexture(backendTex);
+}
+
enum class VkLayout {
kUndefined,
kReadOnlyOptimal,
@@ -452,11 +594,11 @@
{ kRGBA_F16Norm_SkColorType, SkColors::kLtGray },
{ kRGBA_F16_SkColorType, SkColors::kYellow },
{ kRGBA_F32_SkColorType, SkColors::kGray },
- { kR8G8_unorm_SkColorType, { .25f, .75f, 0, 0 } },
+ { kR8G8_unorm_SkColorType, { .25f, .75f, 0, 1 } },
{ kR16G16_unorm_SkColorType, SkColors::kGreen },
{ kA16_unorm_SkColorType, kTransCol },
{ kA16_float_SkColorType, kTransCol },
- { kR16G16_float_SkColorType, { .25f, .75f, 0, 0 } },
+ { kR16G16_float_SkColorType, { .25f, .75f, 0, 1 } },
{ kR16G16B16A16_unorm_SkColorType,{ .25f, .5f, .75f, 1 } },
};
@@ -482,6 +624,7 @@
renderable).isValid()) {
continue;
}
+
if (GrRenderable::kYes == renderable) {
if (kRGB_888x_SkColorType == combo.fColorType) {
// Ganesh can't perform the blends correctly when rendering this format
@@ -549,10 +692,41 @@
SkColorTypeToGrColorType(colorType),
combo.fColor, mipMapped, renderable);
}
+
+ // Gray_8 is problematic. In the colorInit tests there is ambiguity when
+ // mapping from format to colorType (since R8 or A8 could be either Alpha_8
+ // or Gray_8). To compensate for this ambiguity we feed in colors with
+ // R==G==B==A. If we actually do know the colorType (as is the case
+ // in the SkPixmap case, there is no ambiguity but the two test expectations
+ // now collide.
+ // For now, skip the SkPixmap tests. The real answer is to plumb the
+ // SkColorType down further in the color-init case.
+ if (colorType != kGray_8_SkColorType) {
+ auto createWithSrcDataMtd = [](GrContext* context,
+ const SkPixmap srcData[],
+ int numLevels,
+ GrRenderable renderable) {
+ SkASSERT(srcData && numLevels);
+ auto result = context->priv().createBackendTexture(srcData, numLevels,
+ renderable,
+ GrProtected::kNo);
+ check_vk_layout(result, VkLayout::kReadOnlyOptimal);
+#ifdef SK_DEBUG
+ {
+ auto format = context->defaultBackendFormat(srcData[0].colorType(),
+ renderable);
+ SkASSERT(format == result.getBackendFormat());
+ }
+#endif
+ return result;
+ };
+
+ test_pixmap_init(context, reporter, createWithSrcDataMtd, colorType,
+ mipMapped, renderable);
+ }
}
}
}
-
}
///////////////////////////////////////////////////////////////////////////////
@@ -692,7 +866,7 @@
const GrVkCaps* vkCaps = static_cast<const GrVkCaps*>(context->priv().caps());
constexpr SkColor4f kTransCol { 0, 0.25f, 0.75f, 0.5f };
- constexpr SkColor4f kGrayCol { 0.75f, 0.75f, 0.75f, 0.75f };
+ constexpr SkColor4f kGrayCol { 0.75f, 0.75f, 0.75f, 1 };
struct {
GrColorType fColorType;
diff --git a/tests/MtlBackendAllocationTest.mm b/tests/MtlBackendAllocationTest.mm
index a9384cb..d3bfc79 100644
--- a/tests/MtlBackendAllocationTest.mm
+++ b/tests/MtlBackendAllocationTest.mm
@@ -32,10 +32,11 @@
const GrMtlCaps* mtlCaps = static_cast<const GrMtlCaps*>(context->priv().caps());
constexpr SkColor4f kTransCol { 0, 0.25f, 0.75f, 0.5f };
+ constexpr SkColor4f kGrayCol { 0.75f, 0.75f, 0.75f, 0.75f };
struct {
GrColorType fColorType;
- MTLPixelFormat fFormat;
+ MTLPixelFormat fFormat;
SkColor4f fColor;
} combinations[] = {
{ GrColorType::kRGBA_8888, MTLPixelFormatRGBA8Unorm, SkColors::kRed },
@@ -56,7 +57,7 @@
{ GrColorType::kAlpha_8, MTLPixelFormatA8Unorm, kTransCol },
{ GrColorType::kAlpha_8, MTLPixelFormatR8Unorm, kTransCol },
- { GrColorType::kGray_8, MTLPixelFormatR8Unorm, SkColors::kDkGray },
+ { GrColorType::kGray_8, MTLPixelFormatR8Unorm, kGrayCol },
{ GrColorType::kRGBA_F32, MTLPixelFormatRGBA32Float, SkColors::kRed },
@@ -114,7 +115,6 @@
combo.fColorType, mipMapped, renderable);
}
- // Not implemented for Metal yet
{
auto createWithColorMtd = [format](GrContext* context,
const SkColor4f& color,