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