aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrClipStackClip.cpp68
-rw-r--r--src/gpu/GrDrawContext.cpp58
-rw-r--r--src/gpu/GrDrawContextPriv.h10
-rw-r--r--src/gpu/GrDrawTarget.cpp10
-rw-r--r--src/gpu/GrDrawTarget.h2
-rw-r--r--src/gpu/GrFixedClip.cpp16
-rw-r--r--src/gpu/GrFixedClip.h38
-rw-r--r--src/gpu/GrGpuCommandBuffer.cpp21
-rw-r--r--src/gpu/GrGpuCommandBuffer.h11
-rw-r--r--src/gpu/GrPathRenderer.h2
-rw-r--r--src/gpu/batches/GrClearBatch.h57
-rw-r--r--src/gpu/batches/GrClearStencilClipBatch.h27
-rw-r--r--src/gpu/gl/GrGLGpu.cpp19
-rw-r--r--src/gpu/gl/GrGLGpu.h4
-rw-r--r--src/gpu/gl/GrGLGpuCommandBuffer.h10
-rw-r--r--src/gpu/vk/GrVkGpuCommandBuffer.cpp38
-rw-r--r--src/gpu/vk/GrVkGpuCommandBuffer.h4
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;