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