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 GrDrawPathOp_DEFINED
9 #define GrDrawPathOp_DEFINED
10 
11 #include "GrDrawOp.h"
12 #include "GrGpu.h"
13 #include "GrOpFlushState.h"
14 #include "GrPath.h"
15 #include "GrPathProcessor.h"
16 #include "GrPathRendering.h"
17 #include "GrProcessorSet.h"
18 #include "GrStencilSettings.h"
19 
20 #include "SkTLList.h"
21 
22 class GrPaint;
23 
24 class GrDrawPathOpBase : public GrDrawOp {
25 protected:
26     GrDrawPathOpBase(uint32_t classID, const SkMatrix& viewMatrix, GrPaint&& paint,
27                      GrPathRendering::FillType fill, GrAA aa);
fixedFunctionFlags()28     FixedFunctionFlags fixedFunctionFlags() const override {
29         return FixedFunctionFlags::kUsesHWAA | FixedFunctionFlags::kUsesStencil;
30     }
xpRequiresDstTexture(const GrCaps & caps,const GrAppliedClip * clip)31     bool xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip) override {
32         return GrXPFactory::WillNeedDstTexture(fProcessorSet.xpFactory(), caps,
33                                                this->doFragmentProcessorAnalysis(caps, clip));
34     }
35 
wasRecorded()36     void wasRecorded() override { fProcessorSet.makePendingExecution(); }
37 
38 protected:
viewMatrix()39     const SkMatrix& viewMatrix() const { return fViewMatrix; }
color()40     GrColor color() const { return fAnalysis.inputColor(); }
fillType()41     GrPathRendering::FillType fillType() const { return fFillType; }
processors()42     const GrProcessorSet& processors() const { return fProcessorSet; }
43     GrPipelineOptimizations initPipeline(const GrOpFlushState&, GrPipeline*);
doFragmentProcessorAnalysis(const GrCaps & caps,const GrAppliedClip * clip)44     const GrProcessorSet::FragmentProcessorAnalysis& doFragmentProcessorAnalysis(
45             const GrCaps& caps, const GrAppliedClip* clip) {
46         fProcessorSet.analyzeAndEliminateFragmentProcessors(
47                 &fAnalysis, fAnalysis.inputColor(), GrPipelineAnalysisCoverage::kNone, clip, caps);
48         return fAnalysis;
49     }
fragmentProcessorAnalysis()50     const GrProcessorSet::FragmentProcessorAnalysis& fragmentProcessorAnalysis() const {
51         SkASSERT(fAnalysis.isInitializedWithProcessorSet());
52         return fAnalysis;
53     }
54 
55 private:
onPrepare(GrOpFlushState *)56     void onPrepare(GrOpFlushState*) final {}
57 
58     SkMatrix fViewMatrix;
59     GrProcessorSet fProcessorSet;
60     GrProcessorSet::FragmentProcessorAnalysis fAnalysis;
61     GrPathRendering::FillType fFillType;
62     GrAA fAA;
63 
64     typedef GrDrawOp INHERITED;
65 };
66 
67 class GrDrawPathOp final : public GrDrawPathOpBase {
68 public:
69     DEFINE_OP_CLASS_ID
70 
Make(const SkMatrix & viewMatrix,GrPaint && paint,GrAA aa,GrPath * path)71     static std::unique_ptr<GrDrawOp> Make(const SkMatrix& viewMatrix, GrPaint&& paint, GrAA aa,
72                                           GrPath* path) {
73         return std::unique_ptr<GrDrawOp>(new GrDrawPathOp(viewMatrix, std::move(paint), aa, path));
74     }
75 
name()76     const char* name() const override { return "DrawPath"; }
77 
78     SkString dumpInfo() const override;
79 
80 private:
GrDrawPathOp(const SkMatrix & viewMatrix,GrPaint && paint,GrAA aa,const GrPath * path)81     GrDrawPathOp(const SkMatrix& viewMatrix, GrPaint&& paint, GrAA aa, const GrPath* path)
82             : GrDrawPathOpBase(ClassID(), viewMatrix, std::move(paint), path->getFillType(), aa)
83             , fPath(path) {
84         this->setTransformedBounds(path->getBounds(), viewMatrix, HasAABloat::kNo, IsZeroArea::kNo);
85     }
86 
onCombineIfPossible(GrOp * t,const GrCaps & caps)87     bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { return false; }
88 
89     void onExecute(GrOpFlushState* state) override;
90 
91     GrPendingIOResource<const GrPath, kRead_GrIOType> fPath;
92 
93     typedef GrDrawPathOpBase INHERITED;
94 };
95 
96 // Template this if we decide to support index types other than 16bit
97 class GrDrawPathRangeOp final : public GrDrawPathOpBase {
98 public:
99     typedef GrPathRendering::PathTransformType TransformType;
100 
101     DEFINE_OP_CLASS_ID
102 
103     struct InstanceData : private ::SkNoncopyable {
104     public:
AllocInstanceData105         static InstanceData* Alloc(TransformType transformType, int reserveCnt) {
106             int transformSize = GrPathRendering::PathTransformSize(transformType);
107             uint8_t* ptr = (uint8_t*)sk_malloc_throw(Align32(sizeof(InstanceData)) +
108                                                      Align32(reserveCnt * sizeof(uint16_t)) +
109                                                      reserveCnt * transformSize * sizeof(float));
110             InstanceData* instanceData = (InstanceData*)ptr;
111             instanceData->fIndices = (uint16_t*)&ptr[Align32(sizeof(InstanceData))];
112             instanceData->fTransformValues = (float*)&ptr[Align32(sizeof(InstanceData)) +
113                                                           Align32(reserveCnt * sizeof(uint16_t))];
114             instanceData->fTransformType = transformType;
115             instanceData->fInstanceCount = 0;
116             instanceData->fRefCnt = 1;
117             SkDEBUGCODE(instanceData->fReserveCnt = reserveCnt);
118             return instanceData;
119         }
120 
121         // Overload this method if we start using other transform types.
appendInstanceData122         void append(uint16_t index, float x, float y) {
123             SkASSERT(GrPathRendering::kTranslate_PathTransformType == fTransformType);
124             SkASSERT(fInstanceCount < fReserveCnt);
125             fIndices[fInstanceCount] = index;
126             fTransformValues[2 * fInstanceCount] = x;
127             fTransformValues[2 * fInstanceCount + 1] = y;
128             ++fInstanceCount;
129         }
130 
transformTypeInstanceData131         TransformType transformType() const { return fTransformType; }
countInstanceData132         int count() const { return fInstanceCount; }
133 
indicesInstanceData134         const uint16_t* indices() const { return fIndices; }
indicesInstanceData135         uint16_t* indices() { return fIndices; }
136 
transformValuesInstanceData137         const float* transformValues() const { return fTransformValues; }
transformValuesInstanceData138         float* transformValues() { return fTransformValues; }
139 
refInstanceData140         void ref() const { ++fRefCnt; }
141 
unrefInstanceData142         void unref() const {
143             if (0 == --fRefCnt) {
144                 sk_free(const_cast<InstanceData*>(this));
145             }
146         }
147 
148     private:
Align32InstanceData149         static int Align32(int sizeInBytes) { return (sizeInBytes + 3) & ~3; }
150 
InstanceDataInstanceData151         InstanceData() {}
~InstanceDataInstanceData152         ~InstanceData() {}
153 
154         uint16_t* fIndices;
155         float* fTransformValues;
156         TransformType fTransformType;
157         int fInstanceCount;
158         mutable int fRefCnt;
159         SkDEBUGCODE(int fReserveCnt;)
160     };
161 
Make(const SkMatrix & viewMatrix,SkScalar scale,SkScalar x,SkScalar y,GrPaint && paint,GrPathRendering::FillType fill,GrAA aa,GrPathRange * range,const InstanceData * instanceData,const SkRect & bounds)162     static std::unique_ptr<GrDrawOp> Make(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x,
163                                           SkScalar y, GrPaint&& paint,
164                                           GrPathRendering::FillType fill, GrAA aa,
165                                           GrPathRange* range, const InstanceData* instanceData,
166                                           const SkRect& bounds) {
167         return std::unique_ptr<GrDrawOp>(new GrDrawPathRangeOp(
168                 viewMatrix, scale, x, y, std::move(paint), fill, aa, range, instanceData, bounds));
169     }
170 
name()171     const char* name() const override { return "DrawPathRange"; }
172 
173     SkString dumpInfo() const override;
174 
175 private:
176     GrDrawPathRangeOp(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x, SkScalar y,
177                       GrPaint&& paint, GrPathRendering::FillType fill, GrAA aa, GrPathRange* range,
178                       const InstanceData* instanceData, const SkRect& bounds);
179 
transformType()180     TransformType transformType() const { return fDraws.head()->fInstanceData->transformType(); }
181 
182     bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override;
183 
184     void onExecute(GrOpFlushState* state) override;
185 
186     struct Draw {
setDraw187         void set(const InstanceData* instanceData, SkScalar x, SkScalar y) {
188             fInstanceData.reset(SkRef(instanceData));
189             fX = x;
190             fY = y;
191         }
192 
193         sk_sp<const InstanceData> fInstanceData;
194         SkScalar fX, fY;
195     };
196 
197     typedef GrPendingIOResource<const GrPathRange, kRead_GrIOType> PendingPathRange;
198     typedef SkTLList<Draw, 4> DrawList;
199 
200     PendingPathRange fPathRange;
201     DrawList fDraws;
202     int fTotalPathCount;
203     SkScalar fScale;
204 
205     typedef GrDrawPathOpBase INHERITED;
206 };
207 
208 #endif
209