Skip to content

Commit fa2eb89

Browse files
authored
[Impeller] Migrate all ColorSourceContents to use a shared rendering routine. (flutter#50261)
This is going to be our "in" for performing StC in all the ColorSourceContents when necessary. No semantic change.
1 parent 215d55f commit fa2eb89

9 files changed

Lines changed: 613 additions & 686 deletions

impeller/entity/contents/color_source_contents.h

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#ifndef FLUTTER_IMPELLER_ENTITY_CONTENTS_COLOR_SOURCE_CONTENTS_H_
66
#define FLUTTER_IMPELLER_ENTITY_CONTENTS_COLOR_SOURCE_CONTENTS_H_
77

8+
#include "impeller/entity/contents/clip_contents.h"
89
#include "impeller/entity/contents/contents.h"
910
#include "impeller/entity/geometry/geometry.h"
1011
#include "impeller/geometry/matrix.h"
@@ -100,6 +101,102 @@ class ColorSourceContents : public Contents {
100101
// |Contents|
101102
void SetInheritedOpacity(Scalar opacity) override;
102103

104+
protected:
105+
using BindFragmentCallback = std::function<bool(RenderPass& pass)>;
106+
using PipelineBuilderMethod = std::shared_ptr<Pipeline<PipelineDescriptor>> (
107+
impeller::ContentContext::*)(ContentContextOptions) const;
108+
using PipelineBuilderCallback =
109+
std::function<std::shared_ptr<Pipeline<PipelineDescriptor>>(
110+
ContentContextOptions)>;
111+
112+
template <typename VertexShaderT>
113+
bool DrawGeometry(GeometryResult geometry_result,
114+
const ContentContext& renderer,
115+
const Entity& entity,
116+
RenderPass& pass,
117+
const PipelineBuilderCallback& pipeline_callback,
118+
typename VertexShaderT::FrameInfo frame_info,
119+
const BindFragmentCallback& bind_fragment_callback) const {
120+
auto options = OptionsFromPassAndEntity(pass, entity);
121+
122+
// If overdraw prevention is enabled (like when drawing stroke paths), we
123+
// increment the stencil buffer as we draw, preventing overlapping fragments
124+
// from drawing. Afterwards, we need to append another draw call to clean up
125+
// the stencil buffer (happens below in this method).
126+
if (geometry_result.prevent_overdraw) {
127+
options.stencil_mode =
128+
ContentContextOptions::StencilMode::kLegacyClipIncrement;
129+
}
130+
options.primitive_type = geometry_result.type;
131+
pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer));
132+
pass.SetStencilReference(entity.GetClipDepth());
133+
134+
// Take the pre-populated vertex shader uniform struct and set managed
135+
// values.
136+
frame_info.depth = entity.GetShaderClipDepth();
137+
frame_info.mvp = geometry_result.transform;
138+
139+
VertexShaderT::BindFrameInfo(
140+
pass, renderer.GetTransientsBuffer().EmplaceUniform(frame_info));
141+
142+
// The reason we need to have a callback mechanism here is that this routine
143+
// may insert draw calls before the main draw call below. For example, for
144+
// sufficiently complex paths we may opt to use stencil-then-cover to avoid
145+
// tessellation.
146+
if (!bind_fragment_callback(pass)) {
147+
return false;
148+
}
149+
150+
pass.SetPipeline(pipeline_callback(options));
151+
152+
if (!pass.Draw().ok()) {
153+
return false;
154+
}
155+
156+
// If we performed overdraw prevention, a subsection of the clip heightmap
157+
// was incremented by 1 in order to self-clip. So simply append a clip
158+
// restore to clean it up.
159+
if (geometry_result.prevent_overdraw) {
160+
auto restore = ClipRestoreContents();
161+
restore.SetRestoreCoverage(GetCoverage(entity));
162+
return restore.Render(renderer, entity, pass);
163+
}
164+
return true;
165+
}
166+
167+
template <typename VertexShaderT>
168+
bool DrawPositions(const ContentContext& renderer,
169+
const Entity& entity,
170+
RenderPass& pass,
171+
const PipelineBuilderCallback& pipeline_callback,
172+
typename VertexShaderT::FrameInfo frame_info,
173+
const BindFragmentCallback& bind_pipeline_callback) const {
174+
GeometryResult geometry_result =
175+
GetGeometry()->GetPositionBuffer(renderer, entity, pass);
176+
177+
return DrawGeometry<VertexShaderT>(std::move(geometry_result), renderer,
178+
entity, pass, pipeline_callback,
179+
frame_info, bind_pipeline_callback);
180+
}
181+
182+
template <typename VertexShaderT>
183+
bool DrawPositionsAndUVs(
184+
Rect texture_coverage,
185+
const Matrix& effect_transform,
186+
const ContentContext& renderer,
187+
const Entity& entity,
188+
RenderPass& pass,
189+
const PipelineBuilderCallback& pipeline_callback,
190+
typename VertexShaderT::FrameInfo frame_info,
191+
const BindFragmentCallback& bind_pipeline_callback) const {
192+
auto geometry_result = GetGeometry()->GetPositionUVBuffer(
193+
texture_coverage, effect_transform, renderer, entity, pass);
194+
195+
return DrawGeometry<VertexShaderT>(std::move(geometry_result), renderer,
196+
entity, pass, pipeline_callback,
197+
frame_info, bind_pipeline_callback);
198+
}
199+
103200
private:
104201
std::shared_ptr<Geometry> geometry_;
105202
Matrix inverse_matrix_;

