Skip to content

Commit 9b42cbc

Browse files
committed
[impeller] implement GetPositionUVBuffer
1 parent 9270e3d commit 9b42cbc

File tree

6 files changed

+205
-115
lines changed

6 files changed

+205
-115
lines changed

impeller/entity/contents/tiled_texture_contents.cc

Lines changed: 4 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,6 @@ bool TiledTextureContents::Render(const ContentContext& renderer,
8686
if (texture_ == nullptr) {
8787
return true;
8888
}
89-
// TODO(jonahwilliams): this is a special case for VerticesGeometry which
90-
// implements GetPositionUVBuffer. The general geometry case does not use
91-
// this method (see note below).
92-
auto geometry = GetGeometry();
93-
if (geometry->GetVertexType() == GeometryVertexType::kUV) {
94-
return RenderVertices(renderer, entity, pass);
95-
}
9689

9790
using VS = TiledTextureFillVertexShader;
9891
using FS = TiledTextureFillFragmentShader;
@@ -104,21 +97,14 @@ bool TiledTextureContents::Render(const ContentContext& renderer,
10497

10598
auto& host_buffer = pass.GetTransientsBuffer();
10699

107-
auto geometry_result =
108-
GetGeometry()->GetPositionBuffer(renderer, entity, pass);
109-
110-
// TODO(bdero): The geometry should be fetched from GetPositionUVBuffer and
111-
// contain coverage-mapped UVs, and this should use
112-
// position_uv.vert.
113-
// https://github.com/flutter/flutter/issues/118553
100+
auto bounds_origin = GetGeometry()->GetCoverage(Matrix())->origin;
101+
auto geometry_result = GetGeometry()->GetPositionUVBuffer(
102+
Rect(bounds_origin, Size(texture_size)), GetInverseMatrix(), renderer,
103+
entity, pass);
114104

115105
VS::FrameInfo frame_info;
116106
frame_info.mvp = geometry_result.transform;
117107
frame_info.texture_sampler_y_coord_scale = texture_->GetYCoordScale();
118-
frame_info.effect_transform = GetInverseMatrix();
119-
frame_info.bounds_origin = geometry->GetCoverage(Matrix())->origin;
120-
frame_info.texture_size = Vector2(static_cast<Scalar>(texture_size.width),
121-
static_cast<Scalar>(texture_size.height));
122108

123109
FS::FragInfo frag_info;
124110
frag_info.x_tile_mode = static_cast<Scalar>(x_tile_mode_);
@@ -169,73 +155,4 @@ bool TiledTextureContents::Render(const ContentContext& renderer,
169155
return true;
170156
}
171157

172-
bool TiledTextureContents::RenderVertices(const ContentContext& renderer,
173-
const Entity& entity,
174-
RenderPass& pass) const {
175-
using VS = PositionUVPipeline::VertexShader;
176-
using FS = PositionUVPipeline::FragmentShader;
177-
178-
const auto texture_size = texture_->GetSize();
179-
if (texture_size.IsEmpty()) {
180-
return true;
181-
}
182-
183-
auto& host_buffer = pass.GetTransientsBuffer();
184-
185-
auto geometry_result = GetGeometry()->GetPositionUVBuffer(
186-
Rect::MakeSize(texture_size), GetInverseMatrix(), renderer, entity, pass);
187-
188-
VS::FrameInfo frame_info;
189-
frame_info.mvp = geometry_result.transform;
190-
frame_info.texture_sampler_y_coord_scale = texture_->GetYCoordScale();
191-
192-
FS::FragInfo frag_info;
193-
frag_info.x_tile_mode = static_cast<Scalar>(x_tile_mode_);
194-
frag_info.y_tile_mode = static_cast<Scalar>(y_tile_mode_);
195-
frag_info.alpha = GetAlpha();
196-
197-
Command cmd;
198-
cmd.label = "PositionUV";
199-
cmd.stencil_reference = entity.GetStencilDepth();
200-
201-
auto options = OptionsFromPassAndEntity(pass, entity);
202-
if (geometry_result.prevent_overdraw) {
203-
options.stencil_compare = CompareFunction::kEqual;
204-
options.stencil_operation = StencilOperation::kIncrementClamp;
205-
}
206-
options.primitive_type = geometry_result.type;
207-
cmd.pipeline = renderer.GetPositionUVPipeline(options);
208-
209-
cmd.BindVertices(geometry_result.vertex_buffer);
210-
VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
211-
FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
212-
213-
if (color_filter_.has_value()) {
214-
auto filtered_texture = CreateFilterTexture(renderer);
215-
if (!filtered_texture.has_value()) {
216-
return false;
217-
}
218-
FS::BindTextureSampler(
219-
cmd, filtered_texture.value(),
220-
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
221-
CreateDescriptor()));
222-
} else {
223-
FS::BindTextureSampler(
224-
cmd, texture_,
225-
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
226-
CreateDescriptor()));
227-
}
228-
229-
if (!pass.AddCommand(std::move(cmd))) {
230-
return false;
231-
}
232-
233-
if (geometry_result.prevent_overdraw) {
234-
auto restore = ClipRestoreContents();
235-
restore.SetRestoreCoverage(GetCoverage(entity));
236-
return restore.Render(renderer, entity, pass);
237-
}
238-
return true;
239-
}
240-
241158
} // namespace impeller

