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 "GrAppliedClip.h" 12 #include "GrDrawOp.h" 13 #include "GrGeometryProcessor.h" 14 #include "GrMesh.h" 15 #include <type_traits> 16 17 class GrAtlasManager; 18 class GrCaps; 19 class GrStrikeCache; 20 class GrOpFlushState; 21 22 /** 23 * Base class for mesh-drawing GrDrawOps. 24 */ 25 class GrMeshDrawOp : public GrDrawOp { 26 public: 27 /** Abstract interface that represents a destination for a GrMeshDrawOp. */ 28 class Target; 29 30 protected: 31 GrMeshDrawOp(uint32_t classID); 32 33 /** Helper for rendering repeating meshes using a patterned index buffer. This class creates the 34 space for the vertices and flushes the draws to the GrMeshDrawOp::Target. */ 35 class PatternHelper { 36 public: 37 PatternHelper(Target*, GrPrimitiveType, size_t vertexStride, sk_sp<const GrBuffer>, 38 int verticesPerRepetition, int indicesPerRepetition, int repeatCount); 39 40 /** Called to issue draws to the GrMeshDrawOp::Target.*/ 41 void recordDraw(Target*, sk_sp<const GrGeometryProcessor>, const GrPipeline*, 42 const GrPipeline::FixedDynamicState*) const; 43 vertices()44 void* vertices() const { return fVertices; } 45 46 protected: 47 PatternHelper() = default; 48 void init(Target*, GrPrimitiveType, size_t vertexStride, sk_sp<const GrBuffer>, 49 int verticesPerRepetition, int indicesPerRepetition, int repeatCount); 50 51 private: 52 void* fVertices = nullptr; 53 GrMesh* fMesh = nullptr; 54 }; 55 56 static const int kVerticesPerQuad = 4; 57 static const int kIndicesPerQuad = 6; 58 59 /** A specialization of InstanceHelper for quad rendering. */ 60 class QuadHelper : private PatternHelper { 61 public: 62 QuadHelper() = delete; 63 QuadHelper(Target* target, size_t vertexStride, int quadsToDraw); 64 65 using PatternHelper::recordDraw; 66 using PatternHelper::vertices; 67 68 private: 69 typedef PatternHelper INHERITED; 70 }; 71 72 private: 73 void onPrepare(GrOpFlushState* state) final; 74 void onExecute(GrOpFlushState* state, const SkRect& chainBounds) final; 75 virtual void onPrepareDraws(Target*) = 0; 76 typedef GrDrawOp INHERITED; 77 }; 78 79 class GrMeshDrawOp::Target { 80 public: ~Target()81 virtual ~Target() {} 82 83 /** Adds a draw of a mesh. */ 84 virtual void draw(sk_sp<const GrGeometryProcessor>, 85 const GrPipeline*, 86 const GrPipeline::FixedDynamicState*, 87 const GrPipeline::DynamicStateArrays*, 88 const GrMesh[], 89 int meshCount) = 0; 90 /** Helper for drawing a single GrMesh. */ draw(sk_sp<const GrGeometryProcessor> gp,const GrPipeline * pipeline,const GrPipeline::FixedDynamicState * fixedDynamicState,const GrMesh * mesh)91 void draw(sk_sp<const GrGeometryProcessor> gp, 92 const GrPipeline* pipeline, 93 const GrPipeline::FixedDynamicState* fixedDynamicState, 94 const GrMesh* mesh) { 95 this->draw(std::move(gp), pipeline, fixedDynamicState, nullptr, mesh, 1); 96 } 97 98 /** 99 * Makes space for vertex data. The returned pointer is the location where vertex data 100 * should be written. On return the buffer that will hold the data as well as an offset into 101 * the buffer (in 'vertexSize' units) where the data will be placed. 102 */ 103 virtual void* makeVertexSpace(size_t vertexSize, int vertexCount, sk_sp<const GrBuffer>*, 104 int* startVertex) = 0; 105 106 /** 107 * Makes space for index data. The returned pointer is the location where index data 108 * should be written. On return the buffer that will hold the data as well as an offset into 109 * the buffer (in uint16_t units) where the data will be placed. 110 */ 111 virtual uint16_t* makeIndexSpace(int indexCount, sk_sp<const GrBuffer>*, int* startIndex) = 0; 112 113 /** 114 * This is similar to makeVertexSpace. It allows the caller to use up to 'actualVertexCount' 115 * vertices in the returned pointer, which may exceed 'minVertexCount'. 116 * 'fallbackVertexCount' is the maximum number of vertices that should be allocated if a new 117 * buffer is allocated on behalf of this request. 118 */ 119 virtual void* makeVertexSpaceAtLeast(size_t vertexSize, int minVertexCount, 120 int fallbackVertexCount, sk_sp<const GrBuffer>*, 121 int* startVertex, int* actualVertexCount) = 0; 122 123 /** 124 * This is similar to makeIndexSpace. It allows the caller to use up to 'actualIndexCount' 125 * indices in the returned pointer, which may exceed 'minIndexCount'. 126 * 'fallbackIndexCount' is the maximum number of indices that should be allocated if a new 127 * buffer is allocated on behalf of this request. 128 */ 129 virtual uint16_t* makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount, 130 sk_sp<const GrBuffer>*, int* startIndex, 131 int* actualIndexCount) = 0; 132 133 /** Helpers for ops which over-allocate and then return excess data to the pool. */ 134 virtual void putBackIndices(int indices) = 0; 135 virtual void putBackVertices(int vertices, size_t vertexStride) = 0; 136 137 /** 138 * Allocate space for a pipeline. The target ensures this pipeline lifetime is at least 139 * as long as any deferred execution of draws added via draw(). 140 * @tparam Args 141 * @param args 142 * @return 143 */ 144 template <typename... Args> allocPipeline(Args &&...args)145 GrPipeline* allocPipeline(Args&&... args) { 146 return this->pipelineArena()->make<GrPipeline>(std::forward<Args>(args)...); 147 } 148 allocMesh(GrPrimitiveType primitiveType)149 GrMesh* allocMesh(GrPrimitiveType primitiveType) { 150 return this->pipelineArena()->make<GrMesh>(primitiveType); 151 } 152 allocMeshes(int n)153 GrMesh* allocMeshes(int n) { return this->pipelineArena()->makeArray<GrMesh>(n); } 154 155 GrPipeline::FixedDynamicState* allocFixedDynamicState(const SkIRect& rect, 156 int numPrimitiveProcessorTextures = 0); 157 158 GrPipeline::DynamicStateArrays* allocDynamicStateArrays(int numMeshes, 159 int numPrimitiveProcessorTextures, 160 bool allocScissors); 161 allocPrimitiveProcessorTextureArray(int n)162 GrTextureProxy** allocPrimitiveProcessorTextureArray(int n) { 163 SkASSERT(n > 0); 164 return this->pipelineArena()->makeArrayDefault<GrTextureProxy*>(n); 165 } 166 167 // Once we have C++17 structured bindings make this just be a tuple because then we can do: 168 // auto [pipeline, fixedDynamicState] = target->makePipeline(...); 169 // in addition to: 170 // std::tie(flushInfo.fPipeline, flushInfo.fFixedState) = target->makePipeline(...); 171 struct PipelineAndFixedDynamicState { 172 const GrPipeline* fPipeline; 173 GrPipeline::FixedDynamicState* fFixedDynamicState; 174 }; 175 176 /** 177 * Helper that makes a pipeline targeting the op's render target that incorporates the op's 178 * GrAppliedClip and uses a fixed dynamic state. 179 */ 180 PipelineAndFixedDynamicState makePipeline(uint32_t pipelineFlags, GrProcessorSet&&, 181 GrAppliedClip&&, 182 int numPrimitiveProcessorTextures = 0); 183 184 virtual GrRenderTargetProxy* proxy() const = 0; 185 186 virtual GrAppliedClip detachAppliedClip() = 0; 187 188 virtual const GrXferProcessor::DstProxy& dstProxy() const = 0; 189 190 virtual GrResourceProvider* resourceProvider() const = 0; contextUniqueID()191 uint32_t contextUniqueID() const { return this->resourceProvider()->contextUniqueID(); } 192 193 virtual GrStrikeCache* glyphCache() const = 0; 194 virtual GrAtlasManager* atlasManager() const = 0; 195 196 virtual const GrCaps& caps() const = 0; 197 198 virtual GrDeferredUploadTarget* deferredUploadTarget() = 0; 199 200 private: 201 virtual SkArenaAlloc* pipelineArena() = 0; 202 }; 203 204 #endif 205