77#include " flutter/fml/logging.h"
88#include " impeller/entity/contents/color_source_contents.h"
99#include " impeller/entity/contents/content_context.h"
10+ #include " impeller/entity/contents/gradient_generator.h"
1011#include " impeller/entity/contents/pipelines.h"
1112#include " impeller/entity/contents/uber_sdf_parameters.h"
1213#include " impeller/geometry/stroke_parameters.h"
@@ -18,9 +19,6 @@ namespace {
1819using PipelineBuilderCallback =
1920 std::function<PipelineRef(ContentContextOptions)>;
2021
21- using VS = UberSDFPipeline::VertexShader;
22- using FS = UberSDFPipeline::FragmentShader;
23-
2422Scalar ToShaderType (UberSDFParameters::Type type) {
2523 switch (type) {
2624 case UberSDFParameters::Type::kCircle :
@@ -64,18 +62,12 @@ struct SamplerBinding {
6462 raw_ptr<const Sampler> sampler;
6563};
6664
67- // / @brief Populates the gradient uniform fields in `frag_info` and returns
68- // / the texture and sampler for the gradient.
69- SamplerBinding SetupGradientParameters (
65+ // / @brief Populates the gradient uniforms shared by both UberSDF variants.
66+ template < typename FragInfo>
67+ void SetupCommonGradientParameters (
7068 const UberSDFParameters::GradientParameters& gradient,
71- const ContentContext& renderer,
72- FS ::FragInfo& frag_info) {
73- FML_DCHECK (gradient.texture );
69+ FragInfo& frag_info) {
7470 frag_info.tile_mode = static_cast <Scalar>(gradient.tile_mode );
75- auto texture_size = gradient.texture ->GetSize ();
76- FML_DCHECK (!texture_size.IsEmpty ());
77- frag_info.half_texel = 0 .5f / texture_size.width ;
78-
7971 if (gradient.type == UberSDFParameters::GradientParameters::Type::kLinear ) {
8072 Point delta = gradient.end - gradient.start ;
8173 Scalar length_sq = delta.x * delta.x + delta.y * delta.y ;
@@ -88,14 +80,42 @@ SamplerBinding SetupGradientParameters(
8880 frag_info.inv_gradient_length =
8981 gradient.end .x > 0 .0f ? 1 .0f / gradient.end .x : 0 .0f ;
9082 }
83+ }
9184
92- SamplerDescriptor sampler_desc;
93- sampler_desc.min_filter = MinMagFilter::kLinear ;
94- sampler_desc.mag_filter = MinMagFilter::kLinear ;
95- raw_ptr<const Sampler> sampler =
96- renderer.GetContext ()->GetSamplerLibrary ()->GetSampler (sampler_desc);
85+ // / @brief Populates the `frag_info` fields shared by both UberSDF variants.
86+ template <typename FragInfo>
87+ void SetupCommonFragInfo (const UberSDFParameters& params,
88+ Scalar opacity,
89+ const Entity& entity,
90+ FragInfo& frag_info) {
91+ frag_info.type = ToShaderType (params.type );
92+ frag_info.color_source_type = ToShaderColorSourceType (params);
93+ frag_info.color = params.color .WithAlpha (params.color .alpha * opacity);
94+ frag_info.center = params.center ;
95+ frag_info.size = params.size ;
96+ Vector2 pixel_size = entity.GetTransform ().GetTransformedPixelSize ();
97+ frag_info.pixel_size = Point (pixel_size.x , pixel_size.y );
98+ frag_info.stroked = params.stroke ? 1 .0f : 0 .0f ;
99+ frag_info.stroke_width = params.stroke ? params.stroke ->width : 0 .0f ;
100+ frag_info.stroke_join =
101+ params.stroke ? ToShaderStrokeJoin (params.stroke ->join ) : 0 .0f ;
102+ frag_info.aa_pixels = UberSDFParameters::kAntialiasPixels ;
103+ frag_info.superellipse_degree = params.superellipse_degree ;
104+ frag_info.angle_span = params.angle_span ;
105+ frag_info.circle_center_top = params.circle_center_top ;
106+ frag_info.circle_center_right = params.circle_center_right ;
107+ frag_info.radii = params.radii ;
97108
98- return {gradient.texture , sampler};
109+ // Gradient parameter defaults; overwritten if there is a gradient.
110+ frag_info.gradient_coords = Vector4 ();
111+ frag_info.half_texel = 0 .0f ;
112+ frag_info.tile_mode = 0 .0f ;
113+ frag_info.inv_gradient_length = 0 .0f ;
114+ frag_info.colors_length = 0 .0f ;
115+
116+ if (params.gradient ) {
117+ SetupCommonGradientParameters (params.gradient .value (), frag_info);
118+ }
99119}
100120
101121} // namespace
@@ -116,37 +136,37 @@ UberSDFContents::~UberSDFContents() = default;
116136bool UberSDFContents::Render (const ContentContext& renderer,
117137 const Entity& entity,
118138 RenderPass& pass) const {
139+ if (renderer.GetDeviceCapabilities ().SupportsSSBO ()) {
140+ return RenderSSBO (renderer, entity, pass);
141+ }
142+ return RenderTexture (renderer, entity, pass);
143+ }
144+
145+ bool UberSDFContents::RenderTexture (const ContentContext& renderer,
146+ const Entity& entity,
147+ RenderPass& pass) const {
148+ using VS = UberSDFPipeline::VertexShader;
149+ using FS = UberSDFPipeline::FragmentShader;
150+
119151 auto & data_host_buffer = renderer.GetTransientsDataBuffer ();
120152
121153 VS ::FrameInfo frame_info;
122154 FS ::FragInfo frag_info;
123- frag_info.type = ToShaderType (params_.type );
124- frag_info.color_source_type = ToShaderColorSourceType (params_);
125- frag_info.color =
126- params_.color .WithAlpha (params_.color .alpha * GetOpacityFactor ());
127- frag_info.center = params_.center ;
128- frag_info.size = params_.size ;
129- Vector2 pixel_size = entity.GetTransform ().GetTransformedPixelSize ();
130- frag_info.pixel_size = Point (pixel_size.x , pixel_size.y );
131- frag_info.stroked = params_.stroke ? 1 .0f : 0 .0f ;
132- frag_info.stroke_width = params_.stroke ? params_.stroke ->width : 0 .0f ;
133- frag_info.stroke_join =
134- params_.stroke ? ToShaderStrokeJoin (params_.stroke ->join ) : 0 .0f ;
135- frag_info.aa_pixels = UberSDFParameters::kAntialiasPixels ;
136- frag_info.superellipse_degree = params_.superellipse_degree ;
137- frag_info.angle_span = params_.angle_span ;
138- frag_info.circle_center_top = params_.circle_center_top ;
139- frag_info.circle_center_right = params_.circle_center_right ;
140- frag_info.radii = params_.radii ;
141- frag_info.gradient_coords = Vector4 ();
142- frag_info.half_texel = 0 .0f ;
143- frag_info.tile_mode = 0 .0f ;
144- frag_info.inv_gradient_length = 0 .0f ;
155+ SetupCommonFragInfo (params_, GetOpacityFactor (), entity, frag_info);
145156
146157 SamplerBinding sampler_binding;
147158 if (params_.gradient ) {
148- sampler_binding =
149- SetupGradientParameters (params_.gradient .value (), renderer, frag_info);
159+ FML_DCHECK (params_.gradient ->texture );
160+ auto texture_size = params_.gradient ->texture ->GetSize ();
161+ FML_DCHECK (!texture_size.IsEmpty ());
162+ frag_info.half_texel = 0 .5f / texture_size.width ;
163+
164+ SamplerDescriptor sampler_desc;
165+ sampler_desc.min_filter = MinMagFilter::kLinear ;
166+ sampler_desc.mag_filter = MinMagFilter::kLinear ;
167+ sampler_binding.texture = params_.gradient ->texture ;
168+ sampler_binding.sampler =
169+ renderer.GetContext ()->GetSamplerLibrary ()->GetSampler (sampler_desc);
150170 } else {
151171 sampler_binding.texture = renderer.GetEmptyTexture ();
152172 sampler_binding.sampler =
@@ -171,6 +191,50 @@ bool UberSDFContents::Render(const ContentContext& renderer,
171191 });
172192}
173193
194+ bool UberSDFContents::RenderSSBO (const ContentContext& renderer,
195+ const Entity& entity,
196+ RenderPass& pass) const {
197+ using VS = UberSDFSSBOPipeline::VertexShader;
198+ using FS = UberSDFSSBOPipeline::FragmentShader;
199+
200+ auto & data_host_buffer = renderer.GetTransientsDataBuffer ();
201+
202+ VS ::FrameInfo frame_info;
203+ FS ::FragInfo frag_info;
204+ SetupCommonFragInfo (params_, GetOpacityFactor (), entity, frag_info);
205+
206+ std::vector<StopData> color_stops;
207+ if (params_.gradient ) {
208+ color_stops =
209+ CreateGradientColors (params_.gradient ->colors , params_.gradient ->stops );
210+ } else {
211+ // The bound ColorData is required to be non-empty to be valid. This entry
212+ // is unused in the shader.
213+ color_stops.resize (1 );
214+ }
215+ frag_info.colors_length = static_cast <Scalar>(color_stops.size ());
216+
217+ BufferView color_buffer = data_host_buffer.Emplace (
218+ color_stops.data (), color_stops.size () * sizeof (StopData),
219+ renderer.GetDeviceCapabilities ().GetMinimumStorageBufferAlignment ());
220+
221+ PipelineBuilderCallback pipeline_callback =
222+ [&renderer](ContentContextOptions options) {
223+ return renderer.GetUberSDFSSBOPipeline (options);
224+ };
225+
226+ return ColorSourceContents::DrawGeometry<VS >(
227+ this , GetGeometry (), renderer, entity, pass, pipeline_callback,
228+ frame_info,
229+ /* bind_fragment_callback=*/
230+ [&frag_info, &data_host_buffer, &color_buffer](RenderPass& pass) {
231+ FS::BindFragInfo (pass, data_host_buffer.EmplaceUniform (frag_info));
232+ FS::BindColorData (pass, color_buffer);
233+ pass.SetCommandLabel (" UberSDFSSBO" );
234+ return true ;
235+ });
236+ }
237+
174238std::optional<Rect> UberSDFContents::GetCoverage (const Entity& entity) const {
175239 return GetGeometry ()->GetCoverage (entity.GetTransform ());
176240}
0 commit comments