nihed-cros-libva: get rid of log dependency
[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;
68362724
KS
8
9use crate::bindings;
10use crate::display::Display;
11use crate::generic_value::GenericValue;
12use crate::status::Status;
13
14/// A configuration for a given [`Display`].
15pub struct Config {
16 display: Rc<Display>,
17 id: bindings::VAConfigID,
18}
19
20impl 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
117impl 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}