gpu_display/
gpu_display_android.rs1use std::ffi::c_char;
6use std::ffi::CStr;
7use std::ffi::CString;
8use std::panic::catch_unwind;
9use std::process::abort;
10use std::ptr::NonNull;
11use std::rc::Rc;
12use std::slice;
13
14use base::error;
15use base::AsRawDescriptor;
16use base::Event;
17use base::RawDescriptor;
18use base::VolatileSlice;
19use vm_control::gpu::DisplayParameters;
20
21use crate::DisplayT;
22use crate::GpuDisplayError;
23use crate::GpuDisplayFramebuffer;
24use crate::GpuDisplayResult;
25use crate::GpuDisplaySurface;
26use crate::SurfaceType;
27use crate::SysDisplayT;
28
29#[repr(C)]
31pub(crate) struct AndroidDisplayContext {
32 _data: [u8; 0],
33 _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
34}
35
36#[repr(C)]
38pub(crate) struct AndroidDisplaySurface {
39 _data: [u8; 0],
40 _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
41}
42
43#[repr(C)]
47pub(crate) struct ANativeWindow_Buffer {
48 width: i32,
49 height: i32,
50 stride: i32, format: i32,
52 bits: *mut u8,
53 reserved: [u32; 6],
54}
55
56pub(crate) type ErrorCallback = unsafe extern "C" fn(message: *const c_char);
57
58extern "C" {
59 fn create_android_display_context(
67 name: *const c_char,
68 error_callback: ErrorCallback,
69 ) -> *mut AndroidDisplayContext;
70
71 fn destroy_android_display_context(self_: *mut AndroidDisplayContext);
73
74 fn create_android_surface(
78 ctx: *mut AndroidDisplayContext,
79 width: u32,
80 height: u32,
81 for_cursor: bool,
82 ) -> *mut AndroidDisplaySurface;
83
84 #[allow(dead_code)]
86 fn destroy_android_surface(
87 ctx: *mut AndroidDisplayContext,
88 surface: *mut AndroidDisplaySurface,
89 );
90
91 fn get_android_surface_buffer(
99 ctx: *mut AndroidDisplayContext,
100 surface: *mut AndroidDisplaySurface,
101 out_buffer: *mut ANativeWindow_Buffer,
102 ) -> bool;
103
104 fn set_android_surface_position(ctx: *mut AndroidDisplayContext, x: u32, y: u32);
105
106 fn post_android_surface_buffer(
110 ctx: *mut AndroidDisplayContext,
111 surface: *mut AndroidDisplaySurface,
112 );
113}
114
115unsafe extern "C" fn error_callback(message: *const c_char) {
116 catch_unwind(|| {
117 error!(
118 "{}",
119 unsafe { CStr::from_ptr(message) }.to_string_lossy()
121 )
122 })
123 .unwrap_or_else(|_| abort())
124}
125
126struct AndroidDisplayContextWrapper(NonNull<AndroidDisplayContext>);
127
128impl Drop for AndroidDisplayContextWrapper {
129 fn drop(&mut self) {
130 unsafe { destroy_android_display_context(self.0.as_ptr()) };
132 }
133}
134
135impl Default for ANativeWindow_Buffer {
136 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
148impl From<ANativeWindow_Buffer> for GpuDisplayFramebuffer<'_> {
149 fn from(anb: ANativeWindow_Buffer) -> Self {
150 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 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
163struct AndroidSurface {
164 context: Rc<AndroidDisplayContextWrapper>,
165 surface: NonNull<AndroidDisplaySurface>,
166}
167
168impl GpuDisplaySurface for AndroidSurface {
169 fn framebuffer(&mut self) -> Option<GpuDisplayFramebuffer> {
170 let mut anb = ANativeWindow_Buffer::default();
171 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
187 fn flip(&mut self) {
188 unsafe { post_android_surface_buffer(self.context.0.as_ptr(), self.surface.as_ptr()) }
190 }
191
192 fn set_position(&mut self, x: u32, y: u32) {
193 unsafe { set_android_surface_position(self.context.0.as_ptr(), x, y) };
195 }
196}
197
198pub struct DisplayAndroid {
199 context: Rc<AndroidDisplayContextWrapper>,
200 event: Event,
202}
203
204impl DisplayAndroid {
205 pub fn new(name: &str) -> GpuDisplayResult<DisplayAndroid> {
206 let name = CString::new(name).unwrap();
207 let context = NonNull::new(
208 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
221impl DisplayT for DisplayAndroid {
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 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
249impl SysDisplayT for DisplayAndroid {}
250
251impl AsRawDescriptor for DisplayAndroid {
252 fn as_raw_descriptor(&self) -> RawDescriptor {
253 self.event.as_raw_descriptor()
254 }
255}