xref: /aosp_15_r20/external/crosvm/gpu_display/src/gpu_display_android.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2024 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::ffi::c_char;
6 use std::ffi::CStr;
7 use std::ffi::CString;
8 use std::panic::catch_unwind;
9 use std::process::abort;
10 use std::ptr::NonNull;
11 use std::rc::Rc;
12 use std::slice;
13 
14 use base::error;
15 use base::AsRawDescriptor;
16 use base::Event;
17 use base::RawDescriptor;
18 use base::VolatileSlice;
19 use vm_control::gpu::DisplayParameters;
20 
21 use crate::DisplayT;
22 use crate::GpuDisplayError;
23 use crate::GpuDisplayFramebuffer;
24 use crate::GpuDisplayResult;
25 use crate::GpuDisplaySurface;
26 use crate::SurfaceType;
27 use crate::SysDisplayT;
28 
29 // Opaque blob
30 #[repr(C)]
31 pub(crate) struct AndroidDisplayContext {
32     _data: [u8; 0],
33     _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
34 }
35 
36 // Opaque blob
37 #[repr(C)]
38 pub(crate) struct AndroidDisplaySurface {
39     _data: [u8; 0],
40     _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
41 }
42 
43 // Should be the same as ANativeWindow_Buffer in android/native_window.h
44 // Note that this struct is part of NDK; guaranteed to be stable, so we use it directly across the
45 // FFI.
46 #[repr(C)]
47 pub(crate) struct ANativeWindow_Buffer {
48     width: i32,
49     height: i32,
50     stride: i32, // in number of pixels, NOT bytes
51     format: i32,
52     bits: *mut u8,
53     reserved: [u32; 6],
54 }
55 
56 pub(crate) type ErrorCallback = unsafe extern "C" fn(message: *const c_char);
57 
58 extern "C" {
59     /// Constructs an AndroidDisplayContext for this backend. This awlays returns a valid (ex:
60     /// non-null) handle to the context. The `name` parameter is from crosvm commandline and the
61     /// client of crosvm will use it to locate and communicate to the AndroidDisplayContext. For
62     /// example, this can be a path to UNIX domain socket where a RPC binder server listens on.
63     /// `error_callback` is a function pointer to an error reporting function, and will be used by
64     /// this and other functions below when something goes wrong. The returned context should be
65     /// destroyed by calling `destroy_android_display_context` if this backend is no longer in use.
create_android_display_context( name: *const c_char, error_callback: ErrorCallback, ) -> *mut AndroidDisplayContext66     fn create_android_display_context(
67         name: *const c_char,
68         error_callback: ErrorCallback,
69     ) -> *mut AndroidDisplayContext;
70 
71     /// Destroys the AndroidDisplayContext created from `create_android_display_context`.
destroy_android_display_context(self_: *mut AndroidDisplayContext)72     fn destroy_android_display_context(self_: *mut AndroidDisplayContext);
73 
74     /// Creates an Android Surface (which is also called as Window) of given size. If the surface
75     /// can't be created for whatever reason, null pointer is returned, in which case we shouldn't
76     /// proceed further.
create_android_surface( ctx: *mut AndroidDisplayContext, width: u32, height: u32, for_cursor: bool, ) -> *mut AndroidDisplaySurface77     fn create_android_surface(
78         ctx: *mut AndroidDisplayContext,
79         width: u32,
80         height: u32,
81         for_cursor: bool,
82     ) -> *mut AndroidDisplaySurface;
83 
84     /// Destroys the Android surface created from `create_android_surface`.
85     #[allow(dead_code)]
destroy_android_surface( ctx: *mut AndroidDisplayContext, surface: *mut AndroidDisplaySurface, )86     fn destroy_android_surface(
87         ctx: *mut AndroidDisplayContext,
88         surface: *mut AndroidDisplaySurface,
89     );
90 
91     /// Obtains one buffer from the given Android Surface. The information about the buffer (buffer
92     /// address, size, stride, etc) is reported via the `ANativeWindow_Buffer` struct. It shouldn't
93     /// be null. The size of the buffer is guaranteed to be bigger than (width * stride * 4) bytes.
94     /// This function locks the buffer for the client, which means the caller has the exclusive
95     /// access to the buffer until it is returned back to Android display stack (surfaceflinger) by
96     /// calling `post_android_surface_buffer`. This function may fail (in which case false is
97     /// returned), then the caller shouldn't try to read `out_buffer` or use the buffer in any way.
get_android_surface_buffer( ctx: *mut AndroidDisplayContext, surface: *mut AndroidDisplaySurface, out_buffer: *mut ANativeWindow_Buffer, ) -> bool98     fn get_android_surface_buffer(
99         ctx: *mut AndroidDisplayContext,
100         surface: *mut AndroidDisplaySurface,
101         out_buffer: *mut ANativeWindow_Buffer,
102     ) -> bool;
103 
set_android_surface_position(ctx: *mut AndroidDisplayContext, x: u32, y: u32)104     fn set_android_surface_position(ctx: *mut AndroidDisplayContext, x: u32, y: u32);
105 
106     /// Posts the buffer obtained from `get_android_surface_buffer` to the Android display system
107     /// so that it can be displayed on the screen. Once this is called, the caller shouldn't use
108     /// the buffer any more.
post_android_surface_buffer( ctx: *mut AndroidDisplayContext, surface: *mut AndroidDisplaySurface, )109     fn post_android_surface_buffer(
110         ctx: *mut AndroidDisplayContext,
111         surface: *mut AndroidDisplaySurface,
112     );
113 }
114 
error_callback(message: *const c_char)115 unsafe extern "C" fn error_callback(message: *const c_char) {
116     catch_unwind(|| {
117         error!(
118             "{}",
119             // SAFETY: message is null terminated
120             unsafe { CStr::from_ptr(message) }.to_string_lossy()
121         )
122     })
123     .unwrap_or_else(|_| abort())
124 }
125 
126 struct AndroidDisplayContextWrapper(NonNull<AndroidDisplayContext>);
127 
128 impl Drop for AndroidDisplayContextWrapper {
drop(&mut self)129     fn drop(&mut self) {
130         // SAFETY: this object is constructed from create_android_display_context
131         unsafe { destroy_android_display_context(self.0.as_ptr()) };
132     }
133 }
134 
135 impl Default for ANativeWindow_Buffer {
default() -> Self136     fn default() -> Self {
137         Self {
138             width: 0,
139             height: 0,
140             stride: 0,
141             format: 0,
142             bits: std::ptr::null_mut(),
143             reserved: [0u32; 6],
144         }
145     }
146 }
147 
148 impl From<ANativeWindow_Buffer> for GpuDisplayFramebuffer<'_> {
from(anb: ANativeWindow_Buffer) -> Self149     fn from(anb: ANativeWindow_Buffer) -> Self {
150         // TODO: check anb.format to see if it's ARGB8888?
151         // TODO: infer bpp from anb.format?
152         const BYTES_PER_PIXEL: u32 = 4;
153         let stride_bytes = BYTES_PER_PIXEL * u32::try_from(anb.stride).unwrap();
154         let buffer_size = stride_bytes * u32::try_from(anb.height).unwrap();
155         let buffer =
156             // SAFETY: get_android_surface_buffer guarantees that bits points to a valid buffer and
157             // the buffer remains available until post_android_surface_buffer is called.
158             unsafe { slice::from_raw_parts_mut(anb.bits, buffer_size.try_into().unwrap()) };
159         Self::new(VolatileSlice::new(buffer), stride_bytes, BYTES_PER_PIXEL)
160     }
161 }
162 
163 struct AndroidSurface {
164     context: Rc<AndroidDisplayContextWrapper>,
165     surface: NonNull<AndroidDisplaySurface>,
166 }
167 
168 impl GpuDisplaySurface for AndroidSurface {
framebuffer(&mut self) -> Option<GpuDisplayFramebuffer>169     fn framebuffer(&mut self) -> Option<GpuDisplayFramebuffer> {
170         let mut anb = ANativeWindow_Buffer::default();
171         // SAFETY: context and surface are opaque handles and buf is used as the out parameter to
172         // hold the return values.
173         let success = unsafe {
174             get_android_surface_buffer(
175                 self.context.0.as_ptr(),
176                 self.surface.as_ptr(),
177                 &mut anb as *mut ANativeWindow_Buffer,
178             )
179         };
180         if success {
181             Some(anb.into())
182         } else {
183             None
184         }
185     }
186 
flip(&mut self)187     fn flip(&mut self) {
188         // SAFETY: context and surface are opaque handles.
189         unsafe { post_android_surface_buffer(self.context.0.as_ptr(), self.surface.as_ptr()) }
190     }
191 
set_position(&mut self, x: u32, y: u32)192     fn set_position(&mut self, x: u32, y: u32) {
193         // SAFETY: context is an opaque handle.
194         unsafe { set_android_surface_position(self.context.0.as_ptr(), x, y) };
195     }
196 }
197 
198 pub struct DisplayAndroid {
199     context: Rc<AndroidDisplayContextWrapper>,
200     /// This event is never triggered and is used solely to fulfill AsRawDescriptor.
201     event: Event,
202 }
203 
204 impl DisplayAndroid {
new(name: &str) -> GpuDisplayResult<DisplayAndroid>205     pub fn new(name: &str) -> GpuDisplayResult<DisplayAndroid> {
206         let name = CString::new(name).unwrap();
207         let context = NonNull::new(
208             // SAFETY: service_name is not leaked outside of this function
209             unsafe { create_android_display_context(name.as_ptr(), error_callback) },
210         )
211         .ok_or(GpuDisplayError::Unsupported)?;
212         let context = AndroidDisplayContextWrapper(context);
213         let event = Event::new().map_err(|_| GpuDisplayError::CreateEvent)?;
214         Ok(DisplayAndroid {
215             context: context.into(),
216             event,
217         })
218     }
219 }
220 
221 impl DisplayT for DisplayAndroid {
create_surface( &mut self, parent_surface_id: Option<u32>, _surface_id: u32, _scanout_id: Option<u32>, display_params: &DisplayParameters, _surf_type: SurfaceType, ) -> GpuDisplayResult<Box<dyn GpuDisplaySurface>>222     fn create_surface(
223         &mut self,
224         parent_surface_id: Option<u32>,
225         _surface_id: u32,
226         _scanout_id: Option<u32>,
227         display_params: &DisplayParameters,
228         _surf_type: SurfaceType,
229     ) -> GpuDisplayResult<Box<dyn GpuDisplaySurface>> {
230         let (requested_width, requested_height) = display_params.get_virtual_display_size();
231         // SAFETY: context is an opaque handle.
232         let surface = NonNull::new(unsafe {
233             create_android_surface(
234                 self.context.0.as_ptr(),
235                 requested_width,
236                 requested_height,
237                 parent_surface_id.is_some(),
238             )
239         })
240         .ok_or(GpuDisplayError::CreateSurface)?;
241 
242         Ok(Box::new(AndroidSurface {
243             context: self.context.clone(),
244             surface,
245         }))
246     }
247 }
248 
249 impl SysDisplayT for DisplayAndroid {}
250 
251 impl AsRawDescriptor for DisplayAndroid {
as_raw_descriptor(&self) -> RawDescriptor252     fn as_raw_descriptor(&self) -> RawDescriptor {
253         self.event.as_raw_descriptor()
254     }
255 }
256