Hide GrPixelConfig in SkSurfaceCharacterization

TBR=bsalomon@google.com
Change-Id: Ifc38d0ca2b18128d27c187f789461fea62d1edae
Reviewed-on: https://skia-review.googlesource.com/117440
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Robert Phillips 2018-04-03 17:17:05 -04:00 committed by Skia Commit-Bot
parent ae52cccf8b
commit be77a02a67
9 changed files with 499 additions and 124 deletions

View File

@ -34,8 +34,6 @@ public:
SkSurfaceCharacterization()
: fCacheMaxResourceBytes(0)
, fOrigin(kBottomLeft_GrSurfaceOrigin)
, fWidth(0)
, fHeight(0)
, fConfig(kUnknown_GrPixelConfig)
, fFSAAType(GrFSAAType::kNone)
, fStencilCnt(0)
@ -63,8 +61,9 @@ public:
return SkSurfaceCharacterization(fContextInfo,
fCacheMaxResourceBytes,
fOrigin, width, height, fConfig, fFSAAType, fStencilCnt,
fIsTextureable, fIsMipMapped, fColorSpace,
fImageInfo.makeWH(width, height),
fOrigin, fConfig, fFSAAType, fStencilCnt,
fIsTextureable, fIsMipMapped,
fSurfaceProps);
}
@ -72,85 +71,84 @@ public:
sk_sp<GrContextThreadSafeProxy> refContextInfo() const { return fContextInfo; }
size_t cacheMaxResourceBytes() const { return fCacheMaxResourceBytes; }
bool isValid() const { return kUnknown_GrPixelConfig != fConfig; }
bool isValid() const { return kUnknown_SkColorType != fImageInfo.colorType(); }
const SkImageInfo& imageInfo() const { return fImageInfo; }
GrSurfaceOrigin origin() const { return fOrigin; }
int width() const { return fWidth; }
int height() const { return fHeight; }
GrPixelConfig config() const { return fConfig; }
int width() const { return fImageInfo.width(); }
int height() const { return fImageInfo.height(); }
SkColorType colorType() const { return fImageInfo.colorType(); }
GrFSAAType fsaaType() const { return fFSAAType; }
int stencilCount() const { return fStencilCnt; }
bool isTextureable() const { return Textureable::kYes == fIsTextureable; }
bool isMipMapped() const { return MipMapped::kYes == fIsMipMapped; }
SkColorSpace* colorSpace() const { return fColorSpace.get(); }
sk_sp<SkColorSpace> refColorSpace() const { return fColorSpace; }
SkColorSpace* colorSpace() const { return fImageInfo.colorSpace(); }
sk_sp<SkColorSpace> refColorSpace() const { return fImageInfo.refColorSpace(); }
const SkSurfaceProps& surfaceProps()const { return fSurfaceProps; }
private:
friend class SkSurface_Gpu; // for 'set'
friend class SkSurface_Gpu; // for 'set' & 'config'
friend class GrContextThreadSafeProxy; // for private ctor
friend class SkDeferredDisplayListRecorder; // for 'config'
friend class SkSurface; // for 'config'
GrPixelConfig config() const { return fConfig; }
SkSurfaceCharacterization(sk_sp<GrContextThreadSafeProxy> contextInfo,
size_t cacheMaxResourceBytes,
GrSurfaceOrigin origin, int width, int height,
GrPixelConfig config, GrFSAAType FSAAType, int stencilCnt,
const SkImageInfo& ii,
GrSurfaceOrigin origin,
GrPixelConfig config,
GrFSAAType FSAAType, int stencilCnt,
Textureable isTextureable, MipMapped isMipMapped,
sk_sp<SkColorSpace> colorSpace,
const SkSurfaceProps& surfaceProps)
: fContextInfo(std::move(contextInfo))
, fCacheMaxResourceBytes(cacheMaxResourceBytes)
, fImageInfo(ii)
, fOrigin(origin)
, fWidth(width)
, fHeight(height)
, fConfig(config)
, fFSAAType(FSAAType)
, fStencilCnt(stencilCnt)
, fIsTextureable(isTextureable)
, fIsMipMapped(isMipMapped)
, fColorSpace(std::move(colorSpace))
, fSurfaceProps(surfaceProps) {
}
void set(sk_sp<GrContextThreadSafeProxy> contextInfo,
size_t cacheMaxResourceBytes,
const SkImageInfo& ii,
GrSurfaceOrigin origin,
int width, int height,
GrPixelConfig config,
GrFSAAType fsaaType,
int stencilCnt,
Textureable isTextureable,
MipMapped isMipMapped,
sk_sp<SkColorSpace> colorSpace,
const SkSurfaceProps& surfaceProps) {
SkASSERT(MipMapped::kNo == isMipMapped || Textureable::kYes == isTextureable);
fContextInfo = contextInfo;
fCacheMaxResourceBytes = cacheMaxResourceBytes;
fImageInfo = ii;
fOrigin = origin;
fWidth = width;
fHeight = height;
fConfig = config;
fFSAAType = fsaaType;
fStencilCnt = stencilCnt;
fIsTextureable = isTextureable;
fIsMipMapped = isMipMapped;
fColorSpace = std::move(colorSpace);
fSurfaceProps = surfaceProps;
}
sk_sp<GrContextThreadSafeProxy> fContextInfo;
size_t fCacheMaxResourceBytes;
SkImageInfo fImageInfo;
GrSurfaceOrigin fOrigin;
int fWidth;
int fHeight;
GrPixelConfig fConfig;
GrFSAAType fFSAAType;
int fStencilCnt;
Textureable fIsTextureable;
MipMapped fIsMipMapped;
sk_sp<SkColorSpace> fColorSpace;
SkSurfaceProps fSurfaceProps;
};

