| 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
|
|
|