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 "GrDrawOp.h"
12 #include "GrGeometryProcessor.h"
13 #include "GrMesh.h"
14 #include "GrPendingProgramElement.h"
15 
16 #include "SkTLList.h"
17 
18 class GrAtlasManager;
19 class GrCaps;
20 class GrGlyphCache;
21 class GrOpFlushState;
22 
23 /**
24  * Base class for mesh-drawing GrDrawOps.
25  */
26 class GrMeshDrawOp : public GrDrawOp {
27 public:
28     /** Abstract interface that represents a destination for a GrMeshDrawOp. */
29     class Target;
30 
31 protected:
32     GrMeshDrawOp(uint32_t classID);
33 
34     /** Helper for rendering repeating meshes using a patterned index buffer. This class creates the
35         space for the vertices and flushes the draws to the GrMeshDrawOp::Target. */
36     class PatternHelper {
37     public:
38         PatternHelper(GrPrimitiveType primitiveType) : fMesh(primitiveType) {}
39         /** Returns the allocated storage for the vertices. The caller should populate the vertices
40             before calling recordDraws(). */
41         void* init(Target*, size_t vertexStride, const GrBuffer*, int verticesPerRepetition,
42                    int indicesPerRepetition, int repeatCount);
43 
44         /** Call after init() to issue draws to the GrMeshDrawOp::Target.*/
45         void recordDraw(Target*, const GrGeometryProcessor*, const GrPipeline*);
46 
47     private:
48         GrMesh fMesh;
49     };
50 
51     static const int kVerticesPerQuad = 4;
52     static const int kIndicesPerQuad = 6;
53 
54     /** A specialization of InstanceHelper for quad rendering. */
55     class QuadHelper : private PatternHelper {
56     public:
57         QuadHelper() : INHERITED(GrPrimitiveType::kTriangles) {}
58         /** Finds the cached quad index buffer and reserves vertex space. Returns nullptr on failure
59             and on success a pointer to the vertex data that the caller should populate before
60             calling recordDraws(). */
61         void* init(Target*, size_t vertexStride, int quadsToDraw);
62 
63         using PatternHelper::recordDraw;
64 
65     private:
66         typedef PatternHelper INHERITED;
67     };
68 
69 private:
70     void onPrepare(GrOpFlushState* state) final;
71     void onExecute(GrOpFlushState* state) final;
72     virtual void onPrepareDraws(Target*) = 0;
73     typedef GrDrawOp INHERITED;
74 };
75 
76 class GrMeshDrawOp::Target {
77 public:
78     virtual ~Target() {}
79 
80     /** Adds a draw of a mesh. */
81     virtual void draw(const GrGeometryProcessor*, const GrPipeline*, const GrMesh&) = 0;
82 
83     /**
84      * Makes space for vertex data. The returned pointer is the location where vertex data
85      * should be written. On return the buffer that will hold the data as well as an offset into
86      * the buffer (in 'vertexSize' units) where the data will be placed.
87      */
88     virtual void* makeVertexSpace(size_t vertexSize, int vertexCount, const GrBuffer**,
89                                   int* startVertex) = 0;
90 
91     /**
92      * Makes space for index data. The returned pointer is the location where index data
93      * should be written. On return the buffer that will hold the data as well as an offset into
94      * the buffer (in uint16_t units) where the data will be placed.
95      */
96     virtual uint16_t* makeIndexSpace(int indexCount, const GrBuffer**, int* startIndex) = 0;
97 
98     /**
99      * This is similar to makeVertexSpace. It allows the caller to use up to 'actualVertexCount'
100      * vertices in the returned pointer, which may exceed 'minVertexCount'.
101      * 'fallbackVertexCount' is the maximum number of vertices that should be allocated if a new
102      * buffer is allocated on behalf of this request.
103      */
104     virtual void* makeVertexSpaceAtLeast(size_t vertexSize, int minVertexCount,
105                                          int fallbackVertexCount, const GrBuffer**,
106                                          int* startVertex, int* actualVertexCount) = 0;
107 
108     /**
109      * This is similar to makeIndexSpace. It allows the caller to use up to 'actualIndexCount'
110      * indices in the returned pointer, which may exceed 'minIndexCount'.
111      * 'fallbackIndexCount' is the maximum number of indices that should be allocated if a new
112      * buffer is allocated on behalf of this request.
113      */
114     virtual uint16_t* makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount,
115                                             const GrBuffer**, int* startIndex,
116                                             int* actualIndexCount) = 0;
117 
118     /** Helpers for ops which over-allocate and then return excess data to the pool. */
119     virtual void putBackIndices(int indices) = 0;
120     virtual void putBackVertices(int vertices, size_t vertexStride) = 0;
121 
122     /**
123      * Allocate space for a pipeline. The target ensures this pipeline lifetime is at least
124      * as long as any deferred execution of draws added via draw().
125      * @tparam Args
126      * @param args
127      * @return
128      */
129     template <typename... Args>
130     GrPipeline* allocPipeline(Args&&... args) {
131         return this->pipelineArena()->make<GrPipeline>(std::forward<Args>(args)...);
132     }
133 
134     /**
135      * Helper that makes a pipeline targeting the op's render target that incorporates the op's
136      * GrAppliedClip.
137      */
138     GrPipeline* makePipeline(uint32_t pipelineFlags, GrProcessorSet&& processorSet,
139                              GrAppliedClip&& clip) {
140         GrPipeline::InitArgs pipelineArgs;
141         pipelineArgs.fFlags = pipelineFlags;
142         pipelineArgs.fProxy = this->proxy();
143         pipelineArgs.fDstProxy = this->dstProxy();
144         pipelineArgs.fCaps = &this->caps();
145         pipelineArgs.fResourceProvider = this->resourceProvider();
146         return this->allocPipeline(pipelineArgs, std::move(processorSet), std::move(clip));
147     }
148 
149     virtual GrRenderTargetProxy* proxy() const = 0;
150 
151     virtual GrAppliedClip detachAppliedClip() = 0;
152 
153     virtual const GrXferProcessor::DstProxy& dstProxy() const = 0;
154 
155     virtual GrResourceProvider* resourceProvider() const = 0;
156 
157     virtual GrGlyphCache* glyphCache() const = 0;
158     virtual GrAtlasManager* fullAtlasManager() const = 0;
159 
160     virtual const GrCaps& caps() const = 0;
161 
162     virtual GrDeferredUploadTarget* deferredUploadTarget() = 0;
163 
164 private:
165     virtual SkArenaAlloc* pipelineArena() = 0;
166 };
167 
168 #endif
169