1use std::ffi::NulError;
8use std::fmt;
9use std::io::Error as IoError;
10use std::num::TryFromIntError;
11use std::os::raw::c_char;
12use std::os::raw::c_void;
13use std::path::PathBuf;
14use std::str::Utf8Error;
15use std::sync::Arc;
16
17#[cfg(any(target_os = "android", target_os = "linux"))]
18use nix::Error as NixError;
19use remain::sorted;
20use thiserror::Error;
21#[cfg(feature = "vulkano")]
22use vulkano::device::DeviceCreationError;
23#[cfg(feature = "vulkano")]
24use vulkano::image::ImageCreationError;
25#[cfg(feature = "vulkano")]
26use vulkano::instance::InstanceCreationError;
27#[cfg(feature = "vulkano")]
28use vulkano::memory::DeviceMemoryError;
29#[cfg(feature = "vulkano")]
30use vulkano::memory::MemoryMapError;
31#[cfg(feature = "vulkano")]
32use vulkano::LoadingError;
33#[cfg(feature = "vulkano")]
34use vulkano::VulkanError;
35
36use crate::rutabaga_os::SafeDescriptor;
37
38#[repr(C)]
41#[derive(Copy, Clone)]
42pub struct RutabagaIovec {
43 pub base: *mut c_void,
44 pub len: usize,
45}
46
47unsafe impl Send for RutabagaIovec {}
49
50unsafe impl Sync for RutabagaIovec {}
52
53pub const RUTABAGA_PIPE_TEXTURE_2D: u32 = 2;
57pub const RUTABAGA_PIPE_BIND_RENDER_TARGET: u32 = 2;
58#[repr(C)]
59#[derive(Copy, Clone, Debug)]
60pub struct ResourceCreate3D {
61 pub target: u32,
62 pub format: u32,
63 pub bind: u32,
64 pub width: u32,
65 pub height: u32,
66 pub depth: u32,
67 pub array_size: u32,
68 pub last_level: u32,
69 pub nr_samples: u32,
70 pub flags: u32,
71}
72
73pub const RUTABAGA_BLOB_MEM_GUEST: u32 = 0x0001;
75pub const RUTABAGA_BLOB_MEM_HOST3D: u32 = 0x0002;
76pub const RUTABAGA_BLOB_MEM_HOST3D_GUEST: u32 = 0x0003;
77
78pub const RUTABAGA_BLOB_FLAG_USE_MAPPABLE: u32 = 0x0001;
79pub const RUTABAGA_BLOB_FLAG_USE_SHAREABLE: u32 = 0x0002;
80pub const RUTABAGA_BLOB_FLAG_USE_CROSS_DEVICE: u32 = 0x0004;
81#[repr(C)]
82#[derive(Copy, Clone, Debug)]
83pub struct ResourceCreateBlob {
84 pub blob_mem: u32,
85 pub blob_flags: u32,
86 pub blob_id: u64,
87 pub size: u64,
88}
89
90#[repr(C)]
91#[derive(Copy, Clone, Debug)]
92pub struct RutabagaMapping {
93 pub ptr: u64,
94 pub size: u64,
95}
96
97#[derive(Default, Copy, Clone, Debug)]
99pub struct Resource3DInfo {
100 pub width: u32,
101 pub height: u32,
102 pub drm_fourcc: u32,
103 pub strides: [u32; 4],
104 pub offsets: [u32; 4],
105 pub modifier: u64,
106 pub guest_cpu_mappable: bool,
108}
109
110#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
112pub struct DeviceId {
113 pub device_uuid: [u8; 16],
114 pub driver_uuid: [u8; 16],
115}
116
117#[derive(Copy, Clone, Default)]
119pub struct VulkanInfo {
120 pub memory_idx: u32,
121 pub device_id: DeviceId,
122}
123
124pub const RUTABAGA_CONTEXT_INIT_CAPSET_ID_MASK: u32 = 0x00ff;
126
127pub const RUTABAGA_FLAG_FENCE: u32 = 1 << 0;
129pub const RUTABAGA_FLAG_INFO_RING_IDX: u32 = 1 << 1;
130pub const RUTABAGA_FLAG_FENCE_SHAREABLE: u32 = 1 << 2;
131
132#[repr(C)]
134#[derive(Copy, Clone)]
135pub struct RutabagaFence {
136 pub flags: u32,
137 pub fence_id: u64,
138 pub ctx_id: u32,
139 pub ring_idx: u8,
140}
141
142pub const RUTABAGA_DEBUG_ERROR: u32 = 0x01;
144pub const RUTABAGA_DEBUG_WARNING: u32 = 0x02;
145pub const RUTABAGA_DEBUG_INFO: u32 = 0x03;
146
147#[repr(C)]
149#[derive(Copy, Clone)]
150pub struct RutabagaDebug {
151 pub debug_type: u32,
152 pub message: *const c_char,
153}
154
155unsafe impl Send for RutabagaDebug {}
160unsafe impl Sync for RutabagaDebug {}
165
166pub const RUTABAGA_MAP_CACHE_MASK: u32 = 0x0f;
168pub const RUTABAGA_MAP_CACHE_CACHED: u32 = 0x01;
169pub const RUTABAGA_MAP_CACHE_UNCACHED: u32 = 0x02;
170pub const RUTABAGA_MAP_CACHE_WC: u32 = 0x03;
171pub const RUTABAGA_MAP_ACCESS_MASK: u32 = 0xf0;
173pub const RUTABAGA_MAP_ACCESS_READ: u32 = 0x10;
174pub const RUTABAGA_MAP_ACCESS_WRITE: u32 = 0x20;
175pub const RUTABAGA_MAP_ACCESS_RW: u32 = 0x30;
176
177pub const RUTABAGA_CAPSET_VIRGL: u32 = 1;
179pub const RUTABAGA_CAPSET_VIRGL2: u32 = 2;
180pub const RUTABAGA_CAPSET_GFXSTREAM_VULKAN: u32 = 3;
181pub const RUTABAGA_CAPSET_VENUS: u32 = 4;
182pub const RUTABAGA_CAPSET_CROSS_DOMAIN: u32 = 5;
183pub const RUTABAGA_CAPSET_DRM: u32 = 6;
184pub const RUTABAGA_CAPSET_GFXSTREAM_MAGMA: u32 = 7;
185pub const RUTABAGA_CAPSET_GFXSTREAM_GLES: u32 = 8;
186pub const RUTABAGA_CAPSET_GFXSTREAM_COMPOSER: u32 = 9;
187
188#[sorted]
190#[derive(Error, Debug)]
191pub enum RutabagaError {
192 #[error("attempted to use a rutabaga asset already in use")]
195 AlreadyInUse,
196 #[error("arithmetic failed: {}({}) {op} {}({})", .field1.0, .field1.1, .field2.0, .field2.1)]
198 CheckedArithmetic {
199 field1: (&'static str, usize),
200 field2: (&'static str, usize),
201 op: &'static str,
202 },
203 #[error("range check failed: {}({}) vs {}({})", .field1.0, .field1.1, .field2.0, .field2.1)]
205 CheckedRange {
206 field1: (&'static str, usize),
207 field2: (&'static str, usize),
208 },
209 #[error("rutabaga component failed with error {0}")]
211 ComponentError(i32),
212 #[error("invalid 2D info")]
214 Invalid2DInfo,
215 #[error("invalid capset")]
217 InvalidCapset,
218 #[error("invalid command buffer submitted")]
220 InvalidCommandBuffer,
221 #[error("command buffer submitted with invalid size: {0}")]
223 InvalidCommandSize(usize),
224 #[error("invalid rutabaga component")]
226 InvalidComponent,
227 #[error("invalid context id")]
229 InvalidContextId,
230 #[error("invalid cross domain channel")]
232 InvalidCrossDomainChannel,
233 #[error("invalid cross domain item id")]
235 InvalidCrossDomainItemId,
236 #[error("invalid cross domain item type")]
238 InvalidCrossDomainItemType,
239 #[error("invalid cross domain state")]
241 InvalidCrossDomainState,
242 #[error("invalid gralloc backend")]
244 InvalidGrallocBackend,
245 #[error("invalid gralloc dimensions")]
247 InvalidGrallocDimensions,
248 #[error("invalid gralloc DRM format")]
250 InvalidGrallocDrmFormat,
251 #[error("invalid GPU type for gralloc")]
253 InvalidGrallocGpuType,
254 #[error("invalid number of YUV planes")]
256 InvalidGrallocNumberOfPlanes,
257 #[error("an iovec is outside of guest memory's range")]
259 InvalidIovec,
260 #[error("invalid resource id")]
262 InvalidResourceId,
263 #[error("invalid rutabaga build parameters: {0}")]
265 InvalidRutabagaBuild(&'static str),
266 #[error("invalid rutabaga handle")]
268 InvalidRutabagaHandle,
269 #[error("invalid vulkan info")]
271 InvalidVulkanInfo,
272 #[error("an input/output error occur: {0}")]
274 IoError(IoError),
275 #[error("The mapping failed with library error: {0}")]
277 MappingFailed(i32),
278 #[cfg(any(target_os = "android", target_os = "linux"))]
280 #[error("The errno is {0}")]
281 NixError(NixError),
282 #[error("Nul Error occured {0}")]
283 NulError(NulError),
284 #[error("violation of the rutabaga spec: {0}")]
286 SpecViolation(&'static str),
287 #[error("int conversion failed: {0}")]
289 TryFromIntError(TryFromIntError),
290 #[error("the requested function is not implemented")]
292 Unsupported,
293 #[error("an utf8 error occured: {0}")]
295 Utf8Error(Utf8Error),
296 #[cfg(feature = "vulkano")]
298 #[error("vulkano device creation failure {0}")]
299 VkDeviceCreationError(DeviceCreationError),
300 #[cfg(feature = "vulkano")]
302 #[error("vulkano device memory failure {0}")]
303 VkDeviceMemoryError(DeviceMemoryError),
304 #[cfg(feature = "vulkano")]
306 #[error("vulkano failure {0}")]
307 VkError(VulkanError),
308 #[cfg(feature = "vulkano")]
310 #[error("vulkano image creation failure {0}")]
311 VkImageCreationError(ImageCreationError),
312 #[cfg(feature = "vulkano")]
314 #[error("vulkano instance creation failure {0}")]
315 VkInstanceCreationError(InstanceCreationError),
316 #[cfg(feature = "vulkano")]
318 #[error("vulkano loading failure {0}")]
319 VkLoadingError(LoadingError),
320 #[cfg(feature = "vulkano")]
322 #[error("vulkano memory map failure {0}")]
323 VkMemoryMapError(MemoryMapError),
324}
325
326#[cfg(any(target_os = "android", target_os = "linux"))]
327impl From<NixError> for RutabagaError {
328 fn from(e: NixError) -> RutabagaError {
329 RutabagaError::NixError(e)
330 }
331}
332
333impl From<NulError> for RutabagaError {
334 fn from(e: NulError) -> RutabagaError {
335 RutabagaError::NulError(e)
336 }
337}
338
339impl From<IoError> for RutabagaError {
340 fn from(e: IoError) -> RutabagaError {
341 RutabagaError::IoError(e)
342 }
343}
344
345impl From<TryFromIntError> for RutabagaError {
346 fn from(e: TryFromIntError) -> RutabagaError {
347 RutabagaError::TryFromIntError(e)
348 }
349}
350
351impl From<Utf8Error> for RutabagaError {
352 fn from(e: Utf8Error) -> RutabagaError {
353 RutabagaError::Utf8Error(e)
354 }
355}
356
357pub type RutabagaResult<T> = std::result::Result<T, RutabagaError>;
359
360const VIRGLRENDERER_USE_EGL: u32 = 1 << 0;
362const VIRGLRENDERER_THREAD_SYNC: u32 = 1 << 1;
363const VIRGLRENDERER_USE_GLX: u32 = 1 << 2;
364const VIRGLRENDERER_USE_SURFACELESS: u32 = 1 << 3;
365const VIRGLRENDERER_USE_GLES: u32 = 1 << 4;
366const VIRGLRENDERER_USE_EXTERNAL_BLOB: u32 = 1 << 5;
367const VIRGLRENDERER_VENUS: u32 = 1 << 6;
368const VIRGLRENDERER_NO_VIRGL: u32 = 1 << 7;
369const VIRGLRENDERER_USE_ASYNC_FENCE_CB: u32 = 1 << 8;
370const VIRGLRENDERER_RENDER_SERVER: u32 = 1 << 9;
371const VIRGLRENDERER_DRM: u32 = 1 << 10;
372
373#[derive(Copy, Clone)]
375pub struct VirglRendererFlags(u32);
376
377impl Default for VirglRendererFlags {
378 fn default() -> VirglRendererFlags {
379 VirglRendererFlags::new()
380 .use_virgl(true)
381 .use_venus(false)
382 .use_egl(true)
383 .use_surfaceless(true)
384 .use_gles(true)
385 .use_render_server(false)
386 }
387}
388
389impl From<VirglRendererFlags> for u32 {
390 fn from(flags: VirglRendererFlags) -> u32 {
391 flags.0
392 }
393}
394
395impl From<VirglRendererFlags> for i32 {
396 fn from(flags: VirglRendererFlags) -> i32 {
397 flags.0 as i32
398 }
399}
400
401impl VirglRendererFlags {
402 pub fn new() -> VirglRendererFlags {
404 VirglRendererFlags(0)
405 }
406
407 fn set_flag(self, bitmask: u32, set: bool) -> VirglRendererFlags {
408 if set {
409 VirglRendererFlags(self.0 | bitmask)
410 } else {
411 VirglRendererFlags(self.0 & (!bitmask))
412 }
413 }
414
415 pub fn use_virgl(self, v: bool) -> VirglRendererFlags {
417 self.set_flag(VIRGLRENDERER_NO_VIRGL, !v)
418 }
419
420 pub fn use_venus(self, v: bool) -> VirglRendererFlags {
422 self.set_flag(VIRGLRENDERER_VENUS, v)
423 }
424
425 pub fn use_drm(self, v: bool) -> VirglRendererFlags {
427 self.set_flag(VIRGLRENDERER_DRM, v)
428 }
429
430 pub fn use_egl(self, v: bool) -> VirglRendererFlags {
432 self.set_flag(VIRGLRENDERER_USE_EGL, v)
433 }
434
435 pub fn use_thread_sync(self, v: bool) -> VirglRendererFlags {
437 self.set_flag(VIRGLRENDERER_THREAD_SYNC, v)
438 }
439
440 pub fn use_glx(self, v: bool) -> VirglRendererFlags {
442 self.set_flag(VIRGLRENDERER_USE_GLX, v)
443 }
444
445 pub fn use_surfaceless(self, v: bool) -> VirglRendererFlags {
447 self.set_flag(VIRGLRENDERER_USE_SURFACELESS, v)
448 }
449
450 pub fn use_gles(self, v: bool) -> VirglRendererFlags {
452 self.set_flag(VIRGLRENDERER_USE_GLES, v)
453 }
454
455 pub fn use_external_blob(self, v: bool) -> VirglRendererFlags {
457 self.set_flag(VIRGLRENDERER_USE_EXTERNAL_BLOB, v)
458 }
459
460 pub fn use_async_fence_cb(self, v: bool) -> VirglRendererFlags {
462 self.set_flag(VIRGLRENDERER_USE_ASYNC_FENCE_CB, v)
463 }
464
465 pub fn use_render_server(self, v: bool) -> VirglRendererFlags {
466 self.set_flag(VIRGLRENDERER_RENDER_SERVER, v)
467 }
468}
469
470const STREAM_RENDERER_FLAGS_USE_EGL: u32 = 1 << 0;
472#[allow(dead_code)]
473const STREAM_RENDERER_FLAGS_THREAD_SYNC: u32 = 1 << 1;
474const STREAM_RENDERER_FLAGS_USE_GLX: u32 = 1 << 2;
475const STREAM_RENDERER_FLAGS_USE_SURFACELESS: u32 = 1 << 3;
476const STREAM_RENDERER_FLAGS_USE_GLES: u32 = 1 << 4;
477const STREAM_RENDERER_FLAGS_USE_VK_BIT: u32 = 1 << 5;
478const STREAM_RENDERER_FLAGS_USE_EXTERNAL_BLOB: u32 = 1 << 6;
479const STREAM_RENDERER_FLAGS_USE_SYSTEM_BLOB: u32 = 1 << 7;
480const STREAM_RENDERER_FLAGS_VULKAN_NATIVE_SWAPCHAIN_BIT: u32 = 1 << 8;
481
482#[derive(Copy, Clone, Default)]
484pub struct GfxstreamFlags(u32);
485
486#[derive(Clone, Debug)]
487pub enum RutabagaWsi {
488 Surfaceless,
489 VulkanSwapchain,
490}
491
492impl GfxstreamFlags {
493 pub fn new() -> GfxstreamFlags {
495 GfxstreamFlags(0)
496 }
497
498 fn set_flag(self, bitmask: u32, set: bool) -> GfxstreamFlags {
499 if set {
500 GfxstreamFlags(self.0 | bitmask)
501 } else {
502 GfxstreamFlags(self.0 & (!bitmask))
503 }
504 }
505
506 pub fn use_egl(self, v: bool) -> GfxstreamFlags {
508 self.set_flag(STREAM_RENDERER_FLAGS_USE_EGL, v)
509 }
510
511 pub fn use_glx(self, v: bool) -> GfxstreamFlags {
513 self.set_flag(STREAM_RENDERER_FLAGS_USE_GLX, v)
514 }
515
516 pub fn use_surfaceless(self, v: bool) -> GfxstreamFlags {
518 self.set_flag(STREAM_RENDERER_FLAGS_USE_SURFACELESS, v)
519 }
520
521 pub fn use_gles(self, v: bool) -> GfxstreamFlags {
523 self.set_flag(STREAM_RENDERER_FLAGS_USE_GLES, v)
524 }
525
526 pub fn use_vulkan(self, v: bool) -> GfxstreamFlags {
528 self.set_flag(STREAM_RENDERER_FLAGS_USE_VK_BIT, v)
529 }
530
531 pub fn set_wsi(self, v: RutabagaWsi) -> GfxstreamFlags {
533 let use_vulkan_swapchain = matches!(v, RutabagaWsi::VulkanSwapchain);
534 self.set_flag(
535 STREAM_RENDERER_FLAGS_VULKAN_NATIVE_SWAPCHAIN_BIT,
536 use_vulkan_swapchain,
537 )
538 }
539
540 pub fn use_external_blob(self, v: bool) -> GfxstreamFlags {
542 self.set_flag(STREAM_RENDERER_FLAGS_USE_EXTERNAL_BLOB, v)
543 }
544
545 pub fn use_system_blob(self, v: bool) -> GfxstreamFlags {
547 self.set_flag(STREAM_RENDERER_FLAGS_USE_SYSTEM_BLOB, v)
548 }
549}
550
551impl From<GfxstreamFlags> for u32 {
552 fn from(flags: GfxstreamFlags) -> u32 {
553 flags.0
554 }
555}
556
557impl From<GfxstreamFlags> for i32 {
558 fn from(flags: GfxstreamFlags) -> i32 {
559 flags.0 as i32
560 }
561}
562
563impl From<GfxstreamFlags> for u64 {
564 fn from(flags: GfxstreamFlags) -> u64 {
565 flags.0 as u64
566 }
567}
568
569#[repr(C)]
571#[derive(Copy, Clone, Debug)]
572pub struct Transfer3D {
573 pub x: u32,
574 pub y: u32,
575 pub z: u32,
576 pub w: u32,
577 pub h: u32,
578 pub d: u32,
579 pub level: u32,
580 pub stride: u32,
581 pub layer_stride: u32,
582 pub offset: u64,
583}
584
585impl Transfer3D {
586 pub fn new_2d(x: u32, y: u32, w: u32, h: u32) -> Transfer3D {
589 Transfer3D {
590 x,
591 y,
592 z: 0,
593 w,
594 h,
595 d: 1,
596 level: 0,
597 stride: 0,
598 layer_stride: 0,
599 offset: 0,
600 }
601 }
602
603 pub fn is_empty(&self) -> bool {
605 self.w == 0 || self.h == 0 || self.d == 0
606 }
607}
608
609pub const RUTABAGA_CHANNEL_TYPE_WAYLAND: u32 = 0x0001;
611pub const RUTABAGA_CHANNEL_TYPE_CAMERA: u32 = 0x0002;
612
613#[derive(Clone)]
616pub struct RutabagaChannel {
617 pub base_channel: PathBuf,
618 pub channel_type: u32,
619}
620
621#[repr(u8)]
623#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)]
624pub enum RutabagaComponentType {
625 Rutabaga2D,
626 VirglRenderer,
627 Gfxstream,
628 CrossDomain,
629}
630
631pub const RUTABAGA_MEM_HANDLE_TYPE_OPAQUE_FD: u32 = 0x0001;
633pub const RUTABAGA_MEM_HANDLE_TYPE_DMABUF: u32 = 0x0002;
634pub const RUTABAGA_MEM_HANDLE_TYPE_OPAQUE_WIN32: u32 = 0x0003;
635pub const RUTABAGA_MEM_HANDLE_TYPE_SHM: u32 = 0x0004;
636pub const RUTABAGA_MEM_HANDLE_TYPE_ZIRCON: u32 = 0x0005;
637
638pub const RUTABAGA_FENCE_HANDLE_TYPE_OPAQUE_FD: u32 = 0x0006;
639pub const RUTABAGA_FENCE_HANDLE_TYPE_SYNC_FD: u32 = 0x0007;
640pub const RUTABAGA_FENCE_HANDLE_TYPE_OPAQUE_WIN32: u32 = 0x0008;
641pub const RUTABAGA_FENCE_HANDLE_TYPE_ZIRCON: u32 = 0x0009;
642
643pub struct RutabagaHandle {
645 pub os_handle: SafeDescriptor,
646 pub handle_type: u32,
647}
648
649impl RutabagaHandle {
650 pub fn try_clone(&self) -> RutabagaResult<RutabagaHandle> {
652 let clone = self
653 .os_handle
654 .try_clone()
655 .map_err(|_| RutabagaError::InvalidRutabagaHandle)?;
656 Ok(RutabagaHandle {
657 os_handle: clone,
658 handle_type: self.handle_type,
659 })
660 }
661}
662
663#[derive(Clone)]
664pub struct RutabagaHandler<S> {
665 closure: Arc<dyn Fn(S) + Send + Sync>,
666}
667
668impl<S> RutabagaHandler<S>
669where
670 S: Send + Sync + Clone + 'static,
671{
672 pub fn new(closure: impl Fn(S) + Send + Sync + 'static) -> RutabagaHandler<S> {
673 RutabagaHandler {
674 closure: Arc::new(closure),
675 }
676 }
677
678 pub fn call(&self, data: S) {
679 (self.closure)(data)
680 }
681}
682
683impl<S> fmt::Debug for RutabagaHandler<S> {
684 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
685 f.debug_struct("Closure debug").finish()
686 }
687}
688
689pub type RutabagaFenceHandler = RutabagaHandler<RutabagaFence>;
690
691pub type RutabagaDebugHandler = RutabagaHandler<RutabagaDebug>;