use std::sync::Arc;
use log::error;
use thiserror::Error;
use crate::bindings;
use crate::display::Display;
use crate::generic_value::GenericValue;
use crate::va_check;
use crate::GenericValueError;
use crate::VaError;
pub struct Config {
display: Arc<Display>,
id: bindings::VAConfigID,
}
#[derive(Debug, Error)]
pub enum QuerySurfaceAttributesError {
#[error("error while calling vaQuerySurfaceAttributes: {0}")]
VaError(#[from] VaError),
#[error("error while converting attribute: {0}")]
GenericValueError(#[from] GenericValueError),
}
impl Config {
pub(crate) fn new(
display: Arc<Display>,
mut attrs: Vec<bindings::VAConfigAttrib>,
profile: bindings::VAProfile::Type,
entrypoint: bindings::VAEntrypoint::Type,
) -> Result<Self, VaError> {
let mut config_id = 0u32;
va_check(unsafe {
bindings::vaCreateConfig(
display.handle(),
profile,
entrypoint,
attrs.as_mut_ptr(),
attrs.len() as i32,
&mut config_id,
)
})?;
Ok(Self { display, id: config_id })
}
pub(crate) fn id(&self) -> bindings::VAConfigID {
self.id
}
fn query_surface_attributes(&mut self) -> Result<Vec<bindings::VASurfaceAttrib>, VaError> {
let attrs_len: std::os::raw::c_uint = 0;
va_check(unsafe {
bindings::vaQuerySurfaceAttributes(
self.display.handle(),
self.id,
std::ptr::null_mut(),
&attrs_len as *const _ as *mut std::os::raw::c_uint,
)
})?;
let mut attrs = Vec::with_capacity(attrs_len as usize);
va_check(unsafe {
bindings::vaQuerySurfaceAttributes(
self.display.handle(),
self.id,
attrs.as_mut_ptr(),
&attrs_len as *const _ as *mut std::os::raw::c_uint,
)
})?;
unsafe {
attrs.set_len(attrs_len as usize);
}
Ok(attrs)
}
pub fn query_surface_attributes_by_type(
&mut self,
attr_type: bindings::VASurfaceAttribType::Type,
) -> Result<Vec<GenericValue>, QuerySurfaceAttributesError> {
let surface_attributes = self.query_surface_attributes()?;
surface_attributes
.into_iter()
.filter(|attr| attr.type_ == attr_type)
.map(|attr| GenericValue::try_from(attr.value).map_err(QuerySurfaceAttributesError::GenericValueError))
.collect()
}
}
impl Drop for Config {
fn drop(&mut self) {
let status = va_check(unsafe { bindings::vaDestroyConfig(self.display.handle(), self.id) });
if status.is_err() {
error!("vaDestroyConfig failed: {}", status.unwrap_err());
}
}
}