Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2010 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef GrClip_DEFINED
      9 #define GrClip_DEFINED
     10 
     11 #include "SkClipStack.h"
     12 #include "GrSurface.h"
     13 
     14 struct SkIRect;
     15 
     16 /**
     17  * GrClip encapsulates the information required to construct the clip
     18  * masks. 'A GrClip is either wide open, just an IRect, just a Rect, or a full clipstack.
     19  * If the clip is a clipstack than the origin is used to translate the stack with
     20  * respect to device coordinates. This allows us to use a clip stack that is
     21  * specified for a root device with a layer device that is restricted to a subset
     22  * of the original canvas. For other clip types the origin will always be (0,0).
     23  *
     24  * NOTE: GrClip *must* point to a const clipstack
     25  */
     26 class GrClip : SkNoncopyable {
     27 public:
     28     GrClip() : fClipType(kWideOpen_ClipType) {
     29         fOrigin.setZero();
     30     }
     31 
     32     GrClip(const SkIRect& rect) : fClipType(kIRect_ClipType) {
     33         fOrigin.setZero();
     34         fClip.fIRect = rect;
     35     }
     36 
     37     GrClip(const SkRect& rect) : fClipType(kIRect_ClipType) {
     38         fOrigin.setZero();
     39         fClip.fIRect.fLeft   = SkScalarRoundToInt(rect.fLeft);
     40         fClip.fIRect.fTop    = SkScalarRoundToInt(rect.fTop);
     41         fClip.fIRect.fRight  = SkScalarRoundToInt(rect.fRight);
     42         fClip.fIRect.fBottom = SkScalarRoundToInt(rect.fBottom);
     43     }
     44 
     45     ~GrClip() { this->reset(); }
     46 
     47     const GrClip& operator=(const GrClip& other) {
     48         this->reset();
     49         fClipType = other.fClipType;
     50         switch (other.fClipType) {
     51             case kWideOpen_ClipType:
     52                 fOrigin.setZero();
     53                 break;
     54             case kClipStack_ClipType:
     55                 fClip.fStack = SkRef(other.clipStack());
     56                 fOrigin = other.origin();
     57                 break;
     58             case kIRect_ClipType:
     59                 fClip.fIRect = other.irect();
     60                 fOrigin.setZero();
     61                 break;
     62         }
     63         return *this;
     64     }
     65 
     66     bool operator==(const GrClip& other) const {
     67         if (this->clipType() != other.clipType()) {
     68             return false;
     69         }
     70 
     71         switch (fClipType) {
     72             case kWideOpen_ClipType:
     73                 return true;
     74             case kClipStack_ClipType:
     75                 if (this->origin() != other.origin()) {
     76                     return false;
     77                 }
     78 
     79                 if (this->clipStack() && other.clipStack()) {
     80                     return *this->clipStack() == *other.clipStack();
     81                 } else {
     82                     return this->clipStack() == other.clipStack();
     83                 }
     84                 break;
     85             case kIRect_ClipType:
     86                 return this->irect() == other.irect();
     87                 break;
     88         }
     89     }
     90 
     91     bool operator!=(const GrClip& other) const {
     92         return !(*this == other);
     93     }
     94 
     95     const SkClipStack* clipStack() const {
     96         SkASSERT(kClipStack_ClipType == fClipType);
     97         return fClip.fStack;
     98     }
     99 
    100     void setClipStack(const SkClipStack* clipStack, const SkIPoint* origin = NULL) {
    101         this->reset();
    102         if (clipStack->isWideOpen()) {
    103             fClipType = kWideOpen_ClipType;
    104             fOrigin.setZero();
    105         } else {
    106             fClipType = kClipStack_ClipType;
    107             fClip.fStack = SkRef(clipStack);
    108             if (origin) {
    109                 fOrigin = *origin;
    110             } else {
    111                 fOrigin.setZero();
    112             }
    113         }
    114     }
    115 
    116     const SkIRect& irect() const {
    117         SkASSERT(kIRect_ClipType == fClipType);
    118         return fClip.fIRect;
    119     }
    120 
    121     void reset() {
    122         if (kClipStack_ClipType == fClipType) {
    123             fClip.fStack->unref();
    124             fClip.fStack = NULL;
    125         }
    126         fClipType = kWideOpen_ClipType;
    127         fOrigin.setZero();
    128     }
    129 
    130     // We support this for all cliptypes to simplify the logic a bit in clip mask manager.
    131     // non clipstack clip types MUST have a (0,0) origin
    132     const SkIPoint& origin() const {
    133         SkASSERT(fClipType == kClipStack_ClipType || (fOrigin.fX == 0 && fOrigin.fY == 0));
    134         return fOrigin;
    135     }
    136 
    137     bool isWideOpen(const SkRect& rect) const {
    138         return (kWideOpen_ClipType == fClipType) ||
    139                (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen()) ||
    140                (kIRect_ClipType == fClipType && this->irect().contains(rect));
    141     }
    142 
    143     bool isWideOpen(const SkIRect& rect) const {
    144         return (kWideOpen_ClipType == fClipType) ||
    145                (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen()) ||
    146                (kIRect_ClipType == fClipType && this->irect().contains(rect));
    147     }
    148 
    149     bool isWideOpen() const {
    150         return (kWideOpen_ClipType == fClipType) ||
    151                (kClipStack_ClipType == fClipType && this->clipStack()->isWideOpen());
    152     }
    153 
    154     bool quickContains(const SkRect& rect) const {
    155         return (kWideOpen_ClipType == fClipType) ||
    156                (kClipStack_ClipType == fClipType && this->clipStack()->quickContains(rect)) ||
    157                (kIRect_ClipType == fClipType && this->irect().contains(rect));
    158     }
    159 
    160     void getConservativeBounds(const GrSurface* surface,
    161                                SkIRect* devResult,
    162                                bool* isIntersectionOfRects = NULL) const {
    163         this->getConservativeBounds(surface->width(), surface->height(),
    164                                     devResult, isIntersectionOfRects);
    165     }
    166 
    167     void getConservativeBounds(int width, int height,
    168                                SkIRect* devResult,
    169                                bool* isIntersectionOfRects = NULL) const;
    170 
    171     static const GrClip& WideOpen();
    172 
    173     enum ClipType {
    174         kClipStack_ClipType,
    175         kWideOpen_ClipType,
    176         kIRect_ClipType,
    177     };
    178 
    179     ClipType clipType() const { return fClipType; }
    180 
    181 private:
    182     union Clip {
    183         const SkClipStack* fStack;
    184         SkIRect fIRect;
    185     } fClip;
    186 
    187     SkIPoint fOrigin;
    188     ClipType fClipType;
    189 };
    190 
    191 #endif
    192