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