1 /*
2  * Copyright 2014 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 GrPathRendering_DEFINED
9 #define GrPathRendering_DEFINED
10 
11 #include "SkPath.h"
12 #include "GrGpu.h"
13 #include "GrPathRange.h"
14 #include "GrPipeline.h"
15 
16 class SkDescriptor;
17 class SkTypeface;
18 class GrPath;
19 class GrStencilSettings;
20 class GrStyle;
21 
22 /**
23  * Abstract class wrapping HW path rendering API.
24  *
25  * The subclasses of this class use the possible HW API to render paths (as opposed to path
26  * rendering implemented in Skia on top of a "3d" HW API).
27  * The subclasses hold the global state needed to render paths, including shadow of the global HW
28  * API state. Similar to GrGpu.
29  *
30  * It is expected that the lifetimes of GrGpuXX and GrXXPathRendering are the same. The call context
31  * interface (eg.  * the concrete instance of GrGpu subclass) should be provided to the instance
32  * during construction.
33  */
34 class GrPathRendering {
35 public:
~GrPathRendering()36     virtual ~GrPathRendering() { }
37 
38     typedef GrPathRange::PathIndexType PathIndexType;
39 
40     enum PathTransformType {
41         kNone_PathTransformType,        //!< []
42         kTranslateX_PathTransformType,  //!< [kMTransX]
43         kTranslateY_PathTransformType,  //!< [kMTransY]
44         kTranslate_PathTransformType,   //!< [kMTransX, kMTransY]
45         kAffine_PathTransformType,      //!< [kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY]
46 
47         kLast_PathTransformType = kAffine_PathTransformType
48     };
49 
PathTransformSize(PathTransformType type)50     static inline int PathTransformSize(PathTransformType type) {
51         switch (type) {
52             case kNone_PathTransformType:
53                 return 0;
54             case kTranslateX_PathTransformType:
55             case kTranslateY_PathTransformType:
56                 return 1;
57             case kTranslate_PathTransformType:
58                 return 2;
59             case kAffine_PathTransformType:
60                 return 6;
61 
62             default:
63                 SkFAIL("Unknown path transform type");
64                 return 0;
65         }
66     }
67 
68     // No native support for inverse at this time
69     enum FillType {
70         /** Specifies that "inside" is computed by a non-zero sum of signed
71             edge crossings
72         */
73         kWinding_FillType,
74         /** Specifies that "inside" is computed by an odd number of edge
75             crossings
76         */
77         kEvenOdd_FillType,
78     };
79 
80     static const GrUserStencilSettings& GetStencilPassSettings(FillType);
81 
82     /**
83      * Creates a new gpu path, based on the specified path and stroke and returns it.
84      * The caller owns a ref on the returned path which must be balanced by a call to unref.
85      *
86      * @param SkPath    the geometry.
87      * @param GrStyle   the style applied to the path. Styles with non-dash path effects are not
88      *                  allowed.
89      * @return a new GPU path object.
90      */
91     virtual GrPath* createPath(const SkPath&, const GrStyle&) = 0;
92 
93     /**
94      * Creates a range of gpu paths with a common style. The caller owns a ref on the
95      * returned path range which must be balanced by a call to unref.
96      *
97      * @param PathGenerator class that generates SkPath objects for each path in the range.
98      * @param GrStyle   the common style applied to each path in the range. Styles with non-dash
99      *                  path effects are not allowed.
100      * @return a new path range.
101      */
102     virtual GrPathRange* createPathRange(GrPathRange::PathGenerator*, const GrStyle&) = 0;
103 
104     /**
105      * Creates a range of glyph paths, indexed by glyph id. The glyphs will have an
106      * inverted y-direction in order to match the raw font path data. The caller owns
107      * a ref on the returned path range which must be balanced by a call to unref.
108      *
109      * @param SkTypeface   Typeface that defines the glyphs.
110      *                     If null, the default typeface will be used.
111      *
112      * @param SkDescriptor Additional font configuration that specifies the font's size,
113      *                     stroke, and other flags. This will generally come from an
114      *                     SkGlyphCache.
115      *
116      *                     It is recommended to leave this value null when possible, in
117      *                     which case the glyphs will be loaded directly from the font's
118      *                     raw path data and sized at SkPaint::kCanonicalTextSizeForPaths.
119      *                     This will result in less memory usage and more efficient paths.
120      *
121      *                     If non-null, the glyph paths will match the font descriptor,
122      *                     including with the stroke information baked directly into
123      *                     the outlines.
124      *
125      * @param GrStyle      Common style that the GPU will apply to every path. Note that
126      *                     if the glyph outlines contain baked-in styles from the font
127      *                     descriptor, the GPU style will be applied on top of those
128      *                     outlines.
129      *
130      * @return a new path range populated with glyphs.
131      */
132     GrPathRange* createGlyphs(const SkTypeface*, const SkScalerContextEffects&,
133                               const SkDescriptor*, const GrStyle&);
134 
135     /** None of these params are optional, pointers used just to avoid making copies. */
136     struct StencilPathArgs {
StencilPathArgsStencilPathArgs137         StencilPathArgs(bool useHWAA,
138                         GrRenderTarget* renderTarget,
139                         const SkMatrix* viewMatrix,
140                         const GrScissorState* scissor,
141                         const GrStencilSettings* stencil)
142             : fUseHWAA(useHWAA)
143             , fRenderTarget(renderTarget)
144             , fViewMatrix(viewMatrix)
145             , fScissor(scissor)
146             , fStencil(stencil) {
147         }
148         bool fUseHWAA;
149         GrRenderTarget* fRenderTarget;
150         const SkMatrix* fViewMatrix;
151         const GrScissorState* fScissor;
152         const GrStencilSettings* fStencil;
153     };
154 
stencilPath(const StencilPathArgs & args,const GrPath * path)155     void stencilPath(const StencilPathArgs& args, const GrPath* path) {
156         fGpu->handleDirtyContext();
157         this->onStencilPath(args, path);
158     }
159 
drawPath(const GrPipeline & pipeline,const GrPrimitiveProcessor & primProc,const GrStencilSettings & stencilPassSettings,const GrPath * path)160     void drawPath(const GrPipeline& pipeline,
161                   const GrPrimitiveProcessor& primProc,
162                   const GrStencilSettings& stencilPassSettings, // Cover pass settings in pipeline.
163                   const GrPath* path) {
164         fGpu->handleDirtyContext();
165         if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*fGpu->caps())) {
166             fGpu->xferBarrier(pipeline.getRenderTarget(), barrierType);
167         }
168         this->onDrawPath(pipeline, primProc, stencilPassSettings, path);
169     }
170 
drawPaths(const GrPipeline & pipeline,const GrPrimitiveProcessor & primProc,const GrStencilSettings & stencilPassSettings,const GrPathRange * pathRange,const void * indices,PathIndexType indexType,const float transformValues[],PathTransformType transformType,int count)171     void drawPaths(const GrPipeline& pipeline,
172                    const GrPrimitiveProcessor& primProc,
173                    const GrStencilSettings& stencilPassSettings, // Cover pass settings in pipeline.
174                    const GrPathRange* pathRange,
175                    const void* indices,
176                    PathIndexType indexType,
177                    const float transformValues[],
178                    PathTransformType transformType,
179                    int count) {
180         fGpu->handleDirtyContext();
181         if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*fGpu->caps())) {
182             fGpu->xferBarrier(pipeline.getRenderTarget(), barrierType);
183         }
184 #ifdef SK_DEBUG
185         pathRange->assertPathsLoaded(indices, indexType, count);
186 #endif
187         this->onDrawPaths(pipeline, primProc, stencilPassSettings, pathRange, indices, indexType,
188                           transformValues, transformType, count);
189     }
190 
191 protected:
GrPathRendering(GrGpu * gpu)192     GrPathRendering(GrGpu* gpu)
193         : fGpu(gpu) {
194     }
195     virtual void onStencilPath(const StencilPathArgs&, const GrPath*) = 0;
196     virtual void onDrawPath(const GrPipeline&,
197                             const GrPrimitiveProcessor&,
198                             const GrStencilSettings&,
199                             const GrPath*) = 0;
200     virtual void onDrawPaths(const GrPipeline&,
201                              const GrPrimitiveProcessor&,
202                              const GrStencilSettings&,
203                              const GrPathRange*,
204                              const void* indices,
205                              PathIndexType,
206                              const float transformValues[],
207                              PathTransformType,
208                              int count) = 0;
209 
210     GrGpu* fGpu;
211 private:
212     GrPathRendering& operator=(const GrPathRendering&);
213 };
214 
215 #endif
216