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; | |
69e6ce02 | 9 | use crate::status::*; |
68362724 KS |
10 | use crate::UsageHint; |
11 | ||
12 | /// An owned VA surface that is tied to the lifetime of a particular VADisplay | |
13 | pub struct Surface { | |
14 | display: Rc<Display>, | |
15 | id: bindings::VASurfaceID, | |
16 | width: u32, | |
17 | height: u32, | |
18 | } | |
19 | ||
20 | impl Surface { | |
21 | /// Create `Surfaces` by wrapping around a `vaCreateSurfaces` call. This is just a helper for | |
22 | /// [`Display::create_surfaces`]. | |
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, | |
69e6ce02 | 31 | ) -> VAResult<Vec<Self>> { |
68362724 KS |
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. | |
69e6ce02 | 67 | (unsafe { |
68362724 KS |
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 | width, | |
93 | height, | |
94 | }) | |
95 | .collect(); | |
96 | ||
97 | Ok(va_surfaces) | |
98 | } | |
99 | ||
100 | /// Blocks until all pending operations on the render target have been completed. Upon return it | |
101 | /// is safe to use the render target for a different picture. | |
69e6ce02 | 102 | pub fn sync(&self) -> VAResult<()> { |
68362724 | 103 | // Safe because `self` represents a valid VASurface. |
69e6ce02 | 104 | (unsafe { bindings::vaSyncSurface(self.display.handle(), self.id) }).check() |
68362724 KS |
105 | } |
106 | ||
107 | /// Convenience function to return a VASurfaceID vector. Useful to interface with the C API | |
108 | /// where a surface array might be needed. | |
109 | pub fn as_id_vec(surfaces: &[Self]) -> Vec<bindings::VASurfaceID> { | |
110 | surfaces.iter().map(|surface| surface.id).collect() | |
111 | } | |
112 | ||
113 | /// Wrapper over `vaQuerySurfaceStatus` to find out any pending ops on the render target. | |
69e6ce02 | 114 | pub fn query_status(&self) -> VAResult<bindings::VASurfaceStatus::Type> { |
68362724 KS |
115 | let mut status: bindings::VASurfaceStatus::Type = 0; |
116 | // Safe because `self` represents a valid VASurface. | |
69e6ce02 | 117 | (unsafe { |
68362724 KS |
118 | bindings::vaQuerySurfaceStatus(self.display.handle(), self.id, &mut status) |
119 | }) | |
120 | .check()?; | |
121 | Ok(status) | |
122 | } | |
123 | ||
124 | /// Returns the ID of this surface. | |
125 | pub fn id(&self) -> bindings::VASurfaceID { | |
126 | self.id | |
127 | } | |
128 | ||
129 | /// Returns the dimensions of this surface. | |
130 | pub fn size(&self) -> (u32, u32) { | |
131 | (self.width, self.height) | |
132 | } | |
133 | } | |
134 | ||
135 | impl Drop for Surface { | |
136 | fn drop(&mut self) { | |
137 | // Safe because `self` represents a valid VASurface. | |
138 | unsafe { bindings::vaDestroySurfaces(self.display.handle(), &mut self.id, 1) }; | |
139 | } | |
140 | } |