1use std::any::Any;
6use std::os::fd::FromRawFd;
7use std::os::fd::OwnedFd;
8use std::os::raw::c_void;
9use std::sync::Arc;
10
11use crate::bindings;
12use crate::display::Display;
13use crate::va_check;
14use crate::UsageHint;
15use crate::VASurfaceID;
16use crate::VaError;
17
18pub trait SurfaceMemoryDescriptor {
29 fn add_attrs(&mut self, attrs: &mut Vec<bindings::VASurfaceAttrib>) -> Option<Box<dyn Any>>;
35}
36
37#[repr(u32)]
39pub enum MemoryType {
40 Va = bindings::VA_SURFACE_ATTRIB_MEM_TYPE_VA,
41 V4L2 = bindings::VA_SURFACE_ATTRIB_MEM_TYPE_V4L2,
42 UserPtr = bindings::VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR,
43 DrmPrime2 = bindings::VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
44}
45
46impl SurfaceMemoryDescriptor for () {
49 fn add_attrs(&mut self, _: &mut Vec<bindings::VASurfaceAttrib>) -> Option<Box<dyn Any>> {
50 None
51 }
52}
53
54mod private {
56 pub trait Sealed {}
57}
58
59pub trait SurfaceExternalDescriptor: private::Sealed {}
61impl private::Sealed for bindings::VASurfaceAttribExternalBuffers {}
62impl SurfaceExternalDescriptor for bindings::VASurfaceAttribExternalBuffers {}
63impl private::Sealed for bindings::VADRMPRIMESurfaceDescriptor {}
64impl SurfaceExternalDescriptor for bindings::VADRMPRIMESurfaceDescriptor {}
65
66pub trait ExternalBufferDescriptor {
69 const MEMORY_TYPE: MemoryType;
71 type DescriptorAttribute: SurfaceExternalDescriptor;
73
74 fn va_surface_attribute(&mut self) -> Self::DescriptorAttribute;
77}
78
79impl<T> SurfaceMemoryDescriptor for T
80where
81 T: ExternalBufferDescriptor,
82 <T as ExternalBufferDescriptor>::DescriptorAttribute: 'static,
83{
84 fn add_attrs(&mut self, attrs: &mut Vec<bindings::VASurfaceAttrib>) -> Option<Box<dyn Any>> {
85 let mut desc = Box::new(self.va_surface_attribute());
86
87 attrs.push(bindings::VASurfaceAttrib::new_memory_type(Self::MEMORY_TYPE));
88 attrs.push(bindings::VASurfaceAttrib::new_buffer_descriptor(desc.as_mut()));
89
90 Some(desc)
91 }
92}
93
94#[repr(u32)]
96#[derive(Debug)]
97pub enum DecodeErrorType {
98 SliceMissing = bindings::VADecodeErrorType::VADecodeSliceMissing,
99 MBError = bindings::VADecodeErrorType::VADecodeMBError,
100 #[cfg(libva_1_20_or_higher)]
101 Reset = bindings::VADecodeErrorType::VADecodeReset,
102}
103
104#[derive(Debug)]
106pub struct SurfaceDecodeMBError {
107 pub start_mb: u32,
109
110 pub end_mb: u32,
112
113 pub decode_error_type: DecodeErrorType,
114
115 pub num_mb: u32,
117}
118
119pub struct Surface<D: SurfaceMemoryDescriptor> {
121 display: Arc<Display>,
122 id: bindings::VASurfaceID,
123 descriptor: D,
124 width: u32,
125 height: u32,
126}
127
128impl From<i32> for bindings::VAGenericValue {
129 fn from(i: i32) -> Self {
130 Self {
131 type_: bindings::VAGenericValueType::VAGenericValueTypeInteger,
132 value: bindings::_VAGenericValue__bindgen_ty_1 { i },
133 }
134 }
135}
136
137impl From<f32> for bindings::VAGenericValue {
138 fn from(f: f32) -> Self {
139 Self {
140 type_: bindings::VAGenericValueType::VAGenericValueTypeFloat,
141 value: bindings::_VAGenericValue__bindgen_ty_1 { f },
142 }
143 }
144}
145
146impl From<*mut c_void> for bindings::VAGenericValue {
147 fn from(p: *mut c_void) -> Self {
148 Self {
149 type_: bindings::VAGenericValueType::VAGenericValueTypePointer,
150 value: bindings::_VAGenericValue__bindgen_ty_1 { p },
151 }
152 }
153}
154
155impl bindings::VASurfaceAttrib {
157 pub fn new_pixel_format(fourcc: u32) -> Self {
158 Self {
159 type_: bindings::VASurfaceAttribType::VASurfaceAttribPixelFormat,
160 flags: bindings::VA_SURFACE_ATTRIB_SETTABLE,
161 value: bindings::VAGenericValue::from(fourcc as i32),
162 }
163 }
164
165 pub fn new_usage_hint(usage_hint: UsageHint) -> Self {
166 Self {
167 type_: bindings::VASurfaceAttribType::VASurfaceAttribUsageHint,
168 flags: bindings::VA_SURFACE_ATTRIB_SETTABLE,
169 value: bindings::VAGenericValue::from(usage_hint.bits() as i32),
170 }
171 }
172
173 pub fn new_memory_type(mem_type: MemoryType) -> Self {
174 Self {
175 type_: bindings::VASurfaceAttribType::VASurfaceAttribMemoryType,
176 flags: bindings::VA_SURFACE_ATTRIB_SETTABLE,
177 value: bindings::VAGenericValue::from(mem_type as i32),
178 }
179 }
180
181 pub fn new_buffer_descriptor<T: SurfaceExternalDescriptor>(desc: &mut T) -> Self {
182 Self {
183 type_: bindings::VASurfaceAttribType::VASurfaceAttribExternalBufferDescriptor,
184 flags: bindings::VA_SURFACE_ATTRIB_SETTABLE,
185 value: bindings::VAGenericValue::from(desc as *mut _ as *mut c_void),
186 }
187 }
188}
189
190impl<D: SurfaceMemoryDescriptor> Surface<D> {
191 pub(crate) fn new(
194 display: Arc<Display>,
195 rt_format: u32,
196 va_fourcc: Option<u32>,
197 width: u32,
198 height: u32,
199 usage_hint: Option<UsageHint>,
200 descriptors: Vec<D>,
201 ) -> Result<Vec<Self>, VaError> {
202 let mut surfaces = vec![];
203
204 for mut descriptor in descriptors {
205 let mut attrs = vec![];
206
207 if let Some(usage_hint) = usage_hint {
208 attrs.push(bindings::VASurfaceAttrib::new_usage_hint(usage_hint));
209 }
210
211 if let Some(fourcc) = va_fourcc {
212 attrs.push(bindings::VASurfaceAttrib::new_pixel_format(fourcc));
213 }
214
215 let mut _va_desc = descriptor.add_attrs(&mut attrs);
217 let mut surface_id: VASurfaceID = 0;
218
219 match va_check(unsafe {
226 bindings::vaCreateSurfaces(
227 display.handle(),
228 rt_format,
229 width,
230 height,
231 &mut surface_id,
232 1,
233 attrs.as_mut_ptr(),
234 attrs.len() as u32,
235 )
236 }) {
237 Ok(()) => surfaces.push(Self {
238 display: Arc::clone(&display),
239 id: surface_id,
240 descriptor,
241 width,
242 height,
243 }),
244 Err(e) => return Err(e),
245 }
246 }
247
248 Ok(surfaces)
249 }
250
251 pub fn display(&self) -> &Arc<Display> {
252 &self.display
253 }
254
255 pub fn sync(&self) -> Result<(), VaError> {
261 va_check(unsafe { bindings::vaSyncSurface(self.display.handle(), self.id) })
263 }
264
265 pub fn as_id_vec(surfaces: &[Self]) -> Vec<bindings::VASurfaceID> {
268 surfaces.iter().map(|surface| surface.id).collect()
269 }
270
271 pub fn query_status(&self) -> Result<bindings::VASurfaceStatus::Type, VaError> {
273 let mut status: bindings::VASurfaceStatus::Type = 0;
274 va_check(unsafe { bindings::vaQuerySurfaceStatus(self.display.handle(), self.id, &mut status) })?;
276
277 Ok(status)
278 }
279
280 pub fn query_error(&self) -> Result<Vec<SurfaceDecodeMBError>, VaError> {
281 let mut raw: *const bindings::VASurfaceDecodeMBErrors = std::ptr::null();
282
283 va_check(unsafe {
285 bindings::vaQuerySurfaceError(
286 self.display.handle(),
287 self.id,
288 bindings::VA_STATUS_ERROR_DECODING_ERROR as i32,
289 (&mut raw) as *mut _ as *mut _,
290 )
291 })?;
292
293 let mut errors = vec![];
294
295 while !raw.is_null() {
296 let error = unsafe { *raw };
298 if error.status == -1 {
299 break;
300 }
301
302 let type_ = match error.decode_error_type {
303 bindings::VADecodeErrorType::VADecodeSliceMissing => DecodeErrorType::SliceMissing,
304 bindings::VADecodeErrorType::VADecodeMBError => DecodeErrorType::MBError,
305 #[cfg(libva_1_20_or_higher)]
306 bindings::VADecodeErrorType::VADecodeReset => DecodeErrorType::Reset,
307 _ => {
308 log::warn!("Unrecognized `decode_error_type` value ({})", error.decode_error_type);
309
310 raw = unsafe { raw.offset(1) };
312 continue;
313 }
314 };
315
316 errors.push(SurfaceDecodeMBError {
317 start_mb: error.start_mb,
318 end_mb: error.end_mb,
319 decode_error_type: type_,
320 num_mb: error.num_mb,
321 });
322
323 raw = unsafe { raw.offset(1) };
325 }
326
327 Ok(errors)
328 }
329
330 pub fn id(&self) -> bindings::VASurfaceID {
332 self.id
333 }
334
335 pub fn size(&self) -> (u32, u32) {
337 (self.width, self.height)
338 }
339
340 pub fn export_prime(&self) -> Result<DrmPrimeSurfaceDescriptor, VaError> {
342 let mut desc: bindings::VADRMPRIMESurfaceDescriptor = Default::default();
343
344 va_check(unsafe {
345 bindings::vaExportSurfaceHandle(
346 self.display.handle(),
347 self.id(),
348 bindings::VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
349 bindings::VA_EXPORT_SURFACE_READ_ONLY | bindings::VA_EXPORT_SURFACE_COMPOSED_LAYERS,
350 &mut desc as *mut _ as *mut c_void,
351 )
352 })?;
353
354 let objects = (0..desc.num_objects as usize)
359 .take(4)
361 .map(|i| desc.objects[i])
362 .map(|o| {
363 DrmPrimeSurfaceDescriptorObject {
364 fd: unsafe { OwnedFd::from_raw_fd(o.fd) },
367 size: o.size,
368 drm_format_modifier: o.drm_format_modifier,
369 }
370 })
371 .collect();
372
373 let layers = (0..desc.num_layers as usize)
374 .take(4)
376 .map(|i| desc.layers[i])
377 .map(|l| DrmPrimeSurfaceDescriptorLayer {
378 drm_format: l.drm_format,
379 num_planes: l.num_planes,
380 object_index: [
381 l.object_index[0] as u8,
382 l.object_index[1] as u8,
383 l.object_index[2] as u8,
384 l.object_index[3] as u8,
385 ],
386 offset: l.offset,
387 pitch: l.pitch,
388 })
389 .collect();
390
391 Ok(DrmPrimeSurfaceDescriptor {
392 fourcc: desc.fourcc,
393 width: desc.width,
394 height: desc.height,
395 objects,
396 layers,
397 })
398 }
399}
400
401impl<D: SurfaceMemoryDescriptor> AsRef<D> for Surface<D> {
402 fn as_ref(&self) -> &D {
403 &self.descriptor
404 }
405}
406
407impl<D: SurfaceMemoryDescriptor> AsMut<D> for Surface<D> {
408 fn as_mut(&mut self) -> &mut D {
409 &mut self.descriptor
410 }
411}
412
413impl<D: SurfaceMemoryDescriptor> Drop for Surface<D> {
414 fn drop(&mut self) {
415 unsafe { bindings::vaDestroySurfaces(self.display.handle(), &mut self.id, 1) };
417 }
418}
419
420pub struct DrmPrimeSurfaceDescriptorObject {
422 pub fd: OwnedFd,
423 pub size: u32,
424 pub drm_format_modifier: u64,
425}
426
427pub struct DrmPrimeSurfaceDescriptorLayer {
429 pub drm_format: u32,
430 pub num_planes: u32,
431 pub object_index: [u8; 4],
432 pub offset: [u32; 4],
433 pub pitch: [u32; 4],
434}
435
436pub struct DrmPrimeSurfaceDescriptor {
438 pub fourcc: u32,
439 pub width: u32,
440 pub height: u32,
441 pub objects: Vec<DrmPrimeSurfaceDescriptorObject>,
442 pub layers: Vec<DrmPrimeSurfaceDescriptorLayer>,
443}