• 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 thiserror::Error;
21 #[cfg(feature = "vulkano")]
22 use vulkano::device::DeviceCreationError;
23 #[cfg(feature = "vulkano")]
24 use vulkano::image::ImageError;
25 #[cfg(feature = "vulkano")]
26 use vulkano::instance::InstanceCreationError;
27 #[cfg(feature = "vulkano")]
28 use vulkano::memory::DeviceMemoryError;
29 #[cfg(feature = "vulkano")]
30 use vulkano::memory::MemoryMapError;
31 #[cfg(feature = "vulkano")]
32 use vulkano::LoadingError;
33 #[cfg(feature = "vulkano")]
34 use vulkano::VulkanError;
35 
36 use 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)]
42 pub struct RutabagaIovec {
43     pub base: *mut c_void,
44     pub len: usize,
45 }
46 
47 // SAFETY: trivially safe
48 unsafe impl Send for RutabagaIovec {}
49 
50 // SAFETY: trivially safe
51 unsafe 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.
56 pub const RUTABAGA_PIPE_TEXTURE_2D: u32 = 2;
57 pub const RUTABAGA_PIPE_BIND_RENDER_TARGET: u32 = 2;
58 #[repr(C)]
59 #[derive(Copy, Clone, Debug)]
60 pub 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.
74 pub const RUTABAGA_BLOB_MEM_GUEST: u32 = 0x0001;
75 pub const RUTABAGA_BLOB_MEM_HOST3D: u32 = 0x0002;
76 pub const RUTABAGA_BLOB_MEM_HOST3D_GUEST: u32 = 0x0003;
77 
78 pub const RUTABAGA_BLOB_FLAG_USE_MAPPABLE: u32 = 0x0001;
79 pub const RUTABAGA_BLOB_FLAG_USE_SHAREABLE: u32 = 0x0002;
80 pub const RUTABAGA_BLOB_FLAG_USE_CROSS_DEVICE: u32 = 0x0004;
81 #[repr(C)]
82 #[derive(Copy, Clone, Debug)]
83 pub 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)]
92 pub 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)]
99 pub 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)]
112 pub 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)]
119 pub struct VulkanInfo {
120     pub memory_idx: u32,
121     pub device_id: DeviceId,
122 }
123 
124 /// Rutabaga context init capset id mask.
125 pub const RUTABAGA_CONTEXT_INIT_CAPSET_ID_MASK: u32 = 0x00ff;
126 
127 /// Rutabaga flags for creating fences.
128 pub const RUTABAGA_FLAG_FENCE: u32 = 1 << 0;
129 pub const RUTABAGA_FLAG_INFO_RING_IDX: u32 = 1 << 1;
130 pub const RUTABAGA_FLAG_FENCE_SHAREABLE: u32 = 1 << 2;
131 
132 /// Convenience struct for Rutabaga fences
133 #[repr(C)]
134 #[derive(Copy, Clone)]
135 pub 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
143 pub const RUTABAGA_DEBUG_ERROR: u32 = 0x01;
144 pub const RUTABAGA_DEBUG_WARNING: u32 = 0x02;
145 pub const RUTABAGA_DEBUG_INFO: u32 = 0x03;
146 
147 /// Convenience struct for debug data
148 #[repr(C)]
149 #[derive(Copy, Clone)]
150 pub 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.
159 unsafe 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.
164 unsafe impl Sync for RutabagaDebug {}
165 
166 /// Mapped memory caching flags (see virtio_gpu spec)
167 pub const RUTABAGA_MAP_CACHE_MASK: u32 = 0x0f;
168 pub const RUTABAGA_MAP_CACHE_CACHED: u32 = 0x01;
169 pub const RUTABAGA_MAP_CACHE_UNCACHED: u32 = 0x02;
170 pub const RUTABAGA_MAP_CACHE_WC: u32 = 0x03;
171 /// Access flags (not in virtio_gpu spec)
172 pub const RUTABAGA_MAP_ACCESS_MASK: u32 = 0xf0;
173 pub const RUTABAGA_MAP_ACCESS_READ: u32 = 0x10;
174 pub const RUTABAGA_MAP_ACCESS_WRITE: u32 = 0x20;
175 pub const RUTABAGA_MAP_ACCESS_RW: u32 = 0x30;
176 
177 /// Rutabaga capsets.
178 pub const RUTABAGA_CAPSET_VIRGL: u32 = 1;
179 pub const RUTABAGA_CAPSET_VIRGL2: u32 = 2;
180 pub const RUTABAGA_CAPSET_GFXSTREAM_VULKAN: u32 = 3;
181 pub const RUTABAGA_CAPSET_VENUS: u32 = 4;
182 pub const RUTABAGA_CAPSET_CROSS_DOMAIN: u32 = 5;
183 pub const RUTABAGA_CAPSET_DRM: u32 = 6;
184 pub const RUTABAGA_CAPSET_GFXSTREAM_MAGMA: u32 = 7;
185 pub const RUTABAGA_CAPSET_GFXSTREAM_GLES: u32 = 8;
186 pub const RUTABAGA_CAPSET_GFXSTREAM_COMPOSER: u32 = 9;
187 
188 /// An error generated while using this crate.
189 #[sorted]
190 #[derive(Error, Debug)]
191 pub 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(ImageError),
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"))]
327 impl From<NixError> for RutabagaError {
from(e: NixError) -> RutabagaError328     fn from(e: NixError) -> RutabagaError {
329         RutabagaError::NixError(e)
330     }
331 }
332 
333 impl From<NulError> for RutabagaError {
from(e: NulError) -> RutabagaError334     fn from(e: NulError) -> RutabagaError {
335         RutabagaError::NulError(e)
336     }
337 }
338 
339 impl From<IoError> for RutabagaError {
from(e: IoError) -> RutabagaError340     fn from(e: IoError) -> RutabagaError {
341         RutabagaError::IoError(e)
342     }
343 }
344 
345 impl From<TryFromIntError> for RutabagaError {
from(e: TryFromIntError) -> RutabagaError346     fn from(e: TryFromIntError) -> RutabagaError {
347         RutabagaError::TryFromIntError(e)
348     }
349 }
350 
351 impl From<Utf8Error> for RutabagaError {
from(e: Utf8Error) -> RutabagaError352     fn from(e: Utf8Error) -> RutabagaError {
353         RutabagaError::Utf8Error(e)
354     }
355 }
356 
357 /// The result of an operation in this crate.
358 pub type RutabagaResult<T> = std::result::Result<T, RutabagaError>;
359 
360 /// Flags for virglrenderer.  Copied from virglrenderer bindings.
361 const VIRGLRENDERER_USE_EGL: u32 = 1 << 0;
362 const VIRGLRENDERER_THREAD_SYNC: u32 = 1 << 1;
363 const VIRGLRENDERER_USE_GLX: u32 = 1 << 2;
364 const VIRGLRENDERER_USE_SURFACELESS: u32 = 1 << 3;
365 const VIRGLRENDERER_USE_GLES: u32 = 1 << 4;
366 const VIRGLRENDERER_USE_EXTERNAL_BLOB: u32 = 1 << 5;
367 const VIRGLRENDERER_VENUS: u32 = 1 << 6;
368 const VIRGLRENDERER_NO_VIRGL: u32 = 1 << 7;
369 const VIRGLRENDERER_USE_ASYNC_FENCE_CB: u32 = 1 << 8;
370 const VIRGLRENDERER_RENDER_SERVER: u32 = 1 << 9;
371 const VIRGLRENDERER_DRM: u32 = 1 << 10;
372 
373 /// virglrenderer flag struct.
374 #[derive(Copy, Clone)]
375 pub struct VirglRendererFlags(u32);
376 
377 impl Default for VirglRendererFlags {
default() -> VirglRendererFlags378     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 
389 impl From<VirglRendererFlags> for u32 {
from(flags: VirglRendererFlags) -> u32390     fn from(flags: VirglRendererFlags) -> u32 {
391         flags.0
392     }
393 }
394 
395 impl From<VirglRendererFlags> for i32 {
from(flags: VirglRendererFlags) -> i32396     fn from(flags: VirglRendererFlags) -> i32 {
397         flags.0 as i32
398     }
399 }
400 
401 impl VirglRendererFlags {
402     /// Create new virglrenderer flags.
new() -> VirglRendererFlags403     pub fn new() -> VirglRendererFlags {
404         VirglRendererFlags(0)
405     }
406 
set_flag(self, bitmask: u32, set: bool) -> VirglRendererFlags407     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
use_virgl(self, v: bool) -> VirglRendererFlags416     pub fn use_virgl(self, v: bool) -> VirglRendererFlags {
417         self.set_flag(VIRGLRENDERER_NO_VIRGL, !v)
418     }
419 
420     /// Enable venus support
use_venus(self, v: bool) -> VirglRendererFlags421     pub fn use_venus(self, v: bool) -> VirglRendererFlags {
422         self.set_flag(VIRGLRENDERER_VENUS, v)
423     }
424 
425     /// Enable drm native context support
use_drm(self, v: bool) -> VirglRendererFlags426     pub fn use_drm(self, v: bool) -> VirglRendererFlags {
427         self.set_flag(VIRGLRENDERER_DRM, v)
428     }
429 
430     /// Use EGL for context creation.
use_egl(self, v: bool) -> VirglRendererFlags431     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.
use_thread_sync(self, v: bool) -> VirglRendererFlags436     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.
use_glx(self, v: bool) -> VirglRendererFlags441     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.
use_surfaceless(self, v: bool) -> VirglRendererFlags446     pub fn use_surfaceless(self, v: bool) -> VirglRendererFlags {
447         self.set_flag(VIRGLRENDERER_USE_SURFACELESS, v)
448     }
449 
450     /// Use GLES drivers.
use_gles(self, v: bool) -> VirglRendererFlags451     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.
use_external_blob(self, v: bool) -> VirglRendererFlags456     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.
use_async_fence_cb(self, v: bool) -> VirglRendererFlags461     pub fn use_async_fence_cb(self, v: bool) -> VirglRendererFlags {
462         self.set_flag(VIRGLRENDERER_USE_ASYNC_FENCE_CB, v)
463     }
464 
use_render_server(self, v: bool) -> VirglRendererFlags465     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.
471 const STREAM_RENDERER_FLAGS_USE_EGL: u32 = 1 << 0;
472 #[allow(dead_code)]
473 const STREAM_RENDERER_FLAGS_THREAD_SYNC: u32 = 1 << 1;
474 const STREAM_RENDERER_FLAGS_USE_GLX: u32 = 1 << 2;
475 const STREAM_RENDERER_FLAGS_USE_SURFACELESS: u32 = 1 << 3;
476 const STREAM_RENDERER_FLAGS_USE_GLES: u32 = 1 << 4;
477 const STREAM_RENDERER_FLAGS_USE_VK_BIT: u32 = 1 << 5;
478 const STREAM_RENDERER_FLAGS_USE_EXTERNAL_BLOB: u32 = 1 << 6;
479 const STREAM_RENDERER_FLAGS_USE_SYSTEM_BLOB: u32 = 1 << 7;
480 const STREAM_RENDERER_FLAGS_VULKAN_NATIVE_SWAPCHAIN_BIT: u32 = 1 << 8;
481 
482 /// gfxstream flag struct.
483 #[derive(Copy, Clone, Default)]
484 pub struct GfxstreamFlags(u32);
485 
486 #[derive(Clone, Debug)]
487 pub enum RutabagaWsi {
488     Surfaceless,
489     VulkanSwapchain,
490 }
491 
492 impl GfxstreamFlags {
493     /// Create new gfxstream flags.
new() -> GfxstreamFlags494     pub fn new() -> GfxstreamFlags {
495         GfxstreamFlags(0)
496     }
497 
set_flag(self, bitmask: u32, set: bool) -> GfxstreamFlags498     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.
use_egl(self, v: bool) -> GfxstreamFlags507     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.
use_glx(self, v: bool) -> GfxstreamFlags512     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.
use_surfaceless(self, v: bool) -> GfxstreamFlags517     pub fn use_surfaceless(self, v: bool) -> GfxstreamFlags {
518         self.set_flag(STREAM_RENDERER_FLAGS_USE_SURFACELESS, v)
519     }
520 
521     /// Use GLES drivers.
use_gles(self, v: bool) -> GfxstreamFlags522     pub fn use_gles(self, v: bool) -> GfxstreamFlags {
523         self.set_flag(STREAM_RENDERER_FLAGS_USE_GLES, v)
524     }
525 
526     /// Support using Vulkan.
use_vulkan(self, v: bool) -> GfxstreamFlags527     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.
set_wsi(self, v: RutabagaWsi) -> GfxstreamFlags532     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.
use_external_blob(self, v: bool) -> GfxstreamFlags541     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.
use_system_blob(self, v: bool) -> GfxstreamFlags546     pub fn use_system_blob(self, v: bool) -> GfxstreamFlags {
547         self.set_flag(STREAM_RENDERER_FLAGS_USE_SYSTEM_BLOB, v)
548     }
549 }
550 
551 impl From<GfxstreamFlags> for u32 {
from(flags: GfxstreamFlags) -> u32552     fn from(flags: GfxstreamFlags) -> u32 {
553         flags.0
554     }
555 }
556 
557 impl From<GfxstreamFlags> for i32 {
from(flags: GfxstreamFlags) -> i32558     fn from(flags: GfxstreamFlags) -> i32 {
559         flags.0 as i32
560     }
561 }
562 
563 impl From<GfxstreamFlags> for u64 {
from(flags: GfxstreamFlags) -> u64564     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)]
572 pub 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 
585 impl Transfer3D {
586     /// Constructs a 2 dimensional XY box in 3 dimensional space with unit depth and zero
587     /// displacement on the Z axis.
new_2d(x: u32, y: u32, w: u32, h: u32) -> Transfer3D588     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.
is_empty(&self) -> bool604     pub fn is_empty(&self) -> bool {
605         self.w == 0 || self.h == 0 || self.d == 0
606     }
607 }
608 
609 /// Rutabaga channel types
610 pub const RUTABAGA_CHANNEL_TYPE_WAYLAND: u32 = 0x0001;
611 pub 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)]
616 pub 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)]
624 pub enum RutabagaComponentType {
625     Rutabaga2D,
626     VirglRenderer,
627     Gfxstream,
628     CrossDomain,
629 }
630 
631 /// Rutabaga handle types (memory and sync in same namespace)
632 pub const RUTABAGA_MEM_HANDLE_TYPE_OPAQUE_FD: u32 = 0x0001;
633 pub const RUTABAGA_MEM_HANDLE_TYPE_DMABUF: u32 = 0x0002;
634 pub const RUTABAGA_MEM_HANDLE_TYPE_OPAQUE_WIN32: u32 = 0x0003;
635 pub const RUTABAGA_MEM_HANDLE_TYPE_SHM: u32 = 0x0004;
636 pub const RUTABAGA_MEM_HANDLE_TYPE_ZIRCON: u32 = 0x0005;
637 
638 pub const RUTABAGA_FENCE_HANDLE_TYPE_OPAQUE_FD: u32 = 0x0006;
639 pub const RUTABAGA_FENCE_HANDLE_TYPE_SYNC_FD: u32 = 0x0007;
640 pub const RUTABAGA_FENCE_HANDLE_TYPE_OPAQUE_WIN32: u32 = 0x0008;
641 pub const RUTABAGA_FENCE_HANDLE_TYPE_ZIRCON: u32 = 0x0009;
642 
643 /// Handle to OS-specific memory or synchronization objects.
644 pub struct RutabagaHandle {
645     pub os_handle: SafeDescriptor,
646     pub handle_type: u32,
647 }
648 
649 impl RutabagaHandle {
650     /// Clones an existing rutabaga handle, by using OS specific mechanisms.
try_clone(&self) -> RutabagaResult<RutabagaHandle>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)]
664 pub struct RutabagaHandler<S> {
665     closure: Arc<dyn Fn(S) + Send + Sync>,
666 }
667 
668 impl<S> RutabagaHandler<S>
669 where
670     S: Send + Sync + Clone + 'static,
671 {
new(closure: impl Fn(S) + Send + Sync + 'static) -> RutabagaHandler<S>672     pub fn new(closure: impl Fn(S) + Send + Sync + 'static) -> RutabagaHandler<S> {
673         RutabagaHandler {
674             closure: Arc::new(closure),
675         }
676     }
677 
call(&self, data: S)678     pub fn call(&self, data: S) {
679         (self.closure)(data)
680     }
681 }
682 
683 impl<S> fmt::Debug for RutabagaHandler<S> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result684     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
685         f.debug_struct("Closure debug").finish()
686     }
687 }
688 
689 pub type RutabagaFenceHandler = RutabagaHandler<RutabagaFence>;
690 
691 pub type RutabagaDebugHandler = RutabagaHandler<RutabagaDebug>;
692