Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 334c92e

Browse files
author
Jonah Williams
authored
[Impeller] drawAtlas blend mode. (#38335)
* fill out drawAtlas * ++ * add drawVertices uage * ++ * test fixes * dont double divide * CI cleanups * some texture coordinates work * ++ * basic texture coordiantes work * ++ * ++ * ++ * Delete color blending * back out vertices change * ++ * ++ * ++ * remove atlas_fill from licenses * blending cleanup * Use sub-contents * fix opacity for pipeline blends * use alpha in snapshot to avoid extra pass * ++ * ++ * fix order
1 parent 59ea78b commit 334c92e

17 files changed

+326
-125
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,8 +1313,6 @@ ORIGIN: ../../../flutter/impeller/entity/geometry.cc + ../../../flutter/LICENSE
13131313
ORIGIN: ../../../flutter/impeller/entity/geometry.h + ../../../flutter/LICENSE
13141314
ORIGIN: ../../../flutter/impeller/entity/inline_pass_context.cc + ../../../flutter/LICENSE
13151315
ORIGIN: ../../../flutter/impeller/entity/inline_pass_context.h + ../../../flutter/LICENSE
1316-
ORIGIN: ../../../flutter/impeller/entity/shaders/atlas_fill.frag + ../../../flutter/LICENSE
1317-
ORIGIN: ../../../flutter/impeller/entity/shaders/atlas_fill.vert + ../../../flutter/LICENSE
13181316
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.glsl + ../../../flutter/LICENSE
13191317
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.vert + ../../../flutter/LICENSE
13201318
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_color.frag + ../../../flutter/LICENSE
@@ -3791,8 +3789,6 @@ FILE: ../../../flutter/impeller/entity/geometry.cc
37913789
FILE: ../../../flutter/impeller/entity/geometry.h
37923790
FILE: ../../../flutter/impeller/entity/inline_pass_context.cc
37933791
FILE: ../../../flutter/impeller/entity/inline_pass_context.h
3794-
FILE: ../../../flutter/impeller/entity/shaders/atlas_fill.frag
3795-
FILE: ../../../flutter/impeller/entity/shaders/atlas_fill.vert
37963792
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.glsl
37973793
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.vert
37983794
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_color.frag

impeller/aiks/canvas.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ void Canvas::DrawTextFrame(const TextFrame& text_frame,
379379

380380
void Canvas::DrawVertices(std::unique_ptr<VerticesGeometry> vertices,
381381
BlendMode blend_mode,
382-
Paint paint) {
382+
const Paint& paint) {
383383
Entity entity;
384384
entity.SetTransformation(GetCurrentTransformation());
385385
entity.SetStencilDepth(GetStencilDepth());

impeller/aiks/canvas.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ class Canvas {
9999

100100
void DrawVertices(std::unique_ptr<VerticesGeometry> vertices,
101101
BlendMode blend_mode,
102-
Paint paint);
102+
const Paint& paint);
103103

104104
void DrawAtlas(const std::shared_ptr<Image>& atlas,
105105
std::vector<Matrix> transforms,

impeller/entity/BUILD.gn

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ impeller_shaders("entity_shaders") {
88
name = "entity"
99

1010
shaders = [
11-
"shaders/atlas_fill.frag",
12-
"shaders/atlas_fill.vert",
1311
"shaders/blending/advanced_blend.vert",
1412
"shaders/blending/advanced_blend_color.frag",
1513
"shaders/blending/advanced_blend_colorburn.frag",

impeller/entity/contents/atlas_contents.cc

Lines changed: 174 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,19 @@
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

1922
namespace impeller {
2023

@@ -47,7 +50,6 @@ void AtlasContents::SetAlpha(Scalar alpha) {
4750
}
4851

4952
void 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

7378
void 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+
8198
bool 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

Comments
 (0)