View File

@ -177,10 +177,6 @@ SkSurfaceCharacterization GrContextThreadSafeProxy::createCharacterization(
return SkSurfaceCharacterization(); // return an invalid characterization
}
if (!SkSurface_Gpu::Valid(ii)) {
return SkSurfaceCharacterization(); // return an invalid characterization
}
if (!fCaps->mipMapSupport()) {
isMipMapped = false;
}
@ -190,6 +186,10 @@ SkSurfaceCharacterization GrContextThreadSafeProxy::createCharacterization(
return SkSurfaceCharacterization(); // return an invalid characterization
}
if (!SkSurface_Gpu::Valid(fCaps.get(), config, ii.colorSpace())) {
return SkSurfaceCharacterization(); // return an invalid characterization
}
sampleCnt = fCaps->getRenderTargetSampleCount(sampleCnt, config);
if (!sampleCnt) {
return SkSurfaceCharacterization(); // return an invalid characterization
@ -207,11 +207,11 @@ SkSurfaceCharacterization GrContextThreadSafeProxy::createCharacterization(
}
return SkSurfaceCharacterization(sk_ref_sp<GrContextThreadSafeProxy>(this),
cacheMaxResourceBytes,
origin, ii.width(), ii.height(), config, FSAAType, sampleCnt,
cacheMaxResourceBytes, ii,
origin, config, FSAAType, sampleCnt,
SkSurfaceCharacterization::Textureable(true),
SkSurfaceCharacterization::MipMapped(isMipMapped),
ii.refColorSpace(), surfaceProps);
surfaceProps);
}
void GrContext::abandonContext() {

View File

@ -476,7 +476,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, sProxy->config(), colorSpace.get())) {
if (!SkSurface_Gpu::Valid(fContext->caps(), sProxy->config(), colorSpace.get())) {
SkDEBUGFAIL("Invalid config and colorspace combination");
return nullptr;
}
@ -499,7 +499,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, sProxy->config(), colorSpace.get())) {
if (!SkSurface_Gpu::Valid(fContext->caps(), sProxy->config(), colorSpace.get())) {
SkDEBUGFAIL("Invalid config and colorspace combination");
return nullptr;
}

View File

@ -10,7 +10,6 @@
#include "GrCaps.h"
#include "GrShaderCaps.h"
#include "gl/GrGLCaps.h"
#include "GrContext.h"
#include "GrContextPriv.h"
#include "GrGpu.h"

View File

@ -6,8 +6,9 @@
*/
#include "GrXferProcessor.h"
#include "GrCaps.h"
#include "GrPipeline.h"
#include "gl/GrGLCaps.h"
GrXferProcessor::GrXferProcessor(ClassID classID)
: INHERITED(classID)

View File

@ -416,6 +416,10 @@ public:
bool getConfigFromBackendFormat(const GrBackendFormat&, SkColorType,
GrPixelConfig*) const override;
#if GR_TEST_UTILS
GrGLStandard standard() const { return fStandard; }
#endif
private:
enum ExternalFormatUsage {
kTexImage_ExternalFormatUsage,

View File

@ -163,7 +163,7 @@ bool SkSurface_Gpu::onWait(int numSemaphores, const GrBackendSemaphore* waitSema
return fDevice->wait(numSemaphores, waitSemaphores);
}
bool SkSurface_Gpu::onCharacterize(SkSurfaceCharacterization* data) const {
bool SkSurface_Gpu::onCharacterize(SkSurfaceCharacterization* characterization) const {
GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
GrContext* ctx = fDevice->context();
@ -174,21 +174,28 @@ bool SkSurface_Gpu::onCharacterize(SkSurfaceCharacterization* data) const {
bool mipmapped = rtc->asTextureProxy() ? GrMipMapped::kYes == rtc->asTextureProxy()->mipMapped()
: false;
data->set(ctx->threadSafeProxy(), maxResourceBytes,
rtc->origin(), rtc->width(), rtc->height(),
rtc->colorSpaceInfo().config(), rtc->fsaaType(), rtc->numStencilSamples(),
SkSurfaceCharacterization::Textureable(SkToBool(rtc->asTextureProxy())),
SkSurfaceCharacterization::MipMapped(mipmapped),
rtc->colorSpaceInfo().refColorSpace(), this->props());
// TODO: the addition of colorType to the surfaceContext should remove this calculation
SkColorType ct;
if (!GrPixelConfigToColorType(rtc->colorSpaceInfo().config(), &ct)) {
return false;
}
SkImageInfo ii = SkImageInfo::Make(rtc->width(), rtc->height(), ct, kPremul_SkAlphaType,
rtc->colorSpaceInfo().refColorSpace());
characterization->set(ctx->threadSafeProxy(), maxResourceBytes, ii, rtc->origin(),
rtc->colorSpaceInfo().config(), rtc->fsaaType(), rtc->numStencilSamples(),
SkSurfaceCharacterization::Textureable(SkToBool(rtc->asTextureProxy())),
SkSurfaceCharacterization::MipMapped(mipmapped), this->props());
return true;
}
bool SkSurface_Gpu::isCompatible(const SkSurfaceCharacterization& data) const {
bool SkSurface_Gpu::isCompatible(const SkSurfaceCharacterization& characterization) const {
GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
GrContext* ctx = fDevice->context();
if (!data.isValid()) {
if (!characterization.isValid()) {
return false;
}
@ -199,7 +206,7 @@ bool SkSurface_Gpu::isCompatible(const SkSurfaceCharacterization& data) const {
size_t maxResourceBytes;
ctx->getResourceCacheLimits(&maxResourceCount, &maxResourceBytes);
if (data.isTextureable()) {
if (characterization.isTextureable()) {
if (!rtc->asTextureProxy()) {
// If the characterization was textureable we require the replay dest to also be
// textureable. If the characterized surface wasn't textureable we allow the replay
@ -207,20 +214,32 @@ bool SkSurface_Gpu::isCompatible(const SkSurfaceCharacterization& data) const {
return false;
}
if (data.isMipMapped() && GrMipMapped::kNo == rtc->asTextureProxy()->mipMapped()) {
if (characterization.isMipMapped() &&
GrMipMapped::kNo == rtc->asTextureProxy()->mipMapped()) {
// Fail if the DDL's surface was mipmapped but the replay surface is not.
// Allow drawing to proceed if the DDL was not mipmapped but the replay surface is.
return false;
}
}
return data.contextInfo() && data.contextInfo()->matches(ctx) &&
data.cacheMaxResourceBytes() <= maxResourceBytes &&
data.origin() == rtc->origin() && data.width() == rtc->width() &&
data.height() == rtc->height() && data.config() == rtc->colorSpaceInfo().config() &&
data.fsaaType() == rtc->fsaaType() && data.stencilCount() == rtc->numStencilSamples() &&
SkColorSpace::Equals(data.colorSpace(), rtc->colorSpaceInfo().colorSpace()) &&
data.surfaceProps() == rtc->surfaceProps();
// TODO: the addition of colorType to the surfaceContext should remove this calculation
SkColorType rtcColorType;
if (!GrPixelConfigToColorType(rtc->colorSpaceInfo().config(), &rtcColorType)) {
return false;
}
return characterization.contextInfo() && characterization.contextInfo()->matches(ctx) &&
characterization.cacheMaxResourceBytes() <= maxResourceBytes &&
characterization.origin() == rtc->origin() &&
characterization.config() == rtc->colorSpaceInfo().config() &&
characterization.width() == rtc->width() &&
characterization.height() == rtc->height() &&
characterization.colorType() == rtcColorType &&
characterization.fsaaType() == rtc->fsaaType() &&
characterization.stencilCount() == rtc->numStencilSamples() &&
SkColorSpace::Equals(characterization.colorSpace(),
rtc->colorSpaceInfo().colorSpace()) &&
characterization.surfaceProps() == rtc->surfaceProps();
}
bool SkSurface_Gpu::onDraw(const SkDeferredDisplayList* ddl) {
@ -250,19 +269,19 @@ bool SkSurface_Gpu::Valid(const SkImageInfo& info) {
}
}
bool SkSurface_Gpu::Valid(GrContext* context, GrPixelConfig config, SkColorSpace* colorSpace) {
bool SkSurface_Gpu::Valid(const GrCaps* caps, GrPixelConfig config, SkColorSpace* colorSpace) {
switch (config) {
case kRGBA_half_GrPixelConfig:
return (!colorSpace) || colorSpace->gammaIsLinear();
case kSRGBA_8888_GrPixelConfig:
case kSBGRA_8888_GrPixelConfig:
return context->caps()->srgbSupport() && colorSpace && colorSpace->gammaCloseToSRGB();
return caps->srgbSupport() && colorSpace && colorSpace->gammaCloseToSRGB();
case kRGBA_8888_GrPixelConfig:
case kBGRA_8888_GrPixelConfig:
// We may get here with either a linear-gamma color space or with a sRGB-gamma color
// space when we lack GPU sRGB support.
return !colorSpace ||
(colorSpace->gammaCloseToSRGB() && !context->caps()->srgbSupport()) ||
(colorSpace->gammaCloseToSRGB() && !caps->srgbSupport()) ||
colorSpace->gammaIsLinear();
default:
return !colorSpace;
@ -272,20 +291,49 @@ bool SkSurface_Gpu::Valid(GrContext* context, GrPixelConfig config, SkColorSpace
sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext* context,
const SkSurfaceCharacterization& c,
SkBudgeted budgeted) {
if (!c.isValid()) {
if (!context || !c.isValid()) {
return nullptr;
}
SkColorType ct;
if (!GrPixelConfigToColorType(c.config(), &ct)) {
if (!SkSurface_Gpu::Valid(context->caps(), c.config(), c.colorSpace())) {
return nullptr;
}
SkImageInfo ii = SkImageInfo::Make(c.width(), c.height(), ct, kPremul_SkAlphaType,
c.refColorSpace());
// In order to ensure compatibility we have to match the backend format (i.e. the GrPixelConfig
// of the characterization)
GrSurfaceDesc desc;
desc.fFlags = kRenderTarget_GrSurfaceFlag;
desc.fWidth = c.width();
desc.fHeight = c.height();
desc.fConfig = c.config();
desc.fSampleCnt = c.stencilCount();
return MakeRenderTarget(context, budgeted, ii, c.stencilCount(), c.origin(),
&c.surfaceProps(), c.isMipMapped());
sk_sp<GrSurfaceContext> sc(
context->contextPriv().makeDeferredSurfaceContext(desc, c.origin(),
GrMipMapped(c.isMipMapped()),
SkBackingFit::kExact, budgeted,
c.refColorSpace(),
&c.surfaceProps()));
if (!sc || !sc->asRenderTargetContext()) {
return nullptr;
}
sk_sp<SkGpuDevice> device(SkGpuDevice::Make(context, sk_ref_sp(sc->asRenderTargetContext()),
c.width(), c.height(),
SkGpuDevice::kClear_InitContents));
if (!device) {
return nullptr;
}
sk_sp<SkSurface> s = sk_make_sp<SkSurface_Gpu>(std::move(device));
#ifdef SK_DEBUG
if (s) {
SkSurface_Gpu* gpuSurface = static_cast<SkSurface_Gpu*>(s.get());
SkASSERT(gpuSurface->isCompatible(c));
}
#endif
return s;
}
@ -377,7 +425,7 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext* context, const GrB
if (!context) {
return nullptr;
}
if (!SkSurface_Gpu::Valid(context, texCopy.config(), colorSpace.get())) {
if (!SkSurface_Gpu::Valid(context->caps(), texCopy.config(), colorSpace.get())) {
return nullptr;
}
sampleCnt = SkTMax(1, sampleCnt);
@ -440,7 +488,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, rtCopy.config(), colorSpace.get())) {
if (!SkSurface_Gpu::Valid(context->caps(), rtCopy.config(), colorSpace.get())) {
return nullptr;
}
@ -475,7 +523,7 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext* cont
if (!context) {
return nullptr;
}
if (!SkSurface_Gpu::Valid(context, tex.config(), colorSpace.get())) {
if (!SkSurface_Gpu::Valid(context->caps(), tex.config(), colorSpace.get())) {
return nullptr;
}
sampleCnt = SkTMax(1, sampleCnt);

View File

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

View File

@ -24,40 +24,230 @@
#include "Test.h"
#include "gl/GrGLDefines.h"
#include "gl/GrGLCaps.h"
#ifdef SK_VULKAN
#include "vk/GrVkDefines.h"
#endif
static GrBackendFormat create_backend_format(GrContext* context, SkColorType colorType) {
// Try to create a backend format from the provided colorType and config. Return an invalid
// backend format if the combination is infeasible.
static GrBackendFormat create_backend_format(GrContext* context,
SkColorType ct, SkColorSpace* cs,
GrPixelConfig config) {
const GrCaps* caps = context->caps();
// TODO: what should be done if we have a colorspace that doesn't have a gammaCloseToSRGB?
switch (context->contextPriv().getBackend()) {
case kOpenGL_GrBackend:
if (kRGBA_8888_SkColorType == colorType) {
GrGLenum format = caps->srgbSupport() ? GR_GL_SRGB8_ALPHA8 : GR_GL_RGBA8;
return GrBackendFormat::MakeGL(format, GR_GL_TEXTURE_2D);
} else if (kRGBA_F16_SkColorType == colorType) {
return GrBackendFormat::MakeGL(GR_GL_RGBA16F, GR_GL_TEXTURE_2D);
case kOpenGL_GrBackend: {
const GrGLCaps* glCaps = static_cast<const GrGLCaps*>(context->caps());
GrGLStandard standard = glCaps->standard();
switch (ct) {
case kUnknown_SkColorType:
return GrBackendFormat();
case kAlpha_8_SkColorType:
if (kAlpha_8_as_Alpha_GrPixelConfig == config) {
return GrBackendFormat::MakeGL(GR_GL_ALPHA8, GR_GL_TEXTURE_2D);
} else if (kAlpha_8_GrPixelConfig == config ||
kAlpha_8_as_Red_GrPixelConfig == config) {
return GrBackendFormat::MakeGL(GR_GL_R8, GR_GL_TEXTURE_2D);
}
break;
case kRGB_565_SkColorType:
if (kRGB_565_GrPixelConfig == config) {
return GrBackendFormat::MakeGL(GR_GL_RGB565, GR_GL_TEXTURE_2D);
}
break;
case kARGB_4444_SkColorType:
if (kRGBA_4444_GrPixelConfig == config) {
return GrBackendFormat::MakeGL(GR_GL_RGBA4, GR_GL_TEXTURE_2D);
}
break;
case kRGBA_8888_SkColorType:
if (kRGBA_8888_GrPixelConfig == config) {
if (!cs || (cs->gammaCloseToSRGB() && !caps->srgbSupport())) {
return GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_2D);
}
} else if (kSRGBA_8888_GrPixelConfig == config) {
if (caps->srgbSupport() && cs && cs->gammaCloseToSRGB()) {
return GrBackendFormat::MakeGL(GR_GL_SRGB8_ALPHA8, GR_GL_TEXTURE_2D);
}
}
break;
case kRGB_888x_SkColorType:
if (kRGB_888_GrPixelConfig == config) {
return GrBackendFormat::MakeGL(GR_GL_RGB8, GR_GL_TEXTURE_2D);
}
break;
case kBGRA_8888_SkColorType:
if (kBGRA_8888_GrPixelConfig == config) {
if (kGL_GrGLStandard == standard) {
return GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_2D);
} else if (kGLES_GrGLStandard == standard) {
return GrBackendFormat::MakeGL(GR_GL_BGRA8, GR_GL_TEXTURE_2D);
}
} else if (kSBGRA_8888_GrPixelConfig == config) {
if (caps->srgbSupport() && cs && cs->gammaCloseToSRGB()) {
return GrBackendFormat::MakeGL(GR_GL_SRGB8_ALPHA8, GR_GL_TEXTURE_2D);
}
}
break;
case kRGBA_1010102_SkColorType:
if (kRGBA_1010102_GrPixelConfig == config) {
return GrBackendFormat::MakeGL(GR_GL_RGB10_A2, GR_GL_TEXTURE_2D);
}
break;
case kRGB_101010x_SkColorType:
return GrBackendFormat();
case kGray_8_SkColorType:
if (kGray_8_as_Lum_GrPixelConfig == config) {
return GrBackendFormat::MakeGL(GR_GL_LUMINANCE8, GR_GL_TEXTURE_2D);
} else if (kGray_8_GrPixelConfig == config ||
kGray_8_as_Red_GrPixelConfig == config) {
return GrBackendFormat::MakeGL(GR_GL_R8, GR_GL_TEXTURE_2D);
}
break;
case kRGBA_F16_SkColorType:
if (kRGBA_half_GrPixelConfig == config) {
return GrBackendFormat::MakeGL(GR_GL_RGBA16F, GR_GL_TEXTURE_2D);
}
break;
}
break;
}
break;
#ifdef SK_VULKAN
case kVulkan_GrBackend:
if (kRGBA_8888_SkColorType == colorType) {
VkFormat format = caps->srgbSupport() ? VK_FORMAT_R8G8B8A8_SRGB
: VK_FORMAT_R8G8B8A8_UNORM;
return GrBackendFormat::MakeVk(format);
} else if (kRGBA_F16_SkColorType == colorType) {
return GrBackendFormat::MakeVk(VK_FORMAT_R16G16B16A16_SFLOAT);
switch (ct) {
case kUnknown_SkColorType:
return GrBackendFormat();
case kAlpha_8_SkColorType:
// TODO: what about kAlpha_8_GrPixelConfig and kAlpha_8_as_Alpha_GrPixelConfig
if (kAlpha_8_as_Red_GrPixelConfig == config) {
return GrBackendFormat::MakeVk(VK_FORMAT_R8_UNORM);
}
break;
case kRGB_565_SkColorType:
if (kRGB_565_GrPixelConfig == config) {
return GrBackendFormat::MakeVk(VK_FORMAT_R5G6B5_UNORM_PACK16);
}
break;
case kARGB_4444_SkColorType:
if (kRGBA_4444_GrPixelConfig == config) {
return GrBackendFormat::MakeVk(VK_FORMAT_B4G4R4A4_UNORM_PACK16);
}
break;
case kRGBA_8888_SkColorType:
if (kRGBA_8888_GrPixelConfig == config) {
if (!cs || (cs->gammaCloseToSRGB() && !caps->srgbSupport())) {
return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_UNORM);
}
} else if (kSRGBA_8888_GrPixelConfig == config) {
if (caps->srgbSupport() && cs && cs->gammaCloseToSRGB()) {
return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_SRGB);
}
}
break;
case kRGB_888x_SkColorType:
if (kRGB_888_GrPixelConfig == config) {
return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8_UNORM);
}
break;
case kBGRA_8888_SkColorType:
if (kBGRA_8888_GrPixelConfig == config) {
return GrBackendFormat::MakeVk(VK_FORMAT_B8G8R8A8_UNORM);
} else if (kSBGRA_8888_GrPixelConfig == config) {
if (caps->srgbSupport() && cs && cs->gammaCloseToSRGB()) {
return GrBackendFormat::MakeVk(VK_FORMAT_B8G8R8A8_SRGB);
}
}
break;
case kRGBA_1010102_SkColorType:
if (kRGBA_1010102_GrPixelConfig == config) {
return GrBackendFormat::MakeVk(VK_FORMAT_A2B10G10R10_UNORM_PACK32);
}
break;
case kRGB_101010x_SkColorType:
return GrBackendFormat();
case kGray_8_SkColorType:
// TODO: what about kAlpha_8_GrPixelConfig and kGray_8_as_Lum_GrPixelConfig?
if (kGray_8_as_Red_GrPixelConfig == config) {
return GrBackendFormat::MakeVk(VK_FORMAT_R8_UNORM);
}
break;
case kRGBA_F16_SkColorType:
if (kRGBA_half_GrPixelConfig == config) {
return GrBackendFormat::MakeVk(VK_FORMAT_R16G16B16A16_SFLOAT);
}
break;
}
break;
#endif
case kMock_GrBackend:
if (kRGBA_8888_SkColorType == colorType) {
GrPixelConfig config = caps->srgbSupport() ? kSRGBA_8888_GrPixelConfig
: kRGBA_8888_GrPixelConfig;
return GrBackendFormat::MakeMock(config);
} else if (kRGBA_F16_SkColorType == colorType) {
return GrBackendFormat::MakeMock(kRGBA_half_GrPixelConfig);
switch (ct) {
case kUnknown_SkColorType:
return GrBackendFormat();
case kAlpha_8_SkColorType:
if (kAlpha_8_GrPixelConfig == config ||
kAlpha_8_as_Alpha_GrPixelConfig == config ||
kAlpha_8_as_Red_GrPixelConfig == config) {
return GrBackendFormat::MakeMock(config);
}
break;
case kRGB_565_SkColorType:
if (kRGB_565_GrPixelConfig == config) {
return GrBackendFormat::MakeMock(config);
}
break;
case kARGB_4444_SkColorType:
if (kRGBA_4444_GrPixelConfig == config) {
return GrBackendFormat::MakeMock(config);
}
break;
case kRGBA_8888_SkColorType:
if (kRGBA_8888_GrPixelConfig == config) {
if (!cs || (cs->gammaCloseToSRGB() && !caps->srgbSupport())) {
return GrBackendFormat::MakeMock(config);
}
} else if (kSRGBA_8888_GrPixelConfig == config) {
if (caps->srgbSupport() && cs && cs->gammaCloseToSRGB()) {
return GrBackendFormat::MakeMock(config);
}
}
break;
case kRGB_888x_SkColorType:
if (kRGB_888_GrPixelConfig == config) {
return GrBackendFormat::MakeMock(config);
}
break;
case kBGRA_8888_SkColorType:
if (kBGRA_8888_GrPixelConfig == config) {
return GrBackendFormat::MakeMock(config);
} else if (kSBGRA_8888_GrPixelConfig == config) {
if (caps->srgbSupport() && cs && cs->gammaCloseToSRGB()) {
return GrBackendFormat::MakeMock(config);
}
}
break;
case kRGBA_1010102_SkColorType:
if (kRGBA_1010102_GrPixelConfig == config) {
return GrBackendFormat::MakeMock(config);
}
break;
case kRGB_101010x_SkColorType:
return GrBackendFormat();
case kGray_8_SkColorType:
if (kGray_8_GrPixelConfig == config ||
kGray_8_as_Lum_GrPixelConfig == config ||
kGray_8_as_Red_GrPixelConfig == config) {
return GrBackendFormat::MakeMock(config);
}
break;
case kRGBA_F16_SkColorType:
if (kRGBA_half_GrPixelConfig == config) {
return GrBackendFormat::MakeMock(config);
}
break;
}
break;
default:
@ -74,11 +264,12 @@ public:
static const int kSampleCount = 5;
static const int kMipMipCount = 8;
SurfaceParameters()
SurfaceParameters(const GrCaps* caps)
: fWidth(64)
, fHeight(64)
, fOrigin(kTopLeft_GrSurfaceOrigin)
, fColorType(kRGBA_8888_SkColorType)
, fConfig(caps->srgbSupport() ? kSRGBA_8888_GrPixelConfig : kRGBA_8888_GrPixelConfig)
, fColorSpace(SkColorSpace::MakeSRGB())
, fSampleCount(1)
, fSurfaceProps(0x0, kUnknown_SkPixelGeometry)
@ -87,6 +278,10 @@ public:
int sampleCount() const { return fSampleCount; }
void setColorType(SkColorType ct) { fColorType = ct; }
void setColorSpace(sk_sp<SkColorSpace> cs) { fColorSpace = std::move(cs); }
void setConfig(GrPixelConfig config) { fConfig = config; }
// Modify the SurfaceParameters in just one way
void modify(int i) {
switch (i) {
@ -101,6 +296,8 @@ public:
break;
case 3:
fColorType = kRGBA_F16_SkColorType;
fConfig = kRGBA_half_GrPixelConfig;
fColorSpace = SkColorSpace::MakeSRGBLinear();
break;
case 4:
fColorSpace = SkColorSpace::MakeSRGBLinear();
@ -130,7 +327,11 @@ public:
SkImageInfo ii = SkImageInfo::Make(fWidth, fHeight, fColorType,
kPremul_SkAlphaType, fColorSpace);
GrBackendFormat backendFormat = create_backend_format(context, fColorType);
GrBackendFormat backendFormat = create_backend_format(context, fColorType,
fColorSpace.get(), fConfig);
if (!backendFormat.isValid()) {
return SkSurfaceCharacterization();
}
SkSurfaceCharacterization c = context->threadSafeProxy()->createCharacterization(
maxResourceBytes, ii, backendFormat, fSampleCount,
@ -154,31 +355,31 @@ public:
}
// Create the surface with the current set of parameters
sk_sp<SkSurface> make(GrContext* context) const {
// Note that Ganesh doesn't make use of the SkImageInfo's alphaType
SkImageInfo ii = SkImageInfo::Make(fWidth, fHeight, fColorType,
kPremul_SkAlphaType, fColorSpace);
return SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, ii, fSampleCount,
fOrigin, &fSurfaceProps, fShouldCreateMipMaps);
}
// Create a surface w/ the current parameters but make it non-textureable
sk_sp<SkSurface> makeNonTextureable(GrContext* context, GrBackendTexture* backend) const {
sk_sp<SkSurface> make(GrContext* context, GrBackendTexture* backend,
bool nonTextureable) const {
GrGpu* gpu = context->contextPriv().getGpu();
GrPixelConfig config = SkImageInfo2GrPixelConfig(fColorType, nullptr, *context->caps());
SkASSERT(kUnknown_GrPixelConfig != config);
GrMipMapped mipmapped = nonTextureable
? GrMipMapped::kNo
: GrMipMapped(fShouldCreateMipMaps);
*backend = gpu->createTestingOnlyBackendTexture(nullptr, fWidth, fHeight,
config, true, GrMipMapped::kNo);
fConfig, true, mipmapped);
if (!backend->isValid() || !gpu->isTestingOnlyBackendTexture(*backend)) {
return nullptr;
}
sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
context, *backend, fOrigin, fSampleCount, fColorType, nullptr, nullptr);
sk_sp<SkSurface> surface;
if (nonTextureable) {
// Create a surface w/ the current parameters but make it non-textureable
surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
context, *backend, fOrigin, fSampleCount, fColorType,
fColorSpace, &fSurfaceProps);
} else {
surface = SkSurface::MakeFromBackendTexture(
context, *backend, fOrigin, fSampleCount, fColorType,
fColorSpace, &fSurfaceProps);
}
if (!surface) {
gpu->deleteTestingOnlyBackendTexture(*backend);
@ -199,6 +400,7 @@ private:
int fHeight;
GrSurfaceOrigin fOrigin;
SkColorType fColorType;
GrPixelConfig fConfig;
sk_sp<SkColorSpace> fColorSpace;
int fSampleCount;
SkSurfaceProps fSurfaceProps;
@ -207,8 +409,9 @@ private:
////////////////////////////////////////////////////////////////////////////////
// This tests SkSurfaceCharacterization/SkSurface compatibility
DEF_GPUTEST_FOR_ALL_CONTEXTS(DDLSurfaceCharacterizationTest, reporter, ctxInfo) {
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLSurfaceCharacterizationTest, reporter, ctxInfo) {
GrContext* context = ctxInfo.grContext();
GrGpu* gpu = context->contextPriv().getGpu();
// Create a bitmap that we can readback into
SkImageInfo imageInfo = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType,
@ -220,27 +423,33 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(DDLSurfaceCharacterizationTest, reporter, ctxInfo)
// First, create a DDL using the stock SkSurface parameters
{
SurfaceParameters params;
SurfaceParameters params(context->caps());
ddl = params.createDDL(context);
SkAssertResult(ddl);
// The DDL should draw into an SkSurface created with the same parameters
sk_sp<SkSurface> s = params.make(context);
GrBackendTexture backend;
sk_sp<SkSurface> s = params.make(context, &backend, false);
if (!s) {
return;
}
REPORTER_ASSERT(reporter, s->draw(ddl.get()));
s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
context->flush();
gpu->testingOnly_flushGpuAndSync();
s = nullptr;
params.cleanUpBackEnd(context, backend);
}
// Then, alter each parameter in turn and check that the DDL & surface are incompatible
for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
SurfaceParameters params;
SurfaceParameters params(context->caps());
params.modify(i);
sk_sp<SkSurface> s = params.make(context);
GrBackendTexture backend;
sk_sp<SkSurface> s = params.make(context, &backend, false);
if (!s) {
continue;
}
@ -254,6 +463,8 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(DDLSurfaceCharacterizationTest, reporter, ctxInfo)
if (1 == supportedSampleCount) {
// If changing the sample count won't result in a different
// surface characterization, skip this step
s = nullptr;
params.cleanUpBackEnd(context, backend);
continue;
}
}
@ -261,17 +472,26 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(DDLSurfaceCharacterizationTest, reporter, ctxInfo)
if (SurfaceParameters::kMipMipCount == i && !context->caps()->mipMapSupport()) {
// If changing the mipmap setting won't result in a different surface characterization,
// skip this step
s = nullptr;
params.cleanUpBackEnd(context, backend);
continue;
}
REPORTER_ASSERT(reporter, !s->draw(ddl.get()),
"DDLSurfaceCharacterizationTest failed on parameter: %d\n", i);
context->flush();
gpu->testingOnly_flushGpuAndSync();
s = nullptr;
params.cleanUpBackEnd(context, backend);
}
// Next test the compatibility of resource cache parameters
{
const SurfaceParameters params;
sk_sp<SkSurface> s = params.make(context);
const SurfaceParameters params(context->caps());
GrBackendTexture backend;
sk_sp<SkSurface> s = params.make(context, &backend, false);
int maxResourceCount;
size_t maxResourceBytes;
@ -296,16 +516,23 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(DDLSurfaceCharacterizationTest, reporter, ctxInfo)
REPORTER_ASSERT(reporter, s->draw(ddl.get()));
s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
#endif
context->flush();
gpu->testingOnly_flushGpuAndSync();
s = nullptr;
params.cleanUpBackEnd(context, backend);
}
// Test that the textureability of the DDL characterization can block a DDL draw
{
GrBackendTexture backend;
const SurfaceParameters params;
sk_sp<SkSurface> s = params.makeNonTextureable(context, &backend);
const SurfaceParameters params(context->caps());
sk_sp<SkSurface> s = params.make(context, &backend, true);
if (s) {
REPORTER_ASSERT(reporter, !s->draw(ddl.get()));
context->flush();
gpu->testingOnly_flushGpuAndSync();
s = nullptr;
params.cleanUpBackEnd(context, backend);
}
@ -322,9 +549,10 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(DDLSurfaceCharacterizationTest, reporter, ctxInfo)
// Exercise the createResized method
{
SurfaceParameters params;
SurfaceParameters params(context->caps());
GrBackendTexture backend;
sk_sp<SkSurface> s = params.make(context);
sk_sp<SkSurface> s = params.make(context, &backend, false);
if (!s) {
return;
}
@ -345,22 +573,38 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(DDLSurfaceCharacterizationTest, reporter, ctxInfo)
REPORTER_ASSERT(reporter, char3.isValid());
REPORTER_ASSERT(reporter, 32 == char3.width());
REPORTER_ASSERT(reporter, 32 == char3.height());
s = nullptr;
params.cleanUpBackEnd(context, backend);
}
}
////////////////////////////////////////////////////////////////////////////////
// This tests the SkSurface::MakeRenderTarget variant that takes an SkSurfaceCharacterization.
// In particular, the SkSurface and the SkSurfaceCharacterization should always be compatible.
DEF_GPUTEST_FOR_ALL_CONTEXTS(DDLMakeRenderTargetTest, reporter, ctxInfo) {
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLMakeRenderTargetTest, reporter, ctxInfo) {
GrContext* context = ctxInfo.grContext();
for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
SurfaceParameters params;
SurfaceParameters params(context->caps());
params.modify(i);
SkSurfaceCharacterization c = params.createCharacterization(context);
GrBackendTexture backend;
sk_sp<SkSurface> s = params.make(context);
if (!c.isValid()) {
sk_sp<SkSurface> tmp = params.make(context, &backend, false);
// If we couldn't characterize the surface we shouldn't be able to create it either
REPORTER_ASSERT(reporter, !tmp);
if (tmp) {
tmp = nullptr;
params.cleanUpBackEnd(context, backend);
}
continue;
}
sk_sp<SkSurface> s = params.make(context, &backend, false);
if (!s) {
REPORTER_ASSERT(reporter, !c.isValid());
continue;
@ -373,6 +617,9 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(DDLMakeRenderTargetTest, reporter, ctxInfo) {
SkSurface_Gpu* g = static_cast<SkSurface_Gpu*>(s.get());
REPORTER_ASSERT(reporter, g->isCompatible(c));
s = nullptr;
params.cleanUpBackEnd(context, backend);
}
}
@ -399,9 +646,10 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLWrapBackendTest, reporter, ctxInfo) {
return;
}
SurfaceParameters params;
SurfaceParameters params(context->caps());
GrBackendTexture backend;
sk_sp<SkSurface> s = params.make(context);
sk_sp<SkSurface> s = params.make(context, &backend, false);
if (!s) {
gpu->deleteTestingOnlyBackendTexture(backendTex);
return;
@ -414,12 +662,16 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLWrapBackendTest, reporter, ctxInfo) {
SkCanvas* canvas = recorder->getCanvas();
if (!canvas) {
s = nullptr;
params.cleanUpBackEnd(context, backend);
gpu->deleteTestingOnlyBackendTexture(backendTex);
return;
}
GrContext* deferredContext = canvas->getGrContext();
if (!deferredContext) {
s = nullptr;
params.cleanUpBackEnd(context, backend);
gpu->deleteTestingOnlyBackendTexture(backendTex);
return;
}
@ -437,6 +689,9 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLWrapBackendTest, reporter, ctxInfo) {
REPORTER_ASSERT(reporter, !image);
gpu->deleteTestingOnlyBackendTexture(backendTex);
s = nullptr;
params.cleanUpBackEnd(context, backend);
}
static void dummy_fulfill_proc(void*, GrBackendTexture*) { SkASSERT(0); }
@ -469,7 +724,8 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLInvalidRecorder, reporter, ctxInfo) {
REPORTER_ASSERT(reporter, !recorder.getCanvas());
REPORTER_ASSERT(reporter, !recorder.detach());
GrBackendFormat format = create_backend_format(context, kRGBA_8888_SkColorType);
GrBackendFormat format = create_backend_format(context, kRGBA_8888_SkColorType,
nullptr, kRGBA_8888_GrPixelConfig);
sk_sp<SkImage> image = recorder.makePromiseTexture(format, 32, 32, GrMipMapped::kNo,
kTopLeft_GrSurfaceOrigin,
kRGBA_8888_SkColorType,
@ -538,6 +794,75 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(DDLTextureFlagsTest, reporter, ctxInfo) {
REPORTER_ASSERT(reporter, backingProxy->texPriv().isClampOnly());
}
}
}
////////////////////////////////////////////////////////////////////////////////
// Exhaustively test colorType and pixelConfig compatibility.
DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(DDLCompatibilityTest, reporter, ctxInfo) {
GrContext* context = ctxInfo.grContext();
for (int ct = 0; ct <= kLastEnum_SkColorType; ++ct) {
SkColorType colorType = static_cast<SkColorType>(ct);
for (int config = 0; config < kGrPixelConfigCnt; ++config) {
GrPixelConfig pixelConfig = static_cast<GrPixelConfig>(config);
SurfaceParameters params(context->caps());
params.setColorType(colorType);
params.setConfig(pixelConfig);
params.setColorSpace(nullptr);
if (kSRGBA_8888_GrPixelConfig == pixelConfig ||
kSBGRA_8888_GrPixelConfig == pixelConfig) {
params.setColorSpace(SkColorSpace::MakeSRGB());
}
SkSurfaceCharacterization c = params.createCharacterization(context);
GrBackendTexture backend;
if (!c.isValid()) {
// TODO: this would be cool to enable but there is, currently, too much crossover
// allowed internally (e.g., kAlpha_8_SkColorType/kGray_8_as_Red_GrPixelConfig
// is permitted on GL).
#if 0
sk_sp<SkSurface> tmp = params.make(context, &backend, false);
// If we couldn't characterize the surface we shouldn't be able to create it either
REPORTER_ASSERT(reporter, !tmp);
if (tmp) {
tmp = nullptr;
params.cleanUpBackEnd(context, backend);
}
#endif
continue;
}
sk_sp<SkSurface> s = params.make(context, &backend, false);
REPORTER_ASSERT(reporter, s);
if (!s) {
s = nullptr;
params.cleanUpBackEnd(context, backend);
continue;
}
SkSurface_Gpu* gpuSurface = static_cast<SkSurface_Gpu*>(s.get());
REPORTER_ASSERT(reporter, gpuSurface->isCompatible(c));
s = nullptr;
params.cleanUpBackEnd(context, backend);
s = SkSurface::MakeRenderTarget(context, c, SkBudgeted::kYes);
REPORTER_ASSERT(reporter, s);
if (!s) {
continue;
}
gpuSurface = static_cast<SkSurface_Gpu*>(s.get());
REPORTER_ASSERT(reporter, gpuSurface->isCompatible(c));
}
}
}
#endif