blob: 73776c63489ccaba4e78cd363dd20718b6d29fc0 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/entity/geometry.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/position_color.vert.h"
#include "impeller/renderer/device_buffer.h"
namespace impeller {
Geometry::Geometry() = default;
Geometry::~Geometry() = default;
// static
std::unique_ptr<Geometry> Geometry::MakeVertices(Vertices vertices) {
return std::make_unique<VerticesGeometry>(std::move(vertices));
}
VerticesGeometry::VerticesGeometry(Vertices vertices)
: vertices_(std::move(vertices)) {}
VerticesGeometry::~VerticesGeometry() = default;
static PrimitiveType GetPrimitiveType(const Vertices& vertices) {
switch (vertices.GetMode()) {
case VertexMode::kTriangle:
return PrimitiveType::kTriangle;
case VertexMode::kTriangleStrip:
return PrimitiveType::kTriangleStrip;
}
}
GeometryResult VerticesGeometry::GetPositionBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer) {
if (!vertices_.IsValid()) {
return {};
}
auto vertex_count = vertices_.GetPositions().size();
size_t total_vtx_bytes = vertex_count * sizeof(float) * 2;
size_t total_idx_bytes = vertices_.GetIndices().size() * sizeof(uint16_t);
DeviceBufferDescriptor buffer_desc;
buffer_desc.size = total_vtx_bytes + total_idx_bytes;
buffer_desc.storage_mode = StorageMode::kHostVisible;
auto buffer = device_allocator->CreateBuffer(buffer_desc);
const auto& positions = vertices_.GetPositions();
if (!buffer->CopyHostBuffer(
reinterpret_cast<const uint8_t*>(positions.data()),
Range{0, total_vtx_bytes}, 0)) {
return {};
}
if (!buffer->CopyHostBuffer(reinterpret_cast<uint8_t*>(const_cast<uint16_t*>(
vertices_.GetIndices().data())),
Range{0, total_idx_bytes}, total_vtx_bytes)) {
return {};
}
return GeometryResult{
.type = GetPrimitiveType(vertices_),
.vertex_buffer =
{
.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,
},
.prevent_overdraw = false,
};
}
GeometryResult VerticesGeometry::GetPositionColorBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer,
Color paint_color,
BlendMode blend_mode) {
using VS = GeometryColorPipeline::VertexShader;
if (!vertices_.IsValid()) {
return {};
}
auto vertex_count = vertices_.GetPositions().size();
std::vector<VS::PerVertexData> vertex_data(vertex_count);
{
const auto& positions = vertices_.GetPositions();
const auto& colors = vertices_.GetColors();
for (size_t i = 0; i < vertex_count; i++) {
auto color = Color::BlendColor(paint_color, colors[i], blend_mode);
vertex_data[i] = {
.position = positions[i],
.color = color,
};
}
}
size_t total_vtx_bytes = vertex_data.size() * sizeof(VS::PerVertexData);
size_t total_idx_bytes = vertices_.GetIndices().size() * sizeof(uint16_t);
DeviceBufferDescriptor buffer_desc;
buffer_desc.size = total_vtx_bytes + total_idx_bytes;
buffer_desc.storage_mode = StorageMode::kHostVisible;
auto buffer = device_allocator->CreateBuffer(buffer_desc);
if (!buffer->CopyHostBuffer(reinterpret_cast<uint8_t*>(vertex_data.data()),
Range{0, total_vtx_bytes}, 0)) {
return {};
}
if (!buffer->CopyHostBuffer(reinterpret_cast<uint8_t*>(const_cast<uint16_t*>(
vertices_.GetIndices().data())),
Range{0, total_idx_bytes}, total_vtx_bytes)) {
return {};
}
return GeometryResult{
.type = GetPrimitiveType(vertices_),
.vertex_buffer =
{
.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,
},
.prevent_overdraw = false,
};
}
GeometryResult VerticesGeometry::GetPositionUVBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer,
ISize render_target_size) {
// TODO(jonahwilliams): support texture coordinates in vertices.
return {};
}
GeometryVertexType VerticesGeometry::GetVertexType() {
if (vertices_.GetColors().size()) {
return GeometryVertexType::kColor;
}
return GeometryVertexType::kPosition;
}
std::optional<Rect> VerticesGeometry::GetCoverage(Matrix transform) {
return vertices_.GetTransformedBoundingBox(transform);
}
} // namespace impeller