Skip to content

Commit a3a9476

Browse files
author
jonahwilliams
committed
basic texture coordiantes work
1 parent 785e18b commit a3a9476

6 files changed

Lines changed: 196 additions & 93 deletions

File tree

impeller/aiks/canvas.cc

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -380,8 +380,21 @@ void Canvas::DrawTextFrame(const TextFrame& text_frame,
380380
void Canvas::DrawVertices(std::unique_ptr<VerticesGeometry> vertices,
381381
BlendMode blend_mode,
382382
const Paint& paint) {
383-
auto has_colors = vertices->GetVertexType() == GeometryVertexType::kColor;
383+
// drawVertices rendering:
384+
// * If there are no per-vertex colors and no texture coordinates, use the
385+
// color source and apply the vertex geometry to this.
386+
// * If there are vertex colors or vertex colors and texture coordinates, then
387+
// the blend_mode parameter applies:
388+
// * The paint color, if any, is treated as fully opaque. The alpha is applied
389+
// separately even to other paint sources.
390+
// * If there are only texture coordinates and the paint source is not a solid
391+
// color, then pretend this is per-vertex color with a source blend mode.
392+
393+
auto has_colors = vertices->HasVertexColors();
394+
auto has_texture_coordinates = vertices->HasTextureCoordinates();
384395
auto rect = vertices->GetCoverage(GetCurrentTransformation());
396+
397+
// Clear blend mode can be ignored entirely.
385398
if ((has_colors && blend_mode == BlendMode::kClear) || !rect.has_value()) {
386399
return;
387400
}
@@ -391,15 +404,21 @@ void Canvas::DrawVertices(std::unique_ptr<VerticesGeometry> vertices,
391404
entity.SetStencilDepth(GetStencilDepth());
392405
entity.SetBlendMode(paint.blend_mode);
393406

394-
if (!has_colors || blend_mode == BlendMode::kSource) {
407+
// No vertex colors or texture coordinates, this can be treated as a regular paint
408+
// op.
409+
// TODO(jonahwilliams): optimization, texture coordinate + solid color contents
410+
// should exit here too.
411+
if (!has_texture_coordinates && (blend_mode == BlendMode::kSource || !has_colors)) {
395412
entity.SetContents(paint.WithFilters(
396413
paint.CreateContentsForGeometry(std::move(vertices))));
397414
GetCurrentPass().AddEntity(entity);
398415
return;
399416
}
400-
auto contents = std::make_shared<VerticesContents>();
417+
// The paint color, if present, should be treated as fully opaque.
401418
auto opaque_paint = paint;
402419
opaque_paint.color = opaque_paint.color.WithAlpha(1.0);
420+
421+
auto contents = std::make_shared<VerticesContents>();
403422
contents->SetSrcContents(opaque_paint.CreateContentsForGeometry(
404423
Geometry::MakeRect(Rect::MakeSize(rect.value().size))));
405424
contents->SetAlpha(paint.color.alpha);

impeller/display_list/display_list_vertices_geometry.cc

Lines changed: 100 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -104,20 +104,21 @@ static PrimitiveType GetPrimitiveType(const flutter::DlVertices* vertices) {
104104
}
105105
}
106106

107-
GeometryResult DLVerticesGeometry::GetPositionBuffer(
108-
const ContentContext& renderer,
109-
const Entity& entity,
110-
RenderPass& pass) {
111-
auto index_count = normalized_indices_.size() == 0
112-
? vertices_->index_count()
113-
: normalized_indices_.size();
114-
auto vertex_count = vertices_->vertex_count();
115-
auto* dl_indices = normalized_indices_.size() == 0
116-
? vertices_->indices()
117-
: normalized_indices_.data();
118-
auto* dl_vertices = vertices_->vertices();
107+
bool DLVerticesGeometry::HasTextureCoordinates() const {
108+
return vertices_->texture_coordinates() != nullptr;
109+
}
110+
111+
bool DLVerticesGeometry::HasVertexColors() const {
112+
return vertices_->colors() != nullptr;
113+
}
119114

120-
size_t total_vtx_bytes = vertex_count * sizeof(float) * 2;
115+
static VertexBuffer CreateVertexBuffer(const ContentContext& renderer,
116+
size_t vertex_count,
117+
size_t index_count,
118+
size_t vertex_size,
119+
const uint8_t* vertex_data,
120+
const uint8_t* index_data) {
121+
size_t total_vtx_bytes = vertex_count * vertex_size;
121122
size_t total_idx_bytes = index_count * sizeof(uint16_t);
122123

123124
DeviceBufferDescriptor buffer_desc;
@@ -127,28 +128,41 @@ GeometryResult DLVerticesGeometry::GetPositionBuffer(
127128
auto buffer =
128129
renderer.GetContext()->GetResourceAllocator()->CreateBuffer(buffer_desc);
129130

130-
if (!buffer->CopyHostBuffer(reinterpret_cast<const uint8_t*>(dl_vertices),
131-
Range{0, total_vtx_bytes}, 0)) {
131+
if (!buffer->CopyHostBuffer(vertex_data, Range{0, total_vtx_bytes}, 0)) {
132132
return {};
133133
}
134-
if (!buffer->CopyHostBuffer(
135-
reinterpret_cast<uint8_t*>(const_cast<uint16_t*>(dl_indices)),
136-
Range{0, total_idx_bytes}, total_vtx_bytes)) {
134+
if (!buffer->CopyHostBuffer(index_data, Range{0, total_idx_bytes},
135+
total_vtx_bytes)) {
137136
return {};
138137
}
138+
return {
139+
.vertex_buffer = {.buffer = buffer, .range = Range{0, total_vtx_bytes}},
140+
.index_buffer = {.buffer = buffer,
141+
.range = Range{total_vtx_bytes, total_idx_bytes}},
142+
.index_count = index_count,
143+
.index_type = IndexType::k16bit,
144+
};
145+
}
146+
147+
GeometryResult DLVerticesGeometry::GetPositionBuffer(
148+
const ContentContext& renderer,
149+
const Entity& entity,
150+
RenderPass& pass) {
151+
auto index_count = normalized_indices_.size() == 0
152+
? vertices_->index_count()
153+
: normalized_indices_.size();
154+
auto vertex_count = vertices_->vertex_count();
155+
auto* dl_indices = normalized_indices_.size() == 0
156+
? vertices_->indices()
157+
: normalized_indices_.data();
158+
auto* dl_vertices = vertices_->vertices();
139159

140160
return GeometryResult{
141161
.type = GetPrimitiveType(vertices_),
142-
.vertex_buffer =
143-
{
144-
.vertex_buffer = {.buffer = buffer,
145-
.range = Range{0, total_vtx_bytes}},
146-
.index_buffer = {.buffer = buffer,
147-
.range =
148-
Range{total_vtx_bytes, total_idx_bytes}},
149-
.index_count = index_count,
150-
.index_type = IndexType::k16bit,
151-
},
162+
.vertex_buffer = CreateVertexBuffer(
163+
renderer, vertex_count, index_count, sizeof(float) * 2,
164+
reinterpret_cast<const uint8_t*>(dl_vertices),
165+
reinterpret_cast<const uint8_t*>(dl_indices)),
152166
.transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
153167
entity.GetTransformation(),
154168
.prevent_overdraw = false,
@@ -185,45 +199,65 @@ GeometryResult DLVerticesGeometry::GetPositionColorBuffer(
185199
}
186200
}
187201

188-
size_t total_vtx_bytes = vertex_data.size() * sizeof(VS::PerVertexData);
189-
size_t total_idx_bytes = index_count * sizeof(uint16_t);
202+
return GeometryResult{
203+
.type = GetPrimitiveType(vertices_),
204+
.vertex_buffer = CreateVertexBuffer(
205+
renderer, vertex_count, index_count, sizeof(VS::PerVertexData),
206+
reinterpret_cast<const uint8_t*>(vertex_data.data()),
207+
reinterpret_cast<const uint8_t*>(dl_indices)),
208+
.transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
209+
entity.GetTransformation(),
210+
.prevent_overdraw = false,
211+
};
212+
}
190213

191-
DeviceBufferDescriptor buffer_desc;
192-
buffer_desc.size = total_vtx_bytes + total_idx_bytes;
193-
buffer_desc.storage_mode = StorageMode::kHostVisible;
214+
GeometryResult DLVerticesGeometry::GetPositionUVBuffer(
215+
const ContentContext& renderer,
216+
const Entity& entity,
217+
RenderPass& pass) {
218+
using VS = TexturePipeline::VertexShader;
194219

195-
auto buffer =
196-
renderer.GetContext()->GetResourceAllocator()->CreateBuffer(buffer_desc);
220+
auto index_count = normalized_indices_.size() == 0
221+
? vertices_->index_count()
222+
: normalized_indices_.size();
223+
auto vertex_count = vertices_->vertex_count();
224+
auto* dl_indices = normalized_indices_.size() == 0
225+
? vertices_->indices()
226+
: normalized_indices_.data();
227+
auto* dl_vertices = vertices_->vertices();
228+
auto* dl_tex_coords = vertices_->texture_coordinates();
197229

198-
if (!buffer->CopyHostBuffer(reinterpret_cast<uint8_t*>(vertex_data.data()),
199-
Range{0, total_vtx_bytes}, 0)) {
200-
return {};
201-
}
202-
if (!buffer->CopyHostBuffer(
203-
reinterpret_cast<uint8_t*>(const_cast<uint16_t*>(dl_indices)),
204-
Range{0, total_idx_bytes}, total_vtx_bytes)) {
205-
return {};
230+
auto coverage_rect = ToRect(vertices_->bounds());
231+
232+
std::vector<VS::PerVertexData> vertex_data(vertex_count);
233+
for (auto i = 0; i < vertex_count; i++) {
234+
auto sk_point = dl_vertices[i];
235+
auto vertex = Point(sk_point.x(), sk_point.y());
236+
237+
// TODO(jonahwilliams): Instead of the coverage rect, this should use the size
238+
// of what is being sampled, such as the image size or gradient bounds.
239+
auto coverage_coords = ToPoint(dl_tex_coords[i]) / coverage_rect.size;
240+
241+
vertex_data[i] = {
242+
.position = vertex,
243+
.texture_coords = coverage_coords,
244+
};
206245
}
207246

208247
return GeometryResult{
209248
.type = GetPrimitiveType(vertices_),
210-
.vertex_buffer =
211-
{
212-
.vertex_buffer = {.buffer = buffer,
213-
.range = Range{0, total_vtx_bytes}},
214-
.index_buffer = {.buffer = buffer,
215-
.range =
216-
Range{total_vtx_bytes, total_idx_bytes}},
217-
.index_count = index_count,
218-
.index_type = IndexType::k16bit,
219-
},
249+
.vertex_buffer = CreateVertexBuffer(
250+
renderer, vertex_count, index_count, sizeof(VS::PerVertexData),
251+
reinterpret_cast<const uint8_t*>(vertex_data.data()),
252+
reinterpret_cast<const uint8_t*>(dl_indices)),
220253
.transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
221254
entity.GetTransformation(),
222255
.prevent_overdraw = false,
223256
};
224257
}
225258

226-
GeometryResult DLVerticesGeometry::GetPositionUVBuffer(
259+
// This method is used even if there are no user-provided texture coordinates.
260+
GeometryResult DLVerticesGeometry::GetPositionUVColorBuffer(
227261
const ContentContext& renderer,
228262
const Entity& entity,
229263
RenderPass& pass) {
@@ -249,10 +283,13 @@ GeometryResult DLVerticesGeometry::GetPositionUVBuffer(
249283
dl_color.getBlueF(), dl_color.getAlphaF());
250284
auto sk_point = dl_vertices[i];
251285
auto vertex = Point(sk_point.x(), sk_point.y());
252-
auto coverage_coords =
253-
(dl_tex_coords == nullptr)
254-
? (vertex - coverage_rect.origin) / coverage_rect.size
255-
: ToPoint(dl_tex_coords[i]);
286+
287+
// TODO(jonahwilliams): Instead of the coverage rect, this should use the size
288+
// of what is being sampled, such as the image size or gradient bounds.
289+
auto coverage_coords = (vertex - coverage_rect.origin) / coverage_rect.size;
290+
if (dl_tex_coords != nullptr) {
291+
coverage_coords = ToPoint(dl_tex_coords[i]) / coverage_rect.size;
292+
}
256293

257294
vertex_data[i] = {
258295
.vertices = vertex,
@@ -261,43 +298,17 @@ GeometryResult DLVerticesGeometry::GetPositionUVBuffer(
261298
};
262299
}
263300

264-
size_t total_vtx_bytes = vertex_data.size() * sizeof(VS::PerVertexData);
265-
size_t total_idx_bytes = index_count * sizeof(uint16_t);
266-
267-
DeviceBufferDescriptor buffer_desc;
268-
buffer_desc.size = total_vtx_bytes + total_idx_bytes;
269-
buffer_desc.storage_mode = StorageMode::kHostVisible;
270-
271-
auto buffer =
272-
renderer.GetContext()->GetResourceAllocator()->CreateBuffer(buffer_desc);
273-
274-
if (!buffer->CopyHostBuffer(reinterpret_cast<uint8_t*>(vertex_data.data()),
275-
Range{0, total_vtx_bytes}, 0)) {
276-
return {};
277-
}
278-
if (!buffer->CopyHostBuffer(
279-
reinterpret_cast<uint8_t*>(const_cast<uint16_t*>(dl_indices)),
280-
Range{0, total_idx_bytes}, total_vtx_bytes)) {
281-
return {};
282-
}
283-
284301
return GeometryResult{
285302
.type = GetPrimitiveType(vertices_),
286-
.vertex_buffer =
287-
{
288-
.vertex_buffer = {.buffer = buffer,
289-
.range = Range{0, total_vtx_bytes}},
290-
.index_buffer = {.buffer = buffer,
291-
.range =
292-
Range{total_vtx_bytes, total_idx_bytes}},
293-
.index_count = index_count,
294-
.index_type = IndexType::k16bit,
295-
},
303+
.vertex_buffer = CreateVertexBuffer(
304+
renderer, vertex_count, index_count, sizeof(VS::PerVertexData),
305+
reinterpret_cast<const uint8_t*>(vertex_data.data()),
306+
reinterpret_cast<const uint8_t*>(dl_indices)),
296307
.transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
297308
entity.GetTransformation(),
298309
.prevent_overdraw = false,
299310
};
300-
} // namespace impeller
311+
}
301312

302313
GeometryVertexType DLVerticesGeometry::GetVertexType() const {
303314
auto* dl_colors = vertices_->colors();

impeller/display_list/display_list_vertices_geometry.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,17 @@ class DLVerticesGeometry : public VerticesGeometry {
3636
const Entity& entity,
3737
RenderPass& pass) override;
3838

39+
// |VerticesGeometry|
40+
GeometryResult GetPositionUVColorBuffer(const ContentContext& renderer,
41+
const Entity& entity,
42+
RenderPass& pass) override;
43+
44+
// |VerticesGeometry|
45+
bool HasTextureCoordinates() const override;
46+
47+
// |VerticesGeometry|
48+
bool HasVertexColors() const override;
49+
3950
// |Geometry|
4051
GeometryResult GetPositionBuffer(const ContentContext& renderer,
4152
const Entity& entity,

impeller/entity/contents/vertices_contents.cc

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ bool VerticesContents::Render(const ContentContext& renderer,
4747
if (blend_mode_ == BlendMode::kDestination) {
4848
return RenderDestination(renderer, entity, pass);
4949
}
50+
if (blend_mode_ == BlendMode::kSource ||
51+
(geometry_->HasTextureCoordinates() && !geometry_->HasVertexColors())) {
52+
return RenderSource(renderer, entity, pass);
53+
}
5054

5155
using VS = AtlasBlendSrcOverPipeline::VertexShader;
5256
using FS = AtlasBlendSrcOverPipeline::FragmentShader;
@@ -58,7 +62,8 @@ bool VerticesContents::Render(const ContentContext& renderer,
5862
cmd.stencil_reference = entity.GetStencilDepth();
5963

6064
auto opts = OptionsFromPassAndEntity(pass, entity);
61-
auto geometry_result = geometry_->GetPositionUVBuffer(renderer, entity, pass);
65+
auto geometry_result =
66+
geometry_->GetPositionUVColorBuffer(renderer, entity, pass);
6267
cmd.BindVertices(geometry_result.vertex_buffer);
6368
opts.primitive_type = geometry_result.type;
6469

@@ -174,6 +179,7 @@ bool VerticesContents::Render(const ContentContext& renderer,
174179
OptionsFromPassAndEntity(pass, entity));
175180
break;
176181
}
182+
// TODO: skip this step if we're given an image shader.
177183
auto src_texture = src_contents_->RenderToSnapshot(renderer, entity);
178184
if (!src_texture.has_value()) {
179185
return false;
@@ -228,4 +234,48 @@ bool VerticesContents::RenderDestination(const ContentContext& renderer,
228234
return pass.AddCommand(std::move(cmd));
229235
}
230236

237+
bool VerticesContents::RenderSource(const ContentContext& renderer,
238+
const Entity& entity,
239+
RenderPass& pass) const {
240+
using VS = TextureFillVertexShader;
241+
using FS = TextureFillFragmentShader;
242+
243+
// TODO: skip this step if we're given an image shader.
244+
auto src_texture = src_contents_->RenderToSnapshot(renderer, entity);
245+
if (!src_texture.has_value()) {
246+
return false;
247+
}
248+
249+
auto& host_buffer = pass.GetTransientsBuffer();
250+
251+
Command cmd;
252+
cmd.label = "Vertices";
253+
cmd.stencil_reference = entity.GetStencilDepth();
254+
255+
auto opts = OptionsFromPassAndEntity(pass, entity);
256+
257+
auto geometry_result = geometry_->GetPositionUVBuffer(renderer, entity, pass);
258+
opts.primitive_type = geometry_result.type;
259+
cmd.pipeline = renderer.GetTexturePipeline(opts);
260+
cmd.BindVertices(geometry_result.vertex_buffer);
261+
262+
VS::VertInfo vert_info;
263+
vert_info.mvp = geometry_result.transform;
264+
265+
FS::FragInfo frag_info;
266+
frag_info.texture_sampler_y_coord_scale =
267+
src_texture->texture->GetYCoordScale();
268+
frag_info.alpha = alpha_;
269+
270+
cmd.stencil_reference = entity.GetStencilDepth();
271+
cmd.BindVertices(geometry_result.vertex_buffer);
272+
VS::BindVertInfo(cmd, host_buffer.EmplaceUniform(vert_info));
273+
FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
274+
FS::BindTextureSampler(
275+
cmd, src_texture.value().texture,
276+
renderer.GetContext()->GetSamplerLibrary()->GetSampler({}));
277+
278+
return pass.AddCommand(std::move(cmd));
279+
}
280+
231281
} // namespace impeller

0 commit comments

Comments
 (0)