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 "GrRenderTargetProxy.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
29class GrAppliedClip;
30class GrDeviceCoordTexture;
31class GrOp;
32class 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 */
39class GrPipeline {
40public:
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 GrUserStencilSettings* fUserStencil = &GrUserStencilSettings::kUnused;
80        GrRenderTargetProxy* fProxy = nullptr;
81        const GrCaps* fCaps = nullptr;
82        GrResourceProvider* fResourceProvider = nullptr;
83        GrXferProcessor::DstProxy fDstProxy;
84    };
85
86    /**
87     *  Graphics state that can change dynamically without creating a new pipeline.
88     **/
89    struct DynamicState {
90        // Overrides the scissor rectangle (if scissor is enabled in the pipeline).
91        // TODO: eventually this should be the only way to specify a scissor rectangle, as is the
92        // case with the simple constructor.
93        SkIRect fScissorRect;
94    };
95
96    /**
97     * Creates a simple pipeline with default settings and no processors. The provided blend mode
98     * must be "Porter Duff" (<= kLastCoeffMode). If using ScissorState::kEnabled, the caller must
99     * specify a scissor rectangle through the DynamicState struct.
100     **/
101    GrPipeline(GrRenderTargetProxy*, ScissorState, SkBlendMode);
102
103    GrPipeline(const InitArgs&, GrProcessorSet&&, GrAppliedClip&&);
104
105    GrPipeline(const GrPipeline&) = delete;
106    GrPipeline& operator=(const GrPipeline&) = delete;
107
108    /// @}
109
110    ///////////////////////////////////////////////////////////////////////////
111    /// @name GrFragmentProcessors
112
113    // Make the renderTargetContext's GrOpList be dependent on any GrOpLists in this pipeline
114    void addDependenciesTo(GrOpList* recipient, const GrCaps&) const;
115
116    int numColorFragmentProcessors() const { return fNumColorProcessors; }
117    int numCoverageFragmentProcessors() const {
118        return fFragmentProcessors.count() - fNumColorProcessors;
119    }
120    int numFragmentProcessors() const { return fFragmentProcessors.count(); }
121
122    const GrXferProcessor& getXferProcessor() const {
123        if (fXferProcessor) {
124            return *fXferProcessor.get();
125        } else {
126            // A null xp member means the common src-over case. GrXferProcessor's ref'ing
127            // mechanism is not thread safe so we do not hold a ref on this global.
128            return GrPorterDuffXPFactory::SimpleSrcOverXP();
129        }
130    }
131
132    /**
133     * If the GrXferProcessor uses a texture to access the dst color, then this returns that
134     * texture and the offset to the dst contents within that texture.
135     */
136    GrTextureProxy* dstTextureProxy(SkIPoint* offset = nullptr) const {
137        if (offset) {
138            *offset = fDstTextureOffset;
139        }
140        return fDstTextureProxy.get();
141    }
142
143    GrTexture* peekDstTexture(SkIPoint* offset = nullptr) const {
144        if (GrTextureProxy* dstProxy = this->dstTextureProxy(offset)) {
145            return dstProxy->priv().peekTexture();
146        }
147
148        return nullptr;
149    }
150
151    const GrFragmentProcessor& getColorFragmentProcessor(int idx) const {
152        SkASSERT(idx < this->numColorFragmentProcessors());
153        return *fFragmentProcessors[idx].get();
154    }
155
156    const GrFragmentProcessor& getCoverageFragmentProcessor(int idx) const {
157        SkASSERT(idx < this->numCoverageFragmentProcessors());
158        return *fFragmentProcessors[fNumColorProcessors + idx].get();
159    }
160
161    const GrFragmentProcessor& getFragmentProcessor(int idx) const {
162        return *fFragmentProcessors[idx].get();
163    }
164
165    /// @}
166
167    /**
168     * Retrieves the currently set render-target.
169     *
170     * @return    The currently set render target.
171     */
172    GrRenderTargetProxy* proxy() const { return fProxy.get(); }
173    GrRenderTarget* renderTarget() const { return fProxy.get()->priv().peekRenderTarget(); }
174
175    const GrUserStencilSettings* getUserStencil() const { return fUserStencilSettings; }
176
177    const GrScissorState& getScissorState() const { return fScissorState; }
178
179    const GrWindowRectsState& getWindowRectsState() const { return fWindowRectsState; }
180
181    bool isHWAntialiasState() const { return SkToBool(fFlags & kHWAntialias_Flag); }
182    bool snapVerticesToPixelCenters() const {
183        return SkToBool(fFlags & kSnapVerticesToPixelCenters_Flag);
184    }
185    bool getDisableOutputConversionToSRGB() const {
186        return SkToBool(fFlags & kDisableOutputConversionToSRGB_Flag);
187    }
188    bool getAllowSRGBInputs() const {
189        return SkToBool(fFlags & kAllowSRGBInputs_Flag);
190    }
191    bool hasStencilClip() const {
192        return SkToBool(fFlags & kHasStencilClip_Flag);
193    }
194    bool isStencilEnabled() const {
195        return SkToBool(fFlags & kStencilEnabled_Flag);
196    }
197    bool isBad() const { return SkToBool(fFlags & kIsBad_Flag); }
198
199    GrXferBarrierType xferBarrierType(const GrCaps& caps) const;
200
201    static SkString DumpFlags(uint32_t flags) {
202        if (flags) {
203            SkString result;
204            if (flags & GrPipeline::kSnapVerticesToPixelCenters_Flag) {
205                result.append("Snap vertices to pixel center.\n");
206            }
207            if (flags & GrPipeline::kHWAntialias_Flag) {
208                result.append("HW Antialiasing enabled.\n");
209            }
210            if (flags & GrPipeline::kDisableOutputConversionToSRGB_Flag) {
211                result.append("Disable output conversion to sRGB.\n");
212            }
213            if (flags & GrPipeline::kAllowSRGBInputs_Flag) {
214                result.append("Allow sRGB Inputs.\n");
215            }
216            return result;
217        }
218        return SkString("No pipeline flags\n");
219    }
220
221private:
222    void markAsBad() { fFlags |= kIsBad_Flag; }
223
224    /** This is a continuation of the public "Flags" enum. */
225    enum PrivateFlags {
226        kHasStencilClip_Flag = 0x10,
227        kStencilEnabled_Flag = 0x20,
228        kIsBad_Flag = 0x40,
229    };
230
231    using RenderTargetProxy = GrPendingIOResource<GrRenderTargetProxy, kWrite_GrIOType>;
232    using DstTextureProxy = GrPendingIOResource<GrTextureProxy, kRead_GrIOType>;
233    using FragmentProcessorArray = SkAutoSTArray<8, std::unique_ptr<const GrFragmentProcessor>>;
234
235    DstTextureProxy fDstTextureProxy;
236    SkIPoint fDstTextureOffset;
237    // MDB TODO: do we still need the destination proxy here?
238    RenderTargetProxy fProxy;
239    GrScissorState fScissorState;
240    GrWindowRectsState fWindowRectsState;
241    const GrUserStencilSettings* fUserStencilSettings;
242    uint16_t fFlags;
243    sk_sp<const GrXferProcessor> fXferProcessor;
244    FragmentProcessorArray fFragmentProcessors;
245
246    // This value is also the index in fFragmentProcessors where coverage processors begin.
247    int fNumColorProcessors;
248
249    typedef SkRefCnt INHERITED;
250};
251
252#endif
253