impeller/entity/contents/conical_gradient_contents.cc

Lines changed: 76 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -64,62 +64,45 @@ bool ConicalGradientContents::RenderSSBO(const ContentContext& renderer,
6464
using VS = ConicalGradientSSBOFillPipeline::VertexShader;
6565
using FS = ConicalGradientSSBOFillPipeline::FragmentShader;
6666

67-
FS::FragInfo frag_info;
68-
frag_info.center = center_;
69-
frag_info.radius = radius_;
70-
frag_info.tile_mode = static_cast<Scalar>(tile_mode_);
71-
frag_info.decal_border_color = decal_border_color_;
72-
frag_info.alpha = GetOpacityFactor();
73-
if (focus_) {
74-
frag_info.focus = focus_.value();
75-
frag_info.focus_radius = focus_radius_;
76-
} else {
77-
frag_info.focus = center_;
78-
frag_info.focus_radius = 0.0;
79-
}
80-
81-
auto& host_buffer = renderer.GetTransientsBuffer();
82-
auto colors = CreateGradientColors(colors_, stops_);
83-
84-
frag_info.colors_length = colors.size();
85-
auto color_buffer =
86-
host_buffer.Emplace(colors.data(), colors.size() * sizeof(StopData),
87-
DefaultUniformAlignment());
88-
8967
VS::FrameInfo frame_info;
90-
frame_info.depth = entity.GetShaderClipDepth();
91-
frame_info.mvp = pass.GetOrthographicTransform() * entity.GetTransform();
9268
frame_info.matrix = GetInverseEffectTransform();
9369

94-
auto geometry_result =
95-
GetGeometry()->GetPositionBuffer(renderer, entity, pass);
96-
auto options = OptionsFromPassAndEntity(pass, entity);
97-
if (geometry_result.prevent_overdraw) {
98-
options.stencil_mode =
99-
ContentContextOptions::StencilMode::kLegacyClipIncrement;
100-
}
101-
options.primitive_type = geometry_result.type;
102-
103-
pass.SetCommandLabel("ConicalGradientSSBOFill");
104-
pass.SetStencilReference(entity.GetClipDepth());
105-
pass.SetPipeline(renderer.GetConicalGradientSSBOFillPipeline(options));
106-
pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer));
107-
FS::BindFragInfo(pass,
108-
renderer.GetTransientsBuffer().EmplaceUniform(frag_info));
109-
FS::BindColorData(pass, color_buffer);
110-
VS::BindFrameInfo(pass,
111-
renderer.GetTransientsBuffer().EmplaceUniform(frame_info));
112-
113-
if (!pass.Draw().ok()) {
114-
return false;
115-
}
116-
117-
if (geometry_result.prevent_overdraw) {
118-
auto restore = ClipRestoreContents();
119-
restore.SetRestoreCoverage(GetCoverage(entity));
120-
return restore.Render(renderer, entity, pass);
121-
}
122-
return true;
70+
PipelineBuilderCallback pipeline_callback =
71+
[&renderer](ContentContextOptions options) {
72+
return renderer.GetConicalGradientSSBOFillPipeline(options);
73+
};
74+
return ColorSourceContents::DrawPositions<VS>(
75+
renderer, entity, pass, pipeline_callback, frame_info,
76+
[this, &renderer](RenderPass& pass) {
77+
FS::FragInfo frag_info;
78+
frag_info.center = center_;
79+
frag_info.radius = radius_;
80+
frag_info.tile_mode = static_cast<Scalar>(tile_mode_);
81+
frag_info.decal_border_color = decal_border_color_;
82+
frag_info.alpha = GetOpacityFactor();
83+
if (focus_) {
84+
frag_info.focus = focus_.value();
85+
frag_info.focus_radius = focus_radius_;
86+
} else {
87+
frag_info.focus = center_;
88+
frag_info.focus_radius = 0.0;
89+
}
90+
91+
auto& host_buffer = renderer.GetTransientsBuffer();
92+
auto colors = CreateGradientColors(colors_, stops_);
93+
94+
frag_info.colors_length = colors.size();
95+
auto color_buffer =
96+
host_buffer.Emplace(colors.data(), colors.size() * sizeof(StopData),
97+
DefaultUniformAlignment());
98+
99+
FS::BindFragInfo(
100+
pass, renderer.GetTransientsBuffer().EmplaceUniform(frag_info));
101+
FS::BindColorData(pass, color_buffer);
102+
103+
pass.SetCommandLabel("ConicalGradientSSBOFill");
104+
return true;
105+
});
123106
}
124107

