55#include < optional>
66#include < utility>
77
8- #include " impeller/renderer/formats.h"
9- #include " impeller/renderer/sampler_library.h"
10- #include " impeller/renderer/vertex_buffer_builder.h"
11-
12- #include " impeller/entity/atlas_fill.frag.h"
13- #include " impeller/entity/atlas_fill.vert.h"
148#include " impeller/entity/contents/atlas_contents.h"
159#include " impeller/entity/contents/content_context.h"
10+ #include " impeller/entity/contents/filters/color_filter_contents.h"
11+ #include " impeller/entity/contents/filters/filter_contents.h"
12+ #include " impeller/entity/contents/texture_contents.h"
1613#include " impeller/entity/entity.h"
14+ #include " impeller/entity/geometry.h"
15+ #include " impeller/entity/texture_fill.frag.h"
16+ #include " impeller/entity/texture_fill.vert.h"
17+ #include " impeller/renderer/formats.h"
1718#include " impeller/renderer/render_pass.h"
19+ #include " impeller/renderer/sampler_library.h"
20+ #include " impeller/renderer/vertex_buffer_builder.h"
1821
1922namespace impeller {
2023
@@ -47,7 +50,6 @@ void AtlasContents::SetAlpha(Scalar alpha) {
4750}
4851
4952void AtlasContents::SetBlendMode (BlendMode blend_mode) {
50- // TODO(jonahwilliams): blending of colors with texture.
5153 blend_mode_ = blend_mode;
5254}
5355
@@ -59,15 +61,18 @@ std::optional<Rect> AtlasContents::GetCoverage(const Entity& entity) const {
5961 if (cull_rect_.has_value ()) {
6062 return cull_rect_.value ().TransformBounds (entity.GetTransformation ());
6163 }
64+ return ComputeBoundingBox ().TransformBounds (entity.GetTransformation ());
65+ }
6266
67+ Rect AtlasContents::ComputeBoundingBox () const {
6368 Rect bounding_box = {};
6469 for (size_t i = 0 ; i < texture_coords_.size (); i++) {
6570 auto matrix = transforms_[i];
6671 auto sample_rect = texture_coords_[i];
6772 auto bounds = Rect::MakeSize (sample_rect.size ).TransformBounds (matrix);
6873 bounding_box = bounds.Union (bounding_box);
6974 }
70- return bounding_box. TransformBounds (entity. GetTransformation ()) ;
75+ return bounding_box;
7176}
7277
7378void AtlasContents::SetSamplerDescriptor (SamplerDescriptor desc) {
@@ -78,30 +83,98 @@ const SamplerDescriptor& AtlasContents::GetSamplerDescriptor() const {
7883 return sampler_descriptor_;
7984}
8085
86+ const std::vector<Matrix>& AtlasContents::GetTransforms () const {
87+ return transforms_;
88+ }
89+
90+ const std::vector<Rect>& AtlasContents::GetTextureCoordinates () const {
91+ return texture_coords_;
92+ }
93+
94+ const std::vector<Color>& AtlasContents::GetColors () const {
95+ return colors_;
96+ }
97+
8198bool AtlasContents::Render (const ContentContext& renderer,
8299 const Entity& entity,
83100 RenderPass& pass) const {
84- if (texture_ == nullptr ) {
101+ if (texture_ == nullptr || blend_mode_ == BlendMode::kClear ||
102+ alpha_ <= 0.0 ) {
85103 return true ;
86104 }
87105
88- using VS = AtlasFillVertexShader;
89- using FS = AtlasFillFragmentShader;
106+ // Ensure that we use the actual computed bounds and not a cull-rect
107+ // approximation of them.
108+ auto coverage = ComputeBoundingBox ();
90109
91- const auto texture_size = texture_->GetSize ();
92- if (texture_size.IsEmpty ()) {
93- return true ;
110+ if (blend_mode_ == BlendMode::kSource || colors_.size () == 0 ) {
111+ auto child_contents = AtlasTextureContents (*this );
112+ child_contents.SetAlpha (alpha_);
113+ child_contents.SetCoverage (coverage);
114+ return child_contents.Render (renderer, entity, pass);
115+ }
116+ if (blend_mode_ == BlendMode::kDestination ) {
117+ auto child_contents = AtlasColorContents (*this );
118+ child_contents.SetAlpha (alpha_);
119+ child_contents.SetCoverage (coverage);
120+ return child_contents.Render (renderer, entity, pass);
94121 }
95122
123+ auto src_contents = std::make_shared<AtlasTextureContents>(*this );
124+ src_contents->SetCoverage (coverage);
125+
126+ auto dst_contents = std::make_shared<AtlasColorContents>(*this );
127+ dst_contents->SetCoverage (coverage);
128+
129+ // For some reason this looks backwards compared to Skia unless
130+ // we reverse the src/dst.
131+ auto contents = ColorFilterContents::MakeBlend (
132+ blend_mode_,
133+ {FilterInput::Make (dst_contents), FilterInput::Make (src_contents)});
134+ contents->SetAlpha (alpha_);
135+ return contents->Render (renderer, entity, pass);
136+ }
137+
138+ // AtlasTextureContents
139+ // ---------------------------------------------------------
140+
141+ AtlasTextureContents::AtlasTextureContents (const AtlasContents& parent)
142+ : parent_(parent) {}
143+
144+ AtlasTextureContents::~AtlasTextureContents () {}
145+
146+ std::optional<Rect> AtlasTextureContents::GetCoverage (
147+ const Entity& entity) const {
148+ return coverage_.TransformBounds (entity.GetTransformation ());
149+ }
150+
151+ void AtlasTextureContents::SetAlpha (Scalar alpha) {
152+ alpha_ = alpha;
153+ }
154+
155+ void AtlasTextureContents::SetCoverage (Rect coverage) {
156+ coverage_ = coverage;
157+ }
158+
159+ bool AtlasTextureContents::Render (const ContentContext& renderer,
160+ const Entity& entity,
161+ RenderPass& pass) const {
162+ using VS = TextureFillVertexShader;
163+ using FS = TextureFillFragmentShader;
164+
165+ auto texture = parent_.GetTexture ();
166+ auto texture_coords = parent_.GetTextureCoordinates ();
167+ auto transforms = parent_.GetTransforms ();
168+
169+ const auto texture_size = texture->GetSize ();
96170 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
97- vertex_builder.Reserve (texture_coords_ .size () * 6 );
171+ vertex_builder.Reserve (texture_coords .size () * 6 );
98172 constexpr size_t indices[6 ] = {0 , 1 , 2 , 1 , 2 , 3 };
99173 constexpr Scalar width[6 ] = {0 , 1 , 0 , 1 , 0 , 1 };
100174 constexpr Scalar height[6 ] = {0 , 0 , 1 , 0 , 1 , 1 };
101- for (size_t i = 0 ; i < texture_coords_.size (); i++) {
102- auto sample_rect = texture_coords_[i];
103- auto matrix = transforms_[i];
104- auto color = colors_.size () > 0 ? colors_[i] : Color::Black ();
175+ for (size_t i = 0 ; i < texture_coords.size (); i++) {
176+ auto sample_rect = texture_coords[i];
177+ auto matrix = transforms[i];
105178 auto transformed_points =
106179 Rect::MakeSize (sample_rect.size ).GetTransformedPoints (matrix);
107180
@@ -112,7 +185,6 @@ bool AtlasContents::Render(const ContentContext& renderer,
112185 (sample_rect.origin + Point (sample_rect.size .width * width[j],
113186 sample_rect.size .height * height[j])) /
114187 texture_size;
115- data.color = color.Premultiply ();
116188 vertex_builder.AppendVertex (data);
117189 }
118190 }
@@ -121,31 +193,103 @@ bool AtlasContents::Render(const ContentContext& renderer,
121193 return true ;
122194 }
123195
196+ Command cmd;
197+ cmd.label = " AtlasTexture" ;
198+
124199 auto & host_buffer = pass.GetTransientsBuffer ();
125200
126201 VS::VertInfo vert_info;
127202 vert_info.mvp = Matrix::MakeOrthographic (pass.GetRenderTargetSize ()) *
128203 entity.GetTransformation ();
129204
130205 FS::FragInfo frag_info;
131- frag_info.texture_sampler_y_coord_scale = texture_->GetYCoordScale ();
132- frag_info.has_vertex_color = colors_.size () > 0 ? 1.0 : 0.0 ;
206+ frag_info.texture_sampler_y_coord_scale = texture->GetYCoordScale ();
133207 frag_info.alpha = alpha_;
134208
135- Command cmd;
136- cmd.label = " DrawAtlas" ;
137- cmd.pipeline =
138- renderer.GetAtlasPipeline (OptionsFromPassAndEntity (pass, entity));
209+ auto options = OptionsFromPassAndEntity (pass, entity);
210+ cmd.pipeline = renderer.GetTexturePipeline (options);
139211 cmd.stencil_reference = entity.GetStencilDepth ();
140212 cmd.BindVertices (vertex_builder.CreateVertexBuffer (host_buffer));
141213 VS::BindVertInfo (cmd, host_buffer.EmplaceUniform (vert_info));
142214 FS::BindFragInfo (cmd, host_buffer.EmplaceUniform (frag_info));
143- FS::BindTextureSampler (cmd, texture_ ,
215+ FS::BindTextureSampler (cmd, texture ,
144216 renderer.GetContext ()->GetSamplerLibrary ()->GetSampler (
145- sampler_descriptor_));
146- pass.AddCommand (std::move (cmd));
217+ parent_.GetSamplerDescriptor ()));
218+ return pass.AddCommand (std::move (cmd));
219+ }
220+
221+ // AtlasColorContents
222+ // ---------------------------------------------------------
223+
224+ AtlasColorContents::AtlasColorContents (const AtlasContents& parent)
225+ : parent_(parent) {}
147226
148- return true ;
227+ AtlasColorContents::~AtlasColorContents () {}
228+
229+ std::optional<Rect> AtlasColorContents::GetCoverage (
230+ const Entity& entity) const {
231+ return coverage_.TransformBounds (entity.GetTransformation ());
232+ }
233+
234+ void AtlasColorContents::SetAlpha (Scalar alpha) {
235+ alpha_ = alpha;
236+ }
237+
238+ void AtlasColorContents::SetCoverage (Rect coverage) {
239+ coverage_ = coverage;
240+ }
241+
242+ bool AtlasColorContents::Render (const ContentContext& renderer,
243+ const Entity& entity,
244+ RenderPass& pass) const {
245+ using VS = GeometryColorPipeline::VertexShader;
246+ using FS = GeometryColorPipeline::FragmentShader;
247+
248+ auto texture_coords = parent_.GetTextureCoordinates ();
249+ auto transforms = parent_.GetTransforms ();
250+ auto colors = parent_.GetColors ();
251+
252+ VertexBufferBuilder<VS::PerVertexData> vertex_builder;
253+ vertex_builder.Reserve (texture_coords.size () * 6 );
254+ constexpr size_t indices[6 ] = {0 , 1 , 2 , 1 , 2 , 3 };
255+ for (size_t i = 0 ; i < texture_coords.size (); i++) {
256+ auto sample_rect = texture_coords[i];
257+ auto matrix = transforms[i];
258+ auto transformed_points =
259+ Rect::MakeSize (sample_rect.size ).GetTransformedPoints (matrix);
260+
261+ for (size_t j = 0 ; j < 6 ; j++) {
262+ VS::PerVertexData data;
263+ data.position = transformed_points[indices[j]];
264+ data.color = colors[i].Premultiply ();
265+ vertex_builder.AppendVertex (data);
266+ }
267+ }
268+
269+ if (!vertex_builder.HasVertices ()) {
270+ return true ;
271+ }
272+
273+ Command cmd;
274+ cmd.label = " AtlasColors" ;
275+
276+ auto & host_buffer = pass.GetTransientsBuffer ();
277+
278+ VS::VertInfo vert_info;
279+ vert_info.mvp = Matrix::MakeOrthographic (pass.GetRenderTargetSize ()) *
280+ entity.GetTransformation ();
281+
282+ FS::FragInfo frag_info;
283+ frag_info.alpha = alpha_;
284+
285+ auto opts = OptionsFromPassAndEntity (pass, entity);
286+ opts.blend_mode = BlendMode::kSourceOver ;
287+ cmd.pipeline = renderer.GetGeometryColorPipeline (opts);
288+ cmd.stencil_reference = entity.GetStencilDepth ();
289+ cmd.BindVertices (vertex_builder.CreateVertexBuffer (host_buffer));
290+ VS::BindVertInfo (cmd, host_buffer.EmplaceUniform (vert_info));
291+ FS::BindFragInfo (cmd, host_buffer.EmplaceUniform (frag_info));
292+ return pass.AddCommand (std::move (cmd));
149293}
150294
151295} // namespace impeller
0 commit comments