Flutter Engine
The Flutter Engine
Public Member Functions | List of all members
CircularRRectEffect::Impl Class Reference
Inheritance diagram for CircularRRectEffect::Impl:
GrFragmentProcessor::ProgramImpl

Public Member Functions

void emitCode (EmitArgs &) override
 
- Public Member Functions inherited from GrFragmentProcessor::ProgramImpl
 ProgramImpl ()=default
 
virtual ~ProgramImpl ()=default
 
virtual void emitCode (EmitArgs &)=0
 
void setData (const GrGLSLProgramDataManager &pdman, const GrFragmentProcessor &processor)
 
int numChildProcessors () const
 
ProgramImplchildProcessor (int index) const
 
void setFunctionName (SkString name)
 
const char * functionName () const
 
SkString invokeChild (int childIndex, EmitArgs &parentArgs, std::string_view skslCoords={})
 
SkString invokeChildWithMatrix (int childIndex, EmitArgs &parentArgs)
 
SkString invokeChild (int childIndex, const char *inputColor, EmitArgs &parentArgs, std::string_view skslCoords={})
 
SkString invokeChildWithMatrix (int childIndex, const char *inputColor, EmitArgs &parentArgs)
 
SkString invokeChild (int childIndex, const char *inputColor, const char *destColor, EmitArgs &parentArgs, std::string_view skslCoords={})
 
SkString invokeChildWithMatrix (int childIndex, const char *inputColor, const char *destColor, EmitArgs &parentArgs)
 

Additional Inherited Members

- Public Types inherited from GrFragmentProcessor::ProgramImpl
using UniformHandle = GrGLSLUniformHandler::UniformHandle
 
using SamplerHandle = GrGLSLUniformHandler::SamplerHandle
 

Detailed Description

Definition at line 159 of file GrRRectEffect.cpp.

Member Function Documentation

◆ emitCode()

void CircularRRectEffect::Impl::emitCode ( EmitArgs args)
overridevirtual

Implements GrFragmentProcessor::ProgramImpl.

Definition at line 171 of file GrRRectEffect.cpp.

