• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::rc::Rc;
6 
7 use anyhow::Result;
8 
9 use crate::bindings;
10 use crate::display::Display;
11 use crate::status::Status;
12 use crate::UsageHint;
13 
14 /// An owned VA surface that is tied to the lifetime of a particular VADisplay
15 pub struct Surface {
16     display: Rc<Display>,
17     id: bindings::VASurfaceID,
18 }
19 
20 impl Surface {
21     /// Create `Surfaces` by wrapping around a `vaCreateSurfaces` call. This is just a helper for
22     /// [`Display::create_surfaces`].
new( display: Rc<Display>, rt_format: u32, va_fourcc: Option<u32>, width: u32, height: u32, usage_hint: Option<UsageHint>, num_surfaces: u32, ) -> Result<Vec<Self>>23     pub(crate) fn new(
24         display: Rc<Display>,
25         rt_format: u32,
26         va_fourcc: Option<u32>,
27         width: u32,
28         height: u32,
29         usage_hint: Option<UsageHint>,
30         num_surfaces: u32,
31     ) -> Result<Vec<Self>> {
32         let mut attrs = vec![];
33 
34         if let Some(usage_hint) = usage_hint {
35             let attr = bindings::VASurfaceAttrib {
36                 type_: bindings::VASurfaceAttribType::VASurfaceAttribUsageHint,
37                 flags: bindings::constants::VA_SURFACE_ATTRIB_SETTABLE,
38                 value: bindings::VAGenericValue {
39                     type_: bindings::VAGenericValueType::VAGenericValueTypeInteger,
40                     value: bindings::_VAGenericValue__bindgen_ty_1 {
41                         i: usage_hint.bits() as i32,
42                     },
43                 },
44             };
45 
46             attrs.push(attr);
47         }
48 
49         if let Some(fourcc) = va_fourcc {
50             let attr = bindings::VASurfaceAttrib {
51                 type_: bindings::VASurfaceAttribType::VASurfaceAttribPixelFormat,
52                 flags: bindings::constants::VA_DISPLAY_ATTRIB_SETTABLE,
53                 value: bindings::VAGenericValue {
54                     type_: bindings::VAGenericValueType::VAGenericValueTypeInteger,
55                     value: bindings::_VAGenericValue__bindgen_ty_1 { i: fourcc as i32 },
56                 },
57             };
58 
59             attrs.push(attr);
60         }
61 
62         let mut surfaces = Vec::with_capacity(num_surfaces as usize);
63 
64         // Safe because `self` represents a valid VADisplay. The `surface` and `attrs` vectors are
65         // properly initialized and valid sizes are passed to the C function, so it is impossible to
66         // write past the end of their storage by mistake.
67         Status(unsafe {
68             bindings::vaCreateSurfaces(
69                 display.handle(),
70                 rt_format,
71                 width,
72                 height,
73                 surfaces.as_mut_ptr(),
74                 num_surfaces,
75                 attrs.as_mut_ptr(),
76                 attrs.len() as u32,
77             )
78         })
79         .check()?;
80 
81         // Safe because the C function will have written to exactly `num_surfaces` entries, which is
82         // known to be within the vector's capacity.
83         unsafe {
84             surfaces.set_len(num_surfaces as usize);
85         }
86 
87         let va_surfaces = surfaces
88             .iter()
89             .map(|&id| Self {
90                 display: Rc::clone(&display),
91                 id,
92             })
93             .collect();
94 
95         Ok(va_surfaces)
96     }
97 
98     /// Blocks until all pending operations on the render target have been completed. Upon return it
99     /// is safe to use the render target for a different picture.
sync(&self) -> Result<()>100     pub fn sync(&self) -> Result<()> {
101         // Safe because `self` represents a valid VASurface.
102         Status(unsafe { bindings::vaSyncSurface(self.display.handle(), self.id) }).check()
103     }
104 
105     /// Convenience function to return a VASurfaceID vector. Useful to interface with the C API
106     /// where a surface array might be needed.
as_id_vec(surfaces: &[Self]) -> Vec<bindings::VASurfaceID>107     pub fn as_id_vec(surfaces: &[Self]) -> Vec<bindings::VASurfaceID> {
108         surfaces.iter().map(|surface| surface.id).collect()
109     }
110 
111     /// Wrapper over `vaQuerySurfaceStatus` to find out any pending ops on the render target.
query_status(&self) -> Result<bindings::VASurfaceStatus::Type>112     pub fn query_status(&self) -> Result<bindings::VASurfaceStatus::Type> {
113         let mut status: bindings::VASurfaceStatus::Type = 0;
114         // Safe because `self` represents a valid VASurface.
115         Status(unsafe {
116             bindings::vaQuerySurfaceStatus(self.display.handle(), self.id, &mut status)
117         })
118         .check()?;
119         Ok(status)
120     }
121 
122     /// Returns the ID of this surface.
id(&self) -> bindings::VASurfaceID123     pub fn id(&self) -> bindings::VASurfaceID {
124         self.id
125     }
126 }
127 
128 impl Drop for Surface {
drop(&mut self)129     fn drop(&mut self) {
130         // Safe because `self` represents a valid VASurface.
131         unsafe { bindings::vaDestroySurfaces(self.display.handle(), &mut self.id, 1) };
132     }
133 }
134