1 // Copyright 2022 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 use std::borrow::Borrow; 6 use std::marker::PhantomData; 7 use std::rc::Rc; 8 9 use crate::bindings; 10 use crate::buffer::Buffer; 11 use crate::context::Context; 12 use crate::surface::Surface; 13 use crate::va_check; 14 use crate::Image; 15 use crate::SurfaceMemoryDescriptor; 16 use crate::VaError; 17 18 // Use the sealed trait pattern to make sure that new states are not created in caller code. More 19 // information about the sealed trait pattern can be found at 20 // <https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed> 21 mod private { 22 pub trait Sealed {} 23 } 24 25 /// A `Picture` will only have valid YUV data after a sequence of operations are performed in a 26 /// particular order. This order correspond to the following VA-API calls: `vaBeginPicture`, 27 /// `vaRenderPicture`, `vaEndPicture` and `vaSyncSurface`. This trait enforces this ordering by 28 /// implementing the Typestate pattern to constrain what operations are available in what particular 29 /// states. 30 /// 31 /// The states for the state machine are: 32 /// 33 /// * PictureNew -> PictureBegin 34 /// * PictureBegin -> PictureRender 35 /// * PictureRender ->PictureEnd 36 /// * PictureEnd -> PictureSync 37 /// 38 /// Where the surface can be reclaimed in both `PictureNew` and `PictureSync`, as either no 39 /// operation took place (as in `PictureNew`), or it is guaranteed that the operation has already 40 /// completed (as in `PictureSync`). 41 /// 42 /// More information about the Typestate pattern can be found at 43 /// <http://cliffle.com/blog/rust-typestate/> 44 pub trait PictureState: private::Sealed {} 45 46 /// Represents a `Picture` that has just been created. 47 pub enum PictureNew {} 48 impl PictureState for PictureNew {} 49 impl private::Sealed for PictureNew {} 50 51 /// Represents a `Picture` after `vaBeginPicture` has been called. 52 pub enum PictureBegin {} 53 impl PictureState for PictureBegin {} 54 impl private::Sealed for PictureBegin {} 55 56 /// Represents a `Picture` after `vaRenderPicture` has been called. 57 pub enum PictureRender {} 58 impl PictureState for PictureRender {} 59 impl private::Sealed for PictureRender {} 60 61 /// Represents a `Picture` after `vaEndPicture` has been called. 62 pub enum PictureEnd {} 63 impl PictureState for PictureEnd {} 64 impl private::Sealed for PictureEnd {} 65 66 /// Represents a `Picture` after `vaSyncSurface` has been called on the underlying surface. 67 pub enum PictureSync {} 68 impl PictureState for PictureSync {} 69 impl private::Sealed for PictureSync {} 70 71 /// Represents a state where one can reclaim the underlying `Surface` for this `Picture`. This is 72 /// true when either no decoding has been initiated or, alternatively, when the decoding operation 73 /// has completed for the underlying `vaSurface` 74 pub trait PictureReclaimableSurface: PictureState + private::Sealed {} 75 impl PictureReclaimableSurface for PictureNew {} 76 impl PictureReclaimableSurface for PictureSync {} 77 78 /// Inner type for [`Picture`], that is, the part that exists in all states. 79 struct PictureInner<T> { 80 /// Timestamp of the picture. 81 timestamp: u64, 82 /// A context associated with this picture. 83 context: Rc<Context>, 84 /// Contains the buffers used to decode the data. 85 buffers: Vec<Buffer>, 86 /// Contains the actual decoded data. Note that the surface may be shared in 87 /// interlaced decoding. 88 surface: Rc<T>, 89 } 90 91 /// A `Surface` that is being rendered into. 92 /// 93 /// This struct abstracts the decoding flow using `vaBeginPicture`, `vaRenderPicture`, 94 /// `vaEndPicture` and `vaSyncSurface` in a type-safe way. 95 /// 96 /// The surface will have valid picture data after all the stages of decoding are called. 97 /// 98 /// The `T` generic parameter must be `Borrow<Surface<_>>`, i.e. it can be [`Surface`] directly or 99 /// some other type that contains one. 100 /// 101 /// No constraint on `T` is specified in this declaration because specifying it here would force us 102 /// to add the generic argument of [`Surface`] to this type as well, turning it into a type with 3 103 /// generics, one of which is redundant. To avoid that we leave `T` unconstrained and instead 104 /// constrain the methods that require to act on it as a [`Surface`]. 105 pub struct Picture<S: PictureState, T> { 106 inner: Box<PictureInner<T>>, 107 phantom: std::marker::PhantomData<S>, 108 } 109 110 impl<T> Picture<PictureNew, T> { 111 /// Creates a new Picture with a given `timestamp`. `surface` is the underlying surface that 112 /// libva will render to. new<D: SurfaceMemoryDescriptor>(timestamp: u64, context: Rc<Context>, surface: T) -> Self where T: Borrow<Surface<D>>,113 pub fn new<D: SurfaceMemoryDescriptor>(timestamp: u64, context: Rc<Context>, surface: T) -> Self 114 where 115 T: Borrow<Surface<D>>, 116 { 117 Self { 118 inner: Box::new(PictureInner { 119 timestamp, 120 context, 121 buffers: Default::default(), 122 surface: Rc::new(surface), 123 }), 124 125 phantom: PhantomData, 126 } 127 } 128 129 /// Creates a new Picture with a given `timestamp` to identify it, 130 /// reusing the Surface from `picture`. This is useful for interlaced 131 /// decoding as one can render both fields to the same underlying surface. new_from_same_surface<S: PictureState>(timestamp: u64, picture: &Picture<S, T>) -> Self132 pub fn new_from_same_surface<S: PictureState>(timestamp: u64, picture: &Picture<S, T>) -> Self { 133 let context = Rc::clone(&picture.inner.context); 134 Picture { 135 inner: Box::new(PictureInner { 136 timestamp, 137 context, 138 buffers: Default::default(), 139 surface: Rc::clone(&picture.inner.surface), 140 }), 141 142 phantom: PhantomData, 143 } 144 } 145 146 /// Add `buffer` to the picture. add_buffer(&mut self, buffer: Buffer)147 pub fn add_buffer(&mut self, buffer: Buffer) { 148 self.inner.buffers.push(buffer); 149 } 150 151 /// Wrapper around `vaBeginPicture`. begin<D: SurfaceMemoryDescriptor>(self) -> Result<Picture<PictureBegin, T>, VaError> where T: Borrow<Surface<D>>,152 pub fn begin<D: SurfaceMemoryDescriptor>(self) -> Result<Picture<PictureBegin, T>, VaError> 153 where 154 T: Borrow<Surface<D>>, 155 { 156 // Safe because `self.inner.context` represents a valid VAContext and 157 // `self.inner.surface` represents a valid VASurface. 158 let res = va_check(unsafe { 159 bindings::vaBeginPicture( 160 self.inner.context.display().handle(), 161 self.inner.context.id(), 162 self.surface().id(), 163 ) 164 }); 165 166 res.map(|()| Picture { 167 inner: self.inner, 168 phantom: PhantomData, 169 }) 170 } 171 } 172 173 impl<T> Picture<PictureBegin, T> { 174 /// Wrapper around `vaRenderPicture`. render(self) -> Result<Picture<PictureRender, T>, VaError>175 pub fn render(self) -> Result<Picture<PictureRender, T>, VaError> { 176 // Safe because `self.inner.context` represents a valid `VAContext` and `self.inner.surface` 177 // represents a valid `VASurface`. `buffers` point to a Rust struct and the vector length is 178 // passed to the C function, so it is impossible to write past the end of the vector's 179 // storage by mistake. 180 va_check(unsafe { 181 bindings::vaRenderPicture( 182 self.inner.context.display().handle(), 183 self.inner.context.id(), 184 Buffer::as_id_vec(&self.inner.buffers).as_mut_ptr(), 185 self.inner.buffers.len() as i32, 186 ) 187 }) 188 .map(|()| Picture { 189 inner: self.inner, 190 phantom: PhantomData, 191 }) 192 } 193 } 194 195 impl<T> Picture<PictureRender, T> { 196 /// Wrapper around `vaEndPicture`. end(self) -> Result<Picture<PictureEnd, T>, VaError>197 pub fn end(self) -> Result<Picture<PictureEnd, T>, VaError> { 198 // Safe because `self.inner.context` represents a valid `VAContext`. 199 va_check(unsafe { 200 bindings::vaEndPicture( 201 self.inner.context.display().handle(), 202 self.inner.context.id(), 203 ) 204 }) 205 .map(|()| Picture { 206 inner: self.inner, 207 phantom: PhantomData, 208 }) 209 } 210 } 211 212 impl<T> Picture<PictureEnd, T> { 213 /// Syncs the picture, ensuring that all pending operations are complete when this call returns. sync<D: SurfaceMemoryDescriptor>( self, ) -> Result<Picture<PictureSync, T>, (VaError, Self)> where T: Borrow<Surface<D>>,214 pub fn sync<D: SurfaceMemoryDescriptor>( 215 self, 216 ) -> Result<Picture<PictureSync, T>, (VaError, Self)> 217 where 218 T: Borrow<Surface<D>>, 219 { 220 let res = self.surface().sync(); 221 222 match res { 223 Ok(()) => Ok(Picture { 224 inner: self.inner, 225 phantom: PhantomData, 226 }), 227 Err(e) => Err((e, self)), 228 } 229 } 230 } 231 232 impl<S: PictureState, T> Picture<S, T> { 233 /// Returns the timestamp of this picture. timestamp(&self) -> u64234 pub fn timestamp(&self) -> u64 { 235 self.inner.timestamp 236 } 237 238 /// Returns a reference to the underlying `Surface`. 239 /// 240 /// If you are interested in obtaining the container of the `Surface`, use `as_ref()` instead. 241 /// This is a convenience method to avoid having to call `borrow()` every time the surface is 242 /// needed. surface<D: SurfaceMemoryDescriptor>(&self) -> &Surface<D> where T: Borrow<Surface<D>>,243 pub fn surface<D: SurfaceMemoryDescriptor>(&self) -> &Surface<D> 244 where 245 T: Borrow<Surface<D>>, 246 { 247 self.as_ref().borrow() 248 } 249 } 250 251 impl<S: PictureReclaimableSurface, T> Picture<S, T> { 252 /// Reclaim ownership of the Surface this picture has been created from, consuming the picture 253 /// in the process. Useful if the Surface is part of a pool. 254 /// 255 /// This will fail and return the passed object if there are more than one reference to the 256 /// underlying surface. take_surface(self) -> Result<T, Self>257 pub fn take_surface(self) -> Result<T, Self> { 258 let inner = self.inner; 259 match Rc::try_unwrap(inner.surface) { 260 Ok(surface) => Ok(surface), 261 Err(surface) => Err(Self { 262 inner: Box::new(PictureInner { 263 surface, 264 context: inner.context, 265 buffers: inner.buffers, 266 timestamp: inner.timestamp, 267 }), 268 phantom: PhantomData, 269 }), 270 } 271 } 272 273 /// Create a new derived image from this `Picture` using `vaDeriveImage`. 274 /// 275 /// Derived images are a direct view (i.e. without any copy) on the buffer content of the 276 /// `Picture`. On the other hand, not all `Pictures` can be derived. derive_image<'a, D: SurfaceMemoryDescriptor + 'a>( &'a self, visible_rect: (u32, u32), ) -> Result<Image, VaError> where T: Borrow<Surface<D>>,277 pub fn derive_image<'a, D: SurfaceMemoryDescriptor + 'a>( 278 &'a self, 279 visible_rect: (u32, u32), 280 ) -> Result<Image, VaError> 281 where 282 T: Borrow<Surface<D>>, 283 { 284 Image::derive_from(self.surface(), visible_rect) 285 } 286 287 /// Create new image from the `Picture` using `vaCreateImage` and `vaGetImage`. 288 /// 289 /// The image will contain a copy of the `Picture` in the desired `format` and `coded_resolution`. create_image<'a, D: SurfaceMemoryDescriptor + 'a>( &'a self, format: bindings::VAImageFormat, coded_resolution: (u32, u32), visible_rect: (u32, u32), ) -> Result<Image, VaError> where T: Borrow<Surface<D>>,290 pub fn create_image<'a, D: SurfaceMemoryDescriptor + 'a>( 291 &'a self, 292 format: bindings::VAImageFormat, 293 coded_resolution: (u32, u32), 294 visible_rect: (u32, u32), 295 ) -> Result<Image, VaError> 296 where 297 T: Borrow<Surface<D>>, 298 { 299 Image::create_from(self.surface(), format, coded_resolution, visible_rect) 300 } 301 } 302 303 impl<S: PictureState, T> AsRef<T> for Picture<S, T> { as_ref(&self) -> &T304 fn as_ref(&self) -> &T { 305 (*self.inner.surface).borrow() 306 } 307 } 308