Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 30262985 authored by Andrew Walbran's avatar Andrew Walbran
Browse files

Add methods to get locked buffer from Surface.

Bug: 307535208
Test: atest libnativewindow_rs-internal_test
Change-Id: Ib9a824a72d1d415dddd82e477d55200765d0b9e6
parent 78c6534a
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -19,10 +19,9 @@ extern crate nativewindow_bindgen as ffi;
mod handle;
mod surface;

pub use handle::NativeHandle;
pub use surface::Surface;

pub use ffi::{AHardwareBuffer_Format, AHardwareBuffer_UsageFlags};
pub use handle::NativeHandle;
pub use surface::{buffer::Buffer, Surface};

use binder::{
    binder_impl::{BorrowedParcel, UnstructuredParcelable},
+43 −3
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@

//! Rust wrapper for `ANativeWindow` and related types.

pub(crate) mod buffer;

use binder::{
    binder_impl::{BorrowedParcel, UnstructuredParcelable},
    impl_deserialize_for_unstructured_parcelable, impl_serialize_for_unstructured_parcelable,
@@ -21,17 +23,18 @@ use binder::{
    StatusCode,
};
use bitflags::bitflags;
use buffer::Buffer;
use nativewindow_bindgen::{
    ADataSpace, AHardwareBuffer_Format, ANativeWindow, ANativeWindow_acquire,
    ANativeWindow_getBuffersDataSpace, ANativeWindow_getBuffersDefaultDataSpace,
    ANativeWindow_getFormat, ANativeWindow_getHeight, ANativeWindow_getWidth,
    ANativeWindow_getFormat, ANativeWindow_getHeight, ANativeWindow_getWidth, ANativeWindow_lock,
    ANativeWindow_readFromParcel, ANativeWindow_release, ANativeWindow_setBuffersDataSpace,
    ANativeWindow_setBuffersGeometry, ANativeWindow_setBuffersTransform,
    ANativeWindow_writeToParcel,
    ANativeWindow_unlockAndPost, ANativeWindow_writeToParcel, ARect,
};
use std::error::Error;
use std::fmt::{self, Debug, Display, Formatter};
use std::ptr::{null_mut, NonNull};
use std::ptr::{self, null_mut, NonNull};

/// Wrapper around an opaque C `ANativeWindow`.
#[derive(PartialEq, Eq)]
@@ -153,6 +156,43 @@ impl Surface {
            Ok(ADataSpace(data_space))
        }
    }

    /// Locks the window's next drawing surface for writing, and returns it.
    pub fn lock(&mut self, bounds: Option<&mut ARect>) -> Result<Buffer, ErrorCode> {
        let mut buffer = buffer::EMPTY;
        // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because
        // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel`
        // and we have not yet released it. The other pointers must be valid because the come from
        // references, and aren't retained after the function returns.
        let status = unsafe {
            ANativeWindow_lock(
                self.0.as_ptr(),
                &mut buffer,
                bounds.map(ptr::from_mut).unwrap_or(null_mut()),
            )
        };
        if status != 0 {
            return Err(ErrorCode(status));
        }

        Ok(Buffer::new(buffer, self))
    }

    /// Unlocks the window's drawing surface which was previously locked, posting the new buffer to
    /// the display.
    ///
    /// This shouldn't be called directly but via the [`Buffer`], hence is not public here.
    fn unlock_and_post(&mut self) -> Result<(), ErrorCode> {
        // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because
        // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel`
        // and we have not yet released it.
        let status = unsafe { ANativeWindow_unlockAndPost(self.0.as_ptr()) };
        if status == 0 {
            Ok(())
        } else {
            Err(ErrorCode(status))
        }
    }
}

impl Drop for Surface {
+46 −0
Original line number Diff line number Diff line
// Copyright (C) 2024 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use super::{ErrorCode, Surface};
use nativewindow_bindgen::ANativeWindow_Buffer;
use std::ptr::null_mut;

/// An empty `ANativeWindow_Buffer`.
pub const EMPTY: ANativeWindow_Buffer = ANativeWindow_Buffer {
    width: 0,
    height: 0,
    stride: 0,
    format: 0,
    bits: null_mut(),
    reserved: [0; 6],
};

/// Rust wrapper for `ANativeWindow_Buffer`, representing a locked buffer from a [`Surface`].
pub struct Buffer<'a> {
    /// The wrapped `ANativeWindow_Buffer`.
    pub buffer: ANativeWindow_Buffer,
    surface: &'a mut Surface,
}

impl<'a> Buffer<'a> {
    pub(crate) fn new(buffer: ANativeWindow_Buffer, surface: &'a mut Surface) -> Self {
        Self { buffer, surface }
    }

    /// Unlocks the window's drawing surface which was previously locked to create this buffer,
    /// posting the buffer to the display.
    pub fn unlock_and_post(self) -> Result<(), ErrorCode> {
        self.surface.unlock_and_post()
    }
}