rutabaga_gfx/
rutabaga_utils.rs

1// Copyright 2020 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! rutabaga_utils: Utility enums, structs, and implementations needed by the rest of the crate.
6
7use 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/// Represents a buffer.  `base` contains the address of a buffer, while `len` contains the length
39/// of the buffer.
40#[repr(C)]
41#[derive(Copy, Clone)]
42pub struct RutabagaIovec {
43    pub base: *mut c_void,
44    pub len: usize,
45}
46
47// SAFETY: trivially safe
48unsafe impl Send for RutabagaIovec {}
49
50// SAFETY: trivially safe
51unsafe impl Sync for RutabagaIovec {}
52
53/// 3D resource creation parameters.  Also used to create 2D resource.  Constants based on Mesa's
54/// (internal) Gallium interface.  Not in the virtio-gpu spec, but should be since dumb resources
55/// can't work with gfxstream/virglrenderer without this.
56pub 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
73/// Blob resource creation parameters.
74pub 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/// Metadata associated with a swapchain, video or camera image.
98#[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    /// Whether the buffer can be accessed by the guest CPU.
107    pub guest_cpu_mappable: bool,
108}
109
110/// A unique identifier for a device.
111#[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/// Memory index and physical device id of the associated VkDeviceMemory.
118#[derive(Copy, Clone, Default)]
119pub struct VulkanInfo {
120    pub memory_idx: u32,
121    pub device_id: DeviceId,
122}
123
124/// Rutabaga context init capset id mask.
125pub const RUTABAGA_CONTEXT_INIT_CAPSET_ID_MASK: u32 = 0x00ff;
126
127/// Rutabaga flags for creating fences.
128pub 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/// Convenience struct for Rutabaga fences
133#[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
142/// Rutabaga debug types
143pub const RUTABAGA_DEBUG_ERROR: u32 = 0x01;
144pub const RUTABAGA_DEBUG_WARNING: u32 = 0x02;
145pub const RUTABAGA_DEBUG_INFO: u32 = 0x03;
146
147/// Convenience struct for debug data
148#[repr(C)]
149#[derive(Copy, Clone)]
150pub struct RutabagaDebug {
151    pub debug_type: u32,
152    pub message: *const c_char,
153}
154
155// SAFETY:
156// This is sketchy, since `message` is a C-string and there's no locking + atomics.  However,
157// the current use case is to mirror the C-API.  If the `RutabagaDebugHandler` is used with
158// by Rust code, a different struct should be used.
159unsafe impl Send for RutabagaDebug {}
160// SAFETY:
161// This is sketchy, since `message` is a C-string and there's no locking + atomics.  However,
162// the current use case is to mirror the C-API.  If the `RutabagaDebugHandler` is used with
163// by Rust code, a different struct should be used.
164unsafe impl Sync for RutabagaDebug {}
165
166/// Mapped memory caching flags (see virtio_gpu spec)
167pub 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;
171/// Access flags (not in virtio_gpu spec)
172pub 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
177/// Rutabaga capsets.
178pub 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/// An error generated while using this crate.
189#[sorted]
190#[derive(Error, Debug)]
191pub enum RutabagaError {
192    /// Indicates `Rutabaga` was already initialized since only one Rutabaga instance per process
193    /// is allowed.
194    #[error("attempted to use a rutabaga asset already in use")]
195    AlreadyInUse,
196    /// Checked Arithmetic error
197    #[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    /// Checked Range error
204    #[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    /// An internal Rutabaga component error was returned.
210    #[error("rutabaga component failed with error {0}")]
211    ComponentError(i32),
212    /// Invalid 2D info
213    #[error("invalid 2D info")]
214    Invalid2DInfo,
215    /// Invalid Capset
216    #[error("invalid capset")]
217    InvalidCapset,
218    /// A command buffer with insufficient space was submitted.
219    #[error("invalid command buffer submitted")]
220    InvalidCommandBuffer,
221    /// A command size was submitted that was invalid.
222    #[error("command buffer submitted with invalid size: {0}")]
223    InvalidCommandSize(usize),
224    /// Invalid RutabagaComponent
225    #[error("invalid rutabaga component")]
226    InvalidComponent,
227    /// Invalid Context ID
228    #[error("invalid context id")]
229    InvalidContextId,
230    /// Invalid cross domain channel
231    #[error("invalid cross domain channel")]
232    InvalidCrossDomainChannel,
233    /// Invalid cross domain item ID
234    #[error("invalid cross domain item id")]
235    InvalidCrossDomainItemId,
236    /// Invalid cross domain item type
237    #[error("invalid cross domain item type")]
238    InvalidCrossDomainItemType,
239    /// Invalid cross domain state
240    #[error("invalid cross domain state")]
241    InvalidCrossDomainState,
242    /// Invalid gralloc backend.
243    #[error("invalid gralloc backend")]
244    InvalidGrallocBackend,
245    /// Invalid gralloc dimensions.
246    #[error("invalid gralloc dimensions")]
247    InvalidGrallocDimensions,
248    /// Invalid gralloc DRM format.
249    #[error("invalid gralloc DRM format")]
250    InvalidGrallocDrmFormat,
251    /// Invalid GPU type.
252    #[error("invalid GPU type for gralloc")]
253    InvalidGrallocGpuType,
254    /// Invalid number of YUV planes.
255    #[error("invalid number of YUV planes")]
256    InvalidGrallocNumberOfPlanes,
257    /// The indicated region of guest memory is invalid.
258    #[error("an iovec is outside of guest memory's range")]
259    InvalidIovec,
260    /// Invalid Resource ID.
261    #[error("invalid resource id")]
262    InvalidResourceId,
263    /// Indicates an error in the RutabagaBuilder.
264    #[error("invalid rutabaga build parameters: {0}")]
265    InvalidRutabagaBuild(&'static str),
266    /// An error with the RutabagaHandle
267    #[error("invalid rutabaga handle")]
268    InvalidRutabagaHandle,
269    /// Invalid Vulkan info
270    #[error("invalid vulkan info")]
271    InvalidVulkanInfo,
272    /// An input/output error occured.
273    #[error("an input/output error occur: {0}")]
274    IoError(IoError),
275    /// The mapping failed.
276    #[error("The mapping failed with library error: {0}")]
277    MappingFailed(i32),
278    /// Nix crate error.
279    #[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    /// Violation of the Rutabaga spec occured.
285    #[error("violation of the rutabaga spec: {0}")]
286    SpecViolation(&'static str),
287    /// An attempted integer conversion failed.
288    #[error("int conversion failed: {0}")]
289    TryFromIntError(TryFromIntError),
290    /// The command is unsupported.
291    #[error("the requested function is not implemented")]
292    Unsupported,
293    /// Utf8 error.
294    #[error("an utf8 error occured: {0}")]
295    Utf8Error(Utf8Error),
296    /// Device creation error
297    #[cfg(feature = "vulkano")]
298    #[error("vulkano device creation failure {0}")]
299    VkDeviceCreationError(DeviceCreationError),
300    /// Device memory error
301    #[cfg(feature = "vulkano")]
302    #[error("vulkano device memory failure {0}")]
303    VkDeviceMemoryError(DeviceMemoryError),
304    /// General Vulkan error
305    #[cfg(feature = "vulkano")]
306    #[error("vulkano failure {0}")]
307    VkError(VulkanError),
308    /// Image creation error
309    #[cfg(feature = "vulkano")]
310    #[error("vulkano image creation failure {0}")]
311    VkImageCreationError(ImageCreationError),
312    /// Instance creation error
313    #[cfg(feature = "vulkano")]
314    #[error("vulkano instance creation failure {0}")]
315    VkInstanceCreationError(InstanceCreationError),
316    /// Loading error
317    #[cfg(feature = "vulkano")]
318    #[error("vulkano loading failure {0}")]
319    VkLoadingError(LoadingError),
320    /// Memory map error
321    #[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
357/// The result of an operation in this crate.
358pub type RutabagaResult<T> = std::result::Result<T, RutabagaError>;
359
360/// Flags for virglrenderer.  Copied from virglrenderer bindings.
361const 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/// virglrenderer flag struct.
374#[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    /// Create new virglrenderer flags.
403    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    /// Enable virgl support
416    pub fn use_virgl(self, v: bool) -> VirglRendererFlags {
417        self.set_flag(VIRGLRENDERER_NO_VIRGL, !v)
418    }
419
420    /// Enable venus support
421    pub fn use_venus(self, v: bool) -> VirglRendererFlags {
422        self.set_flag(VIRGLRENDERER_VENUS, v)
423    }
424
425    /// Enable drm native context support
426    pub fn use_drm(self, v: bool) -> VirglRendererFlags {
427        self.set_flag(VIRGLRENDERER_DRM, v)
428    }
429
430    /// Use EGL for context creation.
431    pub fn use_egl(self, v: bool) -> VirglRendererFlags {
432        self.set_flag(VIRGLRENDERER_USE_EGL, v)
433    }
434
435    /// Use a dedicated thread for fence synchronization.
436    pub fn use_thread_sync(self, v: bool) -> VirglRendererFlags {
437        self.set_flag(VIRGLRENDERER_THREAD_SYNC, v)
438    }
439
440    /// Use GLX for context creation.
441    pub fn use_glx(self, v: bool) -> VirglRendererFlags {
442        self.set_flag(VIRGLRENDERER_USE_GLX, v)
443    }
444
445    /// No surfaces required when creating context.
446    pub fn use_surfaceless(self, v: bool) -> VirglRendererFlags {
447        self.set_flag(VIRGLRENDERER_USE_SURFACELESS, v)
448    }
449
450    /// Use GLES drivers.
451    pub fn use_gles(self, v: bool) -> VirglRendererFlags {
452        self.set_flag(VIRGLRENDERER_USE_GLES, v)
453    }
454
455    /// Use external memory when creating blob resources.
456    pub fn use_external_blob(self, v: bool) -> VirglRendererFlags {
457        self.set_flag(VIRGLRENDERER_USE_EXTERNAL_BLOB, v)
458    }
459
460    /// Retire fence directly from sync thread.
461    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
470/// Flags for the gfxstream renderer.
471const 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/// gfxstream flag struct.
483#[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    /// Create new gfxstream flags.
494    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    /// Use EGL for context creation.
507    pub fn use_egl(self, v: bool) -> GfxstreamFlags {
508        self.set_flag(STREAM_RENDERER_FLAGS_USE_EGL, v)
509    }
510
511    /// Use GLX for context creation.
512    pub fn use_glx(self, v: bool) -> GfxstreamFlags {
513        self.set_flag(STREAM_RENDERER_FLAGS_USE_GLX, v)
514    }
515
516    /// No surfaces required when creating context.
517    pub fn use_surfaceless(self, v: bool) -> GfxstreamFlags {
518        self.set_flag(STREAM_RENDERER_FLAGS_USE_SURFACELESS, v)
519    }
520
521    /// Use GLES drivers.
522    pub fn use_gles(self, v: bool) -> GfxstreamFlags {
523        self.set_flag(STREAM_RENDERER_FLAGS_USE_GLES, v)
524    }
525
526    /// Support using Vulkan.
527    pub fn use_vulkan(self, v: bool) -> GfxstreamFlags {
528        self.set_flag(STREAM_RENDERER_FLAGS_USE_VK_BIT, v)
529    }
530
531    /// Use the Vulkan swapchain to draw on the host window.
532    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    /// Use external blob when creating resources.
541    pub fn use_external_blob(self, v: bool) -> GfxstreamFlags {
542        self.set_flag(STREAM_RENDERER_FLAGS_USE_EXTERNAL_BLOB, v)
543    }
544
545    /// Use system blob when creating resources.
546    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/// Transfers {to, from} 1D buffers, 2D textures, 3D textures, and cubemaps.
570#[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    /// Constructs a 2 dimensional XY box in 3 dimensional space with unit depth and zero
587    /// displacement on the Z axis.
588    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    /// Returns true if this box represents a volume of zero.
604    pub fn is_empty(&self) -> bool {
605        self.w == 0 || self.h == 0 || self.d == 0
606    }
607}
608
609/// Rutabaga channel types
610pub const RUTABAGA_CHANNEL_TYPE_WAYLAND: u32 = 0x0001;
611pub const RUTABAGA_CHANNEL_TYPE_CAMERA: u32 = 0x0002;
612
613/// Information needed to open an OS-specific RutabagaConnection (TBD).  Only Linux hosts are
614/// considered at the moment.
615#[derive(Clone)]
616pub struct RutabagaChannel {
617    pub base_channel: PathBuf,
618    pub channel_type: u32,
619}
620
621/// Enumeration of possible rutabaga components.
622#[repr(u8)]
623#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)]
624pub enum RutabagaComponentType {
625    Rutabaga2D,
626    VirglRenderer,
627    Gfxstream,
628    CrossDomain,
629}
630
631/// Rutabaga handle types (memory and sync in same namespace)
632pub 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
643/// Handle to OS-specific memory or synchronization objects.
644pub struct RutabagaHandle {
645    pub os_handle: SafeDescriptor,
646    pub handle_type: u32,
647}
648
649impl RutabagaHandle {
650    /// Clones an existing rutabaga handle, by using OS specific mechanisms.
651    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>;