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 "src/gpu/ops/GrSimpleMeshDrawOpHelper.h" 9 10#include "src/gpu/GrAppliedClip.h" 11#include "src/gpu/GrProcessorSet.h" 12#include "src/gpu/GrProgramInfo.h" 13#include "src/gpu/GrUserStencilSettings.h" 14#include "src/gpu/SkGr.h" 15#include "src/gpu/geometry/GrRect.h" 16 17GrSimpleMeshDrawOpHelper::GrSimpleMeshDrawOpHelper(GrProcessorSet* processorSet, 18 GrAAType aaType, 19 InputFlags inputFlags) 20 : fProcessors(processorSet) 21 , fPipelineFlags((GrPipeline::InputFlags)inputFlags) 22 , fAAType((int)aaType) 23 , fUsesLocalCoords(false) 24 , fCompatibleWithCoverageAsAlpha(false) { 25 SkDEBUGCODE(fDidAnalysis = false); 26 SkDEBUGCODE(fMadePipeline = false); 27} 28 29GrSimpleMeshDrawOpHelper::~GrSimpleMeshDrawOpHelper() { 30 if (fProcessors) { 31 fProcessors->~GrProcessorSet(); 32 } 33} 34 35GrDrawOp::FixedFunctionFlags GrSimpleMeshDrawOpHelper::fixedFunctionFlags() const { 36 return GrAATypeIsHW(this->aaType()) ? GrDrawOp::FixedFunctionFlags::kUsesHWAA 37 : GrDrawOp::FixedFunctionFlags::kNone; 38} 39 40bool GrSimpleMeshDrawOpHelper::isCompatible(const GrSimpleMeshDrawOpHelper& that, 41 const GrCaps& caps, const SkRect& thisBounds, 42 const SkRect& thatBounds, bool ignoreAAType) const { 43 if (SkToBool(fProcessors) != SkToBool(that.fProcessors)) { 44 return false; 45 } 46 if (fProcessors) { 47 if (*fProcessors != *that.fProcessors) { 48 return false; 49 } 50 } 51 52#ifdef SK_DEBUG 53 if (ignoreAAType) { 54 // If we're ignoring AA it should be bc we already know they are the same or that 55 // the are different but are compatible (i.e., one is AA and the other is None) 56 SkASSERT(fAAType == that.fAAType || 57 GrMeshDrawOp::CanUpgradeAAOnMerge(this->aaType(), that.aaType())); 58 } 59#endif 60 61 bool result = fPipelineFlags == that.fPipelineFlags && 62 (ignoreAAType || fAAType == that.fAAType); 63 SkASSERT(!result || fCompatibleWithCoverageAsAlpha == that.fCompatibleWithCoverageAsAlpha); 64 SkASSERT(!result || fUsesLocalCoords == that.fUsesLocalCoords); 65 return result; 66} 67 68GrProcessorSet::Analysis GrSimpleMeshDrawOpHelper::finalizeProcessors( 69 const GrCaps& caps, const GrAppliedClip* clip, GrClampType clampType, 70 GrProcessorAnalysisCoverage geometryCoverage, SkPMColor4f* geometryColor, bool* wideColor) { 71 GrProcessorAnalysisColor color = *geometryColor; 72 auto result = this->finalizeProcessors(caps, clip, clampType, geometryCoverage, &color); 73 color.isConstant(geometryColor); 74 if (wideColor) { 75 *wideColor = !geometryColor->fitsInBytes(); 76 } 77 return result; 78} 79 80GrProcessorSet::Analysis GrSimpleMeshDrawOpHelper::finalizeProcessors( 81 const GrCaps& caps, const GrAppliedClip* clip, const GrUserStencilSettings* userStencil, 82 GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage, 83 GrProcessorAnalysisColor* geometryColor) { 84 SkDEBUGCODE(fDidAnalysis = true); 85 GrProcessorSet::Analysis analysis; 86 if (fProcessors) { 87 GrProcessorAnalysisCoverage coverage = geometryCoverage; 88 if (GrProcessorAnalysisCoverage::kNone == coverage) { 89 coverage = (clip && clip->hasCoverageFragmentProcessor()) 90 ? GrProcessorAnalysisCoverage::kSingleChannel 91 : GrProcessorAnalysisCoverage::kNone; 92 } 93 SkPMColor4f overrideColor; 94 analysis = fProcessors->finalize(*geometryColor, coverage, clip, userStencil, caps, 95 clampType, &overrideColor); 96 if (analysis.inputColorIsOverridden()) { 97 *geometryColor = overrideColor; 98 } 99 } else { 100 analysis = GrProcessorSet::EmptySetAnalysis(); 101 } 102 fUsesLocalCoords = analysis.usesLocalCoords(); 103 fCompatibleWithCoverageAsAlpha = analysis.isCompatibleWithCoverageAsAlpha(); 104 return analysis; 105} 106 107const GrPipeline* GrSimpleMeshDrawOpHelper::CreatePipeline( 108 const GrCaps* caps, 109 SkArenaAlloc* arena, 110 GrSwizzle writeViewSwizzle, 111 GrAppliedClip&& appliedClip, 112 const GrDstProxyView& dstProxyView, 113 GrProcessorSet&& processorSet, 114 GrPipeline::InputFlags pipelineFlags) { 115 GrPipeline::InitArgs pipelineArgs; 116 117 pipelineArgs.fInputFlags = pipelineFlags; 118 pipelineArgs.fCaps = caps; 119 pipelineArgs.fDstProxyView = dstProxyView; 120 pipelineArgs.fWriteSwizzle = writeViewSwizzle; 121 122 return arena->make<GrPipeline>(pipelineArgs, 123 std::move(processorSet), 124 std::move(appliedClip)); 125} 126 127const GrPipeline* GrSimpleMeshDrawOpHelper::CreatePipeline( 128 GrOpFlushState* flushState, 129 GrProcessorSet&& processorSet, 130 GrPipeline::InputFlags pipelineFlags) { 131 return CreatePipeline(&flushState->caps(), 132 flushState->allocator(), 133 flushState->writeView().swizzle(), 134 flushState->detachAppliedClip(), 135 flushState->dstProxyView(), 136 std::move(processorSet), 137 pipelineFlags); 138} 139 140const GrPipeline* GrSimpleMeshDrawOpHelper::createPipeline(GrOpFlushState* flushState) { 141 return CreatePipeline(&flushState->caps(), 142 flushState->allocator(), 143 flushState->writeView().swizzle(), 144 flushState->detachAppliedClip(), 145 flushState->dstProxyView(), 146 this->detachProcessorSet(), 147 this->pipelineFlags()); 148} 149 150const GrPipeline* GrSimpleMeshDrawOpHelper::createPipeline( 151 const GrCaps* caps, 152 SkArenaAlloc* arena, 153 GrSwizzle writeViewSwizzle, 154 GrAppliedClip&& appliedClip, 155 const GrDstProxyView& dstProxyView) { 156 return GrSimpleMeshDrawOpHelper::CreatePipeline(caps, 157 arena, 158 writeViewSwizzle, 159 std::move(appliedClip), 160 dstProxyView, 161 this->detachProcessorSet(), 162 this->pipelineFlags()); 163} 164 165GrProgramInfo* GrSimpleMeshDrawOpHelper::CreateProgramInfo( 166 const GrCaps* caps, 167 SkArenaAlloc* arena, 168 const GrSurfaceProxyView& writeView, 169 bool usesMSAASurface, 170 GrAppliedClip&& appliedClip, 171 const GrDstProxyView& dstProxyView, 172 GrGeometryProcessor* geometryProcessor, 173 GrProcessorSet&& processorSet, 174 GrPrimitiveType primitiveType, 175 GrXferBarrierFlags renderPassXferBarriers, 176 GrLoadOp colorLoadOp, 177 GrPipeline::InputFlags pipelineFlags, 178 const GrUserStencilSettings* stencilSettings) { 179 auto pipeline = CreatePipeline(caps, 180 arena, 181 writeView.swizzle(), 182 std::move(appliedClip), 183 dstProxyView, 184 std::move(processorSet), 185 pipelineFlags); 186 187 return CreateProgramInfo(caps, arena, pipeline, writeView, usesMSAASurface, geometryProcessor, 188 primitiveType, renderPassXferBarriers, colorLoadOp, stencilSettings); 189} 190 191GrProgramInfo* GrSimpleMeshDrawOpHelper::CreateProgramInfo(const GrCaps* caps, 192 SkArenaAlloc* arena, 193 const GrPipeline* pipeline, 194 const GrSurfaceProxyView& writeView, 195 bool usesMSAASurface, 196 GrGeometryProcessor* geometryProcessor, 197 GrPrimitiveType primitiveType, 198 GrXferBarrierFlags xferBarrierFlags, 199 GrLoadOp colorLoadOp, 200 const GrUserStencilSettings* stencilSettings) { 201 auto tmp = arena->make<GrProgramInfo>(*caps, 202 writeView, 203 usesMSAASurface, 204 pipeline, 205 stencilSettings, 206 geometryProcessor, 207 primitiveType, 208 0, 209 xferBarrierFlags, 210 colorLoadOp); 211 return tmp; 212} 213 214GrProgramInfo* GrSimpleMeshDrawOpHelper::createProgramInfo( 215 const GrCaps* caps, 216 SkArenaAlloc* arena, 217 const GrSurfaceProxyView& writeView, 218 bool usesMSAASurface, 219 GrAppliedClip&& appliedClip, 220 const GrDstProxyView& dstProxyView, 221 GrGeometryProcessor* gp, 222 GrPrimitiveType primType, 223 GrXferBarrierFlags renderPassXferBarriers, 224 GrLoadOp colorLoadOp) { 225 return CreateProgramInfo(caps, 226 arena, 227 writeView, 228 usesMSAASurface, 229 std::move(appliedClip), 230 dstProxyView, 231 gp, 232 this->detachProcessorSet(), 233 primType, 234 renderPassXferBarriers, 235 colorLoadOp, 236 this->pipelineFlags()); 237} 238 239#if GR_TEST_UTILS 240static void dump_pipeline_flags(GrPipeline::InputFlags flags, SkString* result) { 241 if (GrPipeline::InputFlags::kNone != flags) { 242 if (flags & GrPipeline::InputFlags::kSnapVerticesToPixelCenters) { 243 result->append("Snap vertices to pixel center.\n"); 244 } 245 if (flags & GrPipeline::InputFlags::kWireframe) { 246 result->append("Wireframe enabled.\n"); 247 } 248 if (flags & GrPipeline::InputFlags::kConservativeRaster) { 249 result->append("Conservative raster enabled.\n"); 250 } 251 return; 252 } 253 result->append("No pipeline flags\n"); 254} 255 256SkString GrSimpleMeshDrawOpHelper::dumpInfo() const { 257 const GrProcessorSet& processors = fProcessors ? *fProcessors : GrProcessorSet::EmptySet(); 258 SkString result = processors.dumpProcessors(); 259 result.append("AA Type: "); 260 switch (this->aaType()) { 261 case GrAAType::kNone: 262 result.append(" none\n"); 263 break; 264 case GrAAType::kCoverage: 265 result.append(" coverage\n"); 266 break; 267 case GrAAType::kMSAA: 268 result.append(" msaa\n"); 269 break; 270 } 271 dump_pipeline_flags(fPipelineFlags, &result); 272 return result; 273} 274#endif 275