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 
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 {
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 
SRGBFlagsFromPaint(const GrPaint & paint)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 
numColorFragmentProcessors()116     int numColorFragmentProcessors() const { return fNumColorProcessors; }
numCoverageFragmentProcessors()117     int numCoverageFragmentProcessors() const {
118         return fFragmentProcessors.count() - fNumColorProcessors;
119     }
numFragmentProcessors()120     int numFragmentProcessors() const { return fFragmentProcessors.count(); }
121 
getXferProcessor()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 
getColorFragmentProcessor(int idx)151     const GrFragmentProcessor& getColorFragmentProcessor(int idx) const {
152         SkASSERT(idx < this->numColorFragmentProcessors());
153         return *fFragmentProcessors[idx].get();
154     }
155 
getCoverageFragmentProcessor(int idx)156     const GrFragmentProcessor& getCoverageFragmentProcessor(int idx) const {
157         SkASSERT(idx < this->numCoverageFragmentProcessors());
158         return *fFragmentProcessors[fNumColorProcessors + idx].get();
159     }
160 
getFragmentProcessor(int idx)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      */
proxy()172     GrRenderTargetProxy* proxy() const { return fProxy.get(); }
renderTarget()173     GrRenderTarget* renderTarget() const { return fProxy.get()->priv().peekRenderTarget(); }
174 
getUserStencil()175     const GrUserStencilSettings* getUserStencil() const { return fUserStencilSettings; }
176 
getScissorState()177     const GrScissorState& getScissorState() const { return fScissorState; }
178 
getWindowRectsState()179     const GrWindowRectsState& getWindowRectsState() const { return fWindowRectsState; }
180 
isHWAntialiasState()181     bool isHWAntialiasState() const { return SkToBool(fFlags & kHWAntialias_Flag); }
snapVerticesToPixelCenters()182     bool snapVerticesToPixelCenters() const {
183         return SkToBool(fFlags & kSnapVerticesToPixelCenters_Flag);
184     }
getDisableOutputConversionToSRGB()185     bool getDisableOutputConversionToSRGB() const {
186         return SkToBool(fFlags & kDisableOutputConversionToSRGB_Flag);
187     }
getAllowSRGBInputs()188     bool getAllowSRGBInputs() const {
189         return SkToBool(fFlags & kAllowSRGBInputs_Flag);
190     }
hasStencilClip()191     bool hasStencilClip() const {
192         return SkToBool(fFlags & kHasStencilClip_Flag);
193     }
isStencilEnabled()194     bool isStencilEnabled() const {
195         return SkToBool(fFlags & kStencilEnabled_Flag);
196     }
isBad()197     bool isBad() const { return SkToBool(fFlags & kIsBad_Flag); }
198 
199     GrXferBarrierType xferBarrierType(const GrCaps& caps) const;
200 
DumpFlags(uint32_t flags)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 
221 private:
markAsBad()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