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 
6 
8 
9 namespace impeller::android {
10 
11 static AHardwareBuffer_Format ToAHardwareBufferFormat(
12  HardwareBufferFormat format) {
13  switch (format) {
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;
28  ahb_desc.usage |= (AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER |
29  AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT);
30  }
32  ahb_desc.usage |= AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY;
33  }
35  ahb_desc.usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
36  }
38  ahb_desc.usage |= AHARDWAREBUFFER_USAGE_CPU_READ_RARELY;
39  }
41  ahb_desc.usage |= AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
42  }
44  ahb_desc.usage |= AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;
45  }
47  ahb_desc.usage |= AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
48  }
49  return ahb_desc;
50 }
51 
53  const auto desc = ToAHardwareBufferDesc(*this);
54  return GetProcTable().AHardwareBuffer_isSupported(&desc) != 0u;
55 }
56 
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 
78 
80  return is_valid_;
81 }
82 
83 AHardwareBuffer* HardwareBuffer::GetHandle() const {
84  return buffer_.get();
85 }
86 
88  const ISize& size) {
91  // Zero sized hardware buffers cannot be allocated.
92  desc.size = size.Max(ISize{1u, 1u});
96  return desc;
97 }
98 
100  return descriptor_;
101 }
102 
103 const AHardwareBuffer_Desc& HardwareBuffer::GetAndroidDescriptor() const {
104  return android_descriptor_;
105 }
106 
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 
138  if (!is_valid_ || !GetProcTable().AHardwareBuffer_lock) {
139  return nullptr;
140  }
141  uint64_t usage = 0;
142  switch (type) {
144  usage |= AHARDWAREBUFFER_USAGE_CPU_READ_MASK;
145  break;
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 
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
GLenum type
HardwareBuffer(HardwareBufferDescriptor descriptor)
const HardwareBufferDescriptor & GetDescriptor() const
AHardwareBuffer * GetHandle() const
const AHardwareBuffer_Desc & GetAndroidDescriptor() const
bool Unlock() const
Unlock a mapping previously locked for CPU access.
static std::optional< AHardwareBuffer_Desc > Describe(AHardwareBuffer *buffer)
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 ...
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...
const ProcTable & GetProcTable()
Definition: proc_table.cc:12
static AHardwareBuffer_Desc ToAHardwareBufferDesc(const HardwareBufferDescriptor &desc)
static AHardwareBuffer_Format ToAHardwareBufferFormat(HardwareBufferFormat format)
constexpr TSize Max(const TSize &o) const
Definition: size.h:97
Type height
Definition: size.h:29
Type width
Definition: size.h:28
A descriptor use to specify hardware buffer allocations.
static HardwareBufferDescriptor MakeForSwapchainImage(const ISize &size)
Create a descriptor of the given size that is suitable for use as a swapchain image.
bool IsAllocatable() const
If hardware buffers can be created using this descriptor. Allocatable descriptors may still cause fai...
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
#define VALIDATION_LOG
Definition: validation.h:91