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 GrCaps; 19 class GrOpFlushState; 20 21 /** 22 * Base class for mesh-drawing GrDrawOps. 23 */ 24 class GrMeshDrawOp : public GrDrawOp { 25 public: 26 class Target; 27 28 /** 29 * Performs analysis of the fragment processors in GrProcessorSet and GrAppliedClip using the 30 * initial color and coverage from this op's geometry processor. 31 */ analyzeProcessors(GrProcessorSet::FragmentProcessorAnalysis * analysis,const GrProcessorSet & processors,const GrAppliedClip * appliedClip,const GrCaps & caps)32 void analyzeProcessors(GrProcessorSet::FragmentProcessorAnalysis* analysis, 33 const GrProcessorSet& processors, 34 const GrAppliedClip* appliedClip, 35 const GrCaps& caps) const { 36 GrPipelineAnalysisColor inputColor; 37 GrPipelineAnalysisCoverage inputCoverage; 38 this->getFragmentProcessorAnalysisInputs(&inputColor, &inputCoverage); 39 analysis->init(inputColor, inputCoverage, processors, appliedClip, caps); 40 } 41 initPipeline(const GrPipeline::InitArgs & args)42 void initPipeline(const GrPipeline::InitArgs& args) { 43 this->applyPipelineOptimizations(fPipeline.init(args)); 44 } 45 46 /** 47 * Mesh draw ops use a legacy system in GrRenderTargetContext where the pipeline is created when 48 * the op is recorded. These methods are unnecessary as this information is in the pipeline. 49 */ fixedFunctionFlags()50 FixedFunctionFlags fixedFunctionFlags() const override { 51 SkFAIL("This should never be called for mesh draw ops."); 52 return FixedFunctionFlags::kNone; 53 } xpRequiresDstTexture(const GrCaps &,const GrAppliedClip *)54 bool xpRequiresDstTexture(const GrCaps&, const GrAppliedClip*) override { 55 SkFAIL("Should never be called for mesh draw ops."); 56 return false; 57 } 58 59 protected: 60 GrMeshDrawOp(uint32_t classID); 61 62 /** Helper for rendering instances using an instanced index index buffer. This class creates the 63 space for the vertices and flushes the draws to the GrMeshDrawOp::Target. */ 64 class InstancedHelper { 65 public: InstancedHelper()66 InstancedHelper() {} 67 /** Returns the allocated storage for the vertices. The caller should populate the vertices 68 before calling recordDraws(). */ 69 void* init(Target*, GrPrimitiveType, size_t vertexStride, const GrBuffer*, 70 int verticesPerInstance, int indicesPerInstance, int instancesToDraw); 71 72 /** Call after init() to issue draws to the GrMeshDrawOp::Target.*/ 73 void recordDraw(Target*, const GrGeometryProcessor*); 74 75 private: 76 GrMesh fMesh; 77 }; 78 79 static const int kVerticesPerQuad = 4; 80 static const int kIndicesPerQuad = 6; 81 82 /** A specialization of InstanceHelper for quad rendering. */ 83 class QuadHelper : private InstancedHelper { 84 public: QuadHelper()85 QuadHelper() : INHERITED() {} 86 /** Finds the cached quad index buffer and reserves vertex space. Returns nullptr on failure 87 and on success a pointer to the vertex data that the caller should populate before 88 calling recordDraws(). */ 89 void* init(Target*, size_t vertexStride, int quadsToDraw); 90 91 using InstancedHelper::recordDraw; 92 93 private: 94 typedef InstancedHelper INHERITED; 95 }; 96 pipeline()97 const GrPipeline* pipeline() const { 98 SkASSERT(fPipeline.isInitialized()); 99 return &fPipeline; 100 } 101 102 private: 103 /** 104 * Provides information about the GrPrimitiveProccesor color and coverage outputs which become 105 * inputs to the first color and coverage fragment processors. 106 */ 107 virtual void getFragmentProcessorAnalysisInputs(GrPipelineAnalysisColor*, 108 GrPipelineAnalysisCoverage*) const = 0; 109 110 /** 111 * After GrPipeline analysis is complete this is called so that the op can use the analysis 112 * results when constructing its GrPrimitiveProcessor. 113 */ 114 virtual void applyPipelineOptimizations(const GrPipelineOptimizations&) = 0; 115 116 void onPrepare(GrOpFlushState* state) final; 117 void onExecute(GrOpFlushState* state) final; 118 119 virtual void onPrepareDraws(Target*) const = 0; 120 121 // A set of contiguous draws that share a draw token and primitive processor. The draws all use 122 // the op's pipeline. The meshes for the draw are stored in the fMeshes array and each 123 // Queued draw uses fMeshCnt meshes from the fMeshes array. The reason for coallescing meshes 124 // that share a primitive processor into a QueuedDraw is that it allows the Gpu object to setup 125 // the shared state once and then issue draws for each mesh. 126 struct QueuedDraw { 127 int fMeshCnt = 0; 128 GrPendingProgramElement<const GrGeometryProcessor> fGeometryProcessor; 129 }; 130 131 // All draws in all the GrMeshDrawOps have implicit tokens based on the order they are enqueued 132 // globally across all ops. This is the offset of the first entry in fQueuedDraws. 133 // fQueuedDraws[i]'s token is fBaseDrawToken + i. 134 GrDrawOpUploadToken fBaseDrawToken; 135 GrPipeline fPipeline; 136 SkSTArray<4, GrMesh> fMeshes; 137 SkSTArray<4, QueuedDraw, true> fQueuedDraws; 138 139 typedef GrDrawOp INHERITED; 140 }; 141 142 #endif 143