SkIRect::MakeWH(w, h), {x, y});
}
private:
- bool apply(GrContext*, GrRenderTargetContext*, bool, bool, GrAppliedClip* out) const override {
+ bool apply(GrContext*, GrRenderTargetContext*, bool, bool, GrAppliedClip* out,
+ SkRect* bounds) const override {
out->addCoverageFP(fFP);
return true;
}
*/
class StencilOnlyClip final : public MaskOnlyClipBase {
private:
- bool apply(GrContext*, GrRenderTargetContext*, bool, bool, GrAppliedClip* out) const override {
+ bool apply(GrContext*, GrRenderTargetContext*, bool, bool, GrAppliedClip* out,
+ SkRect* bounds) const override {
out->addStencilClip();
return true;
}
*/
class GrAppliedClip : public SkNoncopyable {
public:
- GrAppliedClip(const SkRect& drawBounds)
- : fHasStencilClip(false)
- , fClippedDrawBounds(drawBounds) {
- }
-
const GrScissorState& scissorState() const { return fScissorState; }
const GrWindowRectsState& windowRectsState() const { return fWindowRectsState; }
GrFragmentProcessor* clipCoverageFragmentProcessor() const { return fClipCoverageFP.get(); }
/**
* Intersects the applied clip with the provided rect. Returns false if the draw became empty.
+ * 'clippedDrawBounds' will be intersected with 'irect'. This returns false if the clip becomes
+ * empty or the draw no longer intersects the clip. In either case the draw can be skipped.
*/
- bool addScissor(const SkIRect& irect) {
- return fScissorState.intersect(irect) && fClippedDrawBounds.intersect(SkRect::Make(irect));
+ bool addScissor(const SkIRect& irect, SkRect* clippedDrawBounds) {
+ return fScissorState.intersect(irect) && clippedDrawBounds->intersect(SkRect::Make(irect));
}
void addWindowRectangles(const GrWindowRectsState& windowState) {
fHasStencilClip = true;
}
- /**
- * Returns the device bounds of the draw after clip has been applied. TODO: Ideally this would
- * consider the combined effect of all clipping techniques in play (scissor, stencil, fp, etc.).
- */
- const SkRect& clippedDrawBounds() const { return fClippedDrawBounds; }
-
private:
GrScissorState fScissorState;
GrWindowRectsState fWindowRectsState;
sk_sp<GrFragmentProcessor> fClipCoverageFP;
- bool fHasStencilClip;
- SkRect fClippedDrawBounds;
+ bool fHasStencilClip = false;
typedef SkNoncopyable INHERITED;
};
}
virtual void getConservativeBounds(int width, int height, SkIRect* devResult,
bool* isIntersectionOfRects = nullptr) const = 0;
+ /**
+ * This computes a GrAppliedClip from the clip which in turn can be used to build a GrPipeline.
+ * To determine the appropriate clipping implementation the GrClip subclass must know whether
+ * the draw will enable HW AA or uses the stencil buffer. On input 'bounds' is a conservative
+ * bounds of the draw that is to be clipped. After return 'bounds' has been intersected with a
+ * conservative bounds of the clip. A return value of false indicates that the draw can be
+ * skipped as it is fully clipped out.
+ */
virtual bool apply(GrContext*, GrRenderTargetContext*, bool useHWAA,
- bool hasUserStencilSettings, GrAppliedClip* out) const = 0;
+ bool hasUserStencilSettings, GrAppliedClip* result,
+ SkRect* bounds) const = 0;
virtual ~GrClip() {}
*isIntersectionOfRects = true;
}
}
- bool apply(GrContext*, GrRenderTargetContext*, bool, bool, GrAppliedClip*) const final {
+ bool apply(GrContext*, GrRenderTargetContext*, bool, bool, GrAppliedClip*,
+ SkRect*) const final {
return true;
}
bool isRRect(const SkRect&, SkRRect*, GrAA*) const override { return false; }
// sort out what kind of clip mask needs to be created: alpha, stencil,
// scissor, or entirely software
bool GrClipStackClip::apply(GrContext* context, GrRenderTargetContext* renderTargetContext,
- bool useHWAA, bool hasUserStencilSettings, GrAppliedClip* out) const {
+ bool useHWAA, bool hasUserStencilSettings, GrAppliedClip* out,
+ SkRect* bounds) const {
if (!fStack || fStack->isWideOpen()) {
return true;
}
- SkRect devBounds = SkRect::MakeIWH(renderTargetContext->width(),
- renderTargetContext->height());
- if (!devBounds.intersect(out->clippedDrawBounds())) {
+ SkRect devBounds = SkRect::MakeIWH(renderTargetContext->width(), renderTargetContext->height());
+ if (!devBounds.intersect(*bounds)) {
return false;
}
renderTargetContext->priv().maxWindowRectangles());
if (reducedClip.hasIBounds() && !GrClip::IsInsideClip(reducedClip.ibounds(), devBounds)) {
- out->addScissor(reducedClip.ibounds());
+ out->addScissor(reducedClip.ibounds(), bounds);
}
if (!reducedClip.windowRectangles().empty()) {
void getConservativeBounds(int width, int height, SkIRect* devResult,
bool* isIntersectionOfRects) const final;
bool apply(GrContext*, GrRenderTargetContext*, bool useHWAA, bool hasUserStencilSettings,
- GrAppliedClip* out) const final;
+ GrAppliedClip* out, SkRect* bounds) const final;
bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA* aa) const override;
return false;
};
-bool GrFixedClip::apply(GrContext*, GrRenderTargetContext* rtc,
- bool, bool, GrAppliedClip* out) const {
+bool GrFixedClip::apply(GrContext*, GrRenderTargetContext* rtc, bool, bool, GrAppliedClip* out,
+ SkRect* bounds) const {
if (fScissorState.enabled()) {
SkIRect tightScissor = SkIRect::MakeWH(rtc->width(), rtc->height());
if (!tightScissor.intersect(fScissorState.rect())) {
return false;
}
- if (IsOutsideClip(tightScissor, out->clippedDrawBounds())) {
+ if (IsOutsideClip(tightScissor, *bounds)) {
return false;
}
- if (!IsInsideClip(fScissorState.rect(), out->clippedDrawBounds())) {
- out->addScissor(tightScissor);
+ if (!IsInsideClip(fScissorState.rect(), *bounds)) {
+ out->addScissor(tightScissor, bounds);
}
}
bool quickContains(const SkRect&) const override;
void getConservativeBounds(int w, int h, SkIRect* devResult, bool* iior) const override;
bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA*) const override;
- bool apply(GrContext*, GrRenderTargetContext*, bool, bool, GrAppliedClip* out) const override;
+ bool apply(GrContext*, GrRenderTargetContext*, bool, bool, GrAppliedClip*,
+ SkRect*) const override;
static const GrFixedClip& Disabled();
return false;
}
bool apply(GrContext* context, GrRenderTargetContext* renderTargetContext, bool useHWAA,
- bool hasUserStencilSettings, GrAppliedClip* out) const override {
- if (!fFixedClip.apply(context, renderTargetContext, useHWAA, hasUserStencilSettings, out)) {
+ bool hasUserStencilSettings, GrAppliedClip* out, SkRect* bounds) const override {
+ if (!fFixedClip.apply(context, renderTargetContext, useHWAA, hasUserStencilSettings, out,
+ bounds)) {
return false;
}
out->addStencilClip();
SkRect bounds = SkRect::MakeIWH(fRenderTargetContext->width(), fRenderTargetContext->height());
// Setup clip
- GrAppliedClip appliedClip(bounds);
+ GrAppliedClip appliedClip;
if (!clip.apply(fRenderTargetContext->fContext, fRenderTargetContext, useHWAA, true,
- &appliedClip)) {
+ &appliedClip, &bounds)) {
return;
}
appliedClip.scissorState(),
fRenderTargetContext->accessRenderTarget(),
path);
- op->setClippedBounds(appliedClip.clippedDrawBounds());
+ op->setClippedBounds(bounds);
fRenderTargetContext->getOpList()->recordOp(std::move(op), fRenderTargetContext);
}
// Setup clip
SkRect bounds;
op_bounds(&bounds, op.get());
- GrAppliedClip appliedClip(bounds);
+ GrAppliedClip appliedClip;
if (!clip.apply(fContext, this, pipelineBuilder.isHWAntialias(),
- pipelineBuilder.hasUserStencilSettings(), &appliedClip)) {
+ pipelineBuilder.hasUserStencilSettings(), &appliedClip, &bounds)) {
return SK_InvalidUniqueID;
}
}
op->initPipeline(args);
// TODO: We need to add pipeline dependencies on textures, etc before recording this op.
- op->setClippedBounds(appliedClip.clippedDrawBounds());
+ op->setClippedBounds(bounds);
return this->getOpList()->addOp(std::move(op), this);
}
GrScissorState dummyScissor;
GrWindowRectsState dummyWindows;
- GrAppliedClip dummyAppliedClip(SkRect::MakeLargest());
+ GrAppliedClip dummyAppliedClip;
GrProcessorSet::FragmentProcessorAnalysis analysis;
GrPipeline::InitArgs args;
dummyBuilder.getPipelineInitArgs(&args);
} testLCDCoverageOp;
GrProcessorSet::FragmentProcessorAnalysis analysis;
- GrAppliedClip clip(SkRect::MakeLargest());
+ GrAppliedClip clip;
testLCDCoverageOp.analyzeProcessors(&analysis, GrProcessorSet(GrPaint()), &clip, caps);
SkASSERT(analysis.hasKnownOutputColor());