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