Add debug option to clip each GrBatch to its device bounds
Review URL: https://codereview.chromium.org/1471083002
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index fa9d189..303aecc 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -126,9 +126,10 @@
return pr;
}
-GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget)
+GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget, bool debugClipBatchToBounds)
: fDrawTarget(drawTarget)
- , fClipMode(kIgnoreClip_StencilClipMode) {
+ , fClipMode(kIgnoreClip_StencilClipMode)
+ , fDebugClipBatchToBounds(debugClipBatchToBounds) {
}
GrContext* GrClipMaskManager::getContext() {
@@ -272,6 +273,38 @@
return !failed;
}
+static void add_rect_to_clip(const GrClip& clip, const SkRect& devRect, GrClip* out) {
+ switch (clip.clipType()) {
+ case GrClip::kClipStack_ClipType: {
+ SkClipStack* stack = new SkClipStack;
+ *stack = *clip.clipStack();
+ // The stack is actually in clip space not device space.
+ SkRect clipRect = devRect;
+ SkPoint origin = { SkIntToScalar(clip.origin().fX), SkIntToScalar(clip.origin().fY) };
+ clipRect.offset(origin);
+ SkIRect iclipRect;
+ clipRect.roundOut(&iclipRect);
+ clipRect = SkRect::Make(iclipRect);
+ stack->clipDevRect(clipRect, SkRegion::kIntersect_Op, false);
+ out->setClipStack(stack, &clip.origin());
+ break;
+ }
+ case GrClip::kWideOpen_ClipType:
+ *out = GrClip(devRect);
+ break;
+ case GrClip::kIRect_ClipType: {
+ SkIRect intersect;
+ devRect.roundOut(&intersect);
+ if (intersect.intersect(clip.irect())) {
+ *out = GrClip(intersect);
+ } else {
+ *out = clip;
+ }
+ break;
+ }
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
// sort out what kind of clip mask needs to be created: alpha, stencil,
// scissor, or entirely software
@@ -294,7 +327,13 @@
SkASSERT(rt);
SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height());
- const GrClip& clip = pipelineBuilder.clip();
+ GrClip devBoundsClip;
+ bool doDevBoundsClip = fDebugClipBatchToBounds && devBounds;
+ if (doDevBoundsClip) {
+ add_rect_to_clip(pipelineBuilder.clip(), *devBounds, &devBoundsClip);
+ }
+ const GrClip& clip = doDevBoundsClip ? devBoundsClip : pipelineBuilder.clip();
+
if (clip.isWideOpen(clipSpaceRTIBounds)) {
this->setPipelineBuilderStencil(pipelineBuilder, ars);
return true;
diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h
index 98fd3af..6b9b727 100644
--- a/src/gpu/GrClipMaskManager.h
+++ b/src/gpu/GrClipMaskManager.h
@@ -55,7 +55,7 @@
*/
class GrClipMaskManager : SkNoncopyable {
public:
- GrClipMaskManager(GrDrawTarget* owner);
+ GrClipMaskManager(GrDrawTarget* owner, bool debugClipBatchToBounds);
/**
* Creates a clip mask if necessary as a stencil buffer or alpha texture
@@ -171,6 +171,7 @@
GrDrawTarget* fDrawTarget; // This is our owning draw target.
StencilClipMode fClipMode;
+ bool fDebugClipBatchToBounds;
typedef SkNoncopyable INHERITED;
};
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 920e3c4..ad89672 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -72,11 +72,11 @@
if (!fGpu) {
return false;
}
- this->initCommon();
+ this->initCommon(options);
return true;
}
-void GrContext::initCommon() {
+void GrContext::initCommon(const GrContextOptions& options) {
fCaps = SkRef(fGpu->caps());
fResourceCache = new GrResourceCache(fCaps);
fResourceCache->setOverBudgetCallback(OverBudgetCB, this);
@@ -86,7 +86,9 @@
fDidTestPMConversions = false;
- fDrawingManager.reset(new GrDrawingManager(this));
+ GrDrawTarget::Options dtOptions;
+ dtOptions.fClipBatchToBounds = options.fClipBatchToBounds;
+ fDrawingManager.reset(new GrDrawingManager(this, dtOptions));
// GrBatchFontCache will eventually replace GrFontCache
fBatchFontCache = new GrBatchFontCache(this);
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index f34e6fc..e41a1b7 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -32,7 +32,8 @@
////////////////////////////////////////////////////////////////////////////////
-GrDrawTarget::GrDrawTarget(GrRenderTarget* rt, GrGpu* gpu, GrResourceProvider* resourceProvider)
+GrDrawTarget::GrDrawTarget(GrRenderTarget* rt, GrGpu* gpu, GrResourceProvider* resourceProvider,
+ const Options& options)
: fGpu(SkRef(gpu))
, fResourceProvider(resourceProvider)
, fFlushing(false)
@@ -40,7 +41,7 @@
, fRenderTarget(rt) {
// TODO: Stop extracting the context (currently needed by GrClipMaskManager)
fContext = fGpu->getContext();
- fClipMaskManager.reset(new GrClipMaskManager(this));
+ fClipMaskManager.reset(new GrClipMaskManager(this, options.fClipBatchToBounds));
rt->setLastDrawTarget(this);
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 240731e..7b0159e 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -43,9 +43,13 @@
class GrDrawTarget final : public SkRefCnt {
public:
- // The context may not be fully constructed and should not be used during GrDrawTarget
- // construction.
- GrDrawTarget(GrRenderTarget* rt, GrGpu* gpu, GrResourceProvider*);
+ /** Options for GrDrawTarget behavior. */
+ struct Options {
+ Options () : fClipBatchToBounds(false) {}
+ bool fClipBatchToBounds;
+ };
+
+ GrDrawTarget(GrRenderTarget*, GrGpu*, GrResourceProvider*, const Options&);
~GrDrawTarget() override;
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index 73b7d16..13167d4 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -152,7 +152,8 @@
}
#endif
- GrDrawTarget* dt = new GrDrawTarget(rt, fContext->getGpu(), fContext->resourceProvider());
+ GrDrawTarget* dt = new GrDrawTarget(rt, fContext->getGpu(), fContext->resourceProvider(),
+ fOptionsForDrawTargets);
*fDrawTargets.append() = dt;
diff --git a/src/gpu/GrDrawingManager.h b/src/gpu/GrDrawingManager.h
index 41d8ab5..672f7b0 100644
--- a/src/gpu/GrDrawingManager.h
+++ b/src/gpu/GrDrawingManager.h
@@ -53,8 +53,9 @@
static bool ProgramUnitTest(GrContext* context, int maxStages);
private:
- GrDrawingManager(GrContext* context)
+ GrDrawingManager(GrContext* context, const GrDrawTarget::Options& optionsForDrawTargets)
: fContext(context)
+ , fOptionsForDrawTargets(optionsForDrawTargets)
, fAbandoned(false)
, fNVPRTextContext(nullptr)
, fPathRendererChain(nullptr)
@@ -74,6 +75,7 @@
static const int kNumDFTOptions = 2; // DFT or no DFT
GrContext* fContext;
+ GrDrawTarget::Options fOptionsForDrawTargets;
bool fAbandoned;
SkTDArray<GrDrawTarget*> fDrawTargets;
diff --git a/src/gpu/GrTest.cpp b/src/gpu/GrTest.cpp
index f0f6370..b0d92fe 100644
--- a/src/gpu/GrTest.cpp
+++ b/src/gpu/GrTest.cpp
@@ -318,7 +318,7 @@
SkASSERT(nullptr == fGpu);
fGpu = new MockGpu(this, options);
SkASSERT(fGpu);
- this->initCommon();
+ this->initCommon(options);
// We delete these because we want to test the cache starting with zero resources. Also, none of
// these objects are required for any of tests that use this context. TODO: make stop allocating