| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef FLUTTER_IMPELLER_TOOLKIT_ANDROID_HARDWARE_BUFFER_H_ |
| #define FLUTTER_IMPELLER_TOOLKIT_ANDROID_HARDWARE_BUFFER_H_ |
| |
| #include <optional> |
| |
| #include "flutter/fml/unique_object.h" |
| #include "impeller/base/mask.h" |
| #include "impeller/geometry/size.h" |
| #include "impeller/toolkit/android/proc_table.h" |
| |
| namespace impeller::android { |
| |
| enum class HardwareBufferFormat { |
| //---------------------------------------------------------------------------- |
| /// This format is guaranteed to be supported on all versions of Android. This |
| /// format can also be converted to an Impeller and Vulkan format. |
| /// |
| /// @see Vulkan Format: VK_FORMAT_R8G8B8A8_UNORM |
| /// @see OpenGL ES Format: GL_RGBA8 |
| /// |
| /// Why have many format when one format do trick? |
| /// |
| kR8G8B8A8UNormInt, |
| }; |
| |
| enum class HardwareBufferUsageFlags { |
| kNone = 0u, |
| kFrameBufferAttachment = 1u << 0u, |
| kCompositorOverlay = 1u << 1u, |
| kSampledImage = 1u << 2u, |
| }; |
| |
| using HardwareBufferUsage = Mask<HardwareBufferUsageFlags>; |
| |
| //------------------------------------------------------------------------------ |
| /// @brief A descriptor use to specify hardware buffer allocations. |
| /// |
| struct HardwareBufferDescriptor { |
| HardwareBufferFormat format = HardwareBufferFormat::kR8G8B8A8UNormInt; |
| ISize size; |
| HardwareBufferUsage usage = HardwareBufferUsageFlags::kNone; |
| |
| //---------------------------------------------------------------------------- |
| /// @brief Create a descriptor of the given size that is suitable for use |
| /// as a swapchain image. |
| /// |
| /// @warning Descriptors of zero size are not allocatable. The next best |
| /// valid size is picked. So make sure to check the actual size of |
| /// the descriptor after this call is made to determine the size |
| /// of the allocated hardware buffer. |
| /// |
| /// @param[in] size The size. See the restrictions about valid sizes above. |
| /// |
| /// @return The hardware buffer descriptor. |
| /// |
| static HardwareBufferDescriptor MakeForSwapchainImage(const ISize& size); |
| |
| //---------------------------------------------------------------------------- |
| /// @brief If hardware buffers can be created using this descriptor. |
| /// Allocatable descriptors may still cause failing allocations in |
| /// case of resource exhaustion. |
| /// |
| /// @return `true` if allocatable (unless resource exhaustion). |
| /// |
| bool IsAllocatable() const; |
| |
| constexpr bool operator==(const HardwareBufferDescriptor& o) const { |
| return format == o.format && size == o.size && usage == o.usage; |
| } |
| |
| constexpr bool operator!=(const HardwareBufferDescriptor& o) const { |
| return !(*this == o); |
| } |
| }; |
| |
| //------------------------------------------------------------------------------ |
| /// @brief A wrapper for AHardwareBuffer |
| /// https://developer.android.com/ndk/reference/group/a-hardware-buffer |
| /// |
| /// This wrapper creates and owns a handle to a managed hardware |
| /// buffer. That is, there is no ability to take a reference to an |
| /// externally created hardware buffer. |
| /// |
| /// This wrapper is only available on Android API 29 and above. |
| /// |
| class HardwareBuffer { |
| public: |
| static bool IsAvailableOnPlatform(); |
| |
| explicit HardwareBuffer(HardwareBufferDescriptor descriptor); |
| |
| ~HardwareBuffer(); |
| |
| HardwareBuffer(const HardwareBuffer&) = delete; |
| |
| HardwareBuffer& operator=(const HardwareBuffer&) = delete; |
| |
| bool IsValid() const; |
| |
| AHardwareBuffer* GetHandle() const; |
| |
| const HardwareBufferDescriptor& GetDescriptor() const; |
| |
| const AHardwareBuffer_Desc& GetAndroidDescriptor() const; |
| |
| static std::optional<AHardwareBuffer_Desc> Describe(AHardwareBuffer* buffer); |
| |
| //---------------------------------------------------------------------------- |
| /// @brief Get the system wide unique ID of the hardware buffer if |
| /// possible. This is only available on Android API 31 and above. |
| /// Within the process, the handle are unique. |
| /// |
| /// @return The system unique id if one can be obtained. |
| /// |
| std::optional<uint64_t> GetSystemUniqueID() const; |
| |
| //---------------------------------------------------------------------------- |
| /// @brief Get the system wide unique ID of the hardware buffer if |
| /// possible. This is only available on Android API 31 and above. |
| /// Within the process, the handle are unique. |
| /// |
| /// @return The system unique id if one can be obtained. |
| /// |
| static std::optional<uint64_t> GetSystemUniqueID(AHardwareBuffer* buffer); |
| |
| private: |
| struct UniqueAHardwareBufferTraits { |
| static AHardwareBuffer* InvalidValue() { return nullptr; } |
| |
| static bool IsValid(AHardwareBuffer* value) { |
| return value != InvalidValue(); |
| } |
| |
| static void Free(AHardwareBuffer* value) { |
| GetProcTable().AHardwareBuffer_release(value); |
| } |
| }; |
| |
| const HardwareBufferDescriptor descriptor_; |
| const AHardwareBuffer_Desc android_descriptor_; |
| fml::UniqueObject<AHardwareBuffer*, UniqueAHardwareBufferTraits> buffer_; |
| bool is_valid_ = false; |
| }; |
| |
| } // namespace impeller::android |
| |
| namespace impeller { |
| |
| IMPELLER_ENUM_IS_MASK(android::HardwareBufferUsageFlags); |
| |
| } // namespace impeller |
| |
| #endif // FLUTTER_IMPELLER_TOOLKIT_ANDROID_HARDWARE_BUFFER_H_ |