1 /*
2  * Copyright 2015 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 GrDrawPathBatch_DEFINED
9 #define GrDrawPathBatch_DEFINED
10 
11 #include "GrBatchFlushState.h"
12 #include "GrDrawBatch.h"
13 #include "GrGpu.h"
14 #include "GrPath.h"
15 #include "GrPathRendering.h"
16 #include "GrPathProcessor.h"
17 
18 #include "SkTLList.h"
19 
20 class GrDrawPathBatchBase : public GrDrawBatch {
21 public:
computePipelineOptimizations(GrInitInvariantOutput * color,GrInitInvariantOutput * coverage,GrBatchToXPOverrides * overrides)22     void computePipelineOptimizations(GrInitInvariantOutput* color,
23                                       GrInitInvariantOutput* coverage,
24                                       GrBatchToXPOverrides* overrides) const override {
25         color->setKnownFourComponents(fColor);
26         coverage->setKnownSingleComponent(0xff);
27     }
28 
fillType()29     GrPathRendering::FillType fillType() const { return fFillType; }
30 
setStencilSettings(const GrStencilSettings & stencil)31     void setStencilSettings(const GrStencilSettings& stencil) { fStencilSettings = stencil; }
32 
33 protected:
GrDrawPathBatchBase(uint32_t classID,const SkMatrix & viewMatrix,GrColor initialColor,GrPathRendering::FillType fill)34     GrDrawPathBatchBase(uint32_t classID, const SkMatrix& viewMatrix, GrColor initialColor,
35                         GrPathRendering::FillType fill)
36         : INHERITED(classID)
37         , fViewMatrix(viewMatrix)
38         , fColor(initialColor)
39         , fFillType(fill) {}
40 
stencilSettings()41     const GrStencilSettings& stencilSettings() const { return fStencilSettings; }
overrides()42     const GrXPOverridesForBatch& overrides() const { return fOverrides; }
viewMatrix()43     const SkMatrix& viewMatrix() const { return fViewMatrix; }
color()44     GrColor color() const { return fColor; }
45 
46 private:
initBatchTracker(const GrXPOverridesForBatch & overrides)47     void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
48         overrides.getOverrideColorIfSet(&fColor);
49         fOverrides = overrides;
50     }
51 
52     SkMatrix                                                fViewMatrix;
53     GrColor                                                 fColor;
54     GrPathRendering::FillType                               fFillType;
55     GrStencilSettings                                       fStencilSettings;
56     GrXPOverridesForBatch                                   fOverrides;
57 
58     typedef GrDrawBatch INHERITED;
59 };
60 
61 class GrDrawPathBatch final : public GrDrawPathBatchBase {
62 public:
63     DEFINE_BATCH_CLASS_ID
64 
65     // This can't return a more abstract type because we install the stencil settings late :(
Create(const SkMatrix & viewMatrix,GrColor color,GrPathRendering::FillType fill,const GrPath * path)66     static GrDrawPathBatchBase* Create(const SkMatrix& viewMatrix, GrColor color,
67                                        GrPathRendering::FillType fill, const GrPath* path) {
68         return new GrDrawPathBatch(viewMatrix, color, fill, path);
69     }
70 
name()71     const char* name() const override { return "DrawPath"; }
72 
73     SkString dumpInfo() const override;
74 
75 private:
GrDrawPathBatch(const SkMatrix & viewMatrix,GrColor color,GrPathRendering::FillType fill,const GrPath * path)76     GrDrawPathBatch(const SkMatrix& viewMatrix, GrColor color, GrPathRendering::FillType fill,
77                     const GrPath* path)
78         : INHERITED(ClassID(), viewMatrix, color, fill)
79         , fPath(path) {
80         fBounds = path->getBounds();
81         viewMatrix.mapRect(&fBounds);
82     }
83 
onCombineIfPossible(GrBatch * t,const GrCaps & caps)84     bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { return false; }
85 
onPrepare(GrBatchFlushState *)86     void onPrepare(GrBatchFlushState*) override {}
87 
88     void onDraw(GrBatchFlushState* state) override;
89 
90     GrPendingIOResource<const GrPath, kRead_GrIOType> fPath;
91 
92     typedef GrDrawPathBatchBase INHERITED;
93 };
94 
95 // Template this if we decide to support index types other than 16bit
96 class GrDrawPathRangeBatch final : public GrDrawPathBatchBase {
97 public:
98     typedef GrPathRendering::PathTransformType TransformType;
99 
100     DEFINE_BATCH_CLASS_ID
101 
102     struct InstanceData : public SkNoncopyable {
103     public:
AllocInstanceData104         static InstanceData* Alloc(TransformType transformType, int reserveCnt) {
105             int transformSize = GrPathRendering::PathTransformSize(transformType);
106             uint8_t* ptr = (uint8_t*)sk_malloc_throw(Align32(sizeof(InstanceData)) +
107                                                      Align32(reserveCnt * sizeof(uint16_t)) +
108                                                      reserveCnt * transformSize * sizeof(float));
109             InstanceData* instanceData = (InstanceData*)ptr;
110             instanceData->fIndices = (uint16_t*)&ptr[Align32(sizeof(InstanceData))];
111             instanceData->fTransformValues = (float*)&ptr[Align32(sizeof(InstanceData)) +
112                                                           Align32(reserveCnt * sizeof(uint16_t))];
113             instanceData->fTransformType = transformType;
114             instanceData->fInstanceCount = 0;
115             instanceData->fRefCnt = 1;
116             SkDEBUGCODE(instanceData->fReserveCnt = reserveCnt;)
117             return instanceData;
118         }
119 
120         // Overload this method if we start using other transform types.
appendInstanceData121         void append(uint16_t index, float x, float y) {
122             SkASSERT(GrPathRendering::kTranslate_PathTransformType == fTransformType);
123             SkASSERT(fInstanceCount < fReserveCnt);
124             fIndices[fInstanceCount] = index;
125             fTransformValues[2 * fInstanceCount] = x;
126             fTransformValues[2 * fInstanceCount + 1] = y;
127             ++fInstanceCount;
128         }
129 
transformTypeInstanceData130         TransformType transformType() const { return fTransformType; }
countInstanceData131         int count() const { return fInstanceCount; }
132 
indicesInstanceData133         const uint16_t* indices() const { return fIndices; }
indicesInstanceData134         uint16_t* indices() { return fIndices; }
135 
transformValuesInstanceData136         const float* transformValues() const { return fTransformValues; }
transformValuesInstanceData137         float* transformValues() { return fTransformValues; }
138 
refInstanceData139         void ref() const { ++fRefCnt; }
140 
unrefInstanceData141         void unref() const {
142             if (0 == --fRefCnt) {
143                 sk_free(const_cast<InstanceData*>(this));
144             }
145         }
146 
147     private:
Align32InstanceData148         static int Align32(int sizeInBytes) { return (sizeInBytes + 3) & ~3; }
149 
InstanceDataInstanceData150         InstanceData() {}
~InstanceDataInstanceData151         ~InstanceData() {}
152 
153         uint16_t*       fIndices;
154         float*          fTransformValues;
155         TransformType   fTransformType;
156         int             fInstanceCount;
157         mutable int     fRefCnt;
158         SkDEBUGCODE(int fReserveCnt;)
159     };
160 
161     // This can't return a more abstract type because we install the stencil settings late :(
Create(const SkMatrix & viewMatrix,SkScalar scale,SkScalar x,SkScalar y,GrColor color,GrPathRendering::FillType fill,GrPathRange * range,const InstanceData * instanceData,const SkRect & bounds)162     static GrDrawPathBatchBase* Create(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x,
163                                        SkScalar y, GrColor color, GrPathRendering::FillType fill,
164                                        GrPathRange* range, const InstanceData* instanceData,
165                                        const SkRect& bounds) {
166         return new GrDrawPathRangeBatch(viewMatrix, scale, x, y, color, fill, range, instanceData,
167                                         bounds);
168     }
169 
name()170     const char* name() const override { return "DrawPathRange"; }
171 
172     SkString dumpInfo() const override;
173 
174 private:
175     GrDrawPathRangeBatch(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x, SkScalar y,
176                          GrColor color, GrPathRendering::FillType fill, GrPathRange* range,
177                          const InstanceData* instanceData, const SkRect& bounds);
178 
transformType()179     TransformType transformType() const { return fDraws.head()->fInstanceData->transformType(); }
180 
181     bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override;
182 
onPrepare(GrBatchFlushState *)183     void onPrepare(GrBatchFlushState*) override {}
184 
185     void onDraw(GrBatchFlushState* state) override;
186 
187     struct Draw {
setDraw188         void set(const InstanceData* instanceData, SkScalar x, SkScalar y) {
189             fInstanceData.reset(SkRef(instanceData));
190             fX = x;
191             fY = y;
192         }
193 
194         SkAutoTUnref<const InstanceData>    fInstanceData;
195         SkScalar                            fX, fY;
196     };
197 
198     typedef GrPendingIOResource<const GrPathRange, kRead_GrIOType> PendingPathRange;
199     typedef SkTLList<Draw, 4> DrawList;
200 
201     PendingPathRange    fPathRange;
202     DrawList            fDraws;
203     int                 fTotalPathCount;
204     SkScalar            fScale;
205 
206     typedef GrDrawPathBatchBase INHERITED;
207 };
208 
209 #endif
210