• 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::io::Error as IoError;
9 use std::num::TryFromIntError;
10 use std::os::raw::c_void;
11 use std::path::PathBuf;
12 use std::str::Utf8Error;
13 
14 use data_model::VolatileMemoryError;
15 #[cfg(unix)]
16 use nix::Error as NixError;
17 use remain::sorted;
18 use serde::Deserialize;
19 use serde::Serialize;
20 use thiserror::Error;
21 #[cfg(feature = "vulkano")]
22 use vulkano::device::DeviceCreationError;
23 #[cfg(feature = "vulkano")]
24 use vulkano::image::ImageCreationError;
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 unsafe impl Send for RutabagaIovec {}
48 unsafe impl Sync for RutabagaIovec {}
49 
50 /// 3D resource creation parameters.  Also used to create 2D resource.  Constants based on Mesa's
51 /// (internal) Gallium interface.  Not in the virtio-gpu spec, but should be since dumb resources
52 /// can't work with gfxstream/virglrenderer without this.
53 pub const RUTABAGA_PIPE_TEXTURE_2D: u32 = 2;
54 pub const RUTABAGA_PIPE_BIND_RENDER_TARGET: u32 = 2;
55 #[repr(C)]
56 #[derive(Copy, Clone, Debug)]
57 pub struct ResourceCreate3D {
58     pub target: u32,
59     pub format: u32,
60     pub bind: u32,
61     pub width: u32,
62     pub height: u32,
63     pub depth: u32,
64     pub array_size: u32,
65     pub last_level: u32,
66     pub nr_samples: u32,
67     pub flags: u32,
68 }
69 
70 /// Blob resource creation parameters.
71 pub const RUTABAGA_BLOB_MEM_GUEST: u32 = 0x0001;
72 pub const RUTABAGA_BLOB_MEM_HOST3D: u32 = 0x0002;
73 pub const RUTABAGA_BLOB_MEM_HOST3D_GUEST: u32 = 0x0003;
74 
75 pub const RUTABAGA_BLOB_FLAG_USE_MAPPABLE: u32 = 0x0001;
76 pub const RUTABAGA_BLOB_FLAG_USE_SHAREABLE: u32 = 0x0002;
77 pub const RUTABAGA_BLOB_FLAG_USE_CROSS_DEVICE: u32 = 0x0004;
78 #[repr(C)]
79 #[derive(Copy, Clone, Debug)]
80 pub struct ResourceCreateBlob {
81     pub blob_mem: u32,
82     pub blob_flags: u32,
83     pub blob_id: u64,
84     pub size: u64,
85 }
86 
87 #[repr(C)]
88 #[derive(Copy, Clone, Debug)]
89 pub struct RutabagaMapping {
90     pub ptr: u64,
91     pub size: u64,
92 }
93 
94 /// Metadata associated with a swapchain, video or camera image.
95 #[derive(Default, Copy, Clone, Debug)]
96 pub struct Resource3DInfo {
97     pub width: u32,
98     pub height: u32,
99     pub drm_fourcc: u32,
100     pub strides: [u32; 4],
101     pub offsets: [u32; 4],
102     pub modifier: u64,
103 }
104 
105 /// A unique identifier for a device.
106 #[derive(
107     Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize,
108 )]
109 pub struct DeviceId {
110     pub device_uuid: [u8; 16],
111     pub driver_uuid: [u8; 16],
112 }
113 
114 /// Memory index and physical device id of the associated VkDeviceMemory.
115 #[derive(Copy, Clone, Default)]
116 pub struct VulkanInfo {
117     pub memory_idx: u32,
118     pub device_id: DeviceId,
119 }
120 
121 /// Rutabaga context init capset id mask.
122 pub const RUTABAGA_CONTEXT_INIT_CAPSET_ID_MASK: u32 = 0x00ff;
123 
124 /// Rutabaga flags for creating fences.
125 pub const RUTABAGA_FLAG_FENCE: u32 = 1 << 0;
126 pub const RUTABAGA_FLAG_INFO_RING_IDX: u32 = 1 << 1;
127 
128 /// Convenience struct for Rutabaga fences
129 #[repr(C)]
130 #[derive(Copy, Clone)]
131 pub struct RutabagaFence {
132     pub flags: u32,
133     pub fence_id: u64,
134     pub ctx_id: u32,
135     pub ring_idx: u8,
136 }
137 
138 /// Mapped memory caching flags (see virtio_gpu spec)
139 pub const RUTABAGA_MAP_CACHE_CACHED: u32 = 0x01;
140 pub const RUTABAGA_MAP_CACHE_UNCACHED: u32 = 0x02;
141 pub const RUTABAGA_MAP_CACHE_WC: u32 = 0x03;
142 
143 /// Rutabaga capsets.
144 pub const RUTABAGA_CAPSET_VIRGL: u32 = 1;
145 pub const RUTABAGA_CAPSET_VIRGL2: u32 = 2;
146 pub const RUTABAGA_CAPSET_GFXSTREAM: u32 = 3;
147 pub const RUTABAGA_CAPSET_VENUS: u32 = 4;
148 pub const RUTABAGA_CAPSET_CROSS_DOMAIN: u32 = 5;
149 pub const RUTABAGA_CAPSET_DRM: u32 = 6;
150 
151 /// An error generated while using this crate.
152 #[sorted]
153 #[derive(Error, Debug)]
154 pub enum RutabagaError {
155     /// Indicates `Rutabaga` was already initialized since only one Rutabaga instance per process
156     /// is allowed.
157     #[error("attempted to use a rutabaga asset already in use")]
158     AlreadyInUse,
159     /// Checked Arithmetic error
160     #[error("arithmetic failed: {}({}) {op} {}({})", .field1.0, .field1.1, .field2.0, .field2.1)]
161     CheckedArithmetic {
162         field1: (&'static str, usize),
163         field2: (&'static str, usize),
164         op: &'static str,
165     },
166     /// Checked Range error
167     #[error("range check failed: {}({}) vs {}({})", .field1.0, .field1.1, .field2.0, .field2.1)]
168     CheckedRange {
169         field1: (&'static str, usize),
170         field2: (&'static str, usize),
171     },
172     /// An internal Rutabaga component error was returned.
173     #[error("rutabaga component failed with error {0}")]
174     ComponentError(i32),
175     /// Invalid 2D info
176     #[error("invalid 2D info")]
177     Invalid2DInfo,
178     /// Invalid Capset
179     #[error("invalid capset")]
180     InvalidCapset,
181     /// A command buffer with insufficient space was submitted.
182     #[error("invalid command buffer submitted")]
183     InvalidCommandBuffer,
184     /// A command size was submitted that was invalid.
185     #[error("command buffer submitted with invalid size: {0}")]
186     InvalidCommandSize(usize),
187     /// Invalid RutabagaComponent
188     #[error("invalid rutabaga component")]
189     InvalidComponent,
190     /// Invalid Context ID
191     #[error("invalid context id")]
192     InvalidContextId,
193     /// Invalid cross domain channel
194     #[error("invalid cross domain channel")]
195     InvalidCrossDomainChannel,
196     /// Invalid cross domain item ID
197     #[error("invalid cross domain item id")]
198     InvalidCrossDomainItemId,
199     /// Invalid cross domain item type
200     #[error("invalid cross domain item type")]
201     InvalidCrossDomainItemType,
202     /// Invalid cross domain state
203     #[error("invalid cross domain state")]
204     InvalidCrossDomainState,
205     /// Invalid gralloc backend.
206     #[error("invalid gralloc backend")]
207     InvalidGrallocBackend,
208     /// Invalid gralloc dimensions.
209     #[error("invalid gralloc dimensions")]
210     InvalidGrallocDimensions,
211     /// Invalid gralloc DRM format.
212     #[error("invalid gralloc DRM format")]
213     InvalidGrallocDrmFormat,
214     /// Invalid GPU type.
215     #[error("invalid GPU type for gralloc")]
216     InvalidGrallocGpuType,
217     /// Invalid number of YUV planes.
218     #[error("invalid number of YUV planes")]
219     InvalidGrallocNumberOfPlanes,
220     /// The indicated region of guest memory is invalid.
221     #[error("an iovec is outside of guest memory's range")]
222     InvalidIovec,
223     /// Invalid Resource ID.
224     #[error("invalid resource id")]
225     InvalidResourceId,
226     /// Indicates an error in the RutabagaBuilder.
227     #[error("invalid rutabaga build parameters: {0}")]
228     InvalidRutabagaBuild(&'static str),
229     /// An error with the RutabagaHandle
230     #[error("invalid rutabaga handle")]
231     InvalidRutabagaHandle,
232     /// Invalid Vulkan info
233     #[error("invalid vulkan info")]
234     InvalidVulkanInfo,
235     /// An input/output error occured.
236     #[error("an input/output error occur: {0}")]
237     IoError(IoError),
238     /// The mapping failed.
239     #[error("The mapping failed with library error: {0}")]
240     MappingFailed(i32),
241     /// Nix crate error.
242     #[cfg(unix)]
243     #[error("The errno is {0}")]
244     NixError(NixError),
245     #[error("Nul Error occured {0}")]
246     NulError(NulError),
247     /// Violation of the Rutabaga spec occured.
248     #[error("violation of the rutabaga spec: {0}")]
249     SpecViolation(&'static str),
250     /// An attempted integer conversion failed.
251     #[error("int conversion failed: {0}")]
252     TryFromIntError(TryFromIntError),
253     /// The command is unsupported.
254     #[error("the requested function is not implemented")]
255     Unsupported,
256     /// Utf8 error.
257     #[error("an utf8 error occured: {0}")]
258     Utf8Error(Utf8Error),
259     /// Device creation error
260     #[cfg(feature = "vulkano")]
261     #[error("vulkano device creation failure {0}")]
262     VkDeviceCreationError(DeviceCreationError),
263     /// Device memory error
264     #[cfg(feature = "vulkano")]
265     #[error("vulkano device memory failure {0}")]
266     VkDeviceMemoryError(DeviceMemoryError),
267     /// General Vulkan error
268     #[cfg(feature = "vulkano")]
269     #[error("vulkano failure {0}")]
270     VkError(VulkanError),
271     /// Image creation error
272     #[cfg(feature = "vulkano")]
273     #[error("vulkano image creation failure {0}")]
274     VkImageCreationError(ImageCreationError),
275     /// Instance creation error
276     #[cfg(feature = "vulkano")]
277     #[error("vulkano instance creation failure {0}")]
278     VkInstanceCreationError(InstanceCreationError),
279     /// Loading error
280     #[cfg(feature = "vulkano")]
281     #[error("vulkano loading failure {0}")]
282     VkLoadingError(LoadingError),
283     /// Memory map error
284     #[cfg(feature = "vulkano")]
285     #[error("vulkano memory map failure {0}")]
286     VkMemoryMapError(MemoryMapError),
287     /// Volatile memory error
288     #[error("noticed a volatile memory error {0}")]
289     VolatileMemoryError(VolatileMemoryError),
290 }
291 
292 #[cfg(unix)]
293 impl From<NixError> for RutabagaError {
from(e: NixError) -> RutabagaError294     fn from(e: NixError) -> RutabagaError {
295         RutabagaError::NixError(e)
296     }
297 }
298 
299 impl From<NulError> for RutabagaError {
from(e: NulError) -> RutabagaError300     fn from(e: NulError) -> RutabagaError {
301         RutabagaError::NulError(e)
302     }
303 }
304 
305 impl From<IoError> for RutabagaError {
from(e: IoError) -> RutabagaError306     fn from(e: IoError) -> RutabagaError {
307         RutabagaError::IoError(e)
308     }
309 }
310 
311 impl From<TryFromIntError> for RutabagaError {
from(e: TryFromIntError) -> RutabagaError312     fn from(e: TryFromIntError) -> RutabagaError {
313         RutabagaError::TryFromIntError(e)
314     }
315 }
316 
317 impl From<Utf8Error> for RutabagaError {
from(e: Utf8Error) -> RutabagaError318     fn from(e: Utf8Error) -> RutabagaError {
319         RutabagaError::Utf8Error(e)
320     }
321 }
322 
323 impl From<VolatileMemoryError> for RutabagaError {
from(e: VolatileMemoryError) -> RutabagaError324     fn from(e: VolatileMemoryError) -> RutabagaError {
325         RutabagaError::VolatileMemoryError(e)
326     }
327 }
328 
329 /// The result of an operation in this crate.
330 pub type RutabagaResult<T> = std::result::Result<T, RutabagaError>;
331 
332 /// Flags for virglrenderer.  Copied from virglrenderer bindings.
333 const VIRGLRENDERER_USE_EGL: u32 = 1 << 0;
334 const VIRGLRENDERER_THREAD_SYNC: u32 = 1 << 1;
335 const VIRGLRENDERER_USE_GLX: u32 = 1 << 2;
336 const VIRGLRENDERER_USE_SURFACELESS: u32 = 1 << 3;
337 const VIRGLRENDERER_USE_GLES: u32 = 1 << 4;
338 const VIRGLRENDERER_USE_EXTERNAL_BLOB: u32 = 1 << 5;
339 const VIRGLRENDERER_VENUS: u32 = 1 << 6;
340 const VIRGLRENDERER_NO_VIRGL: u32 = 1 << 7;
341 const VIRGLRENDERER_USE_ASYNC_FENCE_CB: u32 = 1 << 8;
342 const VIRGLRENDERER_RENDER_SERVER: u32 = 1 << 9;
343 const VIRGLRENDERER_DRM: u32 = 1 << 10;
344 
345 /// virglrenderer flag struct.
346 #[derive(Copy, Clone)]
347 pub struct VirglRendererFlags(u32);
348 
349 impl Default for VirglRendererFlags {
default() -> VirglRendererFlags350     fn default() -> VirglRendererFlags {
351         VirglRendererFlags::new()
352             .use_virgl(true)
353             .use_venus(false)
354             .use_egl(true)
355             .use_surfaceless(true)
356             .use_gles(true)
357             .use_render_server(false)
358     }
359 }
360 
361 impl From<VirglRendererFlags> for u32 {
from(flags: VirglRendererFlags) -> u32362     fn from(flags: VirglRendererFlags) -> u32 {
363         flags.0
364     }
365 }
366 
367 impl From<VirglRendererFlags> for i32 {
from(flags: VirglRendererFlags) -> i32368     fn from(flags: VirglRendererFlags) -> i32 {
369         flags.0 as i32
370     }
371 }
372 
373 impl VirglRendererFlags {
374     /// Create new virglrenderer flags.
new() -> VirglRendererFlags375     pub fn new() -> VirglRendererFlags {
376         VirglRendererFlags(0)
377     }
378 
set_flag(self, bitmask: u32, set: bool) -> VirglRendererFlags379     fn set_flag(self, bitmask: u32, set: bool) -> VirglRendererFlags {
380         if set {
381             VirglRendererFlags(self.0 | bitmask)
382         } else {
383             VirglRendererFlags(self.0 & (!bitmask))
384         }
385     }
386 
387     /// Enable virgl support
use_virgl(self, v: bool) -> VirglRendererFlags388     pub fn use_virgl(self, v: bool) -> VirglRendererFlags {
389         self.set_flag(VIRGLRENDERER_NO_VIRGL, !v)
390     }
391 
392     /// Enable venus support
use_venus(self, v: bool) -> VirglRendererFlags393     pub fn use_venus(self, v: bool) -> VirglRendererFlags {
394         self.set_flag(VIRGLRENDERER_VENUS, v)
395     }
396 
397     /// Enable drm native context support
use_drm(self, v: bool) -> VirglRendererFlags398     pub fn use_drm(self, v: bool) -> VirglRendererFlags {
399         self.set_flag(VIRGLRENDERER_DRM, v)
400     }
401 
402     /// Use EGL for context creation.
use_egl(self, v: bool) -> VirglRendererFlags403     pub fn use_egl(self, v: bool) -> VirglRendererFlags {
404         self.set_flag(VIRGLRENDERER_USE_EGL, v)
405     }
406 
407     /// Use a dedicated thread for fence synchronization.
use_thread_sync(self, v: bool) -> VirglRendererFlags408     pub fn use_thread_sync(self, v: bool) -> VirglRendererFlags {
409         self.set_flag(VIRGLRENDERER_THREAD_SYNC, v)
410     }
411 
412     /// Use GLX for context creation.
use_glx(self, v: bool) -> VirglRendererFlags413     pub fn use_glx(self, v: bool) -> VirglRendererFlags {
414         self.set_flag(VIRGLRENDERER_USE_GLX, v)
415     }
416 
417     /// No surfaces required when creating context.
use_surfaceless(self, v: bool) -> VirglRendererFlags418     pub fn use_surfaceless(self, v: bool) -> VirglRendererFlags {
419         self.set_flag(VIRGLRENDERER_USE_SURFACELESS, v)
420     }
421 
422     /// Use GLES drivers.
use_gles(self, v: bool) -> VirglRendererFlags423     pub fn use_gles(self, v: bool) -> VirglRendererFlags {
424         self.set_flag(VIRGLRENDERER_USE_GLES, v)
425     }
426 
427     /// Use external memory when creating blob resources.
use_external_blob(self, v: bool) -> VirglRendererFlags428     pub fn use_external_blob(self, v: bool) -> VirglRendererFlags {
429         self.set_flag(VIRGLRENDERER_USE_EXTERNAL_BLOB, v)
430     }
431 
432     /// Retire fence directly from sync thread.
use_async_fence_cb(self, v: bool) -> VirglRendererFlags433     pub fn use_async_fence_cb(self, v: bool) -> VirglRendererFlags {
434         self.set_flag(VIRGLRENDERER_USE_ASYNC_FENCE_CB, v)
435     }
436 
use_render_server(self, v: bool) -> VirglRendererFlags437     pub fn use_render_server(self, v: bool) -> VirglRendererFlags {
438         self.set_flag(VIRGLRENDERER_RENDER_SERVER, v)
439     }
440 }
441 
442 /// Flags for the gfxstream renderer.
443 const GFXSTREAM_RENDERER_FLAGS_USE_EGL: u32 = 1 << 0;
444 #[allow(dead_code)]
445 const GFXSTREAM_RENDERER_FLAGS_THREAD_SYNC: u32 = 1 << 1;
446 const GFXSTREAM_RENDERER_FLAGS_USE_GLX: u32 = 1 << 2;
447 const GFXSTREAM_RENDERER_FLAGS_USE_SURFACELESS: u32 = 1 << 3;
448 const GFXSTREAM_RENDERER_FLAGS_USE_GLES: u32 = 1 << 4;
449 const GFXSTREAM_RENDERER_FLAGS_NO_VK_BIT: u32 = 1 << 5;
450 const GFXSTREAM_RENDERER_FLAGS_ENABLE_GLES31_BIT: u32 = 1 << 9;
451 const GFXSTREAM_RENDERER_FLAGS_USE_EXTERNAL_BLOB: u32 = 1 << 10;
452 const GFXSTREAM_RENDERER_FLAGS_USE_SYSTEM_BLOB: u32 = 1 << 11;
453 const GFXSTREAM_RENDERER_FLAGS_GUEST_USES_ANGLE: u32 = 1 << 21;
454 const GFXSTREAM_RENDERER_FLAGS_VULKAN_NATIVE_SWAPCHAIN_BIT: u32 = 1 << 22;
455 const GFXSTREAM_RENDERER_FLAGS_ASYNC_FENCE_CB: u32 = 1 << 23;
456 
457 /// gfxstream flag struct.
458 #[derive(Copy, Clone, Default)]
459 pub struct GfxstreamFlags(u32);
460 
461 #[derive(Clone, Debug, Serialize, Deserialize)]
462 #[serde(rename_all = "kebab-case")]
463 pub enum RutabagaWsi {
464     #[serde(alias = "vk")]
465     Vulkan,
466 }
467 
468 impl GfxstreamFlags {
469     /// Create new gfxstream flags.
new() -> GfxstreamFlags470     pub fn new() -> GfxstreamFlags {
471         GfxstreamFlags(0)
472     }
473 
set_flag(self, bitmask: u32, set: bool) -> GfxstreamFlags474     fn set_flag(self, bitmask: u32, set: bool) -> GfxstreamFlags {
475         if set {
476             GfxstreamFlags(self.0 | bitmask)
477         } else {
478             GfxstreamFlags(self.0 & (!bitmask))
479         }
480     }
481 
482     /// Use EGL for context creation.
use_egl(self, v: bool) -> GfxstreamFlags483     pub fn use_egl(self, v: bool) -> GfxstreamFlags {
484         self.set_flag(GFXSTREAM_RENDERER_FLAGS_USE_EGL, v)
485     }
486 
487     /// Use GLX for context creation.
use_glx(self, v: bool) -> GfxstreamFlags488     pub fn use_glx(self, v: bool) -> GfxstreamFlags {
489         self.set_flag(GFXSTREAM_RENDERER_FLAGS_USE_GLX, v)
490     }
491 
492     /// No surfaces required when creating context.
use_surfaceless(self, v: bool) -> GfxstreamFlags493     pub fn use_surfaceless(self, v: bool) -> GfxstreamFlags {
494         self.set_flag(GFXSTREAM_RENDERER_FLAGS_USE_SURFACELESS, v)
495     }
496 
497     /// Use GLES drivers.
use_gles(self, v: bool) -> GfxstreamFlags498     pub fn use_gles(self, v: bool) -> GfxstreamFlags {
499         self.set_flag(GFXSTREAM_RENDERER_FLAGS_USE_GLES, v)
500     }
501 
502     /// Support using Vulkan.
use_vulkan(self, v: bool) -> GfxstreamFlags503     pub fn use_vulkan(self, v: bool) -> GfxstreamFlags {
504         self.set_flag(GFXSTREAM_RENDERER_FLAGS_NO_VK_BIT, !v)
505     }
506 
507     /// Use ANGLE as the guest GLES driver.
use_guest_angle(self, v: bool) -> GfxstreamFlags508     pub fn use_guest_angle(self, v: bool) -> GfxstreamFlags {
509         self.set_flag(GFXSTREAM_RENDERER_FLAGS_GUEST_USES_ANGLE, v)
510     }
511 
512     /// Use async fence completion callback.
use_async_fence_cb(self, v: bool) -> GfxstreamFlags513     pub fn use_async_fence_cb(self, v: bool) -> GfxstreamFlags {
514         self.set_flag(GFXSTREAM_RENDERER_FLAGS_ASYNC_FENCE_CB, v)
515     }
516 
517     /// Enable GLES 3.1 support.
support_gles31(self, v: bool) -> GfxstreamFlags518     pub fn support_gles31(self, v: bool) -> GfxstreamFlags {
519         self.set_flag(GFXSTREAM_RENDERER_FLAGS_ENABLE_GLES31_BIT, v)
520     }
521 
522     /// Use the Vulkan swapchain to draw on the host window.
set_wsi(self, v: Option<&RutabagaWsi>) -> GfxstreamFlags523     pub fn set_wsi(self, v: Option<&RutabagaWsi>) -> GfxstreamFlags {
524         let use_vulkan_swapchain = matches!(v, Some(RutabagaWsi::Vulkan));
525         self.set_flag(
526             GFXSTREAM_RENDERER_FLAGS_VULKAN_NATIVE_SWAPCHAIN_BIT,
527             use_vulkan_swapchain,
528         )
529     }
530 
531     /// Use external blob when creating resources.
use_external_blob(self, v: bool) -> GfxstreamFlags532     pub fn use_external_blob(self, v: bool) -> GfxstreamFlags {
533         self.set_flag(GFXSTREAM_RENDERER_FLAGS_USE_EXTERNAL_BLOB, v)
534     }
535 
536     /// Use system blob when creating resources.
use_system_blob(self, v: bool) -> GfxstreamFlags537     pub fn use_system_blob(self, v: bool) -> GfxstreamFlags {
538         self.set_flag(GFXSTREAM_RENDERER_FLAGS_USE_SYSTEM_BLOB, v)
539     }
540 }
541 
542 impl From<GfxstreamFlags> for u32 {
from(flags: GfxstreamFlags) -> u32543     fn from(flags: GfxstreamFlags) -> u32 {
544         flags.0
545     }
546 }
547 
548 impl From<GfxstreamFlags> for i32 {
from(flags: GfxstreamFlags) -> i32549     fn from(flags: GfxstreamFlags) -> i32 {
550         flags.0 as i32
551     }
552 }
553 
554 impl From<GfxstreamFlags> for u64 {
from(flags: GfxstreamFlags) -> u64555     fn from(flags: GfxstreamFlags) -> u64 {
556         flags.0 as u64
557     }
558 }
559 
560 /// Transfers {to, from} 1D buffers, 2D textures, 3D textures, and cubemaps.
561 #[repr(C)]
562 #[derive(Copy, Clone, Debug)]
563 pub struct Transfer3D {
564     pub x: u32,
565     pub y: u32,
566     pub z: u32,
567     pub w: u32,
568     pub h: u32,
569     pub d: u32,
570     pub level: u32,
571     pub stride: u32,
572     pub layer_stride: u32,
573     pub offset: u64,
574 }
575 
576 impl Transfer3D {
577     /// Constructs a 2 dimensional XY box in 3 dimensional space with unit depth and zero
578     /// displacement on the Z axis.
new_2d(x: u32, y: u32, w: u32, h: u32) -> Transfer3D579     pub fn new_2d(x: u32, y: u32, w: u32, h: u32) -> Transfer3D {
580         Transfer3D {
581             x,
582             y,
583             z: 0,
584             w,
585             h,
586             d: 1,
587             level: 0,
588             stride: 0,
589             layer_stride: 0,
590             offset: 0,
591         }
592     }
593 
594     /// Returns true if this box represents a volume of zero.
is_empty(&self) -> bool595     pub fn is_empty(&self) -> bool {
596         self.w == 0 || self.h == 0 || self.d == 0
597     }
598 }
599 
600 /// Rutabaga channel types
601 pub const RUTABAGA_CHANNEL_TYPE_WAYLAND: u32 = 0x0001;
602 pub const RUTABAGA_CHANNEL_TYPE_CAMERA: u32 = 0x0002;
603 
604 /// Information needed to open an OS-specific RutabagaConnection (TBD).  Only Linux hosts are
605 /// considered at the moment.
606 #[derive(Clone)]
607 pub struct RutabagaChannel {
608     pub base_channel: PathBuf,
609     pub channel_type: u32,
610 }
611 
612 /// Enumeration of possible rutabaga components.
613 #[repr(u8)]
614 #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)]
615 pub enum RutabagaComponentType {
616     Rutabaga2D,
617     VirglRenderer,
618     Gfxstream,
619     CrossDomain,
620 }
621 
622 /// Rutabaga handle types (memory and sync in same namespace)
623 pub const RUTABAGA_MEM_HANDLE_TYPE_OPAQUE_FD: u32 = 0x0001;
624 pub const RUTABAGA_MEM_HANDLE_TYPE_DMABUF: u32 = 0x0002;
625 pub const RUTABAGA_MEM_HANDLE_TYPE_OPAQUE_WIN32: u32 = 0x0003;
626 pub const RUTABAGA_MEM_HANDLE_TYPE_SHM: u32 = 0x0004;
627 pub const RUTABAGA_FENCE_HANDLE_TYPE_OPAQUE_FD: u32 = 0x0010;
628 pub const RUTABAGA_FENCE_HANDLE_TYPE_SYNC_FD: u32 = 0x0011;
629 pub const RUTABAGA_FENCE_HANDLE_TYPE_OPAQUE_WIN32: u32 = 0x0012;
630 
631 /// Handle to OS-specific memory or synchronization objects.
632 pub struct RutabagaHandle {
633     pub os_handle: SafeDescriptor,
634     pub handle_type: u32,
635 }
636 
637 impl RutabagaHandle {
638     /// Clones an existing rutabaga handle, by using OS specific mechanisms.
try_clone(&self) -> RutabagaResult<RutabagaHandle>639     pub fn try_clone(&self) -> RutabagaResult<RutabagaHandle> {
640         let clone = self
641             .os_handle
642             .try_clone()
643             .map_err(|_| RutabagaError::InvalidRutabagaHandle)?;
644         Ok(RutabagaHandle {
645             os_handle: clone,
646             handle_type: self.handle_type,
647         })
648     }
649 }
650 
651 /// Trait for fence completion handlers
652 pub trait RutabagaFenceCallback: Send {
call(&self, data: RutabagaFence)653     fn call(&self, data: RutabagaFence);
clone_box(&self) -> RutabagaFenceHandler654     fn clone_box(&self) -> RutabagaFenceHandler;
655 }
656 
657 /// Wrapper type to allow cloning while respecting object-safety
658 pub type RutabagaFenceHandler = Box<dyn RutabagaFenceCallback>;
659 
660 impl Clone for RutabagaFenceHandler {
clone(&self) -> Self661     fn clone(&self) -> Self {
662         self.clone_box()
663     }
664 }
665 
666 /// Fence handler implementation that wraps a closure
667 #[derive(Clone)]
668 pub struct RutabagaFenceClosure<T> {
669     closure: T,
670 }
671 
672 impl<T> RutabagaFenceClosure<T>
673 where
674     T: Fn(RutabagaFence) + Clone + Send + 'static,
675 {
new(closure: T) -> RutabagaFenceHandler676     pub fn new(closure: T) -> RutabagaFenceHandler {
677         Box::new(RutabagaFenceClosure { closure })
678     }
679 }
680 
681 impl<T> RutabagaFenceCallback for RutabagaFenceClosure<T>
682 where
683     T: Fn(RutabagaFence) + Clone + Send + 'static,
684 {
call(&self, data: RutabagaFence)685     fn call(&self, data: RutabagaFence) {
686         (self.closure)(data)
687     }
688 
clone_box(&self) -> RutabagaFenceHandler689     fn clone_box(&self) -> RutabagaFenceHandler {
690         Box::new(self.clone())
691     }
692 }
693