Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
GrXferProcessor.cpp
Go to the documentation of this file.
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
9
12#include "src/gpu/KeyBuilder.h"
18
19#include <cstdint>
20
21enum class GrClampType;
22
24 : INHERITED(classID)
25 , fWillReadDstColor(false)
26 , fIsLCD(false) {}
27
28GrXferProcessor::GrXferProcessor(ClassID classID, bool willReadDstColor,
30 : INHERITED(classID)
31 , fWillReadDstColor(willReadDstColor)
32 , fIsLCD(GrProcessorAnalysisCoverage::kLCD == coverage) {}
33
35 if (!this->willReadDstColor()) {
36 return this->onHasSecondaryOutput();
37 }
38 return false;
39}
40
43 const GrSurfaceOrigin* originIfDstTexture,
44 bool usesInputAttachmentForDstRead) const {
45 uint32_t key = this->willReadDstColor() ? 0x1 : 0x0;
46 if (key) {
47 if (originIfDstTexture) {
48 key |= 0x2;
49 if (kTopLeft_GrSurfaceOrigin == *originIfDstTexture) {
50 key |= 0x4;
51 }
52 if (usesInputAttachmentForDstRead) {
53 key |= 0x8;
54 }
55 }
56 }
57 if (fIsLCD) {
58 key |= 0x10;
59 }
60 b->add32(key);
61 this->onAddToKey(caps, b);
62}
63
64///////////////////////////////////////////////////////////////////////////////
65
89
93 const GrCaps& caps,
94 GrClampType clampType) {
95 if (factory) {
96 return factory->makeXferProcessor(color, coverage, caps, clampType);
97 } else {
99 }
100}
101
103 if (SkBlendMode_AsCoeff(mode, nullptr, nullptr)) {
106 return result;
107 }
108
110 return GrCustomXfermode::Get(mode);
111}
112
113//////////////////////////////////////////////////////////////////////////////
114
116
117// This is only called for cases where we are doing LCD coverage and not using in shader blending.
118// For these cases we assume the the src alpha is 1, thus we can just use the max for the alpha
119// coverage since src alpha will always be greater than or equal to dst alpha.
121 const char* srcCoverage,
122 const GrXferProcessor& proc) {
123 if (srcCoverage && proc.isLCD()) {
124 fragBuilder->codeAppendf("%s.a = max(max(%s.r, %s.g), %s.b);",
125 srcCoverage,
126 srcCoverage,
127 srcCoverage,
128 srcCoverage);
129 }
130}
131
132void ProgramImpl::emitCode(const EmitArgs& args) {
133 if (!args.fXP.willReadDstColor()) {
134 adjust_for_lcd_coverage(args.fXPFragBuilder, args.fInputCoverage, args.fXP);
135 this->emitOutputsForBlendState(args);
136 } else {
137 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
138 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
139 const char* dstColor = fragBuilder->dstColor();
140
141 bool needsLocalOutColor = false;
142
143 if (args.fDstTextureSamplerHandle.isValid()) {
144 if (args.fInputCoverage) {
145 // We don't think any shaders actually output negative coverage, but just as a
146 // safety check for floating point precision errors, we compare with <= here. We
147 // just check the RGB values of the coverage, since the alpha may not have been set
148 // when using LCD. If we are using single-channel coverage, alpha will be equal to
149 // RGB anyway.
150 //
151 // The discard here also helps for batching text-draws together, which need to read
152 // from a dst copy for blends. However, this only helps the case where the outer
153 // bounding boxes of each letter overlap and not two actually parts of the text.
154 fragBuilder->codeAppendf("if (all(lessThanEqual(%s.rgb, half3(0)))) {"
155 " discard;"
156 "}",
157 args.fInputCoverage);
158 }
159 } else {
160 needsLocalOutColor = args.fShaderCaps->fRequiresLocalOutputColorForFBFetch;
161 }
162
163 const char* outColor = "_localColorOut";
164 if (!needsLocalOutColor) {
165 outColor = args.fOutputPrimary;
166 } else {
167 fragBuilder->codeAppendf("half4 %s;", outColor);
168 }
169
170 this->emitBlendCodeForDstRead(fragBuilder,
171 uniformHandler,
172 args.fInputColor,
173 args.fInputCoverage,
174 dstColor,
175 outColor,
176 args.fOutputSecondary,
177 args.fXP);
178 if (needsLocalOutColor) {
179 fragBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, outColor);
180 }
181 }
182
183 // Swizzle the fragment shader outputs if necessary.
184 this->emitWriteSwizzle(args.fXPFragBuilder,
185 args.fWriteSwizzle,
186 args.fOutputPrimary,
187 args.fOutputSecondary);
188}
189
190void ProgramImpl::emitWriteSwizzle(GrGLSLXPFragmentBuilder* x,
191 const skgpu::Swizzle& swizzle,
192 const char* outColor,
193 const char* outColorSecondary) const {
194 if (skgpu::Swizzle::RGBA() != swizzle) {
195 x->codeAppendf("%s = %s.%s;", outColor, outColor, swizzle.asString().c_str());
196 if (outColorSecondary) {
197 x->codeAppendf("%s = %s.%s;",
198 outColorSecondary,
199 outColorSecondary,
200 swizzle.asString().c_str());
201 }
202 }
203}
204
206 this->onSetData(pdm, xp);
207}
208
209void ProgramImpl::DefaultCoverageModulation(GrGLSLXPFragmentBuilder* fragBuilder,
210 const char* srcCoverage,
211 const char* dstColor,
212 const char* outColor,
213 const char* outColorSecondary,
214 const GrXferProcessor& proc) {
215 if (srcCoverage) {
216 if (proc.isLCD()) {
217 fragBuilder->codeAppendf("half3 lerpRGB = mix(%s.aaa, %s.aaa, %s.rgb);",
218 dstColor,
219 outColor,
220 srcCoverage);
221 }
222 fragBuilder->codeAppendf("%s = %s * %s + (half4(1.0) - %s) * %s;",
223 outColor,
224 srcCoverage,
225 outColor,
226 srcCoverage,
227 dstColor);
228 if (proc.isLCD()) {
229 fragBuilder->codeAppendf("%s.a = max(max(lerpRGB.r, lerpRGB.b), lerpRGB.g);", outColor);
230 }
231 }
232}
GrProcessorAnalysisCoverage
GrClampType
GrSurfaceOrigin
Definition GrTypes.h:147
@ kTopLeft_GrSurfaceOrigin
Definition GrTypes.h:148
static void adjust_for_lcd_coverage(GrGLSLXPFragmentBuilder *fragBuilder, const char *srcCoverage, const GrXferProcessor &proc)
SkColor4f color
#define SkASSERT(cond)
Definition SkAssert.h:116
SK_API bool SkBlendMode_AsCoeff(SkBlendMode mode, SkBlendModeCoeff *src, SkBlendModeCoeff *dst)
SkBlendMode
Definition SkBlendMode.h:38
const GrShaderCaps * shaderCaps() const
Definition GrCaps.h:63
void setData(const GrGLSLProgramDataManager &pdman, const GrFragmentProcessor &processor)
virtual void onSetData(const GrGLSLProgramDataManager &, const GrFragmentProcessor &)
void codeAppendf(const char format[],...) SK_PRINTF_LIKE(2
virtual const char * dstColor()=0
static sk_sp< const GrXferProcessor > MakeSrcOverXferProcessor(const GrProcessorAnalysisColor &, GrProcessorAnalysisCoverage, const GrCaps &)
static const GrXPFactory * Get(SkBlendMode blendMode)
static AnalysisProperties SrcOverAnalysisProperties(const GrProcessorAnalysisColor &, const GrProcessorAnalysisCoverage &, const GrCaps &, GrClampType)
virtual sk_sp< const GrXferProcessor > makeXferProcessor(const GrProcessorAnalysisColor &, GrProcessorAnalysisCoverage, const GrCaps &, GrClampType) const =0
static const GrXPFactory * FromBlendMode(SkBlendMode)
static sk_sp< const GrXferProcessor > MakeXferProcessor(const GrXPFactory *, const GrProcessorAnalysisColor &, GrProcessorAnalysisCoverage, const GrCaps &caps, GrClampType)
virtual AnalysisProperties analysisProperties(const GrProcessorAnalysisColor &, const GrProcessorAnalysisCoverage &, const GrCaps &, GrClampType) const =0
static AnalysisProperties GetAnalysisProperties(const GrXPFactory *, const GrProcessorAnalysisColor &, const GrProcessorAnalysisCoverage &, const GrCaps &, GrClampType)
void emitCode(const EmitArgs &)
bool isLCD() const
virtual void onAddToKey(const GrShaderCaps &, skgpu::KeyBuilder *) const =0
bool hasSecondaryOutput() const
GrXferProcessor(ClassID classID)
bool willReadDstColor() const
void addToKey(const GrShaderCaps &, skgpu::KeyBuilder *, const GrSurfaceOrigin *originIfDstTexture, bool usesInputAttachmentForDstRead) const
virtual bool onHasSecondaryOutput() const
const char * c_str() const
Definition SkString.h:133
SkString asString() const
Definition Swizzle.cpp:46
static constexpr Swizzle RGBA()
Definition Swizzle.h:66
static bool b
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
GAsyncResult * result
double x
bool IsSupportedMode(SkBlendMode mode)
const GrXPFactory * Get(SkBlendMode mode)
bool fDstReadInShaderSupport