1 // Copyright (C) 2024 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 //! Rust wrapper for `ANativeWindow` and related types. 16 17 pub(crate) mod buffer; 18 19 use binder::{ 20 binder_impl::{BorrowedParcel, UnstructuredParcelable}, 21 impl_deserialize_for_unstructured_parcelable, impl_serialize_for_unstructured_parcelable, 22 unstable_api::{status_result, AsNative}, 23 StatusCode, 24 }; 25 use bitflags::bitflags; 26 use buffer::Buffer; 27 use nativewindow_bindgen::{ 28 ADataSpace, AHardwareBuffer_Format, ANativeWindow, ANativeWindow_acquire, 29 ANativeWindow_getBuffersDataSpace, ANativeWindow_getBuffersDefaultDataSpace, 30 ANativeWindow_getFormat, ANativeWindow_getHeight, ANativeWindow_getWidth, ANativeWindow_lock, 31 ANativeWindow_readFromParcel, ANativeWindow_release, ANativeWindow_setBuffersDataSpace, 32 ANativeWindow_setBuffersGeometry, ANativeWindow_setBuffersTransform, 33 ANativeWindow_unlockAndPost, ANativeWindow_writeToParcel, ARect, 34 }; 35 use std::error::Error; 36 use std::fmt::{self, Debug, Display, Formatter}; 37 use std::ptr::{self, null_mut, NonNull}; 38 39 /// Wrapper around an opaque C `ANativeWindow`. 40 #[derive(PartialEq, Eq)] 41 pub struct Surface(NonNull<ANativeWindow>); 42 43 impl Surface { 44 /// Returns the current width in pixels of the window surface. width(&self) -> Result<u32, ErrorCode>45 pub fn width(&self) -> Result<u32, ErrorCode> { 46 // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because 47 // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel` 48 // and we have not yet released it. 49 let width = unsafe { ANativeWindow_getWidth(self.0.as_ptr()) }; 50 width.try_into().map_err(|_| ErrorCode(width)) 51 } 52 53 /// Returns the current height in pixels of the window surface. height(&self) -> Result<u32, ErrorCode>54 pub fn height(&self) -> Result<u32, ErrorCode> { 55 // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because 56 // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel` 57 // and we have not yet released it. 58 let height = unsafe { ANativeWindow_getHeight(self.0.as_ptr()) }; 59 height.try_into().map_err(|_| ErrorCode(height)) 60 } 61 62 /// Returns the current pixel format of the window surface. format(&self) -> Result<AHardwareBuffer_Format::Type, ErrorCode>63 pub fn format(&self) -> Result<AHardwareBuffer_Format::Type, ErrorCode> { 64 // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because 65 // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel` 66 // and we have not yet released it. 67 let format = unsafe { ANativeWindow_getFormat(self.0.as_ptr()) }; 68 format.try_into().map_err(|_| ErrorCode(format)) 69 } 70 71 /// Changes the format and size of the window buffers. 72 /// 73 /// The width and height control the number of pixels in the buffers, not the dimensions of the 74 /// window on screen. If these are different than the window's physical size, then its buffer 75 /// will be scaled to match that size when compositing it to the screen. The width and height 76 /// must be either both zero or both non-zero. If both are 0 then the window's base value will 77 /// come back in force. set_buffers_geometry( &mut self, width: i32, height: i32, format: AHardwareBuffer_Format::Type, ) -> Result<(), ErrorCode>78 pub fn set_buffers_geometry( 79 &mut self, 80 width: i32, 81 height: i32, 82 format: AHardwareBuffer_Format::Type, 83 ) -> Result<(), ErrorCode> { 84 // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because 85 // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel` 86 // and we have not yet released it. 87 let status = unsafe { 88 ANativeWindow_setBuffersGeometry( 89 self.0.as_ptr(), 90 width, 91 height, 92 format.try_into().expect("Invalid format"), 93 ) 94 }; 95 96 if status == 0 { 97 Ok(()) 98 } else { 99 Err(ErrorCode(status)) 100 } 101 } 102 103 /// Sets a transfom that will be applied to future buffers posted to the window. set_buffers_transform(&mut self, transform: Transform) -> Result<(), ErrorCode>104 pub fn set_buffers_transform(&mut self, transform: Transform) -> Result<(), ErrorCode> { 105 // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because 106 // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel` 107 // and we have not yet released it. 108 let status = 109 unsafe { ANativeWindow_setBuffersTransform(self.0.as_ptr(), transform.bits() as i32) }; 110 111 if status == 0 { 112 Ok(()) 113 } else { 114 Err(ErrorCode(status)) 115 } 116 } 117 118 /// Sets the data space that will be applied to future buffers posted to the window. set_buffers_data_space(&mut self, data_space: ADataSpace) -> Result<(), ErrorCode>119 pub fn set_buffers_data_space(&mut self, data_space: ADataSpace) -> Result<(), ErrorCode> { 120 // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because 121 // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel` 122 // and we have not yet released it. 123 let status = unsafe { ANativeWindow_setBuffersDataSpace(self.0.as_ptr(), data_space.0) }; 124 125 if status == 0 { 126 Ok(()) 127 } else { 128 Err(ErrorCode(status)) 129 } 130 } 131 132 /// Gets the data space of the buffers in the window. get_buffers_data_space(&mut self) -> Result<ADataSpace, ErrorCode>133 pub fn get_buffers_data_space(&mut self) -> Result<ADataSpace, ErrorCode> { 134 // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because 135 // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel` 136 // and we have not yet released it. 137 let data_space = unsafe { ANativeWindow_getBuffersDataSpace(self.0.as_ptr()) }; 138 139 if data_space < 0 { 140 Err(ErrorCode(data_space)) 141 } else { 142 Ok(ADataSpace(data_space)) 143 } 144 } 145 146 /// Gets the default data space of the buffers in the window as set by the consumer. get_buffers_default_data_space(&mut self) -> Result<ADataSpace, ErrorCode>147 pub fn get_buffers_default_data_space(&mut self) -> Result<ADataSpace, ErrorCode> { 148 // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because 149 // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel` 150 // and we have not yet released it. 151 let data_space = unsafe { ANativeWindow_getBuffersDefaultDataSpace(self.0.as_ptr()) }; 152 153 if data_space < 0 { 154 Err(ErrorCode(data_space)) 155 } else { 156 Ok(ADataSpace(data_space)) 157 } 158 } 159 160 /// Locks the window's next drawing surface for writing, and returns it. lock(&mut self, bounds: Option<&mut ARect>) -> Result<Buffer, ErrorCode>161 pub fn lock(&mut self, bounds: Option<&mut ARect>) -> Result<Buffer, ErrorCode> { 162 let mut buffer = buffer::EMPTY; 163 // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because 164 // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel` 165 // and we have not yet released it. The other pointers must be valid because the come from 166 // references, and aren't retained after the function returns. 167 let status = unsafe { 168 ANativeWindow_lock( 169 self.0.as_ptr(), 170 &mut buffer, 171 bounds.map(ptr::from_mut).unwrap_or(null_mut()), 172 ) 173 }; 174 if status != 0 { 175 return Err(ErrorCode(status)); 176 } 177 178 Ok(Buffer::new(buffer, self)) 179 } 180 181 /// Unlocks the window's drawing surface which was previously locked, posting the new buffer to 182 /// the display. 183 /// 184 /// This shouldn't be called directly but via the [`Buffer`], hence is not public here. unlock_and_post(&mut self) -> Result<(), ErrorCode>185 fn unlock_and_post(&mut self) -> Result<(), ErrorCode> { 186 // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because 187 // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel` 188 // and we have not yet released it. 189 let status = unsafe { ANativeWindow_unlockAndPost(self.0.as_ptr()) }; 190 if status == 0 { 191 Ok(()) 192 } else { 193 Err(ErrorCode(status)) 194 } 195 } 196 } 197 198 impl Drop for Surface { drop(&mut self)199 fn drop(&mut self) { 200 // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because 201 // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel` 202 // and we have not yet released it. 203 unsafe { ANativeWindow_release(self.0.as_ptr()) } 204 } 205 } 206 207 impl Debug for Surface { fmt(&self, f: &mut Formatter) -> fmt::Result208 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 209 f.debug_struct("Surface") 210 .field("width", &self.width()) 211 .field("height", &self.height()) 212 .field("format", &self.format()) 213 .finish() 214 } 215 } 216 217 impl Clone for Surface { clone(&self) -> Self218 fn clone(&self) -> Self { 219 // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because 220 // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel` 221 // and we have not yet released it. 222 unsafe { ANativeWindow_acquire(self.0.as_ptr()) }; 223 Self(self.0) 224 } 225 } 226 227 impl UnstructuredParcelable for Surface { write_to_parcel(&self, parcel: &mut BorrowedParcel) -> Result<(), StatusCode>228 fn write_to_parcel(&self, parcel: &mut BorrowedParcel) -> Result<(), StatusCode> { 229 let status = 230 // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because 231 // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel` 232 // and we have not yet released it. 233 unsafe { ANativeWindow_writeToParcel(self.0.as_ptr(), parcel.as_native_mut()) }; 234 status_result(status) 235 } 236 from_parcel(parcel: &BorrowedParcel) -> Result<Self, StatusCode>237 fn from_parcel(parcel: &BorrowedParcel) -> Result<Self, StatusCode> { 238 let mut buffer = null_mut(); 239 240 let status = 241 // SAFETY: Both pointers must be valid because they are obtained from references. 242 // `ANativeWindow_readFromParcel` doesn't store them or do anything else special 243 // with them. If it returns success then it will have allocated a new 244 // `ANativeWindow` and incremented the reference count, so we can use it until we 245 // release it. 246 unsafe { ANativeWindow_readFromParcel(parcel.as_native(), &mut buffer) }; 247 248 status_result(status)?; 249 250 Ok(Self( 251 NonNull::new(buffer) 252 .expect("ANativeWindow_readFromParcel returned success but didn't allocate buffer"), 253 )) 254 } 255 } 256 257 impl_deserialize_for_unstructured_parcelable!(Surface); 258 impl_serialize_for_unstructured_parcelable!(Surface); 259 260 // SAFETY: The underlying *ANativeWindow can be moved between threads. 261 unsafe impl Send for Surface {} 262 263 // SAFETY: The underlying *ANativeWindow can be used from multiple threads concurrently. 264 unsafe impl Sync for Surface {} 265 266 /// An error code returned by methods on [`Surface`]. 267 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 268 pub struct ErrorCode(i32); 269 270 impl Error for ErrorCode {} 271 272 impl Display for ErrorCode { fmt(&self, f: &mut Formatter) -> fmt::Result273 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 274 write!(f, "Error {}", self.0) 275 } 276 } 277 278 bitflags! { 279 /// Transforms that can be applied to buffers as they are displayed to a window. 280 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 281 pub struct Transform: u32 { 282 const MIRROR_HORIZONTAL = 0x01; 283 const MIRROR_VERTICAL = 0x02; 284 const ROTATE_90 = 0x04; 285 } 286 } 287 288 impl Transform { 289 pub const IDENTITY: Self = Self::empty(); 290 pub const ROTATE_180: Self = Self::MIRROR_HORIZONTAL.union(Self::MIRROR_VERTICAL); 291 pub const ROTATE_270: Self = Self::ROTATE_180.union(Self::ROTATE_90); 292 } 293