/* * Copyright 2017 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "src/gpu/GrAppliedClip.h" #include "src/gpu/GrProcessorSet.h" #include "src/gpu/GrUserStencilSettings.h" #include "src/gpu/SkGr.h" #include "src/gpu/geometry/GrRect.h" #include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h" GrSimpleMeshDrawOpHelper::GrSimpleMeshDrawOpHelper(const MakeArgs& args, GrAAType aaType, InputFlags inputFlags) : fProcessors(args.fProcessorSet) , fPipelineFlags((GrPipeline::InputFlags)inputFlags) , fAAType((int)aaType) , fUsesLocalCoords(false) , fCompatibleWithCoverageAsAlpha(false) { SkDEBUGCODE(fDidAnalysis = false); SkDEBUGCODE(fMadePipeline = false); if (GrAATypeIsHW(aaType)) { fPipelineFlags |= GrPipeline::InputFlags::kHWAntialias; } } GrSimpleMeshDrawOpHelper::~GrSimpleMeshDrawOpHelper() { if (fProcessors) { fProcessors->~GrProcessorSet(); } } GrDrawOp::FixedFunctionFlags GrSimpleMeshDrawOpHelper::fixedFunctionFlags() const { return GrAATypeIsHW((this->aaType())) ? GrDrawOp::FixedFunctionFlags::kUsesHWAA : GrDrawOp::FixedFunctionFlags::kNone; } static bool none_as_coverage_aa_compatible(GrAAType aa1, GrAAType aa2) { return (aa1 == GrAAType::kNone && aa2 == GrAAType::kCoverage) || (aa1 == GrAAType::kCoverage && aa2 == GrAAType::kNone); } bool GrSimpleMeshDrawOpHelper::isCompatible(const GrSimpleMeshDrawOpHelper& that, const GrCaps& caps, const SkRect& thisBounds, const SkRect& thatBounds, bool noneAsCoverageAA) const { if (SkToBool(fProcessors) != SkToBool(that.fProcessors)) { return false; } if (fProcessors) { if (*fProcessors != *that.fProcessors) { return false; } } bool result = fPipelineFlags == that.fPipelineFlags && (fAAType == that.fAAType || (noneAsCoverageAA && none_as_coverage_aa_compatible(this->aaType(), that.aaType()))); SkASSERT(!result || fCompatibleWithCoverageAsAlpha == that.fCompatibleWithCoverageAsAlpha); SkASSERT(!result || fUsesLocalCoords == that.fUsesLocalCoords); return result; } GrProcessorSet::Analysis GrSimpleMeshDrawOpHelper::finalizeProcessors( const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage, GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage, SkPMColor4f* geometryColor, bool* wideColor) { GrProcessorAnalysisColor color = *geometryColor; auto result = this->finalizeProcessors( caps, clip, hasMixedSampledCoverage, clampType, geometryCoverage, &color); color.isConstant(geometryColor); if (wideColor) { *wideColor = SkPMColor4fNeedsWideColor(*geometryColor, clampType, caps); } return result; } GrProcessorSet::Analysis GrSimpleMeshDrawOpHelper::finalizeProcessors( const GrCaps& caps, const GrAppliedClip* clip, const GrUserStencilSettings* userStencil, bool hasMixedSampledCoverage, GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage, GrProcessorAnalysisColor* geometryColor) { SkDEBUGCODE(fDidAnalysis = true); GrProcessorSet::Analysis analysis; if (fProcessors) { GrProcessorAnalysisCoverage coverage = geometryCoverage; if (GrProcessorAnalysisCoverage::kNone == coverage) { coverage = clip->numClipCoverageFragmentProcessors() ? GrProcessorAnalysisCoverage::kSingleChannel : GrProcessorAnalysisCoverage::kNone; } SkPMColor4f overrideColor; analysis = fProcessors->finalize(*geometryColor, coverage, clip, userStencil, hasMixedSampledCoverage, caps, clampType, &overrideColor); if (analysis.inputColorIsOverridden()) { *geometryColor = overrideColor; } } else { analysis = GrProcessorSet::EmptySetAnalysis(); } fUsesLocalCoords = analysis.usesLocalCoords(); fCompatibleWithCoverageAsAlpha = analysis.isCompatibleWithCoverageAsAlpha(); return analysis; } void GrSimpleMeshDrawOpHelper::executeDrawsAndUploads( const GrOp* op, GrOpFlushState* flushState, const SkRect& chainBounds) { if (fProcessors) { flushState->executeDrawsAndUploadsForMeshDrawOp( op, chainBounds, std::move(*fProcessors), fPipelineFlags); } else { flushState->executeDrawsAndUploadsForMeshDrawOp( op, chainBounds, GrProcessorSet::MakeEmptySet(), fPipelineFlags); } } #ifdef SK_DEBUG static void dump_pipeline_flags(GrPipeline::InputFlags flags, SkString* result) { if (GrPipeline::InputFlags::kNone != flags) { if (flags & GrPipeline::InputFlags::kSnapVerticesToPixelCenters) { result->append("Snap vertices to pixel center.\n"); } if (flags & GrPipeline::InputFlags::kHWAntialias) { result->append("HW Antialiasing enabled.\n"); } return; } result->append("No pipeline flags\n"); } SkString GrSimpleMeshDrawOpHelper::dumpInfo() const { const GrProcessorSet& processors = fProcessors ? *fProcessors : GrProcessorSet::EmptySet(); SkString result = processors.dumpProcessors(); result.append("AA Type: "); switch (this->aaType()) { case GrAAType::kNone: result.append(" none\n"); break; case GrAAType::kCoverage: result.append(" coverage\n"); break; case GrAAType::kMSAA: result.append(" msaa\n"); break; } dump_pipeline_flags(fPipelineFlags, &result); return result; } #endif GrSimpleMeshDrawOpHelperWithStencil::GrSimpleMeshDrawOpHelperWithStencil( const MakeArgs& args, GrAAType aaType, const GrUserStencilSettings* stencilSettings, InputFlags inputFlags) : INHERITED(args, aaType, inputFlags) , fStencilSettings(stencilSettings ? stencilSettings : &GrUserStencilSettings::kUnused) {} GrDrawOp::FixedFunctionFlags GrSimpleMeshDrawOpHelperWithStencil::fixedFunctionFlags() const { GrDrawOp::FixedFunctionFlags flags = INHERITED::fixedFunctionFlags(); if (fStencilSettings != &GrUserStencilSettings::kUnused) { flags |= GrDrawOp::FixedFunctionFlags::kUsesStencil; } return flags; } GrProcessorSet::Analysis GrSimpleMeshDrawOpHelperWithStencil::finalizeProcessors( const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage, GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage, SkPMColor4f* geometryColor, bool* wideColor) { GrProcessorAnalysisColor color = *geometryColor; auto result = this->finalizeProcessors( caps, clip, hasMixedSampledCoverage, clampType, geometryCoverage, &color); color.isConstant(geometryColor); if (wideColor) { *wideColor = SkPMColor4fNeedsWideColor(*geometryColor, clampType, caps); } return result; } bool GrSimpleMeshDrawOpHelperWithStencil::isCompatible( const GrSimpleMeshDrawOpHelperWithStencil& that, const GrCaps& caps, const SkRect& thisBounds, const SkRect& thatBounds, bool noneAsCoverageAA) const { return INHERITED::isCompatible(that, caps, thisBounds, thatBounds, noneAsCoverageAA) && fStencilSettings == that.fStencilSettings; } void GrSimpleMeshDrawOpHelperWithStencil::executeDrawsAndUploads( const GrOp* op, GrOpFlushState* flushState, const SkRect& chainBounds) { if (fProcessors) { flushState->executeDrawsAndUploadsForMeshDrawOp( op, chainBounds, std::move(*fProcessors), fPipelineFlags, fStencilSettings); } else { flushState->executeDrawsAndUploadsForMeshDrawOp( op, chainBounds, GrProcessorSet::MakeEmptySet(), fPipelineFlags, fStencilSettings); } } #ifdef SK_DEBUG SkString GrSimpleMeshDrawOpHelperWithStencil::dumpInfo() const { SkString result = INHERITED::dumpInfo(); result.appendf("Stencil settings: %s\n", (fStencilSettings ? "yes" : "no")); return result; } #endif