Add SkSurfaceCharacterization::isCompatible
Although the main change in this CL is the addition of GrCaps::areColorTypeAndFormatCompatible.
This is split out of:
https://skia-review.googlesource.com/c/skia/+/222781 (Add bridge between GrContext::createBackendTexture and SkSurface::MakeFromBackendTexture)
Change-Id: I2e50fff91eb07fb1358840e1a4a76dc138a2f195
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/223932
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/include/core/SkSurfaceCharacterization.h b/include/core/SkSurfaceCharacterization.h
index 774b0b8..97b72ab 100644
--- a/include/core/SkSurfaceCharacterization.h
+++ b/include/core/SkSurfaceCharacterization.h
@@ -82,6 +82,9 @@
sk_sp<SkColorSpace> refColorSpace() const { return fImageInfo.refColorSpace(); }
const SkSurfaceProps& surfaceProps()const { return fSurfaceProps; }
+ // Is the provided backend texture compatible with this surface characterization?
+ bool isCompatible(const GrBackendTexture&) const;
+
private:
friend class SkSurface_Gpu; // for 'set' & 'config'
friend class GrVkSecondaryCBDrawContext; // for 'set' & 'config'
diff --git a/include/private/GrTypesPriv.h b/include/private/GrTypesPriv.h
index bcf6c24..6a0902f 100644
--- a/include/private/GrTypesPriv.h
+++ b/include/private/GrTypesPriv.h
@@ -1392,9 +1392,9 @@
return GrPixelConfigToColorTypeAndEncoding(config, &bogusEncoded);
}
-static constexpr GrPixelConfig GrColorTypeToPixelConfig(GrColorType config,
+static constexpr GrPixelConfig GrColorTypeToPixelConfig(GrColorType colorType,
GrSRGBEncoded srgbEncoded) {
- switch (config) {
+ switch (colorType) {
case GrColorType::kUnknown:
return kUnknown_GrPixelConfig;
case GrColorType::kAlpha_8:
diff --git a/src/core/SkSurfaceCharacterization.cpp b/src/core/SkSurfaceCharacterization.cpp
index a73c6e7..a051547 100644
--- a/src/core/SkSurfaceCharacterization.cpp
+++ b/src/core/SkSurfaceCharacterization.cpp
@@ -49,4 +49,58 @@
fVulkanSecondaryCBCompatible, fSurfaceProps);
}
+bool SkSurfaceCharacterization::isCompatible(const GrBackendTexture& backendTex) const {
+ if (!this->isValid() || !backendTex.isValid()) {
+ return false;
+ }
+
+ const GrCaps* caps = fContextInfo->priv().caps();
+
+ // TODO: remove this block involving the pixel config
+ {
+ GrPixelConfig config = caps->getConfigFromBackendFormat(backendTex.getBackendFormat(),
+ this->colorType());
+ if (GrPixelConfig::kUnknown_GrPixelConfig == config) {
+ return false;
+ }
+
+ if (this->config() != config) {
+ return false;
+ }
+ }
+
+ if (this->usesGLFBO0()) {
+ // It is a backend texture so can't be wrapping FBO0
+ return false;
+ }
+
+ if (this->vulkanSecondaryCBCompatible()) {
+ return false;
+ }
+
+ int maxColorSamples = caps->maxRenderTargetSampleCount(this->colorType(),
+ backendTex.getBackendFormat());
+ if (0 == maxColorSamples) {
+ return false; // backendTex isn't renderable
+ }
+
+ if (this->isMipMapped() && !backendTex.hasMipMaps()) {
+ // backend texture is allowed to have mipmaps even if the characterization doesn't require
+ // them.
+ return false;
+ }
+
+ if (!caps->areColorTypeAndFormatCompatible(this->colorType(), backendTex.getBackendFormat())) {
+ return false;
+ }
+
+ if (this->width() != backendTex.width() || this->height() != backendTex.height()) {
+ return false;
+ }
+
+ // TODO: need to check protected status here
+ return true;
+}
+
+
#endif
diff --git a/src/gpu/GrCaps.h b/src/gpu/GrCaps.h
index 67e2209..275fc79 100644
--- a/src/gpu/GrCaps.h
+++ b/src/gpu/GrCaps.h
@@ -349,6 +349,8 @@
virtual GrPixelConfig validateBackendRenderTarget(const GrBackendRenderTarget&,
SkColorType) const = 0;
+ virtual bool areColorTypeAndFormatCompatible(SkColorType ct, const GrBackendFormat&) const = 0;
+
// TODO: replace validateBackendRenderTarget with calls to getConfigFromBackendFormat?
// TODO: it seems like we could pass the full SkImageInfo and validate its colorSpace too
// Returns kUnknown if a valid config could not be determined.
diff --git a/src/gpu/GrContextThreadSafeProxy.cpp b/src/gpu/GrContextThreadSafeProxy.cpp
index 8da3afe..8bf5afb 100644
--- a/src/gpu/GrContextThreadSafeProxy.cpp
+++ b/src/gpu/GrContextThreadSafeProxy.cpp
@@ -38,6 +38,8 @@
return SkSurfaceCharacterization(); // return an invalid characterization
}
+ SkASSERT(isTextureable || !isMipMapped);
+
if (GrBackendApi::kOpenGL != backendFormat.backend() && willUseGLFBO0) {
// The willUseGLFBO0 flags can only be used for a GL backend.
return SkSurfaceCharacterization(); // return an invalid characterization
diff --git a/src/gpu/GrProxyProvider.cpp b/src/gpu/GrProxyProvider.cpp
index cb2cefa..c7d4de9 100644
--- a/src/gpu/GrProxyProvider.cpp
+++ b/src/gpu/GrProxyProvider.cpp
@@ -422,8 +422,8 @@
// SkColorType are correct.
return true;
}
- GrPixelConfig testConfig = caps->getConfigFromBackendFormat(format, colorType);
- return testConfig != kUnknown_GrPixelConfig;
+
+ return caps->areColorTypeAndFormatCompatible(colorType, format);
}
#endif
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index a1dfca6..cba9277 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -3621,6 +3621,16 @@
return validate_sized_format(fbInfo.fFormat, ct, fStandard);
}
+bool GrGLCaps::areColorTypeAndFormatCompatible(SkColorType ct,
+ const GrBackendFormat& format) const {
+ const GrGLenum* glFormat = format.getGLFormat();
+ if (!glFormat) {
+ return false;
+ }
+
+ return kUnknown_GrPixelConfig != validate_sized_format(*glFormat, ct, fStandard);
+}
+
GrPixelConfig GrGLCaps::getConfigFromBackendFormat(const GrBackendFormat& format,
SkColorType ct) const {
const GrGLenum* glFormat = format.getGLFormat();
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index d9cb6e6..c3e8918 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -427,6 +427,8 @@
GrPixelConfig validateBackendRenderTarget(const GrBackendRenderTarget&,
SkColorType) const override;
+ bool areColorTypeAndFormatCompatible(SkColorType, const GrBackendFormat&) const override;
+
GrPixelConfig getConfigFromBackendFormat(const GrBackendFormat&, SkColorType) const override;
GrPixelConfig getYUVAConfigFromBackendFormat(const GrBackendFormat&) const override;
diff --git a/src/gpu/mock/GrMockCaps.h b/src/gpu/mock/GrMockCaps.h
index ff39757..b4b005f 100644
--- a/src/gpu/mock/GrMockCaps.h
+++ b/src/gpu/mock/GrMockCaps.h
@@ -124,6 +124,84 @@
return kUnknown_GrPixelConfig;
}
+ bool areColorTypeAndFormatCompatible(SkColorType ct,
+ const GrBackendFormat& format) const override {
+ const GrPixelConfig* mockFormat = format.getMockFormat();
+ if (!mockFormat) {
+ return kUnknown_GrPixelConfig;
+ }
+
+ switch (ct) {
+ case kUnknown_SkColorType:
+ return false;
+ case kAlpha_8_SkColorType:
+ if (kAlpha_8_GrPixelConfig == *mockFormat ||
+ kAlpha_8_as_Alpha_GrPixelConfig == *mockFormat ||
+ kAlpha_8_as_Red_GrPixelConfig == *mockFormat) {
+ return true;
+ }
+ break;
+ case kRGB_565_SkColorType:
+ if (kRGB_565_GrPixelConfig == *mockFormat) {
+ return true;
+ }
+ break;
+ case kARGB_4444_SkColorType:
+ if (kRGBA_4444_GrPixelConfig == *mockFormat) {
+ return true;
+ }
+ break;
+ case kRGBA_8888_SkColorType:
+ if (kRGBA_8888_GrPixelConfig == *mockFormat ||
+ kSRGBA_8888_GrPixelConfig == *mockFormat) {
+ return true;
+ }
+ break;
+ case kRGB_888x_SkColorType:
+ if (kRGB_888X_GrPixelConfig == *mockFormat ||
+ kRGB_888_GrPixelConfig == *mockFormat) {
+ return true;
+ }
+ break;
+ case kBGRA_8888_SkColorType:
+ if (kBGRA_8888_GrPixelConfig == *mockFormat) {
+ return true;
+ }
+ break;
+ case kRGBA_1010102_SkColorType:
+ if (kRGBA_1010102_GrPixelConfig == *mockFormat) {
+ return true;
+ }
+ break;
+ case kRGB_101010x_SkColorType:
+ return false;
+ case kGray_8_SkColorType:
+ if (kGray_8_GrPixelConfig == *mockFormat ||
+ kGray_8_as_Lum_GrPixelConfig == *mockFormat ||
+ kGray_8_as_Red_GrPixelConfig == *mockFormat) {
+ return true;
+ }
+ break;
+ case kRGBA_F16Norm_SkColorType:
+ if (kRGBA_half_Clamped_GrPixelConfig == *mockFormat) {
+ return true;
+ }
+ break;
+ case kRGBA_F16_SkColorType:
+ if (kRGBA_half_GrPixelConfig == *mockFormat) {
+ return true;
+ }
+ break;
+ case kRGBA_F32_SkColorType:
+ if (kRGBA_float_GrPixelConfig == *mockFormat) {
+ return true;
+ }
+ break;
+ }
+
+ return false;
+ }
+
GrPixelConfig getConfigFromBackendFormat(const GrBackendFormat& format,
SkColorType ct) const override {
const GrPixelConfig* mockFormat = format.getMockFormat();
diff --git a/src/gpu/mtl/GrMtlCaps.h b/src/gpu/mtl/GrMtlCaps.h
index adebbce..8de71ce 100644
--- a/src/gpu/mtl/GrMtlCaps.h
+++ b/src/gpu/mtl/GrMtlCaps.h
@@ -67,6 +67,8 @@
GrPixelConfig validateBackendRenderTarget(const GrBackendRenderTarget&,
SkColorType) const override;
+ bool areColorTypeAndFormatCompatible(SkColorType, const GrBackendFormat&) const override;
+
GrPixelConfig getConfigFromBackendFormat(const GrBackendFormat&, SkColorType) const override;
GrPixelConfig getYUVAConfigFromBackendFormat(const GrBackendFormat&) const override;
diff --git a/src/gpu/mtl/GrMtlCaps.mm b/src/gpu/mtl/GrMtlCaps.mm
index dc3469a..b662578 100644
--- a/src/gpu/mtl/GrMtlCaps.mm
+++ b/src/gpu/mtl/GrMtlCaps.mm
@@ -566,6 +566,17 @@
return validate_sized_format(texture.pixelFormat, ct);
}
+bool GrMtlCaps::areColorTypeAndFormatCompatible(SkColorType ct,
+ const GrBackendFormat& format) const {
+ const GrMTLPixelFormat* mtlFormat = format.getMtlFormat();
+ if (!mtlFormat) {
+ return false;
+ }
+
+ return kUnknown_GrPixelConfig != validate_sized_format(*mtlFormat, ct);
+}
+
+
GrPixelConfig GrMtlCaps::getConfigFromBackendFormat(const GrBackendFormat& format,
SkColorType ct) const {
const GrMTLPixelFormat* mtlFormat = format.getMtlFormat();
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 7d28cd8..aa4bac3 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -1026,6 +1026,18 @@
return validate_image_info(imageInfo.fFormat, ct, imageInfo.fYcbcrConversionInfo.isValid());
}
+bool GrVkCaps::areColorTypeAndFormatCompatible(SkColorType ct,
+ const GrBackendFormat& format) const {
+ const VkFormat* vkFormat = format.getVkFormat();
+ const GrVkYcbcrConversionInfo* ycbcrInfo = format.getVkYcbcrConversionInfo();
+ if (!vkFormat || !ycbcrInfo) {
+ return false;
+ }
+
+ return kUnknown_GrPixelConfig != validate_image_info(*vkFormat, ct, ycbcrInfo->isValid());
+}
+
+
GrPixelConfig GrVkCaps::getConfigFromBackendFormat(const GrBackendFormat& format,
SkColorType ct) const {
const VkFormat* vkFormat = format.getVkFormat();
diff --git a/src/gpu/vk/GrVkCaps.h b/src/gpu/vk/GrVkCaps.h
index c859121..771d8e9 100644
--- a/src/gpu/vk/GrVkCaps.h
+++ b/src/gpu/vk/GrVkCaps.h
@@ -164,6 +164,8 @@
GrPixelConfig validateBackendRenderTarget(const GrBackendRenderTarget&,
SkColorType) const override;
+ bool areColorTypeAndFormatCompatible(SkColorType, const GrBackendFormat&) const override;
+
GrPixelConfig getConfigFromBackendFormat(const GrBackendFormat&, SkColorType) const override;
GrPixelConfig getYUVAConfigFromBackendFormat(const GrBackendFormat&) const override;
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index cc1b978..5a6e388 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -351,6 +351,10 @@
return nullptr;
}
+ if (c.vulkanSecondaryCBCompatible()) {
+ return nullptr;
+ }
+
const GrBackendFormat format = caps->getBackendFormatFromColorType(c.colorType());
if (!format.isValid()) {
return nullptr;
diff --git a/tests/DeferredDisplayListTest.cpp b/tests/DeferredDisplayListTest.cpp
index 6a3bdbf..e5c1f84 100644
--- a/tests/DeferredDisplayListTest.cpp
+++ b/tests/DeferredDisplayListTest.cpp
@@ -113,10 +113,12 @@
case 9:
if (GrBackendApi::kOpenGL == fBackend) {
fUsesGLFBO0 = true;
+ fShouldCreateMipMaps = false; // needs to changed in tandem w/ textureability
fIsTextureable = false;
}
break;
case 10:
+ fShouldCreateMipMaps = false; // needs to changed in tandem w/ textureability
fIsTextureable = false;
break;
}
@@ -199,6 +201,10 @@
return nullptr;
}
+ // Even if a characterization couldn't be constructed we want to soldier on to make
+ // sure that surface creation will/would've also failed
+ SkASSERT(!c.isValid() || c.isCompatible(*backend));
+
sk_sp<SkSurface> surface;
if (!fIsTextureable) {
// Create a surface w/ the current parameters but make it non-textureable
@@ -212,10 +218,12 @@
}
if (!surface) {
+ SkASSERT(!c.isValid());
this->cleanUpBackEnd(context, *backend);
return nullptr;
}
+ SkASSERT(c.isValid());
SkASSERT(surface->isCompatible(c));
return surface;
}
@@ -409,6 +417,7 @@
{
GrBackendTexture backend;
SurfaceParameters params(context->backend());
+ params.setShouldCreateMipMaps(false);
params.setTextureable(false);
sk_sp<SkSurface> s = params.make(context, &backend);
@@ -480,10 +489,11 @@
for (bool textureability : { true, false }) {
std::unique_ptr<SkDeferredDisplayList> ddl;
- // First, create a DDL w/o textureability. TODO: once we have reusable DDLs, move this
- // outside of the loop.
+ // First, create a DDL w/o textureability (and thus no mipmaps). TODO: once we have
+ // reusable DDLs, move this outside of the loop.
{
SurfaceParameters params(context->backend());
+ params.setShouldCreateMipMaps(false);
params.setTextureable(false);
ddl = params.createDDL(context);
@@ -492,6 +502,7 @@
// Then verify it can draw into either flavor of destination
SurfaceParameters params(context->backend());
+ params.setShouldCreateMipMaps(textureability);
params.setTextureable(textureability);
GrBackendTexture backend;
@@ -543,6 +554,7 @@
}
REPORTER_ASSERT(reporter, c.isValid());
+ REPORTER_ASSERT(reporter, c.isCompatible(backend));
REPORTER_ASSERT(reporter, s->isCompatible(c));
// Note that we're leaving 'backend' live here
}