Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2012 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 #ifndef GrClipMaskManager_DEFINED
      8 #define GrClipMaskManager_DEFINED
      9 
     10 #include "GrClipMaskCache.h"
     11 #include "GrContext.h"
     12 #include "GrPipelineBuilder.h"
     13 #include "GrReducedClip.h"
     14 #include "GrStencil.h"
     15 #include "GrTexture.h"
     16 #include "SkClipStack.h"
     17 #include "SkDeque.h"
     18 #include "SkPath.h"
     19 #include "SkRefCnt.h"
     20 #include "SkTLList.h"
     21 #include "SkTypes.h"
     22 
     23 class GrClipTarget;
     24 class GrPathRenderer;
     25 class GrPathRendererChain;
     26 class GrTexture;
     27 class SkPath;
     28 /**
     29  * The clip mask creator handles the generation of the clip mask. If anti
     30  * aliasing is requested it will (in the future) generate a single channel
     31  * (8bit) mask. If no anti aliasing is requested it will generate a 1-bit
     32  * mask in the stencil buffer. In the non anti-aliasing case, if the clip
     33  * mask can be represented as a rectangle then scissoring is used. In all
     34  * cases scissoring is used to bound the range of the clip mask.
     35  */
     36 class GrClipMaskManager : SkNoncopyable {
     37 public:
     38     GrClipMaskManager()
     39         : fCurrClipMaskType(kNone_ClipMaskType)
     40         , fClipTarget(NULL)
     41         , fClipMode(kIgnoreClip_StencilClipMode) {
     42     }
     43 
     44     /**
     45      * Creates a clip mask if necessary as a stencil buffer or alpha texture
     46      * and sets the GrGpu's scissor and stencil state. If the return is false
     47      * then the draw can be skipped. The AutoRestoreEffects is initialized by
     48      * the manager when it must install additional effects to implement the
     49      * clip. devBounds is optional but can help optimize clipping.
     50      */
     51     bool setupClipping(GrPipelineBuilder*,
     52                        GrPipelineBuilder::AutoRestoreFragmentProcessors*,
     53                        GrPipelineBuilder::AutoRestoreStencil*,
     54                        GrScissorState*,
     55                        const SkRect* devBounds);
     56 
     57     /**
     58      * Purge resources to free up memory. TODO: This class shouldn't hold any long lived refs
     59      * which will allow Resourcecache to automatically purge anything this class has created.
     60      */
     61     void purgeResources();
     62 
     63     bool isClipInStencil() const {
     64         return kStencil_ClipMaskType == fCurrClipMaskType;
     65     }
     66 
     67     bool isClipInAlpha() const {
     68         return kAlpha_ClipMaskType == fCurrClipMaskType;
     69     }
     70 
     71     GrContext* getContext() {
     72         return fAACache.getContext();
     73     }
     74 
     75     void setClipTarget(GrClipTarget*);
     76 
     77     void adjustPathStencilParams(const GrStencilAttachment*, GrStencilSettings*);
     78 
     79 private:
     80     /**
     81      * Informs the helper function adjustStencilParams() about how the stencil
     82      * buffer clip is being used.
     83      */
     84     enum StencilClipMode {
     85         // Draw to the clip bit of the stencil buffer
     86         kModifyClip_StencilClipMode,
     87         // Clip against the existing representation of the clip in the high bit
     88         // of the stencil buffer.
     89         kRespectClip_StencilClipMode,
     90         // Neither writing to nor clipping against the clip bit.
     91         kIgnoreClip_StencilClipMode,
     92     };
     93 
     94     // Attempts to install a series of coverage effects to implement the clip. Return indicates
     95     // whether the element list was successfully converted to effects.
     96     bool installClipEffects(GrPipelineBuilder*,
     97                             GrPipelineBuilder::AutoRestoreFragmentProcessors*,
     98                             const GrReducedClip::ElementList&,
     99                             const SkVector& clipOffset,
    100                             const SkRect* devBounds);
    101 
    102     // Draws the clip into the stencil buffer
    103     bool createStencilClipMask(GrRenderTarget*,
    104                                int32_t elementsGenID,
    105                                GrReducedClip::InitialState initialState,
    106                                const GrReducedClip::ElementList& elements,
    107                                const SkIRect& clipSpaceIBounds,
    108                                const SkIPoint& clipSpaceToStencilOffset);
    109 
    110     // Creates an alpha mask of the clip. The mask is a rasterization of elements through the
    111     // rect specified by clipSpaceIBounds.
    112     GrTexture* createAlphaClipMask(int32_t elementsGenID,
    113                                    GrReducedClip::InitialState initialState,
    114                                    const GrReducedClip::ElementList& elements,
    115                                    const SkVector& clipToMaskOffset,
    116                                    const SkIRect& clipSpaceIBounds);
    117 
    118     // Similar to createAlphaClipMask but it rasterizes in SW and uploads to the result texture.
    119     GrTexture* createSoftwareClipMask(int32_t elementsGenID,
    120                                       GrReducedClip::InitialState initialState,
    121                                       const GrReducedClip::ElementList& elements,
    122                                       const SkVector& clipToMaskOffset,
    123                                       const SkIRect& clipSpaceIBounds);
    124 
    125     // Returns the cached mask texture if it matches the elementsGenID and the clipSpaceIBounds.
    126     // Returns NULL if not found.
    127     GrTexture* getCachedMaskTexture(int32_t elementsGenID, const SkIRect& clipSpaceIBounds);
    128 
    129     // Handles allocation (if needed) of a clip alpha-mask texture for both the sw-upload
    130     // or gpu-rendered cases.
    131     GrTexture* allocMaskTexture(int32_t elementsGenID,
    132                                 const SkIRect& clipSpaceIBounds,
    133                                 bool willUpload);
    134 
    135     bool useSWOnlyPath(const GrPipelineBuilder*,
    136                        const SkVector& clipToMaskOffset,
    137                        const GrReducedClip::ElementList& elements);
    138 
    139     // Draws a clip element into the target alpha mask. The caller should have already setup the
    140     // desired blend operation. Optionally if the caller already selected a path renderer it can
    141     // be passed. Otherwise the function will select one if the element is a path.
    142     bool drawElement(GrPipelineBuilder*,
    143                      const SkMatrix& viewMatrix,
    144                      GrTexture* target,
    145                      const SkClipStack::Element*,
    146                      GrPathRenderer* pr = NULL);
    147 
    148     // Determines whether it is possible to draw the element to both the stencil buffer and the
    149     // alpha mask simultaneously. If so and the element is a path a compatible path renderer is
    150     // also returned.
    151     bool canStencilAndDrawElement(GrPipelineBuilder*,
    152                                   GrTexture* target,
    153                                   GrPathRenderer**,
    154                                   const SkClipStack::Element*);
    155 
    156     void mergeMask(GrPipelineBuilder*,
    157                    GrTexture* dstMask,
    158                    GrTexture* srcMask,
    159                    SkRegion::Op op,
    160                    const SkIRect& dstBound,
    161                    const SkIRect& srcBound);
    162 
    163     GrTexture* createTempMask(int width, int height);
    164 
    165     void setupCache(const SkClipStack& clip,
    166                     const SkIRect& bounds);
    167     /**
    168      * Called prior to return control back the GrGpu in setupClipping. It updates the
    169      * GrPipelineBuilder with stencil settings that account for stencil-based clipping.
    170      */
    171     void setPipelineBuilderStencil(GrPipelineBuilder*, GrPipelineBuilder::AutoRestoreStencil*);
    172 
    173     /**
    174      * Adjusts the stencil settings to account for interaction with stencil
    175      * clipping.
    176      */
    177     void adjustStencilParams(GrStencilSettings* settings,
    178                              StencilClipMode mode,
    179                              int stencilBitCnt);
    180 
    181     /**
    182      * We may represent the clip as a mask in the stencil buffer or as an alpha
    183      * texture. It may be neither because the scissor rect suffices or we
    184      * haven't yet examined the clip.
    185      */
    186     enum ClipMaskType {
    187         kNone_ClipMaskType,
    188         kStencil_ClipMaskType,
    189         kAlpha_ClipMaskType,
    190     } fCurrClipMaskType;
    191 
    192     GrClipMaskCache fAACache;       // cache for the AA path
    193     GrClipTarget*   fClipTarget;
    194     StencilClipMode fClipMode;
    195 
    196     typedef SkNoncopyable INHERITED;
    197 };
    198 #endif // GrClipMaskManager_DEFINED
    199