mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[Impeller] Copy user indices directly into buffer for DrawVertices (flutter/engine#34792)
This commit is contained in:
parent
24e07cd37e
commit
b14c460a7a
@ -108,7 +108,7 @@ class DlVertices {
|
||||
///
|
||||
/// Vertices are always required. Optional texture coordinates
|
||||
/// and optional colors are reserved depending on the |Flags|.
|
||||
/// Optional indices will be reserved iff the index_count is
|
||||
/// Optional indices will be reserved if the index_count is
|
||||
/// positive (>0).
|
||||
///
|
||||
/// The caller must provide all data that is promised by the
|
||||
|
||||
@ -306,11 +306,12 @@ void Canvas::DrawTextFrame(TextFrame text_frame, Point position, Paint paint) {
|
||||
}
|
||||
|
||||
void Canvas::DrawVertices(Vertices vertices,
|
||||
Entity::BlendMode mode,
|
||||
Entity::BlendMode blend_mode,
|
||||
Paint paint) {
|
||||
std::shared_ptr<VerticesContents> contents =
|
||||
std::make_shared<VerticesContents>(std::move(vertices));
|
||||
contents->SetColor(paint.color);
|
||||
contents->SetBlendMode(blend_mode);
|
||||
Entity entity;
|
||||
entity.SetTransformation(GetCurrentTransformation());
|
||||
entity.SetStencilDepth(GetStencilDepth());
|
||||
|
||||
@ -93,7 +93,9 @@ class Canvas {
|
||||
|
||||
void DrawTextFrame(TextFrame text_frame, Point position, Paint paint);
|
||||
|
||||
void DrawVertices(Vertices vertices, Entity::BlendMode mode, Paint paint);
|
||||
void DrawVertices(Vertices vertices,
|
||||
Entity::BlendMode blend_mode,
|
||||
Paint paint);
|
||||
|
||||
Picture EndRecordingAsPicture();
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#include "impeller/renderer/formats.h"
|
||||
#include "impeller/renderer/render_pass.h"
|
||||
#include "impeller/renderer/sampler_library.h"
|
||||
#include "impeller/renderer/vertex_buffer.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
@ -28,10 +29,27 @@ void VerticesContents::SetColor(Color color) {
|
||||
color_ = color.Premultiply();
|
||||
}
|
||||
|
||||
void VerticesContents::SetBlendMode(Entity::BlendMode blend_mode) {
|
||||
blend_mode_ = blend_mode;
|
||||
}
|
||||
|
||||
static PrimitiveType GetPrimitiveType(const Vertices& vertices) {
|
||||
switch (vertices.GetMode()) {
|
||||
case VertexMode::kTriangle:
|
||||
return PrimitiveType::kTriangle;
|
||||
case VertexMode::kTriangleStrip:
|
||||
return PrimitiveType::kTriangleStrip;
|
||||
}
|
||||
}
|
||||
|
||||
bool VerticesContents::Render(const ContentContext& renderer,
|
||||
const Entity& entity,
|
||||
RenderPass& pass) const {
|
||||
using VS = VerticesVertexShader;
|
||||
if (!vertices_.IsValid()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
using VS = VerticesPipeline::VertexShader;
|
||||
|
||||
const auto coverage_rect = vertices_.GetBoundingBox();
|
||||
|
||||
@ -43,42 +61,36 @@ bool VerticesContents::Render(const ContentContext& renderer,
|
||||
return true;
|
||||
}
|
||||
|
||||
VertexBufferBuilder<VS::PerVertexData> vertex_builder;
|
||||
std::vector<Point> points = vertices_.GetPoints();
|
||||
std::vector<uint16_t> indices = vertices_.GetIndices();
|
||||
// TODO: colors are currently unused, must be blended with
|
||||
// paint color based on provided blend mode.
|
||||
std::vector<Color> colors = vertices_.GetColors();
|
||||
VertexMode mode = vertices_.GetMode();
|
||||
|
||||
if (indices.size() == 0) {
|
||||
for (size_t i = 0; i < points.size(); i += 1) {
|
||||
VS::PerVertexData data;
|
||||
data.point = points[i];
|
||||
data.vertex_color = color_;
|
||||
vertex_builder.AppendVertex(data);
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < indices.size(); i += 1) {
|
||||
VS::PerVertexData data;
|
||||
data.point = points[indices[i]];
|
||||
data.vertex_color = color_;
|
||||
vertex_builder.AppendVertex(data);
|
||||
std::vector<VS::PerVertexData> vertex_data;
|
||||
{
|
||||
const auto& positions = vertices_.GetPositions();
|
||||
const auto& colors = vertices_.GetColors();
|
||||
for (size_t i = 0; i < positions.size(); i++) {
|
||||
vertex_data.push_back(VS::PerVertexData{
|
||||
.position = positions[i],
|
||||
// TODO(108047): Blend these colors together when available. Use
|
||||
// colors[i] as the destination and color_ as the
|
||||
// source. Always use color_ when vertex colors are not
|
||||
// supplied.
|
||||
.color = i < colors.size() ? colors[i] : color_,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
PrimitiveType primitiveType;
|
||||
switch (mode) {
|
||||
case VertexMode::kTriangle:
|
||||
primitiveType = PrimitiveType::kTriangle;
|
||||
break;
|
||||
case VertexMode::kTriangleStrip:
|
||||
primitiveType = PrimitiveType::kTriangleStrip;
|
||||
break;
|
||||
}
|
||||
size_t total_vtx_bytes = vertex_data.size() * sizeof(VS::PerVertexData);
|
||||
size_t total_idx_bytes = vertices_.GetIndices().size() * sizeof(uint16_t);
|
||||
|
||||
if (!vertex_builder.HasVertices()) {
|
||||
return true;
|
||||
auto buffer = renderer.GetContext()->GetTransientsAllocator()->CreateBuffer(
|
||||
StorageMode::kHostVisible, total_vtx_bytes + total_idx_bytes);
|
||||
|
||||
if (!buffer->CopyHostBuffer(reinterpret_cast<uint8_t*>(vertex_data.data()),
|
||||
Range{0, total_vtx_bytes}, 0)) {
|
||||
return false;
|
||||
}
|
||||
if (!buffer->CopyHostBuffer(reinterpret_cast<uint8_t*>(const_cast<uint16_t*>(
|
||||
vertices_.GetIndices().data())),
|
||||
Range{0, total_idx_bytes}, total_vtx_bytes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& host_buffer = pass.GetTransientsBuffer();
|
||||
@ -91,8 +103,14 @@ bool VerticesContents::Render(const ContentContext& renderer,
|
||||
cmd.pipeline =
|
||||
renderer.GetVerticesPipeline(OptionsFromPassAndEntity(pass, entity));
|
||||
cmd.stencil_reference = entity.GetStencilDepth();
|
||||
cmd.primitive_type = primitiveType;
|
||||
cmd.BindVertices(vertex_builder.CreateVertexBuffer(host_buffer));
|
||||
cmd.primitive_type = GetPrimitiveType(vertices_);
|
||||
cmd.BindVertices({
|
||||
.vertex_buffer = {.buffer = buffer, .range = Range{0, total_vtx_bytes}},
|
||||
.index_buffer = {.buffer = buffer,
|
||||
.range = Range{total_vtx_bytes, total_idx_bytes}},
|
||||
.index_count = vertices_.GetIndices().size(),
|
||||
.index_type = IndexType::k16bit,
|
||||
});
|
||||
VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
|
||||
pass.AddCommand(std::move(cmd));
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "impeller/entity/contents/contents.h"
|
||||
#include "impeller/entity/entity.h"
|
||||
#include "impeller/geometry/color.h"
|
||||
#include "impeller/geometry/path.h"
|
||||
#include "impeller/geometry/point.h"
|
||||
@ -26,6 +27,8 @@ class VerticesContents final : public Contents {
|
||||
|
||||
void SetColor(Color color);
|
||||
|
||||
void SetBlendMode(Entity::BlendMode blend_mode);
|
||||
|
||||
// |Contents|
|
||||
std::optional<Rect> GetCoverage(const Entity& entity) const override;
|
||||
|
||||
@ -37,6 +40,7 @@ class VerticesContents final : public Contents {
|
||||
public:
|
||||
Vertices vertices_;
|
||||
Color color_;
|
||||
Entity::BlendMode blend_mode_ = Entity::BlendMode::kSource;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(VerticesContents);
|
||||
};
|
||||
|
||||
@ -1055,14 +1055,31 @@ TEST_P(EntityTest, BorderMaskBlurCoverageIsCorrect) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(EntityTest, DrawVerticesSolidColorTrianglesWithoutIndex) {
|
||||
std::vector<Point> points = {Point(100, 300), Point(200, 100),
|
||||
Point(300, 300)};
|
||||
std::vector<uint16_t> indexes;
|
||||
TEST_P(EntityTest, DrawVerticesSolidColorTrianglesWithoutIndices) {
|
||||
std::vector<Point> positions = {Point(100, 300), Point(200, 100),
|
||||
Point(300, 300)};
|
||||
std::vector<Color> colors = {Color::White(), Color::White(), Color::White()};
|
||||
|
||||
Vertices vertices = Vertices(points, indexes, colors, VertexMode::kTriangle,
|
||||
Rect(100, 100, 300, 300));
|
||||
Vertices vertices = Vertices(positions, {} /* indices */, colors,
|
||||
VertexMode::kTriangle, Rect(100, 100, 300, 300));
|
||||
|
||||
std::shared_ptr<VerticesContents> contents =
|
||||
std::make_shared<VerticesContents>(vertices);
|
||||
contents->SetColor(Color::White());
|
||||
Entity e;
|
||||
e.SetTransformation(Matrix::MakeScale(GetContentScale()));
|
||||
e.SetContents(contents);
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(e));
|
||||
}
|
||||
|
||||
TEST_P(EntityTest, DrawVerticesSolidColorTrianglesWithIndices) {
|
||||
std::vector<Point> positions = {Point(100, 300), Point(200, 100),
|
||||
Point(300, 300), Point(200, 500)};
|
||||
std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
|
||||
|
||||
Vertices vertices = Vertices(positions, indices, {} /* colors */,
|
||||
VertexMode::kTriangle, Rect(100, 100, 300, 300));
|
||||
|
||||
std::shared_ptr<VerticesContents> contents =
|
||||
std::make_shared<VerticesContents>(vertices);
|
||||
|
||||
@ -2,10 +2,10 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
in vec4 color;
|
||||
in vec4 v_color;
|
||||
|
||||
out vec4 frag_color;
|
||||
|
||||
void main() {
|
||||
frag_color = color;
|
||||
frag_color = v_color;
|
||||
}
|
||||
|
||||
@ -6,12 +6,12 @@ uniform FrameInfo {
|
||||
mat4 mvp;
|
||||
} frame_info;
|
||||
|
||||
in vec2 point;
|
||||
in vec4 vertex_color;
|
||||
in vec2 position;
|
||||
in vec4 color;
|
||||
|
||||
out vec4 color;
|
||||
out vec4 v_color;
|
||||
|
||||
void main() {
|
||||
gl_Position = frame_info.mvp * vec4(point, 0.0, 1.0);
|
||||
color = vertex_color;
|
||||
gl_Position = frame_info.mvp * vec4(position, 0.0, 1.0);
|
||||
v_color = color;
|
||||
}
|
||||
|
||||
@ -1233,7 +1233,7 @@ TEST(GeometryTest, VerticesConstructorAndGetters) {
|
||||
Rect(0, 0, 4, 4));
|
||||
|
||||
ASSERT_EQ(vertices.GetBoundingBox().value(), Rect(0, 0, 4, 4));
|
||||
ASSERT_EQ(vertices.GetPoints(), points);
|
||||
ASSERT_EQ(vertices.GetPositions(), points);
|
||||
ASSERT_EQ(vertices.GetIndices(), indices);
|
||||
ASSERT_EQ(vertices.GetColors(), colors);
|
||||
ASSERT_EQ(vertices.GetMode(), VertexMode::kTriangle);
|
||||
|
||||
@ -11,14 +11,31 @@ Vertices::Vertices(std::vector<Point> points,
|
||||
std::vector<Color> colors,
|
||||
VertexMode vertex_mode,
|
||||
Rect bounds)
|
||||
: points_(std::move(points)),
|
||||
: positions_(std::move(points)),
|
||||
indices_(std::move(indices)),
|
||||
colors_(std::move(colors)),
|
||||
vertex_mode_(vertex_mode),
|
||||
bounds_(bounds){};
|
||||
bounds_(bounds) {
|
||||
NormalizeIndices();
|
||||
}
|
||||
|
||||
Vertices::~Vertices() = default;
|
||||
|
||||
bool Vertices::IsValid() const {
|
||||
size_t points_size = positions_.size();
|
||||
size_t colors_size = colors_.size();
|
||||
|
||||
if (colors_size > 0 && colors_size != points_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<Rect> Vertices::GetBoundingBox() const {
|
||||
return bounds_;
|
||||
};
|
||||
|
||||
std::optional<Rect> Vertices::GetTransformedBoundingBox(
|
||||
const Matrix& transform) const {
|
||||
auto bounds = GetBoundingBox();
|
||||
@ -28,4 +45,29 @@ std::optional<Rect> Vertices::GetTransformedBoundingBox(
|
||||
return bounds->TransformBounds(transform);
|
||||
};
|
||||
|
||||
const std::vector<Point>& Vertices::GetPositions() const {
|
||||
return positions_;
|
||||
}
|
||||
|
||||
const std::vector<uint16_t>& Vertices::GetIndices() const {
|
||||
return indices_;
|
||||
}
|
||||
|
||||
const std::vector<Color>& Vertices::GetColors() const {
|
||||
return colors_;
|
||||
}
|
||||
|
||||
VertexMode Vertices::GetMode() const {
|
||||
return vertex_mode_;
|
||||
}
|
||||
|
||||
void Vertices::NormalizeIndices() {
|
||||
if (indices_.size() != 0 || positions_.size() == 0) {
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < positions_.size(); i++) {
|
||||
indices_.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
@ -20,7 +20,7 @@ enum class VertexMode {
|
||||
|
||||
class Vertices {
|
||||
public:
|
||||
Vertices(std::vector<Point> points,
|
||||
Vertices(std::vector<Point> positions,
|
||||
std::vector<uint16_t> indices,
|
||||
std::vector<Color> colors,
|
||||
VertexMode vertex_mode,
|
||||
@ -28,24 +28,28 @@ class Vertices {
|
||||
|
||||
~Vertices();
|
||||
|
||||
std::optional<Rect> GetBoundingBox() const { return bounds_; };
|
||||
bool IsValid() const;
|
||||
|
||||
std::optional<Rect> GetBoundingBox() const;
|
||||
|
||||
std::optional<Rect> GetTransformedBoundingBox(const Matrix& transform) const;
|
||||
|
||||
const std::vector<Point>& GetPoints() const { return points_; }
|
||||
const std::vector<Point>& GetPositions() const;
|
||||
|
||||
const std::vector<uint16_t>& GetIndices() const { return indices_; }
|
||||
const std::vector<uint16_t>& GetIndices() const;
|
||||
|
||||
const std::vector<Color>& GetColors() const { return colors_; }
|
||||
const std::vector<Color>& GetColors() const;
|
||||
|
||||
VertexMode GetMode() const { return vertex_mode_; }
|
||||
VertexMode GetMode() const;
|
||||
|
||||
private:
|
||||
std::vector<Point> points_;
|
||||
std::vector<Point> positions_;
|
||||
std::vector<uint16_t> indices_;
|
||||
std::vector<Color> colors_;
|
||||
VertexMode vertex_mode_;
|
||||
Rect bounds_;
|
||||
|
||||
void NormalizeIndices();
|
||||
};
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user