blob: 23adb3c7eb01fbfd842f31b72c12b49dd29626a6 [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 "lib/escher/shape/rounded_rect_factory.h"
#include "lib/escher/escher.h"
#include "lib/escher/renderer/batch_gpu_uploader.h"
#include "lib/escher/shape/mesh.h"
#include "lib/escher/shape/mesh_spec.h"
#include "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::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: {
auto writer = batch_gpu_uploader->AcquireWriter(vertex_buffer_size);
GenerateRoundedRectVertices(spec, mesh_spec, writer->host_ptr(),
writer->size());
writer->WriteBuffer(vertex_buffer, {0, 0, vertex_buffer->size()});
batch_gpu_uploader->PostWriter(std::move(writer));
return fxl::MakeRefCounted<Mesh>(
static_cast<ResourceRecycler*>(this), mesh_spec, bounding_box,
vertex_count, index_count, vertex_buffer, std::move(index_buffer));
}
case 2: {
auto writer = batch_gpu_uploader->AcquireWriter(vertex_buffer_size);
GenerateRoundedRectVertices(
spec, mesh_spec, writer->host_ptr(),
vertex_count * primary_buffer_stride,
writer->host_ptr() + vertex_count * primary_buffer_stride,
vertex_count * secondary_buffer_stride);
writer->WriteBuffer(vertex_buffer, {0, 0, vertex_buffer->size()});
batch_gpu_uploader->PostWriter(std::move(writer));
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::eTransferDst,
vk::MemoryPropertyFlagBits::eDeviceLocal);
auto writer = batch_gpu_uploader->AcquireWriter(index_buffer_size);
GenerateRoundedRectIndices(spec, mesh_spec, writer->host_ptr(),
writer->size());
writer->WriteBuffer(index_buffer_, {0, 0, index_buffer_->size()});
batch_gpu_uploader->PostWriter(std::move(writer));
}
return index_buffer_;
}
} // namespace escher