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