diff options
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/GrClipMaskManager.cpp | 351 | ||||
-rw-r--r-- | src/gpu/GrClipMaskManager.h | 48 | ||||
-rw-r--r-- | src/gpu/GrDrawContext.cpp | 172 | ||||
-rw-r--r-- | src/gpu/GrDrawContextPriv.h | 60 | ||||
-rw-r--r-- | src/gpu/GrDrawTarget.cpp | 18 | ||||
-rw-r--r-- | src/gpu/GrDrawTarget.h | 2 | ||||
-rw-r--r-- | src/gpu/GrPipelineBuilder.h | 8 | ||||
-rw-r--r-- | src/gpu/GrTest.cpp | 16 |
8 files changed, 242 insertions, 433 deletions
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp index 70c65ed705..3168424cf8 100644 --- a/src/gpu/GrClipMaskManager.cpp +++ b/src/gpu/GrClipMaskManager.cpp @@ -8,7 +8,7 @@ #include "GrClipMaskManager.h" #include "GrCaps.h" #include "GrDrawingManager.h" -#include "GrDrawContextPriv.h" +#include "GrDrawContext.h" #include "GrDrawTarget.h" #include "GrGpuResourcePriv.h" #include "GrPaint.h" @@ -159,8 +159,7 @@ GrResourceProvider* GrClipMaskManager::resourceProvider() { * will be used on any element. If so, it returns true to indicate that the * entire clip should be rendered in SW and then uploaded en masse to the gpu. */ -bool GrClipMaskManager::UseSWOnlyPath(GrContext* context, - const GrPipelineBuilder& pipelineBuilder, +bool GrClipMaskManager::useSWOnlyPath(const GrPipelineBuilder& pipelineBuilder, const GrRenderTarget* rt, const SkVector& clipToMaskOffset, const GrReducedClip::ElementList& elements) { @@ -180,7 +179,7 @@ bool GrClipMaskManager::UseSWOnlyPath(GrContext* context, bool needsStencil = invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op; - if (PathNeedsSWRenderer(context, pipelineBuilder.getStencil().isDisabled(), + if (PathNeedsSWRenderer(this->getContext(), pipelineBuilder.getStencil().isDisabled(), rt, translate, element, nullptr, needsStencil)) { return true; } @@ -317,42 +316,6 @@ static void add_rect_to_clip(const GrClip& clip, const SkRect& devRect, GrClip* } } -bool GrClipMaskManager::setupScissorClip(const GrPipelineBuilder& pipelineBuilder, - GrPipelineBuilder::AutoRestoreStencil* ars, - const SkIRect& clipScissor, - const SkRect* devBounds, - GrAppliedClip* out) { - if (kRespectClip_StencilClipMode == fClipMode) { - fClipMode = kIgnoreClip_StencilClipMode; - } - - GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); - - SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); - SkIRect devBoundsScissor; - const SkIRect* scissor = &clipScissor; - bool doDevBoundsClip = fDebugClipBatchToBounds && devBounds; - if (doDevBoundsClip) { - devBounds->roundOut(&devBoundsScissor); - if (devBoundsScissor.intersect(clipScissor)) { - scissor = &devBoundsScissor; - } - } - - if (scissor->contains(clipSpaceRTIBounds)) { - // This counts as wide open - this->setPipelineBuilderStencil(pipelineBuilder, ars); - return true; - } - - if (clipSpaceRTIBounds.intersect(*scissor)) { - out->fScissorState.set(clipSpaceRTIBounds); - this->setPipelineBuilderStencil(pipelineBuilder, ars); - return true; - } - return false; -} - //////////////////////////////////////////////////////////////////////////////// // sort out what kind of clip mask needs to be created: alpha, stencil, // scissor, or entirely software @@ -476,23 +439,21 @@ bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder, SkIntToScalar(-clipSpaceIBounds.fTop) }; - if (UseSWOnlyPath(this->getContext(), pipelineBuilder, rt, clipToMaskOffset, elements)) { + if (this->useSWOnlyPath(pipelineBuilder, rt, clipToMaskOffset, elements)) { // The clip geometry is complex enough that it will be more efficient to create it // entirely in software - result.reset(CreateSoftwareClipMask(this->getContext(), - genID, - initialState, - elements, - clipToMaskOffset, - clipSpaceIBounds)); + result.reset(this->createSoftwareClipMask(genID, + initialState, + elements, + clipToMaskOffset, + clipSpaceIBounds)); } else { - result.reset(CreateAlphaClipMask(this->getContext(), - genID, - initialState, - elements, - clipToMaskOffset, - clipSpaceIBounds)); - // If createAlphaClipMask fails it means UseSWOnlyPath has a bug + result.reset(this->createAlphaClipMask(genID, + initialState, + elements, + clipToMaskOffset, + clipSpaceIBounds)); + // If createAlphaClipMask fails it means useSWOnlyPath has a bug SkASSERT(result); } @@ -527,67 +488,93 @@ bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder, return true; } -static bool stencil_element(GrDrawContext* dc, - const SkIRect* scissorRect, - const GrStencilSettings& ss, - const SkMatrix& viewMatrix, - const SkClipStack::Element* element) { - - // TODO: Draw rrects directly here. - switch (element->getType()) { - case Element::kEmpty_Type: - SkDEBUGFAIL("Should never get here with an empty element."); - break; - case Element::kRect_Type: - return dc->drawContextPriv().drawAndStencilRect(scissorRect, ss, - element->getOp(), - element->isInverseFilled(), - element->isAA(), - viewMatrix, element->getRect()); - break; - default: { - SkPath path; - element->asPath(&path); - if (path.isInverseFillType()) { - path.toggleInverseFillType(); - } +namespace { +//////////////////////////////////////////////////////////////////////////////// +// Set a coverage drawing XPF on the pipelineBuilder for the given op and invertCoverage mode +void set_coverage_drawing_xpf(SkRegion::Op op, bool invertCoverage, + GrPipelineBuilder* pipelineBuilder) { + SkASSERT(op <= SkRegion::kLastOp); + pipelineBuilder->setCoverageSetOpXPFactory(op, invertCoverage); +} +} - return dc->drawContextPriv().drawAndStencilPath(scissorRect, ss, - element->getOp(), - element->isInverseFilled(), - element->isAA(), viewMatrix, path); - break; - } - } +//////////////////////////////////////////////////////////////////////////////// +bool GrClipMaskManager::drawElement(GrPipelineBuilder* pipelineBuilder, + const SkMatrix& viewMatrix, + GrTexture* target, + const SkClipStack::Element* element, + GrPathRenderer* pr) { - return false; -} + GrRenderTarget* rt = target->asRenderTarget(); + pipelineBuilder->setRenderTarget(rt); -static void draw_element(GrDrawContext* dc, - const GrClip& clip, // TODO: can this just always be WideOpen? - const GrPaint &paint, - const SkMatrix& viewMatrix, - const SkClipStack::Element* element) { + // The color we use to draw does not matter since we will always be using a GrCoverageSetOpXP + // which ignores color. + GrColor color = GrColor_WHITE; // TODO: Draw rrects directly here. switch (element->getType()) { case Element::kEmpty_Type: SkDEBUGFAIL("Should never get here with an empty element."); break; - case Element::kRect_Type: - dc->drawRect(clip, paint, viewMatrix, element->getRect()); - break; + case Element::kRect_Type: { + // TODO: Do rects directly to the accumulator using a aa-rect GrProcessor that covers + // the entire mask bounds and writes 0 outside the rect. + if (element->isAA()) { + SkRect devRect = element->getRect(); + viewMatrix.mapRect(&devRect); + + SkAutoTUnref<GrDrawBatch> batch( + GrRectBatchFactory::CreateAAFill(color, viewMatrix, element->getRect(), + devRect)); + + fDrawTarget->drawBatch(*pipelineBuilder, batch); + } else { + draw_non_aa_rect(fDrawTarget, *pipelineBuilder, color, viewMatrix, + element->getRect()); + } + return true; + } default: { SkPath path; element->asPath(&path); if (path.isInverseFillType()) { path.toggleInverseFillType(); } + GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle); + if (nullptr == pr) { + GrPathRendererChain::DrawType type; + type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawType : + GrPathRendererChain::kColor_DrawType; - dc->drawPath(clip, paint, viewMatrix, path, GrStrokeInfo::FillInfo()); + GrPathRenderer::CanDrawPathArgs canDrawArgs; + canDrawArgs.fShaderCaps = this->getContext()->caps()->shaderCaps(); + canDrawArgs.fViewMatrix = &viewMatrix; + canDrawArgs.fPath = &path; + canDrawArgs.fStroke = &stroke; + canDrawArgs.fAntiAlias = element->isAA();; + canDrawArgs.fIsStencilDisabled = pipelineBuilder->getStencil().isDisabled(); + canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampled(); + + pr = this->getContext()->drawingManager()->getPathRenderer(canDrawArgs, false, type); + } + if (nullptr == pr) { + return false; + } + GrPathRenderer::DrawPathArgs args; + args.fTarget = fDrawTarget; + args.fResourceProvider = this->getContext()->resourceProvider(); + args.fPipelineBuilder = pipelineBuilder; + args.fColor = color; + args.fViewMatrix = &viewMatrix; + args.fPath = &path; + args.fStroke = &stroke; + args.fAntiAlias = element->isAA(); + pr->drawPath(args); break; } } + return true; } //////////////////////////////////////////////////////////////////////////////// @@ -601,13 +588,32 @@ static void GetClipMaskKey(int32_t clipGenID, const SkIRect& bounds, GrUniqueKey builder[2] = SkToU16(bounds.fTop) | (SkToU16(bounds.fBottom) << 16); } -GrTexture* GrClipMaskManager::CreateAlphaClipMask(GrContext* context, - int32_t elementsGenID, +GrTexture* GrClipMaskManager::createCachedMask(int width, int height, const GrUniqueKey& key, + bool renderTarget) { + GrSurfaceDesc desc; + desc.fWidth = width; + desc.fHeight = height; + desc.fFlags = renderTarget ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags; + if (!renderTarget || this->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { + desc.fConfig = kAlpha_8_GrPixelConfig; + } else { + desc.fConfig = kRGBA_8888_GrPixelConfig; + } + + GrTexture* texture = this->resourceProvider()->createApproxTexture(desc, 0); + if (!texture) { + return nullptr; + } + texture->resourcePriv().setUniqueKey(key); + return texture; +} + +GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID, GrReducedClip::InitialState initialState, const GrReducedClip::ElementList& elements, const SkVector& clipToMaskOffset, const SkIRect& clipSpaceIBounds) { - GrResourceProvider* resourceProvider = context->resourceProvider(); + GrResourceProvider* resourceProvider = this->resourceProvider(); GrUniqueKey key; GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key); if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)) { @@ -615,27 +621,15 @@ GrTexture* GrClipMaskManager::CreateAlphaClipMask(GrContext* context, } // There's no texture in the cache. Let's try to allocate it then. - GrSurfaceDesc desc; - desc.fWidth = clipSpaceIBounds.width(); - desc.fHeight = clipSpaceIBounds.height(); - desc.fFlags = kRenderTarget_GrSurfaceFlag; - if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { - desc.fConfig = kAlpha_8_GrPixelConfig; - } else { - desc.fConfig = kRGBA_8888_GrPixelConfig; - } - - SkAutoTUnref<GrTexture> texture(resourceProvider->createApproxTexture(desc, 0)); + SkAutoTUnref<GrTexture> texture(this->createCachedMask( + clipSpaceIBounds.width(), clipSpaceIBounds.height(), key, true)); if (!texture) { return nullptr; } - texture->resourcePriv().setUniqueKey(key); - - SkAutoTUnref<GrDrawContext> dc(context->drawContext(texture->asRenderTarget())); - if (!dc) { - return nullptr; - } + // Set the matrix so that rendered clip elements are transformed to mask space from clip + // space. + const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMaskOffset.fY); // The texture may be larger than necessary, this rect represents the part of the texture // we populate with a rasterization of the clip. @@ -643,18 +637,16 @@ GrTexture* GrClipMaskManager::CreateAlphaClipMask(GrContext* context, // The scratch texture that we are drawing into can be substantially larger than the mask. Only // clear the part that we care about. - dc->clear(&maskSpaceIBounds, - GrReducedClip::kAllIn_InitialState == initialState ? 0xffffffff : 0x00000000, - true); + fDrawTarget->clear(&maskSpaceIBounds, + GrReducedClip::kAllIn_InitialState == initialState ? 0xffffffff : 0x00000000, + true, + texture->asRenderTarget()); - // Set the matrix so that rendered clip elements are transformed to mask space from clip - // space. - const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMaskOffset.fY); - - // It is important that we use maskSpaceIBounds as the stencil rect in the below loop. + // When we use the stencil in the below loop it is important to have this clip installed. // The second pass that zeros the stencil buffer renders the rect maskSpaceIBounds so the first // pass must not set values outside of this bounds or stencil values outside the rect won't be // cleared. + const GrClip clip(maskSpaceIBounds); // walk through each clip element and perform its set op for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get(); iter.next()) { @@ -662,54 +654,68 @@ GrTexture* GrClipMaskManager::CreateAlphaClipMask(GrContext* context, SkRegion::Op op = element->getOp(); bool invert = element->isInverseFilled(); if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) { -#ifdef SK_DEBUG - GrPathRenderer* pr = GetPathRenderer(context, + + GrPathRenderer* pr = GetPathRenderer(this->getContext(), texture, translate, element); if (Element::kRect_Type != element->getType() && !pr) { - // UseSWOnlyPath should now filter out all cases where gpu-side mask merging would - // be performed (i.e., pr would be NULL for a non-rect path). - // See https://bug.skia.org/4519 for rationale and details. + // useSWOnlyPath should now filter out all cases where gpu-side mask merging would + // be performed (i.e., pr would be NULL for a non-rect path). See https://bug.skia.org/4519 + // for rationale and details. SkASSERT(0); + continue; } -#endif - - // draw directly into the result with the stencil set to make the pixels affected - // by the clip shape be non-zero. - GR_STATIC_CONST_SAME_STENCIL(kStencilInElement, - kReplace_StencilOp, - kReplace_StencilOp, - kAlways_StencilFunc, - 0xffff, - 0xffff, - 0xffff) - if (!stencil_element(dc, &maskSpaceIBounds, kStencilInElement, - translate, element)) { - texture->resourcePriv().removeUniqueKey(); - return nullptr; + + { + GrPipelineBuilder pipelineBuilder; + + pipelineBuilder.setClip(clip); + pipelineBuilder.setRenderTarget(texture->asRenderTarget()); + SkASSERT(pipelineBuilder.getStencil().isDisabled()); + + // draw directly into the result with the stencil set to make the pixels affected + // by the clip shape be non-zero. + GR_STATIC_CONST_SAME_STENCIL(kStencilInElement, + kReplace_StencilOp, + kReplace_StencilOp, + kAlways_StencilFunc, + 0xffff, + 0xffff, + 0xffff); + pipelineBuilder.setStencil(kStencilInElement); + set_coverage_drawing_xpf(op, invert, &pipelineBuilder); + + if (!this->drawElement(&pipelineBuilder, translate, texture, element, pr)) { + texture->resourcePriv().removeUniqueKey(); + return nullptr; + } } - // Draw to the exterior pixels (those with a zero stencil value). - GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, - kZero_StencilOp, - kZero_StencilOp, - kEqual_StencilFunc, - 0xffff, - 0x0000, - 0xffff); - if (!dc->drawContextPriv().drawAndStencilRect(&maskSpaceIBounds, kDrawOutsideElement, - op, !invert, false, - translate, - SkRect::Make(clipSpaceIBounds))) { - texture->resourcePriv().removeUniqueKey(); - return nullptr; + { + GrPipelineBuilder backgroundPipelineBuilder; + backgroundPipelineBuilder.setRenderTarget(texture->asRenderTarget()); + + set_coverage_drawing_xpf(op, !invert, &backgroundPipelineBuilder); + // Draw to the exterior pixels (those with a zero stencil value). + GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, + kZero_StencilOp, + kZero_StencilOp, + kEqual_StencilFunc, + 0xffff, + 0x0000, + 0xffff); + backgroundPipelineBuilder.setStencil(kDrawOutsideElement); + + // The color passed in here does not matter since the coverageSetOpXP won't read it. + draw_non_aa_rect(fDrawTarget, backgroundPipelineBuilder, GrColor_WHITE, translate, + SkRect::Make(clipSpaceIBounds)); } } else { - // all the remaining ops can just be directly draw into the accumulation buffer - GrPaint paint; - paint.setAntiAlias(element->isAA()); - paint.setCoverageSetOpXPFactory(op, false); + GrPipelineBuilder pipelineBuilder; - draw_element(dc, GrClip::WideOpen(), paint, translate, element); + // all the remaining ops can just be directly draw into the accumulation buffer + set_coverage_drawing_xpf(op, false, &pipelineBuilder); + // The color passed in here does not matter since the coverageSetOpXP won't read it. + this->drawElement(&pipelineBuilder, translate, texture, element); } } @@ -1075,15 +1081,14 @@ void GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings, } //////////////////////////////////////////////////////////////////////////////// -GrTexture* GrClipMaskManager::CreateSoftwareClipMask(GrContext* context, - int32_t elementsGenID, +GrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t elementsGenID, GrReducedClip::InitialState initialState, const GrReducedClip::ElementList& elements, const SkVector& clipToMaskOffset, const SkIRect& clipSpaceIBounds) { GrUniqueKey key; GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key); - GrResourceProvider* resourceProvider = context->resourceProvider(); + GrResourceProvider* resourceProvider = this->resourceProvider(); if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)) { return texture; } @@ -1092,7 +1097,7 @@ GrTexture* GrClipMaskManager::CreateSoftwareClipMask(GrContext* context, // the top left corner of the resulting rect to the top left of the texture. SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height()); - GrSWMaskHelper helper(context); + GrSWMaskHelper helper(this->getContext()); // Set the matrix so that rendered clip elements are transformed to mask space from clip // space. @@ -1136,17 +1141,11 @@ GrTexture* GrClipMaskManager::CreateSoftwareClipMask(GrContext* context, } // Allocate clip mask texture - GrSurfaceDesc desc; - desc.fWidth = clipSpaceIBounds.width(); - desc.fHeight = clipSpaceIBounds.height(); - desc.fConfig = kAlpha_8_GrPixelConfig; - - GrTexture* result = context->resourceProvider()->createApproxTexture(desc, 0); - if (!result) { + GrTexture* result = this->createCachedMask(clipSpaceIBounds.width(), clipSpaceIBounds.height(), + key, false); + if (nullptr == result) { return nullptr; } - result->resourcePriv().setUniqueKey(key); - helper.toTexture(result); return result; diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h index 36354545d5..6b9b727161 100644 --- a/src/gpu/GrClipMaskManager.h +++ b/src/gpu/GrClipMaskManager.h @@ -69,12 +69,6 @@ public: const SkRect* devBounds, GrAppliedClip*); - bool setupScissorClip(const GrPipelineBuilder& pipelineBuilder, - GrPipelineBuilder::AutoRestoreStencil* ars, - const SkIRect& scissor, - const SkRect* devBounds, - GrAppliedClip* out); - void adjustPathStencilParams(const GrStencilAttachment*, GrStencilSettings*); private: @@ -129,26 +123,32 @@ private: // Creates an alpha mask of the clip. The mask is a rasterization of elements through the // rect specified by clipSpaceIBounds. - static GrTexture* CreateAlphaClipMask(GrContext*, - int32_t elementsGenID, - GrReducedClip::InitialState initialState, - const GrReducedClip::ElementList& elements, - const SkVector& clipToMaskOffset, - const SkIRect& clipSpaceIBounds); + GrTexture* createAlphaClipMask(int32_t elementsGenID, + GrReducedClip::InitialState initialState, + const GrReducedClip::ElementList& elements, + const SkVector& clipToMaskOffset, + const SkIRect& clipSpaceIBounds); // Similar to createAlphaClipMask but it rasterizes in SW and uploads to the result texture. - static GrTexture* CreateSoftwareClipMask(GrContext*, - int32_t elementsGenID, - GrReducedClip::InitialState initialState, - const GrReducedClip::ElementList& elements, - const SkVector& clipToMaskOffset, - const SkIRect& clipSpaceIBounds); - - static bool UseSWOnlyPath(GrContext*, - const GrPipelineBuilder&, - const GrRenderTarget* rt, - const SkVector& clipToMaskOffset, - const GrReducedClip::ElementList& elements); + GrTexture* createSoftwareClipMask(int32_t elementsGenID, + GrReducedClip::InitialState initialState, + const GrReducedClip::ElementList& elements, + const SkVector& clipToMaskOffset, + const SkIRect& clipSpaceIBounds); + + bool useSWOnlyPath(const GrPipelineBuilder&, + const GrRenderTarget* rt, + const SkVector& clipToMaskOffset, + const GrReducedClip::ElementList& elements); + + // Draws a clip element into the target alpha mask. The caller should have already setup the + // desired blend operation. Optionally if the caller already selected a path renderer it can + // be passed. Otherwise the function will select one if the element is a path. + bool drawElement(GrPipelineBuilder*, + const SkMatrix& viewMatrix, + GrTexture* target, + const SkClipStack::Element*, + GrPathRenderer* pr = nullptr); /** * Called prior to return control back the GrGpu in setupClipping. It updates the diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp index 43ef760d82..628b4b2fb2 100644 --- a/src/gpu/GrDrawContext.cpp +++ b/src/gpu/GrDrawContext.cpp @@ -9,7 +9,6 @@ #include "GrBatchTest.h" #include "GrColor.h" #include "GrDrawContext.h" -#include "GrDrawContextPriv.h" #include "GrDrawingManager.h" #include "GrOvalRenderer.h" #include "GrPathRenderer.h" @@ -34,11 +33,8 @@ #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingManager->getContext()) #define ASSERT_SINGLE_OWNER \ SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);) -#define ASSERT_SINGLE_OWNER_PRIV \ - SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fDrawContext->fSingleOwner);) #define RETURN_IF_ABANDONED if (fDrawingManager->abandoned()) { return; } #define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->abandoned()) { return false; } -#define RETURN_FALSE_IF_ABANDONED_PRIV if (fDrawContext->fDrawingManager->abandoned()) { return false; } #define RETURN_NULL_IF_ABANDONED if (fDrawingManager->abandoned()) { return nullptr; } class AutoCheckFlush { @@ -254,28 +250,6 @@ static bool should_apply_coverage_aa(const GrPaint& paint, GrRenderTarget* rt) { return paint.isAntiAlias() && !rt->isUnifiedMultisampled(); } -GrDrawBatch* GrDrawContext::getFillRectBatch(const GrPaint& paint, - const SkMatrix& viewMatrix, - const SkRect& rect) { - - GrDrawBatch* batch = nullptr; - if (should_apply_coverage_aa(paint, fRenderTarget)) { - // The fill path can handle rotation but not skew. - if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) { - SkRect devBoundRect; - viewMatrix.mapRect(&devBoundRect, rect); - batch = GrRectBatchFactory::CreateAAFill(paint.getColor(), viewMatrix, - rect, devBoundRect); - } - } else { - // filled BW rect - batch = GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rect, - nullptr, nullptr); - } - - return batch; -} - void GrDrawContext::drawRect(const GrClip& clip, const GrPaint& paint, const SkMatrix& viewMatrix, @@ -329,28 +303,35 @@ void GrDrawContext::drawRect(const GrClip& clip, bool snapToPixelCenters = false; SkAutoTUnref<GrDrawBatch> batch; - if (width < 0) { - batch.reset(this->getFillRectBatch(paint, viewMatrix, rect)); - } else { - GrColor color = paint.getColor(); - - if (should_apply_coverage_aa(paint, fRenderTarget)) { + if (should_apply_coverage_aa(paint, fRenderTarget)) { + if (width >= 0) { // The stroke path needs the rect to remain axis aligned (no rotation or skew). if (viewMatrix.rectStaysRect()) { - batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix, rect, + batch.reset(GrRectBatchFactory::CreateAAStroke(paint.getColor(), viewMatrix, rect, *strokeInfo)); } } else { - // Non-AA hairlines are snapped to pixel centers to make which pixels are hit - // deterministic - snapToPixelCenters = (0 == width && !fRenderTarget->isUnifiedMultisampled()); - batch.reset(GrRectBatchFactory::CreateNonAAStroke(color, viewMatrix, rect, - width, snapToPixelCenters)); - - // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of - // hairline rects. We jam all the vertices to pixel centers to avoid this, but not - // when MSAA is enabled because it can cause ugly artifacts. + // The fill path can handle rotation but not skew. + if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) { + SkRect devBoundRect; + viewMatrix.mapRect(&devBoundRect, rect); + batch.reset(GrRectBatchFactory::CreateAAFill(paint.getColor(), viewMatrix, rect, + devBoundRect)); + } } + } else if (width >= 0) { + // Non-AA hairlines are snapped to pixel centers to make which pixels are hit deterministic + snapToPixelCenters = (0 == width && !fRenderTarget->isUnifiedMultisampled()); + batch.reset(GrRectBatchFactory::CreateNonAAStroke(paint.getColor(), viewMatrix, rect, + width, snapToPixelCenters)); + + // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of + // hairline rects. We jam all the vertices to pixel centers to avoid this, but not when + // MSAA is enabled because it can cause ugly artifacts. + } else { + // filled BW rect + batch.reset(GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rect, + nullptr, nullptr)); } if (batch) { @@ -372,39 +353,6 @@ void GrDrawContext::drawRect(const GrClip& clip, strokeInfo ? *strokeInfo : GrStrokeInfo::FillInfo()); } -bool GrDrawContextPriv::drawAndStencilRect(const SkIRect* scissorRect, - const GrStencilSettings& ss, - SkRegion::Op op, - bool invert, - bool doAA, - const SkMatrix& viewMatrix, - const SkRect& rect) { - ASSERT_SINGLE_OWNER_PRIV - RETURN_FALSE_IF_ABANDONED_PRIV - SkDEBUGCODE(fDrawContext->validate();) - GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::stencilRect"); - - AutoCheckFlush acf(fDrawContext->fDrawingManager); - - GrPaint paint; - paint.setAntiAlias(doAA); - paint.setCoverageSetOpXPFactory(op, invert); - - SkAutoTUnref<GrDrawBatch> batch(fDrawContext->getFillRectBatch(paint, viewMatrix, rect)); - if (batch) { - GrPipelineBuilder pipelineBuilder(paint, fDrawContext->fRenderTarget, GrClip::WideOpen()); - pipelineBuilder.setStencil(ss); - - fDrawContext->getDrawTarget()->drawBatch(pipelineBuilder, batch, scissorRect); - return true; - } - - SkPath path; - path.setIsVolatile(true); - path.addRect(rect); - return this->drawAndStencilPath(scissorRect, ss, op, invert, doAA, viewMatrix, path); -} - void GrDrawContext::fillRectToRect(const GrClip& clip, const GrPaint& paint, const SkMatrix& viewMatrix, @@ -853,80 +801,6 @@ void GrDrawContext::drawPath(const GrClip& clip, this->internalDrawPath(clip, paint, viewMatrix, path, strokeInfo); } -bool GrDrawContextPriv::drawAndStencilPath(const SkIRect* scissorRect, - const GrStencilSettings& ss, - SkRegion::Op op, - bool invert, - bool doAA, - const SkMatrix& viewMatrix, - const SkPath& path) { - ASSERT_SINGLE_OWNER_PRIV - RETURN_FALSE_IF_ABANDONED_PRIV - SkDEBUGCODE(fDrawContext->validate();) - GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPath"); - - if (path.isEmpty() && path.isInverseFillType()) { - this->drawAndStencilRect(scissorRect, ss, op, invert, false, SkMatrix::I(), - SkRect::MakeIWH(fDrawContext->fRenderTarget->width(), - fDrawContext->fRenderTarget->height())); - return true; - } - - AutoCheckFlush acf(fDrawContext->fDrawingManager); - - // An Assumption here is that path renderer would use some form of tweaking - // the src color (either the input alpha or in the frag shader) to implement - // 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 = doAA && !fDrawContext->fRenderTarget->isUnifiedMultisampled(); - bool isStencilDisabled = true; - bool isStencilBufferMSAA = fDrawContext->fRenderTarget->isStencilBufferMultisampled(); - - const GrPathRendererChain::DrawType type = - useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType - : GrPathRendererChain::kColor_DrawType; - - GrPathRenderer::CanDrawPathArgs canDrawArgs; - canDrawArgs.fShaderCaps = fDrawContext->fDrawingManager->getContext()->caps()->shaderCaps(); - canDrawArgs.fViewMatrix = &viewMatrix; - canDrawArgs.fPath = &path; - canDrawArgs.fStroke = &GrStrokeInfo::FillInfo(); - canDrawArgs.fAntiAlias = useCoverageAA; - canDrawArgs.fIsStencilDisabled = isStencilDisabled; - canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA; - - // Don't allow the SW renderer - GrPathRenderer* pr = fDrawContext->fDrawingManager->getPathRenderer(canDrawArgs, false, type); - if (!pr) { - return false; - } - - GrPaint paint; - paint.setCoverageSetOpXPFactory(op, invert); - - // TODO: it is unfortunate that we have to convert this to a GrClip to - // call drawPath. - GrClip clip; - if (scissorRect) { - clip.setIRect(*scissorRect); - } - - GrPipelineBuilder pipelineBuilder(paint, fDrawContext->fRenderTarget, clip); - pipelineBuilder.setStencil(ss); - - GrPathRenderer::DrawPathArgs args; - args.fTarget = fDrawContext->getDrawTarget(); - args.fResourceProvider = fDrawContext->fDrawingManager->getContext()->resourceProvider(); - args.fPipelineBuilder = &pipelineBuilder; - args.fColor = GrColor_WHITE; - args.fViewMatrix = &viewMatrix; - args.fPath = &path; - args.fStroke = &GrStrokeInfo::FillInfo(); - args.fAntiAlias = useCoverageAA; - pr->drawPath(args); - return true; -} - void GrDrawContext::internalDrawPath(const GrClip& clip, const GrPaint& paint, const SkMatrix& viewMatrix, diff --git a/src/gpu/GrDrawContextPriv.h b/src/gpu/GrDrawContextPriv.h deleted file mode 100644 index 935b631a26..0000000000 --- a/src/gpu/GrDrawContextPriv.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef GrDrawContextPriv_DEFINED -#define GrDrawContextPriv_DEFINED - -#include "GrDrawContext.h" - -class GrStencilSettings; - -/** Class that adds methods to GrDrawContext that are only intended for use internal to Skia. - This class is purely a privileged window into GrDrawContext. It should never have additional - data members or virtual methods. */ -class GrDrawContextPriv { -public: - bool drawAndStencilRect(const SkIRect* scissorRect, - const GrStencilSettings&, - SkRegion::Op op, - bool invert, - bool doAA, - const SkMatrix& viewMatrix, - const SkRect&); - - bool drawAndStencilPath(const SkIRect* scissorRect, - const GrStencilSettings&, - SkRegion::Op op, - bool invert, - bool doAA, - const SkMatrix& viewMatrix, - const SkPath&); - - void testingOnly_drawBatch(const GrPipelineBuilder& pipelineBuilder, - GrDrawBatch* batch); - -private: - explicit GrDrawContextPriv(GrDrawContext* drawContext) : fDrawContext(drawContext) {} - GrDrawContextPriv(const GrRenderTargetPriv&) {} // unimpl - GrDrawContextPriv& operator=(const GrRenderTargetPriv&); // unimpl - - // No taking addresses of this type. - const GrDrawContextPriv* operator&() const; - GrDrawContextPriv* operator&(); - - GrDrawContext* fDrawContext; - - friend class GrDrawContext; // to construct/copy this type. -}; - -inline GrDrawContextPriv GrDrawContext::drawContextPriv() { return GrDrawContextPriv(this); } - -inline const GrDrawContextPriv GrDrawContext::drawContextPriv () const { - return GrDrawContextPriv(const_cast<GrDrawContext*>(this)); -} - -#endif - diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp index fc8c71b443..173617ebe6 100644 --- a/src/gpu/GrDrawTarget.cpp +++ b/src/gpu/GrDrawTarget.cpp @@ -221,25 +221,13 @@ void GrDrawTarget::reset() { fBatches.reset(); } -void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder, - GrDrawBatch* batch, - const SkIRect* scissorRect) { +void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder, GrDrawBatch* batch) { // Setup clip GrPipelineBuilder::AutoRestoreStencil ars; GrAppliedClip clip; - - if (scissorRect) { - SkASSERT(GrClip::kWideOpen_ClipType == pipelineBuilder.clip().clipType()); - if (!fClipMaskManager->setupScissorClip(pipelineBuilder, &ars, *scissorRect, - &batch->bounds(), &clip)) { - return; - } - } else { - if (!fClipMaskManager->setupClipping(pipelineBuilder, &ars, &batch->bounds(), &clip)) { - return; - } + if (!fClipMaskManager->setupClipping(pipelineBuilder, &ars, &batch->bounds(), &clip)) { + return; } - GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps; if (clip.clipCoverageFragmentProcessor()) { arfps.set(&pipelineBuilder); diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h index 8b30ab9b60..a850efd842 100644 --- a/src/gpu/GrDrawTarget.h +++ b/src/gpu/GrDrawTarget.h @@ -101,7 +101,7 @@ public: */ const GrCaps* caps() const { return fGpu->caps(); } - void drawBatch(const GrPipelineBuilder&, GrDrawBatch*, const SkIRect* scissorRect = nullptr); + void drawBatch(const GrPipelineBuilder&, GrDrawBatch*); /** * Draws path into the stencil buffer. The fill must be either even/odd or diff --git a/src/gpu/GrPipelineBuilder.h b/src/gpu/GrPipelineBuilder.h index f66ced3025..f5fe9f80dc 100644 --- a/src/gpu/GrPipelineBuilder.h +++ b/src/gpu/GrPipelineBuilder.h @@ -155,6 +155,14 @@ public: } /** + * Sets a GrXPFactory that will ignore src color and perform a set operation between the draws + * output coverage and the destination. This is useful to render coverage masks as CSG. + */ + void setCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage = false) { + fXPFactory.reset(GrCoverageSetOpXPFactory::Create(regionOp, invertCoverage)); + } + + /** * Sets a GrXPFactory that disables color writes to the destination. This is useful when * rendering to the stencil buffer. */ diff --git a/src/gpu/GrTest.cpp b/src/gpu/GrTest.cpp index 56037d11f5..9a37f2b82f 100644 --- a/src/gpu/GrTest.cpp +++ b/src/gpu/GrTest.cpp @@ -9,7 +9,7 @@ #include "GrBatchAtlas.h" #include "GrContextOptions.h" -#include "GrDrawContextPriv.h" +#include "GrDrawContext.h" #include "GrDrawingManager.h" #include "GrGpuResourceCacheAccess.h" #include "GrResourceCache.h" @@ -258,17 +258,17 @@ void GrResourceCache::changeTimestamp(uint32_t newTimestamp) { fTimestamp = newT /////////////////////////////////////////////////////////////////////////////// #define ASSERT_SINGLE_OWNER \ - SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fDrawContext->fSingleOwner);) -#define RETURN_IF_ABANDONED if (fDrawContext->fDrawingManager->abandoned()) { return; } + SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);) +#define RETURN_IF_ABANDONED if (fDrawingManager->abandoned()) { return; } -void GrDrawContextPriv::testingOnly_drawBatch(const GrPipelineBuilder& pipelineBuilder, - GrDrawBatch* batch) { +void GrDrawContext::internal_drawBatch(const GrPipelineBuilder& pipelineBuilder, + GrDrawBatch* batch) { ASSERT_SINGLE_OWNER RETURN_IF_ABANDONED - SkDEBUGCODE(fDrawContext->validate();) - GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::testingOnly_drawBatch"); + SkDEBUGCODE(this->validate();) + GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::internal_drawBatch"); - fDrawContext->getDrawTarget()->drawBatch(pipelineBuilder, batch); + this->getDrawTarget()->drawBatch(pipelineBuilder, batch); } #undef ASSERT_SINGLE_OWNER |