blob: 438562d5f689ebc1c6e60b203ab97144c9fe8586 [file] [log] [blame]
// Copyright 2017 The Fuchsia 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 "src/ui/lib/escher/shape/rounded_rect_factory.h"
#include "src/ui/lib/escher/escher.h"
#include "src/ui/lib/escher/renderer/batch_gpu_uploader.h"
#include "src/ui/lib/escher/shape/mesh.h"
#include "src/ui/lib/escher/shape/mesh_spec.h"
#include "src/ui/lib/escher/vk/buffer_factory.h"
namespace escher {
RoundedRectFactory::RoundedRectFactory(EscherWeakPtr weak_escher)
: ResourceRecycler(std::move(weak_escher)),
buffer_factory_(GetEscherWeakPtr()->gpu_allocator(),
GetEscherWeakPtr()->resource_recycler()) {}
RoundedRectFactory::~RoundedRectFactory() {}
MeshPtr RoundedRectFactory::NewRoundedRect(const RoundedRectSpec& spec, const MeshSpec& mesh_spec,
BatchGpuUploader* batch_gpu_uploader) {
FXL_DCHECK(batch_gpu_uploader);
auto index_buffer = GetIndexBuffer(spec, mesh_spec, batch_gpu_uploader);
auto counts = GetRoundedRectMeshVertexAndIndexCounts(spec);
const uint32_t vertex_count = counts.first;
const uint32_t index_count = counts.second;
const size_t primary_buffer_stride = mesh_spec.stride(0);
const size_t secondary_buffer_stride = mesh_spec.stride(1);
const size_t vertex_buffer_size =
vertex_count * (primary_buffer_stride + secondary_buffer_stride);
auto vertex_buffer = buffer_factory_.NewBuffer(vertex_buffer_size,
vk::BufferUsageFlagBits::eVertexBuffer |
vk::BufferUsageFlagBits::eTransferSrc |
vk::BufferUsageFlagBits::eTransferDst,
vk::MemoryPropertyFlagBits::eDeviceLocal);
const auto bounding_box = BoundingBox::NewChecked(-0.5f * vec3(spec.width, spec.height, 0),
0.5f * vec3(spec.width, spec.height, 0), 1);
switch (mesh_spec.vertex_buffer_count()) {
case 1: {
batch_gpu_uploader->ScheduleWriteBuffer(
vertex_buffer,
[spec, mesh_spec, vertex_buffer_size](uint8_t* host_ptr, size_t copy_size) {
GenerateRoundedRectVertices(spec, mesh_spec, host_ptr, vertex_buffer_size);
},
/* target_offset */ 0U, /* copy_size */ vertex_buffer_size);
return fxl::MakeRefCounted<Mesh>(static_cast<ResourceRecycler*>(this), mesh_spec,
bounding_box, vertex_count, index_count, vertex_buffer,
std::move(index_buffer));
}
case 2: {
batch_gpu_uploader->ScheduleWriteBuffer(
vertex_buffer,
[spec, mesh_spec, vertex_count, primary_buffer_stride, secondary_buffer_stride](
uint8_t* host_ptr, size_t copy_size) {
GenerateRoundedRectVertices(spec, mesh_spec, host_ptr,
vertex_count * primary_buffer_stride,
host_ptr + vertex_count * primary_buffer_stride,
vertex_count * secondary_buffer_stride);
},
/* target_offset */ 0U, /* copy_size */ vertex_buffer_size);
return fxl::MakeRefCounted<Mesh>(static_cast<ResourceRecycler*>(this), mesh_spec,
bounding_box, index_count, std::move(index_buffer), 0,
vertex_count, vertex_buffer, 0, std::move(vertex_buffer),
vertex_count * primary_buffer_stride);
}
default:
FXL_CHECK(false) << "unsupported vertex buffer count: " << mesh_spec.vertex_buffer_count();
return nullptr;
}
}
BufferPtr RoundedRectFactory::GetIndexBuffer(const RoundedRectSpec& spec, const MeshSpec& mesh_spec,
BatchGpuUploader* batch_gpu_uploader) {
FXL_DCHECK(batch_gpu_uploader);
// Lazily create index buffer. Since the rounded-rect tessellation functions
// don't currently take |RoundedRectSpec.zoom| into account, we can always
// return the same index buffer.
if (!index_buffer_) {
uint32_t index_count = GetRoundedRectMeshVertexAndIndexCounts(spec).second;
size_t index_buffer_size = index_count * sizeof(MeshSpec::IndexType);
index_buffer_ = buffer_factory_.NewBuffer(index_buffer_size,
vk::BufferUsageFlagBits::eIndexBuffer |
vk::BufferUsageFlagBits::eTransferSrc |
vk::BufferUsageFlagBits::eTransferDst,
vk::MemoryPropertyFlagBits::eDeviceLocal);
batch_gpu_uploader->ScheduleWriteBuffer(
index_buffer_,
[spec, mesh_spec, index_buffer_size](uint8_t* host_ptr, size_t copy_size) {
GenerateRoundedRectIndices(spec, mesh_spec, host_ptr, index_buffer_size);
},
/* target_offset */ 0U, /* copy_size */ index_buffer_size);
}
return index_buffer_;
}
} // namespace escher