Chromium Code Reviews| Index: include/gpu/GrClip.h |
| diff --git a/include/gpu/GrClip.h b/include/gpu/GrClip.h |
| index fd8b970e39dc8861695181a369429a0a71d60240..c2d3aaae4d854c436c77d6cf156ea901d90cf2ec 100644 |
| --- a/include/gpu/GrClip.h |
| +++ b/include/gpu/GrClip.h |
| @@ -8,185 +8,130 @@ |
| #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; |
| - } |
| +/** |
| + * Special clip implementation for a wide open clip (aka no clip). |
| + */ |
| +class GrWideOpenClip final : public GrClip { |
|
bsalomon
2016/05/13 02:34:12
I've never been crazy about "WideOpen", what if we
Chris Dalton
2016/05/13 03:53:46
Done. I like GrNoClip.
|
| +private: |
| + bool quickContains(const SkRect& rect) const override final { return true; } |
|
bsalomon
2016/05/13 02:34:11
Can we have just one of final/override? Either see
Chris Dalton
2016/05/13 03:53:46
Done. Good point.
|
| + void getConservativeBounds(int width, int height, SkIRect* devResult, |
| + bool* isIntersectionOfRects) const override final; |
| + bool apply(GrClipMaskManager*, const GrPipelineBuilder&, |
| + const SkRect*, GrAppliedClip*) const override 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 does not write a |
| + * clip to the stencil buffer, 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 resetNonAA(const SkRect& clipRect) { |
| + fScissorState.setNonAA(clipRect); |
| + fHasStencilClip = false; |
| } |
| - // 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; |
| - } |
| + void enableStencilClip(bool enable) { fHasStencilClip = enable; } |
| - bool isWideOpen(const SkRect& rect) const { |
| - return (kWideOpen_ClipType == fClipType) || |
| - (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen()) || |
| - (kIRect_ClipType == fClipType && this->irect().contains(rect)); |
| - } |
| + const GrScissorState& scissorState() const { return fScissorState; } |
| + bool hasStencilClip() const { return fHasStencilClip; } |
| - bool isWideOpen(const SkIRect& rect) const { |
| - return (kWideOpen_ClipType == fClipType) || |
| - (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen()) || |
| - (kIRect_ClipType == fClipType && this->irect().contains(rect)); |
| - } |
| + bool quickContains(const SkRect& rect) const override final; |
| + void getConservativeBounds(int width, int height, SkIRect* devResult, |
| + bool* isIntersectionOfRects) const override final; |
| - bool isWideOpen() const { |
| - return (kWideOpen_ClipType == fClipType) || |
| - (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen()); |
| - } |
| +private: |
| + bool apply(GrClipMaskManager*, const GrPipelineBuilder&, |
| + const SkRect* devBounds, GrAppliedClip* out) const override final; |
| - bool quickContains(const SkRect& rect) const { |
| - return (kWideOpen_ClipType == fClipType) || |
| - (kClipStack_ClipType == fClipType && this->clipStack()->quickContains(rect)) || |
| - (kIRect_ClipType == fClipType && this->irect().contains(rect)); |
| - } |
| + GrScissorState fScissorState; |
| + bool fHasStencilClip; |
| +}; |
| - void getConservativeBounds(int width, int height, |
| - SkIRect* devResult, |
| - bool* isIntersectionOfRects = NULL) const; |
| +/** |
| + * 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); |
| + } |
| - 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& rect) const override final; |
| + void getConservativeBounds(int width, int height, SkIRect* devResult, |
| + bool* isIntersectionOfRects) const override final; |
| + bool apply(GrClipMaskManager*, const GrPipelineBuilder&, |
| + const SkRect* devBounds, GrAppliedClip*) const override final; |
| private: |
| - union Clip { |
| - const SkClipStack* fStack; |
| - SkIRect fIRect; |
| - } fClip; |
| - |
| - SkIPoint fOrigin; |
| - ClipType fClipType; |
| + SkIPoint fOrigin; |
| + SkAutoTUnref<const SkClipStack> fStack; |
| }; |
| #endif |