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