blob: 553a955d4f7e54124bfc4d62373081e5128e2890 [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 <lib/fake_ddk/fake_ddk.h>
#include <lib/gtest/test_loop_fixture.h>
#include <lib/sys/cpp/component_context.h>
#include "src/camera/drivers/controller/memory_allocation.h"
#include "src/camera/drivers/controller/pipeline_manager.h"
#include "src/camera/drivers/controller/sherlock/common_util.h"
#include "src/camera/drivers/controller/sherlock/monitoring_config.h"
#include "src/camera/drivers/controller/sherlock/video_conferencing_config.h"
#include "src/camera/drivers/controller/test/fake_gdc.h"
#include "src/camera/drivers/controller/test/fake_isp.h"
#include "src/camera/lib/format_conversion/buffer_collection_helper.h"
#include "src/camera/lib/format_conversion/format_conversion.h"
// Relaxes memory placement constraints to be more permissive. This improves the reliability of
// allocation as it is no longer competing with other components in the system for fixed
// allocations of e.g. contiguous memory.
void RelaxMemoryConstraints(
std::vector<fuchsia::sysmem::BufferCollectionConstraints>& constraints) {
for (auto& c : constraints) {
c.buffer_memory_constraints.cpu_domain_supported = true;
c.buffer_memory_constraints.ram_domain_supported = true;
c.buffer_memory_constraints.inaccessible_domain_supported = true;
c.buffer_memory_constraints.secure_required = false;
c.buffer_memory_constraints.physically_contiguous_required = false;
}
}
// NOTE: In this test, we are actually just unit testing
// the sysmem allocation using different constraints.
namespace camera {
class ControllerMemoryAllocatorTest : public gtest::TestLoopFixture {
public:
ControllerMemoryAllocatorTest()
: context_(sys::ComponentContext::CreateAndServeOutgoingDirectory()) {}
void SetUp() override {
ASSERT_EQ(ZX_OK, context_->svc()->Connect(sysmem_allocator_.NewRequest()));
ASSERT_EQ(ZX_OK, zx::event::create(0, &event_));
controller_memory_allocator_ =
std::make_unique<ControllerMemoryAllocator>(std::move(sysmem_allocator_));
pipeline_manager_ =
std::make_unique<PipelineManager>(fake_ddk::kFakeParent, dispatcher(), isp_, gdc_, ge2d_,
std::move(sysmem_allocator1_), event_);
}
void TearDown() override {
context_ = nullptr;
sysmem_allocator_ = nullptr;
}
zx::event event_;
std::unique_ptr<sys::ComponentContext> context_;
fuchsia::sysmem::AllocatorSyncPtr sysmem_allocator_;
std::unique_ptr<ControllerMemoryAllocator> controller_memory_allocator_;
std::unique_ptr<camera::PipelineManager> pipeline_manager_;
fuchsia::sysmem::AllocatorSyncPtr sysmem_allocator1_;
ddk::IspProtocolClient isp_;
ddk::GdcProtocolClient gdc_;
ddk::Ge2dProtocolClient ge2d_;
};
// Validate FR --> GDC1 --> OutputStreamMLDS
// Buffer collection constraints.
TEST_F(ControllerMemoryAllocatorTest, MonitorConfigFR) {
auto internal_config = MonitorConfigFullRes();
auto fr_constraints = internal_config.output_constraints;
auto gdc1_constraints = internal_config.child_nodes[1].input_constraints;
fuchsia::sysmem::BufferCollectionInfo_2 buffer_collection_info;
std::vector<fuchsia::sysmem::BufferCollectionConstraints> constraints;
constraints.push_back(fr_constraints);
constraints.push_back(gdc1_constraints);
RelaxMemoryConstraints(constraints);
ASSERT_EQ(ZX_OK, controller_memory_allocator_->AllocateSharedMemory(
constraints, &buffer_collection_info, "TestMonitorConfigFR"));
EXPECT_EQ(buffer_collection_info.buffer_count, kOutputStreamMlDSMinBufferForCamping);
EXPECT_GT(buffer_collection_info.settings.buffer_settings.size_bytes,
kOutputStreamMlFRHeight * kOutputStreamMlFRWidth);
EXPECT_TRUE(buffer_collection_info.settings.has_image_format_constraints);
EXPECT_EQ(fuchsia::sysmem::PixelFormatType::NV12,
buffer_collection_info.settings.image_format_constraints.pixel_format.type);
EXPECT_EQ(kOutputStreamMlFRHeight,
buffer_collection_info.settings.image_format_constraints.required_max_coded_height);
EXPECT_EQ(kOutputStreamMlFRWidth,
buffer_collection_info.settings.image_format_constraints.required_max_coded_width);
EXPECT_EQ(kIspBytesPerRowDivisor,
buffer_collection_info.settings.image_format_constraints.bytes_per_row_divisor);
for (uint32_t i = 0; i < buffer_collection_info.buffer_count; i++) {
EXPECT_TRUE(buffer_collection_info.buffers.at(i).vmo.is_valid());
}
EXPECT_FALSE(
buffer_collection_info.buffers.at(buffer_collection_info.buffer_count).vmo.is_valid());
}
// Validate FR --> GDC1
TEST_F(ControllerMemoryAllocatorTest, VideoConfigFRGDC1) {
auto internal_config = VideoConfigFullRes(false);
auto fr_constraints = internal_config.output_constraints;
auto gdc1_constraints = internal_config.child_nodes[0].input_constraints;
fuchsia::sysmem::BufferCollectionInfo_2 buffer_collection_info;
std::vector<fuchsia::sysmem::BufferCollectionConstraints> constraints;
constraints.push_back(fr_constraints);
constraints.push_back(gdc1_constraints);
RelaxMemoryConstraints(constraints);
ASSERT_EQ(ZX_OK, controller_memory_allocator_->AllocateSharedMemory(
constraints, &buffer_collection_info, "TestVideoConfigFRGDC1"));
EXPECT_EQ(buffer_collection_info.buffer_count, kMlFRMinBufferForCamping + kGdcBufferForCamping);
EXPECT_GT(buffer_collection_info.settings.buffer_settings.size_bytes, kIspFRWidth * kIspFRHeight);
EXPECT_TRUE(buffer_collection_info.settings.has_image_format_constraints);
EXPECT_EQ(fuchsia::sysmem::PixelFormatType::NV12,
buffer_collection_info.settings.image_format_constraints.pixel_format.type);
EXPECT_EQ(kIspFRHeight,
buffer_collection_info.settings.image_format_constraints.required_max_coded_height);
EXPECT_EQ(kIspFRWidth,
buffer_collection_info.settings.image_format_constraints.required_max_coded_width);
EXPECT_EQ(kIspBytesPerRowDivisor,
buffer_collection_info.settings.image_format_constraints.bytes_per_row_divisor);
for (uint32_t i = 0; i < buffer_collection_info.buffer_count; i++) {
EXPECT_TRUE(buffer_collection_info.buffers.at(i).vmo.is_valid());
}
EXPECT_FALSE(
buffer_collection_info.buffers.at(buffer_collection_info.buffer_count).vmo.is_valid());
}
// Validate GDC1 ---> GDC2
// |
// ---> GE2D
TEST_F(ControllerMemoryAllocatorTest, VideoConfigGDC1GDC2) {
auto input_node = VideoConfigFullRes(false);
auto gdc1_node = input_node.child_nodes[0];
auto gdc2_node = gdc1_node.child_nodes[0];
auto ge2d_node = gdc1_node.child_nodes[1];
auto gdc1_constraints = gdc1_node.output_constraints;
auto gdc2_constraints = gdc2_node.input_constraints;
auto ge2d_constraints = ge2d_node.input_constraints;
fuchsia::sysmem::BufferCollectionInfo_2 buffer_collection_info;
std::vector<fuchsia::sysmem::BufferCollectionConstraints> constraints;
constraints.push_back(gdc1_constraints);
constraints.push_back(gdc2_constraints);
constraints.push_back(ge2d_constraints);
RelaxMemoryConstraints(constraints);
ASSERT_EQ(ZX_OK, controller_memory_allocator_->AllocateSharedMemory(
constraints, &buffer_collection_info, "TestvideoConfigGDC1GDC2"));
EXPECT_EQ(buffer_collection_info.buffer_count,
kVideoMinBufferForCamping + kVideoMinBufferForCamping);
EXPECT_GT(buffer_collection_info.settings.buffer_settings.size_bytes, kGdcFRWidth * kGdcFRHeight);
EXPECT_TRUE(buffer_collection_info.settings.has_image_format_constraints);
EXPECT_EQ(fuchsia::sysmem::PixelFormatType::NV12,
buffer_collection_info.settings.image_format_constraints.pixel_format.type);
EXPECT_EQ(kGdcFRHeight,
buffer_collection_info.settings.image_format_constraints.required_max_coded_height);
EXPECT_EQ(kGdcFRWidth,
buffer_collection_info.settings.image_format_constraints.required_max_coded_width);
EXPECT_EQ(kGe2dBytesPerRowDivisor,
buffer_collection_info.settings.image_format_constraints.bytes_per_row_divisor);
for (uint32_t i = 0; i < buffer_collection_info.buffer_count; i++) {
EXPECT_TRUE(buffer_collection_info.buffers.at(i).vmo.is_valid());
}
EXPECT_FALSE(
buffer_collection_info.buffers.at(buffer_collection_info.buffer_count).vmo.is_valid());
}
// Validate DS --> GDC2 --> (GE2D) --> OutputStreamMonitoring
// This validates only DS --> GDC2
// Buffer collection constraints.
TEST_F(ControllerMemoryAllocatorTest, MonitorConfigDS) {
auto internal_config = MonitorConfigDownScaledRes();
auto ds_constraints = internal_config.output_constraints;
auto gdc2_constraints = internal_config.child_nodes[0].input_constraints;
fuchsia::sysmem::BufferCollectionInfo_2 buffer_collection_info;
std::vector<fuchsia::sysmem::BufferCollectionConstraints> constraints;
constraints.push_back(ds_constraints);
constraints.push_back(gdc2_constraints);
RelaxMemoryConstraints(constraints);
ASSERT_EQ(ZX_OK, controller_memory_allocator_->AllocateSharedMemory(
constraints, &buffer_collection_info, "TestMonitorConfigDS"));
EXPECT_EQ(buffer_collection_info.buffer_count, kOutputStreamMonitoringMinBufferForCamping);
EXPECT_GT(buffer_collection_info.settings.buffer_settings.size_bytes,
kOutputStreamDSHeight * kOutputStreamDSWidth);
EXPECT_TRUE(buffer_collection_info.settings.has_image_format_constraints);
EXPECT_EQ(fuchsia::sysmem::PixelFormatType::NV12,
buffer_collection_info.settings.image_format_constraints.pixel_format.type);
EXPECT_EQ(0u, buffer_collection_info.settings.image_format_constraints.min_coded_height);
EXPECT_EQ(0u, buffer_collection_info.settings.image_format_constraints.min_coded_width);
EXPECT_EQ(kIspBytesPerRowDivisor,
buffer_collection_info.settings.image_format_constraints.bytes_per_row_divisor);
for (uint32_t i = 0; i < buffer_collection_info.buffer_count; i++) {
EXPECT_TRUE(buffer_collection_info.buffers.at(i).vmo.is_valid());
}
EXPECT_FALSE(
buffer_collection_info.buffers.at(buffer_collection_info.buffer_count).vmo.is_valid());
}
TEST_F(ControllerMemoryAllocatorTest, ConvertBufferCollectionInfo2TypeTest) {
auto internal_config = MonitorConfigFullRes();
auto fr_constraints = internal_config.output_constraints;
auto gdc1_constraints = internal_config.child_nodes[1].input_constraints;
fuchsia::sysmem::BufferCollectionInfo_2 hlcpp_buffer;
std::vector<fuchsia::sysmem::BufferCollectionConstraints> constraints;
constraints.push_back(fr_constraints);
constraints.push_back(gdc1_constraints);
RelaxMemoryConstraints(constraints);
// Allocating some buffer collection
ASSERT_EQ(ZX_OK, controller_memory_allocator_->AllocateSharedMemory(
constraints, &hlcpp_buffer, "TestConvertBufferCollection2TypeTest"));
EXPECT_EQ(hlcpp_buffer.buffer_count, kOutputStreamMlDSMinBufferForCamping);
BufferCollectionHelper buffer_collection_helper(hlcpp_buffer);
fuchsia_sysmem_BufferCollectionInfo_2 c_buffer = *buffer_collection_helper.GetC();
EXPECT_EQ(c_buffer.buffer_count, hlcpp_buffer.buffer_count);
auto& c_buffer_settings = c_buffer.settings.buffer_settings;
auto& hlcpp_buffer_settings = hlcpp_buffer.settings.buffer_settings;
EXPECT_EQ(c_buffer_settings.size_bytes, hlcpp_buffer_settings.size_bytes);
EXPECT_EQ(c_buffer_settings.heap,
*reinterpret_cast<const fuchsia_sysmem_HeapType*>(&hlcpp_buffer_settings.heap));
EXPECT_EQ(c_buffer.settings.has_image_format_constraints,
hlcpp_buffer.settings.has_image_format_constraints);
auto& c_image_format_constraints = c_buffer.settings.image_format_constraints;
auto& hlcpp_image_format_constraints = hlcpp_buffer.settings.image_format_constraints;
EXPECT_EQ(c_image_format_constraints.pixel_format.type,
*reinterpret_cast<const fuchsia_sysmem_PixelFormatType*>(
&hlcpp_image_format_constraints.pixel_format.type));
EXPECT_EQ(c_image_format_constraints.pixel_format.has_format_modifier,
hlcpp_image_format_constraints.pixel_format.has_format_modifier);
EXPECT_EQ(c_image_format_constraints.pixel_format.format_modifier.value,
hlcpp_image_format_constraints.pixel_format.format_modifier.value);
EXPECT_EQ(c_image_format_constraints.color_spaces_count,
hlcpp_image_format_constraints.color_spaces_count);
EXPECT_EQ(c_image_format_constraints.min_coded_width,
hlcpp_image_format_constraints.min_coded_width);
EXPECT_EQ(c_image_format_constraints.max_coded_width,
hlcpp_image_format_constraints.max_coded_width);
EXPECT_EQ(c_image_format_constraints.min_coded_height,
hlcpp_image_format_constraints.min_coded_height);
EXPECT_EQ(c_image_format_constraints.max_coded_height,
hlcpp_image_format_constraints.max_coded_height);
EXPECT_EQ(c_image_format_constraints.min_bytes_per_row,
hlcpp_image_format_constraints.min_bytes_per_row);
EXPECT_EQ(c_image_format_constraints.max_bytes_per_row,
hlcpp_image_format_constraints.max_bytes_per_row);
EXPECT_EQ(c_image_format_constraints.max_coded_width_times_coded_height,
hlcpp_image_format_constraints.max_coded_width_times_coded_height);
EXPECT_EQ(c_image_format_constraints.layers, hlcpp_image_format_constraints.layers);
EXPECT_EQ(c_image_format_constraints.coded_width_divisor,
hlcpp_image_format_constraints.coded_width_divisor);
EXPECT_EQ(c_image_format_constraints.coded_height_divisor,
hlcpp_image_format_constraints.coded_height_divisor);
EXPECT_EQ(c_image_format_constraints.bytes_per_row_divisor,
hlcpp_image_format_constraints.bytes_per_row_divisor);
EXPECT_EQ(c_image_format_constraints.start_offset_divisor,
hlcpp_image_format_constraints.start_offset_divisor);
EXPECT_EQ(c_image_format_constraints.display_width_divisor,
hlcpp_image_format_constraints.display_width_divisor);
EXPECT_EQ(c_image_format_constraints.display_height_divisor,
hlcpp_image_format_constraints.display_height_divisor);
EXPECT_EQ(c_image_format_constraints.required_min_coded_width,
hlcpp_image_format_constraints.required_min_coded_width);
EXPECT_EQ(c_image_format_constraints.required_max_coded_width,
hlcpp_image_format_constraints.required_max_coded_width);
EXPECT_EQ(c_image_format_constraints.required_min_coded_height,
hlcpp_image_format_constraints.required_min_coded_height);
EXPECT_EQ(c_image_format_constraints.required_max_coded_height,
hlcpp_image_format_constraints.required_max_coded_height);
EXPECT_EQ(c_image_format_constraints.required_min_bytes_per_row,
hlcpp_image_format_constraints.required_min_bytes_per_row);
EXPECT_EQ(c_image_format_constraints.required_max_bytes_per_row,
hlcpp_image_format_constraints.required_max_bytes_per_row);
for (uint32_t i = 0; i < c_buffer.buffer_count; ++i) {
EXPECT_EQ(ZX_OK, zx_handle_close(c_buffer.buffers[i].vmo));
}
}
TEST_F(ControllerMemoryAllocatorTest, ConvertImageFormat2TypeTest) {
auto internal_config = MonitorConfigFullRes();
auto vector_image_formats = internal_config.image_formats;
fuchsia::sysmem::ImageFormat_2 hlcpp_image_format = vector_image_formats[0];
fuchsia_sysmem_ImageFormat_2 c_image_format = ConvertHlcppImageFormat2toCType(hlcpp_image_format);
EXPECT_EQ(c_image_format.pixel_format.type,
*reinterpret_cast<const fuchsia_sysmem_PixelFormatType*>(
&hlcpp_image_format.pixel_format.type));
EXPECT_EQ(c_image_format.pixel_format.has_format_modifier,
hlcpp_image_format.pixel_format.has_format_modifier);
EXPECT_EQ(c_image_format.pixel_format.format_modifier.value,
hlcpp_image_format.pixel_format.format_modifier.value);
EXPECT_EQ(c_image_format.coded_width, hlcpp_image_format.coded_width);
EXPECT_EQ(c_image_format.coded_height, hlcpp_image_format.coded_height);
EXPECT_EQ(c_image_format.bytes_per_row, hlcpp_image_format.bytes_per_row);
EXPECT_EQ(c_image_format.display_width, hlcpp_image_format.display_width);
EXPECT_EQ(c_image_format.display_height, hlcpp_image_format.display_height);
EXPECT_EQ(c_image_format.layers, hlcpp_image_format.layers);
EXPECT_EQ(c_image_format.has_pixel_aspect_ratio, hlcpp_image_format.has_pixel_aspect_ratio);
EXPECT_EQ(c_image_format.pixel_aspect_ratio_width, hlcpp_image_format.pixel_aspect_ratio_width);
EXPECT_EQ(c_image_format.pixel_aspect_ratio_height, hlcpp_image_format.pixel_aspect_ratio_height);
}
} // namespace camera