| // 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" | |
| // 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); | |
| EXPECT_EQ(ZX_OK, controller_memory_allocator_->AllocateSharedMemory(constraints, | |
| &buffer_collection_info)); | |
| EXPECT_EQ(buffer_collection_info.buffer_count, kOutputStreamMlDSMinBufferForCamping); | |
| EXPECT_TRUE(buffer_collection_info.settings.buffer_settings.is_physically_contiguous); | |
| 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); | |
| EXPECT_EQ(ZX_OK, controller_memory_allocator_->AllocateSharedMemory(constraints, | |
| &buffer_collection_info)); | |
| EXPECT_EQ(buffer_collection_info.buffer_count, kMlFRMinBufferForCamping + kGdcBufferForCamping); | |
| EXPECT_TRUE(buffer_collection_info.settings.buffer_settings.is_physically_contiguous); | |
| 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); | |
| EXPECT_EQ(ZX_OK, controller_memory_allocator_->AllocateSharedMemory(constraints, | |
| &buffer_collection_info)); | |
| EXPECT_EQ(buffer_collection_info.buffer_count, | |
| kVideoMinBufferForCamping + kVideoMinBufferForCamping); | |
| EXPECT_TRUE(buffer_collection_info.settings.buffer_settings.is_physically_contiguous); | |
| 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); | |
| EXPECT_EQ(ZX_OK, controller_memory_allocator_->AllocateSharedMemory(constraints, | |
| &buffer_collection_info)); | |
| EXPECT_EQ(buffer_collection_info.buffer_count, kOutputStreamMonitoringMinBufferForCamping); | |
| EXPECT_TRUE(buffer_collection_info.settings.buffer_settings.is_physically_contiguous); | |
| 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); | |
| // Allocating some buffer collection | |
| EXPECT_EQ(ZX_OK, controller_memory_allocator_->AllocateSharedMemory(constraints, &hlcpp_buffer)); | |
| 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.is_physically_contiguous, | |
| hlcpp_buffer_settings.is_physically_contiguous); | |
| EXPECT_EQ(c_buffer_settings.is_secure, hlcpp_buffer_settings.is_secure); | |
| EXPECT_EQ(c_buffer_settings.coherency_domain, | |
| *reinterpret_cast<const fuchsia_sysmem_CoherencyDomain*>( | |
| &hlcpp_buffer_settings.coherency_domain)); | |
| 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 |