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
16class SkDescriptor;
17class SkTypeface;
18class GrPath;
19class GrStencilSettings;
20class GrStrokeInfo;
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 */
34class GrPathRendering {
35public:
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
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    /**
81     * Creates a new gpu path, based on the specified path and stroke and returns it.
82     * The caller owns a ref on the returned path which must be balanced by a call to unref.
83     *
84     * @param skPath the path geometry.
85     * @param stroke the path stroke.
86     * @return a new path.
87     */
88    virtual GrPath* createPath(const SkPath&, const GrStrokeInfo&) = 0;
89
90    /**
91     * Creates a range of gpu paths with a common stroke. The caller owns a ref on the
92     * returned path range which must be balanced by a call to unref.
93     *
94     * @param PathGenerator class that generates SkPath objects for each path in the range.
95     * @param GrStrokeInfo   the common stroke applied to each path in the range.
96     * @return a new path range.
97     */
98    virtual GrPathRange* createPathRange(GrPathRange::PathGenerator*, const GrStrokeInfo&) = 0;
99
100    /**
101     * Creates a range of glyph paths, indexed by glyph id. The glyphs will have an
102     * inverted y-direction in order to match the raw font path data. The caller owns
103     * a ref on the returned path range which must be balanced by a call to unref.
104     *
105     * @param SkTypeface   Typeface that defines the glyphs.
106     *                     If null, the default typeface will be used.
107     *
108     * @param SkDescriptor Additional font configuration that specifies the font's size,
109     *                     stroke, and other flags. This will generally come from an
110     *                     SkGlyphCache.
111     *
112     *                     It is recommended to leave this value null when possible, in
113     *                     which case the glyphs will be loaded directly from the font's
114     *                     raw path data and sized at SkPaint::kCanonicalTextSizeForPaths.
115     *                     This will result in less memory usage and more efficient paths.
116     *
117     *                     If non-null, the glyph paths will match the font descriptor,
118     *                     including with the stroke information baked directly into
119     *                     the outlines.
120     *
121     * @param GrStrokeInfo Common stroke that the GPU will apply to every path. Note that
122     *                     if the glyph outlines contain baked-in strokes from the font
123     *                     descriptor, the GPU stroke will be applied on top of those
124     *                     outlines.
125     *
126     * @return a new path range populated with glyphs.
127     */
128    GrPathRange* createGlyphs(const SkTypeface*, const SkDescriptor*, const GrStrokeInfo&);
129
130    /** None of these params are optional, pointers used just to avoid making copies. */
131    struct StencilPathArgs {
132        StencilPathArgs(bool useHWAA,
133                        GrRenderTarget* renderTarget,
134                        const SkMatrix* viewMatrix,
135                        const GrScissorState* scissor,
136                        const GrStencilSettings* stencil)
137            : fUseHWAA(useHWAA)
138            , fRenderTarget(renderTarget)
139            , fViewMatrix(viewMatrix)
140            , fScissor(scissor)
141            , fStencil(stencil) {
142        }
143        bool fUseHWAA;
144        GrRenderTarget* fRenderTarget;
145        const SkMatrix* fViewMatrix;
146        const GrScissorState* fScissor;
147        const GrStencilSettings* fStencil;
148    };
149
150    void stencilPath(const StencilPathArgs& args, const GrPath* path) {
151        fGpu->handleDirtyContext();
152        this->onStencilPath(args, path);
153    }
154
155    struct DrawPathArgs : public GrGpu::DrawArgs {
156        DrawPathArgs(const GrPrimitiveProcessor* primProc,
157                     const GrPipeline* pipeline,
158                     const GrProgramDesc* desc,
159                     const GrStencilSettings* stencil)
160            : DrawArgs(primProc, pipeline, desc)
161            , fStencil(stencil) {
162        }
163
164        const GrStencilSettings* fStencil;
165    };
166
167    void drawPath(const DrawPathArgs& args, const GrPath* path) {
168        fGpu->handleDirtyContext();
169        if (GrXferBarrierType barrierType = args.fPipeline->xferBarrierType(*fGpu->caps())) {
170            fGpu->xferBarrier(args.fPipeline->getRenderTarget(), barrierType);
171        }
172        this->onDrawPath(args, path);
173    }
174
175    void drawPaths(const DrawPathArgs& args, const GrPathRange* pathRange, const void* indices,
176                   PathIndexType indexType, const float transformValues[],
177                   PathTransformType transformType, int count) {
178        fGpu->handleDirtyContext();
179        if (GrXferBarrierType barrierType = args.fPipeline->xferBarrierType(*fGpu->caps())) {
180            fGpu->xferBarrier(args.fPipeline->getRenderTarget(), barrierType);
181        }
182#ifdef SK_DEBUG
183        pathRange->assertPathsLoaded(indices, indexType, count);
184#endif
185        this->onDrawPaths(args, pathRange, indices, indexType, transformValues, transformType,
186                          count);
187    }
188
189protected:
190    GrPathRendering(GrGpu* gpu)
191        : fGpu(gpu) {
192    }
193    virtual void onStencilPath(const StencilPathArgs&, const GrPath*) = 0;
194    virtual void onDrawPath(const DrawPathArgs&, const GrPath*) = 0;
195    virtual void onDrawPaths(const DrawPathArgs&, const GrPathRange*, const void*, PathIndexType,
196                             const float[], PathTransformType, int) = 0;
197
198    GrGpu* fGpu;
199private:
200    GrPathRendering& operator=(const GrPathRendering&);
201};
202
203#endif
204