| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 1 | // Copyright (C) 2023 The Android Open Source Project | 
|  | 2 | // | 
|  | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 4 | // you may not use this file except in compliance with the License. | 
|  | 5 | // You may obtain a copy of the License at | 
|  | 6 | // | 
|  | 7 | //     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 8 | // | 
|  | 9 | // Unless required by applicable law or agreed to in writing, software | 
|  | 10 | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 12 | // See the License for the specific language governing permissions and | 
|  | 13 | // limitations under the License. | 
|  | 14 |  | 
|  | 15 | //! Pleasant Rust bindings for libnativewindow, including AHardwareBuffer | 
|  | 16 |  | 
|  | 17 | extern crate nativewindow_bindgen as ffi; | 
|  | 18 |  | 
| Andrew Walbran | 9487efd | 2024-08-20 18:37:59 +0100 | [diff] [blame] | 19 | mod handle; | 
| Jiyong Park | 8032bff | 2024-04-01 16:17:15 +0900 | [diff] [blame] | 20 | mod surface; | 
| Andrew Walbran | 9487efd | 2024-08-20 18:37:59 +0100 | [diff] [blame] | 21 |  | 
| Andrew Walbran | 43bddb6 | 2023-09-01 16:43:09 +0100 | [diff] [blame] | 22 | pub use ffi::{AHardwareBuffer_Format, AHardwareBuffer_UsageFlags}; | 
| Andrew Walbran | 3026298 | 2024-09-27 16:38:42 +0100 | [diff] [blame] | 23 | pub use handle::NativeHandle; | 
|  | 24 | pub use surface::{buffer::Buffer, Surface}; | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 25 |  | 
| Andrew Walbran | 43bddb6 | 2023-09-01 16:43:09 +0100 | [diff] [blame] | 26 | use binder::{ | 
| Andrew Walbran | e9573af | 2024-01-11 16:34:16 +0000 | [diff] [blame] | 27 | binder_impl::{BorrowedParcel, UnstructuredParcelable}, | 
|  | 28 | impl_deserialize_for_unstructured_parcelable, impl_serialize_for_unstructured_parcelable, | 
| Andrew Walbran | 43bddb6 | 2023-09-01 16:43:09 +0100 | [diff] [blame] | 29 | unstable_api::{status_result, AsNative}, | 
|  | 30 | StatusCode, | 
|  | 31 | }; | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 32 | use ffi::{ | 
|  | 33 | AHardwareBuffer, AHardwareBuffer_Desc, AHardwareBuffer_readFromParcel, | 
|  | 34 | AHardwareBuffer_writeToParcel, | 
|  | 35 | }; | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 36 | use std::fmt::{self, Debug, Formatter}; | 
|  | 37 | use std::mem::ManuallyDrop; | 
| Andrew Walbran | 43bddb6 | 2023-09-01 16:43:09 +0100 | [diff] [blame] | 38 | use std::ptr::{self, null_mut, NonNull}; | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 39 |  | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 40 | /// Wrapper around a C `AHardwareBuffer_Desc`. | 
|  | 41 | #[derive(Clone, Debug, PartialEq, Eq)] | 
|  | 42 | pub struct HardwareBufferDescription(AHardwareBuffer_Desc); | 
|  | 43 |  | 
|  | 44 | impl HardwareBufferDescription { | 
|  | 45 | /// Creates a new `HardwareBufferDescription` with the given parameters. | 
|  | 46 | pub fn new( | 
|  | 47 | width: u32, | 
|  | 48 | height: u32, | 
|  | 49 | layers: u32, | 
|  | 50 | format: AHardwareBuffer_Format::Type, | 
|  | 51 | usage: AHardwareBuffer_UsageFlags, | 
|  | 52 | stride: u32, | 
|  | 53 | ) -> Self { | 
|  | 54 | Self(AHardwareBuffer_Desc { | 
|  | 55 | width, | 
|  | 56 | height, | 
|  | 57 | layers, | 
|  | 58 | format, | 
|  | 59 | usage: usage.0, | 
|  | 60 | stride, | 
|  | 61 | rfu0: 0, | 
|  | 62 | rfu1: 0, | 
|  | 63 | }) | 
|  | 64 | } | 
|  | 65 |  | 
|  | 66 | /// Returns the width from the buffer description. | 
|  | 67 | pub fn width(&self) -> u32 { | 
|  | 68 | self.0.width | 
|  | 69 | } | 
|  | 70 |  | 
|  | 71 | /// Returns the height from the buffer description. | 
|  | 72 | pub fn height(&self) -> u32 { | 
|  | 73 | self.0.height | 
|  | 74 | } | 
|  | 75 |  | 
|  | 76 | /// Returns the number from layers from the buffer description. | 
|  | 77 | pub fn layers(&self) -> u32 { | 
|  | 78 | self.0.layers | 
|  | 79 | } | 
|  | 80 |  | 
|  | 81 | /// Returns the format from the buffer description. | 
|  | 82 | pub fn format(&self) -> AHardwareBuffer_Format::Type { | 
|  | 83 | self.0.format | 
|  | 84 | } | 
|  | 85 |  | 
|  | 86 | /// Returns the usage bitvector from the buffer description. | 
|  | 87 | pub fn usage(&self) -> AHardwareBuffer_UsageFlags { | 
|  | 88 | AHardwareBuffer_UsageFlags(self.0.usage) | 
|  | 89 | } | 
|  | 90 |  | 
|  | 91 | /// Returns the stride from the buffer description. | 
|  | 92 | pub fn stride(&self) -> u32 { | 
|  | 93 | self.0.stride | 
|  | 94 | } | 
|  | 95 | } | 
|  | 96 |  | 
|  | 97 | impl Default for HardwareBufferDescription { | 
|  | 98 | fn default() -> Self { | 
|  | 99 | Self(AHardwareBuffer_Desc { | 
|  | 100 | width: 0, | 
|  | 101 | height: 0, | 
|  | 102 | layers: 0, | 
|  | 103 | format: 0, | 
|  | 104 | usage: 0, | 
|  | 105 | stride: 0, | 
|  | 106 | rfu0: 0, | 
|  | 107 | rfu1: 0, | 
|  | 108 | }) | 
|  | 109 | } | 
|  | 110 | } | 
|  | 111 |  | 
| Andrew Walbran | 43bddb6 | 2023-09-01 16:43:09 +0100 | [diff] [blame] | 112 | /// Wrapper around an opaque C `AHardwareBuffer`. | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 113 | #[derive(PartialEq, Eq)] | 
|  | 114 | pub struct HardwareBuffer(NonNull<AHardwareBuffer>); | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 115 |  | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 116 | impl HardwareBuffer { | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 117 | /// Test whether the given format and usage flag combination is allocatable.  If this function | 
|  | 118 | /// returns true, it means that a buffer with the given description can be allocated on this | 
|  | 119 | /// implementation, unless resource exhaustion occurs. If this function returns false, it means | 
|  | 120 | /// that the allocation of the given description will never succeed. | 
|  | 121 | /// | 
|  | 122 | /// Available since API 29 | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 123 | pub fn is_supported(buffer_description: &HardwareBufferDescription) -> bool { | 
|  | 124 | // SAFETY: The pointer comes from a reference so must be valid. | 
|  | 125 | let status = unsafe { ffi::AHardwareBuffer_isSupported(&buffer_description.0) }; | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 126 |  | 
|  | 127 | status == 1 | 
|  | 128 | } | 
|  | 129 |  | 
|  | 130 | /// Allocates a buffer that matches the passed AHardwareBuffer_Desc. If allocation succeeds, the | 
|  | 131 | /// buffer can be used according to the usage flags specified in its description. If a buffer is | 
|  | 132 | /// used in ways not compatible with its usage flags, the results are undefined and may include | 
|  | 133 | /// program termination. | 
|  | 134 | /// | 
|  | 135 | /// Available since API level 26. | 
| Jim Shargo | e4680d7 | 2023-08-07 16:46:45 +0000 | [diff] [blame] | 136 | #[inline] | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 137 | pub fn new(buffer_description: &HardwareBufferDescription) -> Option<Self> { | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 138 | let mut ptr = ptr::null_mut(); | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 139 | // SAFETY: The returned pointer is valid until we drop/deallocate it. The function may fail | 
|  | 140 | // and return a status, but we check it later. | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 141 | let status = unsafe { ffi::AHardwareBuffer_allocate(&buffer_description.0, &mut ptr) }; | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 142 |  | 
|  | 143 | if status == 0 { | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 144 | Some(Self(NonNull::new(ptr).expect("Allocated AHardwareBuffer was null"))) | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 145 | } else { | 
|  | 146 | None | 
|  | 147 | } | 
|  | 148 | } | 
|  | 149 |  | 
| Andrew Walbran | a73d62c | 2024-08-20 17:20:56 +0100 | [diff] [blame] | 150 | /// Creates a `HardwareBuffer` from a native handle. | 
|  | 151 | /// | 
|  | 152 | /// The native handle is cloned, so this doesn't take ownership of the original handle passed | 
|  | 153 | /// in. | 
|  | 154 | pub fn create_from_handle( | 
|  | 155 | handle: &NativeHandle, | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 156 | buffer_description: &HardwareBufferDescription, | 
| Andrew Walbran | a73d62c | 2024-08-20 17:20:56 +0100 | [diff] [blame] | 157 | ) -> Result<Self, StatusCode> { | 
|  | 158 | let mut buffer = ptr::null_mut(); | 
|  | 159 | // SAFETY: The caller guarantees that `handle` is valid, and the buffer pointer is valid | 
|  | 160 | // because it comes from a reference. The method we pass means that | 
|  | 161 | // `AHardwareBuffer_createFromHandle` will clone the handle rather than taking ownership of | 
|  | 162 | // it. | 
|  | 163 | let status = unsafe { | 
|  | 164 | ffi::AHardwareBuffer_createFromHandle( | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 165 | &buffer_description.0, | 
| Andrew Walbran | a73d62c | 2024-08-20 17:20:56 +0100 | [diff] [blame] | 166 | handle.as_raw().as_ptr(), | 
|  | 167 | ffi::CreateFromHandleMethod_AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE | 
|  | 168 | .try_into() | 
|  | 169 | .unwrap(), | 
|  | 170 | &mut buffer, | 
|  | 171 | ) | 
|  | 172 | }; | 
|  | 173 | status_result(status)?; | 
|  | 174 | Ok(Self(NonNull::new(buffer).expect("Allocated AHardwareBuffer was null"))) | 
|  | 175 | } | 
|  | 176 |  | 
|  | 177 | /// Returns a clone of the native handle of the buffer. | 
|  | 178 | /// | 
|  | 179 | /// Returns `None` if the operation fails for any reason. | 
|  | 180 | pub fn cloned_native_handle(&self) -> Option<NativeHandle> { | 
|  | 181 | // SAFETY: The AHardwareBuffer pointer we pass is guaranteed to be non-null and valid | 
|  | 182 | // because it must have been allocated by `AHardwareBuffer_allocate`, | 
|  | 183 | // `AHardwareBuffer_readFromParcel` or the caller of `from_raw` and we have not yet | 
|  | 184 | // released it. | 
|  | 185 | let native_handle = unsafe { ffi::AHardwareBuffer_getNativeHandle(self.0.as_ptr()) }; | 
|  | 186 | NonNull::new(native_handle.cast_mut()).and_then(|native_handle| { | 
|  | 187 | // SAFETY: `AHardwareBuffer_getNativeHandle` should have returned a valid pointer which | 
|  | 188 | // is valid at least as long as the buffer is, and `clone_from_raw` clones it rather | 
|  | 189 | // than taking ownership of it so the original `native_handle` isn't stored. | 
|  | 190 | unsafe { NativeHandle::clone_from_raw(native_handle) } | 
|  | 191 | }) | 
|  | 192 | } | 
|  | 193 |  | 
| Andrew Walbran | a0b3a9d | 2024-01-12 16:43:12 +0000 | [diff] [blame] | 194 | /// Adopts the given raw pointer and wraps it in a Rust HardwareBuffer. | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 195 | /// | 
|  | 196 | /// # Safety | 
|  | 197 | /// | 
| Andrew Walbran | a0b3a9d | 2024-01-12 16:43:12 +0000 | [diff] [blame] | 198 | /// This function takes ownership of the pointer and does NOT increment the refcount on the | 
|  | 199 | /// buffer. If the caller uses the pointer after the created object is dropped it will cause | 
|  | 200 | /// undefined behaviour. If the caller wants to continue using the pointer after calling this | 
|  | 201 | /// then use [`clone_from_raw`](Self::clone_from_raw) instead. | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 202 | pub unsafe fn from_raw(buffer_ptr: NonNull<AHardwareBuffer>) -> Self { | 
|  | 203 | Self(buffer_ptr) | 
|  | 204 | } | 
|  | 205 |  | 
| Andrew Walbran | 7e947d3 | 2024-10-23 17:03:59 +0100 | [diff] [blame] | 206 | /// Creates a new Rust HardwareBuffer to wrap the given `AHardwareBuffer` without taking | 
|  | 207 | /// ownership of it. | 
| Andrew Walbran | a0b3a9d | 2024-01-12 16:43:12 +0000 | [diff] [blame] | 208 | /// | 
|  | 209 | /// Unlike [`from_raw`](Self::from_raw) this method will increment the refcount on the buffer. | 
|  | 210 | /// This means that the caller can continue to use the raw buffer it passed in, and must call | 
|  | 211 | /// [`AHardwareBuffer_release`](ffi::AHardwareBuffer_release) when it is finished with it to | 
|  | 212 | /// avoid a memory leak. | 
|  | 213 | /// | 
|  | 214 | /// # Safety | 
|  | 215 | /// | 
|  | 216 | /// The buffer pointer must point to a valid `AHardwareBuffer`. | 
|  | 217 | pub unsafe fn clone_from_raw(buffer: NonNull<AHardwareBuffer>) -> Self { | 
|  | 218 | // SAFETY: The caller guarantees that the AHardwareBuffer pointer is valid. | 
|  | 219 | unsafe { ffi::AHardwareBuffer_acquire(buffer.as_ptr()) }; | 
|  | 220 | Self(buffer) | 
|  | 221 | } | 
|  | 222 |  | 
| Andrew Walbran | 7e947d3 | 2024-10-23 17:03:59 +0100 | [diff] [blame] | 223 | /// Returns the internal `AHardwareBuffer` pointer. | 
|  | 224 | /// | 
|  | 225 | /// This is only valid as long as this `HardwareBuffer` exists, so shouldn't be stored. It can | 
|  | 226 | /// be used to provide a pointer for a C/C++ API over FFI. | 
| Ren-Pei Zeng | 8237ba6 | 2024-10-22 15:20:18 +0000 | [diff] [blame] | 227 | pub fn as_raw(&self) -> NonNull<AHardwareBuffer> { | 
|  | 228 | self.0 | 
|  | 229 | } | 
|  | 230 |  | 
| Andrew Walbran | 7e947d3 | 2024-10-23 17:03:59 +0100 | [diff] [blame] | 231 | /// Gets the internal `AHardwareBuffer` pointer without decrementing the refcount. This can | 
|  | 232 | /// be used for a C/C++ API which takes ownership of the pointer. | 
|  | 233 | /// | 
|  | 234 | /// The caller is responsible for releasing the `AHardwareBuffer` pointer by calling | 
|  | 235 | /// `AHardwareBuffer_release` when it is finished with it, or may convert it back to a Rust | 
|  | 236 | /// `HardwareBuffer` by calling [`HardwareBuffer::from_raw`]. | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 237 | pub fn into_raw(self) -> NonNull<AHardwareBuffer> { | 
|  | 238 | let buffer = ManuallyDrop::new(self); | 
|  | 239 | buffer.0 | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 240 | } | 
|  | 241 |  | 
|  | 242 | /// Get the system wide unique id for an AHardwareBuffer. This function may panic in extreme | 
|  | 243 | /// and undocumented circumstances. | 
|  | 244 | /// | 
|  | 245 | /// Available since API level 31. | 
|  | 246 | pub fn id(&self) -> u64 { | 
|  | 247 | let mut out_id = 0; | 
| Andrew Walbran | 43bddb6 | 2023-09-01 16:43:09 +0100 | [diff] [blame] | 248 | // SAFETY: The AHardwareBuffer pointer we pass is guaranteed to be non-null and valid | 
|  | 249 | // because it must have been allocated by `AHardwareBuffer_allocate`, | 
|  | 250 | // `AHardwareBuffer_readFromParcel` or the caller of `from_raw` and we have not yet | 
|  | 251 | // released it. The id pointer must be valid because it comes from a reference. | 
|  | 252 | let status = unsafe { ffi::AHardwareBuffer_getId(self.0.as_ptr(), &mut out_id) }; | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 253 | assert_eq!(status, 0, "id() failed for AHardwareBuffer with error code: {status}"); | 
|  | 254 |  | 
|  | 255 | out_id | 
|  | 256 | } | 
|  | 257 |  | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 258 | /// Returns the description of this buffer. | 
|  | 259 | pub fn description(&self) -> HardwareBufferDescription { | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 260 | let mut buffer_desc = ffi::AHardwareBuffer_Desc { | 
|  | 261 | width: 0, | 
|  | 262 | height: 0, | 
|  | 263 | layers: 0, | 
|  | 264 | format: 0, | 
|  | 265 | usage: 0, | 
|  | 266 | stride: 0, | 
|  | 267 | rfu0: 0, | 
|  | 268 | rfu1: 0, | 
|  | 269 | }; | 
|  | 270 | // SAFETY: neither the buffer nor AHardwareBuffer_Desc pointers will be null. | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 271 | unsafe { ffi::AHardwareBuffer_describe(self.0.as_ref(), &mut buffer_desc) }; | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 272 | HardwareBufferDescription(buffer_desc) | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 273 | } | 
|  | 274 | } | 
|  | 275 |  | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 276 | impl Drop for HardwareBuffer { | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 277 | fn drop(&mut self) { | 
| Andrew Walbran | 43bddb6 | 2023-09-01 16:43:09 +0100 | [diff] [blame] | 278 | // SAFETY: The AHardwareBuffer pointer we pass is guaranteed to be non-null and valid | 
|  | 279 | // because it must have been allocated by `AHardwareBuffer_allocate`, | 
|  | 280 | // `AHardwareBuffer_readFromParcel` or the caller of `from_raw` and we have not yet | 
|  | 281 | // released it. | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 282 | unsafe { ffi::AHardwareBuffer_release(self.0.as_ptr()) } | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 283 | } | 
|  | 284 | } | 
|  | 285 |  | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 286 | impl Debug for HardwareBuffer { | 
| Andrew Walbran | 8ee0ef1 | 2024-01-12 15:56:14 +0000 | [diff] [blame] | 287 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 288 | f.debug_struct("HardwareBuffer").field("id", &self.id()).finish() | 
|  | 289 | } | 
|  | 290 | } | 
|  | 291 |  | 
|  | 292 | impl Clone for HardwareBuffer { | 
|  | 293 | fn clone(&self) -> Self { | 
|  | 294 | // SAFETY: ptr is guaranteed to be non-null and the acquire can not fail. | 
|  | 295 | unsafe { ffi::AHardwareBuffer_acquire(self.0.as_ptr()) }; | 
|  | 296 | Self(self.0) | 
|  | 297 | } | 
|  | 298 | } | 
|  | 299 |  | 
| Andrew Walbran | e9573af | 2024-01-11 16:34:16 +0000 | [diff] [blame] | 300 | impl UnstructuredParcelable for HardwareBuffer { | 
|  | 301 | fn write_to_parcel(&self, parcel: &mut BorrowedParcel) -> Result<(), StatusCode> { | 
|  | 302 | let status = | 
|  | 303 | // SAFETY: The AHardwareBuffer pointer we pass is guaranteed to be non-null and valid | 
|  | 304 | // because it must have been allocated by `AHardwareBuffer_allocate`, | 
|  | 305 | // `AHardwareBuffer_readFromParcel` or the caller of `from_raw` and we have not yet | 
|  | 306 | // released it. | 
|  | 307 | unsafe { AHardwareBuffer_writeToParcel(self.0.as_ptr(), parcel.as_native_mut()) }; | 
|  | 308 | status_result(status) | 
|  | 309 | } | 
|  | 310 |  | 
|  | 311 | fn from_parcel(parcel: &BorrowedParcel) -> Result<Self, StatusCode> { | 
|  | 312 | let mut buffer = null_mut(); | 
|  | 313 |  | 
|  | 314 | let status = | 
|  | 315 | // SAFETY: Both pointers must be valid because they are obtained from references. | 
|  | 316 | // `AHardwareBuffer_readFromParcel` doesn't store them or do anything else special | 
|  | 317 | // with them. If it returns success then it will have allocated a new | 
|  | 318 | // `AHardwareBuffer` and incremented the reference count, so we can use it until we | 
|  | 319 | // release it. | 
|  | 320 | unsafe { AHardwareBuffer_readFromParcel(parcel.as_native(), &mut buffer) }; | 
|  | 321 |  | 
|  | 322 | status_result(status)?; | 
|  | 323 |  | 
|  | 324 | Ok(Self( | 
|  | 325 | NonNull::new(buffer).expect( | 
|  | 326 | "AHardwareBuffer_readFromParcel returned success but didn't allocate buffer", | 
|  | 327 | ), | 
|  | 328 | )) | 
| Andrew Walbran | 43bddb6 | 2023-09-01 16:43:09 +0100 | [diff] [blame] | 329 | } | 
|  | 330 | } | 
|  | 331 |  | 
| Andrew Walbran | e9573af | 2024-01-11 16:34:16 +0000 | [diff] [blame] | 332 | impl_deserialize_for_unstructured_parcelable!(HardwareBuffer); | 
|  | 333 | impl_serialize_for_unstructured_parcelable!(HardwareBuffer); | 
| Andrew Walbran | 43bddb6 | 2023-09-01 16:43:09 +0100 | [diff] [blame] | 334 |  | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 335 | // SAFETY: The underlying *AHardwareBuffers can be moved between threads. | 
|  | 336 | unsafe impl Send for HardwareBuffer {} | 
|  | 337 |  | 
|  | 338 | // SAFETY: The underlying *AHardwareBuffers can be used from multiple threads. | 
|  | 339 | // | 
|  | 340 | // AHardwareBuffers are backed by C++ GraphicBuffers, which are mostly immutable. The only cases | 
|  | 341 | // where they are not immutable are: | 
|  | 342 | // | 
|  | 343 | //   - reallocation (which is never actually done across the codebase and requires special | 
|  | 344 | //     privileges/platform code access to do) | 
|  | 345 | //   - "locking" for reading/writing (which is explicitly allowed to be done across multiple threads | 
|  | 346 | //     according to the docs on the underlying gralloc calls) | 
|  | 347 | unsafe impl Sync for HardwareBuffer {} | 
|  | 348 |  | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 349 | #[cfg(test)] | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 350 | mod test { | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 351 | use super::*; | 
|  | 352 |  | 
|  | 353 | #[test] | 
|  | 354 | fn create_valid_buffer_returns_ok() { | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 355 | let buffer = HardwareBuffer::new(&HardwareBufferDescription::new( | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 356 | 512, | 
|  | 357 | 512, | 
|  | 358 | 1, | 
|  | 359 | AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, | 
|  | 360 | AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 361 | 0, | 
|  | 362 | )); | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 363 | assert!(buffer.is_some()); | 
|  | 364 | } | 
|  | 365 |  | 
|  | 366 | #[test] | 
|  | 367 | fn create_invalid_buffer_returns_err() { | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 368 | let buffer = HardwareBuffer::new(&HardwareBufferDescription::new( | 
|  | 369 | 512, | 
|  | 370 | 512, | 
|  | 371 | 1, | 
|  | 372 | 0, | 
|  | 373 | AHardwareBuffer_UsageFlags(0), | 
|  | 374 | 0, | 
|  | 375 | )); | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 376 | assert!(buffer.is_none()); | 
|  | 377 | } | 
|  | 378 |  | 
|  | 379 | #[test] | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 380 | fn from_raw_allows_getters() { | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 381 | let buffer_desc = ffi::AHardwareBuffer_Desc { | 
|  | 382 | width: 1024, | 
|  | 383 | height: 512, | 
|  | 384 | layers: 1, | 
|  | 385 | format: AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, | 
|  | 386 | usage: AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN.0, | 
|  | 387 | stride: 0, | 
|  | 388 | rfu0: 0, | 
|  | 389 | rfu1: 0, | 
|  | 390 | }; | 
|  | 391 | let mut raw_buffer_ptr = ptr::null_mut(); | 
|  | 392 |  | 
| Andrew Walbran | 03350bc | 2023-08-03 16:02:51 +0000 | [diff] [blame] | 393 | // SAFETY: The pointers are valid because they come from references, and | 
|  | 394 | // `AHardwareBuffer_allocate` doesn't retain them after it returns. | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 395 | let status = unsafe { ffi::AHardwareBuffer_allocate(&buffer_desc, &mut raw_buffer_ptr) }; | 
|  | 396 | assert_eq!(status, 0); | 
|  | 397 |  | 
| Andrew Walbran | 03350bc | 2023-08-03 16:02:51 +0000 | [diff] [blame] | 398 | // SAFETY: The pointer must be valid because it was just allocated successfully, and we | 
|  | 399 | // don't use it after calling this. | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 400 | let buffer = unsafe { HardwareBuffer::from_raw(NonNull::new(raw_buffer_ptr).unwrap()) }; | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 401 | assert_eq!(buffer.description().width(), 1024); | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 402 | } | 
|  | 403 |  | 
|  | 404 | #[test] | 
|  | 405 | fn basic_getters() { | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 406 | let buffer = HardwareBuffer::new(&HardwareBufferDescription::new( | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 407 | 1024, | 
|  | 408 | 512, | 
|  | 409 | 1, | 
|  | 410 | AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, | 
|  | 411 | AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 412 | 0, | 
|  | 413 | )) | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 414 | .expect("Buffer with some basic parameters was not created successfully"); | 
|  | 415 |  | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 416 | let description = buffer.description(); | 
|  | 417 | assert_eq!(description.width(), 1024); | 
|  | 418 | assert_eq!(description.height(), 512); | 
|  | 419 | assert_eq!(description.layers(), 1); | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 420 | assert_eq!( | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 421 | description.format(), | 
|  | 422 | AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM | 
|  | 423 | ); | 
|  | 424 | assert_eq!( | 
|  | 425 | description.usage(), | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 426 | AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | 
|  | 427 | ); | 
|  | 428 | } | 
|  | 429 |  | 
|  | 430 | #[test] | 
|  | 431 | fn id_getter() { | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 432 | let buffer = HardwareBuffer::new(&HardwareBufferDescription::new( | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 433 | 1024, | 
|  | 434 | 512, | 
|  | 435 | 1, | 
|  | 436 | AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, | 
|  | 437 | AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 438 | 0, | 
|  | 439 | )) | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 440 | .expect("Buffer with some basic parameters was not created successfully"); | 
|  | 441 |  | 
|  | 442 | assert_ne!(0, buffer.id()); | 
|  | 443 | } | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 444 |  | 
|  | 445 | #[test] | 
|  | 446 | fn clone() { | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 447 | let buffer = HardwareBuffer::new(&HardwareBufferDescription::new( | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 448 | 1024, | 
|  | 449 | 512, | 
|  | 450 | 1, | 
|  | 451 | AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, | 
|  | 452 | AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 453 | 0, | 
|  | 454 | )) | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 455 | .expect("Buffer with some basic parameters was not created successfully"); | 
|  | 456 | let buffer2 = buffer.clone(); | 
|  | 457 |  | 
|  | 458 | assert_eq!(buffer, buffer2); | 
|  | 459 | } | 
|  | 460 |  | 
|  | 461 | #[test] | 
|  | 462 | fn into_raw() { | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 463 | let buffer = HardwareBuffer::new(&HardwareBufferDescription::new( | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 464 | 1024, | 
|  | 465 | 512, | 
|  | 466 | 1, | 
|  | 467 | AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, | 
|  | 468 | AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 469 | 0, | 
|  | 470 | )) | 
| Jim Shargo | b69c6ef | 2023-10-05 22:54:51 +0000 | [diff] [blame] | 471 | .expect("Buffer with some basic parameters was not created successfully"); | 
|  | 472 | let buffer2 = buffer.clone(); | 
|  | 473 |  | 
|  | 474 | let raw_buffer = buffer.into_raw(); | 
|  | 475 | // SAFETY: This is the same pointer we had before. | 
|  | 476 | let remade_buffer = unsafe { HardwareBuffer::from_raw(raw_buffer) }; | 
|  | 477 |  | 
|  | 478 | assert_eq!(remade_buffer, buffer2); | 
|  | 479 | } | 
| Andrew Walbran | a73d62c | 2024-08-20 17:20:56 +0100 | [diff] [blame] | 480 |  | 
|  | 481 | #[test] | 
|  | 482 | fn native_handle_and_back() { | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 483 | let buffer_description = HardwareBufferDescription::new( | 
| Andrew Walbran | a73d62c | 2024-08-20 17:20:56 +0100 | [diff] [blame] | 484 | 1024, | 
|  | 485 | 512, | 
|  | 486 | 1, | 
|  | 487 | AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, | 
|  | 488 | AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 489 | 1024, | 
|  | 490 | ); | 
|  | 491 | let buffer = HardwareBuffer::new(&buffer_description) | 
|  | 492 | .expect("Buffer with some basic parameters was not created successfully"); | 
| Andrew Walbran | a73d62c | 2024-08-20 17:20:56 +0100 | [diff] [blame] | 493 |  | 
|  | 494 | let native_handle = | 
|  | 495 | buffer.cloned_native_handle().expect("Failed to get native handle for buffer"); | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 496 | let buffer2 = HardwareBuffer::create_from_handle(&native_handle, &buffer_description) | 
| Andrew Walbran | a73d62c | 2024-08-20 17:20:56 +0100 | [diff] [blame] | 497 | .expect("Failed to create buffer from native handle"); | 
|  | 498 |  | 
| Andrew Walbran | abc932e | 2024-08-30 14:10:29 +0100 | [diff] [blame] | 499 | assert_eq!(buffer.description(), buffer_description); | 
|  | 500 | assert_eq!(buffer2.description(), buffer_description); | 
| Andrew Walbran | a73d62c | 2024-08-20 17:20:56 +0100 | [diff] [blame] | 501 | } | 
| Jim Shargo | 7df9f75 | 2023-07-18 20:33:45 +0000 | [diff] [blame] | 502 | } |