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