xref: /aosp_15_r20/external/crosvm/rutabaga_gfx/ffi/src/lib.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2021 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker ///! C-bindings for the rutabaga_gfx crate
6*bb4ee6a4SAndroid Build Coastguard Worker extern crate rutabaga_gfx;
7*bb4ee6a4SAndroid Build Coastguard Worker 
8*bb4ee6a4SAndroid Build Coastguard Worker use std::cell::RefCell;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::TryInto;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::ffi::CStr;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::ffi::CString;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::File;
13*bb4ee6a4SAndroid Build Coastguard Worker use std::io::IoSliceMut;
14*bb4ee6a4SAndroid Build Coastguard Worker use std::os::raw::c_char;
15*bb4ee6a4SAndroid Build Coastguard Worker use std::os::raw::c_void;
16*bb4ee6a4SAndroid Build Coastguard Worker use std::panic::catch_unwind;
17*bb4ee6a4SAndroid Build Coastguard Worker use std::panic::AssertUnwindSafe;
18*bb4ee6a4SAndroid Build Coastguard Worker use std::path::Path;
19*bb4ee6a4SAndroid Build Coastguard Worker use std::path::PathBuf;
20*bb4ee6a4SAndroid Build Coastguard Worker use std::ptr::copy_nonoverlapping;
21*bb4ee6a4SAndroid Build Coastguard Worker use std::ptr::null;
22*bb4ee6a4SAndroid Build Coastguard Worker use std::ptr::null_mut;
23*bb4ee6a4SAndroid Build Coastguard Worker use std::slice::from_raw_parts;
24*bb4ee6a4SAndroid Build Coastguard Worker use std::slice::from_raw_parts_mut;
25*bb4ee6a4SAndroid Build Coastguard Worker 
26*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(unix)]
27*bb4ee6a4SAndroid Build Coastguard Worker use libc::iovec;
28*bb4ee6a4SAndroid Build Coastguard Worker use libc::EINVAL;
29*bb4ee6a4SAndroid Build Coastguard Worker use libc::ESRCH;
30*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::ResourceCreate3D;
31*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::ResourceCreateBlob;
32*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::Rutabaga;
33*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaBuilder;
34*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaChannel;
35*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaComponentType;
36*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaDebug;
37*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaDebugHandler;
38*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaDescriptor;
39*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaFence;
40*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaFenceHandler;
41*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaFromRawDescriptor;
42*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaHandle;
43*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaIntoRawDescriptor;
44*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaIovec;
45*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaResult;
46*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaWsi;
47*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::Transfer3D;
48*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RUTABAGA_DEBUG_ERROR;
49*bb4ee6a4SAndroid Build Coastguard Worker 
50*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(not(unix))]
51*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
52*bb4ee6a4SAndroid Build Coastguard Worker pub struct iovec {
53*bb4ee6a4SAndroid Build Coastguard Worker     pub iov_base: *mut c_void,
54*bb4ee6a4SAndroid Build Coastguard Worker     pub iov_len: usize,
55*bb4ee6a4SAndroid Build Coastguard Worker }
56*bb4ee6a4SAndroid Build Coastguard Worker 
57*bb4ee6a4SAndroid Build Coastguard Worker const NO_ERROR: i32 = 0;
58*bb4ee6a4SAndroid Build Coastguard Worker const RUTABAGA_WSI_SURFACELESS: u64 = 1;
59*bb4ee6a4SAndroid Build Coastguard Worker 
60*bb4ee6a4SAndroid Build Coastguard Worker thread_local! {
61*bb4ee6a4SAndroid Build Coastguard Worker     static S_DEBUG_HANDLER: RefCell<Option<RutabagaDebugHandler>> = const { RefCell::new(None) };
62*bb4ee6a4SAndroid Build Coastguard Worker }
63*bb4ee6a4SAndroid Build Coastguard Worker 
log_error(debug_string: String)64*bb4ee6a4SAndroid Build Coastguard Worker fn log_error(debug_string: String) {
65*bb4ee6a4SAndroid Build Coastguard Worker     S_DEBUG_HANDLER.with(|handler_cell| {
66*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(handler) = &*handler_cell.borrow() {
67*bb4ee6a4SAndroid Build Coastguard Worker             let cstring = CString::new(debug_string.as_str()).expect("CString creation failed");
68*bb4ee6a4SAndroid Build Coastguard Worker 
69*bb4ee6a4SAndroid Build Coastguard Worker             let debug = RutabagaDebug {
70*bb4ee6a4SAndroid Build Coastguard Worker                 debug_type: RUTABAGA_DEBUG_ERROR,
71*bb4ee6a4SAndroid Build Coastguard Worker                 message: cstring.as_ptr(),
72*bb4ee6a4SAndroid Build Coastguard Worker             };
73*bb4ee6a4SAndroid Build Coastguard Worker 
74*bb4ee6a4SAndroid Build Coastguard Worker             handler.call(debug);
75*bb4ee6a4SAndroid Build Coastguard Worker         }
76*bb4ee6a4SAndroid Build Coastguard Worker     });
77*bb4ee6a4SAndroid Build Coastguard Worker }
78*bb4ee6a4SAndroid Build Coastguard Worker 
return_result<T>(result: RutabagaResult<T>) -> i3279*bb4ee6a4SAndroid Build Coastguard Worker fn return_result<T>(result: RutabagaResult<T>) -> i32 {
80*bb4ee6a4SAndroid Build Coastguard Worker     if let Err(e) = result {
81*bb4ee6a4SAndroid Build Coastguard Worker         log_error(e.to_string());
82*bb4ee6a4SAndroid Build Coastguard Worker         -EINVAL
83*bb4ee6a4SAndroid Build Coastguard Worker     } else {
84*bb4ee6a4SAndroid Build Coastguard Worker         NO_ERROR
85*bb4ee6a4SAndroid Build Coastguard Worker     }
86*bb4ee6a4SAndroid Build Coastguard Worker }
87*bb4ee6a4SAndroid Build Coastguard Worker 
88*bb4ee6a4SAndroid Build Coastguard Worker macro_rules! return_on_error {
89*bb4ee6a4SAndroid Build Coastguard Worker     ($result:expr) => {
90*bb4ee6a4SAndroid Build Coastguard Worker         match $result {
91*bb4ee6a4SAndroid Build Coastguard Worker             Ok(t) => t,
92*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => {
93*bb4ee6a4SAndroid Build Coastguard Worker                 log_error(e.to_string());
94*bb4ee6a4SAndroid Build Coastguard Worker                 return -EINVAL;
95*bb4ee6a4SAndroid Build Coastguard Worker             }
96*bb4ee6a4SAndroid Build Coastguard Worker         }
97*bb4ee6a4SAndroid Build Coastguard Worker     };
98*bb4ee6a4SAndroid Build Coastguard Worker }
99*bb4ee6a4SAndroid Build Coastguard Worker 
100*bb4ee6a4SAndroid Build Coastguard Worker macro_rules! return_on_io_error {
101*bb4ee6a4SAndroid Build Coastguard Worker     ($result:expr) => {
102*bb4ee6a4SAndroid Build Coastguard Worker         match $result {
103*bb4ee6a4SAndroid Build Coastguard Worker             Ok(t) => t,
104*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => {
105*bb4ee6a4SAndroid Build Coastguard Worker                 log_error(e.to_string());
106*bb4ee6a4SAndroid Build Coastguard Worker                 return -e.raw_os_error().unwrap_or(EINVAL);
107*bb4ee6a4SAndroid Build Coastguard Worker             }
108*bb4ee6a4SAndroid Build Coastguard Worker         }
109*bb4ee6a4SAndroid Build Coastguard Worker     };
110*bb4ee6a4SAndroid Build Coastguard Worker }
111*bb4ee6a4SAndroid Build Coastguard Worker 
112*bb4ee6a4SAndroid Build Coastguard Worker #[allow(non_camel_case_types)]
113*bb4ee6a4SAndroid Build Coastguard Worker type rutabaga = Rutabaga;
114*bb4ee6a4SAndroid Build Coastguard Worker 
115*bb4ee6a4SAndroid Build Coastguard Worker #[allow(non_camel_case_types)]
116*bb4ee6a4SAndroid Build Coastguard Worker type rutabaga_create_blob = ResourceCreateBlob;
117*bb4ee6a4SAndroid Build Coastguard Worker 
118*bb4ee6a4SAndroid Build Coastguard Worker #[allow(non_camel_case_types)]
119*bb4ee6a4SAndroid Build Coastguard Worker type rutabaga_create_3d = ResourceCreate3D;
120*bb4ee6a4SAndroid Build Coastguard Worker 
121*bb4ee6a4SAndroid Build Coastguard Worker #[allow(non_camel_case_types)]
122*bb4ee6a4SAndroid Build Coastguard Worker type rutabaga_transfer = Transfer3D;
123*bb4ee6a4SAndroid Build Coastguard Worker 
124*bb4ee6a4SAndroid Build Coastguard Worker #[allow(non_camel_case_types)]
125*bb4ee6a4SAndroid Build Coastguard Worker type rutabaga_fence = RutabagaFence;
126*bb4ee6a4SAndroid Build Coastguard Worker 
127*bb4ee6a4SAndroid Build Coastguard Worker #[allow(non_camel_case_types)]
128*bb4ee6a4SAndroid Build Coastguard Worker type rutabaga_debug = RutabagaDebug;
129*bb4ee6a4SAndroid Build Coastguard Worker 
130*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
131*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
132*bb4ee6a4SAndroid Build Coastguard Worker pub struct rutabaga_iovecs {
133*bb4ee6a4SAndroid Build Coastguard Worker     pub iovecs: *mut iovec,
134*bb4ee6a4SAndroid Build Coastguard Worker     pub num_iovecs: usize,
135*bb4ee6a4SAndroid Build Coastguard Worker }
136*bb4ee6a4SAndroid Build Coastguard Worker 
137*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
138*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
139*bb4ee6a4SAndroid Build Coastguard Worker pub struct rutabaga_handle {
140*bb4ee6a4SAndroid Build Coastguard Worker     pub os_handle: i64,
141*bb4ee6a4SAndroid Build Coastguard Worker     pub handle_type: u32,
142*bb4ee6a4SAndroid Build Coastguard Worker }
143*bb4ee6a4SAndroid Build Coastguard Worker 
144*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
145*bb4ee6a4SAndroid Build Coastguard Worker pub struct rutabaga_mapping {
146*bb4ee6a4SAndroid Build Coastguard Worker     pub ptr: *mut c_void,
147*bb4ee6a4SAndroid Build Coastguard Worker     pub size: u64,
148*bb4ee6a4SAndroid Build Coastguard Worker }
149*bb4ee6a4SAndroid Build Coastguard Worker 
150*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
151*bb4ee6a4SAndroid Build Coastguard Worker pub struct rutabaga_channel {
152*bb4ee6a4SAndroid Build Coastguard Worker     pub channel_name: *const c_char,
153*bb4ee6a4SAndroid Build Coastguard Worker     pub channel_type: u32,
154*bb4ee6a4SAndroid Build Coastguard Worker }
155*bb4ee6a4SAndroid Build Coastguard Worker 
156*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
157*bb4ee6a4SAndroid Build Coastguard Worker pub struct rutabaga_channels {
158*bb4ee6a4SAndroid Build Coastguard Worker     pub channels: *const rutabaga_channel,
159*bb4ee6a4SAndroid Build Coastguard Worker     pub num_channels: usize,
160*bb4ee6a4SAndroid Build Coastguard Worker }
161*bb4ee6a4SAndroid Build Coastguard Worker 
162*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
163*bb4ee6a4SAndroid Build Coastguard Worker pub struct rutabaga_command {
164*bb4ee6a4SAndroid Build Coastguard Worker     pub ctx_id: u32,
165*bb4ee6a4SAndroid Build Coastguard Worker     pub cmd_size: u32,
166*bb4ee6a4SAndroid Build Coastguard Worker     pub cmd: *mut u8,
167*bb4ee6a4SAndroid Build Coastguard Worker     pub num_in_fences: u32,
168*bb4ee6a4SAndroid Build Coastguard Worker     pub fence_ids: *mut u64,
169*bb4ee6a4SAndroid Build Coastguard Worker }
170*bb4ee6a4SAndroid Build Coastguard Worker 
171*bb4ee6a4SAndroid Build Coastguard Worker #[allow(non_camel_case_types)]
172*bb4ee6a4SAndroid Build Coastguard Worker pub type rutabaga_fence_callback = extern "C" fn(user_data: u64, fence: &rutabaga_fence);
173*bb4ee6a4SAndroid Build Coastguard Worker 
174*bb4ee6a4SAndroid Build Coastguard Worker #[allow(non_camel_case_types)]
175*bb4ee6a4SAndroid Build Coastguard Worker pub type rutabaga_debug_callback = extern "C" fn(user_data: u64, debug: &rutabaga_debug);
176*bb4ee6a4SAndroid Build Coastguard Worker 
177*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
178*bb4ee6a4SAndroid Build Coastguard Worker pub struct rutabaga_builder<'a> {
179*bb4ee6a4SAndroid Build Coastguard Worker     pub user_data: u64,
180*bb4ee6a4SAndroid Build Coastguard Worker     pub capset_mask: u64,
181*bb4ee6a4SAndroid Build Coastguard Worker     pub wsi: u64,
182*bb4ee6a4SAndroid Build Coastguard Worker     pub fence_cb: rutabaga_fence_callback,
183*bb4ee6a4SAndroid Build Coastguard Worker     pub debug_cb: Option<rutabaga_debug_callback>,
184*bb4ee6a4SAndroid Build Coastguard Worker     pub channels: Option<&'a rutabaga_channels>,
185*bb4ee6a4SAndroid Build Coastguard Worker     pub renderer_features: *const c_char,
186*bb4ee6a4SAndroid Build Coastguard Worker }
187*bb4ee6a4SAndroid Build Coastguard Worker 
create_ffi_fence_handler( user_data: u64, fence_cb: rutabaga_fence_callback, ) -> RutabagaFenceHandler188*bb4ee6a4SAndroid Build Coastguard Worker fn create_ffi_fence_handler(
189*bb4ee6a4SAndroid Build Coastguard Worker     user_data: u64,
190*bb4ee6a4SAndroid Build Coastguard Worker     fence_cb: rutabaga_fence_callback,
191*bb4ee6a4SAndroid Build Coastguard Worker ) -> RutabagaFenceHandler {
192*bb4ee6a4SAndroid Build Coastguard Worker     RutabagaFenceHandler::new(move |completed_fence| fence_cb(user_data, &completed_fence))
193*bb4ee6a4SAndroid Build Coastguard Worker }
194*bb4ee6a4SAndroid Build Coastguard Worker 
create_ffi_debug_handler( user_data: u64, debug_cb: rutabaga_debug_callback, ) -> RutabagaDebugHandler195*bb4ee6a4SAndroid Build Coastguard Worker fn create_ffi_debug_handler(
196*bb4ee6a4SAndroid Build Coastguard Worker     user_data: u64,
197*bb4ee6a4SAndroid Build Coastguard Worker     debug_cb: rutabaga_debug_callback,
198*bb4ee6a4SAndroid Build Coastguard Worker ) -> RutabagaDebugHandler {
199*bb4ee6a4SAndroid Build Coastguard Worker     RutabagaDebugHandler::new(move |rutabaga_debug| debug_cb(user_data, &rutabaga_debug))
200*bb4ee6a4SAndroid Build Coastguard Worker }
201*bb4ee6a4SAndroid Build Coastguard Worker 
202*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
203*bb4ee6a4SAndroid Build Coastguard Worker /// # Safety
204*bb4ee6a4SAndroid Build Coastguard Worker /// - `capset_names` must be a null-terminated C-string.
rutabaga_calculate_capset_mask( capset_names: *const c_char, capset_mask: &mut u64, ) -> i32205*bb4ee6a4SAndroid Build Coastguard Worker pub unsafe extern "C" fn rutabaga_calculate_capset_mask(
206*bb4ee6a4SAndroid Build Coastguard Worker     capset_names: *const c_char,
207*bb4ee6a4SAndroid Build Coastguard Worker     capset_mask: &mut u64,
208*bb4ee6a4SAndroid Build Coastguard Worker ) -> i32 {
209*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
210*bb4ee6a4SAndroid Build Coastguard Worker         if capset_names == null() {
211*bb4ee6a4SAndroid Build Coastguard Worker             return -EINVAL;
212*bb4ee6a4SAndroid Build Coastguard Worker         }
213*bb4ee6a4SAndroid Build Coastguard Worker 
214*bb4ee6a4SAndroid Build Coastguard Worker         let c_str_slice = CStr::from_ptr(capset_names);
215*bb4ee6a4SAndroid Build Coastguard Worker         let result = c_str_slice.to_str();
216*bb4ee6a4SAndroid Build Coastguard Worker         let str_slice = return_on_error!(result);
217*bb4ee6a4SAndroid Build Coastguard Worker         *capset_mask = rutabaga_gfx::calculate_capset_mask(str_slice.split(':'));
218*bb4ee6a4SAndroid Build Coastguard Worker         NO_ERROR
219*bb4ee6a4SAndroid Build Coastguard Worker     }))
220*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
221*bb4ee6a4SAndroid Build Coastguard Worker }
222*bb4ee6a4SAndroid Build Coastguard Worker 
223*bb4ee6a4SAndroid Build Coastguard Worker /// # Safety
224*bb4ee6a4SAndroid Build Coastguard Worker /// - If `(*builder).channels` is not null, the caller must ensure `(*channels).channels` points to
225*bb4ee6a4SAndroid Build Coastguard Worker ///   a valid array of `struct rutabaga_channel` of size `(*channels).num_channels`.
226*bb4ee6a4SAndroid Build Coastguard Worker /// - The `channel_name` field of `struct rutabaga_channel` must be a null-terminated C-string.
227*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_init(builder: &rutabaga_builder, ptr: &mut *mut rutabaga) -> i32228*bb4ee6a4SAndroid Build Coastguard Worker pub unsafe extern "C" fn rutabaga_init(builder: &rutabaga_builder, ptr: &mut *mut rutabaga) -> i32 {
229*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
230*bb4ee6a4SAndroid Build Coastguard Worker         let fence_handler = create_ffi_fence_handler((*builder).user_data, (*builder).fence_cb);
231*bb4ee6a4SAndroid Build Coastguard Worker         let mut debug_handler_opt: Option<RutabagaDebugHandler> = None;
232*bb4ee6a4SAndroid Build Coastguard Worker 
233*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(func) = (*builder).debug_cb {
234*bb4ee6a4SAndroid Build Coastguard Worker             let debug_handler = create_ffi_debug_handler((*builder).user_data, func);
235*bb4ee6a4SAndroid Build Coastguard Worker             S_DEBUG_HANDLER.with(|handler_cell| {
236*bb4ee6a4SAndroid Build Coastguard Worker                 *handler_cell.borrow_mut() = Some(debug_handler.clone());
237*bb4ee6a4SAndroid Build Coastguard Worker             });
238*bb4ee6a4SAndroid Build Coastguard Worker             debug_handler_opt = Some(debug_handler);
239*bb4ee6a4SAndroid Build Coastguard Worker         }
240*bb4ee6a4SAndroid Build Coastguard Worker 
241*bb4ee6a4SAndroid Build Coastguard Worker         let mut rutabaga_channels_opt = None;
242*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(channels) = (*builder).channels {
243*bb4ee6a4SAndroid Build Coastguard Worker             let mut rutabaga_channels: Vec<RutabagaChannel> = Vec::new();
244*bb4ee6a4SAndroid Build Coastguard Worker             let channels_slice = from_raw_parts(channels.channels, channels.num_channels);
245*bb4ee6a4SAndroid Build Coastguard Worker 
246*bb4ee6a4SAndroid Build Coastguard Worker             for channel in channels_slice {
247*bb4ee6a4SAndroid Build Coastguard Worker                 let c_str_slice = CStr::from_ptr(channel.channel_name);
248*bb4ee6a4SAndroid Build Coastguard Worker                 let result = c_str_slice.to_str();
249*bb4ee6a4SAndroid Build Coastguard Worker                 let str_slice = return_on_error!(result);
250*bb4ee6a4SAndroid Build Coastguard Worker                 let string = str_slice.to_owned();
251*bb4ee6a4SAndroid Build Coastguard Worker                 let path = PathBuf::from(&string);
252*bb4ee6a4SAndroid Build Coastguard Worker 
253*bb4ee6a4SAndroid Build Coastguard Worker                 rutabaga_channels.push(RutabagaChannel {
254*bb4ee6a4SAndroid Build Coastguard Worker                     base_channel: path,
255*bb4ee6a4SAndroid Build Coastguard Worker                     channel_type: channel.channel_type,
256*bb4ee6a4SAndroid Build Coastguard Worker                 });
257*bb4ee6a4SAndroid Build Coastguard Worker             }
258*bb4ee6a4SAndroid Build Coastguard Worker 
259*bb4ee6a4SAndroid Build Coastguard Worker             rutabaga_channels_opt = Some(rutabaga_channels);
260*bb4ee6a4SAndroid Build Coastguard Worker         }
261*bb4ee6a4SAndroid Build Coastguard Worker 
262*bb4ee6a4SAndroid Build Coastguard Worker         let mut renderer_features_opt = None;
263*bb4ee6a4SAndroid Build Coastguard Worker         let renderer_features_ptr = (*builder).renderer_features;
264*bb4ee6a4SAndroid Build Coastguard Worker         if !renderer_features_ptr.is_null() {
265*bb4ee6a4SAndroid Build Coastguard Worker             let c_str_slice = CStr::from_ptr(renderer_features_ptr);
266*bb4ee6a4SAndroid Build Coastguard Worker             let result = c_str_slice.to_str();
267*bb4ee6a4SAndroid Build Coastguard Worker             let str_slice = return_on_error!(result);
268*bb4ee6a4SAndroid Build Coastguard Worker             let string = str_slice.to_owned();
269*bb4ee6a4SAndroid Build Coastguard Worker             renderer_features_opt = Some(string);
270*bb4ee6a4SAndroid Build Coastguard Worker         }
271*bb4ee6a4SAndroid Build Coastguard Worker 
272*bb4ee6a4SAndroid Build Coastguard Worker         let mut component_type = RutabagaComponentType::CrossDomain;
273*bb4ee6a4SAndroid Build Coastguard Worker         if (*builder).capset_mask == 0 {
274*bb4ee6a4SAndroid Build Coastguard Worker             component_type = RutabagaComponentType::Rutabaga2D;
275*bb4ee6a4SAndroid Build Coastguard Worker         }
276*bb4ee6a4SAndroid Build Coastguard Worker 
277*bb4ee6a4SAndroid Build Coastguard Worker         let rutabaga_wsi = match (*builder).wsi {
278*bb4ee6a4SAndroid Build Coastguard Worker             RUTABAGA_WSI_SURFACELESS => RutabagaWsi::Surfaceless,
279*bb4ee6a4SAndroid Build Coastguard Worker             _ => return -EINVAL,
280*bb4ee6a4SAndroid Build Coastguard Worker         };
281*bb4ee6a4SAndroid Build Coastguard Worker 
282*bb4ee6a4SAndroid Build Coastguard Worker         let result = RutabagaBuilder::new(component_type, (*builder).capset_mask)
283*bb4ee6a4SAndroid Build Coastguard Worker             .set_use_external_blob(false)
284*bb4ee6a4SAndroid Build Coastguard Worker             .set_use_egl(true)
285*bb4ee6a4SAndroid Build Coastguard Worker             .set_wsi(rutabaga_wsi)
286*bb4ee6a4SAndroid Build Coastguard Worker             .set_debug_handler(debug_handler_opt)
287*bb4ee6a4SAndroid Build Coastguard Worker             .set_rutabaga_channels(rutabaga_channels_opt)
288*bb4ee6a4SAndroid Build Coastguard Worker             .set_renderer_features(renderer_features_opt)
289*bb4ee6a4SAndroid Build Coastguard Worker             .build(fence_handler, None);
290*bb4ee6a4SAndroid Build Coastguard Worker 
291*bb4ee6a4SAndroid Build Coastguard Worker         let rtbg = return_on_error!(result);
292*bb4ee6a4SAndroid Build Coastguard Worker         *ptr = Box::into_raw(Box::new(rtbg)) as _;
293*bb4ee6a4SAndroid Build Coastguard Worker         NO_ERROR
294*bb4ee6a4SAndroid Build Coastguard Worker     }))
295*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
296*bb4ee6a4SAndroid Build Coastguard Worker }
297*bb4ee6a4SAndroid Build Coastguard Worker 
298*bb4ee6a4SAndroid Build Coastguard Worker /// # Safety
299*bb4ee6a4SAndroid Build Coastguard Worker /// - `ptr` must have been created by `rutabaga_init`.
300*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_finish(ptr: &mut *mut rutabaga) -> i32301*bb4ee6a4SAndroid Build Coastguard Worker pub extern "C" fn rutabaga_finish(ptr: &mut *mut rutabaga) -> i32 {
302*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
303*bb4ee6a4SAndroid Build Coastguard Worker         let _ = unsafe { Box::from_raw(*ptr) };
304*bb4ee6a4SAndroid Build Coastguard Worker         *ptr = null_mut();
305*bb4ee6a4SAndroid Build Coastguard Worker         NO_ERROR
306*bb4ee6a4SAndroid Build Coastguard Worker     }))
307*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
308*bb4ee6a4SAndroid Build Coastguard Worker }
309*bb4ee6a4SAndroid Build Coastguard Worker 
310*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_get_num_capsets(ptr: &mut rutabaga, num_capsets: &mut u32) -> i32311*bb4ee6a4SAndroid Build Coastguard Worker pub extern "C" fn rutabaga_get_num_capsets(ptr: &mut rutabaga, num_capsets: &mut u32) -> i32 {
312*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
313*bb4ee6a4SAndroid Build Coastguard Worker         *num_capsets = ptr.get_num_capsets();
314*bb4ee6a4SAndroid Build Coastguard Worker         NO_ERROR
315*bb4ee6a4SAndroid Build Coastguard Worker     }))
316*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
317*bb4ee6a4SAndroid Build Coastguard Worker }
318*bb4ee6a4SAndroid Build Coastguard Worker 
319*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_get_capset_info( ptr: &mut rutabaga, capset_index: u32, capset_id: &mut u32, capset_version: &mut u32, capset_size: &mut u32, ) -> i32320*bb4ee6a4SAndroid Build Coastguard Worker pub extern "C" fn rutabaga_get_capset_info(
321*bb4ee6a4SAndroid Build Coastguard Worker     ptr: &mut rutabaga,
322*bb4ee6a4SAndroid Build Coastguard Worker     capset_index: u32,
323*bb4ee6a4SAndroid Build Coastguard Worker     capset_id: &mut u32,
324*bb4ee6a4SAndroid Build Coastguard Worker     capset_version: &mut u32,
325*bb4ee6a4SAndroid Build Coastguard Worker     capset_size: &mut u32,
326*bb4ee6a4SAndroid Build Coastguard Worker ) -> i32 {
327*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
328*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.get_capset_info(capset_index);
329*bb4ee6a4SAndroid Build Coastguard Worker         let info = return_on_error!(result);
330*bb4ee6a4SAndroid Build Coastguard Worker         *capset_id = info.0;
331*bb4ee6a4SAndroid Build Coastguard Worker         *capset_version = info.1;
332*bb4ee6a4SAndroid Build Coastguard Worker         *capset_size = info.2;
333*bb4ee6a4SAndroid Build Coastguard Worker         NO_ERROR
334*bb4ee6a4SAndroid Build Coastguard Worker     }))
335*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
336*bb4ee6a4SAndroid Build Coastguard Worker }
337*bb4ee6a4SAndroid Build Coastguard Worker 
338*bb4ee6a4SAndroid Build Coastguard Worker /// # Safety
339*bb4ee6a4SAndroid Build Coastguard Worker /// - `capset` must point an array of bytes of size `capset_size`.
340*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_get_capset( ptr: &mut rutabaga, capset_id: u32, version: u32, capset: *mut u8, capset_size: u32, ) -> i32341*bb4ee6a4SAndroid Build Coastguard Worker pub unsafe extern "C" fn rutabaga_get_capset(
342*bb4ee6a4SAndroid Build Coastguard Worker     ptr: &mut rutabaga,
343*bb4ee6a4SAndroid Build Coastguard Worker     capset_id: u32,
344*bb4ee6a4SAndroid Build Coastguard Worker     version: u32,
345*bb4ee6a4SAndroid Build Coastguard Worker     capset: *mut u8,
346*bb4ee6a4SAndroid Build Coastguard Worker     capset_size: u32,
347*bb4ee6a4SAndroid Build Coastguard Worker ) -> i32 {
348*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
349*bb4ee6a4SAndroid Build Coastguard Worker         let size: usize = capset_size.try_into().map_err(|_e| -EINVAL).unwrap();
350*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.get_capset(capset_id, version);
351*bb4ee6a4SAndroid Build Coastguard Worker         let vec = return_on_error!(result);
352*bb4ee6a4SAndroid Build Coastguard Worker         copy_nonoverlapping(vec.as_ptr(), capset, size);
353*bb4ee6a4SAndroid Build Coastguard Worker         NO_ERROR
354*bb4ee6a4SAndroid Build Coastguard Worker     }))
355*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
356*bb4ee6a4SAndroid Build Coastguard Worker }
357*bb4ee6a4SAndroid Build Coastguard Worker 
358*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_context_create( ptr: &mut rutabaga, ctx_id: u32, context_init: u32, context_name: *const c_char, context_name_len: u32, ) -> i32359*bb4ee6a4SAndroid Build Coastguard Worker pub extern "C" fn rutabaga_context_create(
360*bb4ee6a4SAndroid Build Coastguard Worker     ptr: &mut rutabaga,
361*bb4ee6a4SAndroid Build Coastguard Worker     ctx_id: u32,
362*bb4ee6a4SAndroid Build Coastguard Worker     context_init: u32,
363*bb4ee6a4SAndroid Build Coastguard Worker     context_name: *const c_char,
364*bb4ee6a4SAndroid Build Coastguard Worker     context_name_len: u32,
365*bb4ee6a4SAndroid Build Coastguard Worker ) -> i32 {
366*bb4ee6a4SAndroid Build Coastguard Worker     let mut name: Option<&str> = None;
367*bb4ee6a4SAndroid Build Coastguard Worker     if !context_name.is_null() && context_name_len > 0 {
368*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because context_name is not NULL and len is a positive integer, so the caller
369*bb4ee6a4SAndroid Build Coastguard Worker         // is expected to provide a valid pointer to an array of bytes at least as long as the
370*bb4ee6a4SAndroid Build Coastguard Worker         // passed length. If the provided byte array doesn't contain valid utf-8, name will be
371*bb4ee6a4SAndroid Build Coastguard Worker         // None.
372*bb4ee6a4SAndroid Build Coastguard Worker         let view = unsafe {
373*bb4ee6a4SAndroid Build Coastguard Worker             std::slice::from_raw_parts(context_name as *const u8, context_name_len as usize)
374*bb4ee6a4SAndroid Build Coastguard Worker         };
375*bb4ee6a4SAndroid Build Coastguard Worker         name = std::str::from_utf8(view).ok();
376*bb4ee6a4SAndroid Build Coastguard Worker     }
377*bb4ee6a4SAndroid Build Coastguard Worker 
378*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
379*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.create_context(ctx_id, context_init, name);
380*bb4ee6a4SAndroid Build Coastguard Worker         return_result(result)
381*bb4ee6a4SAndroid Build Coastguard Worker     }))
382*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
383*bb4ee6a4SAndroid Build Coastguard Worker }
384*bb4ee6a4SAndroid Build Coastguard Worker 
385*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_context_destroy(ptr: &mut rutabaga, ctx_id: u32) -> i32386*bb4ee6a4SAndroid Build Coastguard Worker pub extern "C" fn rutabaga_context_destroy(ptr: &mut rutabaga, ctx_id: u32) -> i32 {
387*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
388*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.destroy_context(ctx_id);
389*bb4ee6a4SAndroid Build Coastguard Worker         return_result(result)
390*bb4ee6a4SAndroid Build Coastguard Worker     }))
391*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
392*bb4ee6a4SAndroid Build Coastguard Worker }
393*bb4ee6a4SAndroid Build Coastguard Worker 
394*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_context_attach_resource( ptr: &mut rutabaga, ctx_id: u32, resource_id: u32, ) -> i32395*bb4ee6a4SAndroid Build Coastguard Worker pub extern "C" fn rutabaga_context_attach_resource(
396*bb4ee6a4SAndroid Build Coastguard Worker     ptr: &mut rutabaga,
397*bb4ee6a4SAndroid Build Coastguard Worker     ctx_id: u32,
398*bb4ee6a4SAndroid Build Coastguard Worker     resource_id: u32,
399*bb4ee6a4SAndroid Build Coastguard Worker ) -> i32 {
400*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
401*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.context_attach_resource(ctx_id, resource_id);
402*bb4ee6a4SAndroid Build Coastguard Worker         return_result(result)
403*bb4ee6a4SAndroid Build Coastguard Worker     }))
404*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
405*bb4ee6a4SAndroid Build Coastguard Worker }
406*bb4ee6a4SAndroid Build Coastguard Worker 
407*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_context_detach_resource( ptr: &mut rutabaga, ctx_id: u32, resource_id: u32, ) -> i32408*bb4ee6a4SAndroid Build Coastguard Worker pub extern "C" fn rutabaga_context_detach_resource(
409*bb4ee6a4SAndroid Build Coastguard Worker     ptr: &mut rutabaga,
410*bb4ee6a4SAndroid Build Coastguard Worker     ctx_id: u32,
411*bb4ee6a4SAndroid Build Coastguard Worker     resource_id: u32,
412*bb4ee6a4SAndroid Build Coastguard Worker ) -> i32 {
413*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
414*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.context_detach_resource(ctx_id, resource_id);
415*bb4ee6a4SAndroid Build Coastguard Worker         return_result(result)
416*bb4ee6a4SAndroid Build Coastguard Worker     }))
417*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
418*bb4ee6a4SAndroid Build Coastguard Worker }
419*bb4ee6a4SAndroid Build Coastguard Worker 
420*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_resource_create_3d( ptr: &mut rutabaga, resource_id: u32, create_3d: &rutabaga_create_3d, ) -> i32421*bb4ee6a4SAndroid Build Coastguard Worker pub extern "C" fn rutabaga_resource_create_3d(
422*bb4ee6a4SAndroid Build Coastguard Worker     ptr: &mut rutabaga,
423*bb4ee6a4SAndroid Build Coastguard Worker     resource_id: u32,
424*bb4ee6a4SAndroid Build Coastguard Worker     create_3d: &rutabaga_create_3d,
425*bb4ee6a4SAndroid Build Coastguard Worker ) -> i32 {
426*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
427*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.resource_create_3d(resource_id, *create_3d);
428*bb4ee6a4SAndroid Build Coastguard Worker         return_result(result)
429*bb4ee6a4SAndroid Build Coastguard Worker     }))
430*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
431*bb4ee6a4SAndroid Build Coastguard Worker }
432*bb4ee6a4SAndroid Build Coastguard Worker 
433*bb4ee6a4SAndroid Build Coastguard Worker /// # Safety
434*bb4ee6a4SAndroid Build Coastguard Worker /// - If `iovecs` is not null, the caller must ensure `(*iovecs).iovecs` points to a valid array of
435*bb4ee6a4SAndroid Build Coastguard Worker ///   iovecs of size `(*iovecs).num_iovecs`.
436*bb4ee6a4SAndroid Build Coastguard Worker /// - Each iovec must point to valid memory starting at `iov_base` with length `iov_len`.
437*bb4ee6a4SAndroid Build Coastguard Worker /// - Each iovec must valid until the resource's backing is explictly detached or the resource is is
438*bb4ee6a4SAndroid Build Coastguard Worker ///   unreferenced.
439*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_resource_attach_backing( ptr: &mut rutabaga, resource_id: u32, iovecs: &rutabaga_iovecs, ) -> i32440*bb4ee6a4SAndroid Build Coastguard Worker pub unsafe extern "C" fn rutabaga_resource_attach_backing(
441*bb4ee6a4SAndroid Build Coastguard Worker     ptr: &mut rutabaga,
442*bb4ee6a4SAndroid Build Coastguard Worker     resource_id: u32,
443*bb4ee6a4SAndroid Build Coastguard Worker     iovecs: &rutabaga_iovecs,
444*bb4ee6a4SAndroid Build Coastguard Worker ) -> i32 {
445*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
446*bb4ee6a4SAndroid Build Coastguard Worker         let slice = from_raw_parts((*iovecs).iovecs, (*iovecs).num_iovecs);
447*bb4ee6a4SAndroid Build Coastguard Worker         let vecs = slice
448*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
449*bb4ee6a4SAndroid Build Coastguard Worker             .map(|iov| RutabagaIovec {
450*bb4ee6a4SAndroid Build Coastguard Worker                 base: iov.iov_base,
451*bb4ee6a4SAndroid Build Coastguard Worker                 len: iov.iov_len,
452*bb4ee6a4SAndroid Build Coastguard Worker             })
453*bb4ee6a4SAndroid Build Coastguard Worker             .collect();
454*bb4ee6a4SAndroid Build Coastguard Worker 
455*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.attach_backing(resource_id, vecs);
456*bb4ee6a4SAndroid Build Coastguard Worker         return_result(result)
457*bb4ee6a4SAndroid Build Coastguard Worker     }))
458*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
459*bb4ee6a4SAndroid Build Coastguard Worker }
460*bb4ee6a4SAndroid Build Coastguard Worker 
461*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_resource_detach_backing(ptr: &mut rutabaga, resource_id: u32) -> i32462*bb4ee6a4SAndroid Build Coastguard Worker pub extern "C" fn rutabaga_resource_detach_backing(ptr: &mut rutabaga, resource_id: u32) -> i32 {
463*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
464*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.detach_backing(resource_id);
465*bb4ee6a4SAndroid Build Coastguard Worker         return_result(result)
466*bb4ee6a4SAndroid Build Coastguard Worker     }))
467*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
468*bb4ee6a4SAndroid Build Coastguard Worker }
469*bb4ee6a4SAndroid Build Coastguard Worker 
470*bb4ee6a4SAndroid Build Coastguard Worker /// # Safety
471*bb4ee6a4SAndroid Build Coastguard Worker /// - If `iovecs` is not null, the caller must ensure `(*iovecs).iovecs` points to a valid array of
472*bb4ee6a4SAndroid Build Coastguard Worker ///   iovecs of size `(*iovecs).num_iovecs`.
473*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_resource_transfer_read( ptr: &mut rutabaga, ctx_id: u32, resource_id: u32, transfer: &rutabaga_transfer, buf: Option<&iovec>, ) -> i32474*bb4ee6a4SAndroid Build Coastguard Worker pub unsafe extern "C" fn rutabaga_resource_transfer_read(
475*bb4ee6a4SAndroid Build Coastguard Worker     ptr: &mut rutabaga,
476*bb4ee6a4SAndroid Build Coastguard Worker     ctx_id: u32,
477*bb4ee6a4SAndroid Build Coastguard Worker     resource_id: u32,
478*bb4ee6a4SAndroid Build Coastguard Worker     transfer: &rutabaga_transfer,
479*bb4ee6a4SAndroid Build Coastguard Worker     buf: Option<&iovec>,
480*bb4ee6a4SAndroid Build Coastguard Worker ) -> i32 {
481*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
482*bb4ee6a4SAndroid Build Coastguard Worker         let mut slice_opt = None;
483*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(iovec) = buf {
484*bb4ee6a4SAndroid Build Coastguard Worker             slice_opt = Some(IoSliceMut::new(std::slice::from_raw_parts_mut(
485*bb4ee6a4SAndroid Build Coastguard Worker                 iovec.iov_base as *mut u8,
486*bb4ee6a4SAndroid Build Coastguard Worker                 iovec.iov_len,
487*bb4ee6a4SAndroid Build Coastguard Worker             )));
488*bb4ee6a4SAndroid Build Coastguard Worker         }
489*bb4ee6a4SAndroid Build Coastguard Worker 
490*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.transfer_read(ctx_id, resource_id, *transfer, slice_opt);
491*bb4ee6a4SAndroid Build Coastguard Worker         return_result(result)
492*bb4ee6a4SAndroid Build Coastguard Worker     }))
493*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
494*bb4ee6a4SAndroid Build Coastguard Worker }
495*bb4ee6a4SAndroid Build Coastguard Worker 
496*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_resource_transfer_write( ptr: &mut rutabaga, ctx_id: u32, resource_id: u32, transfer: &rutabaga_transfer, ) -> i32497*bb4ee6a4SAndroid Build Coastguard Worker pub extern "C" fn rutabaga_resource_transfer_write(
498*bb4ee6a4SAndroid Build Coastguard Worker     ptr: &mut rutabaga,
499*bb4ee6a4SAndroid Build Coastguard Worker     ctx_id: u32,
500*bb4ee6a4SAndroid Build Coastguard Worker     resource_id: u32,
501*bb4ee6a4SAndroid Build Coastguard Worker     transfer: &rutabaga_transfer,
502*bb4ee6a4SAndroid Build Coastguard Worker ) -> i32 {
503*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
504*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.transfer_write(ctx_id, resource_id, *transfer);
505*bb4ee6a4SAndroid Build Coastguard Worker         return_result(result)
506*bb4ee6a4SAndroid Build Coastguard Worker     }))
507*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
508*bb4ee6a4SAndroid Build Coastguard Worker }
509*bb4ee6a4SAndroid Build Coastguard Worker 
510*bb4ee6a4SAndroid Build Coastguard Worker /// # Safety
511*bb4ee6a4SAndroid Build Coastguard Worker /// - If `iovecs` is not null, the caller must ensure `(*iovecs).iovecs` points to a valid array of
512*bb4ee6a4SAndroid Build Coastguard Worker ///   iovecs of size `(*iovecs).num_iovecs`.
513*bb4ee6a4SAndroid Build Coastguard Worker /// - If `handle` is not null, the caller must ensure it is a valid OS-descriptor.  Ownership is
514*bb4ee6a4SAndroid Build Coastguard Worker ///   transfered to rutabaga.
515*bb4ee6a4SAndroid Build Coastguard Worker /// - Each iovec must valid until the resource's backing is explictly detached or the resource is is
516*bb4ee6a4SAndroid Build Coastguard Worker ///   unreferenced.
517*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_resource_create_blob( ptr: &mut rutabaga, ctx_id: u32, resource_id: u32, create_blob: &rutabaga_create_blob, iovecs: Option<&rutabaga_iovecs>, handle: Option<&rutabaga_handle>, ) -> i32518*bb4ee6a4SAndroid Build Coastguard Worker pub unsafe extern "C" fn rutabaga_resource_create_blob(
519*bb4ee6a4SAndroid Build Coastguard Worker     ptr: &mut rutabaga,
520*bb4ee6a4SAndroid Build Coastguard Worker     ctx_id: u32,
521*bb4ee6a4SAndroid Build Coastguard Worker     resource_id: u32,
522*bb4ee6a4SAndroid Build Coastguard Worker     create_blob: &rutabaga_create_blob,
523*bb4ee6a4SAndroid Build Coastguard Worker     iovecs: Option<&rutabaga_iovecs>,
524*bb4ee6a4SAndroid Build Coastguard Worker     handle: Option<&rutabaga_handle>,
525*bb4ee6a4SAndroid Build Coastguard Worker ) -> i32 {
526*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
527*bb4ee6a4SAndroid Build Coastguard Worker         let mut iovecs_opt: Option<Vec<RutabagaIovec>> = None;
528*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(iovs) = iovecs {
529*bb4ee6a4SAndroid Build Coastguard Worker             let slice = if iovs.num_iovecs != 0 {
530*bb4ee6a4SAndroid Build Coastguard Worker                 from_raw_parts(iovs.iovecs, iovs.num_iovecs)
531*bb4ee6a4SAndroid Build Coastguard Worker             } else {
532*bb4ee6a4SAndroid Build Coastguard Worker                 &[]
533*bb4ee6a4SAndroid Build Coastguard Worker             };
534*bb4ee6a4SAndroid Build Coastguard Worker             let vecs = slice
535*bb4ee6a4SAndroid Build Coastguard Worker                 .iter()
536*bb4ee6a4SAndroid Build Coastguard Worker                 .map(|iov| RutabagaIovec {
537*bb4ee6a4SAndroid Build Coastguard Worker                     base: iov.iov_base,
538*bb4ee6a4SAndroid Build Coastguard Worker                     len: iov.iov_len,
539*bb4ee6a4SAndroid Build Coastguard Worker                 })
540*bb4ee6a4SAndroid Build Coastguard Worker                 .collect();
541*bb4ee6a4SAndroid Build Coastguard Worker             iovecs_opt = Some(vecs);
542*bb4ee6a4SAndroid Build Coastguard Worker         }
543*bb4ee6a4SAndroid Build Coastguard Worker 
544*bb4ee6a4SAndroid Build Coastguard Worker         let mut handle_opt: Option<RutabagaHandle> = None;
545*bb4ee6a4SAndroid Build Coastguard Worker 
546*bb4ee6a4SAndroid Build Coastguard Worker         // Only needed on Unix, since there is no way to create a handle from guest memory on
547*bb4ee6a4SAndroid Build Coastguard Worker         // Windows.
548*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(unix)]
549*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(hnd) = handle {
550*bb4ee6a4SAndroid Build Coastguard Worker             handle_opt = Some(RutabagaHandle {
551*bb4ee6a4SAndroid Build Coastguard Worker                 os_handle: RutabagaDescriptor::from_raw_descriptor(
552*bb4ee6a4SAndroid Build Coastguard Worker                     (*hnd).os_handle.try_into().unwrap(),
553*bb4ee6a4SAndroid Build Coastguard Worker                 ),
554*bb4ee6a4SAndroid Build Coastguard Worker                 handle_type: (*hnd).handle_type,
555*bb4ee6a4SAndroid Build Coastguard Worker             });
556*bb4ee6a4SAndroid Build Coastguard Worker         }
557*bb4ee6a4SAndroid Build Coastguard Worker 
558*bb4ee6a4SAndroid Build Coastguard Worker         let result =
559*bb4ee6a4SAndroid Build Coastguard Worker             ptr.resource_create_blob(ctx_id, resource_id, *create_blob, iovecs_opt, handle_opt);
560*bb4ee6a4SAndroid Build Coastguard Worker 
561*bb4ee6a4SAndroid Build Coastguard Worker         return_result(result)
562*bb4ee6a4SAndroid Build Coastguard Worker     }))
563*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
564*bb4ee6a4SAndroid Build Coastguard Worker }
565*bb4ee6a4SAndroid Build Coastguard Worker 
566*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_resource_unref(ptr: &mut rutabaga, resource_id: u32) -> i32567*bb4ee6a4SAndroid Build Coastguard Worker pub extern "C" fn rutabaga_resource_unref(ptr: &mut rutabaga, resource_id: u32) -> i32 {
568*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
569*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.unref_resource(resource_id);
570*bb4ee6a4SAndroid Build Coastguard Worker         return_result(result)
571*bb4ee6a4SAndroid Build Coastguard Worker     }))
572*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
573*bb4ee6a4SAndroid Build Coastguard Worker }
574*bb4ee6a4SAndroid Build Coastguard Worker 
575*bb4ee6a4SAndroid Build Coastguard Worker /// # Safety
576*bb4ee6a4SAndroid Build Coastguard Worker /// Caller owns raw descriptor on success and is responsible for closing it.
577*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_resource_export_blob( ptr: &mut rutabaga, resource_id: u32, handle: &mut rutabaga_handle, ) -> i32578*bb4ee6a4SAndroid Build Coastguard Worker pub extern "C" fn rutabaga_resource_export_blob(
579*bb4ee6a4SAndroid Build Coastguard Worker     ptr: &mut rutabaga,
580*bb4ee6a4SAndroid Build Coastguard Worker     resource_id: u32,
581*bb4ee6a4SAndroid Build Coastguard Worker     handle: &mut rutabaga_handle,
582*bb4ee6a4SAndroid Build Coastguard Worker ) -> i32 {
583*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
584*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.export_blob(resource_id);
585*bb4ee6a4SAndroid Build Coastguard Worker         let hnd = return_on_error!(result);
586*bb4ee6a4SAndroid Build Coastguard Worker 
587*bb4ee6a4SAndroid Build Coastguard Worker         (*handle).handle_type = hnd.handle_type;
588*bb4ee6a4SAndroid Build Coastguard Worker         (*handle).os_handle = hnd.os_handle.into_raw_descriptor() as i64;
589*bb4ee6a4SAndroid Build Coastguard Worker         NO_ERROR
590*bb4ee6a4SAndroid Build Coastguard Worker     }))
591*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
592*bb4ee6a4SAndroid Build Coastguard Worker }
593*bb4ee6a4SAndroid Build Coastguard Worker 
594*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_resource_map( ptr: &mut rutabaga, resource_id: u32, mapping: &mut rutabaga_mapping, ) -> i32595*bb4ee6a4SAndroid Build Coastguard Worker pub extern "C" fn rutabaga_resource_map(
596*bb4ee6a4SAndroid Build Coastguard Worker     ptr: &mut rutabaga,
597*bb4ee6a4SAndroid Build Coastguard Worker     resource_id: u32,
598*bb4ee6a4SAndroid Build Coastguard Worker     mapping: &mut rutabaga_mapping,
599*bb4ee6a4SAndroid Build Coastguard Worker ) -> i32 {
600*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
601*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.map(resource_id);
602*bb4ee6a4SAndroid Build Coastguard Worker         let internal_map = return_on_error!(result);
603*bb4ee6a4SAndroid Build Coastguard Worker         (*mapping).ptr = internal_map.ptr as *mut c_void;
604*bb4ee6a4SAndroid Build Coastguard Worker         (*mapping).size = internal_map.size;
605*bb4ee6a4SAndroid Build Coastguard Worker         NO_ERROR
606*bb4ee6a4SAndroid Build Coastguard Worker     }))
607*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
608*bb4ee6a4SAndroid Build Coastguard Worker }
609*bb4ee6a4SAndroid Build Coastguard Worker 
610*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_resource_unmap(ptr: &mut rutabaga, resource_id: u32) -> i32611*bb4ee6a4SAndroid Build Coastguard Worker pub extern "C" fn rutabaga_resource_unmap(ptr: &mut rutabaga, resource_id: u32) -> i32 {
612*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
613*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.unmap(resource_id);
614*bb4ee6a4SAndroid Build Coastguard Worker         return_result(result)
615*bb4ee6a4SAndroid Build Coastguard Worker     }))
616*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
617*bb4ee6a4SAndroid Build Coastguard Worker }
618*bb4ee6a4SAndroid Build Coastguard Worker 
619*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_resource_map_info( ptr: &mut rutabaga, resource_id: u32, map_info: &mut u32, ) -> i32620*bb4ee6a4SAndroid Build Coastguard Worker pub extern "C" fn rutabaga_resource_map_info(
621*bb4ee6a4SAndroid Build Coastguard Worker     ptr: &mut rutabaga,
622*bb4ee6a4SAndroid Build Coastguard Worker     resource_id: u32,
623*bb4ee6a4SAndroid Build Coastguard Worker     map_info: &mut u32,
624*bb4ee6a4SAndroid Build Coastguard Worker ) -> i32 {
625*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
626*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.map_info(resource_id);
627*bb4ee6a4SAndroid Build Coastguard Worker         *map_info = return_on_error!(result);
628*bb4ee6a4SAndroid Build Coastguard Worker         NO_ERROR
629*bb4ee6a4SAndroid Build Coastguard Worker     }))
630*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
631*bb4ee6a4SAndroid Build Coastguard Worker }
632*bb4ee6a4SAndroid Build Coastguard Worker 
633*bb4ee6a4SAndroid Build Coastguard Worker /// # Safety
634*bb4ee6a4SAndroid Build Coastguard Worker /// - `commands` must point to a contiguous memory region of `size` bytes.
635*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_submit_command( ptr: &mut rutabaga, cmd: &rutabaga_command, ) -> i32636*bb4ee6a4SAndroid Build Coastguard Worker pub unsafe extern "C" fn rutabaga_submit_command(
637*bb4ee6a4SAndroid Build Coastguard Worker     ptr: &mut rutabaga,
638*bb4ee6a4SAndroid Build Coastguard Worker     cmd: &rutabaga_command,
639*bb4ee6a4SAndroid Build Coastguard Worker ) -> i32 {
640*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
641*bb4ee6a4SAndroid Build Coastguard Worker         let cmd_slice = if cmd.cmd_size != 0 {
642*bb4ee6a4SAndroid Build Coastguard Worker             from_raw_parts_mut(cmd.cmd, cmd.cmd_size as usize)
643*bb4ee6a4SAndroid Build Coastguard Worker         } else {
644*bb4ee6a4SAndroid Build Coastguard Worker             &mut []
645*bb4ee6a4SAndroid Build Coastguard Worker         };
646*bb4ee6a4SAndroid Build Coastguard Worker         let fence_ids = if cmd.num_in_fences != 0 {
647*bb4ee6a4SAndroid Build Coastguard Worker             from_raw_parts(cmd.fence_ids, cmd.num_in_fences as usize)
648*bb4ee6a4SAndroid Build Coastguard Worker         } else {
649*bb4ee6a4SAndroid Build Coastguard Worker             &mut []
650*bb4ee6a4SAndroid Build Coastguard Worker         };
651*bb4ee6a4SAndroid Build Coastguard Worker 
652*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.submit_command(cmd.ctx_id, cmd_slice, fence_ids);
653*bb4ee6a4SAndroid Build Coastguard Worker         return_result(result)
654*bb4ee6a4SAndroid Build Coastguard Worker     }))
655*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
656*bb4ee6a4SAndroid Build Coastguard Worker }
657*bb4ee6a4SAndroid Build Coastguard Worker 
658*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_create_fence(ptr: &mut rutabaga, fence: &rutabaga_fence) -> i32659*bb4ee6a4SAndroid Build Coastguard Worker pub extern "C" fn rutabaga_create_fence(ptr: &mut rutabaga, fence: &rutabaga_fence) -> i32 {
660*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
661*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.create_fence(*fence);
662*bb4ee6a4SAndroid Build Coastguard Worker         return_result(result)
663*bb4ee6a4SAndroid Build Coastguard Worker     }))
664*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
665*bb4ee6a4SAndroid Build Coastguard Worker }
666*bb4ee6a4SAndroid Build Coastguard Worker 
667*bb4ee6a4SAndroid Build Coastguard Worker /// # Safety
668*bb4ee6a4SAndroid Build Coastguard Worker /// - `dir` must be a null-terminated C-string.
669*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_snapshot(ptr: &mut rutabaga, dir: *const c_char) -> i32670*bb4ee6a4SAndroid Build Coastguard Worker pub unsafe extern "C" fn rutabaga_snapshot(ptr: &mut rutabaga, dir: *const c_char) -> i32 {
671*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
672*bb4ee6a4SAndroid Build Coastguard Worker         let c_str_slice = CStr::from_ptr(dir);
673*bb4ee6a4SAndroid Build Coastguard Worker 
674*bb4ee6a4SAndroid Build Coastguard Worker         let result = c_str_slice.to_str();
675*bb4ee6a4SAndroid Build Coastguard Worker         let directory = return_on_error!(result);
676*bb4ee6a4SAndroid Build Coastguard Worker 
677*bb4ee6a4SAndroid Build Coastguard Worker         let file = return_on_io_error!(File::create(Path::new(directory).join("snapshot")));
678*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.snapshot(&mut std::io::BufWriter::new(file), directory);
679*bb4ee6a4SAndroid Build Coastguard Worker         return_result(result)
680*bb4ee6a4SAndroid Build Coastguard Worker     }))
681*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
682*bb4ee6a4SAndroid Build Coastguard Worker }
683*bb4ee6a4SAndroid Build Coastguard Worker 
684*bb4ee6a4SAndroid Build Coastguard Worker /// # Safety
685*bb4ee6a4SAndroid Build Coastguard Worker /// - `dir` must be a null-terminated C-string.
686*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_restore(ptr: &mut rutabaga, dir: *const c_char) -> i32687*bb4ee6a4SAndroid Build Coastguard Worker pub unsafe extern "C" fn rutabaga_restore(ptr: &mut rutabaga, dir: *const c_char) -> i32 {
688*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
689*bb4ee6a4SAndroid Build Coastguard Worker         let c_str_slice = CStr::from_ptr(dir);
690*bb4ee6a4SAndroid Build Coastguard Worker 
691*bb4ee6a4SAndroid Build Coastguard Worker         let result = c_str_slice.to_str();
692*bb4ee6a4SAndroid Build Coastguard Worker         let directory = return_on_error!(result);
693*bb4ee6a4SAndroid Build Coastguard Worker 
694*bb4ee6a4SAndroid Build Coastguard Worker         let file = return_on_io_error!(File::open(Path::new(directory).join("snapshot")));
695*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.restore(&mut std::io::BufReader::new(file), directory);
696*bb4ee6a4SAndroid Build Coastguard Worker         return_result(result)
697*bb4ee6a4SAndroid Build Coastguard Worker     }))
698*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
699*bb4ee6a4SAndroid Build Coastguard Worker }
700*bb4ee6a4SAndroid Build Coastguard Worker 
701*bb4ee6a4SAndroid Build Coastguard Worker #[no_mangle]
rutabaga_resource_wait_sync(ptr: &mut rutabaga, resource_id: u32) -> i32702*bb4ee6a4SAndroid Build Coastguard Worker pub extern "C" fn rutabaga_resource_wait_sync(ptr: &mut rutabaga, resource_id: u32) -> i32 {
703*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(AssertUnwindSafe(|| {
704*bb4ee6a4SAndroid Build Coastguard Worker         let result = ptr.wait_sync(resource_id);
705*bb4ee6a4SAndroid Build Coastguard Worker         return_result(result)
706*bb4ee6a4SAndroid Build Coastguard Worker     }))
707*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or(-ESRCH)
708*bb4ee6a4SAndroid Build Coastguard Worker }
709