| /* |
| * 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 "GrSimpleMeshDrawOpHelper.h" |
| #include "GrAppliedClip.h" |
| #include "GrProcessorSet.h" |
| #include "GrRect.h" |
| #include "GrUserStencilSettings.h" |
| |
| GrSimpleMeshDrawOpHelper::GrSimpleMeshDrawOpHelper(const MakeArgs& args, GrAAType aaType, |
| Flags flags) |
| : fProcessors(args.fProcessorSet) |
| , fPipelineFlags(args.fSRGBFlags) |
| , fAAType((int)aaType) |
| , fRequiresDstTexture(false) |
| , fUsesLocalCoords(false) |
| , fCompatibleWithAlphaAsCoveage(false) { |
| SkDEBUGCODE(fDidAnalysis = false); |
| SkDEBUGCODE(fMadePipeline = false); |
| if (GrAATypeIsHW(aaType)) { |
| fPipelineFlags |= GrPipeline::kHWAntialias_Flag; |
| } |
| if (flags & Flags::kSnapVerticesToPixelCenters) { |
| fPipelineFlags |= GrPipeline::kSnapVerticesToPixelCenters_Flag; |
| } |
| } |
| |
| GrSimpleMeshDrawOpHelper::~GrSimpleMeshDrawOpHelper() { |
| if (fProcessors) { |
| fProcessors->~GrProcessorSet(); |
| } |
| } |
| |
| GrDrawOp::FixedFunctionFlags GrSimpleMeshDrawOpHelper::fixedFunctionFlags() const { |
| return GrAATypeIsHW((this->aaType())) ? GrDrawOp::FixedFunctionFlags::kUsesHWAA |
| : GrDrawOp::FixedFunctionFlags::kNone; |
| } |
| |
| bool GrSimpleMeshDrawOpHelper::isCompatible(const GrSimpleMeshDrawOpHelper& that, |
| const GrCaps& caps, const SkRect& thisBounds, |
| const SkRect& thatBounds) const { |
| if (SkToBool(fProcessors) != SkToBool(that.fProcessors)) { |
| return false; |
| } |
| if (fProcessors) { |
| if (*fProcessors != *that.fProcessors) { |
| return false; |
| } |
| if (fRequiresDstTexture || |
| (fProcessors->xferProcessor() && fProcessors->xferProcessor()->xferBarrierType(caps))) { |
| if (GrRectsTouchOrOverlap(thisBounds, thatBounds)) { |
| return false; |
| } |
| } |
| } |
| bool result = fPipelineFlags == that.fPipelineFlags && fAAType == that.fAAType; |
| SkASSERT(!result || fCompatibleWithAlphaAsCoveage == that.fCompatibleWithAlphaAsCoveage); |
| SkASSERT(!result || fUsesLocalCoords == that.fUsesLocalCoords); |
| return result; |
| } |
| |
| GrDrawOp::RequiresDstTexture GrSimpleMeshDrawOpHelper::xpRequiresDstTexture( |
| const GrCaps& caps, const GrAppliedClip* clip, GrPixelConfigIsClamped dstIsClamped, |
| 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; |
| } |
| bool isMixedSamples = this->aaType() == GrAAType::kMixedSamples; |
| GrColor overrideColor; |
| analysis = fProcessors->finalize(*geometryColor, coverage, clip, isMixedSamples, caps, |
| dstIsClamped, &overrideColor); |
| if (analysis.inputColorIsOverridden()) { |
| *geometryColor = overrideColor; |
| } |
| } else { |
| analysis = GrProcessorSet::EmptySetAnalysis(); |
| } |
| fRequiresDstTexture = analysis.requiresDstTexture(); |
| fUsesLocalCoords = analysis.usesLocalCoords(); |
| fCompatibleWithAlphaAsCoveage = analysis.isCompatibleWithCoverageAsAlpha(); |
| return analysis.requiresDstTexture() ? GrDrawOp::RequiresDstTexture::kYes |
| : GrDrawOp::RequiresDstTexture::kNo; |
| } |
| |
| GrDrawOp::RequiresDstTexture GrSimpleMeshDrawOpHelper::xpRequiresDstTexture( |
| const GrCaps& caps, const GrAppliedClip* clip, GrPixelConfigIsClamped dstIsClamped, |
| GrProcessorAnalysisCoverage geometryCoverage, GrColor* geometryColor) { |
| GrProcessorAnalysisColor color = *geometryColor; |
| auto result = this->xpRequiresDstTexture(caps, clip, dstIsClamped, geometryCoverage, &color); |
| color.isConstant(geometryColor); |
| return result; |
| } |
| |
| 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; |
| case GrAAType::kMixedSamples: |
| result.append(" mixed samples\n"); |
| break; |
| } |
| result.append(GrPipeline::DumpFlags(fPipelineFlags)); |
| return result; |
| } |
| |
| GrPipeline::InitArgs GrSimpleMeshDrawOpHelper::pipelineInitArgs( |
| GrMeshDrawOp::Target* target) const { |
| GrPipeline::InitArgs args; |
| args.fFlags = this->pipelineFlags(); |
| args.fProxy = target->proxy(); |
| args.fDstProxy = target->dstProxy(); |
| args.fCaps = &target->caps(); |
| args.fResourceProvider = target->resourceProvider(); |
| return args; |
| } |
| |
| GrPipeline* GrSimpleMeshDrawOpHelper::internalMakePipeline(GrMeshDrawOp::Target* target, |
| const GrPipeline::InitArgs& args) { |
| // A caller really should only call this once as the processor set and applied clip get |
| // moved into the GrPipeline. |
| SkASSERT(!fMadePipeline); |
| SkDEBUGCODE(fMadePipeline = true); |
| if (fProcessors) { |
| return target->allocPipeline(args, std::move(*fProcessors), target->detachAppliedClip()); |
| } else { |
| return target->allocPipeline(args, GrProcessorSet::MakeEmptySet(), |
| target->detachAppliedClip()); |
| } |
| } |
| |
| GrSimpleMeshDrawOpHelperWithStencil::GrSimpleMeshDrawOpHelperWithStencil( |
| const MakeArgs& args, GrAAType aaType, const GrUserStencilSettings* stencilSettings, |
| Flags flags) |
| : INHERITED(args, aaType, flags) |
| , 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; |
| } |
| |
| bool GrSimpleMeshDrawOpHelperWithStencil::isCompatible( |
| const GrSimpleMeshDrawOpHelperWithStencil& that, const GrCaps& caps, |
| const SkRect& thisBounds, const SkRect& thatBounds) const { |
| return INHERITED::isCompatible(that, caps, thisBounds, thatBounds) && |
| fStencilSettings == that.fStencilSettings; |
| } |
| |
| const GrPipeline* GrSimpleMeshDrawOpHelperWithStencil::makePipeline( |
| GrMeshDrawOp::Target* target) { |
| auto args = INHERITED::pipelineInitArgs(target); |
| args.fUserStencil = fStencilSettings; |
| return this->internalMakePipeline(target, args); |
| } |
| |
| SkString GrSimpleMeshDrawOpHelperWithStencil::dumpInfo() const { |
| SkString result = INHERITED::dumpInfo(); |
| result.appendf("Stencil settings: %s\n", (fStencilSettings ? "yes" : "no")); |
| return result; |
| } |