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 GrMeshDrawOp_DEFINED
9 #define GrMeshDrawOp_DEFINED
10 
11 #include "src/core/SkArenaAlloc.h"
12 #include "src/gpu/GrAppliedClip.h"
13 #include "src/gpu/GrGeometryProcessor.h"
14 #include "src/gpu/GrSimpleMesh.h"
15 #include "src/gpu/ops/GrDrawOp.h"
16 #include <type_traits>
17 
18 class GrAtlasManager;
19 class GrCaps;
20 class GrStrikeCache;
21 class GrOpFlushState;
22 class GrSmallPathAtlasMgr;
23 
24 /**
25  * Base class for mesh-drawing GrDrawOps.
26  */
27 class GrMeshDrawOp : public GrDrawOp {
28 public:
29     /** Abstract interface that represents a destination for a GrMeshDrawOp. */
30     class Target;
31 
CanUpgradeAAOnMerge(GrAAType aa1,GrAAType aa2)32     static bool CanUpgradeAAOnMerge(GrAAType aa1, GrAAType aa2) {
33         return (aa1 == GrAAType::kNone && aa2 == GrAAType::kCoverage) ||
34                (aa1 == GrAAType::kCoverage && aa2 == GrAAType::kNone);
35     }
36 
37 protected:
38     GrMeshDrawOp(uint32_t classID);
39 
createProgramInfo(const GrCaps * caps,SkArenaAlloc * arena,const GrSurfaceProxyView * writeView,GrAppliedClip && appliedClip,const GrXferProcessor::DstProxyView & dstProxyView,GrXferBarrierFlags renderPassXferBarriers)40     void createProgramInfo(const GrCaps* caps,
41                            SkArenaAlloc* arena,
42                            const GrSurfaceProxyView* writeView,
43                            GrAppliedClip&& appliedClip,
44                            const GrXferProcessor::DstProxyView& dstProxyView,
45                            GrXferBarrierFlags renderPassXferBarriers) {
46         this->onCreateProgramInfo(caps, arena, writeView, std::move(appliedClip), dstProxyView,
47                                   renderPassXferBarriers);
48     }
49 
50     void createProgramInfo(Target* target);
51 
52     /** Helper for rendering repeating meshes using a patterned index buffer. This class creates the
53         space for the vertices and flushes the draws to the GrMeshDrawOp::Target. */
54     class PatternHelper {
55     public:
56         PatternHelper(Target*, GrPrimitiveType, size_t vertexStride,
57                       sk_sp<const GrBuffer> indexBuffer, int verticesPerRepetition,
58                       int indicesPerRepetition, int repeatCount, int maxRepetitions);
59 
60         /** Called to issue draws to the GrMeshDrawOp::Target.*/
61         void recordDraw(Target*, const GrGeometryProcessor*) const;
62         void recordDraw(Target*, const GrGeometryProcessor*,
63                         const GrSurfaceProxy* const primProcProxies[]) const;
64 
vertices()65         void* vertices() const { return fVertices; }
mesh()66         GrSimpleMesh* mesh() { return fMesh; }
67 
68     protected:
69         PatternHelper() = default;
70         void init(Target*, GrPrimitiveType, size_t vertexStride, sk_sp<const GrBuffer> indexBuffer,
71                   int verticesPerRepetition, int indicesPerRepetition, int repeatCount,
72                   int maxRepetitions);
73 
74     private:
75         void* fVertices = nullptr;
76         GrSimpleMesh* fMesh = nullptr;
77         GrPrimitiveType fPrimitiveType;
78     };
79 
80     /** A specialization of InstanceHelper for quad rendering.
81      *  It only draws non-antialiased indexed quads.
82      */
83     class QuadHelper : private PatternHelper {
84     public:
85         QuadHelper() = delete;
86         QuadHelper(Target* target, size_t vertexStride, int quadsToDraw);
87 
88         using PatternHelper::mesh;
89         using PatternHelper::recordDraw;
90         using PatternHelper::vertices;
91 
92     private:
93         using INHERITED = PatternHelper;
94     };
95 
CombinedQuadCountWillOverflow(GrAAType aaType,bool willBeUpgradedToAA,int combinedQuadCount)96     static bool CombinedQuadCountWillOverflow(GrAAType aaType,
97                                               bool willBeUpgradedToAA,
98                                               int combinedQuadCount) {
99         bool willBeAA = (aaType == GrAAType::kCoverage) || willBeUpgradedToAA;
100 
101         return combinedQuadCount > (willBeAA ? GrResourceProvider::MaxNumAAQuads()
102                                              : GrResourceProvider::MaxNumNonAAQuads());
103     }
104 
105     virtual void onPrePrepareDraws(GrRecordingContext*,
106                                    const GrSurfaceProxyView* writeView,
107                                    GrAppliedClip*,
108                                    const GrXferProcessor::DstProxyView&,
109                                    GrXferBarrierFlags renderPassXferBarriers);
110 
111 private:
112     virtual GrProgramInfo* programInfo() = 0;
113     // This method is responsible for creating all the programInfos required
114     // by this op.
115     virtual void onCreateProgramInfo(const GrCaps*,
116                                      SkArenaAlloc*,
117                                      const GrSurfaceProxyView* writeView,
118                                      GrAppliedClip&&,
119                                      const GrXferProcessor::DstProxyView&,
120                                      GrXferBarrierFlags renderPassXferBarriers) = 0;
121 
onPrePrepare(GrRecordingContext * context,const GrSurfaceProxyView * writeView,GrAppliedClip * clip,const GrXferProcessor::DstProxyView & dstProxyView,GrXferBarrierFlags renderPassXferBarriers)122     void onPrePrepare(GrRecordingContext* context,
123                       const GrSurfaceProxyView* writeView,
124                       GrAppliedClip* clip,
125                       const GrXferProcessor::DstProxyView& dstProxyView,
126                       GrXferBarrierFlags renderPassXferBarriers) final {
127         this->onPrePrepareDraws(context, writeView, clip, dstProxyView, renderPassXferBarriers);
128     }
129     void onPrepare(GrOpFlushState* state) final;
130 
131     virtual void onPrepareDraws(Target*) = 0;
132     using INHERITED = GrDrawOp;
133 };
134 
135 class GrMeshDrawOp::Target {
136 public:
~Target()137     virtual ~Target() {}
138 
139     /** Adds a draw of a mesh. 'primProcProxies' must have
140      * GrPrimitiveProcessor::numTextureSamplers() entries. Can be null if no samplers.
141      */
142     virtual void recordDraw(const GrGeometryProcessor*,
143                             const GrSimpleMesh[],
144                             int meshCnt,
145                             const GrSurfaceProxy* const primProcProxies[],
146                             GrPrimitiveType) = 0;
147 
148     /**
149      * Helper for drawing GrSimpleMesh(es) with zero primProc textures.
150      */
recordDraw(const GrGeometryProcessor * gp,const GrSimpleMesh meshes[],int meshCnt,GrPrimitiveType primitiveType)151     void recordDraw(const GrGeometryProcessor* gp,
152                     const GrSimpleMesh meshes[],
153                     int meshCnt,
154                     GrPrimitiveType primitiveType) {
155         this->recordDraw(gp, meshes, meshCnt, nullptr, primitiveType);
156     }
157 
158     /**
159      * Makes space for vertex data. The returned pointer is the location where vertex data
160      * should be written. On return the buffer that will hold the data as well as an offset into
161      * the buffer (in 'vertexSize' units) where the data will be placed.
162      */
163     virtual void* makeVertexSpace(size_t vertexSize, int vertexCount, sk_sp<const GrBuffer>*,
164                                   int* startVertex) = 0;
165 
166     /**
167      * Makes space for index data. The returned pointer is the location where index data
168      * should be written. On return the buffer that will hold the data as well as an offset into
169      * the buffer (in uint16_t units) where the data will be placed.
170      */
171     virtual uint16_t* makeIndexSpace(int indexCount, sk_sp<const GrBuffer>*, int* startIndex) = 0;
172 
173     /**
174      * This is similar to makeVertexSpace. It allows the caller to use up to 'actualVertexCount'
175      * vertices in the returned pointer, which may exceed 'minVertexCount'.
176      * 'fallbackVertexCount' is the maximum number of vertices that should be allocated if a new
177      * buffer is allocated on behalf of this request.
178      */
179     virtual void* makeVertexSpaceAtLeast(size_t vertexSize, int minVertexCount,
180                                          int fallbackVertexCount, sk_sp<const GrBuffer>*,
181                                          int* startVertex, int* actualVertexCount) = 0;
182 
183     /**
184      * This is similar to makeIndexSpace. It allows the caller to use up to 'actualIndexCount'
185      * indices in the returned pointer, which may exceed 'minIndexCount'.
186      * 'fallbackIndexCount' is the maximum number of indices that should be allocated if a new
187      * buffer is allocated on behalf of this request.
188      */
189     virtual uint16_t* makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount,
190                                             sk_sp<const GrBuffer>*, int* startIndex,
191                                             int* actualIndexCount) = 0;
192 
193     /**
194      * Makes space for elements in a draw-indirect buffer. Upon success, the returned pointer is a
195      * CPU mapping where the data should be written.
196      */
197     virtual GrDrawIndirectCommand* makeDrawIndirectSpace(int drawCount,
198                                                          sk_sp<const GrBuffer>* buffer,
199                                                          size_t* offsetInBytes) = 0;
200 
201     /**
202      * Makes space for elements in a draw-indexed-indirect buffer. Upon success, the returned
203      * pointer is a CPU mapping where the data should be written.
204      */
205     virtual GrDrawIndexedIndirectCommand* makeDrawIndexedIndirectSpace(
206             int drawCount, sk_sp<const GrBuffer>* buffer, size_t* offsetInBytes) = 0;
207 
208     /** Helpers for ops which over-allocate and then return excess data to the pool. */
209     virtual void putBackIndices(int indices) = 0;
210     virtual void putBackVertices(int vertices, size_t vertexStride) = 0;
211 
allocMesh()212     GrSimpleMesh* allocMesh() { return this->allocator()->make<GrSimpleMesh>(); }
allocMeshes(int n)213     GrSimpleMesh* allocMeshes(int n) { return this->allocator()->makeArray<GrSimpleMesh>(n); }
allocPrimProcProxyPtrs(int n)214     const GrSurfaceProxy** allocPrimProcProxyPtrs(int n) {
215         return this->allocator()->makeArray<const GrSurfaceProxy*>(n);
216     }
217 
218     virtual GrRenderTargetProxy* proxy() const = 0;
219     virtual const GrSurfaceProxyView* writeView() const = 0;
220 
221     virtual const GrAppliedClip* appliedClip() const = 0;
222     virtual GrAppliedClip detachAppliedClip() = 0;
223 
224     virtual const GrXferProcessor::DstProxyView& dstProxyView() const = 0;
225 
226     virtual GrXferBarrierFlags renderPassBarriers() const = 0;
227 
228     virtual GrThreadSafeCache* threadSafeCache() const = 0;
229     virtual GrResourceProvider* resourceProvider() const = 0;
contextUniqueID()230     uint32_t contextUniqueID() const { return this->resourceProvider()->contextUniqueID(); }
231 
232     virtual GrStrikeCache* strikeCache() const = 0;
233     virtual GrAtlasManager* atlasManager() const = 0;
234     virtual GrSmallPathAtlasMgr* smallPathAtlasManager() const = 0;
235 
236     // This should be called during onPrepare of a GrOp. The caller should add any proxies to the
237     // array it will use that it did not access during a call to visitProxies. This is usually the
238     // case for atlases.
239     virtual SkTArray<GrSurfaceProxy*, true>* sampledProxyArray() = 0;
240 
241     virtual const GrCaps& caps() const = 0;
242 
243     virtual GrDeferredUploadTarget* deferredUploadTarget() = 0;
244 
245     virtual SkArenaAlloc* allocator() = 0;
246 };
247 
248 #endif
249