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