Add debug option to clip each GrBatch to its device bounds
Review URL: https://codereview.chromium.org/1471083002
This commit is contained in:
parent
d1c94a4158
commit
69cfe95b7b
@ -57,6 +57,7 @@ public:
|
||||
|
||||
struct GrContextOptions {
|
||||
bool fImmediateMode;
|
||||
bool fClipBatchToBounds;
|
||||
};
|
||||
|
||||
class GrContextFactory {
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user