| /* | |
| * 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/ganesh/ops/GrSimpleMeshDrawOpHelper.h" | |
| #include "include/private/base/SkTo.h" | |
| #include "src/base/SkArenaAlloc.h" | |
| #include "src/gpu/Swizzle.h" | |
| #include "src/gpu/ganesh/GrAppliedClip.h" | |
| #include "src/gpu/ganesh/GrDstProxyView.h" | |
| #include "src/gpu/ganesh/GrOpFlushState.h" | |
| #include "src/gpu/ganesh/GrProcessorAnalysis.h" | |
| #include "src/gpu/ganesh/GrProcessorSet.h" | |
| #include "src/gpu/ganesh/GrProgramInfo.h" | |
| #include "src/gpu/ganesh/GrSurfaceProxyView.h" | |
| #include "src/gpu/ganesh/ops/GrMeshDrawOp.h" | |
| enum class GrXferBarrierFlags; | |
| struct SkRect; | |
| GrSimpleMeshDrawOpHelper::GrSimpleMeshDrawOpHelper(GrProcessorSet* processorSet, | |
| GrAAType aaType, | |
| InputFlags inputFlags) | |
| : fProcessors(processorSet) | |
| , fPipelineFlags((GrPipeline::InputFlags)inputFlags) | |
| , fAAType((int)aaType) | |
| , fUsesLocalCoords(false) | |
| , fCompatibleWithCoverageAsAlpha(false) { | |
| SkDEBUGCODE(fDidAnalysis = false); | |
| SkDEBUGCODE(fMadePipeline = false); | |
| } | |
| 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, bool ignoreAAType) const { | |
| if (SkToBool(fProcessors) != SkToBool(that.fProcessors)) { | |
| return false; | |
| } | |
| if (fProcessors) { | |
| if (*fProcessors != *that.fProcessors) { | |
| return false; | |
| } | |
| } | |
| #ifdef SK_DEBUG | |
| if (ignoreAAType) { | |
| // If we're ignoring AA it should be bc we already know they are the same or that | |
| // the are different but are compatible (i.e., one is AA and the other is None) | |
| SkASSERT(fAAType == that.fAAType || | |
| GrMeshDrawOp::CanUpgradeAAOnMerge(this->aaType(), that.aaType())); | |
| } | |
| #endif | |
| bool result = fPipelineFlags == that.fPipelineFlags && | |
| (ignoreAAType || fAAType == that.fAAType); | |
| SkASSERT(!result || fCompatibleWithCoverageAsAlpha == that.fCompatibleWithCoverageAsAlpha); | |
| SkASSERT(!result || fUsesLocalCoords == that.fUsesLocalCoords); | |
| return result; | |
| } | |
| GrProcessorSet::Analysis GrSimpleMeshDrawOpHelper::finalizeProcessors( | |
| const GrCaps& caps, const GrAppliedClip* clip, GrClampType clampType, | |
| GrProcessorAnalysisCoverage geometryCoverage, SkPMColor4f* geometryColor, bool* wideColor) { | |
| GrProcessorAnalysisColor color = *geometryColor; | |
| auto result = this->finalizeProcessors(caps, clip, clampType, geometryCoverage, &color); | |
| color.isConstant(geometryColor); | |
| if (wideColor) { | |
| *wideColor = !geometryColor->fitsInBytes(); | |
| } | |
| return result; | |
| } | |
| GrProcessorSet::Analysis GrSimpleMeshDrawOpHelper::finalizeProcessors( | |
| const GrCaps& caps, const GrAppliedClip* clip, const GrUserStencilSettings* userStencil, | |
| GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage, | |
| GrProcessorAnalysisColor* geometryColor) { | |
| SkDEBUGCODE(fDidAnalysis = true); | |
| GrProcessorSet::Analysis analysis; | |
| if (fProcessors) { | |
| GrProcessorAnalysisCoverage coverage = geometryCoverage; | |
| if (GrProcessorAnalysisCoverage::kNone == coverage) { | |
| coverage = (clip && clip->hasCoverageFragmentProcessor()) | |
| ? GrProcessorAnalysisCoverage::kSingleChannel | |
| : GrProcessorAnalysisCoverage::kNone; | |
| } | |
| SkPMColor4f overrideColor; | |
| analysis = fProcessors->finalize(*geometryColor, coverage, clip, userStencil, caps, | |
| clampType, &overrideColor); | |
| if (analysis.inputColorIsOverridden()) { | |
| *geometryColor = overrideColor; | |
| } | |
| } else { | |
| analysis = GrProcessorSet::EmptySetAnalysis(); | |
| } | |
| fUsesLocalCoords = analysis.usesLocalCoords(); | |
| fCompatibleWithCoverageAsAlpha = analysis.isCompatibleWithCoverageAsAlpha(); | |
| return analysis; | |
| } | |
| const GrPipeline* GrSimpleMeshDrawOpHelper::CreatePipeline(const GrCaps* caps, | |
| SkArenaAlloc* arena, | |
| skgpu::Swizzle writeViewSwizzle, | |
| GrAppliedClip&& appliedClip, | |
| const GrDstProxyView& dstProxyView, | |
| GrProcessorSet&& processorSet, | |
| GrPipeline::InputFlags pipelineFlags) { | |
| GrPipeline::InitArgs pipelineArgs; | |
| pipelineArgs.fInputFlags = pipelineFlags; | |
| pipelineArgs.fCaps = caps; | |
| pipelineArgs.fDstProxyView = dstProxyView; | |
| pipelineArgs.fWriteSwizzle = writeViewSwizzle; | |
| return arena->make<GrPipeline>(pipelineArgs, | |
| std::move(processorSet), | |
| std::move(appliedClip)); | |
| } | |
| const GrPipeline* GrSimpleMeshDrawOpHelper::CreatePipeline(GrOpFlushState* flushState, | |
| GrProcessorSet&& processorSet, | |
| GrPipeline::InputFlags pipelineFlags) { | |
| return CreatePipeline(&flushState->caps(), | |
| flushState->allocator(), | |
| flushState->writeView().swizzle(), | |
| flushState->detachAppliedClip(), | |
| flushState->dstProxyView(), | |
| std::move(processorSet), | |
| pipelineFlags); | |
| } | |
| const GrPipeline* GrSimpleMeshDrawOpHelper::createPipeline(GrOpFlushState* flushState) { | |
| return CreatePipeline(&flushState->caps(), | |
| flushState->allocator(), | |
| flushState->writeView().swizzle(), | |
| flushState->detachAppliedClip(), | |
| flushState->dstProxyView(), | |
| this->detachProcessorSet(), | |
| this->pipelineFlags()); | |
| } | |
| const GrPipeline* GrSimpleMeshDrawOpHelper::createPipeline(const GrCaps* caps, | |
| SkArenaAlloc* arena, | |
| skgpu::Swizzle writeViewSwizzle, | |
| GrAppliedClip&& appliedClip, | |
| const GrDstProxyView& dstProxyView) { | |
| return GrSimpleMeshDrawOpHelper::CreatePipeline(caps, | |
| arena, | |
| writeViewSwizzle, | |
| std::move(appliedClip), | |
| dstProxyView, | |
| this->detachProcessorSet(), | |
| this->pipelineFlags()); | |
| } | |
| GrProgramInfo* GrSimpleMeshDrawOpHelper::CreateProgramInfo( | |
| const GrCaps* caps, | |
| SkArenaAlloc* arena, | |
| const GrSurfaceProxyView& writeView, | |
| bool usesMSAASurface, | |
| GrAppliedClip&& appliedClip, | |
| const GrDstProxyView& dstProxyView, | |
| GrGeometryProcessor* geometryProcessor, | |
| GrProcessorSet&& processorSet, | |
| GrPrimitiveType primitiveType, | |
| GrXferBarrierFlags renderPassXferBarriers, | |
| GrLoadOp colorLoadOp, | |
| GrPipeline::InputFlags pipelineFlags, | |
| const GrUserStencilSettings* stencilSettings) { | |
| auto pipeline = CreatePipeline(caps, | |
| arena, | |
| writeView.swizzle(), | |
| std::move(appliedClip), | |
| dstProxyView, | |
| std::move(processorSet), | |
| pipelineFlags); | |
| return CreateProgramInfo(caps, arena, pipeline, writeView, usesMSAASurface, geometryProcessor, | |
| primitiveType, renderPassXferBarriers, colorLoadOp, stencilSettings); | |
| } | |
| GrProgramInfo* GrSimpleMeshDrawOpHelper::CreateProgramInfo(const GrCaps* caps, | |
| SkArenaAlloc* arena, | |
| const GrPipeline* pipeline, | |
| const GrSurfaceProxyView& writeView, | |
| bool usesMSAASurface, | |
| GrGeometryProcessor* geometryProcessor, | |
| GrPrimitiveType primitiveType, | |
| GrXferBarrierFlags xferBarrierFlags, | |
| GrLoadOp colorLoadOp, | |
| const GrUserStencilSettings* stencilSettings) { | |
| auto tmp = arena->make<GrProgramInfo>(*caps, | |
| writeView, | |
| usesMSAASurface, | |
| pipeline, | |
| stencilSettings, | |
| geometryProcessor, | |
| primitiveType, | |
| xferBarrierFlags, | |
| colorLoadOp); | |
| return tmp; | |
| } | |
| GrProgramInfo* GrSimpleMeshDrawOpHelper::createProgramInfo( | |
| const GrCaps* caps, | |
| SkArenaAlloc* arena, | |
| const GrSurfaceProxyView& writeView, | |
| bool usesMSAASurface, | |
| GrAppliedClip&& appliedClip, | |
| const GrDstProxyView& dstProxyView, | |
| GrGeometryProcessor* gp, | |
| GrPrimitiveType primType, | |
| GrXferBarrierFlags renderPassXferBarriers, | |
| GrLoadOp colorLoadOp) { | |
| return CreateProgramInfo(caps, | |
| arena, | |
| writeView, | |
| usesMSAASurface, | |
| std::move(appliedClip), | |
| dstProxyView, | |
| gp, | |
| this->detachProcessorSet(), | |
| primType, | |
| renderPassXferBarriers, | |
| colorLoadOp, | |
| this->pipelineFlags()); | |
| } | |
| #if defined(GPU_TEST_UTILS) | |
| 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::kWireframe) { | |
| result->append("Wireframe enabled.\n"); | |
| } | |
| if (flags & GrPipeline::InputFlags::kConservativeRaster) { | |
| result->append("Conservative raster 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 |