diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrClipStackClip.cpp | 68 | ||||
-rw-r--r-- | src/gpu/GrDrawContext.cpp | 58 | ||||
-rw-r--r-- | src/gpu/GrDrawContextPriv.h | 10 | ||||
-rw-r--r-- | src/gpu/GrDrawTarget.cpp | 10 | ||||
-rw-r--r-- | src/gpu/GrDrawTarget.h | 2 | ||||
-rw-r--r-- | src/gpu/GrFixedClip.cpp | 16 | ||||
-rw-r--r-- | src/gpu/GrFixedClip.h | 38 | ||||
-rw-r--r-- | src/gpu/GrGpuCommandBuffer.cpp | 21 | ||||
-rw-r--r-- | src/gpu/GrGpuCommandBuffer.h | 11 | ||||
-rw-r--r-- | src/gpu/GrPathRenderer.h | 2 | ||||
-rw-r--r-- | src/gpu/batches/GrClearBatch.h | 57 | ||||
-rw-r--r-- | src/gpu/batches/GrClearStencilClipBatch.h | 27 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 19 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.h | 4 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpuCommandBuffer.h | 10 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpuCommandBuffer.cpp | 38 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpuCommandBuffer.h | 4 |
17 files changed, 234 insertions, 161 deletions
diff --git a/src/gpu/GrClipStackClip.cpp b/src/gpu/GrClipStackClip.cpp index 8233786ba2..23c2b42a92 100644 --- a/src/gpu/GrClipStackClip.cpp +++ b/src/gpu/GrClipStackClip.cpp @@ -489,10 +489,12 @@ sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context, // The texture may be larger than necessary, this rect represents the part of the texture // we populate with a rasterization of the clip. SkIRect maskSpaceIBounds = SkIRect::MakeWH(reducedClip.width(), reducedClip.height()); + GrFixedClip clip(maskSpaceIBounds); // 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, InitialState::kAllIn == reducedClip.initialState() ? -1 : 0, true); + GrColor initialCoverage = InitialState::kAllIn == reducedClip.initialState() ? -1 : 0; + dc->drawContextPriv().clear(clip, initialCoverage, true); // Set the matrix so that rendered clip elements are transformed to mask space from clip // space. @@ -509,8 +511,6 @@ sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context, SkRegion::Op op = element->getOp(); bool invert = element->isInverseFilled(); if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) { - GrFixedClip clip(maskSpaceIBounds); - // draw directly into the result with the stencil set to make the pixels affected // by the clip shape be non-zero. static constexpr GrUserStencilSettings kStencilInElement( @@ -549,7 +549,7 @@ sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context, paint.setAntiAlias(element->isAA()); paint.setCoverageSetOpXPFactory(op, false); - draw_element(dc.get(), GrNoClip(), paint, translate, element); + draw_element(dc.get(), clip, paint, translate, element); } } @@ -560,8 +560,37 @@ sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context, } //////////////////////////////////////////////////////////////////////////////// -// Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device -// (as opposed to canvas) coordinates +// Create a 1-bit clip mask in the stencil buffer. + +class StencilClip final : public GrClip { +public: + StencilClip(const SkIRect& scissorRect) : fFixedClip(scissorRect) {} + const GrFixedClip& fixedClip() const { return fFixedClip; } + +private: + bool quickContains(const SkRect&) const final { + return false; + } + void getConservativeBounds(int width, int height, SkIRect* devResult, bool* iior) const final { + fFixedClip.getConservativeBounds(width, height, devResult, iior); + } + bool isRRect(const SkRect& rtBounds, SkRRect* rr, bool* aa) const final { + return false; + } + bool apply(GrContext* context, GrDrawContext* drawContext, bool useHWAA, + bool hasUserStencilSettings, GrAppliedClip* out) const final { + if (!fFixedClip.apply(context, drawContext, useHWAA, hasUserStencilSettings, out)) { + return false; + } + out->addStencilClip(); + return true; + } + + GrFixedClip fFixedClip; + + typedef GrClip INHERITED; +}; + bool GrClipStackClip::CreateStencilClipMask(GrContext* context, GrDrawContext* drawContext, const GrReducedClip& reducedClip, @@ -590,10 +619,10 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context, // We set the current clip to the bounds so that our recursive draws are scissored to them. SkIRect stencilSpaceIBounds(reducedClip.ibounds()); stencilSpaceIBounds.offset(clipSpaceToStencilOffset); - GrFixedClip clip(stencilSpaceIBounds); + StencilClip stencilClip(stencilSpaceIBounds); - bool insideClip = InitialState::kAllIn == reducedClip.initialState(); - drawContext->drawContextPriv().clearStencilClip(stencilSpaceIBounds, insideClip); + bool initialState = InitialState::kAllIn == reducedClip.initialState(); + drawContext->drawContextPriv().clearStencilClip(stencilClip.fixedClip(), initialState); // walk through each clip element and perform its set op // with the existing clip. @@ -602,8 +631,6 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context, bool useHWAA = element->isAA() && drawContext->isStencilBufferMultisampled(); bool fillInverted = false; - // enabled at bottom of loop - clip.disableStencilClip(); // This will be used to determine whether the clip shape can be rendered into the // stencil with arbitrary stencil settings. @@ -663,7 +690,8 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context, 0xffff>() ); if (Element::kRect_Type == element->getType()) { - drawContext->drawContextPriv().stencilRect(clip, &kDrawToStencil, useHWAA, + drawContext->drawContextPriv().stencilRect(stencilClip.fixedClip(), + &kDrawToStencil, useHWAA, viewMatrix, element->getRect()); } else { if (!clipPath.isEmpty()) { @@ -678,7 +706,7 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context, args.fPaint = &paint; args.fUserStencilSettings = &kDrawToStencil; args.fDrawContext = drawContext; - args.fClip = &clip; + args.fClip = &stencilClip.fixedClip(); args.fViewMatrix = &viewMatrix; args.fShape = &shape; args.fAntiAlias = false; @@ -688,7 +716,7 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context, GrPathRenderer::StencilPathArgs args; args.fResourceProvider = context->resourceProvider(); args.fDrawContext = drawContext; - args.fClip = &clip; + args.fClip = &stencilClip.fixedClip(); args.fViewMatrix = &viewMatrix; args.fIsAA = element->isAA(); args.fShape = &shape; @@ -698,16 +726,13 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context, } } - // Just enable stencil clip. The passes choose whether or not they will actually use it. - clip.enableStencilClip(); - // now we modify the clip bit by rendering either the clip // element directly or a bounding rect of the entire clip. for (GrUserStencilSettings const* const* pass = stencilPasses; *pass; ++pass) { if (drawDirectToClip) { if (Element::kRect_Type == element->getType()) { - drawContext->drawContextPriv().stencilRect(clip, *pass, useHWAA, viewMatrix, - element->getRect()); + drawContext->drawContextPriv().stencilRect(stencilClip, *pass, useHWAA, + viewMatrix, element->getRect()); } else { GrShape shape(clipPath, GrStyle::SimpleFill()); GrPaint paint; @@ -718,7 +743,7 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context, args.fPaint = &paint; args.fUserStencilSettings = *pass; args.fDrawContext = drawContext; - args.fClip = &clip; + args.fClip = &stencilClip; args.fViewMatrix = &viewMatrix; args.fShape = &shape; args.fAntiAlias = false; @@ -728,7 +753,8 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context, } else { // The view matrix is setup to do clip space -> stencil space translation, so // draw rect in clip space. - drawContext->drawContextPriv().stencilRect(clip, *pass, false, viewMatrix, + drawContext->drawContextPriv().stencilRect(stencilClip, *pass, + false, viewMatrix, SkRect::Make(reducedClip.ibounds())); } } diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp index 2bb9caa8b1..0ca07d11ef 100644 --- a/src/gpu/GrDrawContext.cpp +++ b/src/gpu/GrDrawContext.cpp @@ -196,45 +196,55 @@ void GrDrawContext::clear(const SkIRect* rect, GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::clear"); AutoCheckFlush acf(fDrawingManager); + this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color, canIgnoreRect); +} - const SkIRect rtRect = SkIRect::MakeWH(this->width(), this->height()); - SkIRect clippedRect; - bool isFull = false; - if (!rect || - (canIgnoreRect && fContext->caps()->fullClearIsFree()) || - rect->contains(rtRect)) { - rect = &rtRect; - isFull = true; - } else { - clippedRect = *rect; - if (!clippedRect.intersect(rtRect)) { - return; - } - rect = &clippedRect; - } +void GrDrawContextPriv::clear(const GrFixedClip& clip, + const GrColor color, + bool canIgnoreClip) { + ASSERT_SINGLE_OWNER_PRIV + RETURN_IF_ABANDONED_PRIV + SkDEBUGCODE(fDrawContext->validate();) + GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContextPriv::clear"); + + AutoCheckFlush acf(fDrawContext->fDrawingManager); + fDrawContext->internalClear(clip, color, canIgnoreClip); +} + +void GrDrawContext::internalClear(const GrFixedClip& clip, + const GrColor color, + bool canIgnoreClip) { + bool isFull = !clip.scissorEnabled() || + (canIgnoreClip && fContext->caps()->fullClearIsFree()) || + clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height())); if (fContext->caps()->useDrawInsteadOfClear()) { // This works around a driver bug with clear by drawing a rect instead. // The driver will ignore a clear if it is the only thing rendered to a // target before the target is read. - if (rect == &rtRect) { + SkRect clearRect = SkRect::MakeIWH(this->width(), this->height()); + if (isFull) { this->discard(); + } else if (!clearRect.intersect(SkRect::Make(clip.scissorRect()))) { + return; } GrPaint paint; paint.setColor4f(GrColor4f::FromGrColor(color)); paint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSrc_Mode)); - this->drawRect(GrNoClip(), paint, SkMatrix::I(), SkRect::Make(*rect)); + this->drawRect(clip, paint, SkMatrix::I(), clearRect); } else if (isFull) { this->getDrawTarget()->fullClear(this->accessRenderTarget(), color); } else { - sk_sp<GrBatch> batch(GrClearBatch::Make(*rect, color, this->accessRenderTarget())); + sk_sp<GrBatch> batch(GrClearBatch::Make(clip, color, this->accessRenderTarget())); + if (!batch) { + return; + } this->getDrawTarget()->addBatch(std::move(batch)); } } - void GrDrawContext::drawPaint(const GrClip& clip, const GrPaint& origPaint, const SkMatrix& viewMatrix) { @@ -543,14 +553,14 @@ void GrDrawContext::drawRect(const GrClip& clip, this->internalDrawPath(clip, paint, viewMatrix, path, *style); } -void GrDrawContextPriv::clearStencilClip(const SkIRect& rect, bool insideClip) { +void GrDrawContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) { ASSERT_SINGLE_OWNER_PRIV RETURN_IF_ABANDONED_PRIV SkDEBUGCODE(fDrawContext->validate();) GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContextPriv::clearStencilClip"); AutoCheckFlush acf(fDrawContext->fDrawingManager); - fDrawContext->getDrawTarget()->clearStencilClip(rect, insideClip, + fDrawContext->getDrawTarget()->clearStencilClip(clip, insideStencilMask, fDrawContext->accessRenderTarget()); } @@ -561,7 +571,7 @@ void GrDrawContextPriv::stencilPath(const GrClip& clip, fDrawContext->getDrawTarget()->stencilPath(fDrawContext, clip, useHWAA, viewMatrix, path); } -void GrDrawContextPriv::stencilRect(const GrFixedClip& clip, +void GrDrawContextPriv::stencilRect(const GrClip& clip, const GrUserStencilSettings* ss, bool useHWAA, const SkMatrix& viewMatrix, @@ -580,7 +590,7 @@ void GrDrawContextPriv::stencilRect(const GrFixedClip& clip, fDrawContext->drawNonAAFilledRect(clip, paint, viewMatrix, rect, nullptr, nullptr, ss, useHWAA); } -bool GrDrawContextPriv::drawAndStencilRect(const GrFixedClip& clip, +bool GrDrawContextPriv::drawAndStencilRect(const GrClip& clip, const GrUserStencilSettings* ss, SkRegion::Op op, bool invert, @@ -1232,7 +1242,7 @@ void GrDrawContext::drawPath(const GrClip& clip, this->internalDrawPath(clip, paint, viewMatrix, path, style); } -bool GrDrawContextPriv::drawAndStencilPath(const GrFixedClip& clip, +bool GrDrawContextPriv::drawAndStencilPath(const GrClip& clip, const GrUserStencilSettings* ss, SkRegion::Op op, bool invert, diff --git a/src/gpu/GrDrawContextPriv.h b/src/gpu/GrDrawContextPriv.h index 31d8481c73..63eae12a06 100644 --- a/src/gpu/GrDrawContextPriv.h +++ b/src/gpu/GrDrawContextPriv.h @@ -25,9 +25,11 @@ public: return fDrawContext->getDrawTarget()->instancedRendering(); } - void clearStencilClip(const SkIRect& rect, bool insideClip); + void clear(const GrFixedClip&, const GrColor, bool canIgnoreClip); - void stencilRect(const GrFixedClip& clip, + void clearStencilClip(const GrFixedClip&, bool insideStencilMask); + + void stencilRect(const GrClip& clip, const GrUserStencilSettings* ss, bool useHWAA, const SkMatrix& viewMatrix, @@ -38,7 +40,7 @@ public: const SkMatrix& viewMatrix, const GrPath*); - bool drawAndStencilRect(const GrFixedClip&, + bool drawAndStencilRect(const GrClip&, const GrUserStencilSettings*, SkRegion::Op op, bool invert, @@ -46,7 +48,7 @@ public: const SkMatrix& viewMatrix, const SkRect&); - bool drawAndStencilPath(const GrFixedClip&, + bool drawAndStencilPath(const GrClip&, const GrUserStencilSettings*, SkRegion::Op op, bool invert, diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp index 45ec9acb9c..f568f7e17f 100644 --- a/src/gpu/GrDrawTarget.cpp +++ b/src/gpu/GrDrawTarget.cpp @@ -459,9 +459,7 @@ void GrDrawTarget::fullClear(GrRenderTarget* renderTarget, GrColor color) { fLastFullClearBatch->setColor(color); return; } - sk_sp<GrClearBatch> batch(GrClearBatch::Make(SkIRect::MakeWH(renderTarget->width(), - renderTarget->height()), - color, renderTarget)); + sk_sp<GrClearBatch> batch(GrClearBatch::Make(GrFixedClip::Disabled(), color, renderTarget)); if (batch.get() == this->recordBatch(batch.get(), batch->bounds())) { fLastFullClearBatch = batch.get(); } @@ -619,8 +617,10 @@ void GrDrawTarget::forwardCombine() { /////////////////////////////////////////////////////////////////////////////// -void GrDrawTarget::clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* rt) { - GrBatch* batch = new GrClearStencilClipBatch(rect, insideClip, rt); +void GrDrawTarget::clearStencilClip(const GrFixedClip& clip, + bool insideStencilMask, + GrRenderTarget* rt) { + GrBatch* batch = new GrClearStencilClipBatch(clip, insideStencilMask, rt); this->recordBatch(batch, batch->bounds()); batch->unref(); } diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h index dfc1489d35..35de239150 100644 --- a/src/gpu/GrDrawTarget.h +++ b/src/gpu/GrDrawTarget.h @@ -215,7 +215,7 @@ private: void addDependency(GrDrawTarget* dependedOn); // Used only by drawContextPriv. - void clearStencilClip(const SkIRect&, bool insideClip, GrRenderTarget*); + void clearStencilClip(const GrFixedClip&, bool insideStencilMask, GrRenderTarget*); struct RecordedBatch { sk_sp<GrBatch> fBatch; diff --git a/src/gpu/GrFixedClip.cpp b/src/gpu/GrFixedClip.cpp index c42214b271..ebdd49bbf8 100644 --- a/src/gpu/GrFixedClip.cpp +++ b/src/gpu/GrFixedClip.cpp @@ -10,13 +10,6 @@ #include "GrAppliedClip.h" #include "GrDrawContext.h" -bool GrFixedClip::quickContains(const SkRect& rect) const { - if (fHasStencilClip) { - return false; - } - return !fScissorState.enabled() || GrClip::IsInsideClip(fScissorState.rect(), rect); -} - void GrFixedClip::getConservativeBounds(int width, int height, SkIRect* devResult, bool* isIntersectionOfRects) const { devResult->setXYWH(0, 0, width, height); @@ -46,9 +39,10 @@ bool GrFixedClip::apply(GrContext*, GrDrawContext* drawContext, bool isHWAntiAli } } - if (fHasStencilClip) { - out->addStencilClip(); - } - return true; } + +const GrFixedClip& GrFixedClip::Disabled() { + static const GrFixedClip disabled = GrFixedClip(); + return disabled; +} diff --git a/src/gpu/GrFixedClip.h b/src/gpu/GrFixedClip.h index 705b2eada9..8b3a9c1c9e 100644 --- a/src/gpu/GrFixedClip.h +++ b/src/gpu/GrFixedClip.h @@ -12,37 +12,30 @@ #include "GrTypesPriv.h" /** - * GrFixedClip is a clip that can be represented by fixed-function hardware. It never modifies the - * stencil buffer itself, but can be configured to use whatever clip is already there. + * GrFixedClip is a clip that gets implemented by fixed-function hardware. */ class GrFixedClip final : public GrClip { public: - GrFixedClip() : fHasStencilClip(false) {} - GrFixedClip(const SkIRect& scissorRect) - : fScissorState(scissorRect) - , fHasStencilClip(false) {} + GrFixedClip() = default; + explicit GrFixedClip(const SkIRect& scissorRect) : fScissorState(scissorRect) {} - void reset() { - fScissorState.setDisabled(); - fHasStencilClip = false; - } + const GrScissorState& scissorState() const { return fScissorState; } + bool scissorEnabled() const { return fScissorState.enabled(); } + const SkIRect& scissorRect() const { SkASSERT(scissorEnabled()); return fScissorState.rect(); } - void reset(const SkIRect& scissorRect) { - fScissorState.set(scissorRect); - fHasStencilClip = false; - } + void disableScissor() { fScissorState.setDisabled(); } - void enableStencilClip() { fHasStencilClip = true; } - void disableStencilClip() { fHasStencilClip = false; } + bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& irect) { + return fScissorState.intersect(irect); + } - bool quickContains(const SkRect&) const final; + bool quickContains(const SkRect& rect) const final { + return !fScissorState.enabled() || GrClip::IsInsideClip(fScissorState.rect(), rect); + } void getConservativeBounds(int width, int height, SkIRect* devResult, bool* isIntersectionOfRects) const final; bool isRRect(const SkRect& rtBounds, SkRRect* rr, bool* aa) const override { - if (fHasStencilClip) { - return false; - } if (fScissorState.enabled()) { SkRect rect = SkRect::Make(fScissorState.rect()); if (!rect.intersects(rtBounds)) { @@ -55,12 +48,13 @@ public: return false; }; -private: bool apply(GrContext*, GrDrawContext*, bool useHWAA, bool hasUserStencilSettings, GrAppliedClip* out) const final; + static const GrFixedClip& Disabled(); + +private: GrScissorState fScissorState; - bool fHasStencilClip; }; #endif diff --git a/src/gpu/GrGpuCommandBuffer.cpp b/src/gpu/GrGpuCommandBuffer.cpp index af0993e033..022c16696f 100644 --- a/src/gpu/GrGpuCommandBuffer.cpp +++ b/src/gpu/GrGpuCommandBuffer.cpp @@ -8,6 +8,7 @@ #include "GrGpuCommandBuffer.h" #include "GrCaps.h" +#include "GrFixedClip.h" #include "GrGpu.h" #include "GrPrimitiveProcessor.h" #include "GrRenderTarget.h" @@ -18,17 +19,19 @@ void GrGpuCommandBuffer::submit(const SkIRect& bounds) { this->onSubmit(bounds); } -void GrGpuCommandBuffer::clear(const SkIRect& rect, GrColor color, GrRenderTarget* renderTarget) { - SkASSERT(renderTarget); - SkASSERT(SkIRect::MakeWH(renderTarget->width(), renderTarget->height()).contains(rect)); - this->onClear(renderTarget, rect, color); +void GrGpuCommandBuffer::clear(const GrFixedClip& clip, GrColor color, GrRenderTarget* rt) { + SkASSERT(rt); + SkASSERT(!clip.scissorEnabled() || + (SkIRect::MakeWH(rt->width(), rt->height()).contains(clip.scissorRect()) && + SkIRect::MakeWH(rt->width(), rt->height()) != clip.scissorRect())); + this->onClear(rt, clip, color); } -void GrGpuCommandBuffer::clearStencilClip(const SkIRect& rect, - bool insideClip, - GrRenderTarget* renderTarget) { - SkASSERT(renderTarget); - this->onClearStencilClip(renderTarget, rect, insideClip); +void GrGpuCommandBuffer::clearStencilClip(const GrFixedClip& clip, + bool insideStencilMask, + GrRenderTarget* rt) { + SkASSERT(rt); + this->onClearStencilClip(rt, clip, insideStencilMask); } diff --git a/src/gpu/GrGpuCommandBuffer.h b/src/gpu/GrGpuCommandBuffer.h index 9abcc20fc7..2336dc5aaf 100644 --- a/src/gpu/GrGpuCommandBuffer.h +++ b/src/gpu/GrGpuCommandBuffer.h @@ -10,6 +10,7 @@ #include "GrColor.h" +class GrFixedClip; class GrGpu; class GrMesh; class GrPipeline; @@ -65,9 +66,9 @@ public: /** * Clear the passed in render target. Ignores the draw state and clip. */ - void clear(const SkIRect& rect, GrColor color, GrRenderTarget* renderTarget); + void clear(const GrFixedClip&, GrColor, GrRenderTarget*); - void clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* renderTarget); + void clearStencilClip(const GrFixedClip&, bool insideStencilMask, GrRenderTarget*); /** * Discards the contents render target. nullptr indicates that the current render target should * be discarded. @@ -86,9 +87,11 @@ private: int meshCount) = 0; // overridden by backend-specific derived class to perform the clear. - virtual void onClear(GrRenderTarget*, const SkIRect& rect, GrColor color) = 0; + virtual void onClear(GrRenderTarget*, const GrFixedClip&, GrColor) = 0; - virtual void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) = 0; + virtual void onClearStencilClip(GrRenderTarget*, + const GrFixedClip&, + bool insideStencilMask) = 0; }; diff --git a/src/gpu/GrPathRenderer.h b/src/gpu/GrPathRenderer.h index 52ecc59075..37cc3f9863 100644 --- a/src/gpu/GrPathRenderer.h +++ b/src/gpu/GrPathRenderer.h @@ -185,7 +185,7 @@ public: struct StencilPathArgs { GrResourceProvider* fResourceProvider; GrDrawContext* fDrawContext; - const GrFixedClip* fClip; + const GrClip* fClip; const SkMatrix* fViewMatrix; bool fIsAA; const GrShape* fShape; diff --git a/src/gpu/batches/GrClearBatch.h b/src/gpu/batches/GrClearBatch.h index 8ebf85af2e..7d84bc3859 100644 --- a/src/gpu/batches/GrClearBatch.h +++ b/src/gpu/batches/GrClearBatch.h @@ -10,6 +10,7 @@ #include "GrBatch.h" #include "GrBatchFlushState.h" +#include "GrFixedClip.h" #include "GrGpu.h" #include "GrGpuCommandBuffer.h" #include "GrRenderTarget.h" @@ -18,8 +19,12 @@ class GrClearBatch final : public GrBatch { public: DEFINE_BATCH_CLASS_ID - static sk_sp<GrClearBatch> Make(const SkIRect& rect, GrColor color, GrRenderTarget* rt) { - return sk_sp<GrClearBatch>(new GrClearBatch(rect, color, rt)); + static sk_sp<GrClearBatch> Make(const GrFixedClip& clip, GrColor color, GrRenderTarget* rt) { + sk_sp<GrClearBatch> batch(new GrClearBatch(clip, color, rt)); + if (!batch->renderTarget()) { + return nullptr; // The clip did not contain any pixels within the render target. + } + return batch; } const char* name() const override { return "Clear"; } @@ -28,10 +33,12 @@ public: GrRenderTarget* renderTarget() const override { return fRenderTarget.get(); } SkString dumpInfo() const override { - SkString string; - string.printf("Color: 0x%08x, Rect [L: %d, T: %d, R: %d, B: %d], RT: %d", - fColor, fRect.fLeft, fRect.fTop, fRect.fRight, fRect.fBottom, - fRenderTarget.get()->getUniqueID()); + SkString string("Scissor ["); + if (fClip.scissorEnabled()) { + const SkIRect& r = fClip.scissorRect(); + string.appendf("L: %d, T: %d, R: %d, B: %d", r.fLeft, r.fTop, r.fRight, r.fBottom); + } + string.appendf("], Color: 0x%08x, RT: %d", fColor, fRenderTarget.get()->getUniqueID()); string.append(INHERITED::dumpInfo()); return string; } @@ -39,12 +46,23 @@ public: void setColor(GrColor color) { fColor = color; } private: - GrClearBatch(const SkIRect& rect, GrColor color, GrRenderTarget* rt) + GrClearBatch(const GrFixedClip& clip, GrColor color, GrRenderTarget* rt) : INHERITED(ClassID()) - , fRect(rect) - , fColor(color) - , fRenderTarget(rt) { - this->setBounds(SkRect::Make(rect), HasAABloat::kNo, IsZeroArea::kNo); + , fClip(clip) + , fColor(color) { + SkIRect rtRect = SkIRect::MakeWH(rt->width(), rt->height()); + if (fClip.scissorEnabled()) { + // Don't let scissors extend outside the RT. This may improve batching. + if (!fClip.intersect(rtRect)) { + return; + } + if (fClip.scissorRect() == rtRect) { + fClip.disableScissor(); + } + } + this->setBounds(SkRect::Make(fClip.scissorEnabled() ? fClip.scissorRect() : rtRect), + HasAABloat::kNo, IsZeroArea::kNo); + fRenderTarget.reset(rt); } bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { @@ -53,24 +71,31 @@ private: // same color. GrClearBatch* cb = t->cast<GrClearBatch>(); SkASSERT(cb->fRenderTarget == fRenderTarget); - if (cb->fRect.contains(fRect)) { - fRect = cb->fRect; + if (cb->contains(this)) { + fClip = cb->fClip; this->replaceBounds(*t); fColor = cb->fColor; return true; - } else if (cb->fColor == fColor && fRect.contains(cb->fRect)) { + } else if (cb->fColor == fColor && this->contains(cb)) { return true; } return false; } + bool contains(const GrClearBatch* that) const { + // The constructor ensures that scissor gets disabled on any clip that fills the entire RT. + return !fClip.scissorEnabled() || + (that->fClip.scissorEnabled() && + fClip.scissorRect().contains(that->fClip.scissorRect())); + } + void onPrepare(GrBatchFlushState*) override {} void onDraw(GrBatchFlushState* state) override { - state->commandBuffer()->clear(fRect, fColor, fRenderTarget.get()); + state->commandBuffer()->clear(fClip, fColor, fRenderTarget.get()); } - SkIRect fRect; + GrFixedClip fClip; GrColor fColor; GrPendingIOResource<GrRenderTarget, kWrite_GrIOType> fRenderTarget; diff --git a/src/gpu/batches/GrClearStencilClipBatch.h b/src/gpu/batches/GrClearStencilClipBatch.h index aa4d4afff0..d13d3dcff4 100644 --- a/src/gpu/batches/GrClearStencilClipBatch.h +++ b/src/gpu/batches/GrClearStencilClipBatch.h @@ -10,6 +10,7 @@ #include "GrBatch.h" #include "GrBatchFlushState.h" +#include "GrFixedClip.h" #include "GrGpu.h" #include "GrGpuCommandBuffer.h" #include "GrRenderTarget.h" @@ -18,12 +19,14 @@ class GrClearStencilClipBatch final : public GrBatch { public: DEFINE_BATCH_CLASS_ID - GrClearStencilClipBatch(const SkIRect& rect, bool insideClip, GrRenderTarget* rt) + GrClearStencilClipBatch(const GrFixedClip& clip, bool insideStencilMask, GrRenderTarget* rt) : INHERITED(ClassID()) - , fRect(rect) - , fInsideClip(insideClip) + , fClip(clip) + , fInsideStencilMask(insideStencilMask) , fRenderTarget(rt) { - this->setBounds(SkRect::Make(rect), HasAABloat::kNo, IsZeroArea::kNo); + const SkRect& bounds = fClip.scissorEnabled() ? SkRect::Make(fClip.scissorRect()) + : SkRect::MakeIWH(rt->width(), rt->height()); + this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo); } const char* name() const override { return "ClearStencilClip"; } @@ -32,10 +35,12 @@ public: GrRenderTarget* renderTarget() const override { return fRenderTarget.get(); } SkString dumpInfo() const override { - SkString string; - string.printf("Rect [L: %d, T: %d, R: %d, B: %d], IC: %d, RT: %d", - fRect.fLeft, fRect.fTop, fRect.fRight, fRect.fBottom, fInsideClip, - fRenderTarget.get()->getUniqueID()); + SkString string("Scissor ["); + if (fClip.scissorEnabled()) { + const SkIRect& r = fClip.scissorRect(); + string.appendf("L: %d, T: %d, R: %d, B: %d", r.fLeft, r.fTop, r.fRight, r.fBottom); + } + string.appendf("], IC: %d, RT: %d", fInsideStencilMask, fRenderTarget.get()->getUniqueID()); string.append(INHERITED::dumpInfo()); return string; } @@ -46,11 +51,11 @@ private: void onPrepare(GrBatchFlushState*) override {} void onDraw(GrBatchFlushState* state) override { - state->commandBuffer()->clearStencilClip(fRect, fInsideClip, fRenderTarget.get()); + state->commandBuffer()->clearStencilClip(fClip, fInsideStencilMask, fRenderTarget.get()); } - SkIRect fRect; - bool fInsideClip; + const GrFixedClip fClip; + const bool fInsideStencilMask; GrPendingIOResource<GrRenderTarget, kWrite_GrIOType> fRenderTarget; typedef GrBatch INHERITED; diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 1370bf992b..a141767e89 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -11,6 +11,7 @@ #include "GrGLGpuCommandBuffer.h" #include "GrGLStencilAttachment.h" #include "GrGLTextureRenderTarget.h" +#include "GrFixedClip.h" #include "GrGpuResourcePriv.h" #include "GrMesh.h" #include "GrPipeline.h" @@ -2197,17 +2198,15 @@ void GrGLGpu::disableScissor() { } } -void GrGLGpu::clear(const SkIRect& rect, GrColor color, GrRenderTarget* target) { +void GrGLGpu::clear(const GrFixedClip& clip, GrColor color, GrRenderTarget* target) { this->handleDirtyContext(); // parent class should never let us get here with no RT SkASSERT(target); GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target); - this->flushRenderTarget(glRT, &rect); - GrScissorState scissorState; - scissorState.set(rect); - this->flushScissor(scissorState, glRT->getViewport(), glRT->origin()); + this->flushRenderTarget(glRT, clip.scissorEnabled() ? &clip.scissorRect() : nullptr); + this->flushScissor(clip.scissorState(), glRT->getViewport(), glRT->origin()); this->disableWindowRectangles(); GrGLfloat r, g, b, a; @@ -2240,7 +2239,9 @@ void GrGLGpu::clearStencil(GrRenderTarget* target) { fHWStencilSettings.invalidate(); } -void GrGLGpu::clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* target) { +void GrGLGpu::clearStencilClip(const GrFixedClip& clip, + bool insideStencilMask, + GrRenderTarget* target) { SkASSERT(target); this->handleDirtyContext(); @@ -2261,7 +2262,7 @@ void GrGLGpu::clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTar static const GrGLint clipStencilMask = ~0; #endif GrGLint value; - if (insideClip) { + if (insideStencilMask) { value = (1 << (stencilBitCount - 1)); } else { value = 0; @@ -2269,9 +2270,7 @@ void GrGLGpu::clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTar GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target); this->flushRenderTarget(glRT, &SkIRect::EmptyIRect()); - GrScissorState scissorState; - scissorState.set(rect); - this->flushScissor(scissorState, glRT->getViewport(), glRT->origin()); + this->flushScissor(clip.scissorState(), glRT->getViewport(), glRT->origin()); this->disableWindowRectangles(); GL_CALL(StencilMask((uint32_t) clipStencilMask)); diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index 448c29243f..3fe4204807 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -105,12 +105,12 @@ public: // The GrGLGpuCommandBuffer does not buffer up draws before submitting them to the gpu. // Thus this is the implementation of the clear call for the corresponding passthrough function // on GrGLGpuCommandBuffer. - void clear(const SkIRect& rect, GrColor color, GrRenderTarget* renderTarget); + void clear(const GrFixedClip&, GrColor, GrRenderTarget*); // The GrGLGpuCommandBuffer does not buffer up draws before submitting them to the gpu. // Thus this is the implementation of the clearStencil call for the corresponding passthrough // function on GrGLGpuCommandBuffer. - void clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* renderTarget); + void clearStencilClip(const GrFixedClip&, bool insideStencilMask, GrRenderTarget*); const GrGLContext* glContextForTesting() const override { return &this->glContext(); diff --git a/src/gpu/gl/GrGLGpuCommandBuffer.h b/src/gpu/gl/GrGLGpuCommandBuffer.h index c5f0eea4ff..4ad2b13ada 100644 --- a/src/gpu/gl/GrGLGpuCommandBuffer.h +++ b/src/gpu/gl/GrGLGpuCommandBuffer.h @@ -39,12 +39,14 @@ private: fGpu->draw(pipeline, primProc, mesh, meshCount); } - void onClear(GrRenderTarget* rt, const SkIRect& rect, GrColor color) override { - fGpu->clear(rect, color, rt); + void onClear(GrRenderTarget* rt, const GrFixedClip& clip, GrColor color) override { + fGpu->clear(clip, color, rt); } - void onClearStencilClip(GrRenderTarget* rt, const SkIRect& rect, bool insideClip) override { - fGpu->clearStencilClip(rect, insideClip, rt); + void onClearStencilClip(GrRenderTarget* rt, + const GrFixedClip& clip, + bool insideStencilMask) override { + fGpu->clearStencilClip(clip, insideStencilMask, rt); } GrGLGpu* fGpu; diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.cpp b/src/gpu/vk/GrVkGpuCommandBuffer.cpp index f49b180e38..d7a030d241 100644 --- a/src/gpu/vk/GrVkGpuCommandBuffer.cpp +++ b/src/gpu/vk/GrVkGpuCommandBuffer.cpp @@ -7,6 +7,7 @@ #include "GrVkGpuCommandBuffer.h" +#include "GrFixedClip.h" #include "GrMesh.h" #include "GrPipeline.h" #include "GrRenderTargetPriv.h" @@ -166,8 +167,8 @@ void GrVkGpuCommandBuffer::discard(GrRenderTarget* target) { } void GrVkGpuCommandBuffer::onClearStencilClip(GrRenderTarget* target, - const SkIRect& rect, - bool insideClip) { + const GrFixedClip& clip, + bool insideStencilMask) { SkASSERT(target); GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target); @@ -182,7 +183,7 @@ void GrVkGpuCommandBuffer::onClearStencilClip(GrRenderTarget* target, VkClearDepthStencilValue vkStencilColor; memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue)); - if (insideClip) { + if (insideStencilMask) { vkStencilColor.stencil = (1 << (stencilBitCount - 1)); } else { vkStencilColor.stencil = 0; @@ -190,11 +191,15 @@ void GrVkGpuCommandBuffer::onClearStencilClip(GrRenderTarget* target, VkClearRect clearRect; // Flip rect if necessary - SkIRect vkRect = rect; - - if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) { - vkRect.fTop = vkRT->height() - rect.fBottom; - vkRect.fBottom = vkRT->height() - rect.fTop; + SkIRect vkRect; + if (!clip.scissorEnabled()) { + vkRect.setXYWH(0, 0, vkRT->width(), vkRT->height()); + } else if (kBottomLeft_GrSurfaceOrigin != vkRT->origin()) { + vkRect = clip.scissorRect(); + } else { + const SkIRect& scissor = clip.scissorRect(); + vkRect.setLTRB(scissor.fLeft, vkRT->height() - scissor.fBottom, + scissor.fRight, vkRT->height() - scissor.fTop); } clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop }; @@ -215,7 +220,7 @@ void GrVkGpuCommandBuffer::onClearStencilClip(GrRenderTarget* target, fIsEmpty = false; } -void GrVkGpuCommandBuffer::onClear(GrRenderTarget* target, const SkIRect& rect, GrColor color) { +void GrVkGpuCommandBuffer::onClear(GrRenderTarget* target, const GrFixedClip& clip, GrColor color) { // parent class should never let us get here with no RT SkASSERT(target); @@ -224,7 +229,7 @@ void GrVkGpuCommandBuffer::onClear(GrRenderTarget* target, const SkIRect& rect, GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target); - if (fIsEmpty && rect.width() == target->width() && rect.height() == target->height()) { + if (fIsEmpty && !clip.scissorEnabled()) { // We will change the render pass to do a clear load instead GrVkRenderPass::LoadStoreOps vkColorOps(VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE); @@ -259,10 +264,15 @@ void GrVkGpuCommandBuffer::onClear(GrRenderTarget* target, const SkIRect& rect, // We always do a sub rect clear with clearAttachments since we are inside a render pass VkClearRect clearRect; // Flip rect if necessary - SkIRect vkRect = rect; - if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) { - vkRect.fTop = vkRT->height() - rect.fBottom; - vkRect.fBottom = vkRT->height() - rect.fTop; + SkIRect vkRect; + if (!clip.scissorEnabled()) { + vkRect.setXYWH(0, 0, vkRT->width(), vkRT->height()); + } else if (kBottomLeft_GrSurfaceOrigin != vkRT->origin()) { + vkRect = clip.scissorRect(); + } else { + const SkIRect& scissor = clip.scissorRect(); + vkRect.setLTRB(scissor.fLeft, vkRT->height() - scissor.fBottom, + scissor.fRight, vkRT->height() - scissor.fTop); } clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop }; clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() }; diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.h b/src/gpu/vk/GrVkGpuCommandBuffer.h index 8459e8e328..506d020371 100644 --- a/src/gpu/vk/GrVkGpuCommandBuffer.h +++ b/src/gpu/vk/GrVkGpuCommandBuffer.h @@ -52,9 +52,9 @@ private: const GrMesh* mesh, int meshCount) override; - void onClear(GrRenderTarget* rt, const SkIRect& rect, GrColor color) override; + void onClear(GrRenderTarget* rt, const GrFixedClip&, GrColor color) override; - void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) override; + void onClearStencilClip(GrRenderTarget*, const GrFixedClip&, bool insideStencilMask) override; const GrVkRenderPass* fRenderPass; GrVkSecondaryCommandBuffer* fCommandBuffer; |