Skip to content

Commit b8b0c6f

Browse files
Treehugger Robotandroid-build-merge-worker-robot
authored andcommitted
Merge "Wrap AHardwareBuffer_LockPlanes too." into main am: 483de12
Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/3350856 Change-Id: If0858526a33e38547aeef1ff8519310935b0fa36 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
2 parents 56cea28 + 483de12 commit b8b0c6f

1 file changed

Lines changed: 65 additions & 2 deletions

File tree

  • libs/nativewindow/rust/src

libs/nativewindow/rust/src/lib.rs

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ use binder::{
3030
StatusCode,
3131
};
3232
use ffi::{
33-
AHardwareBuffer, AHardwareBuffer_Desc, AHardwareBuffer_readFromParcel,
34-
AHardwareBuffer_writeToParcel, ARect,
33+
AHardwareBuffer, AHardwareBuffer_Desc, AHardwareBuffer_Plane, AHardwareBuffer_Planes,
34+
AHardwareBuffer_readFromParcel, AHardwareBuffer_writeToParcel, ARect,
3535
};
3636
use std::ffi::c_void;
3737
use std::fmt::{self, Debug, Formatter};
@@ -313,6 +313,57 @@ impl HardwareBuffer {
313313
})
314314
}
315315

316+
/// Lock a potentially multi-planar hardware buffer for direct CPU access.
317+
///
318+
/// # Safety
319+
///
320+
/// - If `fence` is `None`, the caller must ensure that all writes to the buffer have completed
321+
/// before calling this function.
322+
/// - If the buffer has `AHARDWAREBUFFER_FORMAT_BLOB`, multiple threads or process may lock the
323+
/// buffer simultaneously, but the caller must ensure that they don't access it simultaneously
324+
/// and break Rust's aliasing rules, like any other shared memory.
325+
/// - Otherwise if `usage` includes `AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY` or
326+
/// `AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN`, the caller must ensure that no other threads or
327+
/// processes lock the buffer simultaneously for any usage.
328+
/// - Otherwise, the caller must ensure that no other threads lock the buffer for writing
329+
/// simultaneously.
330+
/// - If `rect` is not `None`, the caller must not modify the buffer outside of that rectangle.
331+
pub unsafe fn lock_planes<'a>(
332+
&'a self,
333+
usage: AHardwareBuffer_UsageFlags,
334+
fence: Option<BorrowedFd>,
335+
rect: Option<&ARect>,
336+
) -> Result<Vec<PlaneGuard<'a>>, StatusCode> {
337+
let fence = if let Some(fence) = fence { fence.as_raw_fd() } else { -1 };
338+
let rect = rect.map(ptr::from_ref).unwrap_or(null());
339+
let mut planes = AHardwareBuffer_Planes {
340+
planeCount: 0,
341+
planes: [const { AHardwareBuffer_Plane { data: null_mut(), pixelStride: 0, rowStride: 0 } };
342+
4],
343+
};
344+
345+
// SAFETY: The `AHardwareBuffer` pointer we wrap is always valid, and the various out
346+
// pointers are valid because they come from references. Our caller promises that writes have
347+
// completed and there will be no simultaneous read/write locks.
348+
let status = unsafe {
349+
ffi::AHardwareBuffer_lockPlanes(self.0.as_ptr(), usage.0, fence, rect, &mut planes)
350+
};
351+
status_result(status)?;
352+
let plane_count = planes.planeCount.try_into().unwrap();
353+
Ok(planes.planes[..plane_count]
354+
.iter()
355+
.map(|plane| PlaneGuard {
356+
guard: HardwareBufferGuard {
357+
buffer: self,
358+
address: NonNull::new(plane.data)
359+
.expect("AHardwareBuffer_lockAndGetInfo set a null outVirtualAddress"),
360+
},
361+
pixel_stride: plane.pixelStride,
362+
row_stride: plane.rowStride,
363+
})
364+
.collect())
365+
}
366+
316367
/// Locks the hardware buffer for direct CPU access, returning information about the bytes per
317368
/// pixel and stride as well.
318369
///
@@ -510,6 +561,18 @@ pub struct LockedBufferInfo<'a> {
510561
pub stride: u32,
511562
}
512563

564+
/// A guard for a single plane of a locked `HardwareBuffer`, with additional information about the
565+
/// stride.
566+
#[derive(Debug)]
567+
pub struct PlaneGuard<'a> {
568+
/// The locked buffer guard.
569+
pub guard: HardwareBufferGuard<'a>,
570+
/// The stride in bytes between the color channel for one pixel to the next pixel.
571+
pub pixel_stride: u32,
572+
/// The stride in bytes between rows in the buffer.
573+
pub row_stride: u32,
574+
}
575+
513576
#[cfg(test)]
514577
mod test {
515578
use super::*;

0 commit comments

Comments
 (0)