| // Copyright 2018 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/sysmem-version/sysmem-version.h" |
| |
| #include <fuchsia/sysmem/c/fidl.h> |
| #include <fuchsia/sysmem/llcpp/fidl.h> |
| #include <fuchsia/sysmem2/llcpp/fidl.h> |
| #include <inttypes.h> |
| #include <lib/fidl-async-2/fidl_struct.h> |
| #include <lib/sysmem-make-tracking/make_tracking.h> |
| #include <zircon/assert.h> |
| |
| #include <map> |
| #include <set> |
| |
| #include "log.h" |
| |
| namespace sysmem { |
| namespace { |
| |
| // Can be replaced with std::remove_cvref<> when C++20. |
| template <typename T> |
| struct RemoveCVRef |
| : ::sysmem::internal::TypeIdentity<std::remove_cv_t<std::remove_reference_t<T>>> {}; |
| template <typename T> |
| using RemoveCVRef_t = typename RemoveCVRef<T>::type; |
| |
| template <typename T, typename Enable = void> |
| struct IsFidlScalar : std::false_type {}; |
| template <typename T> |
| struct IsFidlScalar< |
| T, typename std::enable_if<fidl::IsFidlType<T>::value && |
| (std::is_arithmetic<T>::value || std::is_enum<T>::value)>::type> |
| : std::true_type {}; |
| |
| template <typename V2Type, typename V1Type, typename Enable = void> |
| struct IsCompatibleFidlScalarTypes : std::false_type {}; |
| template <typename V2Type, typename V1Type> |
| struct IsCompatibleFidlScalarTypes< |
| V2Type, V1Type, |
| typename std::enable_if< |
| // must be able to write to v2 |
| !std::is_const<typename std::remove_reference<V2Type>::type>::value && |
| IsFidlScalar<typename RemoveCVRef<V2Type>::type>::value && |
| IsFidlScalar<typename RemoveCVRef<V1Type>::type>::value && |
| std::is_same<typename ::sysmem::internal::UnderlyingTypeOrType< |
| typename RemoveCVRef<V2Type>::type>::type, |
| typename ::sysmem::internal::UnderlyingTypeOrType< |
| typename RemoveCVRef<V1Type>::type>::type>::value>::type> |
| : std::true_type {}; |
| template <typename V2, typename V1> |
| inline constexpr bool IsCompatibleFidlScalarTypes_v = IsCompatibleFidlScalarTypes<V2, V1>::value; |
| |
| // The C++ style guide discourages macros, but does not prohibit them. To operate on a bunch of |
| // separate fields with different names, it's a choice among tons of error-prone repetetive |
| // verbosity, macros, or more abstraction than I think anyone would want. Macros are the least-bad |
| // option (among those options considred so far). Feel free to propose another option. |
| |
| // This macro is needed to cut down on the noise from the exact same error check occurring every |
| // place we might early return a failure. |
| #define OK_OR_RET_ERROR(foo) \ |
| do { \ |
| if (!(foo).is_ok()) { \ |
| LOG(ERROR, "!is_ok()"); \ |
| return fit::error(); \ |
| } \ |
| } while (false) |
| |
| // This macro is needed to ensure that we don't cross-wire fields as we're converting from V1 to V2 |
| // and to cut down on the noise from the exact same code structure for most fields. Also, this way |
| // we can include a static check that the type of the v2 field exactly matches the type of the v1 |
| // field, which doesn't generate any actual code, yet needs to be repeated for each field being |
| // converted. |
| // |
| // This handles scalar fields, including enum fields. It doesn't handle vector fields, tensor |
| // fields, struct fields, or table fields. |
| // |
| // All bool fields are set regardless of false or true. Other scalar fields are only set if not |
| // equal to zero. |
| #define PROCESS_SCALAR_FIELD_V1(field_name) \ |
| do { \ |
| using V2FieldType = std::remove_reference<decltype(v2b.build().field_name())>::type; \ |
| /* double parens are significant here */ \ |
| using V1FieldType = std::remove_reference<decltype((v1.field_name))>::type; \ |
| static_assert(IsCompatibleFidlScalarTypes_v<V2FieldType, V1FieldType>); \ |
| if (std::is_same<bool, RemoveCVRef<V1FieldType>::type>::value || \ |
| static_cast<bool>(v1.field_name)) { \ |
| v2b.set_##field_name(MakeTracking(allocator, static_cast<V2FieldType>(v1.field_name))); \ |
| } \ |
| } while (false) |
| |
| #define PROCESS_SCALAR_FIELD_V2(field_name) \ |
| do { \ |
| using V1FieldType = decltype(v1.field_name); \ |
| using V2FieldType = std::remove_reference<decltype(v2.field_name())>::type; \ |
| static_assert(IsCompatibleFidlScalarTypes<V1FieldType, V2FieldType>::value); \ |
| if (v2.has_##field_name()) { \ |
| v1.field_name = static_cast<V1FieldType>(v2.field_name()); \ |
| } else { \ |
| v1.field_name = static_cast<V1FieldType>(0); \ |
| } \ |
| } while (false) |
| |
| #define ASSIGN_SCALAR(dst, src) \ |
| do { \ |
| using DstType = decltype((dst)); \ |
| using SrcType = decltype((src)); \ |
| static_assert(IsCompatibleFidlScalarTypes_v<DstType, SrcType>); \ |
| using DstNoRef = std::remove_reference<DstType>::type; \ |
| (dst) = static_cast<DstNoRef>(src); \ |
| } while (false) |
| |
| template <size_t N> |
| fit::result<fidl::VectorView<llcpp::fuchsia::sysmem2::HeapType>> V2CopyFromV1HeapPermittedArray( |
| fidl::Allocator* allocator, const fidl::Array<llcpp::fuchsia::sysmem::HeapType, N>& v1a, |
| const uint32_t v1_count) { |
| ZX_DEBUG_ASSERT(allocator); |
| ZX_DEBUG_ASSERT(v1_count); |
| if (v1_count > v1a.size()) { |
| LOG(ERROR, "v1_count > v1a.size() - v1_count: %u v1a.size(): %zu", v1_count, v1a.size()); |
| return fit::error(); |
| } |
| auto v2a = allocator->make_vec<llcpp::fuchsia::sysmem2::HeapType>(v1_count); |
| for (uint32_t i = 0; i < v1_count; i++) { |
| ASSIGN_SCALAR(v2a[i], v1a[i]); |
| } |
| return fit::ok(std::move(v2a)); |
| } |
| |
| template <size_t N> |
| fit::result<fidl::VectorView<llcpp::fuchsia::sysmem2::ColorSpace>> V2CopyFromV1ColorSpaceArray( |
| fidl::Allocator* allocator, const fidl::Array<llcpp::fuchsia::sysmem::ColorSpace, N>& v1a, |
| uint32_t v1_count) { |
| ZX_DEBUG_ASSERT(allocator); |
| ZX_DEBUG_ASSERT(v1_count); |
| if (v1_count > v1a.size()) { |
| LOG(ERROR, "v1_count > v1a.size() - v1_count: %u v1a.size(): %zu", v1_count, v1a.size()); |
| return fit::error(); |
| } |
| auto v2a = allocator->make_vec<llcpp::fuchsia::sysmem2::ColorSpace>(v1_count); |
| for (uint32_t i = 0; i < v1_count; i++) { |
| v2a[i] = V2CopyFromV1ColorSpace(allocator, v1a[i]).build(); |
| } |
| return fit::ok(std::move(v2a)); |
| } |
| |
| template <size_t N> |
| fit::result<fidl::VectorView<llcpp::fuchsia::sysmem2::ImageFormatConstraints>> |
| V2CopyFromV1ImageFormatConstraintsArray( |
| fidl::Allocator* allocator, |
| const fidl::Array<llcpp::fuchsia::sysmem::ImageFormatConstraints, N>& v1a, |
| const uint32_t v1_count) { |
| ZX_DEBUG_ASSERT(allocator); |
| ZX_DEBUG_ASSERT(v1_count); |
| if (v1_count > v1a.size()) { |
| LOG(ERROR, "v1_count > v1a.size() - v1_count: %u v1a.size(): %zu", v1_count, v1a.size()); |
| return fit::error(); |
| } |
| auto v2a = allocator->make_vec<llcpp::fuchsia::sysmem2::ImageFormatConstraints>(v1_count); |
| for (uint32_t i = 0; i < v1_count; i++) { |
| auto result = V2CopyFromV1ImageFormatConstraints(allocator, v1a[i]); |
| OK_OR_RET_ERROR(result); |
| v2a[i] = result.take_value().build(); |
| } |
| return fit::ok(std::move(v2a)); |
| } |
| |
| fit::result<> V2CopyFromV1BufferCollectionConstraintsMain( |
| fidl::Allocator* allocator, |
| llcpp::fuchsia::sysmem2::BufferCollectionConstraints::Builder* v2b_param, |
| const llcpp::fuchsia::sysmem::BufferCollectionConstraints& v1) { |
| ZX_DEBUG_ASSERT(allocator); |
| ZX_DEBUG_ASSERT(v2b_param); |
| llcpp::fuchsia::sysmem2::BufferCollectionConstraints::Builder& v2b = *v2b_param; |
| |
| // This sets usage regardless of whether the client set any usage bits within uage. That's |
| // checked later (regardless of v1 or v2 client). If a v1 client said !has_constraints, we |
| // won't call the current method and usage field will remain un-set so that |
| // Constraints2.IsEmpty() overall. |
| { |
| auto result = V2CopyFromV1BufferUsage(allocator, v1.usage); |
| OK_OR_RET_ERROR(result); |
| v2b.set_usage(sysmem::MakeTracking(allocator, result.take_value().build())); |
| } |
| |
| PROCESS_SCALAR_FIELD_V1(min_buffer_count_for_camping); |
| PROCESS_SCALAR_FIELD_V1(min_buffer_count_for_dedicated_slack); |
| PROCESS_SCALAR_FIELD_V1(min_buffer_count_for_shared_slack); |
| PROCESS_SCALAR_FIELD_V1(min_buffer_count); |
| PROCESS_SCALAR_FIELD_V1(max_buffer_count); |
| if (v1.has_buffer_memory_constraints) { |
| auto result = V2CopyFromV1BufferMemoryConstraints(allocator, v1.buffer_memory_constraints); |
| OK_OR_RET_ERROR(result); |
| v2b.set_buffer_memory_constraints(sysmem::MakeTracking(allocator, result.take_value().build())); |
| } |
| if (v1.image_format_constraints_count) { |
| auto result = V2CopyFromV1ImageFormatConstraintsArray(allocator, v1.image_format_constraints, |
| v1.image_format_constraints_count); |
| OK_OR_RET_ERROR(result); |
| v2b.set_image_format_constraints(sysmem::MakeTracking(allocator, result.take_value())); |
| } |
| return fit::ok(); |
| } |
| |
| fit::result<> V2CopyFromV1BufferCollectionConstraintsAuxBuffers( |
| fidl::Allocator* allocator, |
| llcpp::fuchsia::sysmem2::BufferCollectionConstraints::Builder* v2b_param, |
| const llcpp::fuchsia::sysmem::BufferCollectionConstraintsAuxBuffers& v1) { |
| ZX_DEBUG_ASSERT(allocator); |
| ZX_DEBUG_ASSERT(v2b_param); |
| llcpp::fuchsia::sysmem2::BufferCollectionConstraints::Builder& v2b = *v2b_param; |
| PROCESS_SCALAR_FIELD_V1(need_clear_aux_buffers_for_secure); |
| PROCESS_SCALAR_FIELD_V1(allow_clear_aux_buffers_for_secure); |
| return fit::ok(); |
| } |
| |
| } // namespace |
| |
| llcpp::fuchsia::sysmem2::PixelFormat::Builder V2CopyFromV1PixelFormat( |
| fidl::Allocator* allocator, const llcpp::fuchsia::sysmem::PixelFormat& v1) { |
| ZX_DEBUG_ASSERT(allocator); |
| auto v2b = allocator->make_table_builder<llcpp::fuchsia::sysmem2::PixelFormat>(); |
| PROCESS_SCALAR_FIELD_V1(type); |
| if (v1.has_format_modifier) { |
| v2b.set_format_modifier_value(sysmem::MakeTracking(allocator, v1.format_modifier.value)); |
| } |
| return v2b; |
| } |
| |
| llcpp::fuchsia::sysmem2::PixelFormat::Builder V2CopyFromV1PixelFormat( |
| fidl::Allocator* allocator, const fuchsia_sysmem_PixelFormat& v1) { |
| ZX_DEBUG_ASSERT(allocator); |
| using CStruct = FidlStruct<fuchsia_sysmem_PixelFormat, llcpp::fuchsia::sysmem::PixelFormat>; |
| return V2CopyFromV1PixelFormat(allocator, *CStruct::BorrowAsLlcpp(&v1)); |
| } |
| |
| llcpp::fuchsia::sysmem2::ColorSpace::Builder V2CopyFromV1ColorSpace( |
| fidl::Allocator* allocator, const llcpp::fuchsia::sysmem::ColorSpace& v1) { |
| ZX_DEBUG_ASSERT(allocator); |
| auto v2b = allocator->make_table_builder<llcpp::fuchsia::sysmem2::ColorSpace>(); |
| PROCESS_SCALAR_FIELD_V1(type); |
| return v2b; |
| } |
| |
| llcpp::fuchsia::sysmem2::ColorSpace::Builder V2CopyFromV1ColorSpace( |
| fidl::Allocator* allocator, const fuchsia_sysmem_ColorSpace& v1) { |
| using CStruct = FidlStruct<fuchsia_sysmem_ColorSpace, llcpp::fuchsia::sysmem::ColorSpace>; |
| return V2CopyFromV1ColorSpace(allocator, *CStruct::BorrowAsLlcpp(&v1)); |
| } |
| |
| fit::result<llcpp::fuchsia::sysmem2::ImageFormatConstraints::Builder> |
| V2CopyFromV1ImageFormatConstraints(fidl::Allocator* allocator, |
| const llcpp::fuchsia::sysmem::ImageFormatConstraints& v1) { |
| ZX_DEBUG_ASSERT(allocator); |
| auto v2b = allocator->make_table_builder<llcpp::fuchsia::sysmem2::ImageFormatConstraints>(); |
| v2b.set_pixel_format( |
| MakeTracking(allocator, V2CopyFromV1PixelFormat(allocator, v1.pixel_format).build())); |
| if (v1.color_spaces_count) { |
| auto result = V2CopyFromV1ColorSpaceArray(allocator, v1.color_space, v1.color_spaces_count); |
| OK_OR_RET_ERROR(result); |
| v2b.set_color_spaces(MakeTracking(allocator, result.take_value())); |
| } |
| PROCESS_SCALAR_FIELD_V1(min_coded_width); |
| PROCESS_SCALAR_FIELD_V1(max_coded_width); |
| PROCESS_SCALAR_FIELD_V1(min_coded_height); |
| PROCESS_SCALAR_FIELD_V1(max_coded_height); |
| PROCESS_SCALAR_FIELD_V1(min_bytes_per_row); |
| PROCESS_SCALAR_FIELD_V1(max_bytes_per_row); |
| PROCESS_SCALAR_FIELD_V1(max_coded_width_times_coded_height); |
| if (v1.layers) { |
| if (v1.layers > 1) { |
| LOG(ERROR, "v1.layers > 1"); |
| return fit::error(); |
| } |
| // v2 ImageFormatConstraints doesn't have layers field (at least not yet), on purpose. If it |
| // ever gains a layers field, most likely we won't translate the v1 layers field to any v2 |
| // layers field. |
| } |
| PROCESS_SCALAR_FIELD_V1(coded_width_divisor); |
| PROCESS_SCALAR_FIELD_V1(coded_height_divisor); |
| PROCESS_SCALAR_FIELD_V1(bytes_per_row_divisor); |
| PROCESS_SCALAR_FIELD_V1(start_offset_divisor); |
| PROCESS_SCALAR_FIELD_V1(display_width_divisor); |
| PROCESS_SCALAR_FIELD_V1(display_height_divisor); |
| PROCESS_SCALAR_FIELD_V1(required_min_coded_width); |
| PROCESS_SCALAR_FIELD_V1(required_max_coded_width); |
| PROCESS_SCALAR_FIELD_V1(required_min_coded_height); |
| PROCESS_SCALAR_FIELD_V1(required_max_coded_height); |
| PROCESS_SCALAR_FIELD_V1(required_min_bytes_per_row); |
| PROCESS_SCALAR_FIELD_V1(required_max_bytes_per_row); |
| return fit::ok(std::move(v2b)); |
| } |
| |
| fit::result<llcpp::fuchsia::sysmem2::ImageFormatConstraints::Builder> |
| V2CopyFromV1ImageFormatConstraints(fidl::Allocator* allocator, |
| const fuchsia_sysmem_ImageFormatConstraints& v1) { |
| using CStruct = FidlStruct<fuchsia_sysmem_ImageFormatConstraints, |
| llcpp::fuchsia::sysmem::ImageFormatConstraints>; |
| return V2CopyFromV1ImageFormatConstraints(allocator, *CStruct::BorrowAsLlcpp(&v1)); |
| } |
| |
| fit::result<llcpp::fuchsia::sysmem2::BufferUsage::Builder> V2CopyFromV1BufferUsage( |
| fidl::Allocator* allocator, const llcpp::fuchsia::sysmem::BufferUsage& v1) { |
| ZX_DEBUG_ASSERT(allocator); |
| auto v2b = allocator->make_table_builder<llcpp::fuchsia::sysmem2::BufferUsage>(); |
| using foo = std::remove_reference<decltype((v1.none))>::type; |
| static_assert(std::is_const<foo>::value); |
| PROCESS_SCALAR_FIELD_V1(none); |
| PROCESS_SCALAR_FIELD_V1(cpu); |
| PROCESS_SCALAR_FIELD_V1(vulkan); |
| PROCESS_SCALAR_FIELD_V1(display); |
| PROCESS_SCALAR_FIELD_V1(video); |
| return fit::ok(std::move(v2b)); |
| } |
| |
| fit::result<llcpp::fuchsia::sysmem2::BufferUsage::Builder> V2CopyFromV1BufferUsage( |
| fidl::Allocator* allocator, const fuchsia_sysmem_BufferUsage& v1) { |
| using CStruct = FidlStruct<fuchsia_sysmem_BufferUsage, llcpp::fuchsia::sysmem::BufferUsage>; |
| return V2CopyFromV1BufferUsage(allocator, *CStruct::BorrowAsLlcpp(&v1)); |
| } |
| |
| fit::result<llcpp::fuchsia::sysmem2::BufferMemoryConstraints::Builder> |
| V2CopyFromV1BufferMemoryConstraints(fidl::Allocator* allocator, |
| const llcpp::fuchsia::sysmem::BufferMemoryConstraints& v1) { |
| ZX_DEBUG_ASSERT(allocator); |
| auto v2b = allocator->make_table_builder<llcpp::fuchsia::sysmem2::BufferMemoryConstraints>(); |
| PROCESS_SCALAR_FIELD_V1(min_size_bytes); |
| PROCESS_SCALAR_FIELD_V1(max_size_bytes); |
| PROCESS_SCALAR_FIELD_V1(physically_contiguous_required); |
| PROCESS_SCALAR_FIELD_V1(secure_required); |
| PROCESS_SCALAR_FIELD_V1(ram_domain_supported); |
| PROCESS_SCALAR_FIELD_V1(cpu_domain_supported); |
| PROCESS_SCALAR_FIELD_V1(inaccessible_domain_supported); |
| if (v1.heap_permitted_count) { |
| auto result = |
| V2CopyFromV1HeapPermittedArray(allocator, v1.heap_permitted, v1.heap_permitted_count); |
| OK_OR_RET_ERROR(result); |
| v2b.set_heap_permitted(MakeTracking(allocator, result.take_value())); |
| } |
| return fit::ok(std::move(v2b)); |
| } |
| |
| fit::result<llcpp::fuchsia::sysmem2::BufferMemoryConstraints::Builder> |
| V2CopyFromV1BufferMemoryConstraints(fidl::Allocator* allocator, |
| const fuchsia_sysmem_BufferMemoryConstraints& v1) { |
| using CStruct = FidlStruct<fuchsia_sysmem_BufferMemoryConstraints, |
| llcpp::fuchsia::sysmem::BufferMemoryConstraints>; |
| return V2CopyFromV1BufferMemoryConstraints(allocator, *CStruct::BorrowAsLlcpp(&v1)); |
| } |
| |
| // If !v1 && !aux_buffers_v1, the result will be fit::is_ok(), but result.value().IsEmpty(). |
| fit::result<llcpp::fuchsia::sysmem2::BufferCollectionConstraints::Builder> |
| V2CopyFromV1BufferCollectionConstraints( |
| fidl::Allocator* allocator, const llcpp::fuchsia::sysmem::BufferCollectionConstraints* v1, |
| const llcpp::fuchsia::sysmem::BufferCollectionConstraintsAuxBuffers* aux_buffers_v1) { |
| ZX_DEBUG_ASSERT(allocator); |
| // Should be enforced by the caller. |
| ZX_DEBUG_ASSERT(v1 || !aux_buffers_v1); |
| llcpp::fuchsia::sysmem2::BufferCollectionConstraints::Builder v2b = |
| allocator->make_table_builder<llcpp::fuchsia::sysmem2::BufferCollectionConstraints>(); |
| |
| if (v1) { |
| auto result = V2CopyFromV1BufferCollectionConstraintsMain(allocator, &v2b, *v1); |
| OK_OR_RET_ERROR(result); |
| } |
| |
| if (aux_buffers_v1) { |
| auto result = |
| V2CopyFromV1BufferCollectionConstraintsAuxBuffers(allocator, &v2b, *aux_buffers_v1); |
| OK_OR_RET_ERROR(result); |
| } |
| |
| return fit::ok(std::move(v2b)); |
| } |
| |
| fit::result<llcpp::fuchsia::sysmem2::BufferCollectionConstraints::Builder> |
| V2CopyFromV1BufferCollectionConstraints( |
| fidl::Allocator* allocator, const fuchsia_sysmem_BufferCollectionConstraints* v1, |
| const fuchsia_sysmem_BufferCollectionConstraintsAuxBuffers* aux_buffers_v1) { |
| using CStructMain = FidlStruct<fuchsia_sysmem_BufferCollectionConstraints, |
| llcpp::fuchsia::sysmem::BufferCollectionConstraints>; |
| using CStructAux = FidlStruct<fuchsia_sysmem_BufferCollectionConstraintsAuxBuffers, |
| llcpp::fuchsia::sysmem::BufferCollectionConstraintsAuxBuffers>; |
| return V2CopyFromV1BufferCollectionConstraints(allocator, CStructMain::BorrowAsLlcpp(v1), |
| CStructAux::BorrowAsLlcpp(aux_buffers_v1)); |
| } |
| |
| fit::result<llcpp::fuchsia::sysmem2::ImageFormat::Builder> V2CopyFromV1ImageFormat( |
| fidl::Allocator* allocator, const llcpp::fuchsia::sysmem::ImageFormat_2& v1) { |
| ZX_DEBUG_ASSERT(allocator); |
| llcpp::fuchsia::sysmem2::ImageFormat::Builder v2b = |
| allocator->make_table_builder<llcpp::fuchsia::sysmem2::ImageFormat>(); |
| v2b.set_pixel_format( |
| sysmem::MakeTracking(allocator, V2CopyFromV1PixelFormat(allocator, v1.pixel_format).build())); |
| PROCESS_SCALAR_FIELD_V1(coded_width); |
| PROCESS_SCALAR_FIELD_V1(coded_height); |
| PROCESS_SCALAR_FIELD_V1(bytes_per_row); |
| PROCESS_SCALAR_FIELD_V1(display_width); |
| PROCESS_SCALAR_FIELD_V1(display_height); |
| if (v1.layers > 1) { |
| LOG(ERROR, "v1.layers > 1"); |
| return fit::error(); |
| } |
| v2b.set_color_space( |
| sysmem::MakeTracking(allocator, V2CopyFromV1ColorSpace(allocator, v1.color_space).build())); |
| if (v1.has_pixel_aspect_ratio) { |
| v2b.set_pixel_aspect_ratio_width(sysmem::MakeTracking(allocator, v1.pixel_aspect_ratio_width)); |
| v2b.set_pixel_aspect_ratio_height( |
| sysmem::MakeTracking(allocator, v1.pixel_aspect_ratio_height)); |
| } else { |
| ZX_DEBUG_ASSERT(!v2b.has_pixel_aspect_ratio_width()); |
| ZX_DEBUG_ASSERT(!v2b.has_pixel_aspect_ratio_height()); |
| } |
| return fit::ok(std::move(v2b)); |
| } |
| |
| fit::result<llcpp::fuchsia::sysmem2::ImageFormat::Builder> V2CopyFromV1ImageFormat( |
| fidl::Allocator* allocator, const fuchsia_sysmem_ImageFormat_2& v1) { |
| using CStruct = FidlStruct<fuchsia_sysmem_ImageFormat_2, llcpp::fuchsia::sysmem::ImageFormat_2>; |
| return V2CopyFromV1ImageFormat(allocator, *CStruct::BorrowAsLlcpp(&v1)); |
| } |
| |
| [[nodiscard]] llcpp::fuchsia::sysmem2::BufferMemorySettings::Builder |
| V2CopyFromV1BufferMemorySettings(fidl::Allocator* allocator, |
| const llcpp::fuchsia::sysmem::BufferMemorySettings& v1) { |
| ZX_DEBUG_ASSERT(allocator); |
| llcpp::fuchsia::sysmem2::BufferMemorySettings::Builder v2b = |
| allocator->make_table_builder<llcpp::fuchsia::sysmem2::BufferMemorySettings>(); |
| PROCESS_SCALAR_FIELD_V1(size_bytes); |
| PROCESS_SCALAR_FIELD_V1(is_physically_contiguous); |
| PROCESS_SCALAR_FIELD_V1(is_secure); |
| PROCESS_SCALAR_FIELD_V1(coherency_domain); |
| PROCESS_SCALAR_FIELD_V1(heap); |
| return v2b; |
| } |
| |
| fit::result<llcpp::fuchsia::sysmem2::SingleBufferSettings::Builder> |
| V2CopyFromV1SingleBufferSettings(fidl::Allocator* allocator, |
| const llcpp::fuchsia::sysmem::SingleBufferSettings& v1) { |
| ZX_DEBUG_ASSERT(allocator); |
| llcpp::fuchsia::sysmem2::SingleBufferSettings::Builder v2b = |
| allocator->make_table_builder<llcpp::fuchsia::sysmem2::SingleBufferSettings>(); |
| v2b.set_buffer_settings(sysmem::MakeTracking( |
| allocator, V2CopyFromV1BufferMemorySettings(allocator, v1.buffer_settings))); |
| if (v1.has_image_format_constraints) { |
| auto image_format_constraints_result = |
| V2CopyFromV1ImageFormatConstraints(allocator, v1.image_format_constraints); |
| if (!image_format_constraints_result.is_ok()) { |
| LOG(ERROR, "!image_format_constraints_result.is_ok()"); |
| return fit::error(); |
| } |
| v2b.set_image_format_constraints( |
| sysmem::MakeTracking(allocator, image_format_constraints_result.take_value())); |
| } |
| return fit::ok(std::move(v2b)); |
| } |
| |
| llcpp::fuchsia::sysmem2::VmoBuffer::Builder V2MoveFromV1VmoBuffer( |
| fidl::Allocator* allocator, llcpp::fuchsia::sysmem::VmoBuffer&& to_move_v1) { |
| ZX_DEBUG_ASSERT(allocator); |
| llcpp::fuchsia::sysmem::VmoBuffer v1 = std::move(to_move_v1); |
| llcpp::fuchsia::sysmem2::VmoBuffer::Builder v2b = |
| allocator->make_table_builder<llcpp::fuchsia::sysmem2::VmoBuffer>(); |
| if (v1.vmo) { |
| v2b.set_vmo(sysmem::MakeTracking(allocator, std::move(v1.vmo))); |
| } |
| PROCESS_SCALAR_FIELD_V1(vmo_usable_start); |
| ZX_DEBUG_ASSERT(!v2b.has_aux_vmo()); |
| return v2b; |
| } |
| |
| fit::result<llcpp::fuchsia::sysmem2::BufferCollectionInfo::Builder> |
| V2MoveFromV1BufferCollectionInfo(fidl::Allocator* allocator, |
| llcpp::fuchsia::sysmem::BufferCollectionInfo_2&& to_move_v1) { |
| ZX_DEBUG_ASSERT(allocator); |
| llcpp::fuchsia::sysmem::BufferCollectionInfo_2 v1 = std::move(to_move_v1); |
| llcpp::fuchsia::sysmem2::BufferCollectionInfo::Builder v2b = |
| allocator->make_table_builder<llcpp::fuchsia::sysmem2::BufferCollectionInfo>(); |
| auto settings_result = V2CopyFromV1SingleBufferSettings(allocator, v1.settings); |
| if (!settings_result.is_ok()) { |
| LOG(ERROR, "!settings_result.is_ok()"); |
| return fit::error(); |
| } |
| v2b.set_settings(sysmem::MakeTracking(allocator, settings_result.take_value())); |
| if (v1.buffer_count) { |
| v2b.set_buffers(allocator->make_vec_ptr<llcpp::fuchsia::sysmem2::VmoBuffer>(v1.buffer_count)); |
| for (uint32_t i = 0; i < v1.buffer_count; ++i) { |
| v2b.buffers()[i] = V2MoveFromV1VmoBuffer(allocator, std::move(v1.buffers[i])).build(); |
| } |
| } |
| return fit::ok(std::move(v2b)); |
| } |
| |
| fit::result<std::pair<std::optional<llcpp::fuchsia::sysmem::BufferCollectionConstraints>, |
| std::optional<llcpp::fuchsia::sysmem::BufferCollectionConstraintsAuxBuffers>>> |
| V1CopyFromV2BufferCollectionConstraints( |
| const llcpp::fuchsia::sysmem2::BufferCollectionConstraints& v2) { |
| llcpp::fuchsia::sysmem::BufferCollectionConstraints v1{}; |
| if (v2.IsEmpty()) { |
| return fit::ok( |
| std::pair<std::optional<llcpp::fuchsia::sysmem::BufferCollectionConstraints>, |
| std::optional<llcpp::fuchsia::sysmem::BufferCollectionConstraintsAuxBuffers>>()); |
| } |
| if (v2.has_usage()) { |
| v1.usage = V1CopyFromV2BufferUsage(v2.usage()); |
| } |
| PROCESS_SCALAR_FIELD_V2(min_buffer_count_for_camping); |
| PROCESS_SCALAR_FIELD_V2(min_buffer_count_for_dedicated_slack); |
| PROCESS_SCALAR_FIELD_V2(min_buffer_count_for_shared_slack); |
| PROCESS_SCALAR_FIELD_V2(min_buffer_count); |
| PROCESS_SCALAR_FIELD_V2(max_buffer_count); |
| ZX_DEBUG_ASSERT(!v1.has_buffer_memory_constraints); |
| if (v2.has_buffer_memory_constraints()) { |
| v1.has_buffer_memory_constraints = true; |
| auto buffer_memory_constraints_result = |
| V1CopyFromV2BufferMemoryConstraints(v2.buffer_memory_constraints()); |
| if (!buffer_memory_constraints_result.is_ok()) { |
| LOG(ERROR, "!buffer_memory_constraints_result.is_ok()"); |
| return fit::error(); |
| } |
| v1.buffer_memory_constraints = buffer_memory_constraints_result.take_value(); |
| } |
| ZX_DEBUG_ASSERT(!v1.image_format_constraints_count); |
| if (v2.has_image_format_constraints()) { |
| if (v2.image_format_constraints().count() > |
| llcpp::fuchsia::sysmem::MAX_COUNT_BUFFER_COLLECTION_CONSTRAINTS_IMAGE_FORMAT_CONSTRAINTS) { |
| LOG(ERROR, |
| "v2 image_format_constraints count > v1 " |
| "MAX_COUNT_BUFFER_COLLECTION_CONSTRAINTS_IMAGE_FORMAT_CONSTRAINTS"); |
| return fit::error(); |
| } |
| v1.image_format_constraints_count = v2.image_format_constraints().count(); |
| for (uint32_t i = 0; i < v2.image_format_constraints().count(); ++i) { |
| auto image_format_constraints_result = |
| V1CopyFromV2ImageFormatConstraints(v2.image_format_constraints()[i]); |
| if (!image_format_constraints_result.is_ok()) { |
| LOG(ERROR, "!image_format_constraints_result.is_ok()"); |
| return fit::error(); |
| } |
| v1.image_format_constraints[i] = image_format_constraints_result.take_value(); |
| } |
| } |
| |
| std::optional<llcpp::fuchsia::sysmem::BufferCollectionConstraintsAuxBuffers> v1_aux_buffers; |
| if (v2.has_need_clear_aux_buffers_for_secure() || v2.has_allow_clear_aux_buffers_for_secure()) { |
| llcpp::fuchsia::sysmem::BufferCollectionConstraintsAuxBuffers v1{}; |
| PROCESS_SCALAR_FIELD_V2(need_clear_aux_buffers_for_secure); |
| PROCESS_SCALAR_FIELD_V2(allow_clear_aux_buffers_for_secure); |
| v1_aux_buffers.emplace(v1); |
| } |
| |
| return fit::ok(std::make_pair(std::move(v1), std::move(v1_aux_buffers))); |
| } |
| |
| fit::result<llcpp::fuchsia::sysmem::BufferMemoryConstraints> V1CopyFromV2BufferMemoryConstraints( |
| const llcpp::fuchsia::sysmem2::BufferMemoryConstraints& v2) { |
| llcpp::fuchsia::sysmem::BufferMemoryConstraints v1{}; |
| PROCESS_SCALAR_FIELD_V2(min_size_bytes); |
| PROCESS_SCALAR_FIELD_V2(max_size_bytes); |
| PROCESS_SCALAR_FIELD_V2(physically_contiguous_required); |
| PROCESS_SCALAR_FIELD_V2(secure_required); |
| PROCESS_SCALAR_FIELD_V2(ram_domain_supported); |
| PROCESS_SCALAR_FIELD_V2(cpu_domain_supported); |
| PROCESS_SCALAR_FIELD_V2(inaccessible_domain_supported); |
| ZX_DEBUG_ASSERT(!v1.heap_permitted_count); |
| if (v2.has_heap_permitted()) { |
| if (v2.heap_permitted().count() > |
| llcpp::fuchsia::sysmem::MAX_COUNT_BUFFER_MEMORY_CONSTRAINTS_HEAP_PERMITTED) { |
| LOG(ERROR, "v2 heap_permitted count > v1 MAX_COUNT_BUFFER_MEMORY_CONSTRAINTS_HEAP_PERMITTED"); |
| return fit::error(); |
| } |
| v1.heap_permitted_count = v2.heap_permitted().count(); |
| for (uint32_t i = 0; i < v2.heap_permitted().count(); ++i) { |
| ASSIGN_SCALAR(v1.heap_permitted[i], v2.heap_permitted()[i]); |
| } |
| } |
| return fit::ok(std::move(v1)); |
| } |
| |
| llcpp::fuchsia::sysmem::BufferUsage V1CopyFromV2BufferUsage( |
| const llcpp::fuchsia::sysmem2::BufferUsage& v2) { |
| llcpp::fuchsia::sysmem::BufferUsage v1{}; |
| PROCESS_SCALAR_FIELD_V2(none); |
| PROCESS_SCALAR_FIELD_V2(cpu); |
| PROCESS_SCALAR_FIELD_V2(vulkan); |
| PROCESS_SCALAR_FIELD_V2(display); |
| PROCESS_SCALAR_FIELD_V2(video); |
| return v1; |
| } |
| |
| // v2 must have all fields set. |
| llcpp::fuchsia::sysmem::BufferMemorySettings V1CopyFromV2BufferMemorySettings( |
| const llcpp::fuchsia::sysmem2::BufferMemorySettings& v2) { |
| llcpp::fuchsia::sysmem::BufferMemorySettings v1{}; |
| PROCESS_SCALAR_FIELD_V2(size_bytes); |
| PROCESS_SCALAR_FIELD_V2(is_physically_contiguous); |
| PROCESS_SCALAR_FIELD_V2(is_secure); |
| PROCESS_SCALAR_FIELD_V2(coherency_domain); |
| PROCESS_SCALAR_FIELD_V2(heap); |
| return v1; |
| } |
| |
| llcpp::fuchsia::sysmem::PixelFormat V1CopyFromV2PixelFormat( |
| const llcpp::fuchsia::sysmem2::PixelFormat& v2) { |
| llcpp::fuchsia::sysmem::PixelFormat v1; |
| PROCESS_SCALAR_FIELD_V2(type); |
| v1.has_format_modifier = v2.has_format_modifier_value(); |
| if (v2.has_format_modifier_value()) { |
| v1.format_modifier.value = v2.format_modifier_value(); |
| } |
| return v1; |
| } |
| |
| llcpp::fuchsia::sysmem::ColorSpace V1CopyFromV2ColorSpace( |
| const llcpp::fuchsia::sysmem2::ColorSpace& v2) { |
| llcpp::fuchsia::sysmem::ColorSpace v1{}; |
| PROCESS_SCALAR_FIELD_V2(type); |
| return v1; |
| } |
| |
| fit::result<llcpp::fuchsia::sysmem::ImageFormatConstraints> V1CopyFromV2ImageFormatConstraints( |
| const llcpp::fuchsia::sysmem2::ImageFormatConstraints& v2) { |
| llcpp::fuchsia::sysmem::ImageFormatConstraints v1; |
| v1.pixel_format = V1CopyFromV2PixelFormat(v2.pixel_format()); |
| ZX_DEBUG_ASSERT(!v1.color_spaces_count); |
| if (v2.has_color_spaces()) { |
| if (v2.color_spaces().count() > |
| llcpp::fuchsia::sysmem::MAX_COUNT_IMAGE_FORMAT_CONSTRAINTS_COLOR_SPACES) { |
| LOG(ERROR, |
| "v2.color_spaces().count() > " |
| "llcpp::fuchsia::sysmem::MAX_COUNT_IMAGE_FORMAT_CONSTRAINTS_COLOR_SPACES"); |
| return fit::error(); |
| } |
| v1.color_spaces_count = v2.color_spaces().count(); |
| for (uint32_t i = 0; i < v2.color_spaces().count(); ++i) { |
| v1.color_space[i] = V1CopyFromV2ColorSpace(v2.color_spaces()[i]); |
| } |
| } |
| PROCESS_SCALAR_FIELD_V2(min_coded_width); |
| PROCESS_SCALAR_FIELD_V2(max_coded_width); |
| PROCESS_SCALAR_FIELD_V2(min_coded_height); |
| PROCESS_SCALAR_FIELD_V2(max_coded_height); |
| PROCESS_SCALAR_FIELD_V2(min_bytes_per_row); |
| PROCESS_SCALAR_FIELD_V2(max_bytes_per_row); |
| PROCESS_SCALAR_FIELD_V2(max_coded_width_times_coded_height); |
| v1.layers = 1; |
| PROCESS_SCALAR_FIELD_V2(coded_width_divisor); |
| PROCESS_SCALAR_FIELD_V2(coded_height_divisor); |
| PROCESS_SCALAR_FIELD_V2(bytes_per_row_divisor); |
| PROCESS_SCALAR_FIELD_V2(start_offset_divisor); |
| PROCESS_SCALAR_FIELD_V2(display_width_divisor); |
| PROCESS_SCALAR_FIELD_V2(display_height_divisor); |
| PROCESS_SCALAR_FIELD_V2(required_min_coded_width); |
| PROCESS_SCALAR_FIELD_V2(required_max_coded_width); |
| PROCESS_SCALAR_FIELD_V2(required_min_coded_height); |
| PROCESS_SCALAR_FIELD_V2(required_max_coded_height); |
| PROCESS_SCALAR_FIELD_V2(required_min_bytes_per_row); |
| PROCESS_SCALAR_FIELD_V2(required_max_bytes_per_row); |
| return fit::ok(std::move(v1)); |
| } |
| |
| fit::result<llcpp::fuchsia::sysmem::ImageFormat_2> V1CopyFromV2ImageFormat( |
| llcpp::fuchsia::sysmem2::ImageFormat& v2) { |
| llcpp::fuchsia::sysmem::ImageFormat_2 v1; |
| if (v2.has_pixel_format()) { |
| v1.pixel_format = V1CopyFromV2PixelFormat(v2.pixel_format()); |
| } |
| PROCESS_SCALAR_FIELD_V2(coded_width); |
| PROCESS_SCALAR_FIELD_V2(coded_height); |
| PROCESS_SCALAR_FIELD_V2(bytes_per_row); |
| PROCESS_SCALAR_FIELD_V2(display_width); |
| PROCESS_SCALAR_FIELD_V2(display_height); |
| v1.layers = 1; |
| if (v2.has_color_space()) { |
| v1.color_space = V1CopyFromV2ColorSpace(v2.color_space()); |
| } |
| v1.has_pixel_aspect_ratio = |
| v2.has_pixel_aspect_ratio_width() && v2.has_pixel_aspect_ratio_height() ? true : false; |
| if (v1.has_pixel_aspect_ratio) { |
| v1.pixel_aspect_ratio_width = v2.pixel_aspect_ratio_width(); |
| v1.pixel_aspect_ratio_height = v2.pixel_aspect_ratio_height(); |
| } |
| return fit::ok(std::move(v1)); |
| } |
| |
| fit::result<llcpp::fuchsia::sysmem::SingleBufferSettings> V1CopyFromV2SingleBufferSettings( |
| const llcpp::fuchsia::sysmem2::SingleBufferSettings& v2) { |
| llcpp::fuchsia::sysmem::SingleBufferSettings v1; |
| v1.buffer_settings = V1CopyFromV2BufferMemorySettings(v2.buffer_settings()); |
| v1.has_image_format_constraints = v2.has_image_format_constraints(); |
| if (v2.has_image_format_constraints()) { |
| auto image_format_constraints_result = |
| V1CopyFromV2ImageFormatConstraints(v2.image_format_constraints()); |
| if (!image_format_constraints_result.is_ok()) { |
| LOG(ERROR, "!image_format_constraints_result.is_ok()"); |
| return fit::error(); |
| } |
| v1.image_format_constraints = image_format_constraints_result.take_value(); |
| } |
| return fit::ok(std::move(v1)); |
| } |
| |
| // Intentionally just consumes aux_vmo. The implied extra handle duplications from this behavior go |
| // away when all participants speak V2. For V1 participants that need the aux_vmo, there's a |
| // completely different method and struct for getting that. |
| llcpp::fuchsia::sysmem::VmoBuffer V1MoveFromV2VmoBuffer( |
| llcpp::fuchsia::sysmem2::VmoBuffer&& to_move_v2) { |
| // Always take ownership even on failure. |
| llcpp::fuchsia::sysmem2::VmoBuffer v2 = std::move(to_move_v2); |
| llcpp::fuchsia::sysmem::VmoBuffer v1; |
| if (v2.has_vmo()) { |
| v1.vmo = std::move(v2.vmo()); |
| } |
| PROCESS_SCALAR_FIELD_V2(vmo_usable_start); |
| // ~v2 will ~aux_vmo, intentionally - see function comment above. |
| return v1; |
| } |
| |
| // Intentionally just consumes vmo (but not aux_vmo). The implied extra handle duplications from |
| // this behavior go away when all participants speak V2. |
| llcpp::fuchsia::sysmem::VmoBuffer V1AuxBuffersMoveFromV2VmoBuffer( |
| llcpp::fuchsia::sysmem2::VmoBuffer&& to_move_v2) { |
| // Always take ownership even on failure. |
| llcpp::fuchsia::sysmem2::VmoBuffer v2 = std::move(to_move_v2); |
| llcpp::fuchsia::sysmem::VmoBuffer v1; |
| if (v2.has_aux_vmo()) { |
| v1.vmo = std::move(v2.aux_vmo()); |
| } |
| PROCESS_SCALAR_FIELD_V2(vmo_usable_start); |
| // ~v2 will ~vmo, intentionally - see function comment above. |
| return v1; |
| } |
| |
| fit::result<llcpp::fuchsia::sysmem::BufferCollectionInfo_2> V1MoveFromV2BufferCollectionInfo( |
| llcpp::fuchsia::sysmem2::BufferCollectionInfo&& to_move_v2) { |
| // This move is mainly to make it very clear what's going on here, but also to ensure that we |
| // don't take any dependency on incorrect/stale failure to move out any of the handles in to_move. |
| // |
| // Always take ownership of the incoming handles, even on failure. |
| llcpp::fuchsia::sysmem2::BufferCollectionInfo v2 = std::move(to_move_v2); |
| llcpp::fuchsia::sysmem::BufferCollectionInfo_2 v1; |
| if (v2.has_buffers()) { |
| if (v2.buffers().count() > llcpp::fuchsia::sysmem::MAX_COUNT_BUFFER_COLLECTION_INFO_BUFFERS) { |
| LOG(ERROR, |
| "v2.buffers().count() > " |
| "llcpp::fuchsia::sysmem::MAX_COUNT_BUFFER_COLLECTION_INFO_BUFFERS"); |
| return fit::error(); |
| } |
| v1.buffer_count = v2.buffers().count(); |
| for (uint32_t i = 0; i < v2.buffers().count(); ++i) { |
| v1.buffers[i] = V1MoveFromV2VmoBuffer(std::move(v2.buffers()[i])); |
| } |
| } |
| auto settings_result = V1CopyFromV2SingleBufferSettings(v2.settings()); |
| if (!settings_result.is_ok()) { |
| LOG(ERROR, "!settings_result.is_ok()"); |
| return fit::error(); |
| } |
| v1.settings = settings_result.take_value(); |
| return fit::ok(std::move(v1)); |
| } |
| |
| [[nodiscard]] fit::result<llcpp::fuchsia::sysmem::BufferCollectionInfo_2> |
| V1AuxBuffersMoveFromV2BufferCollectionInfo( |
| llcpp::fuchsia::sysmem2::BufferCollectionInfo&& to_move_v2) { |
| // This move is mainly to make it very clear what's going on here, but also to ensure that we |
| // don't take any dependency on incorrect/stale failure to move out any of the handles in to_move. |
| // |
| // Always take ownership of the incoming handles, even on failure. |
| llcpp::fuchsia::sysmem2::BufferCollectionInfo v2 = std::move(to_move_v2); |
| llcpp::fuchsia::sysmem::BufferCollectionInfo_2 v1; |
| if (v2.has_buffers()) { |
| if (v2.buffers().count() > llcpp::fuchsia::sysmem::MAX_COUNT_BUFFER_COLLECTION_INFO_BUFFERS) { |
| LOG(ERROR, |
| "v2.buffers().count() > " |
| "llcpp::fuchsia::sysmem::MAX_COUNT_BUFFER_COLLECTION_INFO_BUFFERS"); |
| return fit::error(); |
| } |
| v1.buffer_count = v2.buffers().count(); |
| for (uint32_t i = 0; i < v2.buffers().count(); ++i) { |
| v1.buffers[i] = V1AuxBuffersMoveFromV2VmoBuffer(std::move(v2.buffers()[i])); |
| } |
| } |
| auto settings_result = V1CopyFromV2SingleBufferSettings(v2.settings()); |
| if (!settings_result.is_ok()) { |
| LOG(ERROR, "!settings_result.is_ok()"); |
| return fit::error(); |
| } |
| v1.settings = settings_result.take_value(); |
| return fit::ok(std::move(v1)); |
| } |
| |
| llcpp::fuchsia::sysmem2::PixelFormat::Builder V2ClonePixelFormat( |
| fidl::Allocator* allocator, const llcpp::fuchsia::sysmem2::PixelFormat& src) { |
| auto builder = allocator->make_table_builder<llcpp::fuchsia::sysmem2::PixelFormat>(); |
| if (src.has_type()) { |
| builder.set_type(sysmem::MakeTracking(allocator, src.type())); |
| } |
| if (src.has_format_modifier_value()) { |
| builder.set_format_modifier_value(sysmem::MakeTracking(allocator, src.format_modifier_value())); |
| } |
| return builder; |
| } |
| |
| llcpp::fuchsia::sysmem2::ColorSpace::Builder V2CloneColorSpace( |
| fidl::Allocator* allocator, const llcpp::fuchsia::sysmem2::ColorSpace& src) { |
| auto builder = allocator->make_table_builder<llcpp::fuchsia::sysmem2::ColorSpace>(); |
| if (src.has_type()) { |
| builder.set_type(sysmem::MakeTracking(allocator, src.type())); |
| } |
| return builder; |
| } |
| |
| llcpp::fuchsia::sysmem2::BufferMemorySettings::Builder V2CloneBufferMemorySettings( |
| fidl::Allocator* allocator, const llcpp::fuchsia::sysmem2::BufferMemorySettings& src) { |
| auto builder = allocator->make_table_builder<llcpp::fuchsia::sysmem2::BufferMemorySettings>(); |
| if (src.has_size_bytes()) { |
| builder.set_size_bytes(sysmem::MakeTracking(allocator, src.size_bytes())); |
| } |
| if (src.has_is_physically_contiguous()) { |
| builder.set_is_physically_contiguous( |
| sysmem::MakeTracking(allocator, src.is_physically_contiguous())); |
| } |
| if (src.has_is_secure()) { |
| builder.set_is_secure(sysmem::MakeTracking(allocator, src.is_secure())); |
| } |
| if (src.has_coherency_domain()) { |
| builder.set_coherency_domain(sysmem::MakeTracking(allocator, src.coherency_domain())); |
| } |
| if (src.has_heap()) { |
| builder.set_heap(sysmem::MakeTracking(allocator, src.heap())); |
| } |
| return builder; |
| } |
| |
| llcpp::fuchsia::sysmem2::ImageFormatConstraints::Builder V2CloneImageFormatConstraints( |
| fidl::Allocator* allocator, const llcpp::fuchsia::sysmem2::ImageFormatConstraints& src) { |
| auto builder = allocator->make_table_builder<llcpp::fuchsia::sysmem2::ImageFormatConstraints>(); |
| if (src.has_pixel_format()) { |
| builder.set_pixel_format( |
| sysmem::MakeTracking(allocator, V2ClonePixelFormat(allocator, src.pixel_format()).build())); |
| } |
| if (src.has_color_spaces()) { |
| builder.set_color_spaces( |
| allocator->make_vec_ptr<llcpp::fuchsia::sysmem2::ColorSpace>(src.color_spaces().count())); |
| for (uint32_t i = 0; i < src.color_spaces().count(); ++i) { |
| builder.color_spaces()[i] = V2CloneColorSpace(allocator, src.color_spaces()[i]).build(); |
| } |
| } |
| if (src.has_min_coded_width()) { |
| builder.set_min_coded_width(sysmem::MakeTracking(allocator, src.min_coded_width())); |
| } |
| if (src.has_max_coded_width()) { |
| builder.set_max_coded_width(sysmem::MakeTracking(allocator, src.max_coded_width())); |
| } |
| if (src.has_min_coded_height()) { |
| builder.set_min_coded_height(sysmem::MakeTracking(allocator, src.min_coded_height())); |
| } |
| if (src.has_max_coded_height()) { |
| builder.set_max_coded_height(sysmem::MakeTracking(allocator, src.max_coded_height())); |
| } |
| if (src.has_min_bytes_per_row()) { |
| builder.set_min_bytes_per_row(sysmem::MakeTracking(allocator, src.min_bytes_per_row())); |
| } |
| if (src.has_max_bytes_per_row()) { |
| builder.set_max_bytes_per_row(sysmem::MakeTracking(allocator, src.max_bytes_per_row())); |
| } |
| if (src.has_max_coded_width_times_coded_height()) { |
| builder.set_max_coded_width_times_coded_height( |
| sysmem::MakeTracking(allocator, src.max_coded_width_times_coded_height())); |
| } |
| if (src.has_coded_width_divisor()) { |
| builder.set_coded_width_divisor(sysmem::MakeTracking(allocator, src.coded_width_divisor())); |
| } |
| if (src.has_coded_height_divisor()) { |
| builder.set_coded_height_divisor(sysmem::MakeTracking(allocator, src.coded_height_divisor())); |
| } |
| if (src.has_bytes_per_row_divisor()) { |
| builder.set_bytes_per_row_divisor(sysmem::MakeTracking(allocator, src.bytes_per_row_divisor())); |
| } |
| if (src.has_start_offset_divisor()) { |
| builder.set_start_offset_divisor(sysmem::MakeTracking(allocator, src.start_offset_divisor())); |
| } |
| if (src.has_display_width_divisor()) { |
| builder.set_display_width_divisor(sysmem::MakeTracking(allocator, src.display_width_divisor())); |
| } |
| if (src.has_display_height_divisor()) { |
| builder.set_display_height_divisor( |
| sysmem::MakeTracking(allocator, src.display_height_divisor())); |
| } |
| if (src.has_required_min_coded_width()) { |
| builder.set_required_min_coded_width( |
| sysmem::MakeTracking(allocator, src.required_min_coded_width())); |
| } |
| if (src.has_required_max_coded_width()) { |
| builder.set_required_max_coded_width( |
| sysmem::MakeTracking(allocator, src.required_max_coded_width())); |
| } |
| if (src.has_required_min_coded_height()) { |
| builder.set_required_min_coded_height( |
| sysmem::MakeTracking(allocator, src.required_min_coded_height())); |
| } |
| if (src.has_required_max_coded_height()) { |
| builder.set_required_max_coded_height( |
| sysmem::MakeTracking(allocator, src.required_max_coded_height())); |
| } |
| if (src.has_required_min_bytes_per_row()) { |
| builder.set_required_min_bytes_per_row( |
| sysmem::MakeTracking(allocator, src.required_min_bytes_per_row())); |
| } |
| if (src.has_required_max_bytes_per_row()) { |
| builder.set_required_max_bytes_per_row( |
| sysmem::MakeTracking(allocator, src.required_max_bytes_per_row())); |
| } |
| return builder; |
| } |
| |
| llcpp::fuchsia::sysmem2::SingleBufferSettings::Builder V2CloneSingleBufferSettings( |
| fidl::Allocator* allocator, const llcpp::fuchsia::sysmem2::SingleBufferSettings& src) { |
| auto builder = allocator->make_table_builder<llcpp::fuchsia::sysmem2::SingleBufferSettings>(); |
| if (src.has_buffer_settings()) { |
| builder.set_buffer_settings(sysmem::MakeTracking( |
| allocator, V2CloneBufferMemorySettings(allocator, src.buffer_settings()).build())); |
| } |
| if (src.has_image_format_constraints()) { |
| builder.set_image_format_constraints(sysmem::MakeTracking( |
| allocator, |
| V2CloneImageFormatConstraints(allocator, src.image_format_constraints()).build())); |
| } |
| return builder; |
| } |
| |
| llcpp::fuchsia::sysmem2::SingleBufferSettings::Builder V2CloneSingleBufferSettingsBuilder( |
| fidl::Allocator* allocator, const llcpp::fuchsia::sysmem2::SingleBufferSettings::Builder& src) { |
| auto builder = allocator->make_table_builder<llcpp::fuchsia::sysmem2::SingleBufferSettings>(); |
| if (src.has_buffer_settings()) { |
| builder.set_buffer_settings(sysmem::MakeTracking( |
| allocator, V2CloneBufferMemorySettings(allocator, src.buffer_settings()).build())); |
| } |
| if (src.has_image_format_constraints()) { |
| builder.set_image_format_constraints(sysmem::MakeTracking( |
| allocator, |
| V2CloneImageFormatConstraints(allocator, src.image_format_constraints()).build())); |
| } |
| return builder; |
| } |
| |
| fit::result<llcpp::fuchsia::sysmem2::VmoBuffer::Builder, zx_status_t> V2CloneVmoBuffer( |
| fidl::Allocator* allocator, const llcpp::fuchsia::sysmem2::VmoBuffer& src, |
| uint32_t vmo_rights_mask, uint32_t aux_vmo_rights_mask) { |
| auto builder = allocator->make_table_builder<llcpp::fuchsia::sysmem2::VmoBuffer>(); |
| if (src.has_vmo()) { |
| zx_info_handle_basic_t info{}; |
| zx_status_t get_info_status = |
| src.vmo().get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr); |
| if (get_info_status != ZX_OK) { |
| LOG(ERROR, "get_info_status: %d", get_info_status); |
| return fit::error(get_info_status); |
| } |
| zx::vmo clone_vmo; |
| zx_status_t duplicate_status = src.vmo().duplicate(info.rights & vmo_rights_mask, &clone_vmo); |
| if (duplicate_status != ZX_OK) { |
| LOG(ERROR, "duplicate_status: %d", duplicate_status); |
| return fit::error(duplicate_status); |
| } |
| builder.set_vmo(sysmem::MakeTracking(allocator, std::move(clone_vmo))); |
| } |
| if (src.has_vmo_usable_start()) { |
| builder.set_vmo_usable_start(sysmem::MakeTracking(allocator, src.vmo_usable_start())); |
| } |
| if (src.has_aux_vmo()) { |
| zx_info_handle_basic_t info{}; |
| zx_status_t get_info_status = |
| src.aux_vmo().get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr); |
| if (get_info_status != ZX_OK) { |
| LOG(ERROR, "get_info_status: %d", get_info_status); |
| return fit::error(get_info_status); |
| } |
| zx::vmo clone_vmo; |
| zx_status_t duplicate_status = |
| src.aux_vmo().duplicate(info.rights & aux_vmo_rights_mask, &clone_vmo); |
| if (duplicate_status != ZX_OK) { |
| LOG(ERROR, "duplicate_status: %d", duplicate_status); |
| return fit::error(duplicate_status); |
| } |
| builder.set_aux_vmo(sysmem::MakeTracking(allocator, std::move(clone_vmo))); |
| } |
| return fit::ok(std::move(builder)); |
| } |
| |
| fit::result<llcpp::fuchsia::sysmem2::BufferCollectionInfo::Builder, zx_status_t> |
| V2CloneBufferCollectionInfo(fidl::Allocator* allocator, |
| const llcpp::fuchsia::sysmem2::BufferCollectionInfo& src, |
| uint32_t vmo_rights_mask, uint32_t aux_vmo_rights_mask) { |
| auto builder = allocator->make_table_builder<llcpp::fuchsia::sysmem2::BufferCollectionInfo>(); |
| if (src.has_settings()) { |
| builder.set_settings(sysmem::MakeTracking( |
| allocator, V2CloneSingleBufferSettings(allocator, src.settings()).build())); |
| } |
| if (src.has_buffers()) { |
| builder.set_buffers( |
| allocator->make_vec_ptr<llcpp::fuchsia::sysmem2::VmoBuffer>(src.buffers().count())); |
| for (uint32_t i = 0; i < src.buffers().count(); ++i) { |
| auto clone_result = |
| V2CloneVmoBuffer(allocator, src.buffers()[i], vmo_rights_mask, aux_vmo_rights_mask); |
| if (!clone_result.is_ok()) { |
| return clone_result.take_error_result(); |
| } |
| builder.buffers()[i] = clone_result.take_value().build(); |
| } |
| } |
| return fit::ok(std::move(builder)); |
| } |
| |
| llcpp::fuchsia::sysmem2::CoherencyDomainSupport::Builder V2CloneCoherencyDomainSuppoort( |
| fidl::Allocator* allocator, const llcpp::fuchsia::sysmem2::CoherencyDomainSupport& src) { |
| auto builder = allocator->make_table_builder<llcpp::fuchsia::sysmem2::CoherencyDomainSupport>(); |
| if (src.has_cpu_supported()) { |
| builder.set_cpu_supported(sysmem::MakeTracking(allocator, src.cpu_supported())); |
| } |
| if (src.has_ram_supported()) { |
| builder.set_ram_supported(sysmem::MakeTracking(allocator, src.ram_supported())); |
| } |
| if (src.has_inaccessible_supported()) { |
| builder.set_inaccessible_supported( |
| sysmem::MakeTracking(allocator, src.inaccessible_supported())); |
| } |
| return builder; |
| } |
| |
| llcpp::fuchsia::sysmem2::HeapProperties::Builder V2CloneHeapProperties( |
| fidl::Allocator* allocator, const llcpp::fuchsia::sysmem2::HeapProperties& src) { |
| auto builder = allocator->make_table_builder<llcpp::fuchsia::sysmem2::HeapProperties>(); |
| if (src.has_coherency_domain_support()) { |
| builder.set_coherency_domain_support(sysmem::MakeTracking( |
| allocator, |
| V2CloneCoherencyDomainSuppoort(allocator, src.coherency_domain_support()).build())); |
| } |
| if (src.has_need_clear()) { |
| builder.set_need_clear(sysmem::MakeTracking(allocator, src.need_clear())); |
| } |
| return builder; |
| } |
| |
| } // namespace sysmem |