aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar vbuzinov <vbuzinov@nvidia.com>2015-06-12 08:59:45 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-06-12 08:59:45 -0700
commitdded69693dd3779f081326cde24c3954505b129d (patch)
tree0cfc3a16d31093185082268ab16599edb7c0464f /src
parent57856a1f589bea64ed84535efed0668221060f9b (diff)
Implement support for mixed sampled render targets
Adds a new FBO type kStencil_MSFBOType that is selected whenever NV_framebuffer_mixed_samples extension is available. In this new FBO type a non-msaa color buffer is created with a multisampled stencil buffer attachment. Replaces numSamples() with separate numColorSamples and numStencilSamples methods in RenderTarget. In mixed samples mode non-MSAA codepaths are used to draw simple shapes, while NVPR-rendered paths and text are rendered with a multisampled stencil. BUG=skia:3177 Review URL: https://codereview.chromium.org/1001503002
Diffstat (limited to 'src')
-rw-r--r--src/core/SkMultiPictureDraw.cpp4
-rw-r--r--src/gpu/GrBlurUtils.cpp2
-rw-r--r--src/gpu/GrClipMaskManager.cpp6
-rwxr-xr-xsrc/gpu/GrContext.cpp3
-rw-r--r--src/gpu/GrDrawContext.cpp11
-rw-r--r--src/gpu/GrGpu.cpp3
-rw-r--r--src/gpu/GrOvalRenderer.cpp6
-rw-r--r--src/gpu/GrPipelineBuilder.cpp2
-rw-r--r--src/gpu/GrPipelineBuilder.h2
-rw-r--r--src/gpu/GrStencilAndCoverPathRenderer.cpp20
-rw-r--r--src/gpu/GrStencilAndCoverTextContext.cpp2
-rw-r--r--src/gpu/GrTexture.cpp2
-rw-r--r--src/gpu/SkGpuDevice.cpp12
-rw-r--r--src/gpu/effects/GrDashingEffect.cpp2
-rw-r--r--src/gpu/gl/GrGLCaps.cpp13
-rw-r--r--src/gpu/gl/GrGLCaps.h16
-rw-r--r--src/gpu/gl/GrGLGpu.cpp16
-rw-r--r--src/gpu/gl/GrGLRenderTarget.cpp4
-rw-r--r--src/gpu/gl/GrGLRenderTarget.h11
-rw-r--r--src/image/SkSurface_Gpu.cpp4
20 files changed, 93 insertions, 48 deletions
diff --git a/src/core/SkMultiPictureDraw.cpp b/src/core/SkMultiPictureDraw.cpp
index 7cdab7300c..22fd05fb08 100644
--- a/src/core/SkMultiPictureDraw.cpp
+++ b/src/core/SkMultiPictureDraw.cpp
@@ -141,7 +141,7 @@ void SkMultiPictureDraw::draw(bool flush) {
GrLayerHoister::FindLayersToAtlas(context, data.fPicture, initialMatrix,
clipBounds,
&atlasedNeedRendering, &atlasedRecycled,
- rt->numSamples());
+ rt->numColorSamples());
}
}
@@ -174,7 +174,7 @@ void SkMultiPictureDraw::draw(bool flush) {
// layers in the 'recycled' list since they have already been drawn.
GrLayerHoister::FindLayersToHoist(context, picture, initialMatrix,
clipBounds, &needRendering, &recycled,
- rt->numSamples());
+ rt->numColorSamples());
GrLayerHoister::DrawLayers(context, needRendering);
diff --git a/src/gpu/GrBlurUtils.cpp b/src/gpu/GrBlurUtils.cpp
index 66861ec07f..caea2b45f5 100644
--- a/src/gpu/GrBlurUtils.cpp
+++ b/src/gpu/GrBlurUtils.cpp
@@ -259,7 +259,7 @@ void GrBlurUtils::drawPathWithMaskFilter(GrContext* context,
*devPathPtr,
strokeInfo,
grPaint.isAntiAlias(),
- renderTarget->numSamples()));
+ renderTarget->numColorSamples()));
if (mask) {
GrTexture* filtered;
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index 9d79a6dc89..17a15a32c4 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -165,7 +165,7 @@ bool GrClipMaskManager::installClipEffects(GrPipelineBuilder* pipelineBuilder,
if (!skip) {
GrPrimitiveEdgeType edgeType;
if (iter.get()->isAA()) {
- if (rt->isMultisampled()) {
+ if (rt->isUnifiedMultisampled()) {
// Coverage based AA clips don't place nicely with MSAA.
failed = true;
break;
@@ -306,7 +306,7 @@ bool GrClipMaskManager::setupClipping(GrPipelineBuilder* pipelineBuilder,
}
// If MSAA is enabled we can do everything in the stencil buffer.
- if (0 == rt->numSamples() && requiresAA) {
+ if (0 == rt->numColorSamples() && requiresAA) {
GrTexture* result = NULL;
// The top-left of the mask corresponds to the top-left corner of the bounds.
@@ -750,7 +750,7 @@ bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt,
pipelineBuilder.setDisableColorXPFactory();
// if the target is MSAA then we want MSAA enabled when the clip is soft
- if (rt->isMultisampled()) {
+ if (rt->isUnifiedMultisampled()) {
pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, element->isAA());
}
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index ca98ffb416..64f4cb3dec 100755
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -250,7 +250,8 @@ GrTextContext* GrContext::createTextContext(GrRenderTarget* renderTarget,
const SkDeviceProperties&
leakyProperties,
bool enableDistanceFieldFonts) {
- if (fGpu->caps()->shaderCaps()->pathRenderingSupport() && renderTarget->isMultisampled()) {
+ if (fGpu->caps()->shaderCaps()->pathRenderingSupport() &&
+ renderTarget->isStencilBufferMultisampled()) {
GrStencilAttachment* sb = renderTarget->renderTargetPriv().attachStencilAttachment();
if (sb) {
return GrStencilAndCoverTextContext::Create(this, leakyProperties);
diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp
index 92a1e36f18..23c349ba17 100644
--- a/src/gpu/GrDrawContext.cpp
+++ b/src/gpu/GrDrawContext.cpp
@@ -156,7 +156,7 @@ static bool apply_aa_to_rect(GrDrawTarget* target,
SkScalar strokeWidth,
const SkMatrix& combinedMatrix,
GrColor color) {
- if (pipelineBuilder->getRenderTarget()->isMultisampled()) {
+ if (pipelineBuilder->getRenderTarget()->isUnifiedMultisampled()) {
return false;
}
@@ -422,7 +422,8 @@ void GrDrawContext::drawRect(GrRenderTarget* rt,
GrColor color = paint.getColor();
SkRect devBoundRect;
- bool needAA = paint.isAntiAlias() && !pipelineBuilder.getRenderTarget()->isMultisampled();
+ bool needAA = paint.isAntiAlias() &&
+ !pipelineBuilder.getRenderTarget()->isUnifiedMultisampled();
bool doAA = needAA && apply_aa_to_rect(fDrawTarget, &pipelineBuilder, &devBoundRect, rect,
width, viewMatrix, color);
@@ -455,7 +456,7 @@ void GrDrawContext::drawRect(GrRenderTarget* rt,
geometry.fStrokeWidth = width;
// Non-AA hairlines are snapped to pixel centers to make which pixels are hit deterministic
- bool snapToPixelCenters = (0 == width && !rt->isMultisampled());
+ bool snapToPixelCenters = (0 == width && !rt->isUnifiedMultisampled());
SkAutoTUnref<GrBatch> batch(StrokeRectBatch::Create(geometry, snapToPixelCenters));
// Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
@@ -1014,7 +1015,7 @@ void GrDrawContext::drawPath(GrRenderTarget* rt,
if (!strokeInfo.isDashed()) {
bool useCoverageAA = paint.isAntiAlias() &&
- !pipelineBuilder.getRenderTarget()->isMultisampled();
+ !pipelineBuilder.getRenderTarget()->isUnifiedMultisampled();
if (useCoverageAA && strokeInfo.getWidth() < 0 && !path.isConvex()) {
// Concave AA paths are expensive - try to avoid them for special cases
@@ -1062,7 +1063,7 @@ void GrDrawContext::internalDrawPath(GrDrawTarget* target,
// aa. If we have some future driver-mojo path AA that can do the right
// thing WRT to the blend then we'll need some query on the PR.
bool useCoverageAA = useAA &&
- !pipelineBuilder->getRenderTarget()->isMultisampled();
+ !pipelineBuilder->getRenderTarget()->isUnifiedMultisampled();
GrPathRendererChain::DrawType type =
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 4d6f5d6238..a6e9654659 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -146,7 +146,8 @@ bool GrGpu::attachStencilAttachmentToRenderTarget(GrRenderTarget* rt) {
}
#endif
- GrStencilAttachment::ComputeSharedStencilAttachmentKey(width, height, rt->numSamples(), &sbKey);
+ GrStencilAttachment::ComputeSharedStencilAttachmentKey(width, height,
+ rt->numStencilSamples(), &sbKey);
SkAutoTUnref<GrStencilAttachment> sb(static_cast<GrStencilAttachment*>(
this->getContext()->getResourceCache()->findAndRefUniqueResource(sbKey)));
if (sb) {
diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp
index f98adaa0a4..e5e742c993 100644
--- a/src/gpu/GrOvalRenderer.cpp
+++ b/src/gpu/GrOvalRenderer.cpp
@@ -610,7 +610,7 @@ bool GrOvalRenderer::DrawOval(GrDrawTarget* target,
const SkRect& oval,
const SkStrokeRec& stroke)
{
- bool useCoverageAA = useAA && !pipelineBuilder->getRenderTarget()->isMultisampled();
+ bool useCoverageAA = useAA && !pipelineBuilder->getRenderTarget()->isUnifiedMultisampled();
if (!useCoverageAA) {
return false;
@@ -1404,7 +1404,7 @@ bool GrOvalRenderer::DrawDRRect(GrDrawTarget* target,
const SkRRect& origOuter,
const SkRRect& origInner) {
bool applyAA = useAA &&
- !pipelineBuilder->getRenderTarget()->isMultisampled();
+ !pipelineBuilder->getRenderTarget()->isUnifiedMultisampled();
GrPipelineBuilder::AutoRestoreFragmentProcessors arfp;
if (!origInner.isEmpty()) {
SkTCopyOnFirstWrite<SkRRect> inner(origInner);
@@ -1978,7 +1978,7 @@ bool GrOvalRenderer::DrawRRect(GrDrawTarget* target,
stroke);
}
- bool useCoverageAA = useAA && !pipelineBuilder->getRenderTarget()->isMultisampled();
+ bool useCoverageAA = useAA && !pipelineBuilder->getRenderTarget()->isUnifiedMultisampled();
// only anti-aliased rrects for now
if (!useCoverageAA) {
diff --git a/src/gpu/GrPipelineBuilder.cpp b/src/gpu/GrPipelineBuilder.cpp
index 26422fd547..b31d105963 100644
--- a/src/gpu/GrPipelineBuilder.cpp
+++ b/src/gpu/GrPipelineBuilder.cpp
@@ -75,7 +75,7 @@ void GrPipelineBuilder::setFromPaint(const GrPaint& paint, GrRenderTarget* rt, c
this->setState(GrPipelineBuilder::kDither_Flag, paint.isDither());
this->setState(GrPipelineBuilder::kHWAntialias_Flag,
- rt->isMultisampled() && paint.isAntiAlias());
+ rt->isUnifiedMultisampled() && paint.isAntiAlias());
fColorProcInfoValid = false;
fCoverageProcInfoValid = false;
diff --git a/src/gpu/GrPipelineBuilder.h b/src/gpu/GrPipelineBuilder.h
index 6a0e137f99..87c2bc08bc 100644
--- a/src/gpu/GrPipelineBuilder.h
+++ b/src/gpu/GrPipelineBuilder.h
@@ -210,7 +210,7 @@ public:
* than the color buffer. In is scenario, the higher sample rate is resolved during blending.
*/
bool hasMixedSamples() const {
- return this->isHWAntialias() && !fRenderTarget->isMultisampled();
+ return this->isHWAntialias() && !fRenderTarget->isUnifiedMultisampled();
}
/// @}
diff --git a/src/gpu/GrStencilAndCoverPathRenderer.cpp b/src/gpu/GrStencilAndCoverPathRenderer.cpp
index a082325b52..248730bde1 100644
--- a/src/gpu/GrStencilAndCoverPathRenderer.cpp
+++ b/src/gpu/GrStencilAndCoverPathRenderer.cpp
@@ -51,9 +51,17 @@ bool GrStencilAndCoverPathRenderer::canDrawPath(const GrDrawTarget* target,
const SkPath& path,
const GrStrokeInfo& stroke,
bool antiAlias) const {
- return !stroke.isHairlineStyle() &&
- !antiAlias && // doesn't do per-path AA, relies on the target having MSAA
- pipelineBuilder->getStencil().isDisabled();
+ if (stroke.isHairlineStyle()) {
+ return false;
+ }
+ if (!pipelineBuilder->getStencil().isDisabled()) {
+ return false;
+ }
+ if (antiAlias) {
+ return pipelineBuilder->getRenderTarget()->isStencilBufferMultisampled();
+ } else {
+ return true; // doesn't do per-path AA, relies on the target having MSAA
+ }
}
GrPathRenderer::StencilSupport
@@ -100,10 +108,14 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(GrDrawTarget* target,
const SkPath& path,
const GrStrokeInfo& stroke,
bool antiAlias) {
- SkASSERT(!antiAlias);
SkASSERT(!stroke.isHairlineStyle());
SkASSERT(pipelineBuilder->getStencil().isDisabled());
+ if (antiAlias) {
+ SkASSERT(pipelineBuilder->getRenderTarget()->isStencilBufferMultisampled());
+ pipelineBuilder->enableState(GrPipelineBuilder::kHWAntialias_Flag);
+ }
+
SkAutoTUnref<GrPath> p(get_gr_path(fResourceProvider, path, stroke));
if (path.isInverseFillType()) {
diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp
index 4d34cf47ba..763863fe75 100644
--- a/src/gpu/GrStencilAndCoverTextContext.cpp
+++ b/src/gpu/GrStencilAndCoverTextContext.cpp
@@ -373,6 +373,8 @@ void GrStencilAndCoverTextContext::init(GrRenderTarget* rt,
fStateRestore.set(&fPipelineBuilder);
fPipelineBuilder.setFromPaint(fPaint, fRenderTarget, fClip);
+ SkASSERT(fRenderTarget->isStencilBufferMultisampled() || !fPaint.isAntiAlias());
+ fPipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, fPaint.isAntiAlias());
GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
kZero_StencilOp,
diff --git a/src/gpu/GrTexture.cpp b/src/gpu/GrTexture.cpp
index 33b8687017..e954c5ee85 100644
--- a/src/gpu/GrTexture.cpp
+++ b/src/gpu/GrTexture.cpp
@@ -51,7 +51,7 @@ void GrTexture::validateDesc() const {
if (this->asRenderTarget()) {
// This texture has a render target
SkASSERT(0 != (fDesc.fFlags & kRenderTarget_GrSurfaceFlag));
- SkASSERT(fDesc.fSampleCnt == this->asRenderTarget()->numSamples());
+ SkASSERT(fDesc.fSampleCnt == this->asRenderTarget()->numColorSamples());
} else {
SkASSERT(0 == (fDesc.fFlags & kRenderTarget_GrSurfaceFlag));
SkASSERT(0 == fDesc.fSampleCnt);
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 6db5c1db0d..18b2643564 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -333,7 +333,7 @@ void SkGpuDevice::replaceRenderTarget(bool shouldRetainContent) {
: SkSurface::kNo_Budgeted;
SkAutoTUnref<GrRenderTarget> newRT(CreateRenderTarget(
- fRenderTarget->getContext(), budgeted, this->imageInfo(), fRenderTarget->numSamples()));
+ fRenderTarget->getContext(), budgeted, this->imageInfo(), fRenderTarget->desc().fSampleCnt));
if (NULL == newRT) {
return;
@@ -919,7 +919,7 @@ void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
// anti-aliased edges, we work around that for now by drawing directly
// if the image size exceeds maximum texture size.
int maxTextureSize = fContext->caps()->maxTextureSize();
- bool directDraw = fRenderTarget->isMultisampled() ||
+ bool directDraw = fRenderTarget->isUnifiedMultisampled() ||
!paint.isAntiAlias() ||
bitmap.width() > maxTextureSize ||
bitmap.height() > maxTextureSize;
@@ -1690,7 +1690,7 @@ SkBaseDevice* SkGpuDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint
desc.fFlags = kRenderTarget_GrSurfaceFlag;
desc.fWidth = cinfo.fInfo.width();
desc.fHeight = cinfo.fInfo.height();
- desc.fSampleCnt = fRenderTarget->numSamples();
+ desc.fSampleCnt = fRenderTarget->desc().fSampleCnt;
SkAutoTUnref<GrTexture> texture;
// Skia's convention is to only clear a device if it is non-opaque.
@@ -1718,7 +1718,7 @@ SkBaseDevice* SkGpuDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint
SkSurface* SkGpuDevice::newSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
// TODO: Change the signature of newSurface to take a budgeted parameter.
static const SkSurface::Budgeted kBudgeted = SkSurface::kNo_Budgeted;
- return SkSurface::NewRenderTarget(fContext, kBudgeted, info, fRenderTarget->numSamples(),
+ return SkSurface::NewRenderTarget(fContext, kBudgeted, info, fRenderTarget->desc().fSampleCnt,
&props);
}
@@ -1758,7 +1758,7 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture
initialMatrix,
clipBounds,
&atlasedNeedRendering, &atlasedRecycled,
- fRenderTarget->numSamples());
+ fRenderTarget->numColorSamples());
GrLayerHoister::DrawLayersToAtlas(fContext, atlasedNeedRendering);
@@ -1770,7 +1770,7 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture
initialMatrix,
clipBounds,
&needRendering, &recycled,
- fRenderTarget->numSamples());
+ fRenderTarget->numColorSamples());
GrLayerHoister::DrawLayers(fContext, needRendering);
diff --git a/src/gpu/effects/GrDashingEffect.cpp b/src/gpu/effects/GrDashingEffect.cpp
index ad6f70d96d..186cc417ee 100644
--- a/src/gpu/effects/GrDashingEffect.cpp
+++ b/src/gpu/effects/GrDashingEffect.cpp
@@ -734,7 +734,7 @@ bool GrDashingEffect::DrawDashLine(GrDrawTarget* target,
const SkMatrix& viewMatrix, const SkPoint pts[2],
bool useAA, const GrStrokeInfo& strokeInfo) {
SkAutoTUnref<GrBatch> batch(create_batch(color, viewMatrix, pts, useAA, strokeInfo,
- pipelineBuilder->getRenderTarget()->isMultisampled()));
+ pipelineBuilder->getRenderTarget()->isUnifiedMultisampled()));
if (!batch) {
return false;
}
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 40405fd55c..e8c3b55163 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -292,6 +292,11 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
ctxInfo.hasExtension("GL_NV_sample_mask_override_coverage") &&
ctxInfo.hasExtension("GL_EXT_raster_multisample");
}
+ // Workaround NVIDIA bug related to glInvalidateFramebuffer and mixed samples.
+ if (kNVIDIA_GrGLDriver == ctxInfo.driver() && fShaderCaps->mixedSamplesSupport()) {
+ fDiscardRenderTargetSupport = false;
+ fInvalidateFBType = kNone_InvalidateFBType;
+ }
/**************************************************************************
* GrCaps fields
@@ -789,6 +794,8 @@ void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo, const GrGLInterfa
fMSFBOType = kES_EXT_MsToTexture_MSFBOType;
} else if (ctxInfo.hasExtension("GL_IMG_multisampled_render_to_texture")) {
fMSFBOType = kES_IMG_MsToTexture_MSFBOType;
+ } else if (fShaderCaps->mixedSamplesSupport() && fShaderCaps->pathRenderingSupport()) {
+ fMSFBOType = kMixedSamples_MSFBOType;
} else if (ctxInfo.version() >= GR_GL_VER(3,0)) {
fMSFBOType = GrGLCaps::kES_3_0_MSFBOType;
} else if (ctxInfo.hasExtension("GL_CHROMIUM_framebuffer_multisample")) {
@@ -799,7 +806,9 @@ void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo, const GrGLInterfa
fMSFBOType = kES_Apple_MSFBOType;
}
} else {
- if ((ctxInfo.version() >= GR_GL_VER(3,0)) ||
+ if (fShaderCaps->mixedSamplesSupport() && fShaderCaps->pathRenderingSupport()) {
+ fMSFBOType = kMixedSamples_MSFBOType;
+ } else if ((ctxInfo.version() >= GR_GL_VER(3,0)) ||
ctxInfo.hasExtension("GL_ARB_framebuffer_object")) {
fMSFBOType = GrGLCaps::kDesktop_ARB_MSFBOType;
} else if (ctxInfo.hasExtension("GL_EXT_framebuffer_multisample") &&
@@ -932,6 +941,7 @@ SkString GrGLCaps::dump() const {
"Apple",
"IMG MS To Texture",
"EXT MS To Texture",
+ "MixedSamples",
};
GR_STATIC_ASSERT(0 == kNone_MSFBOType);
GR_STATIC_ASSERT(1 == kDesktop_ARB_MSFBOType);
@@ -940,6 +950,7 @@ SkString GrGLCaps::dump() const {
GR_STATIC_ASSERT(4 == kES_Apple_MSFBOType);
GR_STATIC_ASSERT(5 == kES_IMG_MsToTexture_MSFBOType);
GR_STATIC_ASSERT(6 == kES_EXT_MsToTexture_MSFBOType);
+ GR_STATIC_ASSERT(7 == kMixedSamples_MSFBOType);
GR_STATIC_ASSERT(SK_ARRAY_COUNT(kMSFBOExtStr) == kLast_MSFBOType + 1);
static const char* kInvalidateFBTypeStr[] = {
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index e924c60efb..b04bf34361 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -67,8 +67,12 @@ public:
* GL_MAX_SAMPLES value.
*/
kES_EXT_MsToTexture_MSFBOType,
+ /**
+ * GL_NV_framebuffer_mixed_samples.
+ */
+ kMixedSamples_MSFBOType,
- kLast_MSFBOType = kES_EXT_MsToTexture_MSFBOType
+ kLast_MSFBOType = kMixedSamples_MSFBOType
};
enum InvalidateFBType {
@@ -141,7 +145,8 @@ public:
bool usesMSAARenderBuffers() const {
return kNone_MSFBOType != fMSFBOType &&
kES_IMG_MsToTexture_MSFBOType != fMSFBOType &&
- kES_EXT_MsToTexture_MSFBOType != fMSFBOType;
+ kES_EXT_MsToTexture_MSFBOType != fMSFBOType &&
+ kMixedSamples_MSFBOType != fMSFBOType;
}
/**
@@ -153,8 +158,6 @@ public:
kES_EXT_MsToTexture_MSFBOType == fMSFBOType;
}
- bool fbMixedSamplesSupport() const { return fFBMixedSamplesSupport; }
-
InvalidateFBType invalidateFBType() const { return fInvalidateFBType; }
/// What type of buffer mapping is supported?
@@ -225,7 +228,9 @@ public:
bool ES2CompatibilitySupport() const { return fES2CompatibilitySupport; }
/// Can we call glDisable(GL_MULTISAMPLE)?
- bool multisampleDisableSupport() const { return fMultisampleDisableSupport; }
+ bool multisampleDisableSupport() const {
+ return fMultisampleDisableSupport;
+ }
/// Use indices or vertices in CPU arrays rather than VBOs for dynamic content.
bool useNonVBOVertexAndIndexDynamicData() const {
@@ -349,7 +354,6 @@ private:
bool fUseNonVBOVertexAndIndexDynamicData : 1;
bool fIsCoreProfile : 1;
bool fFullClearIsFree : 1;
- bool fFBMixedSamplesSupport : 1;
struct ReadPixelsSupportedFormat {
GrGLenum fFormat;
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 08e83ec197..625299d58c 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -373,6 +373,14 @@ void GrGLGpu::onResetContext(uint32_t resetBits) {
if (resetBits & kMSAAEnable_GrGLBackendState) {
fMSAAEnabled = kUnknown_TriState;
+
+ // In mixed samples mode coverage modulation allows the coverage to be converted to
+ // "opacity", which can then be blended into the color buffer to accomplish antialiasing.
+ // Enable coverage modulation suitable for premultiplied alpha colors.
+ // This state has no effect when not rendering to a mixed sampled target.
+ if (this->glCaps().shaderCaps()->mixedSamplesSupport()) {
+ GL_CALL(CoverageModulation(GR_GL_RGBA));
+ }
}
fHWActiveTextureUnitIdx = -1; // invalid
@@ -851,6 +859,7 @@ static bool renderbuffer_storage_msaa(const GrGLContext& ctx,
switch (ctx.caps()->msFBOType()) {
case GrGLCaps::kDesktop_ARB_MSFBOType:
case GrGLCaps::kDesktop_EXT_MSFBOType:
+ case GrGLCaps::kMixedSamples_MSFBOType:
case GrGLCaps::kES_3_0_MSFBOType:
GL_ALLOC_CALL(ctx.interface(),
RenderbufferStorageMultisample(GR_GL_RENDERBUFFER,
@@ -888,6 +897,9 @@ bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc,
idDesc->fRTFBOID = 0;
idDesc->fTexFBOID = 0;
idDesc->fLifeCycle = lifeCycle;
+ idDesc->fSampleConfig = (GrGLCaps::kMixedSamples_MSFBOType == this->glCaps().msFBOType() &&
+ desc.fSampleCnt > 0) ? GrRenderTarget::kStencil_SampleConfig :
+ GrRenderTarget::kUnified_SampleConfig;
GrGLenum status;
@@ -1170,7 +1182,7 @@ bool GrGLGpu::createStencilAttachmentForRenderTarget(GrRenderTarget* rt, int wid
SkASSERT(width >= rt->width());
SkASSERT(height >= rt->height());
- int samples = rt->numSamples();
+ int samples = rt->numStencilSamples();
GrGLStencilAttachment::IDDesc sbDesc;
int stencilFmtCnt = this->glCaps().stencilFormats().count();
@@ -2090,7 +2102,7 @@ void GrGLGpu::flushStencil(const GrStencilSettings& stencilSettings) {
}
void GrGLGpu::flushHWAAState(GrRenderTarget* rt, bool useHWAA) {
- SkASSERT(!useHWAA || rt->isMultisampled());
+ SkASSERT(!useHWAA || rt->isStencilBufferMultisampled());
if (this->glCaps().multisampleDisableSupport()) {
if (useHWAA) {
diff --git a/src/gpu/gl/GrGLRenderTarget.cpp b/src/gpu/gl/GrGLRenderTarget.cpp
index c9e65d4fab..a89022e27c 100644
--- a/src/gpu/gl/GrGLRenderTarget.cpp
+++ b/src/gpu/gl/GrGLRenderTarget.cpp
@@ -15,7 +15,7 @@
// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc)
: GrSurface(gpu, idDesc.fLifeCycle, desc)
- , INHERITED(gpu, idDesc.fLifeCycle, desc) {
+ , INHERITED(gpu, idDesc.fLifeCycle, desc, idDesc.fSampleConfig) {
this->init(desc, idDesc);
this->registerWithCache();
}
@@ -23,7 +23,7 @@ GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc, cons
GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc,
Derived)
: GrSurface(gpu, idDesc.fLifeCycle, desc)
- , INHERITED(gpu, idDesc.fLifeCycle, desc) {
+ , INHERITED(gpu, idDesc.fLifeCycle, desc, idDesc.fSampleConfig) {
this->init(desc, idDesc);
}
diff --git a/src/gpu/gl/GrGLRenderTarget.h b/src/gpu/gl/GrGLRenderTarget.h
index 7c0c08cdf6..32c7d4fd5e 100644
--- a/src/gpu/gl/GrGLRenderTarget.h
+++ b/src/gpu/gl/GrGLRenderTarget.h
@@ -22,10 +22,11 @@ public:
enum { kUnresolvableFBOID = 0 };
struct IDDesc {
- GrGLuint fRTFBOID;
- GrGLuint fTexFBOID;
- GrGLuint fMSColorRenderbufferID;
- GrGpuResource::LifeCycle fLifeCycle;
+ GrGLuint fRTFBOID;
+ GrGLuint fTexFBOID;
+ GrGLuint fMSColorRenderbufferID;
+ GrGpuResource::LifeCycle fLifeCycle;
+ GrRenderTarget::SampleConfig fSampleConfig;
};
GrGLRenderTarget(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&);
@@ -43,7 +44,7 @@ public:
// override of GrRenderTarget
ResolveType getResolveType() const override {
- if (!this->isMultisampled() ||
+ if (!this->isUnifiedMultisampled() ||
fRTFBOID == fTexFBOID) {
// catches FBO 0 and non MSAA case
return kAutoResolves_ResolveType;
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index f44bbfede0..ff18a04754 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -37,7 +37,7 @@ SkCanvas* SkSurface_Gpu::onNewCanvas() {
SkSurface* SkSurface_Gpu::onNewSurface(const SkImageInfo& info) {
GrRenderTarget* rt = fDevice->accessRenderTarget();
- int sampleCount = rt->numSamples();
+ int sampleCount = rt->numColorSamples();
// TODO: Make caller specify this (change virtual signature of onNewSurface).
static const Budgeted kBudgeted = kNo_Budgeted;
return SkSurface::NewRenderTarget(fDevice->context(), kBudgeted, info, sampleCount,
@@ -46,7 +46,7 @@ SkSurface* SkSurface_Gpu::onNewSurface(const SkImageInfo& info) {
SkImage* SkSurface_Gpu::onNewImageSnapshot(Budgeted budgeted) {
const SkImageInfo info = fDevice->imageInfo();
- const int sampleCount = fDevice->accessRenderTarget()->numSamples();
+ const int sampleCount = fDevice->accessRenderTarget()->numColorSamples();
SkImage* image = NULL;
GrTexture* tex = fDevice->accessRenderTarget()->asTexture();
if (tex) {