Home | History | Annotate | Download | only in ops
      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 #ifndef GrSimpleMeshDrawOpHelper_DEFINED
      9 #define GrSimpleMeshDrawOpHelper_DEFINED
     10 
     11 #include "GrMemoryPool.h" // only here bc of the templated FactoryHelper
     12 #include "GrMeshDrawOp.h"
     13 #include "GrOpFlushState.h"
     14 #include "GrPipeline.h"
     15 #include "GrRecordingContext.h"
     16 #include "GrRecordingContextPriv.h"
     17 #include <new>
     18 
     19 struct SkRect;
     20 
     21 /**
     22  * This class can be used to help implement simple mesh draw ops. It reduces the amount of
     23  * boilerplate code to type and also provides a mechanism for optionally allocating space for a
     24  * GrProcessorSet based on a GrPaint. It is intended to be used by ops that construct a single
     25  * GrPipeline for a uniform primitive color and a GrPaint.
     26  */
     27 class GrSimpleMeshDrawOpHelper {
     28 public:
     29     struct MakeArgs;
     30 
     31     /**
     32      * This can be used by a Op class to perform allocation and initialization such that a
     33      * GrProcessorSet (if required) is allocated as part of the the same allocation that as
     34      * the Op instance. It requires that Op implements a constructor of the form:
     35      *      Op(MakeArgs, GrColor, OpArgs...)
     36      * which is public or made accessible via 'friend'.
     37      */
     38     template <typename Op, typename... OpArgs>
     39     static std::unique_ptr<GrDrawOp> FactoryHelper(GrRecordingContext*, GrPaint&&, OpArgs...);
     40 
     41     enum class Flags : uint32_t {
     42         kNone = 0x0,
     43         kSnapVerticesToPixelCenters = 0x1,
     44     };
     45     GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(Flags);
     46 
     47     GrSimpleMeshDrawOpHelper(const MakeArgs&, GrAAType, Flags = Flags::kNone);
     48     ~GrSimpleMeshDrawOpHelper();
     49 
     50     GrSimpleMeshDrawOpHelper() = delete;
     51     GrSimpleMeshDrawOpHelper(const GrSimpleMeshDrawOpHelper&) = delete;
     52     GrSimpleMeshDrawOpHelper& operator=(const GrSimpleMeshDrawOpHelper&) = delete;
     53 
     54     GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const;
     55 
     56     // noneAACompatibleWithCoverage should be set to true if the op can properly render a non-AA
     57     // primitive merged into a coverage-based op.
     58     bool isCompatible(const GrSimpleMeshDrawOpHelper& that, const GrCaps&, const SkRect& thisBounds,
     59                       const SkRect& thatBounds, bool noneAACompatibleWithCoverage = false) const;
     60 
     61     /**
     62      * Finalizes the processor set and determines whether the destination must be provided
     63      * to the fragment shader as a texture for blending.
     64      *
     65      * @param geometryCoverage Describes the coverage output of the op's geometry processor
     66      * @param geometryColor An in/out param. As input this informs processor analysis about the
     67      *                      color the op expects to output from its geometry processor. As output
     68      *                      this may be set to a known color in which case the op must output this
     69      *                      color from its geometry processor instead.
     70      */
     71     GrProcessorSet::Analysis finalizeProcessors(
     72             const GrCaps& caps, const GrAppliedClip* clip, GrFSAAType fsaaType,
     73             GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage,
     74             GrProcessorAnalysisColor* geometryColor) {
     75         return this->finalizeProcessors(caps, clip, &GrUserStencilSettings::kUnused, fsaaType,
     76                                         clampType, geometryCoverage, geometryColor);
     77     }
     78 
     79     /**
     80      * Version of above that can be used by ops that have a constant color geometry processor
     81      * output. The op passes this color as 'geometryColor' and after return if 'geometryColor' has
     82      * changed the op must override its geometry processor color output with the new color.
     83      */
     84     GrProcessorSet::Analysis finalizeProcessors(
     85             const GrCaps&, const GrAppliedClip*, GrFSAAType, GrClampType,
     86             GrProcessorAnalysisCoverage geometryCoverage, SkPMColor4f* geometryColor);
     87 
     88     bool isTrivial() const {
     89       return fProcessors == nullptr;
     90     }
     91 
     92     bool usesLocalCoords() const {
     93         SkASSERT(fDidAnalysis);
     94         return fUsesLocalCoords;
     95     }
     96 
     97     bool compatibleWithAlphaAsCoverage() const { return fCompatibleWithAlphaAsCoveage; }
     98 
     99     struct MakeArgs {
    100     private:
    101         MakeArgs() = default;
    102 
    103         GrProcessorSet* fProcessorSet;
    104 
    105         friend class GrSimpleMeshDrawOpHelper;
    106     };
    107 
    108     void visitProxies(const std::function<void(GrSurfaceProxy*)>& func) const {
    109         if (fProcessors) {
    110             fProcessors->visitProxies(func);
    111         }
    112     }
    113 
    114 #ifdef SK_DEBUG
    115     SkString dumpInfo() const;
    116 #endif
    117     GrAAType aaType() const { return static_cast<GrAAType>(fAAType); }
    118 
    119     void setAAType(GrAAType aaType) {
    120       fAAType = static_cast<unsigned>(aaType);
    121     }
    122 
    123     void executeDrawsAndUploads(const GrOp*, GrOpFlushState*, const SkRect& chainBounds);
    124 
    125 protected:
    126     uint32_t pipelineFlags() const { return fPipelineFlags; }
    127 
    128     GrProcessorSet::Analysis finalizeProcessors(
    129             const GrCaps& caps, const GrAppliedClip*, const GrUserStencilSettings*, GrFSAAType,
    130             GrClampType, GrProcessorAnalysisCoverage geometryCoverage,
    131             GrProcessorAnalysisColor* geometryColor);
    132 
    133     GrProcessorSet* fProcessors;
    134     unsigned fPipelineFlags : 8;
    135     unsigned fAAType : 2;
    136     unsigned fUsesLocalCoords : 1;
    137     unsigned fCompatibleWithAlphaAsCoveage : 1;
    138     SkDEBUGCODE(unsigned fMadePipeline : 1;)
    139     SkDEBUGCODE(unsigned fDidAnalysis : 1;)
    140 };
    141 
    142 /**
    143  * This class extends GrSimpleMeshDrawOpHelper to support an optional GrUserStencilSettings. This
    144  * uses private inheritance because it non-virtually overrides methods in the base class and should
    145  * never be used with a GrSimpleMeshDrawOpHelper pointer or reference.
    146  */
    147 class GrSimpleMeshDrawOpHelperWithStencil : private GrSimpleMeshDrawOpHelper {
    148 public:
    149     using MakeArgs = GrSimpleMeshDrawOpHelper::MakeArgs;
    150     using Flags = GrSimpleMeshDrawOpHelper::Flags;
    151 
    152     using GrSimpleMeshDrawOpHelper::visitProxies;
    153 
    154     // using declarations can't be templated, so this is a pass through function instead.
    155     template <typename Op, typename... OpArgs>
    156     static std::unique_ptr<GrDrawOp> FactoryHelper(GrRecordingContext* context, GrPaint&& paint,
    157                                                    OpArgs... opArgs) {
    158         return GrSimpleMeshDrawOpHelper::FactoryHelper<Op, OpArgs...>(
    159                 context, std::move(paint), std::forward<OpArgs>(opArgs)...);
    160     }
    161 
    162     GrSimpleMeshDrawOpHelperWithStencil(const MakeArgs&, GrAAType, const GrUserStencilSettings*,
    163                                         Flags = Flags::kNone);
    164 
    165     GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const;
    166 
    167     GrProcessorSet::Analysis finalizeProcessors(
    168             const GrCaps& caps, const GrAppliedClip* clip, GrFSAAType fsaaType,
    169             GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage,
    170             GrProcessorAnalysisColor* geometryColor) {
    171         return this->INHERITED::finalizeProcessors(
    172                 caps, clip, fStencilSettings, fsaaType, clampType, geometryCoverage, geometryColor);
    173     }
    174 
    175     GrProcessorSet::Analysis finalizeProcessors(
    176             const GrCaps&, const GrAppliedClip*, GrFSAAType, GrClampType,
    177             GrProcessorAnalysisCoverage geometryCoverage, SkPMColor4f* geometryColor);
    178 
    179     using GrSimpleMeshDrawOpHelper::aaType;
    180     using GrSimpleMeshDrawOpHelper::setAAType;
    181     using GrSimpleMeshDrawOpHelper::isTrivial;
    182     using GrSimpleMeshDrawOpHelper::usesLocalCoords;
    183     using GrSimpleMeshDrawOpHelper::compatibleWithAlphaAsCoverage;
    184 
    185     bool isCompatible(const GrSimpleMeshDrawOpHelperWithStencil& that, const GrCaps&,
    186                       const SkRect& thisBounds, const SkRect& thatBounds,
    187                       bool noneAACompatibleWithCoverage = false) const;
    188 
    189     void executeDrawsAndUploads(const GrOp*, GrOpFlushState*, const SkRect& chainBounds);
    190 
    191 #ifdef SK_DEBUG
    192     SkString dumpInfo() const;
    193 #endif
    194 
    195 private:
    196     const GrUserStencilSettings* fStencilSettings;
    197     typedef GrSimpleMeshDrawOpHelper INHERITED;
    198 };
    199 
    200 template <typename Op, typename... OpArgs>
    201 std::unique_ptr<GrDrawOp> GrSimpleMeshDrawOpHelper::FactoryHelper(GrRecordingContext* context,
    202                                                                   GrPaint&& paint,
    203                                                                   OpArgs... opArgs) {
    204     GrOpMemoryPool* pool = context->priv().opMemoryPool();
    205 
    206     MakeArgs makeArgs;
    207 
    208     if (paint.isTrivial()) {
    209         makeArgs.fProcessorSet = nullptr;
    210         return pool->allocate<Op>(makeArgs, paint.getColor4f(), std::forward<OpArgs>(opArgs)...);
    211     } else {
    212         char* mem = (char*) pool->allocate(sizeof(Op) + sizeof(GrProcessorSet));
    213         char* setMem = mem + sizeof(Op);
    214         auto color = paint.getColor4f();
    215         makeArgs.fProcessorSet = new (setMem) GrProcessorSet(std::move(paint));
    216         return std::unique_ptr<GrDrawOp>(new (mem) Op(makeArgs, color,
    217                                                       std::forward<OpArgs>(opArgs)...));
    218     }
    219 }
    220 
    221 GR_MAKE_BITFIELD_CLASS_OPS(GrSimpleMeshDrawOpHelper::Flags)
    222 
    223 #endif
    224