Add debug option to clip each GrBatch to its device bounds

Review URL: https://codereview.chromium.org/1471083002
This commit is contained in:
bsalomon 2015-11-30 13:27:47 -08:00 committed by Commit bot
parent d1c94a4158
commit 69cfe95b7b
12 changed files with 77 additions and 17 deletions

View File

@ -57,6 +57,7 @@ public:
struct GrContextOptions {
bool fImmediateMode;
bool fClipBatchToBounds;
};
class GrContextFactory {

View File

@ -806,12 +806,16 @@ int GPUSink::enclave() const {
void PreAbandonGpuContextErrorHandler(SkError, void*) {}
DEFINE_bool(imm, false, "Run gpu configs in immediate mode.");
DEFINE_bool(batchClip, false, "Clip each GrBatch to its device bounds for testing.");
Error GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log) const {
GrContextOptions options;
if (FLAGS_imm) {
options.fImmediateMode = true;
}
if (FLAGS_batchClip) {
options.fClipBatchToBounds = true;
}
src.modifyGrContextOptions(&options);
GrContextFactory factory(options);

View File

@ -406,7 +406,7 @@ private:
bool init(GrBackend, GrBackendContext, const GrContextOptions& options);
void initMockContext();
void initCommon();
void initCommon(const GrContextOptions&);
/**
* These functions create premul <-> unpremul effects if it is possible to generate a pair

View File

@ -20,6 +20,7 @@ struct GrContextOptions {
, fGeometryBufferMapThreshold(-1)
, fUseDrawInsteadOfPartialRenderTargetWrite(false)
, fImmediateMode(false)
, fClipBatchToBounds(false)
, fUseShaderSwizzling(false) {}
// EXPERIMENTAL
@ -48,10 +49,14 @@ struct GrContextOptions {
/** some gpus have problems with partial writes of the rendertarget */
bool fUseDrawInsteadOfPartialRenderTargetWrite;
/** The GrContext operates in immedidate mode. It will issue all draws to the backend API
/** The GrContext operates in immediate mode. It will issue all draws to the backend API
immediately. Intended to ease debugging. */
bool fImmediateMode;
/** For debugging purposes turn each GrBatch's bounds into a clip rect. This is used to
verify that the clip bounds are conservative. */
bool fClipBatchToBounds;
/** Force us to do all swizzling manually in the shader and don't rely on extensions to do
swizzling. */
bool fUseShaderSwizzling;

View File

@ -126,9 +126,10 @@ GrPathRenderer* GrClipMaskManager::GetPathRenderer(GrContext* context,
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 @@ bool GrClipMaskManager::getAnalyticClipProcessor(const GrReducedClip::ElementLis
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 @@ bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder,
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;

View File

@ -55,7 +55,7 @@ private:
*/
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 @@ private:
GrDrawTarget* fDrawTarget; // This is our owning draw target.
StencilClipMode fClipMode;
bool fDebugClipBatchToBounds;
typedef SkNoncopyable INHERITED;
};

View File

@ -72,11 +72,11 @@ bool GrContext::init(GrBackend backend, GrBackendContext backendContext,
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 @@ void GrContext::initCommon() {
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);

View File

@ -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 @@ GrDrawTarget::GrDrawTarget(GrRenderTarget* rt, GrGpu* gpu, GrResourceProvider* r
, 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);

View File

@ -43,9 +43,13 @@ class GrPathRangeDraw;
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;

View File

@ -152,7 +152,8 @@ GrDrawTarget* GrDrawingManager::newDrawTarget(GrRenderTarget* rt) {
}
#endif
GrDrawTarget* dt = new GrDrawTarget(rt, fContext->getGpu(), fContext->resourceProvider());
GrDrawTarget* dt = new GrDrawTarget(rt, fContext->getGpu(), fContext->resourceProvider(),
fOptionsForDrawTargets);
*fDrawTargets.append() = dt;

View File

@ -53,8 +53,9 @@ public:
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 @@ private:
static const int kNumDFTOptions = 2; // DFT or no DFT
GrContext* fContext;
GrDrawTarget::Options fOptionsForDrawTargets;
bool fAbandoned;
SkTDArray<GrDrawTarget*> fDrawTargets;

View File

@ -318,7 +318,7 @@ void GrContext::initMockContext() {
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