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 #include "src/gpu/ganesh/GrPipeline.h"
8
9 #include "include/gpu/GpuTypes.h"
10 #include "include/private/base/SkAssert.h"
11 #include "src/gpu/Blend.h"
12 #include "src/gpu/KeyBuilder.h"
13 #include "src/gpu/ganesh/GrAppliedClip.h"
14 #include "src/gpu/ganesh/GrProcessorSet.h"
15 #include "src/gpu/ganesh/GrScissorState.h"
16 #include "src/gpu/ganesh/GrTexture.h"
17 #include "src/gpu/ganesh/GrXferProcessor.h"
18 #include "src/gpu/ganesh/glsl/GrGLSLProgramDataManager.h"
19 #include "src/gpu/ganesh/glsl/GrGLSLUniformHandler.h"
20
21 #include <utility>
22
GrPipeline(const InitArgs & args,sk_sp<const GrXferProcessor> xferProcessor,const GrAppliedHardClip & hardClip)23 GrPipeline::GrPipeline(const InitArgs& args,
24 sk_sp<const GrXferProcessor> xferProcessor,
25 const GrAppliedHardClip& hardClip)
26 : fDstProxy(args.fDstProxyView)
27 , fWindowRectsState(hardClip.windowRectsState())
28 , fXferProcessor(std::move(xferProcessor))
29 , fWriteSwizzle(args.fWriteSwizzle) {
30 fFlags = (Flags)args.fInputFlags;
31 if (hardClip.hasStencilClip()) {
32 fFlags |= Flags::kHasStencilClip;
33 }
34 if (hardClip.scissorState().enabled()) {
35 fFlags |= Flags::kScissorTestEnabled;
36 }
37 // If we have any special dst sample flags we better also have a dst proxy
38 SkASSERT(this->dstSampleFlags() == GrDstSampleFlags::kNone || this->dstProxyView());
39 }
40
GrPipeline(const InitArgs & args,GrProcessorSet && processors,GrAppliedClip && appliedClip)41 GrPipeline::GrPipeline(const InitArgs& args, GrProcessorSet&& processors,
42 GrAppliedClip&& appliedClip)
43 : GrPipeline(args, processors.refXferProcessor(), appliedClip.hardClip()) {
44 SkASSERT(processors.isFinalized());
45 // Copy GrFragmentProcessors from GrProcessorSet to Pipeline
46 fNumColorProcessors = processors.hasColorFragmentProcessor() ? 1 : 0;
47 int numTotalProcessors = fNumColorProcessors +
48 (processors.hasCoverageFragmentProcessor() ? 1 : 0) +
49 (appliedClip.hasCoverageFragmentProcessor() ? 1 : 0);
50 fFragmentProcessors.reset(numTotalProcessors);
51
52 int currFPIdx = 0;
53 if (processors.hasColorFragmentProcessor()) {
54 fFragmentProcessors[currFPIdx++] = processors.detachColorFragmentProcessor();
55 }
56 if (processors.hasCoverageFragmentProcessor()) {
57 fFragmentProcessors[currFPIdx++] = processors.detachCoverageFragmentProcessor();
58 }
59 if (appliedClip.hasCoverageFragmentProcessor()) {
60 fFragmentProcessors[currFPIdx++] = appliedClip.detachCoverageFragmentProcessor();
61 }
62 }
63
xferBarrierType(const GrCaps & caps) const64 GrXferBarrierType GrPipeline::xferBarrierType(const GrCaps& caps) const {
65 if (this->dstSampleFlags() & GrDstSampleFlags::kRequiresTextureBarrier) {
66 return kTexture_GrXferBarrierType;
67 }
68 return this->getXferProcessor().xferBarrierType(caps);
69 }
70
GrPipeline(GrScissorTest scissorTest,sk_sp<const GrXferProcessor> xp,const skgpu::Swizzle & writeSwizzle,InputFlags inputFlags)71 GrPipeline::GrPipeline(GrScissorTest scissorTest,
72 sk_sp<const GrXferProcessor> xp,
73 const skgpu::Swizzle& writeSwizzle,
74 InputFlags inputFlags)
75 : fWindowRectsState()
76 , fFlags((Flags)inputFlags)
77 , fXferProcessor(std::move(xp))
78 , fWriteSwizzle(writeSwizzle) {
79 if (GrScissorTest::kEnabled == scissorTest) {
80 fFlags |= Flags::kScissorTestEnabled;
81 }
82 }
83
genKey(skgpu::KeyBuilder * b,const GrCaps & caps) const84 void GrPipeline::genKey(skgpu::KeyBuilder* b, const GrCaps& caps) const {
85 // kSnapVerticesToPixelCenters is implemented in a shader.
86 InputFlags ignoredFlags = InputFlags::kSnapVerticesToPixelCenters;
87 b->add32((uint32_t)fFlags & ~(uint32_t)ignoredFlags, "flags");
88
89 const skgpu::BlendInfo& blendInfo = this->getXferProcessor().getBlendInfo();
90
91 static constexpr uint32_t kBlendCoeffSize = 5;
92 static constexpr uint32_t kBlendEquationSize = 5;
93 static_assert(static_cast<int>(skgpu::BlendCoeff::kLast) < (1 << kBlendCoeffSize));
94 static_assert(static_cast<int>(skgpu::BlendEquation::kLast) < (1 << kBlendEquationSize));
95
96 b->addBool(blendInfo.fWritesColor, "writesColor");
97 b->addBits(kBlendCoeffSize, static_cast<int>(blendInfo.fSrcBlend), "srcBlend");
98 b->addBits(kBlendCoeffSize, static_cast<int>(blendInfo.fDstBlend), "dstBlend");
99 b->addBits(kBlendEquationSize, static_cast<int>(blendInfo.fEquation), "equation");
100 b->addBool(this->usesDstInputAttachment(), "inputAttach");
101 }
102
visitTextureEffects(const std::function<void (const GrTextureEffect &)> & func) const103 void GrPipeline::visitTextureEffects(
104 const std::function<void(const GrTextureEffect&)>& func) const {
105 for (auto& fp : fFragmentProcessors) {
106 fp->visitTextureEffects(func);
107 }
108 }
109
visitProxies(const GrVisitProxyFunc & func) const110 void GrPipeline::visitProxies(const GrVisitProxyFunc& func) const {
111 // This iteration includes any clip coverage FPs
112 for (auto& fp : fFragmentProcessors) {
113 fp->visitProxies(func);
114 }
115 if (this->usesDstTexture()) {
116 func(this->dstProxyView().proxy(), skgpu::Mipmapped::kNo);
117 }
118 }
119
setDstTextureUniforms(const GrGLSLProgramDataManager & pdm,GrGLSLBuiltinUniformHandles * fBuiltinUniformHandles) const120 void GrPipeline::setDstTextureUniforms(const GrGLSLProgramDataManager& pdm,
121 GrGLSLBuiltinUniformHandles* fBuiltinUniformHandles) const {
122 GrTexture* dstTexture = this->peekDstTexture();
123
124 if (dstTexture) {
125 if (fBuiltinUniformHandles->fDstTextureCoordsUni.isValid()) {
126 float scaleX = 1.f;
127 float scaleY = 1.f;
128 if (dstTexture->textureType() == GrTextureType::kRectangle) {
129 // When we have a rectangle texture, we use the scaleX component to store the height
130 // in case we need to flip the coords when using a bottom left origin.
131 scaleX = dstTexture->height();
132 } else {
133 scaleX /= dstTexture->width();
134 scaleY /= dstTexture->height();
135 }
136 pdm.set4f(fBuiltinUniformHandles->fDstTextureCoordsUni,
137 static_cast<float>(this->dstTextureOffset().fX),
138 static_cast<float>(this->dstTextureOffset().fY),
139 scaleX,
140 scaleY);
141 }
142 } else {
143 SkASSERT(!fBuiltinUniformHandles->fDstTextureCoordsUni.isValid());
144 }
145 }
146