| 1 | /* | 
| 2 |  * Copyright 2011 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 GrPathRenderer_DEFINED | 
| 9 | #define GrPathRenderer_DEFINED | 
| 10 |  | 
| 11 | #include "include/core/SkRefCnt.h" | 
| 12 | #include "include/private/GrTypesPriv.h" | 
| 13 | #include "include/private/SkTArray.h" | 
| 14 |  | 
| 15 | class GrCaps; | 
| 16 | class GrClip; | 
| 17 | class GrFixedClip; | 
| 18 | class GrHardClip; | 
| 19 | class GrPaint; | 
| 20 | class GrRecordingContext; | 
| 21 | class GrRenderTargetContext; | 
| 22 | class GrRenderTargetProxy; | 
| 23 | class GrShape; | 
| 24 | class GrStyle; | 
| 25 | struct GrUserStencilSettings; | 
| 26 | struct SkIRect; | 
| 27 | class SkMatrix; | 
| 28 | class SkPath; | 
| 29 |  | 
| 30 | /** | 
| 31 |  *  Base class for drawing paths into a GrOpsTask. | 
| 32 |  */ | 
| 33 | class GrPathRenderer : public SkRefCnt { | 
| 34 | public: | 
| 35 |     GrPathRenderer(); | 
| 36 |  | 
| 37 |     /** | 
| 38 |      * A caller may wish to use a path renderer to draw a path into the stencil buffer. However, | 
| 39 |      * the path renderer itself may require use of the stencil buffer. Also a path renderer may | 
| 40 |      * use a GrProcessor coverage stage that sets coverage to zero to eliminate pixels that are | 
| 41 |      * covered by bounding geometry but outside the path. These exterior pixels would still be | 
| 42 |      * rendered into the stencil. | 
| 43 |      * | 
| 44 |      * A GrPathRenderer can provide three levels of support for stenciling paths: | 
| 45 |      * 1) kNoRestriction: This is the most general. The caller passes a GrPaint and calls drawPath(). | 
| 46 |      *                    The path is rendered exactly as the draw state indicates including support | 
| 47 |      *                    for simultaneous color and stenciling with arbitrary stenciling rules. | 
| 48 |      *                    Pixels partially covered by AA paths are affected by the stencil settings. | 
| 49 |      * 2) kStencilOnly: The path renderer cannot apply arbitrary stencil rules nor shade and stencil | 
| 50 |      *                  simultaneously. The path renderer does support the stencilPath() function | 
| 51 |      *                  which performs no color writes and writes a non-zero stencil value to pixels | 
| 52 |      *                  covered by the path. | 
| 53 |      * 3) kNoSupport: This path renderer cannot be used to stencil the path. | 
| 54 |      */ | 
| 55 |     enum StencilSupport { | 
| 56 |         kNoSupport_StencilSupport, | 
| 57 |         kStencilOnly_StencilSupport, | 
| 58 |         kNoRestriction_StencilSupport, | 
| 59 |     }; | 
| 60 |  | 
| 61 |     /** | 
| 62 |      * This function is to get the stencil support for a particular path. The path's fill must | 
| 63 |      * not be an inverse type. The path will always be filled and not stroked. | 
| 64 |      * | 
| 65 |      * @param shape   the shape that will be drawn. Must be simple fill styled and non-inverse | 
| 66 |      *                filled. | 
| 67 |      */ | 
| 68 |     StencilSupport getStencilSupport(const GrShape& shape) const; | 
| 69 |  | 
| 70 |     enum class CanDrawPath { | 
| 71 |         kNo, | 
| 72 |         kAsBackup, // i.e. This renderer is better than SW fallback if no others can draw the path. | 
| 73 |         kYes | 
| 74 |     }; | 
| 75 |  | 
| 76 |     struct CanDrawPathArgs { | 
| 77 |         SkDEBUGCODE(CanDrawPathArgs() { memset(this, 0, sizeof(*this)); }) // For validation. | 
| 78 |  | 
| 79 |         const GrCaps*               fCaps; | 
| 80 |         const GrRenderTargetProxy*  fProxy; | 
| 81 |         const SkIRect*              fClipConservativeBounds; | 
| 82 |         const SkMatrix*             fViewMatrix; | 
| 83 |         const GrShape*              fShape; | 
| 84 |         GrAAType                    fAAType; | 
| 85 |         bool                        fTargetIsWrappedVkSecondaryCB; | 
| 86 |  | 
| 87 |         // This is only used by GrStencilAndCoverPathRenderer | 
| 88 |         bool                        fHasUserStencilSettings; | 
| 89 |  | 
| 90 | #ifdef SK_DEBUG | 
| 91 |         void validate() const { | 
| 92 |             SkASSERT(fCaps); | 
| 93 |             SkASSERT(fProxy); | 
| 94 |             SkASSERT(fClipConservativeBounds); | 
| 95 |             SkASSERT(fViewMatrix); | 
| 96 |             SkASSERT(fShape); | 
| 97 |         } | 
| 98 | #endif | 
| 99 |     }; | 
| 100 |  | 
| 101 |     /** | 
| 102 |      * Returns how well this path renderer is able to render the given path. Returning kNo or | 
| 103 |      * kAsBackup allows the caller to keep searching for a better path renderer. This function is | 
| 104 |      * called when searching for the best path renderer to draw a path. | 
| 105 |      */ | 
| 106 |     CanDrawPath canDrawPath(const CanDrawPathArgs& args) const { | 
| 107 |         SkDEBUGCODE(args.validate();) | 
| 108 |         return this->onCanDrawPath(args); | 
| 109 |     } | 
| 110 |  | 
| 111 |     struct DrawPathArgs { | 
| 112 |         GrRecordingContext*          fContext; | 
| 113 |         GrPaint&&                    fPaint; | 
| 114 |         const GrUserStencilSettings* fUserStencilSettings; | 
| 115 |         GrRenderTargetContext*       fRenderTargetContext; | 
| 116 |         const GrClip*                fClip; | 
| 117 |         const SkIRect*               fClipConservativeBounds; | 
| 118 |         const SkMatrix*              fViewMatrix; | 
| 119 |         const GrShape*               fShape; | 
| 120 |         GrAAType                     fAAType; | 
| 121 |         bool                         fGammaCorrect; | 
| 122 | #ifdef SK_DEBUG | 
| 123 |         void validate() const { | 
| 124 |             SkASSERT(fContext); | 
| 125 |             SkASSERT(fUserStencilSettings); | 
| 126 |             SkASSERT(fRenderTargetContext); | 
| 127 |             SkASSERT(fClip); | 
| 128 |             SkASSERT(fClipConservativeBounds); | 
| 129 |             SkASSERT(fViewMatrix); | 
| 130 |             SkASSERT(fShape); | 
| 131 |         } | 
| 132 | #endif | 
| 133 |     }; | 
| 134 |  | 
| 135 |     /** | 
| 136 |      * Draws the path into the draw target. If getStencilSupport() would return kNoRestriction then | 
| 137 |      * the subclass must respect the stencil settings. | 
| 138 |      */ | 
| 139 |     bool drawPath(const DrawPathArgs& args); | 
| 140 |     /** | 
| 141 |      * Args to stencilPath(). fAAType cannot be kCoverage. | 
| 142 |      */ | 
| 143 |     struct StencilPathArgs { | 
| 144 |         SkDEBUGCODE(StencilPathArgs() { memset(this, 0, sizeof(*this)); }) // For validation. | 
| 145 |  | 
| 146 |         GrRecordingContext*    fContext; | 
| 147 |         GrRenderTargetContext* fRenderTargetContext; | 
| 148 |         const GrHardClip*      fClip; | 
| 149 |         const SkIRect*         fClipConservativeBounds; | 
| 150 |         const SkMatrix*        fViewMatrix; | 
| 151 |         const GrShape*         fShape; | 
| 152 |         GrAA                   fDoStencilMSAA; | 
| 153 |  | 
| 154 |         SkDEBUGCODE(void validate() const); | 
| 155 |     }; | 
| 156 |  | 
| 157 |     /** | 
| 158 |      * Draws the path to the stencil buffer. Assume the writable stencil bits are already | 
| 159 |      * initialized to zero. The pixels inside the path will have non-zero stencil values afterwards. | 
| 160 |      */ | 
| 161 |     void stencilPath(const StencilPathArgs& args) { | 
| 162 |         SkDEBUGCODE(args.validate();) | 
| 163 |         SkASSERT(kNoSupport_StencilSupport != this->getStencilSupport(*args.fShape)); | 
| 164 |         this->onStencilPath(args); | 
| 165 |     } | 
| 166 |  | 
| 167 |     // Helper for determining if we can treat a thin stroke as a hairline w/ coverage. | 
| 168 |     // If we can, we draw lots faster (raster device does this same test). | 
| 169 |     static bool IsStrokeHairlineOrEquivalent(const GrStyle&, const SkMatrix&, | 
| 170 |                                              SkScalar* outCoverage); | 
| 171 |  | 
| 172 | protected: | 
| 173 |     // Helper for getting the device bounds of a path. Inverse filled paths will have bounds set | 
| 174 |     // by devSize. Non-inverse path bounds will not necessarily be clipped to devSize. | 
| 175 |     static void GetPathDevBounds(const SkPath& path, | 
| 176 |                                  SkISize devSize, | 
| 177 |                                  const SkMatrix& matrix, | 
| 178 |                                  SkRect* bounds); | 
| 179 |  | 
| 180 | private: | 
| 181 |     /** | 
| 182 |      * Subclass overrides if it has any limitations of stenciling support. | 
| 183 |      */ | 
| 184 |     virtual StencilSupport onGetStencilSupport(const GrShape&) const { | 
| 185 |         return kNoRestriction_StencilSupport; | 
| 186 |     } | 
| 187 |  | 
| 188 |     /** | 
| 189 |      * Subclass implementation of drawPath() | 
| 190 |      */ | 
| 191 |     virtual bool onDrawPath(const DrawPathArgs& args) = 0; | 
| 192 |  | 
| 193 |     /** | 
| 194 |      * Subclass implementation of canDrawPath() | 
| 195 |      */ | 
| 196 |     virtual CanDrawPath onCanDrawPath(const CanDrawPathArgs& args) const = 0; | 
| 197 |  | 
| 198 |     /** | 
| 199 |      * Subclass implementation of stencilPath(). Subclass must override iff it ever returns | 
| 200 |      * kStencilOnly in onGetStencilSupport(). | 
| 201 |      */ | 
| 202 |     virtual void onStencilPath(const StencilPathArgs&); | 
| 203 |  | 
| 204 |     typedef SkRefCnt INHERITED; | 
| 205 | }; | 
| 206 |  | 
| 207 | #endif | 
| 208 |  |