Flutter Engine
 
Loading...
Searching...
No Matches
solid_rrect_like_blur_contents.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6#include <optional>
7
14
15namespace impeller {
16
17namespace {
18// Generous padding to make sure blurs with large sigmas are fully visible. Used
19// to expand the geometry around the rrect. Larger sigmas have more subtle
20// gradients so they need larger padding to avoid hard cutoffs. Sigma is
21// maximized to 3.5 since that should cover 99.95% of all samples. 3.0 should
22// cover 99.7% but that was seen to be not enough for large sigmas.
23Scalar PadForSigma(Scalar sigma) {
24 Scalar scalar = std::min((1.0f / 47.6f) * sigma + 2.5f, 3.5f);
25 return sigma * scalar;
26}
27} // namespace
28
30
32
34 rect_ = rect;
35 corner_radius_ = corner_radius;
36}
37
39 sigma_ = sigma;
40}
41
43 color_ = color.Premultiply();
44}
45
47 return color_;
48}
49
50static Point eccentricity(Point v, double sInverse) {
51 Point vOverS = v * sInverse * 0.5;
52 Point vOverS_squared = -(vOverS * vOverS);
53 return {std::exp(vOverS_squared.x), std::exp(vOverS_squared.y)};
54}
55
56static Scalar kTwoOverSqrtPi = 2.0 / std::sqrt(kPi);
57
58// use crate::math::compute_erf7;
61 float xx = x * x;
62 x = x + (0.24295 + (0.03395 + 0.0104 * xx) * xx) * (x * xx);
63 return x / sqrt(1.0 + x * x);
64}
65
66static Point NegPos(Scalar v) {
67 return {std::min(v, 0.0f), std::max(v, 0.0f)};
68}
69
70bool SolidRRectLikeBlurContents::PopulateFragContext(PassContext& pass_context,
71 Scalar blurSigma,
72 Point center,
73 Point rSize,
74 Scalar radius) {
75 Scalar sigma = std::max(blurSigma * kSqrt2, 1.f);
76
77 pass_context.center = rSize * 0.5f;
78 pass_context.minEdge = std::min(rSize.x, rSize.y);
79 double rMax = 0.5 * pass_context.minEdge;
80 double r0 = std::min(std::hypot(radius, sigma * 1.15), rMax);
81 pass_context.r1 = std::min(std::hypot(radius, sigma * 2.0), rMax);
82
83 pass_context.exponent = 2.0 * pass_context.r1 / r0;
84
85 pass_context.sInv = 1.0 / sigma;
86
87 // Pull in long end (make less eccentric).
88 Point eccentricV = eccentricity(rSize, pass_context.sInv);
89 double delta = 1.25 * sigma * (eccentricV.x - eccentricV.y);
90 rSize += NegPos(delta);
91
92 pass_context.adjust = rSize * 0.5 - pass_context.r1;
93 pass_context.exponentInv = 1.0 / pass_context.exponent;
94 pass_context.scale =
95 0.5 * computeErf7(pass_context.sInv * 0.5 *
96 (std::max(rSize.x, rSize.y) - 0.5 * radius));
97
98 return pass_context.center.IsFinite() && //
99 pass_context.adjust.IsFinite() && //
100 std::isfinite(pass_context.minEdge) && //
101 std::isfinite(pass_context.r1) && //
102 std::isfinite(pass_context.exponent) && //
103 std::isfinite(pass_context.sInv) && //
104 std::isfinite(pass_context.exponentInv) && //
105 std::isfinite(pass_context.scale);
106}
107
109 const Entity& entity) const {
110 Scalar radius = PadForSigma(sigma_.sigma);
111
112 return rect_.Expand(radius).TransformBounds(entity.GetTransform());
113}
114
116 const Entity& entity,
117 RenderPass& pass) const {
118 using VS = RrectLikeBlurVertexShader;
119
120 Matrix basis_invert = entity.GetTransform().Basis().Invert();
121 Vector2 max_sigmas =
122 Vector2((basis_invert * Vector2(500.f, 0.f)).GetLength(),
123 (basis_invert * Vector2(0.f, 500.f)).GetLength());
124 Scalar max_sigma = std::min(max_sigmas.x, max_sigmas.y);
125 // Clamp the max kernel width/height to 1000 (@ 2x) to limit the extent
126 // of the blur and to kEhCloseEnough to prevent NaN calculations
127 // trying to evaluate a Gaussian distribution with a sigma of 0.
128 auto blur_sigma = std::clamp(sigma_.sigma, kEhCloseEnough, max_sigma);
129 // Increase quality by making the radius a bit bigger than the typical
130 // sigma->radius conversion we use for slower blurs.
131 Scalar blur_radius = PadForSigma(blur_sigma);
132 Rect positive_rect = rect_.GetPositive();
133 Scalar left = -blur_radius;
134 Scalar top = -blur_radius;
135 Scalar right = positive_rect.GetWidth() + blur_radius;
136 Scalar bottom = positive_rect.GetHeight() + blur_radius;
137
140 Color color = color_;
141 if (entity.GetBlendMode() == BlendMode::kClear) {
142 opts.is_for_rrect_blur_clear = true;
143 color = Color::White();
144 }
145
146 std::array<VS::PerVertexData, 4> vertices = {
147 VS::PerVertexData{Point(left, top)},
148 VS::PerVertexData{Point(right, top)},
149 VS::PerVertexData{Point(left, bottom)},
150 VS::PerVertexData{Point(right, bottom)},
151 };
152
153 PassContext pass_context = {
154 .opts = opts,
155 };
156
157 Scalar radius = std::min(std::clamp(corner_radius_, kEhCloseEnough,
158 positive_rect.GetWidth() * 0.5f),
159 std::clamp(corner_radius_, kEhCloseEnough,
160 positive_rect.GetHeight() * 0.5f));
161 if (!PopulateFragContext(pass_context, blur_sigma, positive_rect.GetCenter(),
162 Point(positive_rect.GetSize()), radius)) {
163 return true;
164 }
165
166 if (!SetPassInfo(pass, renderer, pass_context)) {
167 return true;
168 }
169
170 VS::FrameInfo frame_info;
171 frame_info.mvp = Entity::GetShaderTransform(
172 entity.GetShaderClipDepth(), pass,
173 entity.GetTransform() *
174 Matrix::MakeTranslation(positive_rect.GetOrigin()));
175
176 auto& data_host_buffer = renderer.GetTransientsDataBuffer();
177 pass.SetVertexBuffer(CreateVertexBuffer(vertices, data_host_buffer));
178 VS::BindFrameInfo(pass, data_host_buffer.EmplaceUniform(frame_info));
179
180 if (!pass.Draw().ok()) {
181 return false;
182 }
183
184 return true;
185}
186
188 const ColorFilterProc& color_filter_proc) {
189 color_ = color_filter_proc(color_);
190 return true;
191}
192
194 return {a.x, a.y, b.x, b.y};
195}
196
197} // namespace impeller
bool ok() const
Definition status.h:71
HostBuffer & GetTransientsDataBuffer() const
Retrieve the current host buffer for transient storage of other non-index data.
std::function< Color(Color)> ColorFilterProc
Definition contents.h:35
Matrix GetShaderTransform(const RenderPass &pass) const
Definition entity.cc:48
BlendMode GetBlendMode() const
Definition entity.cc:101
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
Definition entity.cc:44
float GetShaderClipDepth() const
Definition entity.cc:88
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition render_pass.h:30
virtual bool SetVertexBuffer(VertexBuffer buffer)
Specify the vertex and index buffer to use for this command.
virtual fml::Status Draw()
Record the currently pending command.
void SetShape(Rect rect, Scalar corner_radius)
std::optional< Rect > GetCoverage(const Entity &entity) const override
Get the area of the render pass that will be affected when this contents is rendered.
virtual bool SetPassInfo(RenderPass &pass, const ContentContext &renderer, PassContext &pass_context) const =0
bool Render(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
bool ApplyColorFilter(const ColorFilterProc &color_filter_proc) override
If possible, applies a color filter to this contents inputs on the CPU.
static Vector4 Concat(Vector2 &a, Vector2 &b)
int32_t x
Vector2 blur_radius
Blur radius in source pixels based on scaled_sigma.
static Scalar computeErf7(Scalar x)
Point Vector2
Definition point.h:331
constexpr float kPi
Definition constants.h:26
float Scalar
Definition scalar.h:19
constexpr float kEhCloseEnough
Definition constants.h:57
static Point NegPos(Scalar v)
TPoint< Scalar > Point
Definition point.h:327
VertexBuffer CreateVertexBuffer(std::array< VertexType, size > input, HostBuffer &data_host_buffer)
Create an index-less vertex buffer from a fixed size array.
static Point eccentricity(Point v, double sInverse)
constexpr float kSqrt2
Definition constants.h:47
LinePipeline::VertexShader VS
ContentContextOptions OptionsFromPassAndEntity(const RenderPass &pass, const Entity &entity)
Definition contents.cc:34
static constexpr Color White()
Definition color.h:264
constexpr Color Premultiply() const
Definition color.h:212
A 4x4 matrix using column-major storage.
Definition matrix.h:37
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition matrix.h:95
constexpr Matrix Basis() const
The Matrix without its w components (without translation).
Definition matrix.h:239
Matrix Invert() const
Definition matrix.cc:99
In filters that use Gaussian distributions, "sigma" is a size of one standard deviation in terms of t...
Definition sigma.h:32
Scalar sigma
Definition sigma.h:33
constexpr TRect TransformBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle.
Definition rect.h:472
constexpr TSize< Type > GetSize() const
Returns the size of the rectangle which may be negative in either width or height and may have been c...
Definition rect.h:327
constexpr Type GetHeight() const
Returns the height of the rectangle, equivalent to |GetSize().height|.
Definition rect.h:347
constexpr TRect GetPositive() const
Get a version of this rectangle that has a non-negative size.
Definition rect.h:398
constexpr Type GetWidth() const
Returns the width of the rectangle, equivalent to |GetSize().width|.
Definition rect.h:341
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
Definition rect.h:618
constexpr Point GetCenter() const
Get the center point as a |Point|.
Definition rect.h:382
constexpr TPoint< Type > GetOrigin() const
Returns the upper left corner of the rectangle as specified by the left/top or x/y values when it was...
Definition rect.h:320