Update SkSurface_Gpu::Valid to take a backend format

This is pulled out of:

https://skia-review.googlesource.com/c/skia/+/222781 (Add bridge between GrContext::createBackendTexture and SkSurface::MakeFromBackendTexture)

Change-Id: I0c26bba2592a6e6fe759b49de83f994b05d862a2
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/223698
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2019-06-25 15:59:50 -04:00 committed by Skia Commit-Bot
parent a5d1e67428
commit f209e882fe
21 changed files with 191 additions and 80 deletions

View File

@ -354,6 +354,9 @@ public:
bool getMtlTextureInfo(GrMtlTextureInfo*) const;
#endif
// Get the GrBackendFormat for this render target (or an invalid format if this is not valid).
GrBackendFormat getBackendFormat() const;
// If the backend API is Mock, copies a snapshot of the GrMockTextureInfo struct into the passed
// in pointer and returns true. Otherwise returns false if the backend API is not Mock.
bool getMockRenderTargetInfo(GrMockRenderTargetInfo*) const;
@ -409,7 +412,9 @@ private:
GrBackendApi fBackend;
union {
#ifdef SK_GL
GrGLFramebufferInfo fGLInfo;
#endif
GrVkBackendSurfaceInfo fVkInfo;
GrMockRenderTargetInfo fMockInfo;
};

View File

@ -401,6 +401,7 @@ static const int kGrSLTypeCount = kLast_GrSLType + 1;
* and sampling parameters are legal for proxies that will be instantiated with wrapped textures.
*/
enum class GrTextureType {
kNone,
k2D,
/* Rectangle uses unnormalized texture coordinates. */
kRectangle,
@ -564,6 +565,9 @@ static inline GrSLType GrSLCombinedSamplerTypeForTextureType(GrTextureType type)
return kTexture2DRectSampler_GrSLType;
case GrTextureType::kExternal:
return kTextureExternalSampler_GrSLType;
default:
SK_ABORT("Unexpected texture type");
return kTexture2DSampler_GrSLType;
}
SK_ABORT("Unexpected texture type");
return kTexture2DSampler_GrSLType;
@ -578,6 +582,9 @@ static inline bool GrTextureTypeHasRestrictedSampling(GrTextureType type) {
return true;
case GrTextureType::kExternal:
return true;
default:
SK_ABORT("Unexpected texture type");
return false;
}
SK_ABORT("Unexpected texture type");
return false;

View File

@ -25,6 +25,9 @@ GrBackendFormat::GrBackendFormat(GrGLenum format, GrGLenum target)
, fValid(true)
, fGLFormat(format) {
switch (target) {
case GR_GL_TEXTURE_NONE:
fTextureType = GrTextureType::kNone;
break;
case GR_GL_TEXTURE_2D:
fTextureType = GrTextureType::k2D;
break;
@ -48,10 +51,13 @@ const GrGLenum* GrBackendFormat::getGLFormat() const {
const GrGLenum* GrBackendFormat::getGLTarget() const {
if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
static constexpr GrGLenum kNone = GR_GL_TEXTURE_NONE;
static constexpr GrGLenum k2D = GR_GL_TEXTURE_2D;
static constexpr GrGLenum kRect = GR_GL_TEXTURE_RECTANGLE;
static constexpr GrGLenum kExternal = GR_GL_TEXTURE_EXTERNAL;
switch (fTextureType) {
case GrTextureType::kNone:
return &kNone;
case GrTextureType::k2D:
return &k2D;
case GrTextureType::kRectangle:
@ -692,6 +698,39 @@ bool GrBackendRenderTarget::getGLFramebufferInfo(GrGLFramebufferInfo* outInfo) c
return false;
}
GrBackendFormat GrBackendRenderTarget::getBackendFormat() const {
if (!this->isValid()) {
return GrBackendFormat();
}
switch (fBackend) {
#ifdef SK_GL
case GrBackendApi::kOpenGL:
return GrBackendFormat::MakeGL(fGLInfo.fFormat, GR_GL_TEXTURE_NONE);
#endif
#ifdef SK_VULKAN
case GrBackendApi::kVulkan: {
auto info = fVkInfo.snapImageInfo();
if (info.fYcbcrConversionInfo.isValid()) {
SkASSERT(info.fFormat == VK_FORMAT_UNDEFINED);
return GrBackendFormat::MakeVk(info.fYcbcrConversionInfo);
}
return GrBackendFormat::MakeVk(info.fFormat);
}
#endif
#ifdef SK_METAL
case GrBackendApi::kMetal: {
GrMtlTextureInfo mtlInfo;
SkAssertResult(this->getMtlTextureInfo(&mtlInfo));
return GrBackendFormat::MakeMtl(GrGetMTLPixelFormatFromMtlTextureInfo(mtlInfo));
}
#endif
case GrBackendApi::kMock:
return GrBackendFormat::MakeMock(fMockInfo.fConfig);
default:
return GrBackendFormat();
}
}
bool GrBackendRenderTarget::getMockRenderTargetInfo(GrMockRenderTargetInfo* outInfo) const {
if (this->isValid() && GrBackendApi::kMock == fBackend) {
*outInfo = fMockInfo;

View File

@ -157,6 +157,8 @@ public:
return this->maxWindowRectangles() > 0 && this->onIsWindowRectanglesSupportedForRT(rt);
}
virtual bool isFormatSRGB(const GrBackendFormat&) const = 0;
virtual bool isFormatTexturable(SkColorType, const GrBackendFormat&) const = 0;
virtual bool isConfigTexturable(GrPixelConfig) const = 0;

View File

@ -47,12 +47,7 @@ SkSurfaceCharacterization GrContextThreadSafeProxy::createCharacterization(
isMipMapped = false;
}
GrPixelConfig config = this->caps()->getConfigFromBackendFormat(backendFormat, ii.colorType());
if (config == kUnknown_GrPixelConfig) {
return SkSurfaceCharacterization(); // return an invalid characterization
}
if (!SkSurface_Gpu::Valid(this->caps(), config, ii.colorSpace())) {
if (!SkSurface_Gpu::Valid(this->caps(), backendFormat)) {
return SkSurfaceCharacterization(); // return an invalid characterization
}
@ -70,6 +65,11 @@ SkSurfaceCharacterization GrContextThreadSafeProxy::createCharacterization(
return SkSurfaceCharacterization(); // return an invalid characterization
}
GrPixelConfig config = this->caps()->getConfigFromBackendFormat(backendFormat, ii.colorType());
if (kUnknown_GrPixelConfig == config) {
return SkSurfaceCharacterization(); // return an invalid characterization
}
return SkSurfaceCharacterization(sk_ref_sp<GrContextThreadSafeProxy>(this),
cacheMaxResourceBytes, ii,
origin, config, sampleCnt,

View File

@ -752,7 +752,7 @@ sk_sp<GrRenderTargetContext> GrDrawingManager::makeRenderTargetContext(
// SkSurface catches bad color space usage at creation. This check handles anything that slips
// by, including internal usage.
if (!SkSurface_Gpu::Valid(fContext->priv().caps(), sProxy->config(), colorSpace.get())) {
if (!SkSurface_Gpu::Valid(fContext->priv().caps(), sProxy->backendFormat())) {
SkDEBUGFAIL("Invalid config and colorspace combination");
return nullptr;
}
@ -777,7 +777,7 @@ sk_sp<GrTextureContext> GrDrawingManager::makeTextureContext(sk_sp<GrSurfaceProx
// SkSurface catches bad color space usage at creation. This check handles anything that slips
// by, including internal usage.
if (!SkSurface_Gpu::Valid(fContext->priv().caps(), sProxy->config(), colorSpace.get())) {
if (!SkSurface_Gpu::Valid(fContext->priv().caps(), sProxy->backendFormat())) {
SkDEBUGFAIL("Invalid config and colorspace combination");
return nullptr;
}

View File

@ -34,6 +34,10 @@ static inline uint16_t texture_type_key(GrTextureType type) {
case GrTextureType::kRectangle:
value = 2;
break;
default:
SK_ABORT("Unexpected texture type");
value = 3;
break;
}
SkASSERT((value & ((1 << kSamplerOrImageTypeKeyBits) - 1)) == value);
return SkToU16(value);

View File

@ -3108,6 +3108,25 @@ bool GrGLCaps::onIsWindowRectanglesSupportedForRT(const GrBackendRenderTarget& b
return fbInfo.fFBOID != 0;
}
static bool format_is_srgb(GrGLenum format) {
SkASSERT(GrGLFormatIsSupported(format));
switch (format) {
case GR_GL_SRGB8_ALPHA8:
return true;
default:
return false;
}
}
bool GrGLCaps::isFormatSRGB(const GrBackendFormat& format) const {
if (!format.getGLFormat()) {
return false;
}
return format_is_srgb(*format.getGLFormat());
}
bool GrGLCaps::isFormatTexturable(SkColorType ct, const GrBackendFormat& format) const {
GrPixelConfig config = this->getConfigFromBackendFormat(format, ct);
if (kUnknown_GrPixelConfig == config) {

View File

@ -106,6 +106,8 @@ public:
GrGLCaps(const GrContextOptions& contextOptions, const GrGLContextInfo& ctxInfo,
const GrGLInterface* glInterface);
bool isFormatSRGB(const GrBackendFormat& format) const override;
bool isFormatTexturable(SkColorType, const GrBackendFormat&) const override;
bool isConfigTexturable(GrPixelConfig config) const override {

View File

@ -147,6 +147,7 @@
/* GL_ALWAYS */
/* EnableCap */
#define GR_GL_TEXTURE_NONE 0x0000
#define GR_GL_TEXTURE_2D 0x0DE1
#define GR_GL_CULL_FACE 0x0B44
#define GR_GL_BLEND 0x0BE2

View File

@ -36,6 +36,9 @@ static inline GrGLenum target_from_texture_type(GrTextureType type) {
return GR_GL_TEXTURE_RECTANGLE;
case GrTextureType::kExternal:
return GR_GL_TEXTURE_EXTERNAL;
default:
SK_ABORT("Unexpected texture target");
return GR_GL_TEXTURE_2D;
}
SK_ABORT("Unexpected texture type");
return GR_GL_TEXTURE_2D;

View File

@ -646,3 +646,33 @@ size_t GrGLBytesPerFormat(GrGLenum glFormat) {
SK_ABORT("Invalid GL format");
return 0;
}
bool GrGLFormatIsSupported(GrGLenum format) {
switch (format) {
case GR_GL_LUMINANCE8:
case GR_GL_ALPHA8:
case GR_GL_R8:
case GR_GL_RGB565:
case GR_GL_RGBA4:
case GR_GL_RG8:
case GR_GL_R16F:
case GR_GL_R16:
case GR_GL_RGB8:
case GR_GL_RGBA8:
case GR_GL_SRGB8_ALPHA8:
case GR_GL_BGRA8:
case GR_GL_RGB10_A2:
case GR_GL_RG16:
case GR_GL_RGBA16F:
case GR_GL_RG32F:
case GR_GL_RGBA32F:
case GR_GL_COMPRESSED_RGB8_ETC2:
case GR_GL_COMPRESSED_ETC1_RGB8:
// Experimental (for Y416 and mutant P016/P010)
case GR_GL_RG16F:
case GR_GL_RGBA16:
return true;
default:
return false;
}
}

View File

@ -277,4 +277,6 @@ size_t GrGLFormatCompressedDataSize(GrGLenum glFormat, int width, int height);
size_t GrGLBytesPerFormat(GrGLenum glFormat);
bool GrGLFormatIsSupported(GrGLenum format);
#endif

View File

@ -36,6 +36,15 @@ public:
this->applyOptionsOverrides(contextOptions);
}
bool isFormatSRGB(const GrBackendFormat& format) const override {
if (!format.getMockFormat()) {
return false;
}
return kSRGBA_8888_GrPixelConfig == *format.getMockFormat() ||
kSBGRA_8888_GrPixelConfig == *format.getMockFormat();
}
bool isFormatTexturable(SkColorType, const GrBackendFormat& format) const override {
if (!format.getMockFormat()) {
return false;

View File

@ -26,6 +26,8 @@ public:
GrMtlCaps(const GrContextOptions& contextOptions, id<MTLDevice> device,
MTLFeatureSet featureSet);
bool isFormatSRGB(const GrBackendFormat& format) const override;
bool isFormatTexturable(SkColorType, const GrBackendFormat&) const override;
bool isConfigTexturable(GrPixelConfig config) const override {

View File

@ -231,6 +231,24 @@ void GrMtlCaps::initGrCaps(const id<MTLDevice> device) {
fHalfFloatVertexAttributeSupport = true;
}
static bool format_is_srgb(MTLPixelFormat format) {
switch (format) {
case MTLPixelFormatRGBA8Unorm_sRGB:
case MTLPixelFormatBGRA8Unorm_sRGB:
return true;
default:
return false;
}
}
bool GrMtlCaps::isFormatSRGB(const GrBackendFormat& format) const {
if (!format.getMtlFormat()) {
return false;
}
return format_is_srgb(static_cast<MTLPixelFormat>(*format.getMtlFormat()));
}
bool GrMtlCaps::isFormatTexturable(SkColorType ct, const GrBackendFormat& format) const {
GrPixelConfig config = this->getConfigFromBackendFormat(format, ct);
if (kUnknown_GrPixelConfig == config) {

View File

@ -645,32 +645,13 @@ void GrVkCaps::initStencilFormat(const GrVkInterface* interface, VkPhysicalDevic
}
static bool format_is_srgb(VkFormat format) {
SkASSERT(GrVkFormatIsSupported(format));
switch (format) {
case VK_FORMAT_R8G8B8A8_SRGB:
case VK_FORMAT_B8G8R8A8_SRGB:
return true;
case VK_FORMAT_R8G8B8A8_UNORM:
case VK_FORMAT_B8G8R8A8_UNORM:
case VK_FORMAT_R8G8B8_UNORM:
case VK_FORMAT_R8G8_UNORM:
case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
case VK_FORMAT_R5G6B5_UNORM_PACK16:
case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
case VK_FORMAT_R8_UNORM:
case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
case VK_FORMAT_R32G32B32A32_SFLOAT:
case VK_FORMAT_R32G32_SFLOAT:
case VK_FORMAT_R16G16B16A16_SFLOAT:
case VK_FORMAT_R16_SFLOAT:
case VK_FORMAT_R16_UNORM:
case VK_FORMAT_R16G16_UNORM:
// Experimental (for Y416 and mutant P016/P010)
case VK_FORMAT_R16G16B16A16_UNORM:
case VK_FORMAT_R16G16_SFLOAT:
return false;
default:
SK_ABORT("Unsupported VkFormat");
return false;
}
}
@ -804,6 +785,14 @@ void GrVkCaps::FormatInfo::init(const GrVkInterface* interface,
}
}
bool GrVkCaps::isFormatSRGB(const GrBackendFormat& format) const {
if (!format.getVkFormat()) {
return false;
}
return format_is_srgb(*format.getVkFormat());
}
bool GrVkCaps::isFormatTexturable(SkColorType, const GrBackendFormat& format) const {
if (!format.getVkFormat()) {
return false;

View File

@ -32,6 +32,8 @@ public:
uint32_t instanceVersion, uint32_t physicalDeviceVersion,
const GrVkExtensions& extensions, GrProtected isProtected = GrProtected::kNo);
bool isFormatSRGB(const GrBackendFormat& format) const override;
bool isFormatTexturable(SkColorType, const GrBackendFormat&) const override;
bool isFormatTexturable(VkFormat) const;
bool isConfigTexturable(GrPixelConfig config) const override;

View File

@ -169,6 +169,7 @@ bool GrVkFormatIsSupported(VkFormat format) {
case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
case VK_FORMAT_R5G6B5_UNORM_PACK16:
case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
case VK_FORMAT_R8_UNORM:
case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
case VK_FORMAT_R32G32B32A32_SFLOAT:

View File

@ -329,18 +329,12 @@ bool SkSurface_Gpu::onDraw(const SkDeferredDisplayList* ddl) {
///////////////////////////////////////////////////////////////////////////////
bool SkSurface_Gpu::Valid(const SkImageInfo& info) {
return true;
}
bool SkSurface_Gpu::Valid(const GrCaps* caps, GrPixelConfig config, SkColorSpace* colorSpace) {
switch (config) {
case kSRGBA_8888_GrPixelConfig:
case kSBGRA_8888_GrPixelConfig:
return caps->srgbSupport();
default:
return true;
bool SkSurface_Gpu::Valid(const GrCaps* caps, const GrBackendFormat& format) {
if (caps->isFormatSRGB(format)) {
return caps->srgbSupport();
}
return true;
}
sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrRecordingContext* context,
@ -350,12 +344,19 @@ sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrRecordingContext* context,
return nullptr;
}
const GrCaps* caps = context->priv().caps();
if (c.usesGLFBO0()) {
// If we are making the surface we will never use FBO0.
return nullptr;
}
if (!SkSurface_Gpu::Valid(context->priv().caps(), c.config(), c.colorSpace())) {
const GrBackendFormat format = caps->getBackendFormatFromColorType(c.colorType());
if (!format.isValid()) {
return nullptr;
}
if (!SkSurface_Gpu::Valid(caps, format)) {
return nullptr;
}
@ -368,9 +369,6 @@ sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrRecordingContext* context,
desc.fConfig = c.config();
desc.fSampleCnt = c.sampleCount();
const GrBackendFormat format =
context->priv().caps()->getBackendFormatFromColorType(c.colorType());
sk_sp<GrSurfaceContext> sc(
context->priv().makeDeferredSurfaceContext(format,
desc,
@ -412,9 +410,6 @@ sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext* ctx, SkBudgeted budgeted
if (!ctx) {
return nullptr;
}
if (!SkSurface_Gpu::Valid(info)) {
return nullptr;
}
sampleCount = SkTMax(1, sampleCount);
GrMipMapped mipMapped = shouldCreateWithMips ? GrMipMapped::kYes : GrMipMapped::kNo;
@ -448,19 +443,12 @@ sk_sp<SkSurface> SkSurface_Gpu::MakeWrappedRenderTarget(GrContext* context,
return sk_make_sp<SkSurface_Gpu>(std::move(device));
}
bool validate_backend_texture(GrContext* ctx, const GrBackendTexture& tex, GrPixelConfig* config,
int sampleCnt, SkColorType ct, sk_sp<SkColorSpace> cs,
bool texturable) {
static bool validate_backend_texture(GrContext* ctx, const GrBackendTexture& tex,
GrPixelConfig* config, int sampleCnt, SkColorType ct,
bool texturable) {
if (!tex.isValid()) {
return false;
}
// TODO: Create a SkImageColorInfo struct for color, alpha, and color space so we don't need to
// create a fake image info here.
SkImageInfo info = SkImageInfo::Make(1, 1, ct, kPremul_SkAlphaType, cs);
if (!SkSurface_Gpu::Valid(info)) {
return false;
}
GrBackendFormat backendFormat = tex.getBackendFormat();
if (!backendFormat.isValid()) {
@ -473,11 +461,11 @@ bool validate_backend_texture(GrContext* ctx, const GrBackendTexture& tex, GrPix
// We don't require that the client gave us an exact valid sample cnt. However, it must be
// less than the max supported sample count and 1 if MSAA is unsupported for the color type.
if (!ctx->priv().caps()->getRenderTargetSampleCount(sampleCnt, *config)) {
if (!ctx->priv().caps()->getRenderTargetSampleCount(sampleCnt, ct, backendFormat)) {
return false;
}
if (texturable && !ctx->priv().caps()->isConfigTexturable(*config)) {
if (texturable && !ctx->priv().caps()->isFormatTexturable(ct, backendFormat)) {
return false;
}
return true;
@ -496,27 +484,20 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext* context, const GrB
sampleCnt = SkTMax(1, sampleCnt);
GrBackendTexture texCopy = tex;
if (!validate_backend_texture(context, texCopy, &texCopy.fConfig,
sampleCnt, colorType, colorSpace, true)) {
sampleCnt, colorType, true)) {
return nullptr;
}
if (!context) {
return nullptr;
}
if (!SkSurface_Gpu::Valid(context->priv().caps(), texCopy.config(), colorSpace.get())) {
if (!SkSurface_Gpu::Valid(context->priv().caps(), texCopy.getBackendFormat())) {
return nullptr;
}
sampleCnt = SkTMax(1, sampleCnt);
sk_sp<GrRenderTargetContext> rtc(context->priv().makeBackendTextureRenderTargetContext(
texCopy,
origin,
sampleCnt,
SkColorTypeToGrColorType(colorType),
std::move(colorSpace),
props,
textureReleaseProc,
releaseContext));
texCopy, origin, sampleCnt, SkColorTypeToGrColorType(colorType),
std::move(colorSpace), props, textureReleaseProc, releaseContext));
if (!rtc) {
return nullptr;
}
@ -566,7 +547,7 @@ bool SkSurface_Gpu::onReplaceBackendTexture(const GrBackendTexture& backendTextu
GrBackendTexture texCopy = backendTexture;
auto colorSpace = sk_ref_sp(oldRTC->colorSpaceInfo().colorSpace());
if (!validate_backend_texture(context, texCopy, &texCopy.fConfig, sampleCnt,
this->getCanvas()->imageInfo().colorType(), colorSpace, true)) {
this->getCanvas()->imageInfo().colorType(), true)) {
return false;
}
sk_sp<GrRenderTargetContext> rtc(context->priv().makeBackendTextureRenderTargetContext(
@ -591,10 +572,6 @@ bool validate_backend_render_target(GrContext* ctx, const GrBackendRenderTarget&
// create a fake image info here.
SkImageInfo info = SkImageInfo::Make(1, 1, ct, kPremul_SkAlphaType, cs);
if (!SkSurface_Gpu::Valid(info)) {
return false;
}
*config = ctx->priv().caps()->validateBackendRenderTarget(rt, ct);
if (*config == kUnknown_GrPixelConfig) {
return false;
@ -627,7 +604,7 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext* context,
if (!validate_backend_render_target(context, rtCopy, &rtCopy.fConfig, colorType, colorSpace)) {
return nullptr;
}
if (!SkSurface_Gpu::Valid(context->priv().caps(), rtCopy.config(), colorSpace.get())) {
if (!SkSurface_Gpu::Valid(context->priv().caps(), rtCopy.getBackendFormat())) {
return nullptr;
}
@ -666,11 +643,11 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext* cont
sampleCnt = SkTMax(1, sampleCnt);
GrBackendTexture texCopy = tex;
if (!validate_backend_texture(context, texCopy, &texCopy.fConfig,
sampleCnt, colorType, colorSpace, false)) {
sampleCnt, colorType, false)) {
return nullptr;
}
if (!SkSurface_Gpu::Valid(context->priv().caps(), texCopy.config(), colorSpace.get())) {
if (!SkSurface_Gpu::Valid(context->priv().caps(), texCopy.getBackendFormat())) {
return nullptr;
}

View File

@ -55,8 +55,7 @@ public:
SkGpuDevice* getDevice() { return fDevice.get(); }
static bool Valid(const SkImageInfo&);
static bool Valid(const GrCaps*, GrPixelConfig, SkColorSpace*);
static bool Valid(const GrCaps*, const GrBackendFormat&);
private:
sk_sp<SkGpuDevice> fDevice;