Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2015 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 GrPipeline_DEFINED
      9 #define GrPipeline_DEFINED
     10 
     11 #include "GrColor.h"
     12 #include "GrFragmentProcessor.h"
     13 #include "GrNonAtomicRef.h"
     14 #include "GrPendingProgramElement.h"
     15 #include "GrProcessorSet.h"
     16 #include "GrProgramDesc.h"
     17 #include "GrRect.h"
     18 #include "GrRenderTarget.h"
     19 #include "GrScissorState.h"
     20 #include "GrUserStencilSettings.h"
     21 #include "GrWindowRectsState.h"
     22 #include "SkMatrix.h"
     23 #include "SkRefCnt.h"
     24 #include "effects/GrCoverageSetOpXP.h"
     25 #include "effects/GrDisableColorXP.h"
     26 #include "effects/GrPorterDuffXferProcessor.h"
     27 #include "effects/GrSimpleTextureEffect.h"
     28 
     29 class GrAppliedClip;
     30 class GrDeviceCoordTexture;
     31 class GrOp;
     32 class GrRenderTargetContext;
     33 
     34 /**
     35  * This immutable object contains information needed to set build a shader program and set API
     36  * state for a draw. It is used along with a GrPrimitiveProcessor and a source of geometric
     37  * data (GrMesh or GrPath) to draw.
     38  */
     39 class GrPipeline : public GrNonAtomicRef<GrPipeline> {
     40 public:
     41     ///////////////////////////////////////////////////////////////////////////
     42     /// @name Creation
     43 
     44     enum Flags {
     45         /**
     46          * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
     47          * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
     48          * the 3D API.
     49          */
     50         kHWAntialias_Flag = 0x1,
     51         /**
     52          * Modifies the vertex shader so that vertices will be positioned at pixel centers.
     53          */
     54         kSnapVerticesToPixelCenters_Flag = 0x2,
     55         /** Disables conversion to sRGB from linear when writing to a sRGB destination. */
     56         kDisableOutputConversionToSRGB_Flag = 0x4,
     57         /** Allows conversion from sRGB to linear when reading from processor's sRGB texture. */
     58         kAllowSRGBInputs_Flag = 0x8,
     59     };
     60 
     61     static uint32_t SRGBFlagsFromPaint(const GrPaint& paint) {
     62         uint32_t flags = 0;
     63         if (paint.getAllowSRGBInputs()) {
     64             flags |= kAllowSRGBInputs_Flag;
     65         }
     66         if (paint.getDisableOutputConversionToSRGB()) {
     67             flags |= kDisableOutputConversionToSRGB_Flag;
     68         }
     69         return flags;
     70     }
     71 
     72     enum ScissorState : bool {
     73         kEnabled = true,
     74         kDisabled = false
     75     };
     76 
     77     struct InitArgs {
     78         uint32_t fFlags = 0;
     79         const GrProcessorSet* fProcessors = nullptr;  // Must be finalized
     80         const GrUserStencilSettings* fUserStencil = &GrUserStencilSettings::kUnused;
     81         const GrAppliedClip* fAppliedClip = nullptr;
     82         GrRenderTarget* fRenderTarget = nullptr;
     83         const GrCaps* fCaps = nullptr;
     84         GrResourceProvider* fResourceProvider = nullptr;
     85         GrXferProcessor::DstProxy fDstProxy;
     86     };
     87 
     88     /**
     89      *  Graphics state that can change dynamically without creating a new pipeline.
     90      **/
     91     struct DynamicState {
     92         // Overrides the scissor rectangle (if scissor is enabled in the pipeline).
     93         // TODO: eventually this should be the only way to specify a scissor rectangle, as is the
     94         // case with the simple constructor.
     95         SkIRect fScissorRect;
     96     };
     97 
     98     /**
     99      * A Default constructed pipeline is unusable until init() is called.
    100      **/
    101     GrPipeline() = default;
    102 
    103     /**
    104      * Creates a simple pipeline with default settings and no processors. The provided blend mode
    105      * must be "Porter Duff" (<= kLastCoeffMode). If using ScissorState::kEnabled, the caller must
    106      * specify a scissor rectangle through the DynamicState struct.
    107      **/
    108     GrPipeline(GrRenderTarget*, ScissorState, SkBlendMode);
    109 
    110     GrPipeline(const InitArgs& args) { this->init(args); }
    111 
    112     /** (Re)initializes a pipeline. After initialization the pipeline can be used. */
    113     void init(const InitArgs&);
    114 
    115     /** True if the pipeline has been initialized. */
    116     bool isInitialized() const { return SkToBool(fRenderTarget.get()); }
    117 
    118     /// @}
    119 
    120     ///////////////////////////////////////////////////////////////////////////
    121     /// @name Comparisons
    122 
    123     /**
    124      * Returns true if these pipelines are equivalent.  Coord transforms may be applied either on
    125      * the GPU or the CPU. When we apply them on the CPU then the matrices need not agree in order
    126      * to combine draws. Therefore we take a param that indicates whether coord transforms should be
    127      * compared."
    128      */
    129     static bool AreEqual(const GrPipeline& a, const GrPipeline& b);
    130 
    131     /**
    132      * Allows a GrOp subclass to determine whether two GrOp instances can combine. This is a
    133      * stricter test than isEqual because it also considers blend barriers when the two ops'
    134      * bounds overlap
    135      */
    136     static bool CanCombine(const GrPipeline& a, const SkRect& aBounds,
    137                            const GrPipeline& b, const SkRect& bBounds,
    138                            const GrCaps& caps)  {
    139         if (!AreEqual(a, b)) {
    140             return false;
    141         }
    142         if (a.xferBarrierType(caps)) {
    143             return !GrRectsTouchOrOverlap(aBounds, bBounds);
    144         }
    145         return true;
    146     }
    147 
    148     /// @}
    149 
    150     ///////////////////////////////////////////////////////////////////////////
    151     /// @name GrFragmentProcessors
    152 
    153     // Make the renderTargetContext's GrOpList be dependent on any GrOpLists in this pipeline
    154     void addDependenciesTo(GrOpList* recipient, const GrCaps&) const;
    155 
    156     int numColorFragmentProcessors() const { return fNumColorProcessors; }
    157     int numCoverageFragmentProcessors() const {
    158         return fFragmentProcessors.count() - fNumColorProcessors;
    159     }
    160     int numFragmentProcessors() const { return fFragmentProcessors.count(); }
    161 
    162     const GrXferProcessor& getXferProcessor() const {
    163         if (fXferProcessor) {
    164             return *fXferProcessor.get();
    165         } else {
    166             // A null xp member means the common src-over case. GrXferProcessor's ref'ing
    167             // mechanism is not thread safe so we do not hold a ref on this global.
    168             return GrPorterDuffXPFactory::SimpleSrcOverXP();
    169         }
    170     }
    171 
    172     /**
    173      * If the GrXferProcessor uses a texture to access the dst color, then this returns that
    174      * texture and the offset to the dst contents within that texture.
    175      */
    176     GrTextureProxy* dstTextureProxy(SkIPoint* offset = nullptr) const {
    177         if (offset) {
    178             *offset = fDstTextureOffset;
    179         }
    180         return fDstTextureProxy.get();
    181     }
    182 
    183     GrTexture* peekDstTexture(SkIPoint* offset = nullptr) const {
    184         if (GrTextureProxy* dstProxy = this->dstTextureProxy(offset)) {
    185             return dstProxy->priv().peekTexture();
    186         }
    187 
    188         return nullptr;
    189     }
    190 
    191     const GrFragmentProcessor& getColorFragmentProcessor(int idx) const {
    192         SkASSERT(idx < this->numColorFragmentProcessors());
    193         return *fFragmentProcessors[idx].get();
    194     }
    195 
    196     const GrFragmentProcessor& getCoverageFragmentProcessor(int idx) const {
    197         SkASSERT(idx < this->numCoverageFragmentProcessors());
    198         return *fFragmentProcessors[fNumColorProcessors + idx].get();
    199     }
    200 
    201     const GrFragmentProcessor& getFragmentProcessor(int idx) const {
    202         return *fFragmentProcessors[idx].get();
    203     }
    204 
    205     /// @}
    206 
    207     /**
    208      * Retrieves the currently set render-target.
    209      *
    210      * @return    The currently set render target.
    211      */
    212     GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
    213 
    214     const GrUserStencilSettings* getUserStencil() const { return fUserStencilSettings; }
    215 
    216     const GrScissorState& getScissorState() const { return fScissorState; }
    217 
    218     const GrWindowRectsState& getWindowRectsState() const { return fWindowRectsState; }
    219 
    220     bool isHWAntialiasState() const { return SkToBool(fFlags & kHWAntialias_Flag); }
    221     bool snapVerticesToPixelCenters() const {
    222         return SkToBool(fFlags & kSnapVerticesToPixelCenters_Flag);
    223     }
    224     bool getDisableOutputConversionToSRGB() const {
    225         return SkToBool(fFlags & kDisableOutputConversionToSRGB_Flag);
    226     }
    227     bool getAllowSRGBInputs() const {
    228         return SkToBool(fFlags & kAllowSRGBInputs_Flag);
    229     }
    230     bool hasStencilClip() const {
    231         return SkToBool(fFlags & kHasStencilClip_Flag);
    232     }
    233     bool isStencilEnabled() const {
    234         return SkToBool(fFlags & kStencilEnabled_Flag);
    235     }
    236     bool isBad() const { return SkToBool(fFlags & kIsBad_Flag); }
    237 
    238     GrXferBarrierType xferBarrierType(const GrCaps& caps) const;
    239 
    240     static SkString DumpFlags(uint32_t flags) {
    241         if (flags) {
    242             SkString result;
    243             if (flags & GrPipeline::kSnapVerticesToPixelCenters_Flag) {
    244                 result.append("Snap vertices to pixel center.\n");
    245             }
    246             if (flags & GrPipeline::kHWAntialias_Flag) {
    247                 result.append("HW Antialiasing enabled.\n");
    248             }
    249             if (flags & GrPipeline::kDisableOutputConversionToSRGB_Flag) {
    250                 result.append("Disable output conversion to sRGB.\n");
    251             }
    252             if (flags & GrPipeline::kAllowSRGBInputs_Flag) {
    253                 result.append("Allow sRGB Inputs.\n");
    254             }
    255             return result;
    256         }
    257         return SkString("No pipeline flags\n");
    258     }
    259 
    260 private:
    261     void markAsBad() { fFlags |= kIsBad_Flag; }
    262 
    263     /** This is a continuation of the public "Flags" enum. */
    264     enum PrivateFlags {
    265         kHasStencilClip_Flag = 0x10,
    266         kStencilEnabled_Flag = 0x20,
    267         kIsBad_Flag = 0x40,
    268     };
    269 
    270     using RenderTarget = GrPendingIOResource<GrRenderTarget, kWrite_GrIOType>;
    271     using DstTextureProxy = GrPendingIOResource<GrTextureProxy, kRead_GrIOType>;
    272     using PendingFragmentProcessor = GrPendingProgramElement<const GrFragmentProcessor>;
    273     using FragmentProcessorArray = SkAutoSTArray<8, PendingFragmentProcessor>;
    274 
    275     DstTextureProxy fDstTextureProxy;
    276     SkIPoint fDstTextureOffset;
    277     RenderTarget fRenderTarget;
    278     GrScissorState fScissorState;
    279     GrWindowRectsState fWindowRectsState;
    280     const GrUserStencilSettings* fUserStencilSettings;
    281     uint16_t fFlags;
    282     sk_sp<const GrXferProcessor> fXferProcessor;
    283     FragmentProcessorArray fFragmentProcessors;
    284 
    285     // This value is also the index in fFragmentProcessors where coverage processors begin.
    286     int fNumColorProcessors;
    287 
    288     typedef SkRefCnt INHERITED;
    289 };
    290 
    291 #endif
    292