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