Skip to main content

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::fmt;
8use std::os::raw::c_char;
9use std::os::raw::c_void;
10use std::path::PathBuf;
11use std::sync::Arc;
12
13use mesa3d_util::MesaError;
14use remain::sorted;
15use serde::Deserialize;
16use serde::Serialize;
17use serde_json::Error as SerdeJsonError;
18use thiserror::Error;
19#[cfg(feature = "vulkano")]
20use vulkano::device::DeviceCreationError;
21#[cfg(feature = "vulkano")]
22use vulkano::image::ImageError;
23#[cfg(feature = "vulkano")]
24use vulkano::instance::InstanceCreationError;
25#[cfg(feature = "vulkano")]
26use vulkano::memory::DeviceMemoryError;
27#[cfg(feature = "vulkano")]
28use vulkano::memory::MemoryMapError;
29#[cfg(feature = "vulkano")]
30use vulkano::LoadingError;
31#[cfg(feature = "vulkano")]
32use vulkano::VulkanError;
33use zerocopy::FromBytes;
34use zerocopy::Immutable;
35use zerocopy::IntoBytes;
36
37/// Represents a buffer.  `base` contains the address of a buffer, while `len` contains the length
38/// of the buffer.
39#[repr(C)]
40#[derive(Copy, Clone)]
41pub struct RutabagaIovec {
42    pub base: *mut c_void,
43    pub len: usize,
44}
45
46// SAFETY: trivially safe
47unsafe impl Send for RutabagaIovec {}
48
49// SAFETY: trivially safe
50unsafe impl Sync for RutabagaIovec {}
51
52/// 3D resource creation parameters.  Also used to create 2D resource.  Constants based on Mesa's
53/// (internal) Gallium interface.  Not in the virtio-gpu spec, but should be since dumb resources
54/// can't work with gfxstream/virglrenderer without this.
55pub const RUTABAGA_PIPE_TEXTURE_2D: u32 = 2;
56pub const RUTABAGA_PIPE_BIND_RENDER_TARGET: u32 = 2;
57#[repr(C)]
58#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
59pub struct ResourceCreate3D {
60    pub target: u32,
61    pub format: u32,
62    pub bind: u32,
63    pub width: u32,
64    pub height: u32,
65    pub depth: u32,
66    pub array_size: u32,
67    pub last_level: u32,
68    pub nr_samples: u32,
69    pub flags: u32,
70}
71
72/// Blob resource creation parameters.
73pub const RUTABAGA_BLOB_MEM_GUEST: u32 = 0x0001;
74pub const RUTABAGA_BLOB_MEM_HOST3D: u32 = 0x0002;
75pub const RUTABAGA_BLOB_MEM_HOST3D_GUEST: u32 = 0x0003;
76
77pub const RUTABAGA_BLOB_FLAG_USE_MAPPABLE: u32 = 0x0001;
78pub const RUTABAGA_BLOB_FLAG_USE_SHAREABLE: u32 = 0x0002;
79pub const RUTABAGA_BLOB_FLAG_USE_CROSS_DEVICE: u32 = 0x0004;
80#[repr(C)]
81#[derive(Copy, Clone, Debug)]
82pub struct ResourceCreateBlob {
83    pub blob_mem: u32,
84    pub blob_flags: u32,
85    pub blob_id: u64,
86    pub size: u64,
87}
88
89/// Metadata associated with a swapchain, video or camera image.
90#[repr(C)]
91#[derive(Default, Copy, Clone, Debug, Deserialize, Serialize)]
92pub struct Resource3DInfo {
93    pub width: u32,
94    pub height: u32,
95    pub drm_fourcc: u32,
96    pub strides: [u32; 4],
97    pub offsets: [u32; 4],
98    pub modifier: u64,
99}
100
101/// A unique identifier for a device.
102#[derive(
103    Copy,
104    Clone,
105    Debug,
106    Default,
107    PartialEq,
108    Eq,
109    PartialOrd,
110    Ord,
111    Hash,
112    FromBytes,
113    IntoBytes,
114    Immutable,
115)]
116#[repr(C)]
117#[derive(Deserialize, Serialize)]
118pub struct DeviceId {
119    pub device_uuid: [u8; 16],
120    pub driver_uuid: [u8; 16],
121}
122
123/// Memory index and physical device id of the associated VkDeviceMemory.
124#[derive(
125    Copy,
126    Clone,
127    Debug,
128    Default,
129    PartialEq,
130    Eq,
131    PartialOrd,
132    Ord,
133    Hash,
134    FromBytes,
135    IntoBytes,
136    Immutable,
137)]
138#[repr(C)]
139#[derive(Deserialize, Serialize)]
140pub struct VulkanInfo {
141    pub memory_idx: u32,
142    pub device_id: DeviceId,
143}
144
145/// Rutabaga context init capset id mask.
146pub const RUTABAGA_CONTEXT_INIT_CAPSET_ID_MASK: u32 = 0x00ff;
147
148/// Rutabaga flags for creating fences.
149pub const RUTABAGA_FLAG_FENCE: u32 = 1 << 0;
150pub const RUTABAGA_FLAG_INFO_RING_IDX: u32 = 1 << 1;
151pub const RUTABAGA_FLAG_FENCE_HOST_SHAREABLE: u32 = 1 << 2;
152
153/// Convenience struct for Rutabaga fences
154#[repr(C)]
155#[derive(Copy, Clone)]
156pub struct RutabagaFence {
157    pub flags: u32,
158    pub fence_id: u64,
159    pub ctx_id: u32,
160    pub ring_idx: u8,
161}
162
163/// Rutabaga debug types
164pub const RUTABAGA_DEBUG_ERROR: u32 = 0x01;
165pub const RUTABAGA_DEBUG_WARNING: u32 = 0x02;
166pub const RUTABAGA_DEBUG_INFO: u32 = 0x03;
167
168/// Convenience struct for debug data
169#[repr(C)]
170#[derive(Copy, Clone)]
171pub struct RutabagaDebug {
172    pub debug_type: u32,
173    pub message: *const c_char,
174}
175
176/// Rutabaga import flags
177pub const RUTABAGA_IMPORT_FLAG_3D_INFO: u32 = 1 << 0;
178pub const RUTABAGA_IMPORT_FLAG_VULKAN_INFO: u32 = 1 << 1;
179pub const RUTABAGA_IMPORT_FLAG_RESOURCE_EXISTS: u32 = 1 << 30;
180pub const RUTABAGA_IMPORT_FLAG_PRESERVE_CONTENT: u32 = 1 << 31;
181
182/// Import Data for resource_import
183#[repr(C)]
184#[derive(Copy, Clone)]
185pub struct RutabagaImportData {
186    pub flags: u32,
187    pub info_3d: Resource3DInfo,
188}
189
190// SAFETY:
191// This is sketchy, since `message` is a C-string and there's no locking + atomics.  However,
192// the current use case is to mirror the C-API.  If the `RutabagaDebugHandler` is used with
193// by Rust code, a different struct should be used.
194unsafe impl Send for RutabagaDebug {}
195// SAFETY:
196// This is sketchy, since `message` is a C-string and there's no locking + atomics.  However,
197// the current use case is to mirror the C-API.  If the `RutabagaDebugHandler` is used with
198// by Rust code, a different struct should be used.
199unsafe impl Sync for RutabagaDebug {}
200
201/// Mapped memory caching flags (see virtio_gpu spec)
202pub const RUTABAGA_MAP_CACHE_MASK: u32 = 0x0f;
203pub const RUTABAGA_MAP_CACHE_CACHED: u32 = 0x01;
204pub const RUTABAGA_MAP_CACHE_UNCACHED: u32 = 0x02;
205pub const RUTABAGA_MAP_CACHE_WC: u32 = 0x03;
206/// Access flags (not in virtio_gpu spec)
207pub const RUTABAGA_MAP_ACCESS_MASK: u32 = 0xf0;
208pub const RUTABAGA_MAP_ACCESS_READ: u32 = 0x10;
209pub const RUTABAGA_MAP_ACCESS_WRITE: u32 = 0x20;
210pub const RUTABAGA_MAP_ACCESS_RW: u32 = 0x30;
211
212/// Rutabaga capsets.
213pub const RUTABAGA_CAPSET_VIRGL: u32 = 1;
214pub const RUTABAGA_CAPSET_VIRGL2: u32 = 2;
215pub const RUTABAGA_CAPSET_GFXSTREAM_VULKAN: u32 = 3;
216pub const RUTABAGA_CAPSET_VENUS: u32 = 4;
217pub const RUTABAGA_CAPSET_CROSS_DOMAIN: u32 = 5;
218pub const RUTABAGA_CAPSET_DRM: u32 = 6;
219pub const RUTABAGA_CAPSET_MAGMA: u32 = 7;
220pub const RUTABAGA_CAPSET_GFXSTREAM_GLES: u32 = 8;
221pub const RUTABAGA_CAPSET_GFXSTREAM_COMPOSER: u32 = 9;
222
223/// A list specifying general categories of rutabaga_gfx error.
224///
225/// This list is intended to grow over time and it is not recommended to exhaustively match against
226/// it.
227///
228/// It is used with the [`RutabagaError`] type.
229#[sorted]
230#[non_exhaustive]
231#[derive(Error, Debug)]
232pub enum RutabagaError {
233    /// Indicates `Rutabaga` was already initialized since only one Rutabaga instance per process
234    /// is allowed.
235    #[error("attempted to use a rutabaga asset already in use")]
236    AlreadyInUse,
237    /// Checked Arithmetic error
238    #[error("arithmetic failed: {}({}) {op} {}({})", .field1.0, .field1.1, .field2.0, .field2.1)]
239    CheckedArithmetic {
240        field1: (&'static str, usize),
241        field2: (&'static str, usize),
242        op: &'static str,
243    },
244    /// Checked Range error
245    #[error("range check failed: {}({}) vs {}({})", .field1.0, .field1.1, .field2.0, .field2.1)]
246    CheckedRange {
247        field1: (&'static str, usize),
248        field2: (&'static str, usize),
249    },
250    /// An internal Rutabaga component error was returned.
251    #[error("rutabaga component failed with error {0}")]
252    ComponentError(i32),
253    /// Invalid 2D info
254    #[error("invalid 2D info")]
255    Invalid2DInfo,
256    /// Invalid Capset
257    #[error("invalid capset")]
258    InvalidCapset,
259    /// A command buffer with insufficient space was submitted.
260    #[error("invalid command buffer submitted")]
261    InvalidCommandBuffer,
262    /// A command size was submitted that was invalid.
263    #[error("command buffer submitted with invalid size: {0}")]
264    InvalidCommandSize(usize),
265    /// Invalid RutabagaComponent
266    #[error("invalid rutabaga component")]
267    InvalidComponent,
268    /// Invalid Context ID
269    #[error("invalid context id")]
270    InvalidContextId,
271    /// Invalid cross domain channel
272    #[error("invalid cross domain channel")]
273    InvalidCrossDomainChannel,
274    /// Invalid cross domain item ID
275    #[error("invalid cross domain item id")]
276    InvalidCrossDomainItemId,
277    /// Invalid cross domain item type
278    #[error("invalid cross domain item type")]
279    InvalidCrossDomainItemType,
280    /// Invalid cross domain state
281    #[error("invalid cross domain state")]
282    InvalidCrossDomainState,
283    /// Invalid gralloc backend.
284    #[error("invalid gralloc backend")]
285    InvalidGrallocBackend,
286    /// Invalid gralloc dimensions.
287    #[error("invalid gralloc dimensions")]
288    InvalidGrallocDimensions,
289    /// Invalid gralloc DRM format.
290    #[error("invalid gralloc DRM format")]
291    InvalidGrallocDrmFormat,
292    /// Invalid GPU type.
293    #[error("invalid GPU type for gralloc")]
294    InvalidGrallocGpuType,
295    /// Invalid number of YUV planes.
296    #[error("invalid number of YUV planes")]
297    InvalidGrallocNumberOfPlanes,
298    /// The indicated region of guest memory is invalid.
299    #[error("an iovec is outside of guest memory's range")]
300    InvalidIovec,
301    /// Invalid Resource ID.
302    #[error("invalid resource id")]
303    InvalidResourceId,
304    /// Indicates an error in the RutabagaBuilder.
305    #[error("invalid rutabaga build parameters")]
306    InvalidRutabagaBuild,
307    /// An error with VulkanInfo
308    #[error("invalid vulkan info")]
309    InvalidVulkanInfo,
310    /// The mapping failed.
311    #[error("The mapping failed with library error: {0}")]
312    MappingFailed(i32),
313    /// A Mesa Error
314    #[error("An mesa error was returned {0}")]
315    MesaError(MesaError),
316    /// A snapshot JSON error was returned
317    #[error("An serde json snapshot error was returned {0}")]
318    SerdeJsonError(SerdeJsonError),
319    /// A snapshot Error
320    #[error("An snapshot error was returned")]
321    SnapshotError,
322    /// Device creation error
323    #[cfg(feature = "vulkano")]
324    #[error("vulkano device creation failure {0}")]
325    VkDeviceCreationError(DeviceCreationError),
326    /// Device memory error
327    #[cfg(feature = "vulkano")]
328    #[error("vulkano device memory failure {0}")]
329    VkDeviceMemoryError(DeviceMemoryError),
330    /// General Vulkan error
331    #[cfg(feature = "vulkano")]
332    #[error("vulkano failure {0}")]
333    VkError(VulkanError),
334    /// Image creation error
335    #[cfg(feature = "vulkano")]
336    #[error("vulkano image creation failure {0}")]
337    VkImageCreationError(ImageError),
338    /// Instance creation error
339    #[cfg(feature = "vulkano")]
340    #[error("vulkano instance creation failure {0}")]
341    VkInstanceCreationError(InstanceCreationError),
342    /// Loading error
343    #[cfg(feature = "vulkano")]
344    #[error("vulkano loading failure {0}")]
345    VkLoadingError(LoadingError),
346    /// Memory map error
347    #[cfg(feature = "vulkano")]
348    #[error("vulkano memory map failure {0}")]
349    VkMemoryMapError(MemoryMapError),
350}
351
352impl From<MesaError> for RutabagaError {
353    fn from(e: MesaError) -> RutabagaError {
354        RutabagaError::MesaError(e)
355    }
356}
357
358impl From<SerdeJsonError> for RutabagaError {
359    fn from(e: SerdeJsonError) -> RutabagaError {
360        RutabagaError::SerdeJsonError(e)
361    }
362}
363
364/// The result of an operation in this crate.
365pub type RutabagaResult<T> = std::result::Result<T, RutabagaError>;
366
367/// Flags for virglrenderer.  Copied from virglrenderer bindings.
368const VIRGLRENDERER_USE_EGL: u32 = 1 << 0;
369const VIRGLRENDERER_THREAD_SYNC: u32 = 1 << 1;
370#[allow(dead_code)]
371const VIRGLRENDERER_USE_GLX: u32 = 1 << 2;
372const VIRGLRENDERER_USE_SURFACELESS: u32 = 1 << 3;
373const VIRGLRENDERER_USE_GLES: u32 = 1 << 4;
374const VIRGLRENDERER_USE_EXTERNAL_BLOB: u32 = 1 << 5;
375const VIRGLRENDERER_VENUS: u32 = 1 << 6;
376const VIRGLRENDERER_NO_VIRGL: u32 = 1 << 7;
377const VIRGLRENDERER_USE_ASYNC_FENCE_CB: u32 = 1 << 8;
378const VIRGLRENDERER_RENDER_SERVER: u32 = 1 << 9;
379const VIRGLRENDERER_DRM: u32 = 1 << 10;
380
381/// virglrenderer flag struct.
382#[derive(Copy, Clone)]
383pub struct VirglRendererFlags(u32);
384
385impl Default for VirglRendererFlags {
386    fn default() -> VirglRendererFlags {
387        VirglRendererFlags::new()
388            .use_virgl(true)
389            .use_venus(false)
390            .use_egl(true)
391            .use_surfaceless(true)
392            .use_gles(true)
393            .use_render_server(false)
394    }
395}
396
397impl From<VirglRendererFlags> for u32 {
398    fn from(flags: VirglRendererFlags) -> u32 {
399        flags.0
400    }
401}
402
403impl From<VirglRendererFlags> for i32 {
404    fn from(flags: VirglRendererFlags) -> i32 {
405        flags.0 as i32
406    }
407}
408
409impl VirglRendererFlags {
410    /// Create new virglrenderer flags.
411    pub fn new() -> VirglRendererFlags {
412        VirglRendererFlags(0)
413    }
414
415    fn set_flag(self, bitmask: u32, set: bool) -> VirglRendererFlags {
416        if set {
417            VirglRendererFlags(self.0 | bitmask)
418        } else {
419            VirglRendererFlags(self.0 & (!bitmask))
420        }
421    }
422
423    /// Enable virgl support
424    pub fn use_virgl(self, v: bool) -> VirglRendererFlags {
425        self.set_flag(VIRGLRENDERER_NO_VIRGL, !v)
426    }
427
428    /// Enable venus support
429    pub fn use_venus(self, v: bool) -> VirglRendererFlags {
430        self.set_flag(VIRGLRENDERER_VENUS, v)
431    }
432
433    /// Enable drm native context support
434    pub fn use_drm(self, v: bool) -> VirglRendererFlags {
435        self.set_flag(VIRGLRENDERER_DRM, v)
436    }
437
438    /// Use EGL for context creation.
439    pub fn use_egl(self, v: bool) -> VirglRendererFlags {
440        self.set_flag(VIRGLRENDERER_USE_EGL, v)
441    }
442
443    /// Use a dedicated thread for fence synchronization.
444    pub fn use_thread_sync(self, v: bool) -> VirglRendererFlags {
445        self.set_flag(VIRGLRENDERER_THREAD_SYNC, v)
446    }
447
448    /// No surfaces required when creating context.
449    pub fn use_surfaceless(self, v: bool) -> VirglRendererFlags {
450        self.set_flag(VIRGLRENDERER_USE_SURFACELESS, v)
451    }
452
453    /// Use GLES drivers.
454    pub fn use_gles(self, v: bool) -> VirglRendererFlags {
455        self.set_flag(VIRGLRENDERER_USE_GLES, v)
456    }
457
458    /// Use external memory when creating blob resources.
459    pub fn use_external_blob(self, v: bool) -> VirglRendererFlags {
460        self.set_flag(VIRGLRENDERER_USE_EXTERNAL_BLOB, v)
461    }
462
463    /// Retire fence directly from sync thread.
464    pub fn use_async_fence_cb(self, v: bool) -> VirglRendererFlags {
465        self.set_flag(VIRGLRENDERER_USE_ASYNC_FENCE_CB, v)
466    }
467
468    pub fn use_render_server(self, v: bool) -> VirglRendererFlags {
469        self.set_flag(VIRGLRENDERER_RENDER_SERVER, v)
470    }
471}
472
473/// Flags for the gfxstream renderer.
474const STREAM_RENDERER_FLAGS_USE_EGL: u32 = 1 << 0;
475#[allow(dead_code)]
476const STREAM_RENDERER_FLAGS_THREAD_SYNC: u32 = 1 << 1;
477#[allow(dead_code)]
478const STREAM_RENDERER_FLAGS_USE_GLX: u32 = 1 << 2;
479const STREAM_RENDERER_FLAGS_USE_SURFACELESS: u32 = 1 << 3;
480const STREAM_RENDERER_FLAGS_USE_GLES: u32 = 1 << 4;
481const STREAM_RENDERER_FLAGS_USE_VK_BIT: u32 = 1 << 5;
482const STREAM_RENDERER_FLAGS_USE_EXTERNAL_BLOB: u32 = 1 << 6;
483const STREAM_RENDERER_FLAGS_USE_SYSTEM_BLOB: u32 = 1 << 7;
484const STREAM_RENDERER_FLAGS_VULKAN_NATIVE_SWAPCHAIN_BIT: u32 = 1 << 8;
485
486/// gfxstream flag struct.
487#[derive(Copy, Clone, Default)]
488pub struct GfxstreamFlags(u32);
489
490#[derive(Clone, Debug)]
491pub enum RutabagaWsi {
492    Surfaceless,
493    VulkanSwapchain,
494}
495
496impl GfxstreamFlags {
497    /// Create new gfxstream flags.
498    pub fn new() -> GfxstreamFlags {
499        GfxstreamFlags(0)
500    }
501
502    fn set_flag(self, bitmask: u32, set: bool) -> GfxstreamFlags {
503        if set {
504            GfxstreamFlags(self.0 | bitmask)
505        } else {
506            GfxstreamFlags(self.0 & (!bitmask))
507        }
508    }
509
510    /// Use EGL for context creation.
511    pub fn use_egl(self, v: bool) -> GfxstreamFlags {
512        self.set_flag(STREAM_RENDERER_FLAGS_USE_EGL, v)
513    }
514
515    /// No surfaces required when creating context.
516    pub fn use_surfaceless(self, v: bool) -> GfxstreamFlags {
517        self.set_flag(STREAM_RENDERER_FLAGS_USE_SURFACELESS, v)
518    }
519
520    /// Use GLES drivers.
521    pub fn use_gles(self, v: bool) -> GfxstreamFlags {
522        self.set_flag(STREAM_RENDERER_FLAGS_USE_GLES, v)
523    }
524
525    /// Support using Vulkan.
526    pub fn use_vulkan(self, v: bool) -> GfxstreamFlags {
527        self.set_flag(STREAM_RENDERER_FLAGS_USE_VK_BIT, v)
528    }
529
530    /// Use the Vulkan swapchain to draw on the host window.
531    pub fn set_wsi(self, v: RutabagaWsi) -> GfxstreamFlags {
532        let use_vulkan_swapchain = matches!(v, RutabagaWsi::VulkanSwapchain);
533        self.set_flag(
534            STREAM_RENDERER_FLAGS_VULKAN_NATIVE_SWAPCHAIN_BIT,
535            use_vulkan_swapchain,
536        )
537    }
538
539    /// Use external blob when creating resources.
540    pub fn use_external_blob(self, v: bool) -> GfxstreamFlags {
541        self.set_flag(STREAM_RENDERER_FLAGS_USE_EXTERNAL_BLOB, v)
542    }
543
544    /// Use system blob when creating resources.
545    pub fn use_system_blob(self, v: bool) -> GfxstreamFlags {
546        self.set_flag(STREAM_RENDERER_FLAGS_USE_SYSTEM_BLOB, v)
547    }
548}
549
550impl From<GfxstreamFlags> for u32 {
551    fn from(flags: GfxstreamFlags) -> u32 {
552        flags.0
553    }
554}
555
556impl From<GfxstreamFlags> for i32 {
557    fn from(flags: GfxstreamFlags) -> i32 {
558        flags.0 as i32
559    }
560}
561
562impl From<GfxstreamFlags> for u64 {
563    fn from(flags: GfxstreamFlags) -> u64 {
564        flags.0 as u64
565    }
566}
567
568/// Transfers {to, from} 1D buffers, 2D textures, 3D textures, and cubemaps.
569#[repr(C)]
570#[derive(Copy, Clone, Debug)]
571pub struct Transfer3D {
572    pub x: u32,
573    pub y: u32,
574    pub z: u32,
575    pub w: u32,
576    pub h: u32,
577    pub d: u32,
578    pub level: u32,
579    pub stride: u32,
580    pub layer_stride: u32,
581    pub offset: u64,
582}
583
584impl Transfer3D {
585    /// Constructs a 2 dimensional XY box in 3 dimensional space with unit depth and zero
586    /// displacement on the Z axis.
587    pub fn new_2d(x: u32, y: u32, w: u32, h: u32, offset: u64) -> Transfer3D {
588        Transfer3D {
589            x,
590            y,
591            z: 0,
592            w,
593            h,
594            d: 1,
595            level: 0,
596            stride: 0,
597            layer_stride: 0,
598            offset,
599        }
600    }
601
602    /// Returns true if this box represents a volume of zero.
603    pub fn is_empty(&self) -> bool {
604        self.w == 0 || self.h == 0 || self.d == 0
605    }
606}
607
608/// Rutabaga path types
609pub const RUTABAGA_PATH_TYPE_WAYLAND: u32 = 0x0001;
610pub const RUTABAGA_PATH_TYPE_GPU: u32 = 0x0002;
611
612pub type RutabagaPaths = Vec<RutabagaPath>;
613
614/// Information needed to open an OS-specific RutabagaConnection (TBD).  Only Linux hosts are
615/// considered at the moment.
616#[derive(Clone)]
617pub struct RutabagaPath {
618    pub path: PathBuf,
619    pub path_type: u32,
620}
621
622/// Enumeration of possible rutabaga components.
623#[repr(u8)]
624#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)]
625pub enum RutabagaComponentType {
626    NoneSelected,
627    Rutabaga2D,
628    VirglRenderer,
629    Gfxstream,
630    CrossDomain,
631    Magma,
632}
633
634impl RutabagaComponentType {
635    pub fn as_str(&self) -> &'static str {
636        match self {
637            RutabagaComponentType::NoneSelected => "none_selected",
638            RutabagaComponentType::CrossDomain => "cross_domain",
639            RutabagaComponentType::Gfxstream => "gfxstream",
640            RutabagaComponentType::Magma => "magma",
641            RutabagaComponentType::Rutabaga2D => "rutabaga_2d",
642            RutabagaComponentType::VirglRenderer => "virgl_renderer",
643        }
644    }
645}
646
647// Handle types to support special-case consumers.
648pub const RUTABAGA_HANDLE_TYPE_PLATFORM_SCREEN_BUFFER_QNX: u32 = 0x01000000;
649pub const RUTABAGA_HANDLE_TYPE_PLATFORM_EGL_NATIVE_PIXMAP: u32 = 0x02000000;
650
651#[derive(Clone)]
652pub struct RutabagaHandler<S> {
653    closure: Arc<dyn Fn(S) + Send + Sync>,
654}
655
656impl<S> RutabagaHandler<S>
657where
658    S: Send + Sync + Clone + 'static,
659{
660    pub fn new(closure: impl Fn(S) + Send + Sync + 'static) -> RutabagaHandler<S> {
661        RutabagaHandler {
662            closure: Arc::new(closure),
663        }
664    }
665
666    pub fn call(&self, data: S) {
667        (self.closure)(data)
668    }
669}
670
671impl<S> fmt::Debug for RutabagaHandler<S> {
672    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
673        f.debug_struct("Closure debug").finish()
674    }
675}
676
677pub type RutabagaFenceHandler = RutabagaHandler<RutabagaFence>;
678pub type RutabagaDebugHandler = RutabagaHandler<RutabagaDebug>;