diff options
author | 2015-06-12 08:59:45 -0700 | |
---|---|---|
committer | 2015-06-12 08:59:45 -0700 | |
commit | dded69693dd3779f081326cde24c3954505b129d (patch) | |
tree | 0cfc3a16d31093185082268ab16599edb7c0464f /src | |
parent | 57856a1f589bea64ed84535efed0668221060f9b (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.cpp | 4 | ||||
-rw-r--r-- | src/gpu/GrBlurUtils.cpp | 2 | ||||
-rw-r--r-- | src/gpu/GrClipMaskManager.cpp | 6 | ||||
-rwxr-xr-x | src/gpu/GrContext.cpp | 3 | ||||
-rw-r--r-- | src/gpu/GrDrawContext.cpp | 11 | ||||
-rw-r--r-- | src/gpu/GrGpu.cpp | 3 | ||||
-rw-r--r-- | src/gpu/GrOvalRenderer.cpp | 6 | ||||
-rw-r--r-- | src/gpu/GrPipelineBuilder.cpp | 2 | ||||
-rw-r--r-- | src/gpu/GrPipelineBuilder.h | 2 | ||||
-rw-r--r-- | src/gpu/GrStencilAndCoverPathRenderer.cpp | 20 | ||||
-rw-r--r-- | src/gpu/GrStencilAndCoverTextContext.cpp | 2 | ||||
-rw-r--r-- | src/gpu/GrTexture.cpp | 2 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 12 | ||||
-rw-r--r-- | src/gpu/effects/GrDashingEffect.cpp | 2 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 13 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.h | 16 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 16 | ||||
-rw-r--r-- | src/gpu/gl/GrGLRenderTarget.cpp | 4 | ||||
-rw-r--r-- | src/gpu/gl/GrGLRenderTarget.h | 11 | ||||
-rw-r--r-- | src/image/SkSurface_Gpu.cpp | 4 |
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) { |