xref: /aosp_15_r20/external/crosvm/rutabaga_gfx/src/virgl_renderer.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2020 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 //! virgl_renderer: Handles 3D virtio-gpu hypercalls using virglrenderer.
6*bb4ee6a4SAndroid Build Coastguard Worker //! External code found at <https://gitlab.freedesktop.org/virgl/virglrenderer/>.
7*bb4ee6a4SAndroid Build Coastguard Worker 
8*bb4ee6a4SAndroid Build Coastguard Worker #![cfg(feature = "virgl_renderer")]
9*bb4ee6a4SAndroid Build Coastguard Worker 
10*bb4ee6a4SAndroid Build Coastguard Worker use std::cmp::min;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Error as SysError;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::io::IoSliceMut;
13*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::size_of;
14*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::transmute;
15*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::ManuallyDrop;
16*bb4ee6a4SAndroid Build Coastguard Worker use std::os::raw::c_char;
17*bb4ee6a4SAndroid Build Coastguard Worker use std::os::raw::c_int;
18*bb4ee6a4SAndroid Build Coastguard Worker use std::os::raw::c_void;
19*bb4ee6a4SAndroid Build Coastguard Worker use std::panic::catch_unwind;
20*bb4ee6a4SAndroid Build Coastguard Worker use std::process::abort;
21*bb4ee6a4SAndroid Build Coastguard Worker use std::ptr::null_mut;
22*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::atomic::AtomicBool;
23*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::atomic::Ordering;
24*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
25*bb4ee6a4SAndroid Build Coastguard Worker 
26*bb4ee6a4SAndroid Build Coastguard Worker use log::debug;
27*bb4ee6a4SAndroid Build Coastguard Worker use log::error;
28*bb4ee6a4SAndroid Build Coastguard Worker use log::warn;
29*bb4ee6a4SAndroid Build Coastguard Worker 
30*bb4ee6a4SAndroid Build Coastguard Worker use crate::generated::virgl_debug_callback_bindings::*;
31*bb4ee6a4SAndroid Build Coastguard Worker use crate::generated::virgl_renderer_bindings::*;
32*bb4ee6a4SAndroid Build Coastguard Worker use crate::renderer_utils::*;
33*bb4ee6a4SAndroid Build Coastguard Worker use crate::rutabaga_core::RutabagaComponent;
34*bb4ee6a4SAndroid Build Coastguard Worker use crate::rutabaga_core::RutabagaContext;
35*bb4ee6a4SAndroid Build Coastguard Worker use crate::rutabaga_core::RutabagaResource;
36*bb4ee6a4SAndroid Build Coastguard Worker use crate::rutabaga_os::FromRawDescriptor;
37*bb4ee6a4SAndroid Build Coastguard Worker use crate::rutabaga_os::IntoRawDescriptor;
38*bb4ee6a4SAndroid Build Coastguard Worker use crate::rutabaga_os::OwnedDescriptor;
39*bb4ee6a4SAndroid Build Coastguard Worker use crate::rutabaga_os::RawDescriptor;
40*bb4ee6a4SAndroid Build Coastguard Worker use crate::rutabaga_utils::*;
41*bb4ee6a4SAndroid Build Coastguard Worker 
42*bb4ee6a4SAndroid Build Coastguard Worker type Query = virgl_renderer_export_query;
43*bb4ee6a4SAndroid Build Coastguard Worker 
dup(rd: RawDescriptor) -> RutabagaResult<OwnedDescriptor>44*bb4ee6a4SAndroid Build Coastguard Worker fn dup(rd: RawDescriptor) -> RutabagaResult<OwnedDescriptor> {
45*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY:
46*bb4ee6a4SAndroid Build Coastguard Worker     // Safe because the underlying raw descriptor is guaranteed valid by rd's existence.
47*bb4ee6a4SAndroid Build Coastguard Worker     //
48*bb4ee6a4SAndroid Build Coastguard Worker     // Note that we are cloning the underlying raw descriptor since we have no guarantee of
49*bb4ee6a4SAndroid Build Coastguard Worker     // its existence after this function returns.
50*bb4ee6a4SAndroid Build Coastguard Worker     let rd_as_safe_desc = ManuallyDrop::new(unsafe { OwnedDescriptor::from_raw_descriptor(rd) });
51*bb4ee6a4SAndroid Build Coastguard Worker 
52*bb4ee6a4SAndroid Build Coastguard Worker     // We have to clone rd because we have no guarantee ownership was transferred (rd is
53*bb4ee6a4SAndroid Build Coastguard Worker     // borrowed).
54*bb4ee6a4SAndroid Build Coastguard Worker     Ok(rd_as_safe_desc.try_clone()?)
55*bb4ee6a4SAndroid Build Coastguard Worker }
56*bb4ee6a4SAndroid Build Coastguard Worker 
57*bb4ee6a4SAndroid Build Coastguard Worker /// The virtio-gpu backend state tracker which supports accelerated rendering.
58*bb4ee6a4SAndroid Build Coastguard Worker pub struct VirglRenderer {}
59*bb4ee6a4SAndroid Build Coastguard Worker 
60*bb4ee6a4SAndroid Build Coastguard Worker struct VirglRendererContext {
61*bb4ee6a4SAndroid Build Coastguard Worker     ctx_id: u32,
62*bb4ee6a4SAndroid Build Coastguard Worker }
63*bb4ee6a4SAndroid Build Coastguard Worker 
import_resource(resource: &mut RutabagaResource) -> RutabagaResult<()>64*bb4ee6a4SAndroid Build Coastguard Worker fn import_resource(resource: &mut RutabagaResource) -> RutabagaResult<()> {
65*bb4ee6a4SAndroid Build Coastguard Worker     if (resource.component_mask & (1 << (RutabagaComponentType::VirglRenderer as u8))) != 0 {
66*bb4ee6a4SAndroid Build Coastguard Worker         return Ok(());
67*bb4ee6a4SAndroid Build Coastguard Worker     }
68*bb4ee6a4SAndroid Build Coastguard Worker 
69*bb4ee6a4SAndroid Build Coastguard Worker     if let Some(handle) = &resource.handle {
70*bb4ee6a4SAndroid Build Coastguard Worker         if handle.handle_type == RUTABAGA_MEM_HANDLE_TYPE_DMABUF {
71*bb4ee6a4SAndroid Build Coastguard Worker             let dmabuf_fd = handle.os_handle.try_clone()?.into_raw_descriptor();
72*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY:
73*bb4ee6a4SAndroid Build Coastguard Worker             // Safe because we are being passed a valid fd
74*bb4ee6a4SAndroid Build Coastguard Worker             unsafe {
75*bb4ee6a4SAndroid Build Coastguard Worker                 let dmabuf_size = libc::lseek64(dmabuf_fd, 0, libc::SEEK_END);
76*bb4ee6a4SAndroid Build Coastguard Worker                 libc::lseek64(dmabuf_fd, 0, libc::SEEK_SET);
77*bb4ee6a4SAndroid Build Coastguard Worker                 let args = virgl_renderer_resource_import_blob_args {
78*bb4ee6a4SAndroid Build Coastguard Worker                     res_handle: resource.resource_id,
79*bb4ee6a4SAndroid Build Coastguard Worker                     blob_mem: resource.blob_mem,
80*bb4ee6a4SAndroid Build Coastguard Worker                     fd_type: VIRGL_RENDERER_BLOB_FD_TYPE_DMABUF,
81*bb4ee6a4SAndroid Build Coastguard Worker                     fd: dmabuf_fd,
82*bb4ee6a4SAndroid Build Coastguard Worker                     size: dmabuf_size as u64,
83*bb4ee6a4SAndroid Build Coastguard Worker                 };
84*bb4ee6a4SAndroid Build Coastguard Worker                 let ret = virgl_renderer_resource_import_blob(&args);
85*bb4ee6a4SAndroid Build Coastguard Worker                 if ret != 0 {
86*bb4ee6a4SAndroid Build Coastguard Worker                     // import_blob can fail if we've previously imported this resource,
87*bb4ee6a4SAndroid Build Coastguard Worker                     // but in any case virglrenderer does not take ownership of the fd
88*bb4ee6a4SAndroid Build Coastguard Worker                     // in error paths
89*bb4ee6a4SAndroid Build Coastguard Worker                     //
90*bb4ee6a4SAndroid Build Coastguard Worker                     // Because of the re-import case we must still fall through to the
91*bb4ee6a4SAndroid Build Coastguard Worker                     // virgl_renderer_ctx_attach_resource() call.
92*bb4ee6a4SAndroid Build Coastguard Worker                     libc::close(dmabuf_fd);
93*bb4ee6a4SAndroid Build Coastguard Worker                     return Ok(());
94*bb4ee6a4SAndroid Build Coastguard Worker                 }
95*bb4ee6a4SAndroid Build Coastguard Worker                 resource.component_mask |= 1 << (RutabagaComponentType::VirglRenderer as u8);
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     Ok(())
101*bb4ee6a4SAndroid Build Coastguard Worker }
102*bb4ee6a4SAndroid Build Coastguard Worker 
103*bb4ee6a4SAndroid Build Coastguard Worker impl RutabagaContext for VirglRendererContext {
submit_cmd( &mut self, commands: &mut [u8], fence_ids: &[u64], _shareable_fences: Vec<RutabagaHandle>, ) -> RutabagaResult<()>104*bb4ee6a4SAndroid Build Coastguard Worker     fn submit_cmd(
105*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
106*bb4ee6a4SAndroid Build Coastguard Worker         commands: &mut [u8],
107*bb4ee6a4SAndroid Build Coastguard Worker         fence_ids: &[u64],
108*bb4ee6a4SAndroid Build Coastguard Worker         _shareable_fences: Vec<RutabagaHandle>,
109*bb4ee6a4SAndroid Build Coastguard Worker     ) -> RutabagaResult<()> {
110*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(not(virgl_renderer_unstable))]
111*bb4ee6a4SAndroid Build Coastguard Worker         if !fence_ids.is_empty() {
112*bb4ee6a4SAndroid Build Coastguard Worker             return Err(RutabagaError::Unsupported);
113*bb4ee6a4SAndroid Build Coastguard Worker         }
114*bb4ee6a4SAndroid Build Coastguard Worker         if commands.len() % size_of::<u32>() != 0 {
115*bb4ee6a4SAndroid Build Coastguard Worker             return Err(RutabagaError::InvalidCommandSize(commands.len()));
116*bb4ee6a4SAndroid Build Coastguard Worker         }
117*bb4ee6a4SAndroid Build Coastguard Worker         let dword_count = (commands.len() / size_of::<u32>()) as i32;
118*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(not(virgl_renderer_unstable))]
119*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
120*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because the context and buffer are valid and virglrenderer will have been
121*bb4ee6a4SAndroid Build Coastguard Worker         // initialized if there are Context instances.
122*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe {
123*bb4ee6a4SAndroid Build Coastguard Worker             virgl_renderer_submit_cmd(
124*bb4ee6a4SAndroid Build Coastguard Worker                 commands.as_mut_ptr() as *mut c_void,
125*bb4ee6a4SAndroid Build Coastguard Worker                 self.ctx_id as i32,
126*bb4ee6a4SAndroid Build Coastguard Worker                 dword_count,
127*bb4ee6a4SAndroid Build Coastguard Worker             )
128*bb4ee6a4SAndroid Build Coastguard Worker         };
129*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(virgl_renderer_unstable)]
130*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
131*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because the context and buffers are valid and virglrenderer will have been
132*bb4ee6a4SAndroid Build Coastguard Worker         // initialized if there are Context instances.
133*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe {
134*bb4ee6a4SAndroid Build Coastguard Worker             virgl_renderer_submit_cmd2(
135*bb4ee6a4SAndroid Build Coastguard Worker                 commands.as_mut_ptr() as *mut c_void,
136*bb4ee6a4SAndroid Build Coastguard Worker                 self.ctx_id as i32,
137*bb4ee6a4SAndroid Build Coastguard Worker                 dword_count,
138*bb4ee6a4SAndroid Build Coastguard Worker                 fence_ids.as_ptr() as *mut u64,
139*bb4ee6a4SAndroid Build Coastguard Worker                 fence_ids.len() as u32,
140*bb4ee6a4SAndroid Build Coastguard Worker             )
141*bb4ee6a4SAndroid Build Coastguard Worker         };
142*bb4ee6a4SAndroid Build Coastguard Worker         ret_to_res(ret)
143*bb4ee6a4SAndroid Build Coastguard Worker     }
144*bb4ee6a4SAndroid Build Coastguard Worker 
attach(&mut self, resource: &mut RutabagaResource)145*bb4ee6a4SAndroid Build Coastguard Worker     fn attach(&mut self, resource: &mut RutabagaResource) {
146*bb4ee6a4SAndroid Build Coastguard Worker         match import_resource(resource) {
147*bb4ee6a4SAndroid Build Coastguard Worker             Ok(()) => (),
148*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => error!("importing resource failing with {}", e),
149*bb4ee6a4SAndroid Build Coastguard Worker         }
150*bb4ee6a4SAndroid Build Coastguard Worker 
151*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
152*bb4ee6a4SAndroid Build Coastguard Worker         // The context id and resource id must be valid because the respective instances ensure
153*bb4ee6a4SAndroid Build Coastguard Worker         // their lifetime.
154*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
155*bb4ee6a4SAndroid Build Coastguard Worker             virgl_renderer_ctx_attach_resource(self.ctx_id as i32, resource.resource_id as i32);
156*bb4ee6a4SAndroid Build Coastguard Worker         }
157*bb4ee6a4SAndroid Build Coastguard Worker     }
158*bb4ee6a4SAndroid Build Coastguard Worker 
detach(&mut self, resource: &RutabagaResource)159*bb4ee6a4SAndroid Build Coastguard Worker     fn detach(&mut self, resource: &RutabagaResource) {
160*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
161*bb4ee6a4SAndroid Build Coastguard Worker         // The context id and resource id must be valid because the respective instances ensure
162*bb4ee6a4SAndroid Build Coastguard Worker         // their lifetime.
163*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
164*bb4ee6a4SAndroid Build Coastguard Worker             virgl_renderer_ctx_detach_resource(self.ctx_id as i32, resource.resource_id as i32);
165*bb4ee6a4SAndroid Build Coastguard Worker         }
166*bb4ee6a4SAndroid Build Coastguard Worker     }
167*bb4ee6a4SAndroid Build Coastguard Worker 
component_type(&self) -> RutabagaComponentType168*bb4ee6a4SAndroid Build Coastguard Worker     fn component_type(&self) -> RutabagaComponentType {
169*bb4ee6a4SAndroid Build Coastguard Worker         RutabagaComponentType::VirglRenderer
170*bb4ee6a4SAndroid Build Coastguard Worker     }
171*bb4ee6a4SAndroid Build Coastguard Worker 
context_create_fence( &mut self, fence: RutabagaFence, ) -> RutabagaResult<Option<RutabagaHandle>>172*bb4ee6a4SAndroid Build Coastguard Worker     fn context_create_fence(
173*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
174*bb4ee6a4SAndroid Build Coastguard Worker         fence: RutabagaFence,
175*bb4ee6a4SAndroid Build Coastguard Worker     ) -> RutabagaResult<Option<RutabagaHandle>> {
176*bb4ee6a4SAndroid Build Coastguard Worker         // RutabagaFence::flags are not compatible with virglrenderer's fencing API and currently
177*bb4ee6a4SAndroid Build Coastguard Worker         // virglrenderer context's assume all fences on a single timeline are MERGEABLE, and enforce
178*bb4ee6a4SAndroid Build Coastguard Worker         // this assumption.
179*bb4ee6a4SAndroid Build Coastguard Worker         let flags: u32 = VIRGL_RENDERER_FENCE_FLAG_MERGEABLE;
180*bb4ee6a4SAndroid Build Coastguard Worker 
181*bb4ee6a4SAndroid Build Coastguard Worker         // TODO(b/315870313): Add safety comment
182*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(clippy::undocumented_unsafe_blocks)]
183*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe {
184*bb4ee6a4SAndroid Build Coastguard Worker             virgl_renderer_context_create_fence(
185*bb4ee6a4SAndroid Build Coastguard Worker                 fence.ctx_id,
186*bb4ee6a4SAndroid Build Coastguard Worker                 flags,
187*bb4ee6a4SAndroid Build Coastguard Worker                 fence.ring_idx as u32,
188*bb4ee6a4SAndroid Build Coastguard Worker                 fence.fence_id,
189*bb4ee6a4SAndroid Build Coastguard Worker             )
190*bb4ee6a4SAndroid Build Coastguard Worker         };
191*bb4ee6a4SAndroid Build Coastguard Worker         ret_to_res(ret)?;
192*bb4ee6a4SAndroid Build Coastguard Worker         Ok(None)
193*bb4ee6a4SAndroid Build Coastguard Worker     }
194*bb4ee6a4SAndroid Build Coastguard Worker }
195*bb4ee6a4SAndroid Build Coastguard Worker 
196*bb4ee6a4SAndroid Build Coastguard Worker impl Drop for VirglRendererContext {
drop(&mut self)197*bb4ee6a4SAndroid Build Coastguard Worker     fn drop(&mut self) {
198*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
199*bb4ee6a4SAndroid Build Coastguard Worker         // The context is safe to destroy because nothing else can be referencing it.
200*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
201*bb4ee6a4SAndroid Build Coastguard Worker             virgl_renderer_context_destroy(self.ctx_id);
202*bb4ee6a4SAndroid Build Coastguard Worker         }
203*bb4ee6a4SAndroid Build Coastguard Worker     }
204*bb4ee6a4SAndroid Build Coastguard Worker }
205*bb4ee6a4SAndroid Build Coastguard Worker 
debug_callback(fmt: *const ::std::os::raw::c_char, ap: stdio::va_list)206*bb4ee6a4SAndroid Build Coastguard Worker extern "C" fn debug_callback(fmt: *const ::std::os::raw::c_char, ap: stdio::va_list) {
207*bb4ee6a4SAndroid Build Coastguard Worker     const BUF_LEN: usize = 256;
208*bb4ee6a4SAndroid Build Coastguard Worker     let mut v = [b' '; BUF_LEN];
209*bb4ee6a4SAndroid Build Coastguard Worker 
210*bb4ee6a4SAndroid Build Coastguard Worker     // TODO(b/315870313): Add safety comment
211*bb4ee6a4SAndroid Build Coastguard Worker     #[allow(clippy::undocumented_unsafe_blocks)]
212*bb4ee6a4SAndroid Build Coastguard Worker     let printed_len = unsafe {
213*bb4ee6a4SAndroid Build Coastguard Worker         let ptr = v.as_mut_ptr() as *mut ::std::os::raw::c_char;
214*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(any(
215*bb4ee6a4SAndroid Build Coastguard Worker             target_arch = "x86",
216*bb4ee6a4SAndroid Build Coastguard Worker             target_arch = "x86_64",
217*bb4ee6a4SAndroid Build Coastguard Worker             target_arch = "aarch64",
218*bb4ee6a4SAndroid Build Coastguard Worker             target_arch = "riscv64"
219*bb4ee6a4SAndroid Build Coastguard Worker         ))]
220*bb4ee6a4SAndroid Build Coastguard Worker         let size = BUF_LEN as ::std::os::raw::c_ulong;
221*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(target_arch = "arm")]
222*bb4ee6a4SAndroid Build Coastguard Worker         let size = BUF_LEN as ::std::os::raw::c_uint;
223*bb4ee6a4SAndroid Build Coastguard Worker 
224*bb4ee6a4SAndroid Build Coastguard Worker         stdio::vsnprintf(ptr, size, fmt, ap)
225*bb4ee6a4SAndroid Build Coastguard Worker     };
226*bb4ee6a4SAndroid Build Coastguard Worker 
227*bb4ee6a4SAndroid Build Coastguard Worker     if printed_len < 0 {
228*bb4ee6a4SAndroid Build Coastguard Worker         debug!(
229*bb4ee6a4SAndroid Build Coastguard Worker             "rutabaga_gfx::virgl_renderer::debug_callback: vsnprintf returned {}",
230*bb4ee6a4SAndroid Build Coastguard Worker             printed_len
231*bb4ee6a4SAndroid Build Coastguard Worker         );
232*bb4ee6a4SAndroid Build Coastguard Worker     } else {
233*bb4ee6a4SAndroid Build Coastguard Worker         // vsnprintf returns the number of chars that *would* have been printed
234*bb4ee6a4SAndroid Build Coastguard Worker         let len = min(printed_len as usize, BUF_LEN - 1);
235*bb4ee6a4SAndroid Build Coastguard Worker         debug!("{}", String::from_utf8_lossy(&v[..len]));
236*bb4ee6a4SAndroid Build Coastguard Worker     }
237*bb4ee6a4SAndroid Build Coastguard Worker }
238*bb4ee6a4SAndroid Build Coastguard Worker 
write_context_fence(cookie: *mut c_void, ctx_id: u32, ring_idx: u32, fence_id: u64)239*bb4ee6a4SAndroid Build Coastguard Worker extern "C" fn write_context_fence(cookie: *mut c_void, ctx_id: u32, ring_idx: u32, fence_id: u64) {
240*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(|| {
241*bb4ee6a4SAndroid Build Coastguard Worker         assert!(!cookie.is_null());
242*bb4ee6a4SAndroid Build Coastguard Worker         // TODO(b/315870313): Add safety comment
243*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(clippy::undocumented_unsafe_blocks)]
244*bb4ee6a4SAndroid Build Coastguard Worker         let cookie = unsafe { &*(cookie as *mut RutabagaCookie) };
245*bb4ee6a4SAndroid Build Coastguard Worker 
246*bb4ee6a4SAndroid Build Coastguard Worker         // Call fence completion callback
247*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(handler) = &cookie.fence_handler {
248*bb4ee6a4SAndroid Build Coastguard Worker             handler.call(RutabagaFence {
249*bb4ee6a4SAndroid Build Coastguard Worker                 flags: RUTABAGA_FLAG_FENCE | RUTABAGA_FLAG_INFO_RING_IDX,
250*bb4ee6a4SAndroid Build Coastguard Worker                 fence_id,
251*bb4ee6a4SAndroid Build Coastguard Worker                 ctx_id,
252*bb4ee6a4SAndroid Build Coastguard Worker                 ring_idx: ring_idx as u8,
253*bb4ee6a4SAndroid Build Coastguard Worker             });
254*bb4ee6a4SAndroid Build Coastguard Worker         }
255*bb4ee6a4SAndroid Build Coastguard Worker     })
256*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or_else(|_| abort())
257*bb4ee6a4SAndroid Build Coastguard Worker }
258*bb4ee6a4SAndroid Build Coastguard Worker 
259*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/315870313): Add safety comment
260*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::undocumented_unsafe_blocks)]
write_fence(cookie: *mut c_void, fence: u32)261*bb4ee6a4SAndroid Build Coastguard Worker unsafe extern "C" fn write_fence(cookie: *mut c_void, fence: u32) {
262*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(|| {
263*bb4ee6a4SAndroid Build Coastguard Worker         assert!(!cookie.is_null());
264*bb4ee6a4SAndroid Build Coastguard Worker         let cookie = &*(cookie as *mut RutabagaCookie);
265*bb4ee6a4SAndroid Build Coastguard Worker 
266*bb4ee6a4SAndroid Build Coastguard Worker         // Call fence completion callback
267*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(handler) = &cookie.fence_handler {
268*bb4ee6a4SAndroid Build Coastguard Worker             handler.call(RutabagaFence {
269*bb4ee6a4SAndroid Build Coastguard Worker                 flags: RUTABAGA_FLAG_FENCE,
270*bb4ee6a4SAndroid Build Coastguard Worker                 fence_id: fence as u64,
271*bb4ee6a4SAndroid Build Coastguard Worker                 ctx_id: 0,
272*bb4ee6a4SAndroid Build Coastguard Worker                 ring_idx: 0,
273*bb4ee6a4SAndroid Build Coastguard Worker             });
274*bb4ee6a4SAndroid Build Coastguard Worker         }
275*bb4ee6a4SAndroid Build Coastguard Worker     })
276*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or_else(|_| abort())
277*bb4ee6a4SAndroid Build Coastguard Worker }
278*bb4ee6a4SAndroid Build Coastguard Worker 
279*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/315870313): Add safety comment
280*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::undocumented_unsafe_blocks)]
get_server_fd(cookie: *mut c_void, version: u32) -> c_int281*bb4ee6a4SAndroid Build Coastguard Worker unsafe extern "C" fn get_server_fd(cookie: *mut c_void, version: u32) -> c_int {
282*bb4ee6a4SAndroid Build Coastguard Worker     catch_unwind(|| {
283*bb4ee6a4SAndroid Build Coastguard Worker         assert!(!cookie.is_null());
284*bb4ee6a4SAndroid Build Coastguard Worker         let cookie = &mut *(cookie as *mut RutabagaCookie);
285*bb4ee6a4SAndroid Build Coastguard Worker 
286*bb4ee6a4SAndroid Build Coastguard Worker         if version != 0 {
287*bb4ee6a4SAndroid Build Coastguard Worker             return -1;
288*bb4ee6a4SAndroid Build Coastguard Worker         }
289*bb4ee6a4SAndroid Build Coastguard Worker 
290*bb4ee6a4SAndroid Build Coastguard Worker         // Transfer the fd ownership to virglrenderer.
291*bb4ee6a4SAndroid Build Coastguard Worker         cookie
292*bb4ee6a4SAndroid Build Coastguard Worker             .render_server_fd
293*bb4ee6a4SAndroid Build Coastguard Worker             .take()
294*bb4ee6a4SAndroid Build Coastguard Worker             .map(OwnedDescriptor::into_raw_descriptor)
295*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap_or(-1)
296*bb4ee6a4SAndroid Build Coastguard Worker     })
297*bb4ee6a4SAndroid Build Coastguard Worker     .unwrap_or_else(|_| abort())
298*bb4ee6a4SAndroid Build Coastguard Worker }
299*bb4ee6a4SAndroid Build Coastguard Worker 
300*bb4ee6a4SAndroid Build Coastguard Worker const VIRGL_RENDERER_CALLBACKS: &virgl_renderer_callbacks = &virgl_renderer_callbacks {
301*bb4ee6a4SAndroid Build Coastguard Worker     version: 3,
302*bb4ee6a4SAndroid Build Coastguard Worker     write_fence: Some(write_fence),
303*bb4ee6a4SAndroid Build Coastguard Worker     create_gl_context: None,
304*bb4ee6a4SAndroid Build Coastguard Worker     destroy_gl_context: None,
305*bb4ee6a4SAndroid Build Coastguard Worker     make_current: None,
306*bb4ee6a4SAndroid Build Coastguard Worker     get_drm_fd: None,
307*bb4ee6a4SAndroid Build Coastguard Worker     write_context_fence: Some(write_context_fence),
308*bb4ee6a4SAndroid Build Coastguard Worker     get_server_fd: Some(get_server_fd),
309*bb4ee6a4SAndroid Build Coastguard Worker     get_egl_display: None,
310*bb4ee6a4SAndroid Build Coastguard Worker };
311*bb4ee6a4SAndroid Build Coastguard Worker 
312*bb4ee6a4SAndroid Build Coastguard Worker /// Retrieves metadata suitable for export about this resource. If "export_fd" is true,
313*bb4ee6a4SAndroid Build Coastguard Worker /// performs an export of this resource so that it may be imported by other processes.
export_query(resource_id: u32) -> RutabagaResult<Query>314*bb4ee6a4SAndroid Build Coastguard Worker fn export_query(resource_id: u32) -> RutabagaResult<Query> {
315*bb4ee6a4SAndroid Build Coastguard Worker     let mut query: Query = Default::default();
316*bb4ee6a4SAndroid Build Coastguard Worker     query.hdr.stype = VIRGL_RENDERER_STRUCTURE_TYPE_EXPORT_QUERY;
317*bb4ee6a4SAndroid Build Coastguard Worker     query.hdr.stype_version = 0;
318*bb4ee6a4SAndroid Build Coastguard Worker     query.hdr.size = size_of::<Query>() as u32;
319*bb4ee6a4SAndroid Build Coastguard Worker     query.in_resource_id = resource_id;
320*bb4ee6a4SAndroid Build Coastguard Worker     query.in_export_fds = 0;
321*bb4ee6a4SAndroid Build Coastguard Worker 
322*bb4ee6a4SAndroid Build Coastguard Worker     let ret =
323*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
324*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because the image parameters are stack variables of the correct type.
325*bb4ee6a4SAndroid Build Coastguard Worker         unsafe { virgl_renderer_execute(&mut query as *mut _ as *mut c_void, query.hdr.size) };
326*bb4ee6a4SAndroid Build Coastguard Worker 
327*bb4ee6a4SAndroid Build Coastguard Worker     ret_to_res(ret)?;
328*bb4ee6a4SAndroid Build Coastguard Worker     Ok(query)
329*bb4ee6a4SAndroid Build Coastguard Worker }
330*bb4ee6a4SAndroid Build Coastguard Worker 
331*bb4ee6a4SAndroid Build Coastguard Worker impl VirglRenderer {
init( virglrenderer_flags: VirglRendererFlags, fence_handler: RutabagaFenceHandler, render_server_fd: Option<OwnedDescriptor>, ) -> RutabagaResult<Box<dyn RutabagaComponent>>332*bb4ee6a4SAndroid Build Coastguard Worker     pub fn init(
333*bb4ee6a4SAndroid Build Coastguard Worker         virglrenderer_flags: VirglRendererFlags,
334*bb4ee6a4SAndroid Build Coastguard Worker         fence_handler: RutabagaFenceHandler,
335*bb4ee6a4SAndroid Build Coastguard Worker         render_server_fd: Option<OwnedDescriptor>,
336*bb4ee6a4SAndroid Build Coastguard Worker     ) -> RutabagaResult<Box<dyn RutabagaComponent>> {
337*bb4ee6a4SAndroid Build Coastguard Worker         if cfg!(debug_assertions) {
338*bb4ee6a4SAndroid Build Coastguard Worker             // TODO(b/315870313): Add safety comment
339*bb4ee6a4SAndroid Build Coastguard Worker             #[allow(clippy::undocumented_unsafe_blocks)]
340*bb4ee6a4SAndroid Build Coastguard Worker             let ret = unsafe { libc::dup2(libc::STDOUT_FILENO, libc::STDERR_FILENO) };
341*bb4ee6a4SAndroid Build Coastguard Worker             if ret == -1 {
342*bb4ee6a4SAndroid Build Coastguard Worker                 warn!(
343*bb4ee6a4SAndroid Build Coastguard Worker                     "unable to dup2 stdout to stderr: {}",
344*bb4ee6a4SAndroid Build Coastguard Worker                     SysError::last_os_error()
345*bb4ee6a4SAndroid Build Coastguard Worker                 );
346*bb4ee6a4SAndroid Build Coastguard Worker             }
347*bb4ee6a4SAndroid Build Coastguard Worker         }
348*bb4ee6a4SAndroid Build Coastguard Worker 
349*bb4ee6a4SAndroid Build Coastguard Worker         // virglrenderer is a global state backed library that uses thread bound OpenGL contexts.
350*bb4ee6a4SAndroid Build Coastguard Worker         // Initialize it only once and use the non-send/non-sync Renderer struct to keep things tied
351*bb4ee6a4SAndroid Build Coastguard Worker         // to whichever thread called this function first.
352*bb4ee6a4SAndroid Build Coastguard Worker         static INIT_ONCE: AtomicBool = AtomicBool::new(false);
353*bb4ee6a4SAndroid Build Coastguard Worker         if INIT_ONCE
354*bb4ee6a4SAndroid Build Coastguard Worker             .compare_exchange(false, true, Ordering::Acquire, Ordering::Acquire)
355*bb4ee6a4SAndroid Build Coastguard Worker             .is_err()
356*bb4ee6a4SAndroid Build Coastguard Worker         {
357*bb4ee6a4SAndroid Build Coastguard Worker             return Err(RutabagaError::AlreadyInUse);
358*bb4ee6a4SAndroid Build Coastguard Worker         }
359*bb4ee6a4SAndroid Build Coastguard Worker 
360*bb4ee6a4SAndroid Build Coastguard Worker         // TODO(b/315870313): Add safety comment
361*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(clippy::undocumented_unsafe_blocks)]
362*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
363*bb4ee6a4SAndroid Build Coastguard Worker             virgl_set_debug_callback(Some(debug_callback))
364*bb4ee6a4SAndroid Build Coastguard Worker         };
365*bb4ee6a4SAndroid Build Coastguard Worker 
366*bb4ee6a4SAndroid Build Coastguard Worker         // Cookie is intentionally never freed because virglrenderer never gets uninitialized.
367*bb4ee6a4SAndroid Build Coastguard Worker         // Otherwise, Resource and Context would become invalid because their lifetime is not tied
368*bb4ee6a4SAndroid Build Coastguard Worker         // to the Renderer instance. Doing so greatly simplifies the ownership for users of this
369*bb4ee6a4SAndroid Build Coastguard Worker         // library.
370*bb4ee6a4SAndroid Build Coastguard Worker         let cookie = Box::into_raw(Box::new(RutabagaCookie {
371*bb4ee6a4SAndroid Build Coastguard Worker             render_server_fd,
372*bb4ee6a4SAndroid Build Coastguard Worker             fence_handler: Some(fence_handler),
373*bb4ee6a4SAndroid Build Coastguard Worker             debug_handler: None,
374*bb4ee6a4SAndroid Build Coastguard Worker         }));
375*bb4ee6a4SAndroid Build Coastguard Worker 
376*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
377*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because a valid cookie and set of callbacks is used and the result is checked for
378*bb4ee6a4SAndroid Build Coastguard Worker         // error.
379*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe {
380*bb4ee6a4SAndroid Build Coastguard Worker             virgl_renderer_init(
381*bb4ee6a4SAndroid Build Coastguard Worker                 cookie as *mut c_void,
382*bb4ee6a4SAndroid Build Coastguard Worker                 virglrenderer_flags.into(),
383*bb4ee6a4SAndroid Build Coastguard Worker                 transmute(VIRGL_RENDERER_CALLBACKS),
384*bb4ee6a4SAndroid Build Coastguard Worker             )
385*bb4ee6a4SAndroid Build Coastguard Worker         };
386*bb4ee6a4SAndroid Build Coastguard Worker 
387*bb4ee6a4SAndroid Build Coastguard Worker         ret_to_res(ret)?;
388*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Box::new(VirglRenderer {}))
389*bb4ee6a4SAndroid Build Coastguard Worker     }
390*bb4ee6a4SAndroid Build Coastguard Worker 
map_info(&self, resource_id: u32) -> RutabagaResult<u32>391*bb4ee6a4SAndroid Build Coastguard Worker     fn map_info(&self, resource_id: u32) -> RutabagaResult<u32> {
392*bb4ee6a4SAndroid Build Coastguard Worker         let mut map_info = 0;
393*bb4ee6a4SAndroid Build Coastguard Worker         // TODO(b/315870313): Add safety comment
394*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(clippy::undocumented_unsafe_blocks)]
395*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { virgl_renderer_resource_get_map_info(resource_id, &mut map_info) };
396*bb4ee6a4SAndroid Build Coastguard Worker         ret_to_res(ret)?;
397*bb4ee6a4SAndroid Build Coastguard Worker 
398*bb4ee6a4SAndroid Build Coastguard Worker         Ok(map_info | RUTABAGA_MAP_ACCESS_RW)
399*bb4ee6a4SAndroid Build Coastguard Worker     }
400*bb4ee6a4SAndroid Build Coastguard Worker 
query(&self, resource_id: u32) -> RutabagaResult<Resource3DInfo>401*bb4ee6a4SAndroid Build Coastguard Worker     fn query(&self, resource_id: u32) -> RutabagaResult<Resource3DInfo> {
402*bb4ee6a4SAndroid Build Coastguard Worker         let query = export_query(resource_id)?;
403*bb4ee6a4SAndroid Build Coastguard Worker         if query.out_num_fds == 0 {
404*bb4ee6a4SAndroid Build Coastguard Worker             return Err(RutabagaError::Unsupported);
405*bb4ee6a4SAndroid Build Coastguard Worker         }
406*bb4ee6a4SAndroid Build Coastguard Worker 
407*bb4ee6a4SAndroid Build Coastguard Worker         // virglrenderer unfortunately doesn't return the width or height, so map to zero.
408*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Resource3DInfo {
409*bb4ee6a4SAndroid Build Coastguard Worker             width: 0,
410*bb4ee6a4SAndroid Build Coastguard Worker             height: 0,
411*bb4ee6a4SAndroid Build Coastguard Worker             drm_fourcc: query.out_fourcc,
412*bb4ee6a4SAndroid Build Coastguard Worker             strides: query.out_strides,
413*bb4ee6a4SAndroid Build Coastguard Worker             offsets: query.out_offsets,
414*bb4ee6a4SAndroid Build Coastguard Worker             modifier: query.out_modifier,
415*bb4ee6a4SAndroid Build Coastguard Worker             guest_cpu_mappable: false,
416*bb4ee6a4SAndroid Build Coastguard Worker         })
417*bb4ee6a4SAndroid Build Coastguard Worker     }
418*bb4ee6a4SAndroid Build Coastguard Worker 
export_blob(&self, resource_id: u32) -> RutabagaResult<Arc<RutabagaHandle>>419*bb4ee6a4SAndroid Build Coastguard Worker     fn export_blob(&self, resource_id: u32) -> RutabagaResult<Arc<RutabagaHandle>> {
420*bb4ee6a4SAndroid Build Coastguard Worker         let mut fd_type = 0;
421*bb4ee6a4SAndroid Build Coastguard Worker         let mut fd = 0;
422*bb4ee6a4SAndroid Build Coastguard Worker         // TODO(b/315870313): Add safety comment
423*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(clippy::undocumented_unsafe_blocks)]
424*bb4ee6a4SAndroid Build Coastguard Worker         let ret =
425*bb4ee6a4SAndroid Build Coastguard Worker             unsafe { virgl_renderer_resource_export_blob(resource_id, &mut fd_type, &mut fd) };
426*bb4ee6a4SAndroid Build Coastguard Worker         ret_to_res(ret)?;
427*bb4ee6a4SAndroid Build Coastguard Worker 
428*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
429*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because the FD was just returned by a successful virglrenderer
430*bb4ee6a4SAndroid Build Coastguard Worker         // call so it must be valid and owned by us.
431*bb4ee6a4SAndroid Build Coastguard Worker         let handle = unsafe { OwnedDescriptor::from_raw_descriptor(fd) };
432*bb4ee6a4SAndroid Build Coastguard Worker 
433*bb4ee6a4SAndroid Build Coastguard Worker         let handle_type = match fd_type {
434*bb4ee6a4SAndroid Build Coastguard Worker             VIRGL_RENDERER_BLOB_FD_TYPE_DMABUF => RUTABAGA_MEM_HANDLE_TYPE_DMABUF,
435*bb4ee6a4SAndroid Build Coastguard Worker             VIRGL_RENDERER_BLOB_FD_TYPE_SHM => RUTABAGA_MEM_HANDLE_TYPE_SHM,
436*bb4ee6a4SAndroid Build Coastguard Worker             VIRGL_RENDERER_BLOB_FD_TYPE_OPAQUE => RUTABAGA_MEM_HANDLE_TYPE_OPAQUE_FD,
437*bb4ee6a4SAndroid Build Coastguard Worker             _ => {
438*bb4ee6a4SAndroid Build Coastguard Worker                 return Err(RutabagaError::Unsupported);
439*bb4ee6a4SAndroid Build Coastguard Worker             }
440*bb4ee6a4SAndroid Build Coastguard Worker         };
441*bb4ee6a4SAndroid Build Coastguard Worker 
442*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Arc::new(RutabagaHandle {
443*bb4ee6a4SAndroid Build Coastguard Worker             os_handle: handle,
444*bb4ee6a4SAndroid Build Coastguard Worker             handle_type,
445*bb4ee6a4SAndroid Build Coastguard Worker         }))
446*bb4ee6a4SAndroid Build Coastguard Worker     }
447*bb4ee6a4SAndroid Build Coastguard Worker }
448*bb4ee6a4SAndroid Build Coastguard Worker 
449*bb4ee6a4SAndroid Build Coastguard Worker impl Drop for VirglRenderer {
drop(&mut self)450*bb4ee6a4SAndroid Build Coastguard Worker     fn drop(&mut self) {
451*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
452*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because virglrenderer is initialized.
453*bb4ee6a4SAndroid Build Coastguard Worker         //
454*bb4ee6a4SAndroid Build Coastguard Worker         // This invalidates all context ids and resource ids.  It is fine because struct Rutabaga
455*bb4ee6a4SAndroid Build Coastguard Worker         // makes sure contexts and resources are dropped before this is reached.  Even if it did
456*bb4ee6a4SAndroid Build Coastguard Worker         // not, virglrenderer is designed to deal with invalid ids safely.
457*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
458*bb4ee6a4SAndroid Build Coastguard Worker             virgl_renderer_cleanup(null_mut());
459*bb4ee6a4SAndroid Build Coastguard Worker         }
460*bb4ee6a4SAndroid Build Coastguard Worker     }
461*bb4ee6a4SAndroid Build Coastguard Worker }
462*bb4ee6a4SAndroid Build Coastguard Worker 
463*bb4ee6a4SAndroid Build Coastguard Worker impl RutabagaComponent for VirglRenderer {
get_capset_info(&self, capset_id: u32) -> (u32, u32)464*bb4ee6a4SAndroid Build Coastguard Worker     fn get_capset_info(&self, capset_id: u32) -> (u32, u32) {
465*bb4ee6a4SAndroid Build Coastguard Worker         let mut version = 0;
466*bb4ee6a4SAndroid Build Coastguard Worker         let mut size = 0;
467*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
468*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because virglrenderer is initialized by now and properly size stack variables are
469*bb4ee6a4SAndroid Build Coastguard Worker         // used for the pointers.
470*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
471*bb4ee6a4SAndroid Build Coastguard Worker             virgl_renderer_get_cap_set(capset_id, &mut version, &mut size);
472*bb4ee6a4SAndroid Build Coastguard Worker         }
473*bb4ee6a4SAndroid Build Coastguard Worker         (version, size)
474*bb4ee6a4SAndroid Build Coastguard Worker     }
475*bb4ee6a4SAndroid Build Coastguard Worker 
get_capset(&self, capset_id: u32, version: u32) -> Vec<u8>476*bb4ee6a4SAndroid Build Coastguard Worker     fn get_capset(&self, capset_id: u32, version: u32) -> Vec<u8> {
477*bb4ee6a4SAndroid Build Coastguard Worker         let (_, max_size) = self.get_capset_info(capset_id);
478*bb4ee6a4SAndroid Build Coastguard Worker         let mut buf = vec![0u8; max_size as usize];
479*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
480*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because virglrenderer is initialized by now and the given buffer is sized properly
481*bb4ee6a4SAndroid Build Coastguard Worker         // for the given cap id/version.
482*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
483*bb4ee6a4SAndroid Build Coastguard Worker             virgl_renderer_fill_caps(capset_id, version, buf.as_mut_ptr() as *mut c_void);
484*bb4ee6a4SAndroid Build Coastguard Worker         }
485*bb4ee6a4SAndroid Build Coastguard Worker         buf
486*bb4ee6a4SAndroid Build Coastguard Worker     }
487*bb4ee6a4SAndroid Build Coastguard Worker 
force_ctx_0(&self)488*bb4ee6a4SAndroid Build Coastguard Worker     fn force_ctx_0(&self) {
489*bb4ee6a4SAndroid Build Coastguard Worker         // TODO(b/315870313): Add safety comment
490*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(clippy::undocumented_unsafe_blocks)]
491*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
492*bb4ee6a4SAndroid Build Coastguard Worker             virgl_renderer_force_ctx_0()
493*bb4ee6a4SAndroid Build Coastguard Worker         };
494*bb4ee6a4SAndroid Build Coastguard Worker     }
495*bb4ee6a4SAndroid Build Coastguard Worker 
create_fence(&mut self, fence: RutabagaFence) -> RutabagaResult<()>496*bb4ee6a4SAndroid Build Coastguard Worker     fn create_fence(&mut self, fence: RutabagaFence) -> RutabagaResult<()> {
497*bb4ee6a4SAndroid Build Coastguard Worker         // TODO(b/315870313): Add safety comment
498*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(clippy::undocumented_unsafe_blocks)]
499*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { virgl_renderer_create_fence(fence.fence_id as i32, fence.ctx_id) };
500*bb4ee6a4SAndroid Build Coastguard Worker         ret_to_res(ret)
501*bb4ee6a4SAndroid Build Coastguard Worker     }
502*bb4ee6a4SAndroid Build Coastguard Worker 
event_poll(&self)503*bb4ee6a4SAndroid Build Coastguard Worker     fn event_poll(&self) {
504*bb4ee6a4SAndroid Build Coastguard Worker         // TODO(b/315870313): Add safety comment
505*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(clippy::undocumented_unsafe_blocks)]
506*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
507*bb4ee6a4SAndroid Build Coastguard Worker             virgl_renderer_poll()
508*bb4ee6a4SAndroid Build Coastguard Worker         };
509*bb4ee6a4SAndroid Build Coastguard Worker     }
510*bb4ee6a4SAndroid Build Coastguard Worker 
poll_descriptor(&self) -> Option<OwnedDescriptor>511*bb4ee6a4SAndroid Build Coastguard Worker     fn poll_descriptor(&self) -> Option<OwnedDescriptor> {
512*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
513*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because it can be called anytime and returns -1 in the event of an error.
514*bb4ee6a4SAndroid Build Coastguard Worker         let fd = unsafe { virgl_renderer_get_poll_fd() };
515*bb4ee6a4SAndroid Build Coastguard Worker         if fd >= 0 {
516*bb4ee6a4SAndroid Build Coastguard Worker             let descriptor: RawDescriptor = fd as RawDescriptor;
517*bb4ee6a4SAndroid Build Coastguard Worker             if let Ok(dup_fd) = dup(descriptor) {
518*bb4ee6a4SAndroid Build Coastguard Worker                 return Some(dup_fd);
519*bb4ee6a4SAndroid Build Coastguard Worker             }
520*bb4ee6a4SAndroid Build Coastguard Worker         }
521*bb4ee6a4SAndroid Build Coastguard Worker         None
522*bb4ee6a4SAndroid Build Coastguard Worker     }
523*bb4ee6a4SAndroid Build Coastguard Worker 
create_3d( &self, resource_id: u32, resource_create_3d: ResourceCreate3D, ) -> RutabagaResult<RutabagaResource>524*bb4ee6a4SAndroid Build Coastguard Worker     fn create_3d(
525*bb4ee6a4SAndroid Build Coastguard Worker         &self,
526*bb4ee6a4SAndroid Build Coastguard Worker         resource_id: u32,
527*bb4ee6a4SAndroid Build Coastguard Worker         resource_create_3d: ResourceCreate3D,
528*bb4ee6a4SAndroid Build Coastguard Worker     ) -> RutabagaResult<RutabagaResource> {
529*bb4ee6a4SAndroid Build Coastguard Worker         let mut args = virgl_renderer_resource_create_args {
530*bb4ee6a4SAndroid Build Coastguard Worker             handle: resource_id,
531*bb4ee6a4SAndroid Build Coastguard Worker             target: resource_create_3d.target,
532*bb4ee6a4SAndroid Build Coastguard Worker             format: resource_create_3d.format,
533*bb4ee6a4SAndroid Build Coastguard Worker             bind: resource_create_3d.bind,
534*bb4ee6a4SAndroid Build Coastguard Worker             width: resource_create_3d.width,
535*bb4ee6a4SAndroid Build Coastguard Worker             height: resource_create_3d.height,
536*bb4ee6a4SAndroid Build Coastguard Worker             depth: resource_create_3d.depth,
537*bb4ee6a4SAndroid Build Coastguard Worker             array_size: resource_create_3d.array_size,
538*bb4ee6a4SAndroid Build Coastguard Worker             last_level: resource_create_3d.last_level,
539*bb4ee6a4SAndroid Build Coastguard Worker             nr_samples: resource_create_3d.nr_samples,
540*bb4ee6a4SAndroid Build Coastguard Worker             flags: resource_create_3d.flags,
541*bb4ee6a4SAndroid Build Coastguard Worker         };
542*bb4ee6a4SAndroid Build Coastguard Worker 
543*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
544*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because virglrenderer is initialized by now, and the return value is checked before
545*bb4ee6a4SAndroid Build Coastguard Worker         // returning a new resource. The backing buffers are not supplied with this call.
546*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { virgl_renderer_resource_create(&mut args, null_mut(), 0) };
547*bb4ee6a4SAndroid Build Coastguard Worker         ret_to_res(ret)?;
548*bb4ee6a4SAndroid Build Coastguard Worker 
549*bb4ee6a4SAndroid Build Coastguard Worker         Ok(RutabagaResource {
550*bb4ee6a4SAndroid Build Coastguard Worker             resource_id,
551*bb4ee6a4SAndroid Build Coastguard Worker             handle: self.export_blob(resource_id).ok(),
552*bb4ee6a4SAndroid Build Coastguard Worker             blob: false,
553*bb4ee6a4SAndroid Build Coastguard Worker             blob_mem: 0,
554*bb4ee6a4SAndroid Build Coastguard Worker             blob_flags: 0,
555*bb4ee6a4SAndroid Build Coastguard Worker             map_info: None,
556*bb4ee6a4SAndroid Build Coastguard Worker             info_2d: None,
557*bb4ee6a4SAndroid Build Coastguard Worker             info_3d: self.query(resource_id).ok(),
558*bb4ee6a4SAndroid Build Coastguard Worker             vulkan_info: None,
559*bb4ee6a4SAndroid Build Coastguard Worker             backing_iovecs: None,
560*bb4ee6a4SAndroid Build Coastguard Worker             component_mask: 1 << (RutabagaComponentType::VirglRenderer as u8),
561*bb4ee6a4SAndroid Build Coastguard Worker             size: 0,
562*bb4ee6a4SAndroid Build Coastguard Worker             mapping: None,
563*bb4ee6a4SAndroid Build Coastguard Worker         })
564*bb4ee6a4SAndroid Build Coastguard Worker     }
565*bb4ee6a4SAndroid Build Coastguard Worker 
attach_backing( &self, resource_id: u32, vecs: &mut Vec<RutabagaIovec>, ) -> RutabagaResult<()>566*bb4ee6a4SAndroid Build Coastguard Worker     fn attach_backing(
567*bb4ee6a4SAndroid Build Coastguard Worker         &self,
568*bb4ee6a4SAndroid Build Coastguard Worker         resource_id: u32,
569*bb4ee6a4SAndroid Build Coastguard Worker         vecs: &mut Vec<RutabagaIovec>,
570*bb4ee6a4SAndroid Build Coastguard Worker     ) -> RutabagaResult<()> {
571*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
572*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because the backing is into guest memory that we store a reference count for.
573*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe {
574*bb4ee6a4SAndroid Build Coastguard Worker             virgl_renderer_resource_attach_iov(
575*bb4ee6a4SAndroid Build Coastguard Worker                 resource_id as i32,
576*bb4ee6a4SAndroid Build Coastguard Worker                 vecs.as_mut_ptr() as *mut iovec,
577*bb4ee6a4SAndroid Build Coastguard Worker                 vecs.len() as i32,
578*bb4ee6a4SAndroid Build Coastguard Worker             )
579*bb4ee6a4SAndroid Build Coastguard Worker         };
580*bb4ee6a4SAndroid Build Coastguard Worker         ret_to_res(ret)
581*bb4ee6a4SAndroid Build Coastguard Worker     }
582*bb4ee6a4SAndroid Build Coastguard Worker 
detach_backing(&self, resource_id: u32)583*bb4ee6a4SAndroid Build Coastguard Worker     fn detach_backing(&self, resource_id: u32) {
584*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
585*bb4ee6a4SAndroid Build Coastguard Worker         // Safe as we don't need the old backing iovecs returned and the reference to the guest
586*bb4ee6a4SAndroid Build Coastguard Worker         // memory can be dropped as it will no longer be needed for this resource.
587*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
588*bb4ee6a4SAndroid Build Coastguard Worker             virgl_renderer_resource_detach_iov(resource_id as i32, null_mut(), null_mut());
589*bb4ee6a4SAndroid Build Coastguard Worker         }
590*bb4ee6a4SAndroid Build Coastguard Worker     }
591*bb4ee6a4SAndroid Build Coastguard Worker 
unref_resource(&self, resource_id: u32)592*bb4ee6a4SAndroid Build Coastguard Worker     fn unref_resource(&self, resource_id: u32) {
593*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
594*bb4ee6a4SAndroid Build Coastguard Worker         // The resource is safe to unreference destroy because no user of these bindings can still
595*bb4ee6a4SAndroid Build Coastguard Worker         // be holding a reference.
596*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
597*bb4ee6a4SAndroid Build Coastguard Worker             virgl_renderer_resource_unref(resource_id);
598*bb4ee6a4SAndroid Build Coastguard Worker         }
599*bb4ee6a4SAndroid Build Coastguard Worker     }
600*bb4ee6a4SAndroid Build Coastguard Worker 
transfer_write( &self, ctx_id: u32, resource: &mut RutabagaResource, transfer: Transfer3D, ) -> RutabagaResult<()>601*bb4ee6a4SAndroid Build Coastguard Worker     fn transfer_write(
602*bb4ee6a4SAndroid Build Coastguard Worker         &self,
603*bb4ee6a4SAndroid Build Coastguard Worker         ctx_id: u32,
604*bb4ee6a4SAndroid Build Coastguard Worker         resource: &mut RutabagaResource,
605*bb4ee6a4SAndroid Build Coastguard Worker         transfer: Transfer3D,
606*bb4ee6a4SAndroid Build Coastguard Worker     ) -> RutabagaResult<()> {
607*bb4ee6a4SAndroid Build Coastguard Worker         if transfer.is_empty() {
608*bb4ee6a4SAndroid Build Coastguard Worker             return Ok(());
609*bb4ee6a4SAndroid Build Coastguard Worker         }
610*bb4ee6a4SAndroid Build Coastguard Worker 
611*bb4ee6a4SAndroid Build Coastguard Worker         let mut transfer_box = VirglBox {
612*bb4ee6a4SAndroid Build Coastguard Worker             x: transfer.x,
613*bb4ee6a4SAndroid Build Coastguard Worker             y: transfer.y,
614*bb4ee6a4SAndroid Build Coastguard Worker             z: transfer.z,
615*bb4ee6a4SAndroid Build Coastguard Worker             w: transfer.w,
616*bb4ee6a4SAndroid Build Coastguard Worker             h: transfer.h,
617*bb4ee6a4SAndroid Build Coastguard Worker             d: transfer.d,
618*bb4ee6a4SAndroid Build Coastguard Worker         };
619*bb4ee6a4SAndroid Build Coastguard Worker 
620*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
621*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because only stack variables of the appropriate type are used.
622*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe {
623*bb4ee6a4SAndroid Build Coastguard Worker             virgl_renderer_transfer_write_iov(
624*bb4ee6a4SAndroid Build Coastguard Worker                 resource.resource_id,
625*bb4ee6a4SAndroid Build Coastguard Worker                 ctx_id,
626*bb4ee6a4SAndroid Build Coastguard Worker                 transfer.level as i32,
627*bb4ee6a4SAndroid Build Coastguard Worker                 transfer.stride,
628*bb4ee6a4SAndroid Build Coastguard Worker                 transfer.layer_stride,
629*bb4ee6a4SAndroid Build Coastguard Worker                 &mut transfer_box as *mut VirglBox as *mut virgl_box,
630*bb4ee6a4SAndroid Build Coastguard Worker                 transfer.offset,
631*bb4ee6a4SAndroid Build Coastguard Worker                 null_mut(),
632*bb4ee6a4SAndroid Build Coastguard Worker                 0,
633*bb4ee6a4SAndroid Build Coastguard Worker             )
634*bb4ee6a4SAndroid Build Coastguard Worker         };
635*bb4ee6a4SAndroid Build Coastguard Worker         ret_to_res(ret)
636*bb4ee6a4SAndroid Build Coastguard Worker     }
637*bb4ee6a4SAndroid Build Coastguard Worker 
transfer_read( &self, ctx_id: u32, resource: &mut RutabagaResource, transfer: Transfer3D, buf: Option<IoSliceMut>, ) -> RutabagaResult<()>638*bb4ee6a4SAndroid Build Coastguard Worker     fn transfer_read(
639*bb4ee6a4SAndroid Build Coastguard Worker         &self,
640*bb4ee6a4SAndroid Build Coastguard Worker         ctx_id: u32,
641*bb4ee6a4SAndroid Build Coastguard Worker         resource: &mut RutabagaResource,
642*bb4ee6a4SAndroid Build Coastguard Worker         transfer: Transfer3D,
643*bb4ee6a4SAndroid Build Coastguard Worker         buf: Option<IoSliceMut>,
644*bb4ee6a4SAndroid Build Coastguard Worker     ) -> RutabagaResult<()> {
645*bb4ee6a4SAndroid Build Coastguard Worker         if transfer.is_empty() {
646*bb4ee6a4SAndroid Build Coastguard Worker             return Ok(());
647*bb4ee6a4SAndroid Build Coastguard Worker         }
648*bb4ee6a4SAndroid Build Coastguard Worker 
649*bb4ee6a4SAndroid Build Coastguard Worker         let mut transfer_box = VirglBox {
650*bb4ee6a4SAndroid Build Coastguard Worker             x: transfer.x,
651*bb4ee6a4SAndroid Build Coastguard Worker             y: transfer.y,
652*bb4ee6a4SAndroid Build Coastguard Worker             z: transfer.z,
653*bb4ee6a4SAndroid Build Coastguard Worker             w: transfer.w,
654*bb4ee6a4SAndroid Build Coastguard Worker             h: transfer.h,
655*bb4ee6a4SAndroid Build Coastguard Worker             d: transfer.d,
656*bb4ee6a4SAndroid Build Coastguard Worker         };
657*bb4ee6a4SAndroid Build Coastguard Worker 
658*bb4ee6a4SAndroid Build Coastguard Worker         let mut iov = RutabagaIovec {
659*bb4ee6a4SAndroid Build Coastguard Worker             base: null_mut(),
660*bb4ee6a4SAndroid Build Coastguard Worker             len: 0,
661*bb4ee6a4SAndroid Build Coastguard Worker         };
662*bb4ee6a4SAndroid Build Coastguard Worker 
663*bb4ee6a4SAndroid Build Coastguard Worker         let (iovecs, num_iovecs) = match buf {
664*bb4ee6a4SAndroid Build Coastguard Worker             Some(mut buf) => {
665*bb4ee6a4SAndroid Build Coastguard Worker                 iov.base = buf.as_mut_ptr() as *mut c_void;
666*bb4ee6a4SAndroid Build Coastguard Worker                 iov.len = buf.len();
667*bb4ee6a4SAndroid Build Coastguard Worker                 (&mut iov as *mut RutabagaIovec as *mut iovec, 1)
668*bb4ee6a4SAndroid Build Coastguard Worker             }
669*bb4ee6a4SAndroid Build Coastguard Worker             None => (null_mut(), 0),
670*bb4ee6a4SAndroid Build Coastguard Worker         };
671*bb4ee6a4SAndroid Build Coastguard Worker 
672*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
673*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because only stack variables of the appropriate type are used.
674*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe {
675*bb4ee6a4SAndroid Build Coastguard Worker             virgl_renderer_transfer_read_iov(
676*bb4ee6a4SAndroid Build Coastguard Worker                 resource.resource_id,
677*bb4ee6a4SAndroid Build Coastguard Worker                 ctx_id,
678*bb4ee6a4SAndroid Build Coastguard Worker                 transfer.level,
679*bb4ee6a4SAndroid Build Coastguard Worker                 transfer.stride,
680*bb4ee6a4SAndroid Build Coastguard Worker                 transfer.layer_stride,
681*bb4ee6a4SAndroid Build Coastguard Worker                 &mut transfer_box as *mut VirglBox as *mut virgl_box,
682*bb4ee6a4SAndroid Build Coastguard Worker                 transfer.offset,
683*bb4ee6a4SAndroid Build Coastguard Worker                 iovecs,
684*bb4ee6a4SAndroid Build Coastguard Worker                 num_iovecs,
685*bb4ee6a4SAndroid Build Coastguard Worker             )
686*bb4ee6a4SAndroid Build Coastguard Worker         };
687*bb4ee6a4SAndroid Build Coastguard Worker         ret_to_res(ret)
688*bb4ee6a4SAndroid Build Coastguard Worker     }
689*bb4ee6a4SAndroid Build Coastguard Worker 
690*bb4ee6a4SAndroid Build Coastguard Worker     #[allow(unused_variables)]
create_blob( &mut self, ctx_id: u32, resource_id: u32, resource_create_blob: ResourceCreateBlob, mut iovec_opt: Option<Vec<RutabagaIovec>>, _handle_opt: Option<RutabagaHandle>, ) -> RutabagaResult<RutabagaResource>691*bb4ee6a4SAndroid Build Coastguard Worker     fn create_blob(
692*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
693*bb4ee6a4SAndroid Build Coastguard Worker         ctx_id: u32,
694*bb4ee6a4SAndroid Build Coastguard Worker         resource_id: u32,
695*bb4ee6a4SAndroid Build Coastguard Worker         resource_create_blob: ResourceCreateBlob,
696*bb4ee6a4SAndroid Build Coastguard Worker         mut iovec_opt: Option<Vec<RutabagaIovec>>,
697*bb4ee6a4SAndroid Build Coastguard Worker         _handle_opt: Option<RutabagaHandle>,
698*bb4ee6a4SAndroid Build Coastguard Worker     ) -> RutabagaResult<RutabagaResource> {
699*bb4ee6a4SAndroid Build Coastguard Worker         let mut iovec_ptr = null_mut();
700*bb4ee6a4SAndroid Build Coastguard Worker         let mut num_iovecs = 0;
701*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(ref mut iovecs) = iovec_opt {
702*bb4ee6a4SAndroid Build Coastguard Worker             iovec_ptr = iovecs.as_mut_ptr();
703*bb4ee6a4SAndroid Build Coastguard Worker             num_iovecs = iovecs.len();
704*bb4ee6a4SAndroid Build Coastguard Worker         }
705*bb4ee6a4SAndroid Build Coastguard Worker 
706*bb4ee6a4SAndroid Build Coastguard Worker         let resource_create_args = virgl_renderer_resource_create_blob_args {
707*bb4ee6a4SAndroid Build Coastguard Worker             res_handle: resource_id,
708*bb4ee6a4SAndroid Build Coastguard Worker             ctx_id,
709*bb4ee6a4SAndroid Build Coastguard Worker             blob_mem: resource_create_blob.blob_mem,
710*bb4ee6a4SAndroid Build Coastguard Worker             blob_flags: resource_create_blob.blob_flags,
711*bb4ee6a4SAndroid Build Coastguard Worker             blob_id: resource_create_blob.blob_id,
712*bb4ee6a4SAndroid Build Coastguard Worker             size: resource_create_blob.size,
713*bb4ee6a4SAndroid Build Coastguard Worker             iovecs: iovec_ptr as *const iovec,
714*bb4ee6a4SAndroid Build Coastguard Worker             num_iovs: num_iovecs as u32,
715*bb4ee6a4SAndroid Build Coastguard Worker         };
716*bb4ee6a4SAndroid Build Coastguard Worker 
717*bb4ee6a4SAndroid Build Coastguard Worker         // TODO(b/315870313): Add safety comment
718*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(clippy::undocumented_unsafe_blocks)]
719*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { virgl_renderer_resource_create_blob(&resource_create_args) };
720*bb4ee6a4SAndroid Build Coastguard Worker         ret_to_res(ret)?;
721*bb4ee6a4SAndroid Build Coastguard Worker 
722*bb4ee6a4SAndroid Build Coastguard Worker         // TODO(b/244591751): assign vulkan_info to support opaque_fd mapping via Vulkano when
723*bb4ee6a4SAndroid Build Coastguard Worker         // sandboxing (hence external_blob) is enabled.
724*bb4ee6a4SAndroid Build Coastguard Worker         Ok(RutabagaResource {
725*bb4ee6a4SAndroid Build Coastguard Worker             resource_id,
726*bb4ee6a4SAndroid Build Coastguard Worker             handle: self.export_blob(resource_id).ok(),
727*bb4ee6a4SAndroid Build Coastguard Worker             blob: true,
728*bb4ee6a4SAndroid Build Coastguard Worker             blob_mem: resource_create_blob.blob_mem,
729*bb4ee6a4SAndroid Build Coastguard Worker             blob_flags: resource_create_blob.blob_flags,
730*bb4ee6a4SAndroid Build Coastguard Worker             map_info: self.map_info(resource_id).ok(),
731*bb4ee6a4SAndroid Build Coastguard Worker             info_2d: None,
732*bb4ee6a4SAndroid Build Coastguard Worker             info_3d: self.query(resource_id).ok(),
733*bb4ee6a4SAndroid Build Coastguard Worker             vulkan_info: None,
734*bb4ee6a4SAndroid Build Coastguard Worker             backing_iovecs: iovec_opt,
735*bb4ee6a4SAndroid Build Coastguard Worker             component_mask: 1 << (RutabagaComponentType::VirglRenderer as u8),
736*bb4ee6a4SAndroid Build Coastguard Worker             size: resource_create_blob.size,
737*bb4ee6a4SAndroid Build Coastguard Worker             mapping: None,
738*bb4ee6a4SAndroid Build Coastguard Worker         })
739*bb4ee6a4SAndroid Build Coastguard Worker     }
740*bb4ee6a4SAndroid Build Coastguard Worker 
map(&self, resource_id: u32) -> RutabagaResult<RutabagaMapping>741*bb4ee6a4SAndroid Build Coastguard Worker     fn map(&self, resource_id: u32) -> RutabagaResult<RutabagaMapping> {
742*bb4ee6a4SAndroid Build Coastguard Worker         let mut map: *mut c_void = null_mut();
743*bb4ee6a4SAndroid Build Coastguard Worker         let mut size: u64 = 0;
744*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
745*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because virglrenderer wraps and validates use of GL/VK.
746*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { virgl_renderer_resource_map(resource_id, &mut map, &mut size) };
747*bb4ee6a4SAndroid Build Coastguard Worker         if ret != 0 {
748*bb4ee6a4SAndroid Build Coastguard Worker             return Err(RutabagaError::MappingFailed(ret));
749*bb4ee6a4SAndroid Build Coastguard Worker         }
750*bb4ee6a4SAndroid Build Coastguard Worker 
751*bb4ee6a4SAndroid Build Coastguard Worker         Ok(RutabagaMapping {
752*bb4ee6a4SAndroid Build Coastguard Worker             ptr: map as u64,
753*bb4ee6a4SAndroid Build Coastguard Worker             size,
754*bb4ee6a4SAndroid Build Coastguard Worker         })
755*bb4ee6a4SAndroid Build Coastguard Worker     }
756*bb4ee6a4SAndroid Build Coastguard Worker 
unmap(&self, resource_id: u32) -> RutabagaResult<()>757*bb4ee6a4SAndroid Build Coastguard Worker     fn unmap(&self, resource_id: u32) -> RutabagaResult<()> {
758*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
759*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because virglrenderer is initialized by now.
760*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { virgl_renderer_resource_unmap(resource_id) };
761*bb4ee6a4SAndroid Build Coastguard Worker         ret_to_res(ret)
762*bb4ee6a4SAndroid Build Coastguard Worker     }
763*bb4ee6a4SAndroid Build Coastguard Worker 
764*bb4ee6a4SAndroid Build Coastguard Worker     #[allow(unused_variables)]
export_fence(&self, fence_id: u64) -> RutabagaResult<RutabagaHandle>765*bb4ee6a4SAndroid Build Coastguard Worker     fn export_fence(&self, fence_id: u64) -> RutabagaResult<RutabagaHandle> {
766*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(virgl_renderer_unstable)]
767*bb4ee6a4SAndroid Build Coastguard Worker         {
768*bb4ee6a4SAndroid Build Coastguard Worker             let mut fd: i32 = 0;
769*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY:
770*bb4ee6a4SAndroid Build Coastguard Worker             // Safe because the parameters are stack variables of the correct type.
771*bb4ee6a4SAndroid Build Coastguard Worker             let ret = unsafe { virgl_renderer_export_fence(fence_id, &mut fd) };
772*bb4ee6a4SAndroid Build Coastguard Worker             ret_to_res(ret)?;
773*bb4ee6a4SAndroid Build Coastguard Worker 
774*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY:
775*bb4ee6a4SAndroid Build Coastguard Worker             // Safe because the FD was just returned by a successful virglrenderer call so it must
776*bb4ee6a4SAndroid Build Coastguard Worker             // be valid and owned by us.
777*bb4ee6a4SAndroid Build Coastguard Worker             let fence = unsafe { OwnedDescriptor::from_raw_descriptor(fd) };
778*bb4ee6a4SAndroid Build Coastguard Worker             Ok(RutabagaHandle {
779*bb4ee6a4SAndroid Build Coastguard Worker                 os_handle: fence,
780*bb4ee6a4SAndroid Build Coastguard Worker                 handle_type: RUTABAGA_FENCE_HANDLE_TYPE_SYNC_FD,
781*bb4ee6a4SAndroid Build Coastguard Worker             })
782*bb4ee6a4SAndroid Build Coastguard Worker         }
783*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(not(virgl_renderer_unstable))]
784*bb4ee6a4SAndroid Build Coastguard Worker         Err(RutabagaError::Unsupported)
785*bb4ee6a4SAndroid Build Coastguard Worker     }
786*bb4ee6a4SAndroid Build Coastguard Worker 
787*bb4ee6a4SAndroid Build Coastguard Worker     #[allow(unused_variables)]
create_context( &self, ctx_id: u32, context_init: u32, context_name: Option<&str>, _fence_handler: RutabagaFenceHandler, ) -> RutabagaResult<Box<dyn RutabagaContext>>788*bb4ee6a4SAndroid Build Coastguard Worker     fn create_context(
789*bb4ee6a4SAndroid Build Coastguard Worker         &self,
790*bb4ee6a4SAndroid Build Coastguard Worker         ctx_id: u32,
791*bb4ee6a4SAndroid Build Coastguard Worker         context_init: u32,
792*bb4ee6a4SAndroid Build Coastguard Worker         context_name: Option<&str>,
793*bb4ee6a4SAndroid Build Coastguard Worker         _fence_handler: RutabagaFenceHandler,
794*bb4ee6a4SAndroid Build Coastguard Worker     ) -> RutabagaResult<Box<dyn RutabagaContext>> {
795*bb4ee6a4SAndroid Build Coastguard Worker         let mut name: &str = "gpu_renderer";
796*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(name_string) = context_name.filter(|s| !s.is_empty()) {
797*bb4ee6a4SAndroid Build Coastguard Worker             name = name_string;
798*bb4ee6a4SAndroid Build Coastguard Worker         }
799*bb4ee6a4SAndroid Build Coastguard Worker 
800*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
801*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because virglrenderer is initialized by now and the context name is statically
802*bb4ee6a4SAndroid Build Coastguard Worker         // allocated. The return value is checked before returning a new context.
803*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe {
804*bb4ee6a4SAndroid Build Coastguard Worker             match context_init {
805*bb4ee6a4SAndroid Build Coastguard Worker                 0 => virgl_renderer_context_create(
806*bb4ee6a4SAndroid Build Coastguard Worker                     ctx_id,
807*bb4ee6a4SAndroid Build Coastguard Worker                     name.len() as u32,
808*bb4ee6a4SAndroid Build Coastguard Worker                     name.as_ptr() as *const c_char,
809*bb4ee6a4SAndroid Build Coastguard Worker                 ),
810*bb4ee6a4SAndroid Build Coastguard Worker                 _ => virgl_renderer_context_create_with_flags(
811*bb4ee6a4SAndroid Build Coastguard Worker                     ctx_id,
812*bb4ee6a4SAndroid Build Coastguard Worker                     context_init,
813*bb4ee6a4SAndroid Build Coastguard Worker                     name.len() as u32,
814*bb4ee6a4SAndroid Build Coastguard Worker                     name.as_ptr() as *const c_char,
815*bb4ee6a4SAndroid Build Coastguard Worker                 ),
816*bb4ee6a4SAndroid Build Coastguard Worker             }
817*bb4ee6a4SAndroid Build Coastguard Worker         };
818*bb4ee6a4SAndroid Build Coastguard Worker         ret_to_res(ret)?;
819*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Box::new(VirglRendererContext { ctx_id }))
820*bb4ee6a4SAndroid Build Coastguard Worker     }
821*bb4ee6a4SAndroid Build Coastguard Worker }
822