xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrPipeline.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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