Index: include/gpu/GrClip.h |
diff --git a/include/gpu/GrClip.h b/include/gpu/GrClip.h |
index fd8b970e39dc8861695181a369429a0a71d60240..68a4eb92241df7286f212c507f72ea38fbe0d2ce 100644 |
--- a/include/gpu/GrClip.h |
+++ b/include/gpu/GrClip.h |
@@ -8,185 +8,125 @@ |
#ifndef GrClip_DEFINED |
#define GrClip_DEFINED |
+#include "GrFragmentProcessor.h" |
+#include "GrTypesPriv.h" |
#include "SkClipStack.h" |
-struct SkIRect; |
+class GrClipMaskManager; |
+class GrPipelineBuilder; |
/** |
- * GrClip encapsulates the information required to construct the clip |
- * masks. 'A GrClip is either wide open, just an IRect, just a Rect, or a full clipstack. |
- * If the clip is a clipstack than the origin is used to translate the stack with |
- * respect to device coordinates. This allows us to use a clip stack that is |
- * specified for a root device with a layer device that is restricted to a subset |
- * of the original canvas. For other clip types the origin will always be (0,0). |
- * |
- * NOTE: GrClip *must* point to a const clipstack |
+ * Produced by GrClip. It provides a set of modifications to the drawing state that are used to |
+ * create the final GrPipeline for a GrBatch. |
*/ |
-class GrClip : SkNoncopyable { |
+class GrAppliedClip { |
public: |
- GrClip() : fClipType(kWideOpen_ClipType) { |
- fOrigin.setZero(); |
- } |
+ GrAppliedClip() : fHasStencilClip(false) {} |
+ const GrFragmentProcessor* clipCoverageFragmentProcessor() const { return fClipCoverageFP; } |
+ const GrScissorState& scissorState() const { return fScissorState; } |
+ bool hasStencilClip() const { return fHasStencilClip; } |
- GrClip(const SkIRect& rect) : fClipType(kIRect_ClipType) { |
- fOrigin.setZero(); |
- fClip.fIRect = rect; |
- } |
+private: |
+ SkAutoTUnref<const GrFragmentProcessor> fClipCoverageFP; |
+ GrScissorState fScissorState; |
+ bool fHasStencilClip; |
- GrClip(const SkRect& rect) : fClipType(kIRect_ClipType) { |
- fOrigin.setZero(); |
- fClip.fIRect.fLeft = SkScalarRoundToInt(rect.fLeft); |
- fClip.fIRect.fTop = SkScalarRoundToInt(rect.fTop); |
- fClip.fIRect.fRight = SkScalarRoundToInt(rect.fRight); |
- fClip.fIRect.fBottom = SkScalarRoundToInt(rect.fBottom); |
- } |
+ friend class GrFixedClip; |
+ friend class GrClipMaskManager; |
- ~GrClip() { this->reset(); } |
- |
- const GrClip& operator=(const GrClip& other) { |
- this->reset(); |
- fClipType = other.fClipType; |
- switch (other.fClipType) { |
- case kWideOpen_ClipType: |
- fOrigin.setZero(); |
- break; |
- case kClipStack_ClipType: |
- fClip.fStack = SkRef(other.clipStack()); |
- fOrigin = other.origin(); |
- break; |
- case kIRect_ClipType: |
- fClip.fIRect = other.irect(); |
- fOrigin.setZero(); |
- break; |
- } |
- return *this; |
- } |
+ typedef SkNoncopyable INHERITED; |
+}; |
- bool operator==(const GrClip& other) const { |
- if (this->clipType() != other.clipType()) { |
- return false; |
- } |
- |
- switch (fClipType) { |
- case kWideOpen_ClipType: |
- return true; |
- case kClipStack_ClipType: |
- if (this->origin() != other.origin()) { |
- return false; |
- } |
- |
- if (this->clipStack() && other.clipStack()) { |
- return *this->clipStack() == *other.clipStack(); |
- } else { |
- return this->clipStack() == other.clipStack(); |
- } |
- break; |
- case kIRect_ClipType: |
- return this->irect() == other.irect(); |
- break; |
- } |
- SkFAIL("This should not occur\n"); |
- return false; |
- } |
+/** |
+ * GrClip is an abstract base class for applying a clip. It constructs a clip mask if necessary, and |
+ * fills out a GrAppliedClip instructing the caller on how to set up the draw state. |
+ */ |
+class GrClip { |
+public: |
+ virtual bool quickContains(const SkRect&) const = 0; |
+ virtual void getConservativeBounds(int width, int height, SkIRect* devResult, |
+ bool* isIntersectionOfRects = nullptr) const = 0; |
+ virtual bool apply(GrClipMaskManager*, const GrPipelineBuilder&, const SkRect* devBounds, |
+ GrAppliedClip*) const = 0; |
- bool operator!=(const GrClip& other) const { |
- return !(*this == other); |
- } |
+ virtual ~GrClip() {} |
+}; |
- const SkClipStack* clipStack() const { |
- SkASSERT(kClipStack_ClipType == fClipType); |
- return fClip.fStack; |
- } |
+/** |
+ * Specialized implementation for no clip. |
+ */ |
+class GrNoClip final : public GrClip { |
+private: |
+ bool quickContains(const SkRect&) const final { return true; } |
+ void getConservativeBounds(int width, int height, SkIRect* devResult, |
+ bool* isIntersectionOfRects) const final; |
+ bool apply(GrClipMaskManager*, const GrPipelineBuilder&, |
+ const SkRect*, GrAppliedClip*) const final { return true; } |
+}; |
- void setClipStack(const SkClipStack* clipStack, const SkIPoint* origin = NULL) { |
- this->reset(); |
- if (clipStack->isWideOpen()) { |
- fClipType = kWideOpen_ClipType; |
- fOrigin.setZero(); |
- } else { |
- fClipType = kClipStack_ClipType; |
- fClip.fStack = SkRef(clipStack); |
- if (origin) { |
- fOrigin = *origin; |
- } else { |
- fOrigin.setZero(); |
- } |
- } |
- } |
+/** |
+ * 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. |
+ */ |
+class GrFixedClip final : public GrClip { |
+public: |
+ GrFixedClip() : fHasStencilClip(false) {} |
+ GrFixedClip(const SkIRect& scissorRect) : fScissorState(scissorRect), fHasStencilClip(false) {} |
- void setIRect(const SkIRect& irect) { |
- this->reset(); |
- fClipType = kIRect_ClipType; |
- fOrigin.setZero(); |
- fClip.fIRect = irect; |
+ void reset() { |
+ fScissorState.setDisabled(); |
+ fHasStencilClip = false; |
} |
- const SkIRect& irect() const { |
- SkASSERT(kIRect_ClipType == fClipType); |
- return fClip.fIRect; |
+ void reset(const SkIRect& scissorRect) { |
+ fScissorState.set(scissorRect); |
+ fHasStencilClip = false; |
} |
- void reset() { |
- if (kClipStack_ClipType == fClipType) { |
- fClip.fStack->unref(); |
- fClip.fStack = NULL; |
- } |
- fClipType = kWideOpen_ClipType; |
- fOrigin.setZero(); |
- } |
+ void enableStencilClip(bool enable) { fHasStencilClip = enable; } |
- // We support this for all cliptypes to simplify the logic a bit in clip mask manager. |
- // non clipstack clip types MUST have a (0,0) origin |
- const SkIPoint& origin() const { |
- SkASSERT(fClipType == kClipStack_ClipType || (fOrigin.fX == 0 && fOrigin.fY == 0)); |
- return fOrigin; |
- } |
+ const GrScissorState& scissorState() const { return fScissorState; } |
+ bool hasStencilClip() const { return fHasStencilClip; } |
- bool isWideOpen(const SkRect& rect) const { |
- return (kWideOpen_ClipType == fClipType) || |
- (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen()) || |
- (kIRect_ClipType == fClipType && this->irect().contains(rect)); |
- } |
+ bool quickContains(const SkRect&) const final; |
+ void getConservativeBounds(int width, int height, SkIRect* devResult, |
+ bool* isIntersectionOfRects) const final; |
- bool isWideOpen(const SkIRect& rect) const { |
- return (kWideOpen_ClipType == fClipType) || |
- (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen()) || |
- (kIRect_ClipType == fClipType && this->irect().contains(rect)); |
- } |
+private: |
+ bool apply(GrClipMaskManager*, const GrPipelineBuilder&, |
+ const SkRect* devBounds, GrAppliedClip* out) const final; |
- bool isWideOpen() const { |
- return (kWideOpen_ClipType == fClipType) || |
- (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen()); |
- } |
+ GrScissorState fScissorState; |
+ bool fHasStencilClip; |
+}; |
- bool quickContains(const SkRect& rect) const { |
- return (kWideOpen_ClipType == fClipType) || |
- (kClipStack_ClipType == fClipType && this->clipStack()->quickContains(rect)) || |
- (kIRect_ClipType == fClipType && this->irect().contains(rect)); |
+/** |
+ * GrClipStackClip can apply a generic SkClipStack to the draw state. It may generate clip masks or |
+ * write to the stencil buffer during apply(). |
+ */ |
+class GrClipStackClip final : public GrClip { |
+public: |
+ GrClipStackClip(const SkClipStack* stack = nullptr, const SkIPoint* origin = nullptr) { |
+ this->reset(stack, origin); |
} |
- void getConservativeBounds(int width, int height, |
- SkIRect* devResult, |
- bool* isIntersectionOfRects = NULL) const; |
- |
- static const GrClip& WideOpen(); |
+ void reset(const SkClipStack* stack = nullptr, const SkIPoint* origin = nullptr) { |
+ fOrigin = origin ? *origin : SkIPoint::Make(0, 0); |
+ fStack.reset(SkSafeRef(stack)); |
+ } |
- enum ClipType { |
- kClipStack_ClipType, |
- kWideOpen_ClipType, |
- kIRect_ClipType, |
- }; |
+ const SkIPoint& origin() const { return fOrigin; } |
+ const SkClipStack* clipStack() const { return fStack; } |
- ClipType clipType() const { return fClipType; } |
+ bool quickContains(const SkRect&) const final; |
+ void getConservativeBounds(int width, int height, SkIRect* devResult, |
+ bool* isIntersectionOfRects) const final; |
+ bool apply(GrClipMaskManager*, const GrPipelineBuilder&, |
+ const SkRect* devBounds, GrAppliedClip*) const final; |
private: |
- union Clip { |
- const SkClipStack* fStack; |
- SkIRect fIRect; |
- } fClip; |
- |
- SkIPoint fOrigin; |
- ClipType fClipType; |
+ SkIPoint fOrigin; |
+ SkAutoTUnref<const SkClipStack> fStack; |
}; |
#endif |