125108
bool ConicalGradientContents::RenderTexture(const ContentContext& renderer,
@@ -135,64 +118,52 @@ bool ConicalGradientContents::RenderTexture(const ContentContext& renderer,
135118
return false;
136119
}
137120

138-
FS::FragInfo frag_info;
139-
frag_info.center = center_;
140-
frag_info.radius = radius_;
141-
frag_info.tile_mode = static_cast<Scalar>(tile_mode_);
142-
frag_info.decal_border_color = decal_border_color_;
143-
frag_info.texture_sampler_y_coord_scale = gradient_texture->GetYCoordScale();
144-
frag_info.alpha = GetOpacityFactor();
145-
frag_info.half_texel = Vector2(0.5 / gradient_texture->GetSize().width,
146-
0.5 / gradient_texture->GetSize().height);
147-
if (focus_) {
148-
frag_info.focus = focus_.value();
149-
frag_info.focus_radius = focus_radius_;
150-
} else {
151-
frag_info.focus = center_;
152-
frag_info.focus_radius = 0.0;
153-
}
154-
155121
auto geometry_result =
156122
GetGeometry()->GetPositionBuffer(renderer, entity, pass);
157123

158124
VS::FrameInfo frame_info;
159-
frame_info.depth = entity.GetShaderClipDepth();
160-
frame_info.mvp = geometry_result.transform;
161125
frame_info.matrix = GetInverseEffectTransform();
162126

163-
pass.SetCommandLabel("ConicalGradientFill");
164-
pass.SetStencilReference(entity.GetClipDepth());
165-
166-
auto options = OptionsFromPassAndEntity(pass, entity);
167-
if (geometry_result.prevent_overdraw) {
168-
options.stencil_mode =
169-
ContentContextOptions::StencilMode::kLegacyClipIncrement;
170-
}
171-
options.primitive_type = geometry_result.type;
172-
pass.SetPipeline(renderer.GetConicalGradientFillPipeline(options));
173-
174-
pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer));
175-
FS::BindFragInfo(pass,
176-
renderer.GetTransientsBuffer().EmplaceUniform(frag_info));
177-
SamplerDescriptor sampler_desc;
178-
sampler_desc.min_filter = MinMagFilter::kLinear;
179-
sampler_desc.mag_filter = MinMagFilter::kLinear;
180-
FS::BindTextureSampler(
181-
pass, gradient_texture,
182-
renderer.GetContext()->GetSamplerLibrary()->GetSampler(sampler_desc));
183-
VS::BindFrameInfo(pass,
184-
renderer.GetTransientsBuffer().EmplaceUniform(frame_info));
185-
186-
if (!pass.Draw().ok()) {
187-
return false;
188-
}
189-
190-
if (geometry_result.prevent_overdraw) {
191-
auto restore = ClipRestoreContents();
192-
restore.SetRestoreCoverage(GetCoverage(entity));
193-
return restore.Render(renderer, entity, pass);
194-
}
195-
return true;
127+
PipelineBuilderCallback pipeline_callback =
128+
[&renderer](ContentContextOptions options) {
129+
return renderer.GetConicalGradientFillPipeline(options);
130+
};
131+
return ColorSourceContents::DrawPositions<VS>(
132+
renderer, entity, pass, pipeline_callback, frame_info,
133+
[this, &renderer, &gradient_texture](RenderPass& pass) {
134+
FS::FragInfo frag_info;
135+
frag_info.center = center_;
136+
frag_info.radius = radius_;
137+
frag_info.tile_mode = static_cast<Scalar>(tile_mode_);
138+
frag_info.decal_border_color = decal_border_color_;
139+
frag_info.texture_sampler_y_coord_scale =
140+
gradient_texture->GetYCoordScale();
141+
frag_info.alpha = GetOpacityFactor();
142+
frag_info.half_texel =
143+
Vector2(0.5 / gradient_texture->GetSize().width,
144+
0.5 / gradient_texture->GetSize().height);
145+
if (focus_) {
146+
frag_info.focus = focus_.value();
147+
frag_info.focus_radius = focus_radius_;
148+
} else {
149+
frag_info.focus = center_;
150+
frag_info.focus_radius = 0.0;
151+
}
152+
153+
pass.SetCommandLabel("ConicalGradientFill");
154+
155+
FS::BindFragInfo(
156+
pass, renderer.GetTransientsBuffer().EmplaceUniform(frag_info));
157+
SamplerDescriptor sampler_desc;
158+
sampler_desc.min_filter = MinMagFilter::kLinear;
159+
sampler_desc.mag_filter = MinMagFilter::kLinear;
160+
FS::BindTextureSampler(
161+
pass, gradient_texture,
162+
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
163+
sampler_desc));
164+
165+
return true;
166+
});
196167
}
197168

198169
bool ConicalGradientContents::ApplyColorFilter(

0 commit comments

Comments
 (0)