blob: 5a72a54c10eada30196ba22ec31fac4181818f2a [file] [log] [blame]
// Copyright 2019 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/camera/drivers/controller/memory_allocation.h"
#include <lib/syslog/global.h>
#include <lib/trace/event.h>
#include <zircon/errors.h>
#include "src/lib/fsl/handles/object_info.h"
namespace camera {
constexpr auto kTag = "camera_controller";
ControllerMemoryAllocator::ControllerMemoryAllocator(
fuchsia::sysmem::AllocatorSyncPtr sysmem_allocator)
: sysmem_allocator_(std::move(sysmem_allocator)) {
if (sysmem_allocator_)
sysmem_allocator_->SetDebugClientInfo("camera controller " + fsl::GetCurrentProcessName(),
fsl::GetCurrentProcessKoid());
}
zx_status_t ControllerMemoryAllocator::AllocateSharedMemory(
const std::vector<fuchsia::sysmem::BufferCollectionConstraints>& constraints,
fuchsia::sysmem::BufferCollectionInfo_2* out_buffer_collection_info, std::string name) const {
TRACE_DURATION("camera", "ControllerMemoryAllocator::AllocateSharedMemory");
if (out_buffer_collection_info == nullptr) {
return ZX_ERR_INVALID_ARGS;
}
auto num_constraints = constraints.size();
// Create tokens which we'll hold on to to get our buffer_collection.
std::vector<fuchsia::sysmem::BufferCollectionTokenSyncPtr> tokens(num_constraints);
// Start the allocation process.
auto status = sysmem_allocator_->AllocateSharedCollection(tokens[0].NewRequest());
if (status != ZX_OK) {
FX_LOG(ERROR, kTag, "Failed to create token");
return status;
}
// Duplicate the tokens.
for (uint32_t i = 1; i < num_constraints; i++) {
status = tokens[0]->Duplicate(std::numeric_limits<uint32_t>::max(), tokens[i].NewRequest());
if (status != ZX_OK) {
FX_LOG(ERROR, kTag, "Failed to duplicate token");
return status;
}
}
// Now convert into a Logical BufferCollection:
std::vector<fuchsia::sysmem::BufferCollectionSyncPtr> buffer_collections(num_constraints);
status = sysmem_allocator_->BindSharedCollection(std::move(tokens[0]),
buffer_collections[0].NewRequest());
if (status != ZX_OK) {
FX_LOG(ERROR, kTag, "Failed to create logical buffer collection");
return status;
}
status = buffer_collections[0]->Sync();
if (status != ZX_OK) {
FX_LOG(ERROR, kTag, "Failed to sync");
return status;
}
constexpr uint32_t kNamePriority = 10u;
buffer_collections[0]->SetName(kNamePriority, name);
// Create rest of the logical buffer collections
for (uint32_t i = 1; i < num_constraints; i++) {
status = sysmem_allocator_->BindSharedCollection(std::move(tokens[i]),
buffer_collections[i].NewRequest());
if (status != ZX_OK) {
FX_LOG(ERROR, kTag, "Failed to create logical buffer collection");
return status;
}
}
// Set constraints
for (uint32_t i = 0; i < num_constraints; i++) {
status = buffer_collections[i]->SetConstraints(true, constraints[i]);
if (status != ZX_OK) {
FX_LOG(ERROR, kTag, "Failed to set buffer collection constraints");
return status;
}
}
zx_status_t allocation_status;
status = buffer_collections[0]->WaitForBuffersAllocated(&allocation_status,
out_buffer_collection_info);
if (status != ZX_OK || allocation_status != ZX_OK) {
FX_LOG(ERROR, kTag, "Failed to wait for buffer collection info.");
return status;
}
for (uint32_t i = 0; i < num_constraints; i++) {
status = buffer_collections[i]->Close();
if (status != ZX_OK) {
FX_LOG(ERROR, kTag, "Failed to close producer buffer collection");
return status;
}
}
// TODO(fxbug.dev/38569): Keep at least one buffer collection around to know about
// any failures sysmem wants to notify by closing the channel.
return ZX_OK;
}
} // namespace camera