use std::borrow::Borrow;
use std::marker::PhantomData;
use std::rc::Rc;
use crate::bindings;
use crate::buffer::Buffer;
use crate::context::Context;
use crate::surface::Surface;
use crate::va_check;
use crate::Image;
use crate::SurfaceMemoryDescriptor;
use crate::VaError;
mod private {
pub trait Sealed {}
}
pub trait PictureState: private::Sealed {}
pub enum PictureNew {}
impl PictureState for PictureNew {}
impl private::Sealed for PictureNew {}
pub enum PictureBegin {}
impl PictureState for PictureBegin {}
impl private::Sealed for PictureBegin {}
pub enum PictureRender {}
impl PictureState for PictureRender {}
impl private::Sealed for PictureRender {}
pub enum PictureEnd {}
impl PictureState for PictureEnd {}
impl private::Sealed for PictureEnd {}
pub enum PictureSync {}
impl PictureState for PictureSync {}
impl private::Sealed for PictureSync {}
pub trait PictureReclaimableSurface: PictureState + private::Sealed {}
impl PictureReclaimableSurface for PictureNew {}
impl PictureReclaimableSurface for PictureSync {}
struct PictureInner<T> {
timestamp: u64,
context: Rc<Context>,
buffers: Vec<Buffer>,
surface: Rc<T>,
}
pub struct Picture<S: PictureState, T> {
inner: Box<PictureInner<T>>,
phantom: std::marker::PhantomData<S>,
}
impl<T> Picture<PictureNew, T> {
pub fn new<D: SurfaceMemoryDescriptor>(timestamp: u64, context: Rc<Context>, surface: T) -> Self
where
T: Borrow<Surface<D>>,
{
Self {
inner: Box::new(PictureInner {
timestamp,
context,
buffers: Default::default(),
surface: Rc::new(surface),
}),
phantom: PhantomData,
}
}
pub fn new_from_same_surface<S: PictureState>(timestamp: u64, picture: &Picture<S, T>) -> Self {
let context = Rc::clone(&picture.inner.context);
Picture {
inner: Box::new(PictureInner {
timestamp,
context,
buffers: Default::default(),
surface: Rc::clone(&picture.inner.surface),
}),
phantom: PhantomData,
}
}
pub fn add_buffer(&mut self, buffer: Buffer) {
self.inner.buffers.push(buffer);
}
pub fn begin<D: SurfaceMemoryDescriptor>(self) -> Result<Picture<PictureBegin, T>, VaError>
where
T: Borrow<Surface<D>>,
{
let res = va_check(unsafe {
bindings::vaBeginPicture(
self.inner.context.display().handle(),
self.inner.context.id(),
self.surface().id(),
)
});
res.map(|()| Picture {
inner: self.inner,
phantom: PhantomData,
})
}
}
impl<T> Picture<PictureBegin, T> {
pub fn render(self) -> Result<Picture<PictureRender, T>, VaError> {
va_check(unsafe {
bindings::vaRenderPicture(
self.inner.context.display().handle(),
self.inner.context.id(),
Buffer::as_id_vec(&self.inner.buffers).as_mut_ptr(),
self.inner.buffers.len() as i32,
)
})
.map(|()| Picture {
inner: self.inner,
phantom: PhantomData,
})
}
}
impl<T> Picture<PictureRender, T> {
pub fn end(self) -> Result<Picture<PictureEnd, T>, VaError> {
va_check(unsafe { bindings::vaEndPicture(self.inner.context.display().handle(), self.inner.context.id()) }).map(
|()| Picture {
inner: self.inner,
phantom: PhantomData,
},
)
}
}
impl<T> Picture<PictureEnd, T> {
pub fn sync<D: SurfaceMemoryDescriptor>(self) -> Result<Picture<PictureSync, T>, (VaError, Self)>
where
T: Borrow<Surface<D>>,
{
let res = self.surface().sync();
match res {
Ok(()) => Ok(Picture {
inner: self.inner,
phantom: PhantomData,
}),
Err(e) => Err((e, self)),
}
}
}
impl<S: PictureState, T> Picture<S, T> {
pub fn timestamp(&self) -> u64 {
self.inner.timestamp
}
pub fn surface<D: SurfaceMemoryDescriptor>(&self) -> &Surface<D>
where
T: Borrow<Surface<D>>,
{
self.as_ref().borrow()
}
}
impl<S: PictureReclaimableSurface, T> Picture<S, T> {
pub fn take_surface(self) -> Result<T, Self> {
let inner = self.inner;
match Rc::try_unwrap(inner.surface) {
Ok(surface) => Ok(surface),
Err(surface) => Err(Self {
inner: Box::new(PictureInner {
surface,
context: inner.context,
buffers: inner.buffers,
timestamp: inner.timestamp,
}),
phantom: PhantomData,
}),
}
}
pub fn derive_image<'a, D: SurfaceMemoryDescriptor + 'a>(
&'a self,
visible_rect: (u32, u32),
) -> Result<Image<'a>, VaError>
where
T: Borrow<Surface<D>>,
{
Image::derive_from(self.surface(), visible_rect)
}
pub fn create_image<'a, D: SurfaceMemoryDescriptor + 'a>(
&'a self,
format: bindings::VAImageFormat,
coded_resolution: (u32, u32),
visible_rect: (u32, u32),
) -> Result<Image<'a>, VaError>
where
T: Borrow<Surface<D>>,
{
Image::create_from(self.surface(), format, coded_resolution, visible_rect)
}
}
impl<S: PictureState, T> AsRef<T> for Picture<S, T> {
fn as_ref(&self) -> &T {
(*self.inner.surface).borrow()
}
}