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 "include/core/SkRefCnt.h"
12 #include "src/gpu/ganesh/GrColor.h"
13 #include "src/gpu/ganesh/GrDstProxyView.h"
14 #include "src/gpu/ganesh/GrFragmentProcessor.h"
15 #include "src/gpu/ganesh/GrProcessorSet.h"
16 #include "src/gpu/ganesh/GrScissorState.h"
17 #include "src/gpu/ganesh/GrSurfaceProxyView.h"
18 #include "src/gpu/ganesh/GrTextureProxy.h"
19 #include "src/gpu/ganesh/GrUserStencilSettings.h"
20 #include "src/gpu/ganesh/GrWindowRectsState.h"
21 #include "src/gpu/ganesh/effects/GrPorterDuffXferProcessor.h"
22
23 class GrAppliedClip;
24 class GrAppliedHardClip;
25 struct GrGLSLBuiltinUniformHandles;
26 class GrGLSLProgramDataManager;
27 class GrOp;
28 class GrTextureEffect;
29
30 /**
31 * This immutable object contains information needed to build a shader program and set API
32 * state for a draw. It is used along with a GrGeometryProcessor and a source of geometric
33 * data to draw.
34 */
35 class GrPipeline {
36 public:
37 ///////////////////////////////////////////////////////////////////////////
38 /// @name Creation
39
40 // Pipeline options that the caller may enable.
41 // NOTE: This enum is extended later by GrPipeline::Flags.
42 enum class InputFlags : uint8_t {
43 kNone = 0,
44 /**
45 * Cause every pixel to be rasterized that is touched by the triangle anywhere (not just at
46 * pixel center). Additionally, if using MSAA, the sample mask will always have 100%
47 * coverage.
48 * NOTE: The primitive type must be a triangle type.
49 */
50 kConservativeRaster = (1 << 1),
51 /**
52 * Draws triangles as outlines.
53 */
54 kWireframe = (1 << 2),
55 /**
56 * Modifies the vertex shader so that vertices will be positioned at pixel centers.
57 */
58 kSnapVerticesToPixelCenters = (1 << 3), // This value must be last. (See kLastInputFlag.)
59 };
60
61 struct InitArgs {
62 InputFlags fInputFlags = InputFlags::kNone;
63 const GrCaps* fCaps = nullptr;
64 GrDstProxyView fDstProxyView;
65 skgpu::Swizzle fWriteSwizzle;
66 };
67
68 /**
69 * Creates a simple pipeline with default settings and no processors. The provided blend mode
70 * must be "Porter Duff" (<= kLastCoeffMode). If using GrScissorTest::kEnabled, the caller must
71 * specify a scissor rectangle through the DynamicState struct.
72 **/
73 GrPipeline(GrScissorTest scissor,
74 SkBlendMode blend,
75 const skgpu::Swizzle& writeSwizzle,
76 InputFlags flags = InputFlags::kNone)
GrPipeline(scissor,GrPorterDuffXPFactory::MakeNoCoverageXP (blend),writeSwizzle,flags)77 : GrPipeline(scissor,
78 GrPorterDuffXPFactory::MakeNoCoverageXP(blend),
79 writeSwizzle,
80 flags) {}
81
82 GrPipeline(GrScissorTest,
83 sk_sp<const GrXferProcessor>,
84 const skgpu::Swizzle& writeSwizzle,
85 InputFlags = InputFlags::kNone);
86
87 GrPipeline(const InitArgs& args, sk_sp<const GrXferProcessor>, const GrAppliedHardClip&);
88 GrPipeline(const InitArgs&, GrProcessorSet&&, GrAppliedClip&&);
89
90 GrPipeline(const GrPipeline&) = delete;
91 GrPipeline& operator=(const GrPipeline&) = delete;
92
93 /// @}
94
95 ///////////////////////////////////////////////////////////////////////////
96 /// @name GrFragmentProcessors
97
numFragmentProcessors()98 int numFragmentProcessors() const { return fFragmentProcessors.count(); }
numColorFragmentProcessors()99 int numColorFragmentProcessors() const { return fNumColorProcessors; }
isColorFragmentProcessor(int idx)100 bool isColorFragmentProcessor(int idx) const { return idx < fNumColorProcessors; }
isCoverageFragmentProcessor(int idx)101 bool isCoverageFragmentProcessor(int idx) const { return idx >= fNumColorProcessors; }
102
usesLocalCoords()103 bool usesLocalCoords() const {
104 // The sample coords for the top level FPs are implicitly the GP's local coords.
105 for (const auto& fp : fFragmentProcessors) {
106 if (fp->usesSampleCoords()) {
107 return true;
108 }
109 }
110 return false;
111 }
112
113 void visitTextureEffects(const std::function<void(const GrTextureEffect&)>&) const;
114
getXferProcessor()115 const GrXferProcessor& getXferProcessor() const {
116 if (fXferProcessor) {
117 return *fXferProcessor;
118 } else {
119 // A null xp member means the common src-over case. GrXferProcessor's ref'ing
120 // mechanism is not thread safe so we do not hold a ref on this global.
121 return GrPorterDuffXPFactory::SimpleSrcOverXP();
122 }
123 }
124
125 // Helper functions to quickly know if this GrPipeline will access the dst as a texture or an
126 // input attachment.
usesDstTexture()127 bool usesDstTexture() const { return this->dstProxyView() && !this->usesDstInputAttachment(); }
usesDstInputAttachment()128 bool usesDstInputAttachment() const {
129 return this->dstSampleFlags() & GrDstSampleFlags::kAsInputAttachment;
130 }
131
132 /**
133 * This returns the GrSurfaceProxyView for the texture used to access the dst color. If the
134 * GrXferProcessor does not use the dst color then the proxy on the GrSurfaceProxyView will be
135 * nullptr.
136 */
dstProxyView()137 const GrSurfaceProxyView& dstProxyView() const { return fDstProxy.proxyView(); }
138
dstTextureOffset()139 SkIPoint dstTextureOffset() const { return fDstProxy.offset(); }
140
dstSampleFlags()141 GrDstSampleFlags dstSampleFlags() const { return fDstProxy.dstSampleFlags(); }
142
143 /** If this GrXferProcessor uses a texture to access the dst color, returns that texture. */
peekDstTexture()144 GrTexture* peekDstTexture() const {
145 if (!this->usesDstTexture()) {
146 return nullptr;
147 }
148
149 if (GrTextureProxy* dstProxy = this->dstProxyView().asTextureProxy()) {
150 return dstProxy->peekTexture();
151 }
152
153 return nullptr;
154 }
155
getFragmentProcessor(int idx)156 const GrFragmentProcessor& getFragmentProcessor(int idx) const {
157 return *fFragmentProcessors[idx];
158 }
159
160 /// @}
161
isScissorTestEnabled()162 bool isScissorTestEnabled() const {
163 return SkToBool(fFlags & Flags::kScissorTestEnabled);
164 }
165
getWindowRectsState()166 const GrWindowRectsState& getWindowRectsState() const { return fWindowRectsState; }
167
usesConservativeRaster()168 bool usesConservativeRaster() const { return fFlags & InputFlags::kConservativeRaster; }
isWireframe()169 bool isWireframe() const { return fFlags & InputFlags::kWireframe; }
snapVerticesToPixelCenters()170 bool snapVerticesToPixelCenters() const {
171 return fFlags & InputFlags::kSnapVerticesToPixelCenters;
172 }
hasStencilClip()173 bool hasStencilClip() const {
174 return SkToBool(fFlags & Flags::kHasStencilClip);
175 }
176 #ifdef SK_DEBUG
allProxiesInstantiated()177 bool allProxiesInstantiated() const {
178 for (int i = 0; i < fFragmentProcessors.count(); ++i) {
179 if (!fFragmentProcessors[i]->isInstantiated()) {
180 return false;
181 }
182 }
183 if (this->dstProxyView().proxy()) {
184 return this->dstProxyView().proxy()->isInstantiated();
185 }
186
187 return true;
188 }
189 #endif
190
191 GrXferBarrierType xferBarrierType(const GrCaps&) const;
192
193 // Used by Vulkan and Metal to cache their respective pipeline objects
194 void genKey(skgpu::KeyBuilder*, const GrCaps&) const;
195
writeSwizzle()196 const skgpu::Swizzle& writeSwizzle() const { return fWriteSwizzle; }
197
198 void visitProxies(const GrVisitProxyFunc&) const;
199
200 void setDstTextureUniforms(const GrGLSLProgramDataManager& pdm,
201 GrGLSLBuiltinUniformHandles* fBuiltinUniformHandles) const;
202
203 private:
204 inline static constexpr uint8_t kLastInputFlag =
205 (uint8_t)InputFlags::kSnapVerticesToPixelCenters;
206
207 /** This is a continuation of the public "InputFlags" enum. */
208 enum class Flags : uint8_t {
209 kHasStencilClip = (kLastInputFlag << 1),
210 kScissorTestEnabled = (kLastInputFlag << 2),
211 };
212
213 GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(Flags);
214
215 friend bool operator&(Flags, InputFlags);
216
217 // A pipeline can contain up to three processors: color, paint coverage, and clip coverage.
218 using FragmentProcessorArray =
219 skia_private::AutoSTArray<3, std::unique_ptr<const GrFragmentProcessor>>;
220
221 GrDstProxyView fDstProxy;
222 GrWindowRectsState fWindowRectsState;
223 Flags fFlags;
224 sk_sp<const GrXferProcessor> fXferProcessor;
225 FragmentProcessorArray fFragmentProcessors;
226
227 // This value is also the index in fFragmentProcessors where coverage processors begin.
228 int fNumColorProcessors = 0;
229
230 skgpu::Swizzle fWriteSwizzle;
231 };
232
233 GR_MAKE_BITFIELD_CLASS_OPS(GrPipeline::InputFlags)
GR_MAKE_BITFIELD_CLASS_OPS(GrPipeline::Flags)234 GR_MAKE_BITFIELD_CLASS_OPS(GrPipeline::Flags)
235
236 inline bool operator&(GrPipeline::Flags flags, GrPipeline::InputFlags inputFlag) {
237 return (flags & (GrPipeline::Flags)inputFlag);
238 }
239
240 #endif
241