171 {
172 const CircularRRectEffect& crre = args.fFp.cast<CircularRRectEffect>();
173 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
174 const char *rectName;
175 const char *radiusPlusHalfName;
176 // The inner rect is the rrect bounds inset by the radius. Its left, top, right, and bottom
177 // edges correspond to components x, y, z, and w, respectively. When a side of the rrect has
178 // only rectangular corners, that side's value corresponds to the rect edge's value outset by
179 // half a pixel.
180 fInnerRectUniform = uniformHandler->addUniform(&crre, kFragment_GrShaderFlag, SkSLType::kFloat4,
181 "innerRect", &rectName);
182 // x is (r + .5) and y is 1/(r + .5)
183 fRadiusPlusHalfUniform = uniformHandler->addUniform(&crre, kFragment_GrShaderFlag,
184 SkSLType::kHalf2, "radiusPlusHalf",
185 &radiusPlusHalfName);
186
187 // If we're on a device where float != fp32 then the length calculation could overflow.
188 SkString clampedCircleDistance;
189 if (!args.fShaderCaps->fFloatIs32Bits) {
190 clampedCircleDistance.printf("saturate(%s.x * (1.0 - length(dxy * %s.y)))",
191 radiusPlusHalfName, radiusPlusHalfName);
192 } else {
193 clampedCircleDistance.printf("saturate(%s.x - length(dxy))", radiusPlusHalfName);
194 }
195
196 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
197 // At each quarter-circle corner we compute a vector that is the offset of the fragment position
198 // from the circle center. The vector is pinned in x and y to be in the quarter-plane relevant
199 // to that corner. This means that points near the interior near the rrect top edge will have
200 // a vector that points straight up for both the TL left and TR corners. Computing an
201 // alpha from this vector at either the TR or TL corner will give the correct result. Similarly,
202 // fragments near the other three edges will get the correct AA. Fragments in the interior of
203 // the rrect will have a (0,0) vector at all four corners. So long as the radius > 0.5 they will
204 // correctly produce an alpha value of 1 at all four corners. We take the min of all the alphas.
205 // The code below is a simplified version of the above that performs maxs on the vector
206 // components before computing distances and alpha values so that only one distance computation
207 // need be computed to determine the min alpha.
208 //
209 // For the cases where one half of the rrect is rectangular we drop one of the x or y
210 // computations, compute a separate rect edge alpha for the rect side, and mul the two computed
211 // alphas together.
212 switch (crre.fCircularCornerFlags) {
213 case CircularRRectEffect::kAll_CornerFlags:
214 fragBuilder->codeAppendf("float2 dxy0 = %s.LT - sk_FragCoord.xy;", rectName);
215 fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.RB;", rectName);
216 fragBuilder->codeAppend("float2 dxy = max(max(dxy0, dxy1), 0.0);");
217 fragBuilder->codeAppendf("half alpha = half(%s);", clampedCircleDistance.c_str());
218 break;
219 case CircularRRectEffect::kTopLeft_CornerFlag:
220 fragBuilder->codeAppendf("float2 dxy = max(%s.LT - sk_FragCoord.xy, 0.0);",
221 rectName);
222 fragBuilder->codeAppendf("half rightAlpha = half(saturate(%s.R - sk_FragCoord.x));",
223 rectName);
224 fragBuilder->codeAppendf("half bottomAlpha = half(saturate(%s.B - sk_FragCoord.y));",
225 rectName);
226 fragBuilder->codeAppendf("half alpha = bottomAlpha * rightAlpha * half(%s);",
227 clampedCircleDistance.c_str());
228 break;
229 case CircularRRectEffect::kTopRight_CornerFlag:
230 fragBuilder->codeAppendf("float2 dxy = max(float2(sk_FragCoord.x - %s.R, "
231 "%s.T - sk_FragCoord.y), 0.0);",
232 rectName, rectName);
233 fragBuilder->codeAppendf("half leftAlpha = half(saturate(sk_FragCoord.x - %s.L));",
234 rectName);
235 fragBuilder->codeAppendf("half bottomAlpha = half(saturate(%s.B - sk_FragCoord.y));",
236 rectName);
237 fragBuilder->codeAppendf("half alpha = bottomAlpha * leftAlpha * half(%s);",
238 clampedCircleDistance.c_str());
239 break;
240 case CircularRRectEffect::kBottomRight_CornerFlag:
241 fragBuilder->codeAppendf("float2 dxy = max(sk_FragCoord.xy - %s.RB, 0.0);",
242 rectName);
243 fragBuilder->codeAppendf("half leftAlpha = half(saturate(sk_FragCoord.x - %s.L));",
244 rectName);
245 fragBuilder->codeAppendf("half topAlpha = half(saturate(sk_FragCoord.y - %s.T));",
246 rectName);
247 fragBuilder->codeAppendf("half alpha = topAlpha * leftAlpha * half(%s);",
248 clampedCircleDistance.c_str());
249 break;
250 case CircularRRectEffect::kBottomLeft_CornerFlag:
251 fragBuilder->codeAppendf("float2 dxy = max(float2(%s.L - sk_FragCoord.x, "
252 "sk_FragCoord.y - %s.B), 0.0);",
253 rectName, rectName);
254 fragBuilder->codeAppendf("half rightAlpha = half(saturate(%s.R - sk_FragCoord.x));",
255 rectName);
256 fragBuilder->codeAppendf("half topAlpha = half(saturate(sk_FragCoord.y - %s.T));",
257 rectName);
258 fragBuilder->codeAppendf("half alpha = topAlpha * rightAlpha * half(%s);",
259 clampedCircleDistance.c_str());
260 break;
261 case CircularRRectEffect::kLeft_CornerFlags:
262 fragBuilder->codeAppendf("float2 dxy0 = %s.LT - sk_FragCoord.xy;", rectName);
263 fragBuilder->codeAppendf("float dy1 = sk_FragCoord.y - %s.B;", rectName);
264 fragBuilder->codeAppend("float2 dxy = max(float2(dxy0.x, max(dxy0.y, dy1)), 0.0);");
265 fragBuilder->codeAppendf("half rightAlpha = half(saturate(%s.R - sk_FragCoord.x));",
266 rectName);
267 fragBuilder->codeAppendf("half alpha = rightAlpha * half(%s);",
268 clampedCircleDistance.c_str());
269 break;
270 case CircularRRectEffect::kTop_CornerFlags:
271 fragBuilder->codeAppendf("float2 dxy0 = %s.LT - sk_FragCoord.xy;", rectName);
272 fragBuilder->codeAppendf("float dx1 = sk_FragCoord.x - %s.R;", rectName);
273 fragBuilder->codeAppend("float2 dxy = max(float2(max(dxy0.x, dx1), dxy0.y), 0.0);");
274 fragBuilder->codeAppendf("half bottomAlpha = half(saturate(%s.B - sk_FragCoord.y));",
275 rectName);
276 fragBuilder->codeAppendf("half alpha = bottomAlpha * half(%s);",
277 clampedCircleDistance.c_str());
278 break;
279 case CircularRRectEffect::kRight_CornerFlags:
280 fragBuilder->codeAppendf("float dy0 = %s.T - sk_FragCoord.y;", rectName);
281 fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.RB;", rectName);
282 fragBuilder->codeAppend("float2 dxy = max(float2(dxy1.x, max(dy0, dxy1.y)), 0.0);");
283 fragBuilder->codeAppendf("half leftAlpha = half(saturate(sk_FragCoord.x - %s.L));",
284 rectName);
285 fragBuilder->codeAppendf("half alpha = leftAlpha * half(%s);",
286 clampedCircleDistance.c_str());
287 break;
288 case CircularRRectEffect::kBottom_CornerFlags:
289 fragBuilder->codeAppendf("float dx0 = %s.L - sk_FragCoord.x;", rectName);
290 fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.RB;", rectName);
291 fragBuilder->codeAppend("float2 dxy = max(float2(max(dx0, dxy1.x), dxy1.y), 0.0);");
292 fragBuilder->codeAppendf("half topAlpha = half(saturate(sk_FragCoord.y - %s.T));",
293 rectName);
294 fragBuilder->codeAppendf("half alpha = topAlpha * half(%s);",
295 clampedCircleDistance.c_str());
296 break;
297 }
298
299 if (GrClipEdgeType::kInverseFillAA == crre.fEdgeType) {
300 fragBuilder->codeAppend("alpha = 1.0 - alpha;");
301 }
302
303 SkString inputSample = this->invokeChild(/*childIndex=*/0, args);
304
305 fragBuilder->codeAppendf("return %s * alpha;", inputSample.c_str());
306}
@ kFragment_GrShaderFlag
Definition: GrTypesPriv.h:287
SkString invokeChild(int childIndex, EmitArgs &parentArgs, std::string_view skslCoords={})
void codeAppend(const char *str)
void codeAppendf(const char format[],...) SK_PRINTF_LIKE(2
void printf(const char format[],...) SK_PRINTF_LIKE(2
Definition: SkString.cpp:534
const char * c_str() const
Definition: SkString.h:133
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args

The documentation for this class was generated from the following file: