diff --git a/lib/src/config.rs b/lib/src/config.rs index 7755062..64b870e 100644 --- a/lib/src/config.rs +++ b/lib/src/config.rs @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -use std::rc::Rc; +use std::sync::Arc; use log::error; use thiserror::Error; @@ -16,7 +16,7 @@ use crate::VaError; /// A configuration for a given [`Display`]. pub struct Config { - display: Rc, + display: Arc, id: bindings::VAConfigID, } @@ -32,7 +32,7 @@ impl Config { /// Creates a Config by wrapping around the `vaCreateConfig` call. This is just a helper for /// [`Display::create_config`]. pub(crate) fn new( - display: Rc, + display: Arc, mut attrs: Vec, profile: bindings::VAProfile::Type, entrypoint: bindings::VAEntrypoint::Type, diff --git a/lib/src/context.rs b/lib/src/context.rs index 1d7414d..05bc85d 100644 --- a/lib/src/context.rs +++ b/lib/src/context.rs @@ -3,6 +3,7 @@ // found in the LICENSE file. use std::rc::Rc; +use std::sync::Arc; use log::error; @@ -19,7 +20,7 @@ use crate::VaError; /// A VA context for a particular [`Display`]. pub struct Context { - display: Rc, + display: Arc, id: bindings::VAContextID, } @@ -27,7 +28,7 @@ impl Context { /// Creates a Context by wrapping around a `vaCreateContext` call. This is just a helper for /// [`Display::create_context`]. pub(crate) fn new( - display: Rc, + display: Arc, config: &Config, coded_width: u32, coded_height: u32, @@ -69,7 +70,7 @@ impl Context { } /// Returns a shared reference to the [`Display`] used by this context. - pub fn display(&self) -> &Rc { + pub fn display(&self) -> &Arc { &self.display } diff --git a/lib/src/display.rs b/lib/src/display.rs index ef9eef6..49636f3 100644 --- a/lib/src/display.rs +++ b/lib/src/display.rs @@ -9,6 +9,7 @@ use std::os::unix::io::AsRawFd; use std::path::Path; use std::path::PathBuf; use std::rc::Rc; +use std::sync::Arc; use thiserror::Error; @@ -92,7 +93,7 @@ impl Display { /// Opens and initializes a specific DRM `Display`. /// /// `path` is the path to a DRM device that supports VAAPI, e.g. `/dev/dri/renderD128`. - pub fn open_drm_display>(path: P) -> Result, OpenDrmDisplayError> { + pub fn open_drm_display>(path: P) -> Result, OpenDrmDisplayError> { let file = std::fs::File::options() .read(true) .write(true) @@ -112,7 +113,7 @@ impl Display { // vaInitialize. The File will close the DRM fd on drop. va_check(unsafe { bindings::vaInitialize(display, &mut major, &mut minor) }) .map(|()| { - Rc::new(Self { + Arc::new(Self { handle: display, drm_file: file, }) @@ -124,7 +125,7 @@ impl Display { /// /// If an error occurs on a given device, it is ignored and the next one is tried until one /// succeeds or we reach the end of the iterator. - pub fn open() -> Option> { + pub fn open() -> Option> { let devices = DrmDeviceIterator::default(); // Try all the DRM devices until one succeeds. @@ -263,7 +264,7 @@ impl Display { /// case of error the `descriptors` will be destroyed. Make sure to duplicate the descriptors /// if you need something outside of libva to access them. pub fn create_surfaces( - self: &Rc, + self: &Arc, rt_format: u32, va_fourcc: Option, width: u32, @@ -272,7 +273,7 @@ impl Display { descriptors: Vec, ) -> Result>, VaError> { Surface::new( - Rc::clone(self), + Arc::clone(self), rt_format, va_fourcc, width, @@ -292,7 +293,7 @@ impl Display { /// * `surfaces` - Optional hint for the amount of surfaces tied to the context /// * `progressive` - Whether only progressive frame pictures are present in the sequence pub fn create_context( - self: &Rc, + self: &Arc, config: &Config, coded_width: u32, coded_height: u32, @@ -300,7 +301,7 @@ impl Display { progressive: bool, ) -> Result, VaError> { Context::new( - Rc::clone(self), + Arc::clone(self), config, coded_width, coded_height, @@ -316,12 +317,12 @@ impl Display { /// [`Display::get_config_attributes`]. Other attributes will take their default values, and /// `attrs` can be empty in order to obtain a default configuration. pub fn create_config( - self: &Rc, + self: &Arc, attrs: Vec, profile: bindings::VAProfile::Type, entrypoint: bindings::VAEntrypoint::Type, ) -> Result { - Config::new(Rc::clone(self), attrs, profile, entrypoint) + Config::new(Arc::clone(self), attrs, profile, entrypoint) } /// Returns available image formats for this display by wrapping around `vaQueryImageFormats`. @@ -360,3 +361,8 @@ impl Drop for Display { } } } + +// Safe because because it only contains a `File` (which is Send+Sync), and a VADisplay handle +// which is also thread-safe. The Drop handler can also be safely called from any thread. +unsafe impl Send for Display {} +unsafe impl Sync for Display {} diff --git a/lib/src/image.rs b/lib/src/image.rs index 255a44e..0eb43fd 100644 --- a/lib/src/image.rs +++ b/lib/src/image.rs @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -use std::rc::Rc; +use std::sync::Arc; use crate::bindings; use crate::va_check; @@ -17,7 +17,7 @@ use crate::VaError; /// client memory to a surface. pub struct Image<'a> { /// The display from which the image was created, so we can unmap it upon destruction. - display: Rc, + display: Arc, /// The `VAImage` returned by libva. image: bindings::VAImage, /// The mapped surface data. @@ -68,7 +68,7 @@ impl<'a> Image<'a> { let data = unsafe { std::slice::from_raw_parts_mut(addr as _, image.data_size as usize) }; Ok(Image { - display: Rc::clone(surface.display()), + display: Arc::clone(surface.display()), image, data, derived, diff --git a/lib/src/surface.rs b/lib/src/surface.rs index 3597409..81594ab 100644 --- a/lib/src/surface.rs +++ b/lib/src/surface.rs @@ -6,7 +6,7 @@ use std::any::Any; use std::os::fd::FromRawFd; use std::os::fd::OwnedFd; use std::os::raw::c_void; -use std::rc::Rc; +use std::sync::Arc; use crate::bindings; use crate::display::Display; @@ -122,7 +122,7 @@ pub struct SurfaceDecodeMBError { /// An owned VA surface that is tied to a particular `Display`. pub struct Surface { - display: Rc, + display: Arc, id: bindings::VASurfaceID, descriptor: D, width: u32, @@ -195,7 +195,7 @@ impl Surface { /// Create `Surfaces` by wrapping around a `vaCreateSurfaces` call. This is just a helper for /// [`Display::create_surfaces`]. pub(crate) fn new( - display: Rc, + display: Arc, rt_format: u32, va_fourcc: Option, width: u32, @@ -239,7 +239,7 @@ impl Surface { ) }) { Ok(()) => surfaces.push(Self { - display: Rc::clone(&display), + display: Arc::clone(&display), id: surface_id, descriptor, width, @@ -252,7 +252,7 @@ impl Surface { Ok(surfaces) } - pub(crate) fn display(&self) -> &Rc { + pub(crate) fn display(&self) -> &Arc { &self.display }