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