impeller/entity/contents/tiled_texture_contents.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,6 @@ class TiledTextureContents final : public ColorSourceContents {
5353
std::optional<std::shared_ptr<Texture>> CreateFilterTexture(
5454
const ContentContext& renderer) const;
5555

56-
bool RenderVertices(const ContentContext& renderer,
57-
const Entity& entity,
58-
RenderPass& pass) const;
59-
6056
SamplerDescriptor CreateDescriptor() const;
6157

6258
std::shared_ptr<Texture> texture_;

impeller/entity/geometry.cc

Lines changed: 154 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "impeller/entity/geometry.h"
66
#include "impeller/entity/contents/content_context.h"
77
#include "impeller/entity/position_color.vert.h"
8+
#include "impeller/entity/texture_fill.vert.h"
89
#include "impeller/geometry/matrix.h"
910
#include "impeller/geometry/path_builder.h"
1011
#include "impeller/renderer/device_buffer.h"
@@ -51,6 +52,40 @@ std::unique_ptr<Geometry> Geometry::MakeRect(Rect rect) {
5152
return std::make_unique<RectGeometry>(rect);
5253
}
5354

55+
static GeometryResult ComputeUVGeometryForRect(Rect source_rect,
56+
Rect texture_coverage,
57+
Matrix effect_transform,
58+
const ContentContext& renderer,
59+
const Entity& entity,
60+
RenderPass& pass) {
61+
constexpr uint16_t kRectIndicies[4] = {0, 1, 2, 3};
62+
auto& host_buffer = pass.GetTransientsBuffer();
63+
64+
std::vector<Point> data(8);
65+
auto points = source_rect.GetPoints();
66+
for (auto i = 0u, j = 0u; i < 8; i += 2, j++) {
67+
data[i] = points[j];
68+
data[i + 1] = effect_transform * ((points[j] - texture_coverage.origin) /
69+
texture_coverage.size);
70+
}
71+
72+
return GeometryResult{
73+
.type = PrimitiveType::kTriangleStrip,
74+
.vertex_buffer =
75+
{
76+
.vertex_buffer = host_buffer.Emplace(
77+
data.data(), 16 * sizeof(float), alignof(float)),
78+
.index_buffer = host_buffer.Emplace(
79+
kRectIndicies, 4 * sizeof(uint16_t), alignof(uint16_t)),
80+
.index_count = 4,
81+
.index_type = IndexType::k16bit,
82+
},
83+
.transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
84+
entity.GetTransformation(),
85+
.prevent_overdraw = false,
86+
};
87+
}
88+
5489
/////// Path Geometry ///////
5590

5691
FillPathGeometry::FillPathGeometry(const Path& path) : path_(path) {}
@@ -89,6 +124,51 @@ GeometryResult FillPathGeometry::GetPositionBuffer(
89124
};
90125
}
91126

