aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrBackendSurface.cpp6
-rw-r--r--src/gpu/GrBackendTextureImageGenerator.cpp4
-rw-r--r--src/gpu/GrBlurUtils.cpp2
-rw-r--r--src/gpu/GrCaps.cpp42
-rw-r--r--src/gpu/GrClipStackClip.cpp2
-rw-r--r--src/gpu/GrContext.cpp19
-rw-r--r--src/gpu/GrGpu.cpp75
-rw-r--r--src/gpu/GrGpu.h4
-rw-r--r--src/gpu/GrProxyProvider.cpp41
-rw-r--r--src/gpu/GrRenderTarget.cpp2
-rw-r--r--src/gpu/GrRenderTargetProxy.cpp8
-rw-r--r--src/gpu/GrResourceProvider.cpp34
-rw-r--r--src/gpu/GrResourceProvider.h2
-rw-r--r--src/gpu/GrSurface.cpp5
-rw-r--r--src/gpu/GrSurfaceProxy.cpp4
-rw-r--r--src/gpu/GrTexture.cpp8
-rw-r--r--src/gpu/GrTextureProducer.cpp4
-rw-r--r--src/gpu/GrTextureProxy.cpp4
-rw-r--r--src/gpu/GrTextureRenderTargetProxy.cpp6
-rw-r--r--src/gpu/SkGr.cpp4
-rw-r--r--src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp2
-rw-r--r--src/gpu/ddl/GrDDLGpu.h2
-rw-r--r--src/gpu/gl/GrGLCaps.cpp47
-rw-r--r--src/gpu/gl/GrGLCaps.h11
-rw-r--r--src/gpu/gl/GrGLGpu.cpp59
-rw-r--r--src/gpu/gl/GrGLRenderTarget.cpp2
-rw-r--r--src/gpu/gl/GrGLStencilAttachment.cpp2
-rw-r--r--src/gpu/mock/GrMockCaps.h34
-rw-r--r--src/gpu/mock/GrMockTexture.h7
-rw-r--r--src/gpu/mtl/GrMtlCaps.h12
-rw-r--r--src/gpu/mtl/GrMtlCaps.mm30
-rw-r--r--src/gpu/mtl/GrMtlRenderTarget.h5
-rw-r--r--src/gpu/vk/GrVkCaps.cpp24
-rw-r--r--src/gpu/vk/GrVkCaps.h9
-rw-r--r--src/gpu/vk/GrVkGpu.cpp33
-rw-r--r--src/gpu/vk/GrVkRenderTarget.cpp19
-rw-r--r--src/gpu/vk/GrVkRenderTarget.h7
-rw-r--r--src/gpu/vk/GrVkStencilAttachment.cpp2
-rw-r--r--src/gpu/vk/GrVkTextureRenderTarget.cpp15
-rw-r--r--src/gpu/vk/GrVkUtil.cpp2
-rw-r--r--src/image/SkImage_Gpu.cpp9
-rw-r--r--src/image/SkImage_Lazy.cpp5
-rw-r--r--src/image/SkSurface.cpp4
-rw-r--r--src/image/SkSurface_Gpu.cpp20
-rw-r--r--src/utils/win/SkWGL.h8
-rw-r--r--src/utils/win/SkWGL_win.cpp7
46 files changed, 351 insertions, 302 deletions
diff --git a/src/gpu/GrBackendSurface.cpp b/src/gpu/GrBackendSurface.cpp
index 406cb228ea..16fa793d25 100644
--- a/src/gpu/GrBackendSurface.cpp
+++ b/src/gpu/GrBackendSurface.cpp
@@ -106,7 +106,7 @@ GrBackendRenderTarget::GrBackendRenderTarget(int width,
const GrVkImageInfo& vkInfo)
: fWidth(width)
, fHeight(height)
- , fSampleCnt(sampleCnt)
+ , fSampleCnt(SkTMax(1, sampleCnt))
, fStencilBits(stencilBits)
, fConfig(GrVkFormatToPixelConfig(vkInfo.fFormat))
, fBackend(kVulkan_GrBackend)
@@ -121,7 +121,7 @@ GrBackendRenderTarget::GrBackendRenderTarget(int width,
const GrGLFramebufferInfo& glInfo)
: fWidth(width)
, fHeight(height)
- , fSampleCnt(sampleCnt)
+ , fSampleCnt(SkTMax(1, sampleCnt))
, fStencilBits(stencilBits)
, fConfig(config)
, fBackend(kOpenGL_GrBackend)
@@ -134,7 +134,7 @@ GrBackendRenderTarget::GrBackendRenderTarget(int width,
const GrGLFramebufferInfo& glInfo)
: fWidth(width)
, fHeight(height)
- , fSampleCnt(sampleCnt)
+ , fSampleCnt(SkTMax(1, sampleCnt))
, fStencilBits(stencilBits)
, fConfig(GrGLSizedFormatToPixelConfig(glInfo.fFormat))
, fBackend(kOpenGL_GrBackend)
diff --git a/src/gpu/GrBackendTextureImageGenerator.cpp b/src/gpu/GrBackendTextureImageGenerator.cpp
index ae27912b32..af28409cfe 100644
--- a/src/gpu/GrBackendTextureImageGenerator.cpp
+++ b/src/gpu/GrBackendTextureImageGenerator.cpp
@@ -186,8 +186,8 @@ sk_sp<GrTextureProxy> GrBackendTextureImageGenerator::onGenerateTexture(
GrMipMapped mipMapped = willNeedMipMaps ? GrMipMapped::kYes : GrMipMapped::kNo;
sk_sp<GrRenderTargetContext> rtContext(context->makeDeferredRenderTargetContext(
- SkBackingFit::kExact, info.width(), info.height(), proxy->config(), nullptr,
- 0, mipMapped, proxy->origin(), nullptr, SkBudgeted::kYes));
+ SkBackingFit::kExact, info.width(), info.height(), proxy->config(), nullptr, 1,
+ mipMapped, proxy->origin(), nullptr, SkBudgeted::kYes));
if (!rtContext) {
return nullptr;
diff --git a/src/gpu/GrBlurUtils.cpp b/src/gpu/GrBlurUtils.cpp
index b79a38a884..b6e3092d5a 100644
--- a/src/gpu/GrBlurUtils.cpp
+++ b/src/gpu/GrBlurUtils.cpp
@@ -110,7 +110,7 @@ static sk_sp<GrTextureProxy> create_mask_GPU(GrContext* context,
int sampleCnt) {
if (GrAA::kNo == aa) {
// Don't need MSAA if mask isn't AA
- sampleCnt = 0;
+ sampleCnt = 1;
}
sk_sp<GrRenderTargetContext> rtContext(context->makeDeferredRenderTargetContextWithFallback(
diff --git a/src/gpu/GrCaps.cpp b/src/gpu/GrCaps.cpp
index 427b20425a..dd589b436f 100644
--- a/src/gpu/GrCaps.cpp
+++ b/src/gpu/GrCaps.cpp
@@ -196,8 +196,7 @@ void GrCaps::dumpJSON(SkJSONWriter* writer) const {
kBlendEquationSupportNames[fBlendEquationSupport]);
writer->appendString("Map Buffer Support", map_flags_to_string(fMapBufferFlags).c_str());
- SkASSERT(!this->isConfigRenderable(kUnknown_GrPixelConfig, false));
- SkASSERT(!this->isConfigRenderable(kUnknown_GrPixelConfig, true));
+ SkASSERT(!this->isConfigRenderable(kUnknown_GrPixelConfig));
SkASSERT(!this->isConfigTexturable(kUnknown_GrPixelConfig));
writer->beginArray("configs");
@@ -206,8 +205,7 @@ void GrCaps::dumpJSON(SkJSONWriter* writer) const {
GrPixelConfig config = static_cast<GrPixelConfig>(i);
writer->beginObject(nullptr, false);
writer->appendString("name", pixel_config_name(config));
- writer->appendBool("renderable", this->isConfigRenderable(config, false));
- writer->appendBool("renderableMSAA", this->isConfigRenderable(config, true));
+ writer->appendS32("max sample count", this->maxRenderTargetSampleCount(config));
writer->appendBool("texturable", this->isConfigTexturable(config));
writer->endObject();
}
@@ -222,3 +220,39 @@ void GrCaps::dumpJSON(SkJSONWriter* writer) const {
writer->endObject();
}
+bool GrCaps::validateSurfaceDesc(const GrSurfaceDesc& desc, GrMipMapped mipped) const {
+ if (!this->isConfigTexturable(desc.fConfig)) {
+ return false;
+ }
+
+ if (GrMipMapped::kYes == mipped) {
+ if (GrPixelConfigIsSint(desc.fConfig) || !this->mipMapSupport()) {
+ return false;
+ }
+ }
+
+ if (desc.fWidth < 1 || desc.fHeight < 1) {
+ return false;
+ }
+
+ if (SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag)) {
+ if (0 == this->getRenderTargetSampleCount(desc.fSampleCnt, desc.fConfig)) {
+ return false;
+ }
+ int maxRTSize = this->maxRenderTargetSize();
+ if (desc.fWidth > maxRTSize || desc.fHeight > maxRTSize) {
+ return false;
+ }
+ } else {
+ // We currently do not support multisampled textures
+ if (desc.fSampleCnt > 1) {
+ return false;
+ }
+ int maxSize = this->maxTextureSize();
+ if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/src/gpu/GrClipStackClip.cpp b/src/gpu/GrClipStackClip.cpp
index 8f82ea1228..24c813e654 100644
--- a/src/gpu/GrClipStackClip.cpp
+++ b/src/gpu/GrClipStackClip.cpp
@@ -198,7 +198,7 @@ bool GrClipStackClip::apply(GrContext* context, GrRenderTargetContext* renderTar
// With mixed samples (non-msaa color buffer), any coverage info is lost from color once it
// hits the color buffer anyway, so we may as well use coverage AA if nothing else in the
// pipe is multisampled.
- if (renderTargetContext->numColorSamples() > 0 || useHWAA || hasUserStencilSettings) {
+ if (renderTargetContext->numColorSamples() > 1 || useHWAA || hasUserStencilSettings) {
maxAnalyticFPs = 0;
}
SkASSERT(!context->caps()->avoidStencilBuffers()); // We disable MSAA when avoiding stencil.
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index b427e70beb..05908f4889 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -420,6 +420,18 @@ size_t GrContext::getResourceCachePurgeableBytes() const {
////////////////////////////////////////////////////////////////////////////////
+bool GrContext::colorTypeSupportedAsImage(SkColorType colorType) const {
+ GrPixelConfig config = SkImageInfo2GrPixelConfig(colorType, nullptr, *this->caps());
+ return this->caps()->isConfigTexturable(config);
+}
+
+int GrContext::maxSurfaceSampleCountForColorType(SkColorType colorType) const {
+ GrPixelConfig config = SkImageInfo2GrPixelConfig(colorType, nullptr, *this->caps());
+ return this->caps()->maxRenderTargetSampleCount(config);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
void GrContext::TextBlobCacheOverBudgetCB(void* data) {
SkASSERT(data);
// TextBlobs are drawn at the SkGpuDevice level, therefore they cannot rely on
@@ -862,6 +874,7 @@ sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureRenderTargetContex
sk_sp<SkColorSpace> colorSpace,
const SkSurfaceProps* props) {
ASSERT_SINGLE_OWNER_PRIV
+ SkASSERT(sampleCnt > 0);
sk_sp<GrTextureProxy> proxy(this->proxyProvider()->createWrappedTextureProxy(tex, origin,
sampleCnt));
@@ -898,7 +911,7 @@ sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureAsRenderTargetRend
sk_sp<SkColorSpace> colorSpace,
const SkSurfaceProps* props) {
ASSERT_SINGLE_OWNER_PRIV
-
+ SkASSERT(sampleCnt > 0);
sk_sp<GrSurfaceProxy> proxy(this->proxyProvider()->createWrappedRenderTargetProxy(tex, origin,
sampleCnt));
if (!proxy) {
@@ -949,7 +962,8 @@ sk_sp<GrRenderTargetContext> GrContext::makeDeferredRenderTargetContextWithFallb
GrSurfaceOrigin origin,
const SkSurfaceProps* surfaceProps,
SkBudgeted budgeted) {
- if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) {
+ SkASSERT(sampleCnt > 0);
+ if (0 == this->caps()->getRenderTargetSampleCount(sampleCnt, config)) {
config = GrPixelConfigFallback(config);
}
@@ -968,6 +982,7 @@ sk_sp<GrRenderTargetContext> GrContext::makeDeferredRenderTargetContext(
GrSurfaceOrigin origin,
const SkSurfaceProps* surfaceProps,
SkBudgeted budgeted) {
+ SkASSERT(sampleCnt > 0);
if (this->abandoned()) {
return nullptr;
}
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index eb005d110a..955d57ddb0 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -72,68 +72,22 @@ bool GrGpu::isACopyNeededForTextureParams(int width, int height,
return false;
}
-/**
- * Prior to creating a texture, make sure the type of texture being created is
- * supported by calling check_texture_creation_params.
- *
- * @param caps The capabilities of the GL device.
- * @param desc The descriptor of the texture to create.
- * @param isRT Indicates if the texture can be a render target.
- * @param texels The texel data for the mipmap levels
- * @param mipLevelCount The number of GrMipLevels in 'texels'
- */
-static bool check_texture_creation_params(const GrCaps& caps, const GrSurfaceDesc& desc,
- bool* isRT,
- const GrMipLevel texels[], int mipLevelCount) {
- if (!caps.isConfigTexturable(desc.fConfig)) {
- return false;
- }
-
- if (GrPixelConfigIsSint(desc.fConfig) && mipLevelCount > 1) {
- return false;
- }
-
- *isRT = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
- if (*isRT && !caps.isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
- return false;
- }
-
- // We currently do not support multisampled textures
- if (!*isRT && desc.fSampleCnt > 0) {
- return false;
- }
-
- if (*isRT) {
- int maxRTSize = caps.maxRenderTargetSize();
- if (desc.fWidth > maxRTSize || desc.fHeight > maxRTSize) {
- return false;
- }
- } else {
- int maxSize = caps.maxTextureSize();
- if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
- return false;
- }
- }
-
- return true;
-}
-
sk_sp<GrTexture> GrGpu::createTexture(const GrSurfaceDesc& origDesc, SkBudgeted budgeted,
const GrMipLevel texels[], int mipLevelCount) {
GR_CREATE_TRACE_MARKER_CONTEXT("GrGpu", "createTexture", fContext);
GrSurfaceDesc desc = origDesc;
- const GrCaps* caps = this->caps();
- bool isRT = false;
- bool textureCreationParamsValid = check_texture_creation_params(*caps, desc, &isRT,
- texels, mipLevelCount);
- if (!textureCreationParamsValid) {
+ GrMipMapped mipMapped = mipLevelCount > 1 ? GrMipMapped::kYes : GrMipMapped::kNo;
+ if (!this->caps()->validateSurfaceDesc(desc, mipMapped)) {
return nullptr;
}
- desc.fSampleCnt = caps->getSampleCount(desc.fSampleCnt, desc.fConfig);
+ bool isRT = desc.fFlags & kRenderTarget_GrSurfaceFlag;
+ if (isRT) {
+ desc.fSampleCnt = this->caps()->getRenderTargetSampleCount(desc.fSampleCnt, desc.fConfig);
+ }
// Attempt to catch un- or wrongly initialized sample counts.
- SkASSERT(desc.fSampleCnt >= 0 && desc.fSampleCnt <= 64);
+ SkASSERT(desc.fSampleCnt > 0 && desc.fSampleCnt <= 64);
if (mipLevelCount && (desc.fFlags & kPerformInitialClear_GrSurfaceFlag)) {
return nullptr;
@@ -142,7 +96,7 @@ sk_sp<GrTexture> GrGpu::createTexture(const GrSurfaceDesc& origDesc, SkBudgeted
this->handleDirtyContext();
sk_sp<GrTexture> tex = this->onCreateTexture(desc, budgeted, texels, mipLevelCount);
if (tex) {
- if (!caps->reuseScratchTextures() && !isRT) {
+ if (!this->caps()->reuseScratchTextures() && !isRT) {
tex->resourcePriv().removeScratchKey();
}
fStats.incTextureCreates();
@@ -179,8 +133,11 @@ sk_sp<GrTexture> GrGpu::wrapBackendTexture(const GrBackendTexture& backendTex,
sk_sp<GrTexture> GrGpu::wrapRenderableBackendTexture(const GrBackendTexture& backendTex,
int sampleCnt, GrWrapOwnership ownership) {
this->handleDirtyContext();
+ if (sampleCnt < 1) {
+ return nullptr;
+ }
if (!this->caps()->isConfigTexturable(backendTex.config()) ||
- !this->caps()->isConfigRenderable(backendTex.config(), sampleCnt > 0)) {
+ !this->caps()->getRenderTargetSampleCount(sampleCnt, backendTex.config())) {
return nullptr;
}
@@ -197,7 +154,7 @@ sk_sp<GrTexture> GrGpu::wrapRenderableBackendTexture(const GrBackendTexture& bac
}
sk_sp<GrRenderTarget> GrGpu::wrapBackendRenderTarget(const GrBackendRenderTarget& backendRT) {
- if (!this->caps()->isConfigRenderable(backendRT.config(), backendRT.sampleCnt() > 0)) {
+ if (0 == this->caps()->getRenderTargetSampleCount(backendRT.sampleCnt(), backendRT.config())) {
return nullptr;
}
this->handleDirtyContext();
@@ -206,14 +163,14 @@ sk_sp<GrRenderTarget> GrGpu::wrapBackendRenderTarget(const GrBackendRenderTarget
sk_sp<GrRenderTarget> GrGpu::wrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
int sampleCnt) {
- this->handleDirtyContext();
- if (!this->caps()->isConfigRenderable(tex.config(), sampleCnt > 0)) {
+ if (0 == this->caps()->getRenderTargetSampleCount(sampleCnt, tex.config())) {
return nullptr;
}
int maxSize = this->caps()->maxTextureSize();
if (tex.width() > maxSize || tex.height() > maxSize) {
return nullptr;
}
+ this->handleDirtyContext();
return this->onWrapBackendTextureAsRenderTarget(tex, sampleCnt);
}
@@ -262,7 +219,7 @@ bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin,
// Check to see if we're going to request that the caller draw when drawing is not possible.
if (!srcSurface->asTexture() ||
- !this->caps()->isConfigRenderable(tempDrawInfo->fTempSurfaceDesc.fConfig, false)) {
+ !this->caps()->isConfigRenderable(tempDrawInfo->fTempSurfaceDesc.fConfig)) {
// If we don't have a fallback to a straight read then fail.
if (kRequireDraw_DrawPreference == *drawPreference) {
return false;
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 2f12073f8a..6527064b93 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -455,6 +455,10 @@ public:
/** Creates a texture directly in the backend API without wrapping it in a GrTexture. This is
only to be used for testing (particularly for testing the methods that import an externally
created texture into Skia. Must be matched with a call to deleteTestingOnlyTexture(). */
+ GrBackendTexture createTestingOnlyBackendTexture(void* pixels, int w, int h, SkColorType,
+ bool isRenderTarget, GrMipMapped);
+
+ /** Older version based on GrPixelConfig. Currently the preferred one above devolves to this. */
virtual GrBackendTexture createTestingOnlyBackendTexture(
void* pixels, int w, int h,
GrPixelConfig config,
diff --git a/src/gpu/GrProxyProvider.cpp b/src/gpu/GrProxyProvider.cpp
index e453246b62..6641bcf9a8 100644
--- a/src/gpu/GrProxyProvider.cpp
+++ b/src/gpu/GrProxyProvider.cpp
@@ -315,37 +315,14 @@ sk_sp<GrTextureProxy> GrProxyProvider::createProxy(const GrSurfaceDesc& desc,
uint32_t flags) {
SkASSERT(0 == flags || GrResourceProvider::kNoPendingIO_Flag == flags);
- const GrCaps* caps = this->caps();
-
- // TODO: move this logic into GrResourceProvider!
- // TODO: share this testing code with check_texture_creation_params
- if (!caps->isConfigTexturable(desc.fConfig)) {
- return nullptr;
- }
-
- bool willBeRT = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
- if (willBeRT && !caps->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
+ if (!this->caps()->validateSurfaceDesc(desc, GrMipMapped::kNo)) {
return nullptr;
}
-
- // We currently do not support multisampled textures
- if (!willBeRT && desc.fSampleCnt > 0) {
- return nullptr;
- }
-
- int maxSize;
- if (willBeRT) {
- maxSize = caps->maxRenderTargetSize();
- } else {
- maxSize = caps->maxTextureSize();
- }
-
- if (desc.fWidth > maxSize || desc.fHeight > maxSize || desc.fWidth <= 0 || desc.fHeight <= 0) {
- return nullptr;
- }
-
GrSurfaceDesc copyDesc = desc;
- copyDesc.fSampleCnt = caps->getSampleCount(desc.fSampleCnt, desc.fConfig);
+ if (desc.fFlags & kRenderTarget_GrSurfaceFlag) {
+ copyDesc.fSampleCnt =
+ this->caps()->getRenderTargetSampleCount(desc.fSampleCnt, desc.fConfig);
+ }
#ifdef SK_DISABLE_DEFERRED_PROXIES
// Temporarily force instantiation for crbug.com/769760 and crbug.com/769898
@@ -363,11 +340,11 @@ sk_sp<GrTextureProxy> GrProxyProvider::createProxy(const GrSurfaceDesc& desc,
return GrSurfaceProxy::MakeWrapped(std::move(tex), copyDesc.fOrigin);
#else
- if (willBeRT) {
+ if (copyDesc.fFlags & kRenderTarget_GrSurfaceFlag) {
// We know anything we instantiate later from this deferred path will be
// both texturable and renderable
- return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(*caps, copyDesc, fit,
- budgeted, flags));
+ return sk_sp<GrTextureProxy>(
+ new GrTextureRenderTargetProxy(*this->caps(), copyDesc, fit, budgeted, flags));
}
return sk_sp<GrTextureProxy>(new GrTextureProxy(copyDesc, fit, budgeted, nullptr, 0, flags));
@@ -507,7 +484,7 @@ sk_sp<GrTextureProxy> GrProxyProvider::createFullyLazyProxy(LazyInstantiateCallb
desc.fWidth = -1;
desc.fHeight = -1;
desc.fConfig = config;
- desc.fSampleCnt = 0;
+ desc.fSampleCnt = 1;
return this->createLazyProxy(std::move(callback), desc, GrMipMapped::kNo,
SkBackingFit::kApprox, SkBudgeted::kYes);
diff --git a/src/gpu/GrRenderTarget.cpp b/src/gpu/GrRenderTarget.cpp
index 3090219751..36fa4ddf1b 100644
--- a/src/gpu/GrRenderTarget.cpp
+++ b/src/gpu/GrRenderTarget.cpp
@@ -27,7 +27,7 @@ GrRenderTarget::GrRenderTarget(GrGpu* gpu, const GrSurfaceDesc& desc,
, fMultisampleSpecsID(0)
, fFlags(flags) {
SkASSERT(desc.fFlags & kRenderTarget_GrSurfaceFlag);
- SkASSERT(!(fFlags & GrRenderTargetFlags::kMixedSampled) || fSampleCnt > 0);
+ SkASSERT(!(fFlags & GrRenderTargetFlags::kMixedSampled) || fSampleCnt > 1);
SkASSERT(!(fFlags & GrRenderTargetFlags::kWindowRectsSupport) ||
gpu->caps()->maxWindowRectangles() > 0);
fResolveRect = SkRectPriv::MakeILargestInverted();
diff --git a/src/gpu/GrRenderTargetProxy.cpp b/src/gpu/GrRenderTargetProxy.cpp
index 9eb37a0b2f..841d4b18fd 100644
--- a/src/gpu/GrRenderTargetProxy.cpp
+++ b/src/gpu/GrRenderTargetProxy.cpp
@@ -26,7 +26,7 @@ GrRenderTargetProxy::GrRenderTargetProxy(const GrCaps& caps, const GrSurfaceDesc
, fRenderTargetFlags(GrRenderTargetFlags::kNone) {
// Since we know the newly created render target will be internal, we are able to precompute
// what the flags will ultimately end up being.
- if (caps.usesMixedSamples() && fSampleCnt > 0) {
+ if (caps.usesMixedSamples() && fSampleCnt > 1) {
fRenderTargetFlags |= GrRenderTargetFlags::kMixedSampled;
}
if (caps.maxWindowRectangles() > 0) {
@@ -97,7 +97,11 @@ sk_sp<GrSurface> GrRenderTargetProxy::createSurface(GrResourceProvider* resource
}
size_t GrRenderTargetProxy::onUninstantiatedGpuMemorySize() const {
- int colorSamplesPerPixel = this->numColorSamples() + 1;
+ int colorSamplesPerPixel = this->numColorSamples();
+ if (colorSamplesPerPixel > 1) {
+ // Add one for the resolve buffer.
+ ++colorSamplesPerPixel;
+ }
// TODO: do we have enough information to improve this worst case estimate?
return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
diff --git a/src/gpu/GrResourceProvider.cpp b/src/gpu/GrResourceProvider.cpp
index 3800383581..ec94968e21 100644
--- a/src/gpu/GrResourceProvider.cpp
+++ b/src/gpu/GrResourceProvider.cpp
@@ -46,28 +46,6 @@ GrResourceProvider::GrResourceProvider(GrGpu* gpu, GrResourceCache* cache, GrSin
fQuadIndexBufferKey = gQuadIndexBufferKey;
}
-bool validate_desc(const GrSurfaceDesc& desc, const GrCaps& caps, int levelCount = 0) {
- if (desc.fWidth <= 0 || desc.fHeight <= 0) {
- return false;
- }
- if (!caps.isConfigTexturable(desc.fConfig)) {
- return false;
- }
- if (desc.fFlags & kRenderTarget_GrSurfaceFlag) {
- if (!caps.isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
- return false;
- }
- } else {
- if (desc.fSampleCnt) {
- return false;
- }
- }
- if (levelCount > 1 && (GrPixelConfigIsSint(desc.fConfig) || !caps.mipMapSupport())) {
- return false;
- }
- return true;
-}
-
sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
const GrMipLevel texels[], int mipLevelCount,
SkDestinationSurfaceColorMode mipColorMode) {
@@ -79,7 +57,8 @@ sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc, Sk
return nullptr;
}
- if (!validate_desc(desc, *fCaps, mipLevelCount)) {
+ GrMipMapped mipMapped = mipLevelCount > 1 ? GrMipMapped::kYes : GrMipMapped::kNo;
+ if (!fCaps->validateSurfaceDesc(desc, mipMapped)) {
return nullptr;
}
@@ -125,7 +104,7 @@ sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
return nullptr;
}
- if (!validate_desc(desc, *fCaps)) {
+ if (!fCaps->validateSurfaceDesc(desc, GrMipMapped::kNo)) {
return nullptr;
}
@@ -157,12 +136,11 @@ sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
uint32_t flags) {
ASSERT_SINGLE_OWNER
-
if (this->isAbandoned()) {
return nullptr;
}
- if (!validate_desc(desc, *fCaps)) {
+ if (!fCaps->validateSurfaceDesc(desc, GrMipMapped::kNo)) {
return nullptr;
}
@@ -183,7 +161,7 @@ sk_sp<GrTexture> GrResourceProvider::createApproxTexture(const GrSurfaceDesc& de
return nullptr;
}
- if (!validate_desc(desc, *fCaps)) {
+ if (!fCaps->validateSurfaceDesc(desc, GrMipMapped::kNo)) {
return nullptr;
}
@@ -212,7 +190,7 @@ sk_sp<GrTexture> GrResourceProvider::refScratchTexture(const GrSurfaceDesc& desc
uint32_t flags) {
ASSERT_SINGLE_OWNER
SkASSERT(!this->isAbandoned());
- SkASSERT(validate_desc(desc, *fCaps));
+ SkASSERT(fCaps->validateSurfaceDesc(desc, GrMipMapped::kNo));
// We could make initial clears work with scratch textures but it is a rare case so we just opt
// to fall back to making a new texture.
diff --git a/src/gpu/GrResourceProvider.h b/src/gpu/GrResourceProvider.h
index 0092430846..385282d6f6 100644
--- a/src/gpu/GrResourceProvider.h
+++ b/src/gpu/GrResourceProvider.h
@@ -89,7 +89,7 @@ public:
GrWrapOwnership = kBorrow_GrWrapOwnership);
/**
- * This makes the backend texture be renderable. If sampleCnt is > 0 and the underlying API
+ * This makes the backend texture be renderable. If sampleCnt is > 1 and the underlying API
* uses separate MSAA render buffers then a MSAA render buffer is created that resolves
* to the texture.
*/
diff --git a/src/gpu/GrSurface.cpp b/src/gpu/GrSurface.cpp
index ec503d7066..b35683c548 100644
--- a/src/gpu/GrSurface.cpp
+++ b/src/gpu/GrSurface.cpp
@@ -29,8 +29,9 @@ size_t GrSurface::WorstCaseSize(const GrSurfaceDesc& desc, bool useNextPow2) {
bool isRenderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
if (isRenderTarget) {
// We own one color value for each MSAA sample.
- int colorValuesPerPixel = SkTMax(1, desc.fSampleCnt);
- if (desc.fSampleCnt) {
+ SkASSERT(desc.fSampleCnt >= 1);
+ int colorValuesPerPixel = desc.fSampleCnt;
+ if (desc.fSampleCnt > 1) {
// Worse case, we own the resolve buffer so that is one more sample per pixel.
colorValuesPerPixel += 1;
}
diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp
index 64c47b56b1..4020758259 100644
--- a/src/gpu/GrSurfaceProxy.cpp
+++ b/src/gpu/GrSurfaceProxy.cpp
@@ -26,7 +26,7 @@ static bool is_valid_fully_lazy(const GrSurfaceDesc& desc, SkBackingFit fit) {
return desc.fWidth <= 0 &&
desc.fHeight <= 0 &&
desc.fConfig != kUnknown_GrPixelConfig &&
- desc.fSampleCnt == 0 &&
+ desc.fSampleCnt == 1 &&
SkBackingFit::kApprox == fit;
}
@@ -190,7 +190,7 @@ bool GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, int s
void GrSurfaceProxy::computeScratchKey(GrScratchKey* key) const {
SkASSERT(LazyState::kFully != this->lazyInstantiationState());
const GrRenderTargetProxy* rtp = this->asRenderTargetProxy();
- int sampleCount = 0;
+ int sampleCount = 1;
if (rtp) {
sampleCount = rtp->numStencilSamples();
}
diff --git a/src/gpu/GrTexture.cpp b/src/gpu/GrTexture.cpp
index b4cefb0174..dd0631775f 100644
--- a/src/gpu/GrTexture.cpp
+++ b/src/gpu/GrTexture.cpp
@@ -78,7 +78,7 @@ bool GrTexture::StealBackendTexture(sk_sp<GrTexture>&& texture,
void GrTexture::computeScratchKey(GrScratchKey* key) const {
const GrRenderTarget* rt = this->asRenderTarget();
- int sampleCount = 0;
+ int sampleCount = 1;
if (rt) {
sampleCount = rt->numStencilSamples();
}
@@ -92,8 +92,10 @@ void GrTexturePriv::ComputeScratchKey(GrPixelConfig config, int width, int heigh
GrMipMapped mipMapped, GrScratchKey* key) {
static const GrScratchKey::ResourceType kType = GrScratchKey::GenerateResourceType();
uint32_t flags = isRenderTarget;
-
- SkASSERT(0 == sampleCnt || isRenderTarget);
+ SkASSERT(width > 0);
+ SkASSERT(height > 0);
+ SkASSERT(sampleCnt > 0);
+ SkASSERT(1 == sampleCnt || isRenderTarget);
// make sure desc.fConfig fits in 5 bits
SkASSERT(sk_float_log2(kLast_GrPixelConfig) <= 5);
diff --git a/src/gpu/GrTextureProducer.cpp b/src/gpu/GrTextureProducer.cpp
index 9593cb6873..9b344cb831 100644
--- a/src/gpu/GrTextureProducer.cpp
+++ b/src/gpu/GrTextureProducer.cpp
@@ -25,8 +25,8 @@ sk_sp<GrTextureProxy> GrTextureProducer::CopyOnGpu(GrContext* context,
GrMipMapped mipMapped = dstWillRequireMipMaps ? GrMipMapped::kYes : GrMipMapped::kNo;
sk_sp<GrRenderTargetContext> copyRTC = context->makeDeferredRenderTargetContextWithFallback(
- SkBackingFit::kExact, dstRect.width(), dstRect.height(), inputProxy->config(), nullptr,
- 0, mipMapped, inputProxy->origin());
+ SkBackingFit::kExact, dstRect.width(), dstRect.height(), inputProxy->config(), nullptr,
+ 1, mipMapped, inputProxy->origin());
if (!copyRTC) {
return nullptr;
}
diff --git a/src/gpu/GrTextureProxy.cpp b/src/gpu/GrTextureProxy.cpp
index 8e6afbf0a7..54d0769a63 100644
--- a/src/gpu/GrTextureProxy.cpp
+++ b/src/gpu/GrTextureProxy.cpp
@@ -64,7 +64,7 @@ bool GrTextureProxy::instantiate(GrResourceProvider* resourceProvider) {
if (LazyState::kNot != this->lazyInstantiationState()) {
return false;
}
- if (!this->instantiateImpl(resourceProvider, 0, /* needsStencil = */ false,
+ if (!this->instantiateImpl(resourceProvider, 1, /* needsStencil = */ false,
kNone_GrSurfaceFlags, fMipMapped, fMipColorMode,
fUniqueKey.isValid() ? &fUniqueKey : nullptr)) {
return false;
@@ -76,7 +76,7 @@ bool GrTextureProxy::instantiate(GrResourceProvider* resourceProvider) {
}
sk_sp<GrSurface> GrTextureProxy::createSurface(GrResourceProvider* resourceProvider) const {
- sk_sp<GrSurface> surface= this->createSurfaceImpl(resourceProvider, 0,
+ sk_sp<GrSurface> surface= this->createSurfaceImpl(resourceProvider, 1,
/* needsStencil = */ false,
kNone_GrSurfaceFlags,
fMipMapped, fMipColorMode);
diff --git a/src/gpu/GrTextureRenderTargetProxy.cpp b/src/gpu/GrTextureRenderTargetProxy.cpp
index da8e48307d..843524c062 100644
--- a/src/gpu/GrTextureRenderTargetProxy.cpp
+++ b/src/gpu/GrTextureRenderTargetProxy.cpp
@@ -53,7 +53,11 @@ GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(sk_sp<GrSurface> surf,
}
size_t GrTextureRenderTargetProxy::onUninstantiatedGpuMemorySize() const {
- int colorSamplesPerPixel = this->numColorSamples() + 1;
+ int colorSamplesPerPixel = this->numColorSamples();
+ if (colorSamplesPerPixel > 1) {
+ // Add one to account for the resolve buffer.
+ ++colorSamplesPerPixel += 1;
+ }
// TODO: do we have enough information to improve this worst case estimate?
return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 3d951c4673..d7ee5c2c02 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -48,7 +48,7 @@ GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info, const GrCaps& ca
desc.fWidth = info.width();
desc.fHeight = info.height();
desc.fConfig = SkImageInfo2GrPixelConfig(info, caps);
- desc.fSampleCnt = 0;
+ desc.fSampleCnt = 1;
return desc;
}
@@ -170,7 +170,7 @@ sk_sp<GrTextureProxy> GrCopyBaseMipMapToTextureProxy(GrContext* ctx, GrTexturePr
desc.fWidth = baseProxy->width();
desc.fHeight = baseProxy->height();
desc.fConfig = baseProxy->config();
- desc.fSampleCnt = 0;
+ desc.fSampleCnt = 1;
sk_sp<GrTextureProxy> proxy = proxyProvider->createMipMapProxy(desc, SkBudgeted::kYes);
if (!proxy) {
diff --git a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
index abe888044e..da6991745f 100644
--- a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
+++ b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
@@ -42,7 +42,7 @@ bool GrCoverageCountingPathRenderer::IsSupported(const GrCaps& caps) {
return shaderCaps.integerSupport() && shaderCaps.flatInterpolationSupport() &&
caps.instanceAttribSupport() && GrCaps::kNone_MapFlags != caps.mapBufferFlags() &&
caps.isConfigTexturable(kAlpha_half_GrPixelConfig) &&
- caps.isConfigRenderable(kAlpha_half_GrPixelConfig, /*withMSAA=*/false) &&
+ caps.isConfigRenderable(kAlpha_half_GrPixelConfig) &&
!caps.blacklistCoverageCounting();
}
diff --git a/src/gpu/ddl/GrDDLGpu.h b/src/gpu/ddl/GrDDLGpu.h
index 16deab0353..e1f463f073 100644
--- a/src/gpu/ddl/GrDDLGpu.h
+++ b/src/gpu/ddl/GrDDLGpu.h
@@ -46,7 +46,7 @@ public:
void onQueryMultisampleSpecs(GrRenderTarget* rt, GrSurfaceOrigin, const GrStencilSettings&,
int* effectiveSampleCnt, SamplePattern*) override {
SkASSERT(0);
- *effectiveSampleCnt = 0; // ??
+ *effectiveSampleCnt = 1; // ??
}
GrGpuRTCommandBuffer* createCommandBuffer(
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 3b90676be1..99f56564d8 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -1958,6 +1958,8 @@ void GrGLCaps::initConfigTable(const GrContextOptions& contextOptions,
for (int i = 0; i < kGrPixelConfigCnt; ++i) {
if (ConfigInfo::kRenderableWithMSAA_Flag & fConfigTable[i].fFlags) {
+ // We assume that MSAA rendering is supported only if we support non-MSAA rendering.
+ SkASSERT(ConfigInfo::kRenderable_Flag & fConfigTable[i].fFlags);
if ((kGL_GrGLStandard == ctxInfo.standard() &&
(ctxInfo.version() >= GR_GL_VER(4,2) ||
ctxInfo.hasExtension("GL_ARB_internalformat_query"))) ||
@@ -1970,10 +1972,15 @@ void GrGLCaps::initConfigTable(const GrContextOptions& contextOptions,
int* temp = new int[count];
GR_GL_GetInternalformativ(gli, GR_GL_RENDERBUFFER, format, GR_GL_SAMPLES, count,
temp);
+ // GL has a concept of MSAA rasterization with a single sample but we do not.
+ if (count && temp[count - 1] == 1) {
+ --count;
+ SkASSERT(!count || temp[count -1] > 1);
+ }
fConfigTable[i].fColorSampleCounts.setCount(count+1);
- // We initialize our supported values with 0 (no msaa) and reverse the order
+ // We initialize our supported values with 1 (no msaa) and reverse the order
// returned by GL so that the array is ascending.
- fConfigTable[i].fColorSampleCounts[0] = 0;
+ fConfigTable[i].fColorSampleCounts[0] = 1;
for (int j = 0; j < count; ++j) {
fConfigTable[i].fColorSampleCounts[j+1] = temp[count - j - 1];
}
@@ -1982,14 +1989,16 @@ void GrGLCaps::initConfigTable(const GrContextOptions& contextOptions,
} else {
// Fake out the table using some semi-standard counts up to the max allowed sample
// count.
- int maxSampleCnt = 0;
+ int maxSampleCnt = 1;
if (GrGLCaps::kES_IMG_MsToTexture_MSFBOType == fMSFBOType) {
GR_GL_GetIntegerv(gli, GR_GL_MAX_SAMPLES_IMG, &maxSampleCnt);
} else if (GrGLCaps::kNone_MSFBOType != fMSFBOType) {
GR_GL_GetIntegerv(gli, GR_GL_MAX_SAMPLES, &maxSampleCnt);
}
+ // Chrome has a mock GL implementation that returns 0.
+ maxSampleCnt = SkTMax(1, maxSampleCnt);
- static constexpr int kDefaultSamples[] = {0, 1, 2, 4, 8};
+ static constexpr int kDefaultSamples[] = {1, 2, 4, 8};
int count = SK_ARRAY_COUNT(kDefaultSamples);
for (; count > 0; --count) {
if (kDefaultSamples[count - 1] <= maxSampleCnt) {
@@ -2000,6 +2009,9 @@ void GrGLCaps::initConfigTable(const GrContextOptions& contextOptions,
fConfigTable[i].fColorSampleCounts.append(count, kDefaultSamples);
}
}
+ } else if (ConfigInfo::kRenderable_Flag & fConfigTable[i].fFlags) {
+ fConfigTable[i].fColorSampleCounts.setCount(1);
+ fConfigTable[i].fColorSampleCounts[0] = 1;
}
}
@@ -2034,7 +2046,7 @@ bool GrGLCaps::initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc*
// If the src is a texture, we can implement the blit as a draw assuming the config is
// renderable.
- if (src->asTextureProxy() && this->isConfigRenderable(src->config(), false)) {
+ if (src->asTextureProxy() && !this->isConfigRenderable(src->config())) {
desc->fOrigin = kBottomLeft_GrSurfaceOrigin;
desc->fFlags = kRenderTarget_GrSurfaceFlag;
desc->fConfig = src->config();
@@ -2059,14 +2071,14 @@ bool GrGLCaps::initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc*
GrSurfaceOrigin originForBlitFramebuffer = kTopLeft_GrSurfaceOrigin;
bool rectsMustMatchForBlitFramebuffer = false;
bool disallowSubrectForBlitFramebuffer = false;
- if (src->numColorSamples() &&
+ if (src->numColorSamples() > 1 &&
(this->blitFramebufferSupportFlags() & kResolveMustBeFull_BlitFrambufferFlag)) {
rectsMustMatchForBlitFramebuffer = true;
disallowSubrectForBlitFramebuffer = true;
// Mirroring causes rects to mismatch later, don't allow it.
originForBlitFramebuffer = src->origin();
- } else if (src->numColorSamples() && (this->blitFramebufferSupportFlags() &
- kRectsMustMatchForMSAASrc_BlitFramebufferFlag)) {
+ } else if (src->numColorSamples() > 1 && (this->blitFramebufferSupportFlags() &
+ kRectsMustMatchForMSAASrc_BlitFramebufferFlag)) {
rectsMustMatchForBlitFramebuffer = true;
// Mirroring causes rects to mismatch later, don't allow it.
originForBlitFramebuffer = src->origin();
@@ -2456,18 +2468,31 @@ void GrGLCaps::onApplyOptionsOverrides(const GrContextOptions& options) {
}
}
-int GrGLCaps::getSampleCount(int requestedCount, GrPixelConfig config) const {
+int GrGLCaps::getRenderTargetSampleCount(int requestedCount, GrPixelConfig config) const {
+ requestedCount = SkTMax(1, requestedCount);
int count = fConfigTable[config].fColorSampleCounts.count();
- if (!count || !this->isConfigRenderable(config, true)) {
+ if (!count) {
return 0;
}
+ if (1 == requestedCount) {
+ return fConfigTable[config].fColorSampleCounts[0] == 1 ? 1 : 0;
+ }
+
for (int i = 0; i < count; ++i) {
if (fConfigTable[config].fColorSampleCounts[i] >= requestedCount) {
return fConfigTable[config].fColorSampleCounts[i];
}
}
- return fConfigTable[config].fColorSampleCounts[count-1];
+ return 0;
+}
+
+int GrGLCaps::maxRenderTargetSampleCount(GrPixelConfig config) const {
+ const auto& table = fConfigTable[config].fColorSampleCounts;
+ if (!table.count()) {
+ return 0;
+ }
+ return table[table.count() - 1];
}
bool validate_sized_format(GrGLenum format, SkColorType ct, GrPixelConfig* config,
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index fd49a65598..7a443e49b0 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -112,19 +112,12 @@ public:
GrGLCaps(const GrContextOptions& contextOptions, const GrGLContextInfo& ctxInfo,
const GrGLInterface* glInterface);
- int getSampleCount(int requestedCount, GrPixelConfig config) const override;
-
bool isConfigTexturable(GrPixelConfig config) const override {
return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kTextureable_Flag);
}
- bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const override {
- if (withMSAA) {
- return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kRenderableWithMSAA_Flag);
- } else {
- return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kRenderable_Flag);
- }
- }
+ int getRenderTargetSampleCount(int requestedCount, GrPixelConfig config) const override;
+ int maxRenderTargetSampleCount(GrPixelConfig config) const override;
bool isConfigCopyable(GrPixelConfig config) const override {
// In GL we have three ways to be able to copy. CopyTexImage, blit, and draw. CopyTexImage
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index ae31495b06..b4a0341174 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -545,7 +545,7 @@ sk_sp<GrTexture> GrGLGpu::onWrapBackendTexture(const GrBackendTexture& backendTe
surfDesc.fWidth = backendTex.width();
surfDesc.fHeight = backendTex.height();
surfDesc.fConfig = backendTex.config();
- surfDesc.fSampleCnt = 0;
+ surfDesc.fSampleCnt = 1;
GrMipMapsStatus mipMapsStatus = backendTex.hasMipMaps() ? GrMipMapsStatus::kValid
: GrMipMapsStatus::kNotAllocated;
@@ -581,7 +581,10 @@ sk_sp<GrTexture> GrGLGpu::onWrapRenderableBackendTexture(const GrBackendTexture&
surfDesc.fWidth = backendTex.width();
surfDesc.fHeight = backendTex.height();
surfDesc.fConfig = backendTex.config();
- surfDesc.fSampleCnt = this->caps()->getSampleCount(sampleCnt, backendTex.config());
+ surfDesc.fSampleCnt = this->caps()->getRenderTargetSampleCount(sampleCnt, backendTex.config());
+ if (surfDesc.fSampleCnt < 1) {
+ return nullptr;
+ }
GrGLRenderTarget::IDDesc rtIDDesc;
if (!this->createRenderTargetObjects(surfDesc, idDesc.fInfo, &rtIDDesc)) {
@@ -616,7 +619,8 @@ sk_sp<GrRenderTarget> GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTa
desc.fWidth = backendRT.width();
desc.fHeight = backendRT.height();
desc.fConfig = backendRT.config();
- desc.fSampleCnt = this->caps()->getSampleCount(backendRT.sampleCnt(), backendRT.config());
+ desc.fSampleCnt =
+ this->caps()->getRenderTargetSampleCount(backendRT.sampleCnt(), backendRT.config());
return GrGLRenderTarget::MakeWrapped(this, desc, idDesc, backendRT.stencilBits());
}
@@ -645,7 +649,7 @@ sk_sp<GrRenderTarget> GrGLGpu::onWrapBackendTextureAsRenderTarget(const GrBacken
surfDesc.fWidth = tex.width();
surfDesc.fHeight = tex.height();
surfDesc.fConfig = tex.config();
- surfDesc.fSampleCnt = this->caps()->getSampleCount(sampleCnt, tex.config());
+ surfDesc.fSampleCnt = this->caps()->getRenderTargetSampleCount(sampleCnt, tex.config());
GrGLRenderTarget::IDDesc rtIDDesc;
if (!this->createRenderTargetObjects(surfDesc, texInfo, &rtIDDesc)) {
@@ -686,7 +690,7 @@ bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOri
}
// If the dst is MSAA, we have to draw, or we'll just be writing to the resolve target.
- if (dstSurface->asRenderTarget() && dstSurface->asRenderTarget()->numColorSamples() > 0) {
+ if (dstSurface->asRenderTarget() && dstSurface->asRenderTarget()->numColorSamples() > 1) {
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
}
@@ -704,7 +708,7 @@ bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOri
tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
tempDrawInfo->fTempSurfaceDesc.fWidth = width;
tempDrawInfo->fTempSurfaceDesc.fHeight = height;
- tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0;
+ tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 1;
tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL.
bool configsAreRBSwaps = GrPixelConfigSwapRAndB(srcConfig) == dstSurface->config();
@@ -1277,13 +1281,13 @@ bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc,
idDesc->fTexFBOID = 0;
SkASSERT((GrGLCaps::kMixedSamples_MSFBOType == this->glCaps().msFBOType()) ==
this->caps()->usesMixedSamples());
- idDesc->fIsMixedSampled = desc.fSampleCnt > 0 && this->caps()->usesMixedSamples();
+ idDesc->fIsMixedSampled = desc.fSampleCnt > 1 && this->caps()->usesMixedSamples();
GrGLenum status;
GrGLenum colorRenderbufferFormat = 0; // suppress warning
- if (desc.fSampleCnt > 0 && GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType()) {
+ if (desc.fSampleCnt > 1 && GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType()) {
goto FAILED;
}
@@ -1296,7 +1300,7 @@ bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc,
// the texture bound to the other. The exception is the IMG multisample extension. With this
// extension the texture is multisampled when rendered to and then auto-resolves it when it is
// rendered from.
- if (desc.fSampleCnt > 0 && this->glCaps().usesMSAARenderBuffers()) {
+ if (desc.fSampleCnt > 1 && this->glCaps().usesMSAARenderBuffers()) {
GL_CALL(GenFramebuffers(1, &idDesc->fRTFBOID));
GL_CALL(GenRenderbuffers(1, &idDesc->fMSColorRenderbufferID));
if (!idDesc->fRTFBOID ||
@@ -1313,7 +1317,7 @@ bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc,
// below here we may bind the FBO
fHWBoundRenderTargetUniqueID.makeInvalid();
if (idDesc->fRTFBOID != idDesc->fTexFBOID) {
- SkASSERT(desc.fSampleCnt > 0);
+ SkASSERT(desc.fSampleCnt > 1);
GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, idDesc->fMSColorRenderbufferID));
if (!renderbuffer_storage_msaa(*fGLContext,
desc.fSampleCnt,
@@ -1338,7 +1342,7 @@ bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc,
fStats.incRenderTargetBinds();
GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, idDesc->fTexFBOID));
- if (this->glCaps().usesImplicitMSAAResolve() && desc.fSampleCnt > 0) {
+ if (this->glCaps().usesImplicitMSAAResolve() && desc.fSampleCnt > 1) {
GL_CALL(FramebufferTexture2DMultisample(GR_GL_FRAMEBUFFER,
GR_GL_COLOR_ATTACHMENT0,
texInfo.fTarget,
@@ -1415,7 +1419,7 @@ sk_sp<GrTexture> GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
const GrMipLevel texels[],
int mipLevelCount) {
// We fail if the MSAA was requested and is not available.
- if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleCnt) {
+ if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleCnt > 1) {
//SkDebugf("MSAA RT requested but not supported on this platform.");
return return_null_texture();
}
@@ -1524,7 +1528,7 @@ void inline get_stencil_rb_sizes(const GrGLInterface* gl,
int GrGLGpu::getCompatibleStencilIndex(GrPixelConfig config) {
static const int kSize = 16;
- SkASSERT(this->caps()->isConfigRenderable(config, false));
+ SkASSERT(this->caps()->isConfigRenderable(config));
if (!this->glCaps().hasStencilFormatBeenDeterminedForConfig(config)) {
// Default to unsupported, set this if we find a stencil format that works.
int firstWorkingStencilFormatIndex = -1;
@@ -1694,7 +1698,7 @@ GrStencilAttachment* GrGLGpu::createStencilAttachmentForRenderTarget(const GrRen
CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
// we do this "if" so that we don't call the multisample
// version on a GL that doesn't have an MSAA extension.
- if (samples > 0) {
+ if (samples > 1) {
SkAssertResult(renderbuffer_storage_msaa(*fGLContext,
samples,
sFmt.fInternalFormat,
@@ -2133,7 +2137,7 @@ bool GrGLGpu::readPixelsSupported(GrPixelConfig rtConfig, GrPixelConfig readConf
GrSurfaceDesc desc;
desc.fConfig = rtConfig;
desc.fWidth = desc.fHeight = 16;
- if (this->glCaps().isConfigRenderable(rtConfig, false)) {
+ if (this->glCaps().isConfigRenderable(rtConfig)) {
desc.fFlags = kRenderTarget_GrSurfaceFlag;
desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
temp = this->createTexture(desc, SkBudgeted::kNo);
@@ -2194,7 +2198,7 @@ bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrig
tempDrawInfo->fTempSurfaceDesc.fFlags = kRenderTarget_GrSurfaceFlag;
tempDrawInfo->fTempSurfaceDesc.fWidth = width;
tempDrawInfo->fTempSurfaceDesc.fHeight = height;
- tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0;
+ tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 1;
tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL.
tempDrawInfo->fTempSurfaceFit = this->glCaps().partialFBOReadIsSlow() ? SkBackingFit::kExact
: SkBackingFit::kApprox;
@@ -2872,10 +2876,13 @@ void GrGLGpu::flushHWAAState(GrRenderTarget* rt, bool useHWAA, bool stencilEnabl
GL_CALL(Enable(GR_GL_RASTER_MULTISAMPLE));
fHWRasterMultisampleEnabled = kYes_TriState;
}
- if (rt->numStencilSamples() != fHWNumRasterSamples) {
- SkASSERT(rt->numStencilSamples() <= this->caps()->maxRasterSamples());
- GL_CALL(RasterSamples(rt->numStencilSamples(), GR_GL_TRUE));
- fHWNumRasterSamples = rt->numStencilSamples();
+ int numStencilSamples = rt->numStencilSamples();
+ // convert to GL's understanding of sample counts where 0 means nonMSAA.
+ numStencilSamples = 1 == numStencilSamples ? 0 : numStencilSamples;
+ if (numStencilSamples != fHWNumRasterSamples) {
+ SkASSERT(numStencilSamples <= this->caps()->maxRasterSamples());
+ GL_CALL(RasterSamples(numStencilSamples, GR_GL_TRUE));
+ fHWNumRasterSamples = numStencilSamples;
}
} else {
if (kNo_TriState != fHWRasterMultisampleEnabled) {
@@ -3334,8 +3341,8 @@ static inline bool can_blit_framebuffer_for_copy_surface(
}
}
if (GrGLCaps::kResolveMustBeFull_BlitFrambufferFlag & blitFramebufferFlags) {
- if (srcRT && srcRT->numColorSamples()) {
- if (dstRT && !dstRT->numColorSamples()) {
+ if (srcRT && srcRT->numColorSamples() > 1) {
+ if (dstRT && 1 == dstRT->numColorSamples()) {
return false;
}
if (SkRect::Make(srcRect) != srcRT->getBoundsRect()) {
@@ -3344,7 +3351,7 @@ static inline bool can_blit_framebuffer_for_copy_surface(
}
}
if (GrGLCaps::kNoMSAADst_BlitFramebufferFlag & blitFramebufferFlags) {
- if (dstRT && dstRT->numColorSamples() > 0) {
+ if (dstRT && dstRT->numColorSamples() > 1) {
return false;
}
}
@@ -3354,12 +3361,12 @@ static inline bool can_blit_framebuffer_for_copy_surface(
}
} else if (GrGLCaps::kNoFormatConversionForMSAASrc_BlitFramebufferFlag & blitFramebufferFlags) {
const GrRenderTarget* srcRT = src->asRenderTarget();
- if (srcRT && srcRT->numColorSamples() && dst->config() != src->config()) {
+ if (srcRT && srcRT->numColorSamples() > 1 && dst->config() != src->config()) {
return false;
}
}
if (GrGLCaps::kRectsMustMatchForMSAASrc_BlitFramebufferFlag & blitFramebufferFlags) {
- if (srcRT && srcRT->numColorSamples()) {
+ if (srcRT && srcRT->numColorSamples() > 1) {
if (dstPoint.fX != srcRect.fLeft || dstPoint.fY != srcRect.fTop) {
return false;
}
@@ -3376,7 +3383,7 @@ static bool rt_has_msaa_render_buffer(const GrGLRenderTarget* rt, const GrGLCaps
// 1) It's multisampled
// 2) We're using an extension with separate MSAA renderbuffers
// 3) It's not FBO 0, which is special and always auto-resolves
- return rt->numColorSamples() > 0 && glCaps.usesMSAARenderBuffers() && rt->renderFBOID() != 0;
+ return rt->numColorSamples() > 1 && glCaps.usesMSAARenderBuffers() && rt->renderFBOID() != 0;
}
static inline bool can_copy_texsubimage(const GrSurface* dst, GrSurfaceOrigin dstOrigin,
diff --git a/src/gpu/gl/GrGLRenderTarget.cpp b/src/gpu/gl/GrGLRenderTarget.cpp
index 443128d4d4..6f3714c504 100644
--- a/src/gpu/gl/GrGLRenderTarget.cpp
+++ b/src/gpu/gl/GrGLRenderTarget.cpp
@@ -224,7 +224,7 @@ int GrGLRenderTarget::msaaSamples() const {
if (fTexFBOID == kUnresolvableFBOID || fTexFBOID != fRTFBOID) {
// If the render target's FBO is external (fTexFBOID == kUnresolvableFBOID), or if we own
// the render target's FBO (fTexFBOID == fRTFBOID) then we use the provided sample count.
- return SkTMax(1, this->numStencilSamples());
+ return this->numStencilSamples();
}
// When fTexFBOID == fRTFBOID, we either are not using MSAA, or MSAA is auto resolving, so use
diff --git a/src/gpu/gl/GrGLStencilAttachment.cpp b/src/gpu/gl/GrGLStencilAttachment.cpp
index aa813ed50e..5c07a7d383 100644
--- a/src/gpu/gl/GrGLStencilAttachment.cpp
+++ b/src/gpu/gl/GrGLStencilAttachment.cpp
@@ -14,7 +14,7 @@ size_t GrGLStencilAttachment::onGpuMemorySize() const {
uint64_t size = this->width();
size *= this->height();
size *= fFormat.fTotalBits;
- size *= SkTMax(1,this->numSamples());
+ size *= this->numSamples();
return static_cast<size_t>(size / 8);
}
diff --git a/src/gpu/mock/GrMockCaps.h b/src/gpu/mock/GrMockCaps.h
index edec5563c4..1e448516d7 100644
--- a/src/gpu/mock/GrMockCaps.h
+++ b/src/gpu/mock/GrMockCaps.h
@@ -33,19 +33,39 @@ public:
this->applyOptionsOverrides(contextOptions);
}
- int getSampleCount(int /*requestCount*/, GrPixelConfig /*config*/) const override {
- return 0;
- }
bool isConfigTexturable(GrPixelConfig config) const override {
return fOptions.fConfigOptions[config].fTexturable;
}
- bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const override {
- return fOptions.fConfigOptions[config].fRenderable[withMSAA];
- }
+
bool isConfigCopyable(GrPixelConfig config) const override {
return false;
}
+ int getRenderTargetSampleCount(int requestCount, GrPixelConfig config) const override {
+ requestCount = SkTMax(requestCount, 1);
+ switch (fOptions.fConfigOptions[config].fRenderability) {
+ case GrMockOptions::ConfigOptions::Renderability::kNo:
+ return 0;
+ case GrMockOptions::ConfigOptions::Renderability::kNonMSAA:
+ return requestCount > 1 ? 0 : 1;
+ case GrMockOptions::ConfigOptions::Renderability::kMSAA:
+ return requestCount > kMaxSampleCnt ? 0 : GrNextPow2(requestCount);
+ }
+ return 0;
+ }
+
+ int maxRenderTargetSampleCount(GrPixelConfig config) const override {
+ switch (fOptions.fConfigOptions[config].fRenderability) {
+ case GrMockOptions::ConfigOptions::Renderability::kNo:
+ return 0;
+ case GrMockOptions::ConfigOptions::Renderability::kNonMSAA:
+ return 1;
+ case GrMockOptions::ConfigOptions::Renderability::kMSAA:
+ return kMaxSampleCnt;
+ }
+ return 0;
+ }
+
bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
bool* rectsMustMatch, bool* disallowSubrect) const override {
return false;
@@ -62,6 +82,8 @@ public:
}
private:
+ static const int kMaxSampleCnt = 16;
+
GrMockOptions fOptions;
typedef GrCaps INHERITED;
};
diff --git a/src/gpu/mock/GrMockTexture.h b/src/gpu/mock/GrMockTexture.h
index 9b6501a3c4..b5cc4a27c0 100644
--- a/src/gpu/mock/GrMockTexture.h
+++ b/src/gpu/mock/GrMockTexture.h
@@ -90,8 +90,11 @@ private:
}
size_t onGpuMemorySize() const override {
- // The plus 1 is to account for the resolve texture.
- int numColorSamples = this->numColorSamples() + 1;
+ int numColorSamples = this->numColorSamples();
+ if (numColorSamples > 1) {
+ // Add one to account for the resolve buffer.
+ ++numColorSamples;
+ }
return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
numColorSamples,
this->texturePriv().mipMapped());
diff --git a/src/gpu/mtl/GrMtlCaps.h b/src/gpu/mtl/GrMtlCaps.h
index 6204eaac5a..935cb07822 100644
--- a/src/gpu/mtl/GrMtlCaps.h
+++ b/src/gpu/mtl/GrMtlCaps.h
@@ -24,20 +24,12 @@ public:
GrMtlCaps(const GrContextOptions& contextOptions, id<MTLDevice> device,
MTLFeatureSet featureSet);
- int getSampleCount(int requestedCount, GrPixelConfig config) const override;
-
bool isConfigTexturable(GrPixelConfig config) const override {
return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kTextureable_Flag);
}
- bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const override {
- if (withMSAA) {
- return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kRenderable_Flag) &&
- SkToBool(fConfigTable[config].fFlags & ConfigInfo::kMSAA_Flag);
- } else {
- return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kRenderable_Flag);
- }
- }
+ int getRenderTargetSampleCount(int requestedCount, GrPixelConfig) const override;
+ int maxRenderTargetSampleCount(GrPixelConfig) const override;
bool isConfigCopyable(GrPixelConfig config) const override {
return true;
diff --git a/src/gpu/mtl/GrMtlCaps.mm b/src/gpu/mtl/GrMtlCaps.mm
index 2bce74a261..0bb7530fe2 100644
--- a/src/gpu/mtl/GrMtlCaps.mm
+++ b/src/gpu/mtl/GrMtlCaps.mm
@@ -121,7 +121,7 @@ void GrMtlCaps::initGrCaps(const id<MTLDevice> device) {
fMaxTextureSize = fMaxRenderTargetSize;
// Init sample counts. All devices support 1 (i.e. 0 in skia).
- fSampleCounts.push(0);
+ fSampleCounts.push(1);
for (auto sampleCnt : {2, 4, 8}) {
if ([device supportsTextureSampleCount:sampleCnt]) {
fSampleCounts.push(sampleCnt);
@@ -164,19 +164,29 @@ void GrMtlCaps::initGrCaps(const id<MTLDevice> device) {
fCrossContextTextureSupport = false;
}
-int GrMtlCaps::getSampleCount(int requestedCount, GrPixelConfig config) const {
- int count = fSampleCounts.count();
- SkASSERT(count > 0); // We always add 0 as a valid sample count
- if (!this->isConfigRenderable(config, true)) {
- return 0;
+
+int GrMtlCaps::maxRenderTargetSampleCount(GrPixelConfig config) const {
+ if (fConfigTable[config].fFlags & ConfigInfo::kMSAA_Flag) {
+ return fSampleCounts[fSampleCounts.count() - 1];
+ } else if (fConfigTable[config].fFlags & ConfigInfo::kRenderable_Flag) {
+ return 1;
}
+ return 0;
+}
- for (int i = 0; i < count; ++i) {
- if (fSampleCounts[i] >= requestedCount) {
- return fSampleCounts[i];
+int GrMtlCaps::getRenderTargetSampleCount(int requestedCount, GrPixelConfig config) const {
+ requestedCount = SkTMax(requestedCount, 1);
+ if (fConfigTable[config].fFlags & ConfigInfo::kMSAA_Flag) {
+ int count = fSampleCounts.count();
+ for (int i = 0; i < count; ++i) {
+ if (fSampleCounts[i] >= requestedCount) {
+ return fSampleCounts[i];
+ }
}
+ } else if (fConfigTable[config].fFlags & ConfigInfo::kRenderable_Flag) {
+ return 1 == requestedCount ? 1 : 0;
}
- return fSampleCounts[count-1];
+ return 0;
}
void GrMtlCaps::initShaderCaps() {
diff --git a/src/gpu/mtl/GrMtlRenderTarget.h b/src/gpu/mtl/GrMtlRenderTarget.h
index 4dac306e7e..83e7d3c240 100644
--- a/src/gpu/mtl/GrMtlRenderTarget.h
+++ b/src/gpu/mtl/GrMtlRenderTarget.h
@@ -63,8 +63,11 @@ protected:
// This accounts for the texture's memory and any MSAA renderbuffer's memory.
size_t onGpuMemorySize() const override {
+ int numColorSamples = this->numColorSamples();
// The plus 1 is to account for the resolve texture or if not using msaa the RT itself
- int numColorSamples = this->numColorSamples() + 1;
+ if (numColorSamples > 1) {
+ ++numColorSamples;
+ }
return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
numColorSamples, GrMipMapped::kNo);
}
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 0ae7c00995..8af81190af 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -346,7 +346,7 @@ void GrVkCaps::ConfigInfo::initSampleCounts(const GrVkInterface* interface,
&properties));
VkSampleCountFlags flags = properties.sampleCounts;
if (flags & VK_SAMPLE_COUNT_1_BIT) {
- fColorSampleCounts.push(0);
+ fColorSampleCounts.push(1);
}
if (kImagination_VkVendor == physProps.vendorID) {
// MSAA does not work on imagination
@@ -386,18 +386,34 @@ void GrVkCaps::ConfigInfo::init(const GrVkInterface* interface,
}
}
-int GrVkCaps::getSampleCount(int requestedCount, GrPixelConfig config) const {
+int GrVkCaps::getRenderTargetSampleCount(int requestedCount, GrPixelConfig config) const {
+ requestedCount = SkTMax(1, requestedCount);
int count = fConfigTable[config].fColorSampleCounts.count();
- if (!count || !this->isConfigRenderable(config, true)) {
+
+ if (!count) {
return 0;
}
+ if (1 == requestedCount) {
+ SkASSERT(fConfigTable[config].fColorSampleCounts.count() &&
+ fConfigTable[config].fColorSampleCounts[0] == 1);
+ return 1;
+ }
+
for (int i = 0; i < count; ++i) {
if (fConfigTable[config].fColorSampleCounts[i] >= requestedCount) {
return fConfigTable[config].fColorSampleCounts[i];
}
}
- return fConfigTable[config].fColorSampleCounts[count-1];
+ return 0;
+}
+
+int GrVkCaps::maxRenderTargetSampleCount(GrPixelConfig config) const {
+ const auto& table = fConfigTable[config].fColorSampleCounts;
+ if (!table.count()) {
+ return 0;
+ }
+ return table[table.count() - 1];
}
bool validate_image_info(const GrVkImageInfo* imageInfo, SkColorType ct, GrPixelConfig* config) {
diff --git a/src/gpu/vk/GrVkCaps.h b/src/gpu/vk/GrVkCaps.h
index d63c2ba9b5..3449dd2ccc 100644
--- a/src/gpu/vk/GrVkCaps.h
+++ b/src/gpu/vk/GrVkCaps.h
@@ -29,20 +29,17 @@ public:
GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
VkPhysicalDevice device, uint32_t featureFlags, uint32_t extensionFlags);
- int getSampleCount(int requestedCount, GrPixelConfig config) const override;
-
bool isConfigTexturable(GrPixelConfig config) const override {
return SkToBool(ConfigInfo::kTextureable_Flag & fConfigTable[config].fOptimalFlags);
}
- bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const override {
- return SkToBool(ConfigInfo::kRenderable_Flag & fConfigTable[config].fOptimalFlags);
- }
-
bool isConfigCopyable(GrPixelConfig config) const override {
return true;
}
+ int getRenderTargetSampleCount(int requestedCount, GrPixelConfig config) const override;
+ int maxRenderTargetSampleCount(GrPixelConfig config) const override;
+
bool isConfigTexturableLinearly(GrPixelConfig config) const {
return SkToBool(ConfigInfo::kTextureable_Flag & fConfigTable[config].fLinearFlags);
}
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index f7e3d47dd9..362ac1fa2b 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -352,7 +352,7 @@ bool GrVkGpu::onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOri
tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
tempDrawInfo->fTempSurfaceDesc.fWidth = width;
tempDrawInfo->fTempSurfaceDesc.fHeight = height;
- tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0;
+ tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 1;
tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin;
if (dstSurface->config() == srcConfig) {
@@ -777,17 +777,7 @@ sk_sp<GrTexture> GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted
bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
VkFormat pixelFormat;
- if (!GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat)) {
- return nullptr;
- }
-
- if (!fVkCaps->isConfigTexturable(desc.fConfig)) {
- return nullptr;
- }
-
- if (renderTarget && !fVkCaps->isConfigRenderable(desc.fConfig, false)) {
- return nullptr;
- }
+ SkAssertResult(GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat));
VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
if (renderTarget) {
@@ -914,7 +904,7 @@ sk_sp<GrTexture> GrVkGpu::onWrapBackendTexture(const GrBackendTexture& backendTe
surfDesc.fWidth = backendTex.width();
surfDesc.fHeight = backendTex.height();
surfDesc.fConfig = backendTex.config();
- surfDesc.fSampleCnt = 0;
+ surfDesc.fSampleCnt = 1;
return GrVkTexture::MakeWrappedTexture(this, surfDesc, ownership, backendTex.getVkImageInfo());
}
@@ -932,7 +922,7 @@ sk_sp<GrTexture> GrVkGpu::onWrapRenderableBackendTexture(const GrBackendTexture&
surfDesc.fWidth = backendTex.width();
surfDesc.fHeight = backendTex.height();
surfDesc.fConfig = backendTex.config();
- surfDesc.fSampleCnt = this->caps()->getSampleCount(sampleCnt, backendTex.config());
+ surfDesc.fSampleCnt = this->caps()->getRenderTargetSampleCount(sampleCnt, backendTex.config());
return GrVkTextureRenderTarget::MakeWrappedTextureRenderTarget(this, surfDesc, ownership,
backendTex.getVkImageInfo());
@@ -943,7 +933,7 @@ sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTa
// general this is not an issue since swapchain images in vulkan are never multisampled. Thus if
// you want a multisampled RT it is best to wrap the swapchain images and then let Skia handle
// creating and owning the MSAA images.
- if (backendRT.sampleCnt()) {
+ if (backendRT.sampleCnt() > 1) {
return nullptr;
}
@@ -961,7 +951,7 @@ sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTa
desc.fWidth = backendRT.width();
desc.fHeight = backendRT.height();
desc.fConfig = backendRT.config();
- desc.fSampleCnt = 0;
+ desc.fSampleCnt = 1;
sk_sp<GrVkRenderTarget> tgt = GrVkRenderTarget::MakeWrappedRenderTarget(this, desc, info);
if (tgt && backendRT.stencilBits()) {
@@ -989,7 +979,10 @@ sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendTextureAsRenderTarget(const GrBacken
desc.fWidth = tex.width();
desc.fHeight = tex.height();
desc.fConfig = tex.config();
- desc.fSampleCnt = this->caps()->getSampleCount(sampleCnt, tex.config());
+ desc.fSampleCnt = this->caps()->getRenderTargetSampleCount(sampleCnt, tex.config());
+ if (!desc.fSampleCnt) {
+ return nullptr;
+ }
sk_sp<GrVkRenderTarget> tgt = GrVkRenderTarget::MakeWrappedRenderTarget(this, desc, info);
return tgt;
@@ -1188,7 +1181,7 @@ GrBackendTexture GrVkGpu::createTestingOnlyBackendTexture(void* srcData, int w,
return GrBackendTexture(); // invalid
}
- if (isRenderTarget && !fVkCaps->isConfigRenderable(config, false)) {
+ if (isRenderTarget && !fVkCaps->isConfigRenderable(config)) {
return GrBackendTexture(); // invalid
}
@@ -1796,7 +1789,7 @@ inline bool can_copy_as_resolve(const GrSurface* dst, GrSurfaceOrigin dstOrigin,
const GrSurface* src, GrSurfaceOrigin srcOrigin,
const GrVkGpu* gpu) {
// Our src must be a multisampled render target
- if (!src->asRenderTarget() || src->asRenderTarget()->numColorSamples() <= 1) {
+ if (!src->asRenderTarget() || 1 == src->asRenderTarget()->numColorSamples()) {
return false;
}
@@ -1894,7 +1887,7 @@ bool GrVkGpu::onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrig
tempDrawInfo->fTempSurfaceDesc.fFlags = kRenderTarget_GrSurfaceFlag;
tempDrawInfo->fTempSurfaceDesc.fWidth = width;
tempDrawInfo->fTempSurfaceDesc.fHeight = height;
- tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0;
+ tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 1;
tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL.
tempDrawInfo->fTempSurfaceFit = SkBackingFit::kApprox;
diff --git a/src/gpu/vk/GrVkRenderTarget.cpp b/src/gpu/vk/GrVkRenderTarget.cpp
index c5a8628cc4..2a745ed51c 100644
--- a/src/gpu/vk/GrVkRenderTarget.cpp
+++ b/src/gpu/vk/GrVkRenderTarget.cpp
@@ -39,7 +39,7 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
, fResolveAttachmentView(resolveAttachmentView)
, fFramebuffer(nullptr)
, fCachedSimpleRenderPass(nullptr) {
- SkASSERT(desc.fSampleCnt);
+ SkASSERT(desc.fSampleCnt > 1);
this->createFramebuffer(gpu);
this->registerWithCache(budgeted);
}
@@ -62,7 +62,7 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
, fResolveAttachmentView(resolveAttachmentView)
, fFramebuffer(nullptr)
, fCachedSimpleRenderPass(nullptr) {
- SkASSERT(desc.fSampleCnt);
+ SkASSERT(desc.fSampleCnt > 1);
this->createFramebuffer(gpu);
}
@@ -82,7 +82,7 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
, fResolveAttachmentView(nullptr)
, fFramebuffer(nullptr)
, fCachedSimpleRenderPass(nullptr) {
- SkASSERT(!desc.fSampleCnt);
+ SkASSERT(1 == desc.fSampleCnt);
this->createFramebuffer(gpu);
this->registerWithCache(budgeted);
}
@@ -102,7 +102,7 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
, fResolveAttachmentView(nullptr)
, fFramebuffer(nullptr)
, fCachedSimpleRenderPass(nullptr) {
- SkASSERT(!desc.fSampleCnt);
+ SkASSERT(1 == desc.fSampleCnt);
this->createFramebuffer(gpu);
}
@@ -121,7 +121,7 @@ GrVkRenderTarget::Create(GrVkGpu* gpu,
// create msaa surface if necessary
GrVkImageInfo msInfo;
const GrVkImageView* resolveAttachmentView = nullptr;
- if (desc.fSampleCnt) {
+ if (desc.fSampleCnt > 1) {
GrVkImage::ImageDesc msImageDesc;
msImageDesc.fImageType = VK_IMAGE_TYPE_2D;
msImageDesc.fFormat = pixelFormat;
@@ -158,7 +158,7 @@ GrVkRenderTarget::Create(GrVkGpu* gpu,
const GrVkImageView* colorAttachmentView = GrVkImageView::Create(gpu, colorImage, pixelFormat,
GrVkImageView::kColor_Type, 1);
if (!colorAttachmentView) {
- if (desc.fSampleCnt) {
+ if (desc.fSampleCnt > 1) {
resolveAttachmentView->unref(gpu);
GrVkImage::DestroyImageInfo(gpu, &msInfo);
}
@@ -166,7 +166,7 @@ GrVkRenderTarget::Create(GrVkGpu* gpu,
}
GrVkRenderTarget* texRT;
- if (desc.fSampleCnt) {
+ if (desc.fSampleCnt > 1) {
texRT = new GrVkRenderTarget(gpu, budgeted, desc, info, msInfo,
colorAttachmentView, resolveAttachmentView, ownership);
} else {
@@ -237,11 +237,10 @@ void GrVkRenderTarget::createFramebuffer(GrVkGpu* gpu) {
void GrVkRenderTarget::getAttachmentsDescriptor(
GrVkRenderPass::AttachmentsDescriptor* desc,
GrVkRenderPass::AttachmentFlags* attachmentFlags) const {
- int colorSamples = this->numColorSamples();
VkFormat colorFormat;
GrPixelConfigToVkFormat(this->config(), &colorFormat);
desc->fColor.fFormat = colorFormat;
- desc->fColor.fSamples = colorSamples ? colorSamples : 1;
+ desc->fColor.fSamples = this->numColorSamples();
*attachmentFlags = GrVkRenderPass::kColor_AttachmentFlag;
uint32_t attachmentCount = 1;
@@ -249,7 +248,7 @@ void GrVkRenderTarget::getAttachmentsDescriptor(
if (stencil) {
const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
desc->fStencil.fFormat = vkStencil->vkFormat();
- desc->fStencil.fSamples = vkStencil->numSamples() ? vkStencil->numSamples() : 1;
+ desc->fStencil.fSamples = vkStencil->numSamples();
// Currently in vulkan stencil and color attachments must all have same number of samples
SkASSERT(desc->fColor.fSamples == desc->fStencil.fSamples);
*attachmentFlags |= GrVkRenderPass::kStencil_AttachmentFlag;
diff --git a/src/gpu/vk/GrVkRenderTarget.h b/src/gpu/vk/GrVkRenderTarget.h
index eb297a8a1d..02d4add455 100644
--- a/src/gpu/vk/GrVkRenderTarget.h
+++ b/src/gpu/vk/GrVkRenderTarget.h
@@ -99,8 +99,11 @@ protected:
// This accounts for the texture's memory and any MSAA renderbuffer's memory.
size_t onGpuMemorySize() const override {
- // The plus 1 is to account for the resolve texture or if not using msaa the RT itself
- int numColorSamples = this->numColorSamples() + 1;
+ int numColorSamples = this->numColorSamples();
+ if (numColorSamples > 1) {
+ // Add one to account for the resolved VkImage.
+ numColorSamples += 1;
+ }
return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
numColorSamples, GrMipMapped::kNo);
}
diff --git a/src/gpu/vk/GrVkStencilAttachment.cpp b/src/gpu/vk/GrVkStencilAttachment.cpp
index 5348885a6b..139c00f3b2 100644
--- a/src/gpu/vk/GrVkStencilAttachment.cpp
+++ b/src/gpu/vk/GrVkStencilAttachment.cpp
@@ -72,7 +72,7 @@ size_t GrVkStencilAttachment::onGpuMemorySize() const {
uint64_t size = this->width();
size *= this->height();
size *= fFormat.fTotalBits;
- size *= SkTMax(1,this->numSamples());
+ size *= this->numSamples();
return static_cast<size_t>(size / 8);
}
diff --git a/src/gpu/vk/GrVkTextureRenderTarget.cpp b/src/gpu/vk/GrVkTextureRenderTarget.cpp
index 9a211e208a..ee31f2364a 100644
--- a/src/gpu/vk/GrVkTextureRenderTarget.cpp
+++ b/src/gpu/vk/GrVkTextureRenderTarget.cpp
@@ -106,7 +106,7 @@ sk_sp<GrVkTextureRenderTarget> GrVkTextureRenderTarget::Make(GrVkGpu* gpu,
// create msaa surface if necessary
GrVkImageInfo msInfo;
const GrVkImageView* resolveAttachmentView = nullptr;
- if (desc.fSampleCnt) {
+ if (desc.fSampleCnt > 1) {
GrVkImage::ImageDesc msImageDesc;
msImageDesc.fImageType = VK_IMAGE_TYPE_2D;
msImageDesc.fFormat = pixelFormat;
@@ -145,7 +145,7 @@ sk_sp<GrVkTextureRenderTarget> GrVkTextureRenderTarget::Make(GrVkGpu* gpu,
const GrVkImageView* colorAttachmentView = GrVkImageView::Create(gpu, colorImage, pixelFormat,
GrVkImageView::kColor_Type, 1);
if (!colorAttachmentView) {
- if (desc.fSampleCnt) {
+ if (desc.fSampleCnt > 1) {
resolveAttachmentView->unref(gpu);
GrVkImage::DestroyImageInfo(gpu, &msInfo);
}
@@ -154,7 +154,7 @@ sk_sp<GrVkTextureRenderTarget> GrVkTextureRenderTarget::Make(GrVkGpu* gpu,
}
sk_sp<GrVkTextureRenderTarget> texRT;
- if (desc.fSampleCnt) {
+ if (desc.fSampleCnt > 1) {
if (!isWrapped) {
texRT = sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget(
gpu, budgeted, desc,
@@ -232,7 +232,7 @@ GrVkTextureRenderTarget::MakeWrappedTextureRenderTarget(GrVkGpu* gpu,
bool GrVkTextureRenderTarget::updateForMipmap(GrVkGpu* gpu, const GrVkImageInfo& newInfo) {
VkFormat pixelFormat;
GrPixelConfigToVkFormat(this->config(), &pixelFormat);
- if (this->numStencilSamples()) {
+ if (this->numStencilSamples() > 1) {
const GrVkImageView* resolveAttachmentView =
GrVkImageView::Create(gpu,
newInfo.fImage,
@@ -262,8 +262,11 @@ bool GrVkTextureRenderTarget::updateForMipmap(GrVkGpu* gpu, const GrVkImageInfo&
}
size_t GrVkTextureRenderTarget::onGpuMemorySize() const {
- // The plus 1 is to account for the resolve texture.
- int numColorSamples = this->numColorSamples() + 1;
+ int numColorSamples = this->numColorSamples();
+ if (numColorSamples > 1) {
+ // Add one to account for the resolve VkImage.
+ ++numColorSamples;
+ }
return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
numColorSamples, // TODO: this still correct?
this->texturePriv().mipMapped());
diff --git a/src/gpu/vk/GrVkUtil.cpp b/src/gpu/vk/GrVkUtil.cpp
index cb0046e58c..12db4c111e 100644
--- a/src/gpu/vk/GrVkUtil.cpp
+++ b/src/gpu/vk/GrVkUtil.cpp
@@ -263,8 +263,8 @@ bool GrVkFormatIsSRGB(VkFormat format, VkFormat* linearFormat) {
}
bool GrSampleCountToVkSampleCount(uint32_t samples, VkSampleCountFlagBits* vkSamples) {
+ SkASSERT(samples >= 1);
switch (samples) {
- case 0: // fall through
case 1:
*vkSamples = VK_SAMPLE_COUNT_1_BIT;
return true;
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index c00c50d000..a136c7b49c 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -438,13 +438,8 @@ static sk_sp<SkImage> make_from_yuv_textures_copy(GrContext* ctx, SkYUVColorSpac
// Needs to be a render target in order to draw to it for the yuv->rgb conversion.
sk_sp<GrRenderTargetContext> renderTargetContext(ctx->makeDeferredRenderTargetContext(
- SkBackingFit::kExact,
- width, height,
- kRGBA_8888_GrPixelConfig,
- std::move(imageColorSpace),
- 0,
- GrMipMapped::kNo,
- origin));
+ SkBackingFit::kExact, width, height, kRGBA_8888_GrPixelConfig,
+ std::move(imageColorSpace), 1, GrMipMapped::kNo, origin));
if (!renderTargetContext) {
return nullptr;
}
diff --git a/src/image/SkImage_Lazy.cpp b/src/image/SkImage_Lazy.cpp
index ed4683542f..92d3a2fed9 100644
--- a/src/image/SkImage_Lazy.cpp
+++ b/src/image/SkImage_Lazy.cpp
@@ -267,9 +267,8 @@ struct CacheCaps {
#if SK_SUPPORT_GPU
bool supportsHalfFloat() const {
- return !fCaps ||
- (fCaps->isConfigTexturable(kRGBA_half_GrPixelConfig) &&
- fCaps->isConfigRenderable(kRGBA_half_GrPixelConfig, false));
+ return !fCaps || (fCaps->isConfigTexturable(kRGBA_half_GrPixelConfig) &&
+ fCaps->isConfigRenderable(kRGBA_half_GrPixelConfig));
}
bool supportsSRGB() const {
diff --git a/src/image/SkSurface.cpp b/src/image/SkSurface.cpp
index 0a684cce60..ef6d809957 100644
--- a/src/image/SkSurface.cpp
+++ b/src/image/SkSurface.cpp
@@ -247,8 +247,8 @@ sk_sp<SkSurface> SkSurface::MakeNull(int width, int height) {
#if !SK_SUPPORT_GPU
-sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&,
- int, GrSurfaceOrigin, const SkSurfaceProps*, bool) {
+sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&, int,
+ GrSurfaceOrigin, const SkSurfaceProps*, bool) {
return nullptr;
}
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index 9f7ec3b7f5..ff66844da7 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -256,7 +256,7 @@ sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext* ctx, SkBudgeted budgeted
if (!SkSurface_Gpu::Valid(info)) {
return nullptr;
}
-
+ sampleCount = SkTMax(1, sampleCount);
GrMipMapped mipMapped = shouldCreateWithMips ? GrMipMapped::kYes : GrMipMapped::kNo;
if (!ctx->caps()->mipMapSupport()) {
@@ -299,6 +299,7 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext* context, const GrB
if (!SkSurface_Gpu::Valid(context, tex.config(), colorSpace.get())) {
return nullptr;
}
+ sampleCnt = SkTMax(1, sampleCnt);
sk_sp<GrRenderTargetContext> rtc(context->contextPriv().makeBackendTextureRenderTargetContext(
tex,
@@ -333,11 +334,9 @@ bool validate_backend_texture(GrContext* ctx, const GrBackendTexture& tex, GrPix
return false;
}
- if (!ctx->caps()->isConfigRenderable(*config, sampleCnt > 0)) {
- return false;
- }
-
- if (ctx->caps()->getSampleCount(sampleCnt, *config) != sampleCnt) {
+ // 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->caps()->getRenderTargetSampleCount(sampleCnt, *config)) {
return false;
}
@@ -355,6 +354,7 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext* context, const GrB
if (!context) {
return nullptr;
}
+ sampleCnt = SkTMax(1, sampleCnt);
GrBackendTexture texCopy = tex;
if (!validate_backend_texture(context, texCopy, &texCopy.fConfig,
sampleCnt, colorType, colorSpace, true)) {
@@ -409,7 +409,11 @@ bool validate_backend_render_target(GrContext* ctx, const GrBackendRenderTarget&
return false;
}
- if (!ctx->caps()->isConfigRenderable(*config, false)) {
+ if (rt.sampleCnt() > 1) {
+ if (ctx->caps()->maxRenderTargetSampleCount(*config) <= 1) {
+ return false;
+ }
+ } else if (!ctx->caps()->isConfigRenderable(*config)) {
return false;
}
@@ -445,6 +449,7 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext* cont
if (!SkSurface_Gpu::Valid(context, tex.config(), colorSpace.get())) {
return nullptr;
}
+ sampleCnt = SkTMax(1, sampleCnt);
sk_sp<GrRenderTargetContext> rtc(
context->contextPriv().makeBackendTextureAsRenderTargetRenderTargetContext(
@@ -475,6 +480,7 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext* cont
if (!context) {
return nullptr;
}
+ sampleCnt = SkTMax(1, sampleCnt);
GrBackendTexture texCopy = tex;
if (!validate_backend_texture(context, texCopy, &texCopy.fConfig,
sampleCnt, colorType, colorSpace, false)) {
diff --git a/src/utils/win/SkWGL.h b/src/utils/win/SkWGL.h
index c6c9479abe..cd19f2eeba 100644
--- a/src/utils/win/SkWGL.h
+++ b/src/utils/win/SkWGL.h
@@ -83,7 +83,8 @@ public:
* priority are:
* * Choose formats with the smallest sample count that is >=
* desiredSampleCount (or the largest sample count if all formats have
- * fewer samples than desiredSampleCount.)
+ * fewer samples than desiredSampleCount.) If desiredSampleCount is 1 then
+ * all msaa formats are excluded from consideration.
* * Choose formats with the fewest color samples when coverage sampling
* is available.
* * If the above rules leave multiple formats, choose the one that
@@ -130,8 +131,9 @@ enum SkWGLContextRequest {
/**
* Helper to create an OpenGL context for a DC using WGL. Configs with a sample count >= to
* msaaSampleCount are preferred but if none is available then a context with a lower sample count
- * (including non-MSAA) will be created. If preferCoreProfile is true but a core profile cannot be
- * created then a compatible profile context will be created.
+ * (including non-MSAA) will be created. If msaaSampleCount is 1 then this will fail if a non-msaa
+ * context cannot be created. If preferCoreProfile is true but a core profile cannot be created
+ * then a compatible profile context will be created.
*/
HGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, bool deepColor, SkWGLContextRequest context,
HGLRC shareContext = nullptr);
diff --git a/src/utils/win/SkWGL_win.cpp b/src/utils/win/SkWGL_win.cpp
index b7c89944e0..441d7a4ebb 100644
--- a/src/utils/win/SkWGL_win.cpp
+++ b/src/utils/win/SkWGL_win.cpp
@@ -126,6 +126,7 @@ int SkWGLExtensions::selectFormat(const int formats[],
int formatCount,
HDC dc,
int desiredSampleCount) const {
+ SkASSERT(desiredSampleCount >= 1);
if (formatCount <= 0) {
return -1;
}
@@ -146,7 +147,7 @@ int SkWGLExtensions::selectFormat(const int formats[],
&kQueryAttr,
&numSamples);
rankedFormats[i].fFormat = formats[i];
- rankedFormats[i].fSampleCnt = numSamples;
+ rankedFormats[i].fSampleCnt = SkTMax(1, numSamples);
rankedFormats[i].fChoosePixelFormatRank = i;
}
SkTQSort(rankedFormats.begin(),
@@ -159,6 +160,10 @@ int SkWGLExtensions::selectFormat(const int formats[],
if (idx < 0) {
idx = ~idx;
}
+ // If the caller asked for non-MSAA fail if the closest format has MSAA.
+ if (desiredSampleCount == 1 && rankedFormats[idx].fSampleCnt != 1) {
+ return -1;
+ }
return rankedFormats[idx].fFormat;
}