]>
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 | ||
7 | use anyhow::Result; | |
68362724 KS |
8 | |
9 | use crate::bindings; | |
10 | use crate::display::Display; | |
11 | use crate::generic_value::GenericValue; | |
12 | use crate::status::Status; | |
13 | ||
14 | /// A configuration for a given [`Display`]. | |
15 | pub struct Config { | |
16 | display: Rc<Display>, | |
17 | id: bindings::VAConfigID, | |
18 | } | |
19 | ||
20 | impl Config { | |
21 | /// Creates a Config by wrapping around the `vaCreateConfig` call. This is just a helper for | |
22 | /// [`Display::create_config`]. | |
23 | pub(crate) fn new( | |
24 | display: Rc<Display>, | |
25 | mut attrs: Vec<bindings::VAConfigAttrib>, | |
26 | profile: bindings::VAProfile::Type, | |
27 | entrypoint: bindings::VAEntrypoint::Type, | |
28 | ) -> Result<Self> { | |
29 | let mut config_id = 0u32; | |
30 | ||
31 | // Safe because `self` represents a valid `VADisplay`. | |
32 | // | |
33 | // The `attrs` vector is also properly initialized and its actual size is passed to | |
34 | // `vaCreateConfig`, so it is impossible to write past the end of its storage by mistake. | |
35 | Status(unsafe { | |
36 | bindings::vaCreateConfig( | |
37 | display.handle(), | |
38 | profile, | |
39 | entrypoint, | |
40 | attrs.as_mut_ptr(), | |
41 | attrs.len() as i32, | |
42 | &mut config_id, | |
43 | ) | |
44 | }) | |
45 | .check()?; | |
46 | ||
47 | Ok(Self { | |
48 | display, | |
49 | id: config_id, | |
50 | }) | |
51 | } | |
52 | ||
53 | /// Returns the ID of this config. | |
54 | pub(crate) fn id(&self) -> bindings::VAConfigID { | |
55 | self.id | |
56 | } | |
57 | ||
58 | // Queries surface attributes for this config. | |
59 | // | |
60 | // This function queries for all supported attributes for this configuration. In particular, if | |
61 | // the underlying hardware supports the creation of VA surfaces in various formats, then this | |
62 | // function will enumerate all pixel formats that are supported. | |
63 | fn query_surface_attributes(&mut self) -> Result<Vec<bindings::VASurfaceAttrib>> { | |
64 | // Safe because `self` represents a valid VAConfig. We first query how | |
65 | // much space is needed by the C API by passing in NULL in the first | |
66 | // call to `vaQuerySurfaceAttributes`. | |
67 | let attrs_len: std::os::raw::c_uint = 0; | |
68 | Status(unsafe { | |
69 | bindings::vaQuerySurfaceAttributes( | |
70 | self.display.handle(), | |
71 | self.id, | |
72 | std::ptr::null_mut(), | |
73 | &attrs_len as *const _ as *mut std::os::raw::c_uint, | |
74 | ) | |
75 | }) | |
76 | .check()?; | |
77 | ||
78 | let mut attrs = Vec::with_capacity(attrs_len as usize); | |
79 | // Safe because we allocate a vector with the required capacity as | |
80 | // returned by the initial call to vaQuerySurfaceAttributes. We then | |
81 | // pass a valid pointer to it. | |
82 | Status(unsafe { | |
83 | bindings::vaQuerySurfaceAttributes( | |
84 | self.display.handle(), | |
85 | self.id, | |
86 | attrs.as_mut_ptr(), | |
87 | &attrs_len as *const _ as *mut std::os::raw::c_uint, | |
88 | ) | |
89 | }) | |
90 | .check()?; | |
91 | ||
92 | // Safe because vaQuerySurfaceAttributes will have written to | |
93 | // exactly attrs_len entries in the vector. | |
94 | unsafe { | |
95 | attrs.set_len(attrs_len as usize); | |
96 | } | |
97 | ||
98 | Ok(attrs) | |
99 | } | |
100 | ||
101 | /// Query the surface attributes of type `attr_type`. The attribute may or may not be defined by | |
102 | /// the driver. | |
103 | pub fn query_surface_attributes_by_type( | |
104 | &mut self, | |
105 | attr_type: bindings::VASurfaceAttribType::Type, | |
106 | ) -> Result<Vec<GenericValue>> { | |
107 | let surface_attributes = self.query_surface_attributes()?; | |
108 | ||
109 | surface_attributes | |
110 | .into_iter() | |
111 | .filter(|attr| attr.type_ == attr_type) | |
112 | .map(|attrib| GenericValue::try_from(attrib.value)) | |
113 | .collect() | |
114 | } | |
115 | } | |
116 | ||
117 | impl Drop for Config { | |
118 | fn drop(&mut self) { | |
119 | // Safe because `self` represents a valid Config. | |
120 | let status = | |
121 | Status(unsafe { bindings::vaDestroyConfig(self.display.handle(), self.id) }).check(); | |
122 | if status.is_err() { | |
51b33b65 | 123 | println!("vaDestroyConfig failed: {}", status.unwrap_err()); |
68362724 KS |
124 | } |
125 | } | |
126 | } |