127+
// |Geometry|
128+
GeometryResult FillPathGeometry::GetPositionUVBuffer(
129+
Rect texture_coverage,
130+
Matrix effect_transform,
131+
const ContentContext& renderer,
132+
const Entity& entity,
133+
RenderPass& pass) {
134+
using VS = TextureFillVertexShader;
135+
136+
VertexBufferBuilder<VS::PerVertexData> vertex_builder;
137+
auto tesselation_result = renderer.GetTessellator()->Tessellate(
138+
path_.GetFillType(),
139+
path_.CreatePolyline(entity.GetTransformation().GetMaxBasisLength()),
140+
[&vertex_builder, &texture_coverage, &effect_transform](
141+
const float* vertices, size_t vertices_count, const uint16_t* indices,
142+
size_t indices_count) {
143+
for (auto i = 0u; i < vertices_count; i += 2) {
144+
VS::PerVertexData data;
145+
Point vtx = {vertices[i], vertices[i + 1]};
146+
data.position = vtx;
147+
auto coverage_coords =
148+
((vtx - texture_coverage.origin) / texture_coverage.size) /
149+
texture_coverage.size;
150+
data.texture_coords = effect_transform * coverage_coords;
151+
vertex_builder.AppendVertex(data);
152+
}
153+
FML_DCHECK(vertex_builder.GetVertexCount() == vertices_count / 2);
154+
for (auto i = 0u; i < indices_count; i++) {
155+
vertex_builder.AppendIndex(indices[i]);
156+
}
157+
return true;
158+
});
159+
if (tesselation_result != Tessellator::Result::kSuccess) {
160+
return {};
161+
}
162+
return GeometryResult{
163+
.type = PrimitiveType::kTriangle,
164+
.vertex_buffer =
165+
vertex_builder.CreateVertexBuffer(pass.GetTransientsBuffer()),
166+
.transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
167+
entity.GetTransformation(),
168+
.prevent_overdraw = false,
169+
};
170+
}
171+
92172
GeometryVertexType FillPathGeometry::GetVertexType() const {
93173
return GeometryVertexType::kPosition;
94174
}
@@ -300,9 +380,9 @@ StrokePathGeometry::CapProc StrokePathGeometry::GetCapProc(Cap stroke_cap) {
300380
}
301381

302382
// static
303-
VertexBuffer StrokePathGeometry::CreateSolidStrokeVertices(
383+
VertexBufferBuilder<SolidFillVertexShader::PerVertexData>
384+
StrokePathGeometry::CreateSolidStrokeVertices(
304385
const Path& path,
305-
HostBuffer& buffer,
306386
Scalar stroke_width,
307387
Scalar scaled_miter_limit,
308388
Cap cap,
@@ -422,7 +502,7 @@ VertexBuffer StrokePathGeometry::CreateSolidStrokeVertices(
422502
}
423503
}
424504

425-
return vtx_builder.CreateVertexBuffer(buffer);
505+
return vtx_builder;
426506
}
427507

