nihed-cros-libva: use simple error enum instead of anyhow crate
[nihav-player.git] / nihed-cros-libva / src / surface.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;
69e6ce02 9use crate::status::*;
68362724
KS
10use crate::UsageHint;
11
12/// An owned VA surface that is tied to the lifetime of a particular VADisplay
13pub struct Surface {
14 display: Rc<Display>,
15 id: bindings::VASurfaceID,
16 width: u32,
17 height: u32,
18}
19
20impl 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
135impl 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}