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
22class GrPaint;
23
24class GrDrawPathOpBase : public GrDrawOp {
25protected:
26    GrDrawPathOpBase(uint32_t classID, const SkMatrix& viewMatrix, GrPaint&& paint,
27                     GrPathRendering::FillType fill, GrAA aa);
28    FixedFunctionFlags fixedFunctionFlags() const override {
29        return FixedFunctionFlags::kUsesHWAA | FixedFunctionFlags::kUsesStencil;
30    }
31    bool xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip) override {
32        return GrXPFactory::WillNeedDstTexture(fProcessorSet.xpFactory(), caps,
33                                               this->doFragmentProcessorAnalysis(caps, clip));
34    }
35
36    void wasRecorded() override { fProcessorSet.makePendingExecution(); }
37
38protected:
39    const SkMatrix& viewMatrix() const { return fViewMatrix; }
40    GrColor color() const { return fAnalysis.inputColor(); }
41    GrPathRendering::FillType fillType() const { return fFillType; }
42    const GrProcessorSet& processors() const { return fProcessorSet; }
43    GrPipelineOptimizations initPipeline(const GrOpFlushState&, GrPipeline*);
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    }
50    const GrProcessorSet::FragmentProcessorAnalysis& fragmentProcessorAnalysis() const {
51        SkASSERT(fAnalysis.isInitializedWithProcessorSet());
52        return fAnalysis;
53    }
54
55private:
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
67class GrDrawPathOp final : public GrDrawPathOpBase {
68public:
69    DEFINE_OP_CLASS_ID
70
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
76    const char* name() const override { return "DrawPath"; }
77
78    SkString dumpInfo() const override;
79
80private:
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
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
97class GrDrawPathRangeOp final : public GrDrawPathOpBase {
98public:
99    typedef GrPathRendering::PathTransformType TransformType;
100
101    DEFINE_OP_CLASS_ID
102
103    struct InstanceData : private ::SkNoncopyable {
104    public:
105        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.
122        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
131        TransformType transformType() const { return fTransformType; }
132        int count() const { return fInstanceCount; }
133
134        const uint16_t* indices() const { return fIndices; }
135        uint16_t* indices() { return fIndices; }
136
137        const float* transformValues() const { return fTransformValues; }
138        float* transformValues() { return fTransformValues; }
139
140        void ref() const { ++fRefCnt; }
141
142        void unref() const {
143            if (0 == --fRefCnt) {
144                sk_free(const_cast<InstanceData*>(this));
145            }
146        }
147
148    private:
149        static int Align32(int sizeInBytes) { return (sizeInBytes + 3) & ~3; }
150
151        InstanceData() {}
152        ~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
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
171    const char* name() const override { return "DrawPathRange"; }
172
173    SkString dumpInfo() const override;
174
175private:
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
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 {
187        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