428508
GeometryResult StrokePathGeometry::GetPositionBuffer(
@@ -441,14 +521,59 @@ GeometryResult StrokePathGeometry::GetPositionBuffer(
441521
Scalar stroke_width = std::max(stroke_width_, min_size);
442522

443523
auto& host_buffer = pass.GetTransientsBuffer();
444-
auto vertex_buffer = CreateSolidStrokeVertices(
445-
path_, host_buffer, stroke_width, miter_limit_ * stroke_width_ * 0.5,
446-
stroke_cap_, GetJoinProc(stroke_join_), GetCapProc(stroke_cap_),
524+
auto vertex_builder = CreateSolidStrokeVertices(
525+
path_, stroke_width, miter_limit_ * stroke_width_ * 0.5, stroke_cap_,
526+
GetJoinProc(stroke_join_), GetCapProc(stroke_cap_),
447527
entity.GetTransformation().GetMaxBasisLength());
448528

449529
return GeometryResult{
450530
.type = PrimitiveType::kTriangleStrip,
451-
.vertex_buffer = vertex_buffer,
531+
.vertex_buffer = vertex_builder.CreateVertexBuffer(host_buffer),
532+
.transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
533+
entity.GetTransformation(),
534+
.prevent_overdraw = true,
535+
};
536+
}
537+
538+
GeometryResult StrokePathGeometry::GetPositionUVBuffer(
539+
Rect texture_coverage,
540+
Matrix effect_transform,
541+
const ContentContext& renderer,
542+
const Entity& entity,
543+
RenderPass& pass) {
544+
if (stroke_width_ < 0.0) {
545+
return {};
546+
}
547+
auto determinant = entity.GetTransformation().GetDeterminant();
548+
if (determinant == 0) {
549+
return {};
550+
}
551+
552+
Scalar min_size = 1.0f / sqrt(std::abs(determinant));
553+
Scalar stroke_width = std::max(stroke_width_, min_size);
554+
555+
auto& host_buffer = pass.GetTransientsBuffer();
556+
auto stroke_builder = CreateSolidStrokeVertices(
557+
path_, stroke_width, miter_limit_ * stroke_width_ * 0.5, stroke_cap_,
558+
GetJoinProc(stroke_join_), GetCapProc(stroke_cap_),
559+
entity.GetTransformation().GetMaxBasisLength());
560+
561+
VertexBufferBuilder<TextureFillVertexShader::PerVertexData> vertex_builder;
562+
stroke_builder.IterateVertices(
563+
[&vertex_builder, &texture_coverage,
564+
&effect_transform](SolidFillVertexShader::PerVertexData old_vtx) {
565+
TextureFillVertexShader::PerVertexData data;
566+
data.position = old_vtx.position;
567+
auto coverage_coords = ((old_vtx.position - texture_coverage.origin) /
568+
texture_coverage.size) /
569+
texture_coverage.size;
570+
data.texture_coords = effect_transform * coverage_coords;
571+
vertex_builder.AppendVertex(data);
572+
});
573+
574+
return GeometryResult{
575+
.type = PrimitiveType::kTriangleStrip,
576+
.vertex_buffer = vertex_builder.CreateVertexBuffer(host_buffer),
452577
.transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
453578
entity.GetTransformation(),
454579
.prevent_overdraw = true,
@@ -515,6 +640,18 @@ GeometryResult CoverGeometry::GetPositionBuffer(const ContentContext& renderer,
515640
};
516641
}
517642

643+
// |Geometry|
644+
GeometryResult CoverGeometry::GetPositionUVBuffer(
645+
Rect texture_coverage,
646+
Matrix effect_transform,
647+
const ContentContext& renderer,
648+
const Entity& entity,
649+
RenderPass& pass) {
650+
auto rect = Rect(Size(pass.GetRenderTargetSize()));
651+
return ComputeUVGeometryForRect(rect, texture_coverage, effect_transform,
652+
renderer, entity, pass);
653+
}
654+
518655
GeometryVertexType CoverGeometry::GetVertexType() const {
519656
return GeometryVertexType::kPosition;
520657
}
@@ -551,6 +688,16 @@ GeometryResult RectGeometry::GetPositionBuffer(const ContentContext& renderer,
551688
};
552689
}
553690

691+
// |Geometry|
692+
GeometryResult RectGeometry::GetPositionUVBuffer(Rect texture_coverage,
693+
Matrix effect_transform,
694+
const ContentContext& renderer,
695+
const Entity& entity,
696+
RenderPass& pass) {
697+
return ComputeUVGeometryForRect(rect_, texture_coverage, effect_transform,
698+
renderer, entity, pass);
699+
}
700+
554701
GeometryVertexType RectGeometry::GetVertexType() const {
555702
return GeometryVertexType::kPosition;
556703
}

0 commit comments

Comments
 (0)