5
5
#include < optional>
6
6
#include < utility>
7
7
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"
14
8
#include " impeller/entity/contents/atlas_contents.h"
15
9
#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"
16
13
#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"
17
18
#include " impeller/renderer/render_pass.h"
19
+ #include " impeller/renderer/sampler_library.h"
20
+ #include " impeller/renderer/vertex_buffer_builder.h"
18
21
19
22
namespace impeller {
20
23
@@ -47,7 +50,6 @@ void AtlasContents::SetAlpha(Scalar alpha) {
47
50
}
48
51
49
52
void AtlasContents::SetBlendMode (BlendMode blend_mode) {
50
- // TODO(jonahwilliams): blending of colors with texture.
51
53
blend_mode_ = blend_mode;
52
54
}
53
55
@@ -59,15 +61,18 @@ std::optional<Rect> AtlasContents::GetCoverage(const Entity& entity) const {
59
61
if (cull_rect_.has_value ()) {
60
62
return cull_rect_.value ().TransformBounds (entity.GetTransformation ());
61
63
}
64
+ return ComputeBoundingBox ().TransformBounds (entity.GetTransformation ());
65
+ }
62
66
67
+ Rect AtlasContents::ComputeBoundingBox () const {
63
68
Rect bounding_box = {};
64
69
for (size_t i = 0 ; i < texture_coords_.size (); i++) {
65
70
auto matrix = transforms_[i];
66
71
auto sample_rect = texture_coords_[i];
67
72
auto bounds = Rect::MakeSize (sample_rect.size ).TransformBounds (matrix);
68
73
bounding_box = bounds.Union (bounding_box);
69
74
}
70
- return bounding_box. TransformBounds (entity. GetTransformation ()) ;
75
+ return bounding_box;
71
76
}
72
77
73
78
void AtlasContents::SetSamplerDescriptor (SamplerDescriptor desc) {
@@ -78,30 +83,98 @@ const SamplerDescriptor& AtlasContents::GetSamplerDescriptor() const {
78
83
return sampler_descriptor_;
79
84
}
80
85
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
+
81
98
bool AtlasContents::Render (const ContentContext& renderer,
82
99
const Entity& entity,
83
100
RenderPass& pass) const {
84
- if (texture_ == nullptr ) {
101
+ if (texture_ == nullptr || blend_mode_ == BlendMode::kClear ||
102
+ alpha_ <= 0.0 ) {
85
103
return true ;
86
104
}
87
105
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 ();
90
109
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);
94
121
}
95
122
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 ();
96
170
VertexBufferBuilder<VS::PerVertexData> vertex_builder;
97
- vertex_builder.Reserve (texture_coords_ .size () * 6 );
171
+ vertex_builder.Reserve (texture_coords .size () * 6 );
98
172
constexpr size_t indices[6 ] = {0 , 1 , 2 , 1 , 2 , 3 };
99
173
constexpr Scalar width[6 ] = {0 , 1 , 0 , 1 , 0 , 1 };
100
174
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];
105
178
auto transformed_points =
106
179
Rect::MakeSize (sample_rect.size ).GetTransformedPoints (matrix);
107
180
@@ -112,7 +185,6 @@ bool AtlasContents::Render(const ContentContext& renderer,
112
185
(sample_rect.origin + Point (sample_rect.size .width * width[j],
113
186
sample_rect.size .height * height[j])) /
114
187
texture_size;
115
- data.color = color.Premultiply ();
116
188
vertex_builder.AppendVertex (data);
117
189
}
118
190
}
@@ -121,31 +193,103 @@ bool AtlasContents::Render(const ContentContext& renderer,
121
193
return true ;
122
194
}
123
195
196
+ Command cmd;
197
+ cmd.label = " AtlasTexture" ;
198
+
124
199
auto & host_buffer = pass.GetTransientsBuffer ();
125
200
126
201
VS::VertInfo vert_info;
127
202
vert_info.mvp = Matrix::MakeOrthographic (pass.GetRenderTargetSize ()) *
128
203
entity.GetTransformation ();
129
204
130
205
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 ();
133
207
frag_info.alpha = alpha_;
134
208
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);
139
211
cmd.stencil_reference = entity.GetStencilDepth ();
140
212
cmd.BindVertices (vertex_builder.CreateVertexBuffer (host_buffer));
141
213
VS::BindVertInfo (cmd, host_buffer.EmplaceUniform (vert_info));
142
214
FS::BindFragInfo (cmd, host_buffer.EmplaceUniform (frag_info));
143
- FS::BindTextureSampler (cmd, texture_ ,
215
+ FS::BindTextureSampler (cmd, texture ,
144
216
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) {}
147
226
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));
149
293
}
150
294
151
295
} // namespace impeller
0 commit comments