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 "GrMeshDrawOp.h"
     12 #include "GrOpFlushState.h"
     13 #include "GrPipeline.h"
     14 
     15 struct SkRect;
     16 
     17 /**
     18  * This class can be used to help implement simple mesh draw ops. It reduces the amount of
     19  * boilerplate code to type and also provides a mechanism for optionally allocating space for a
     20  * GrProcessorSet based on a GrPaint. It is intended to be used by ops that construct a single
     21  * GrPipeline for a uniform primitive color and a GrPaint.
     22  */
     23 class GrSimpleMeshDrawOpHelper {
     24 public:
     25     struct MakeArgs;
     26 
     27     /**
     28      * This can be used by a Op class to perform allocation and initialization such that a
     29      * GrProcessorSet (if required) is allocated as part of the the same allocation that as
     30      * the Op instance. It requires that Op implements a constructor of the form:
     31      *      Op(MakeArgs, GrColor, OpArgs...)
     32      * which is public or made accessible via 'friend'.
     33      */
     34     template <typename Op, typename... OpArgs>
     35     static std::unique_ptr<GrDrawOp> FactoryHelper(GrPaint&& paint, OpArgs... opArgs);
     36 
     37     enum class Flags : uint32_t {
     38         kNone = 0x0,
     39         kSnapVerticesToPixelCenters = 0x1,
     40     };
     41     GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(Flags);
     42 
     43     GrSimpleMeshDrawOpHelper(const MakeArgs&, GrAAType, Flags = Flags::kNone);
     44     ~GrSimpleMeshDrawOpHelper();
     45 
     46     GrSimpleMeshDrawOpHelper() = delete;
     47     GrSimpleMeshDrawOpHelper(const GrSimpleMeshDrawOpHelper&) = delete;
     48     GrSimpleMeshDrawOpHelper& operator=(const GrSimpleMeshDrawOpHelper&) = delete;
     49 
     50     GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const;
     51 
     52     bool isCompatible(const GrSimpleMeshDrawOpHelper& that, const GrCaps&, const SkRect& thisBounds,
     53                       const SkRect& thatBounds) const;
     54 
     55     /**
     56      * Finalizes the processor set and determines whether the destination must be provided
     57      * to the fragment shader as a texture for blending.
     58      *
     59      * @param geometryCoverage Describes the coverage output of the op's geometry processor
     60      * @param geometryColor An in/out param. As input this informs processor analysis about the
     61      *                      color the op expects to output from its geometry processor. As output
     62      *                      this may be set to a known color in which case the op must output this
     63      *                      color from its geometry processor instead.
     64      */
     65     GrDrawOp::RequiresDstTexture xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip,
     66                                                       GrProcessorAnalysisCoverage geometryCoverage,
     67                                                       GrProcessorAnalysisColor* geometryColor);
     68 
     69     /**
     70      * Version of above that can be used by ops that have a constant color geometry processor
     71      * output. The op passes this color as 'geometryColor' and after return if 'geometryColor' has
     72      * changed the op must override its geometry processor color output with the new color.
     73      */
     74     GrDrawOp::RequiresDstTexture xpRequiresDstTexture(const GrCaps&, const GrAppliedClip*,
     75                                                       GrProcessorAnalysisCoverage geometryCoverage,
     76                                                       GrColor* geometryColor);
     77 
     78     bool usesLocalCoords() const {
     79         SkASSERT(fDidAnalysis);
     80         return fUsesLocalCoords;
     81     }
     82 
     83     bool compatibleWithAlphaAsCoverage() const { return fCompatibleWithAlphaAsCoveage; }
     84 
     85     GrPipeline* makePipeline(GrMeshDrawOp::Target* target) const {
     86         return target->allocPipeline(this->pipelineInitArgs(target));
     87     }
     88 
     89     struct MakeArgs {
     90     private:
     91         MakeArgs() = default;
     92 
     93         GrProcessorSet* fProcessorSet;
     94         uint32_t fSRGBFlags;
     95 
     96         friend class GrSimpleMeshDrawOpHelper;
     97     };
     98 
     99     SkString dumpInfo() const;
    100 
    101 protected:
    102     GrAAType aaType() const { return static_cast<GrAAType>(fAAType); }
    103     uint32_t pipelineFlags() const { return fPipelineFlags; }
    104     const GrProcessorSet& processors() const {
    105         return fProcessors ? *fProcessors : GrProcessorSet::EmptySet();
    106     }
    107 
    108     GrPipeline::InitArgs pipelineInitArgs(GrMeshDrawOp::Target* target) const;
    109 
    110 private:
    111     GrProcessorSet* fProcessors;
    112     unsigned fPipelineFlags : 8;
    113     unsigned fAAType : 2;
    114     unsigned fRequiresDstTexture : 1;
    115     unsigned fUsesLocalCoords : 1;
    116     unsigned fCompatibleWithAlphaAsCoveage : 1;
    117     SkDEBUGCODE(unsigned fDidAnalysis : 1;)
    118 };
    119 
    120 /**
    121  * This class extends GrSimpleMeshDrawOpHelper to support an optional GrUserStencilSettings. This
    122  * uses private inheritance because it non-virtually overrides methods in the base class and should
    123  * never be used with a GrSimpleMeshDrawOpHelper pointer or reference.
    124  */
    125 class GrSimpleMeshDrawOpHelperWithStencil : private GrSimpleMeshDrawOpHelper {
    126 public:
    127     using MakeArgs = GrSimpleMeshDrawOpHelper::MakeArgs;
    128     using Flags = GrSimpleMeshDrawOpHelper::Flags;
    129 
    130     // using declarations can't be templated, so this is a pass through function instead.
    131     template <typename Op, typename... OpArgs>
    132     static std::unique_ptr<GrDrawOp> FactoryHelper(GrPaint&& paint, OpArgs... opArgs) {
    133         return GrSimpleMeshDrawOpHelper::FactoryHelper<Op, OpArgs...>(
    134                 std::move(paint), std::forward<OpArgs>(opArgs)...);
    135     }
    136 
    137     GrSimpleMeshDrawOpHelperWithStencil(const MakeArgs&, GrAAType, const GrUserStencilSettings*,
    138                                         Flags = Flags::kNone);
    139 
    140     GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const;
    141 
    142     using GrSimpleMeshDrawOpHelper::xpRequiresDstTexture;
    143     using GrSimpleMeshDrawOpHelper::usesLocalCoords;
    144     using GrSimpleMeshDrawOpHelper::compatibleWithAlphaAsCoverage;
    145 
    146     bool isCompatible(const GrSimpleMeshDrawOpHelperWithStencil& that, const GrCaps&,
    147                       const SkRect& thisBounds, const SkRect& thatBounds) const;
    148 
    149     const GrPipeline* makePipeline(GrMeshDrawOp::Target*) const;
    150 
    151     SkString dumpInfo() const;
    152 
    153 private:
    154     const GrUserStencilSettings* fStencilSettings;
    155     typedef GrSimpleMeshDrawOpHelper INHERITED;
    156 };
    157 
    158 template <typename Op, typename... OpArgs>
    159 std::unique_ptr<GrDrawOp> GrSimpleMeshDrawOpHelper::FactoryHelper(GrPaint&& paint,
    160                                                                   OpArgs... opArgs) {
    161     MakeArgs makeArgs;
    162     makeArgs.fSRGBFlags = GrPipeline::SRGBFlagsFromPaint(paint);
    163     GrColor color = paint.getColor();
    164     if (paint.isTrivial()) {
    165         makeArgs.fProcessorSet = nullptr;
    166         return std::unique_ptr<GrDrawOp>(new Op(makeArgs, color, std::forward<OpArgs>(opArgs)...));
    167     } else {
    168         char* mem = (char*)GrOp::operator new(sizeof(Op) + sizeof(GrProcessorSet));
    169         char* setMem = mem + sizeof(Op);
    170         makeArgs.fProcessorSet = new (setMem) GrProcessorSet(std::move(paint));
    171         return std::unique_ptr<GrDrawOp>(
    172                 new (mem) Op(makeArgs, color, std::forward<OpArgs>(opArgs)...));
    173     }
    174 }
    175 
    176 GR_MAKE_BITFIELD_CLASS_OPS(GrSimpleMeshDrawOpHelper::Flags)
    177 
    178 #endif
    179