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