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 #include "GrSimpleMeshDrawOpHelper.h" 9 #include "GrAppliedClip.h" 10 #include "GrProcessorSet.h" 11 #include "GrRect.h" 12 #include "GrUserStencilSettings.h" 13 14 GrSimpleMeshDrawOpHelper::GrSimpleMeshDrawOpHelper(const MakeArgs& args, GrAAType aaType, 15 Flags flags) 16 : fProcessors(args.fProcessorSet) 17 , fPipelineFlags(args.fSRGBFlags) 18 , fAAType((int)aaType) 19 , fRequiresDstTexture(false) 20 , fUsesLocalCoords(false) 21 , fCompatibleWithAlphaAsCoveage(false) { 22 SkDEBUGCODE(fDidAnalysis = false); 23 SkDEBUGCODE(fMadePipeline = false); 24 if (GrAATypeIsHW(aaType)) { 25 fPipelineFlags |= GrPipeline::kHWAntialias_Flag; 26 } 27 if (flags & Flags::kSnapVerticesToPixelCenters) { 28 fPipelineFlags |= GrPipeline::kSnapVerticesToPixelCenters_Flag; 29 } 30 } 31 32 GrSimpleMeshDrawOpHelper::~GrSimpleMeshDrawOpHelper() { 33 if (fProcessors) { 34 fProcessors->~GrProcessorSet(); 35 } 36 } 37 38 GrDrawOp::FixedFunctionFlags GrSimpleMeshDrawOpHelper::fixedFunctionFlags() const { 39 return GrAATypeIsHW((this->aaType())) ? GrDrawOp::FixedFunctionFlags::kUsesHWAA 40 : GrDrawOp::FixedFunctionFlags::kNone; 41 } 42 43 bool GrSimpleMeshDrawOpHelper::isCompatible(const GrSimpleMeshDrawOpHelper& that, 44 const GrCaps& caps, const SkRect& thisBounds, 45 const SkRect& thatBounds) const { 46 if (SkToBool(fProcessors) != SkToBool(that.fProcessors)) { 47 return false; 48 } 49 if (fProcessors) { 50 if (*fProcessors != *that.fProcessors) { 51 return false; 52 } 53 if (fRequiresDstTexture || 54 (fProcessors->xferProcessor() && fProcessors->xferProcessor()->xferBarrierType(caps))) { 55 if (GrRectsTouchOrOverlap(thisBounds, thatBounds)) { 56 return false; 57 } 58 } 59 } 60 bool result = fPipelineFlags == that.fPipelineFlags && fAAType == that.fAAType; 61 SkASSERT(!result || fCompatibleWithAlphaAsCoveage == that.fCompatibleWithAlphaAsCoveage); 62 SkASSERT(!result || fUsesLocalCoords == that.fUsesLocalCoords); 63 return result; 64 } 65 66 GrDrawOp::RequiresDstTexture GrSimpleMeshDrawOpHelper::xpRequiresDstTexture( 67 const GrCaps& caps, const GrAppliedClip* clip, GrPixelConfigIsClamped dstIsClamped, 68 GrProcessorAnalysisCoverage geometryCoverage, GrProcessorAnalysisColor* geometryColor) { 69 SkDEBUGCODE(fDidAnalysis = true); 70 GrProcessorSet::Analysis analysis; 71 if (fProcessors) { 72 GrProcessorAnalysisCoverage coverage = geometryCoverage; 73 if (GrProcessorAnalysisCoverage::kNone == coverage) { 74 coverage = clip->numClipCoverageFragmentProcessors() 75 ? GrProcessorAnalysisCoverage::kSingleChannel 76 : GrProcessorAnalysisCoverage::kNone; 77 } 78 bool isMixedSamples = this->aaType() == GrAAType::kMixedSamples; 79 GrColor overrideColor; 80 analysis = fProcessors->finalize(*geometryColor, coverage, clip, isMixedSamples, caps, 81 dstIsClamped, &overrideColor); 82 if (analysis.inputColorIsOverridden()) { 83 *geometryColor = overrideColor; 84 } 85 } else { 86 analysis = GrProcessorSet::EmptySetAnalysis(); 87 } 88 fRequiresDstTexture = analysis.requiresDstTexture(); 89 fUsesLocalCoords = analysis.usesLocalCoords(); 90 fCompatibleWithAlphaAsCoveage = analysis.isCompatibleWithCoverageAsAlpha(); 91 return analysis.requiresDstTexture() ? GrDrawOp::RequiresDstTexture::kYes 92 : GrDrawOp::RequiresDstTexture::kNo; 93 } 94 95 GrDrawOp::RequiresDstTexture GrSimpleMeshDrawOpHelper::xpRequiresDstTexture( 96 const GrCaps& caps, const GrAppliedClip* clip, GrPixelConfigIsClamped dstIsClamped, 97 GrProcessorAnalysisCoverage geometryCoverage, GrColor* geometryColor) { 98 GrProcessorAnalysisColor color = *geometryColor; 99 auto result = this->xpRequiresDstTexture(caps, clip, dstIsClamped, geometryCoverage, &color); 100 color.isConstant(geometryColor); 101 return result; 102 } 103 104 SkString GrSimpleMeshDrawOpHelper::dumpInfo() const { 105 const GrProcessorSet& processors = fProcessors ? *fProcessors : GrProcessorSet::EmptySet(); 106 SkString result = processors.dumpProcessors(); 107 result.append("AA Type: "); 108 switch (this->aaType()) { 109 case GrAAType::kNone: 110 result.append(" none\n"); 111 break; 112 case GrAAType::kCoverage: 113 result.append(" coverage\n"); 114 break; 115 case GrAAType::kMSAA: 116 result.append(" msaa\n"); 117 break; 118 case GrAAType::kMixedSamples: 119 result.append(" mixed samples\n"); 120 break; 121 } 122 result.append(GrPipeline::DumpFlags(fPipelineFlags)); 123 return result; 124 } 125 126 GrPipeline::InitArgs GrSimpleMeshDrawOpHelper::pipelineInitArgs( 127 GrMeshDrawOp::Target* target) const { 128 GrPipeline::InitArgs args; 129 args.fFlags = this->pipelineFlags(); 130 args.fProxy = target->proxy(); 131 args.fDstProxy = target->dstProxy(); 132 args.fCaps = &target->caps(); 133 args.fResourceProvider = target->resourceProvider(); 134 return args; 135 } 136 137 GrPipeline* GrSimpleMeshDrawOpHelper::internalMakePipeline(GrMeshDrawOp::Target* target, 138 const GrPipeline::InitArgs& args) { 139 // A caller really should only call this once as the processor set and applied clip get 140 // moved into the GrPipeline. 141 SkASSERT(!fMadePipeline); 142 SkDEBUGCODE(fMadePipeline = true); 143 if (fProcessors) { 144 return target->allocPipeline(args, std::move(*fProcessors), target->detachAppliedClip()); 145 } else { 146 return target->allocPipeline(args, GrProcessorSet::MakeEmptySet(), 147 target->detachAppliedClip()); 148 } 149 } 150 151 GrSimpleMeshDrawOpHelperWithStencil::GrSimpleMeshDrawOpHelperWithStencil( 152 const MakeArgs& args, GrAAType aaType, const GrUserStencilSettings* stencilSettings, 153 Flags flags) 154 : INHERITED(args, aaType, flags) 155 , fStencilSettings(stencilSettings ? stencilSettings : &GrUserStencilSettings::kUnused) {} 156 157 GrDrawOp::FixedFunctionFlags GrSimpleMeshDrawOpHelperWithStencil::fixedFunctionFlags() const { 158 GrDrawOp::FixedFunctionFlags flags = INHERITED::fixedFunctionFlags(); 159 if (fStencilSettings != &GrUserStencilSettings::kUnused) { 160 flags |= GrDrawOp::FixedFunctionFlags::kUsesStencil; 161 } 162 return flags; 163 } 164 165 bool GrSimpleMeshDrawOpHelperWithStencil::isCompatible( 166 const GrSimpleMeshDrawOpHelperWithStencil& that, const GrCaps& caps, 167 const SkRect& thisBounds, const SkRect& thatBounds) const { 168 return INHERITED::isCompatible(that, caps, thisBounds, thatBounds) && 169 fStencilSettings == that.fStencilSettings; 170 } 171 172 const GrPipeline* GrSimpleMeshDrawOpHelperWithStencil::makePipeline( 173 GrMeshDrawOp::Target* target) { 174 auto args = INHERITED::pipelineInitArgs(target); 175 args.fUserStencil = fStencilSettings; 176 return this->internalMakePipeline(target, args); 177 } 178 179 SkString GrSimpleMeshDrawOpHelperWithStencil::dumpInfo() const { 180 SkString result = INHERITED::dumpInfo(); 181 result.appendf("Stencil settings: %s\n", (fStencilSettings ? "yes" : "no")); 182 return result; 183 } 184