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