| Flutter Impeller |

hardware_buffer.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "impeller/toolkit/android/hardware_buffer.h"
6
7 #include "impeller/base/validation.h"
8
9 namespace impeller::android {
10
11 static AHardwareBuffer_Format ToAHardwareBufferFormat(
12 HardwareBufferFormat format) {
13 switch (format) {
14 case HardwareBufferFormat::kR8G8B8A8UNormInt:
15 return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
16 }
17 FML_UNREACHABLE();
18 }
19
20 static AHardwareBuffer_Desc ToAHardwareBufferDesc(
21 const HardwareBufferDescriptor& desc) {
22 AHardwareBuffer_Desc ahb_desc = {};
23 ahb_desc.width = desc.size.width;
24 ahb_desc.height = desc.size.height;
25 ahb_desc.format = ToAHardwareBufferFormat(desc.format);
26 ahb_desc.layers = 1u;
27 if (desc.usage & HardwareBufferUsageFlags::kFrameBufferAttachment) {
28 ahb_desc.usage |= (AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER |
29 AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT);
30 }
31 if (desc.usage & HardwareBufferUsageFlags::kCompositorOverlay) {
32 ahb_desc.usage |= AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY;
33 }
34 if (desc.usage & HardwareBufferUsageFlags::kSampledImage) {
35 ahb_desc.usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
36 }
37 if (desc.usage & HardwareBufferUsageFlags::kCPUReadRarely) {
38 ahb_desc.usage |= AHARDWAREBUFFER_USAGE_CPU_READ_RARELY;
39 }
40 if (desc.usage & HardwareBufferUsageFlags::kCPUReadOften) {
41 ahb_desc.usage |= AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
42 }
43 if (desc.usage & HardwareBufferUsageFlags::kCPUWriteRarely) {
44 ahb_desc.usage |= AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;
45 }
46 if (desc.usage & HardwareBufferUsageFlags::kCPUWriteOften) {
47 ahb_desc.usage |= AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
48 }
49 return ahb_desc;
50 }
51
52 bool HardwareBufferDescriptor::IsAllocatable() const {
53 const auto desc = ToAHardwareBufferDesc(*this);
54 return GetProcTable().AHardwareBuffer_isSupported(&desc) != 0u;
55 }
56
57 HardwareBuffer::HardwareBuffer(HardwareBufferDescriptor descriptor)
58 : descriptor_(descriptor),
59 android_descriptor_(ToAHardwareBufferDesc(descriptor_)) {
60 if (!descriptor_.IsAllocatable()) {
61 VALIDATION_LOG << "The hardware buffer descriptor is not allocatable.";
62 return;
63 }
64 const auto& proc_table = GetProcTable();
65
66 AHardwareBuffer* buffer = nullptr;
67 if (auto result =
68 proc_table.AHardwareBuffer_allocate(&android_descriptor_, &buffer);
69 result != 0 || buffer == nullptr) {
70 VALIDATION_LOG << "Could not allocate hardware buffer. Error: " << result;
71 return;
72 }
73 buffer_.reset(buffer);
74 is_valid_ = true;
75 }
76
77 HardwareBuffer::~HardwareBuffer() = default;
78
79 bool HardwareBuffer::IsValid() const {
80 return is_valid_;
81 }
82
83 AHardwareBuffer* HardwareBuffer::GetHandle() const {
84 return buffer_.get();
85 }
86
87 HardwareBufferDescriptor HardwareBufferDescriptor::MakeForSwapchainImage(
88 const ISize& size) {
89 HardwareBufferDescriptor desc;
90 desc.format = HardwareBufferFormat::kR8G8B8A8UNormInt;
91 // Zero sized hardware buffers cannot be allocated.
92 desc.size = size.Max(ISize{1u, 1u});
93 desc.usage = HardwareBufferUsageFlags::kFrameBufferAttachment |
94 HardwareBufferUsageFlags::kCompositorOverlay |
95 HardwareBufferUsageFlags::kSampledImage;
96 return desc;
97 }
98
99 const HardwareBufferDescriptor& HardwareBuffer::GetDescriptor() const {
100 return descriptor_;
101 }
102
103 const AHardwareBuffer_Desc& HardwareBuffer::GetAndroidDescriptor() const {
104 return android_descriptor_;
105 }
106
107 bool HardwareBuffer::IsAvailableOnPlatform() {
108 return GetProcTable().IsValid() && GetProcTable().AHardwareBuffer_isSupported;
109 }
110
111 std::optional<uint64_t> HardwareBuffer::GetSystemUniqueID() const {
112 return GetSystemUniqueID(GetHandle());
113 }
114
115 std::optional<uint64_t> HardwareBuffer::GetSystemUniqueID(
116 AHardwareBuffer* buffer) {
117 if (!GetProcTable().AHardwareBuffer_getId) {
118 return std::nullopt;
119 }
120 uint64_t out_id = 0u;
121 if (GetProcTable().AHardwareBuffer_getId(buffer, &out_id) != 0) {
122 return std::nullopt;
123 }
124 return out_id;
125 }
126
127 std::optional<AHardwareBuffer_Desc> HardwareBuffer::Describe(
128 AHardwareBuffer* buffer) {
129 if (!buffer || !GetProcTable().AHardwareBuffer_describe) {
130 return std::nullopt;
131 }
132 AHardwareBuffer_Desc desc = {};
133 GetProcTable().AHardwareBuffer_describe(buffer, &desc);
134 return desc;
135 }
136
137 void* HardwareBuffer::Lock(CPUAccessType type) const {
138 if (!is_valid_ || !GetProcTable().AHardwareBuffer_lock) {
139 return nullptr;
140 }
141 uint64_t usage = 0;
142 switch (type) {
143 case CPUAccessType::kRead:
144 usage |= AHARDWAREBUFFER_USAGE_CPU_READ_MASK;
145 break;
146 case CPUAccessType::kWrite:
147 usage |= AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK;
148 break;
149 }
150 void* buffer = nullptr;
151 const auto result = GetProcTable().AHardwareBuffer_lock( //
152 buffer_.get(), // buffer
153 usage, // usage
154 -1, // fence
155 nullptr, // rect
156 &buffer // out-addr
157 );
158 return result == 0 ? buffer : nullptr;
159 }
160
161 bool HardwareBuffer::Unlock() const {
162 if (!is_valid_ || !GetProcTable().AHardwareBuffer_unlock) {
163 return false;
164 }
165 const auto result =
166 GetProcTable().AHardwareBuffer_unlock(buffer_.get(), nullptr);
167 return result == 0;
168 }
169
170 } // namespace impeller::android
hardware_buffer.h
impeller::android::HardwareBuffer::CPUAccessType
CPUAccessType
Definition: hardware_buffer.h:135
impeller::android::HardwareBuffer::IsAvailableOnPlatform
static bool IsAvailableOnPlatform()
Definition: hardware_buffer.cc:107
impeller::android::ToAHardwareBufferDesc
static AHardwareBuffer_Desc ToAHardwareBufferDesc(const HardwareBufferDescriptor &desc)
Definition: hardware_buffer.cc:20
impeller::android::HardwareBuffer::CPUAccessType::kRead
@ kRead
impeller::android::HardwareBuffer::GetSystemUniqueID
std::optional< uint64_t > GetSystemUniqueID() const
Get the system wide unique ID of the hardware buffer if possible. This is only available on Android A...
Definition: hardware_buffer.cc:111
impeller::android::HardwareBuffer::Lock
void * Lock(CPUAccessType type) const
Lock the buffer for CPU access. This call may fail if the buffer was not created with one the usages ...
Definition: hardware_buffer.cc:137
impeller::android::HardwareBuffer::GetDescriptor
const HardwareBufferDescriptor & GetDescriptor() const
Definition: hardware_buffer.cc:99
impeller::android::HardwareBufferUsageFlags::kSampledImage
@ kSampledImage
validation.h
impeller::android::HardwareBufferDescriptor::MakeForSwapchainImage
static HardwareBufferDescriptor MakeForSwapchainImage(const ISize &size)
Create a descriptor of the given size that is suitable for use as a swapchain image.
Definition: hardware_buffer.cc:87
impeller::android
Definition: choreographer.cc:9
impeller::TSize
Definition: size.h:19
impeller::android::HardwareBufferUsageFlags::kCPUWriteOften
@ kCPUWriteOften
impeller::android::HardwareBufferFormat
HardwareBufferFormat
Definition: hardware_buffer.h:18
impeller::android::HardwareBuffer::CPUAccessType::kWrite
@ kWrite
impeller::android::HardwareBufferUsageFlags::kCPUReadOften
@ kCPUReadOften
impeller::TSize::Max
constexpr TSize Max(const TSize &o) const
Definition: size.h:81
impeller::android::ProcTable::IsValid
bool IsValid() const
If a valid proc table could be setup. This may fail in case of setup on non-Android platforms.
Definition: proc_table.cc:65
impeller::android::HardwareBuffer::~HardwareBuffer
~HardwareBuffer()
type
GLenum type
Definition: blit_command_gles.cc:126
impeller::android::HardwareBufferFormat::kR8G8B8A8UNormInt
@ kR8G8B8A8UNormInt
impeller::android::ToAHardwareBufferFormat
static AHardwareBuffer_Format ToAHardwareBufferFormat(HardwareBufferFormat format)
Definition: hardware_buffer.cc:11
impeller::android::HardwareBufferDescriptor
A descriptor use to specify hardware buffer allocations.
Definition: hardware_buffer.h:47
impeller::android::HardwareBufferUsageFlags::kFrameBufferAttachment
@ kFrameBufferAttachment
impeller::android::HardwareBuffer::GetHandle
AHardwareBuffer * GetHandle() const
Definition: hardware_buffer.cc:83
impeller::TSize::width
Type width
Definition: size.h:22
impeller::android::HardwareBufferUsageFlags::kCompositorOverlay
@ kCompositorOverlay
impeller::android::HardwareBufferDescriptor::size
ISize size
Definition: hardware_buffer.h:49
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:73
impeller::android::HardwareBufferUsageFlags::kCPUWriteRarely
@ kCPUWriteRarely
impeller::android::HardwareBuffer::Describe
static std::optional< AHardwareBuffer_Desc > Describe(AHardwareBuffer *buffer)
Definition: hardware_buffer.cc:127
impeller::android::HardwareBufferDescriptor::usage
HardwareBufferUsage usage
Definition: hardware_buffer.h:50
impeller::android::HardwareBuffer::HardwareBuffer
HardwareBuffer(HardwareBufferDescriptor descriptor)
Definition: hardware_buffer.cc:57
impeller::android::GetProcTable
const ProcTable & GetProcTable()
Definition: proc_table.cc:12
impeller::android::HardwareBuffer::IsValid
bool IsValid() const
Definition: hardware_buffer.cc:79
impeller::TSize::height
Type height
Definition: size.h:23
impeller::android::HardwareBufferDescriptor::format
HardwareBufferFormat format
Definition: hardware_buffer.h:48
impeller::android::HardwareBuffer::Unlock
bool Unlock() const
Unlock a mapping previously locked for CPU access.
Definition: hardware_buffer.cc:161
impeller::android::HardwareBufferDescriptor::IsAllocatable
bool IsAllocatable() const
If hardware buffers can be created using this descriptor. Allocatable descriptors may still cause fai...
Definition: hardware_buffer.cc:52
impeller::android::HardwareBuffer::GetAndroidDescriptor
const AHardwareBuffer_Desc & GetAndroidDescriptor() const
Definition: hardware_buffer.cc:103
impeller::android::HardwareBufferUsageFlags::kCPUReadRarely
@ kCPUReadRarely