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