1 /* 2 * Copyright 2017 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 GrSimpleMeshDrawOpHelper_DEFINED 9 #define GrSimpleMeshDrawOpHelper_DEFINED 10 11 #include "GrMemoryPool.h" // only here bc of the templated FactoryHelper 12 #include "GrMeshDrawOp.h" 13 #include "GrOpFlushState.h" 14 #include "GrPipeline.h" 15 #include "GrRecordingContext.h" 16 #include "GrRecordingContextPriv.h" 17 #include <new> 18 19 struct SkRect; 20 21 /** 22 * This class can be used to help implement simple mesh draw ops. It reduces the amount of 23 * boilerplate code to type and also provides a mechanism for optionally allocating space for a 24 * GrProcessorSet based on a GrPaint. It is intended to be used by ops that construct a single 25 * GrPipeline for a uniform primitive color and a GrPaint. 26 */ 27 class GrSimpleMeshDrawOpHelper { 28 public: 29 struct MakeArgs; 30 31 /** 32 * This can be used by a Op class to perform allocation and initialization such that a 33 * GrProcessorSet (if required) is allocated as part of the the same allocation that as 34 * the Op instance. It requires that Op implements a constructor of the form: 35 * Op(MakeArgs, GrColor, OpArgs...) 36 * which is public or made accessible via 'friend'. 37 */ 38 template <typename Op, typename... OpArgs> 39 static std::unique_ptr<GrDrawOp> FactoryHelper(GrRecordingContext*, GrPaint&&, OpArgs...); 40 41 enum class Flags : uint32_t { 42 kNone = 0x0, 43 kSnapVerticesToPixelCenters = 0x1, 44 }; 45 GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(Flags); 46 47 GrSimpleMeshDrawOpHelper(const MakeArgs&, GrAAType, Flags = Flags::kNone); 48 ~GrSimpleMeshDrawOpHelper(); 49 50 GrSimpleMeshDrawOpHelper() = delete; 51 GrSimpleMeshDrawOpHelper(const GrSimpleMeshDrawOpHelper&) = delete; 52 GrSimpleMeshDrawOpHelper& operator=(const GrSimpleMeshDrawOpHelper&) = delete; 53 54 GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const; 55 56 // noneAACompatibleWithCoverage should be set to true if the op can properly render a non-AA 57 // primitive merged into a coverage-based op. 58 bool isCompatible(const GrSimpleMeshDrawOpHelper& that, const GrCaps&, const SkRect& thisBounds, 59 const SkRect& thatBounds, bool noneAACompatibleWithCoverage = false) const; 60 61 /** 62 * Finalizes the processor set and determines whether the destination must be provided 63 * to the fragment shader as a texture for blending. 64 * 65 * @param geometryCoverage Describes the coverage output of the op's geometry processor 66 * @param geometryColor An in/out param. As input this informs processor analysis about the 67 * color the op expects to output from its geometry processor. As output 68 * this may be set to a known color in which case the op must output this 69 * color from its geometry processor instead. 70 */ 71 GrProcessorSet::Analysis finalizeProcessors( 72 const GrCaps& caps, const GrAppliedClip* clip, GrFSAAType fsaaType, 73 GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage, 74 GrProcessorAnalysisColor* geometryColor) { 75 return this->finalizeProcessors(caps, clip, &GrUserStencilSettings::kUnused, fsaaType, 76 clampType, geometryCoverage, geometryColor); 77 } 78 79 /** 80 * Version of above that can be used by ops that have a constant color geometry processor 81 * output. The op passes this color as 'geometryColor' and after return if 'geometryColor' has 82 * changed the op must override its geometry processor color output with the new color. 83 */ 84 GrProcessorSet::Analysis finalizeProcessors( 85 const GrCaps&, const GrAppliedClip*, GrFSAAType, GrClampType, 86 GrProcessorAnalysisCoverage geometryCoverage, SkPMColor4f* geometryColor); 87 88 bool isTrivial() const { 89 return fProcessors == nullptr; 90 } 91 92 bool usesLocalCoords() const { 93 SkASSERT(fDidAnalysis); 94 return fUsesLocalCoords; 95 } 96 97 bool compatibleWithAlphaAsCoverage() const { return fCompatibleWithAlphaAsCoveage; } 98 99 struct MakeArgs { 100 private: 101 MakeArgs() = default; 102 103 GrProcessorSet* fProcessorSet; 104 105 friend class GrSimpleMeshDrawOpHelper; 106 }; 107 108 void visitProxies(const std::function<void(GrSurfaceProxy*)>& func) const { 109 if (fProcessors) { 110 fProcessors->visitProxies(func); 111 } 112 } 113 114 #ifdef SK_DEBUG 115 SkString dumpInfo() const; 116 #endif 117 GrAAType aaType() const { return static_cast<GrAAType>(fAAType); } 118 119 void setAAType(GrAAType aaType) { 120 fAAType = static_cast<unsigned>(aaType); 121 } 122 123 void executeDrawsAndUploads(const GrOp*, GrOpFlushState*, const SkRect& chainBounds); 124 125 protected: 126 uint32_t pipelineFlags() const { return fPipelineFlags; } 127 128 GrProcessorSet::Analysis finalizeProcessors( 129 const GrCaps& caps, const GrAppliedClip*, const GrUserStencilSettings*, GrFSAAType, 130 GrClampType, GrProcessorAnalysisCoverage geometryCoverage, 131 GrProcessorAnalysisColor* geometryColor); 132 133 GrProcessorSet* fProcessors; 134 unsigned fPipelineFlags : 8; 135 unsigned fAAType : 2; 136 unsigned fUsesLocalCoords : 1; 137 unsigned fCompatibleWithAlphaAsCoveage : 1; 138 SkDEBUGCODE(unsigned fMadePipeline : 1;) 139 SkDEBUGCODE(unsigned fDidAnalysis : 1;) 140 }; 141 142 /** 143 * This class extends GrSimpleMeshDrawOpHelper to support an optional GrUserStencilSettings. This 144 * uses private inheritance because it non-virtually overrides methods in the base class and should 145 * never be used with a GrSimpleMeshDrawOpHelper pointer or reference. 146 */ 147 class GrSimpleMeshDrawOpHelperWithStencil : private GrSimpleMeshDrawOpHelper { 148 public: 149 using MakeArgs = GrSimpleMeshDrawOpHelper::MakeArgs; 150 using Flags = GrSimpleMeshDrawOpHelper::Flags; 151 152 using GrSimpleMeshDrawOpHelper::visitProxies; 153 154 // using declarations can't be templated, so this is a pass through function instead. 155 template <typename Op, typename... OpArgs> 156 static std::unique_ptr<GrDrawOp> FactoryHelper(GrRecordingContext* context, GrPaint&& paint, 157 OpArgs... opArgs) { 158 return GrSimpleMeshDrawOpHelper::FactoryHelper<Op, OpArgs...>( 159 context, std::move(paint), std::forward<OpArgs>(opArgs)...); 160 } 161 162 GrSimpleMeshDrawOpHelperWithStencil(const MakeArgs&, GrAAType, const GrUserStencilSettings*, 163 Flags = Flags::kNone); 164 165 GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const; 166 167 GrProcessorSet::Analysis finalizeProcessors( 168 const GrCaps& caps, const GrAppliedClip* clip, GrFSAAType fsaaType, 169 GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage, 170 GrProcessorAnalysisColor* geometryColor) { 171 return this->INHERITED::finalizeProcessors( 172 caps, clip, fStencilSettings, fsaaType, clampType, geometryCoverage, geometryColor); 173 } 174 175 GrProcessorSet::Analysis finalizeProcessors( 176 const GrCaps&, const GrAppliedClip*, GrFSAAType, GrClampType, 177 GrProcessorAnalysisCoverage geometryCoverage, SkPMColor4f* geometryColor); 178 179 using GrSimpleMeshDrawOpHelper::aaType; 180 using GrSimpleMeshDrawOpHelper::setAAType; 181 using GrSimpleMeshDrawOpHelper::isTrivial; 182 using GrSimpleMeshDrawOpHelper::usesLocalCoords; 183 using GrSimpleMeshDrawOpHelper::compatibleWithAlphaAsCoverage; 184 185 bool isCompatible(const GrSimpleMeshDrawOpHelperWithStencil& that, const GrCaps&, 186 const SkRect& thisBounds, const SkRect& thatBounds, 187 bool noneAACompatibleWithCoverage = false) const; 188 189 void executeDrawsAndUploads(const GrOp*, GrOpFlushState*, const SkRect& chainBounds); 190 191 #ifdef SK_DEBUG 192 SkString dumpInfo() const; 193 #endif 194 195 private: 196 const GrUserStencilSettings* fStencilSettings; 197 typedef GrSimpleMeshDrawOpHelper INHERITED; 198 }; 199 200 template <typename Op, typename... OpArgs> 201 std::unique_ptr<GrDrawOp> GrSimpleMeshDrawOpHelper::FactoryHelper(GrRecordingContext* context, 202 GrPaint&& paint, 203 OpArgs... opArgs) { 204 GrOpMemoryPool* pool = context->priv().opMemoryPool(); 205 206 MakeArgs makeArgs; 207 208 if (paint.isTrivial()) { 209 makeArgs.fProcessorSet = nullptr; 210 return pool->allocate<Op>(makeArgs, paint.getColor4f(), std::forward<OpArgs>(opArgs)...); 211 } else { 212 char* mem = (char*) pool->allocate(sizeof(Op) + sizeof(GrProcessorSet)); 213 char* setMem = mem + sizeof(Op); 214 auto color = paint.getColor4f(); 215 makeArgs.fProcessorSet = new (setMem) GrProcessorSet(std::move(paint)); 216 return std::unique_ptr<GrDrawOp>(new (mem) Op(makeArgs, color, 217 std::forward<OpArgs>(opArgs)...)); 218 } 219 } 220 221 GR_MAKE_BITFIELD_CLASS_OPS(GrSimpleMeshDrawOpHelper::Flags) 222 223 #endif 224