nihed-cros-libva: introduce more enums instead of constants
[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;
0f2fb233 9use crate::formats::{RTFormat, VAFourcc};
69e6ce02 10use crate::status::*;
379fea7e 11use crate::UsageHints;
68362724
KS
12
13/// An owned VA surface that is tied to the lifetime of a particular VADisplay
14pub struct Surface {
15 display: Rc<Display>,
16 id: bindings::VASurfaceID,
17 width: u32,
18 height: u32,
19}
20
21impl Surface {
22 /// Create `Surfaces` by wrapping around a `vaCreateSurfaces` call. This is just a helper for
23 /// [`Display::create_surfaces`].
24 pub(crate) fn new(
25 display: Rc<Display>,
0f2fb233
KS
26 rt_format: RTFormat,
27 va_fourcc: Option<VAFourcc>,
68362724
KS
28 width: u32,
29 height: u32,
379fea7e 30 usage_hints: Option<UsageHints>,
68362724 31 num_surfaces: u32,
69e6ce02 32 ) -> VAResult<Vec<Self>> {
68362724
KS
33 let mut attrs = vec![];
34
379fea7e 35 if let Some(usage_hints) = usage_hints {
68362724
KS
36 let attr = bindings::VASurfaceAttrib {
37 type_: bindings::VASurfaceAttribType::VASurfaceAttribUsageHint,
38 flags: bindings::constants::VA_SURFACE_ATTRIB_SETTABLE,
39 value: bindings::VAGenericValue {
40 type_: bindings::VAGenericValueType::VAGenericValueTypeInteger,
41 value: bindings::_VAGenericValue__bindgen_ty_1 {
379fea7e 42 i: usage_hints.bits() as i32,
68362724
KS
43 },
44 },
45 };
46
47 attrs.push(attr);
48 }
49
50 if let Some(fourcc) = va_fourcc {
51 let attr = bindings::VASurfaceAttrib {
52 type_: bindings::VASurfaceAttribType::VASurfaceAttribPixelFormat,
53 flags: bindings::constants::VA_DISPLAY_ATTRIB_SETTABLE,
54 value: bindings::VAGenericValue {
55 type_: bindings::VAGenericValueType::VAGenericValueTypeInteger,
56 value: bindings::_VAGenericValue__bindgen_ty_1 { i: fourcc as i32 },
57 },
58 };
59
60 attrs.push(attr);
61 }
62
63 let mut surfaces = Vec::with_capacity(num_surfaces as usize);
64
65 // Safe because `self` represents a valid VADisplay. The `surface` and `attrs` vectors are
66 // properly initialized and valid sizes are passed to the C function, so it is impossible to
67 // write past the end of their storage by mistake.
69e6ce02 68 (unsafe {
68362724
KS
69 bindings::vaCreateSurfaces(
70 display.handle(),
0f2fb233 71 rt_format.into(),
68362724
KS
72 width,
73 height,
74 surfaces.as_mut_ptr(),
75 num_surfaces,
76 attrs.as_mut_ptr(),
77 attrs.len() as u32,
78 )
79 })
80 .check()?;
81
82 // Safe because the C function will have written to exactly `num_surfaces` entries, which is
83 // known to be within the vector's capacity.
84 unsafe {
85 surfaces.set_len(num_surfaces as usize);
86 }
87
88 let va_surfaces = surfaces
89 .iter()
90 .map(|&id| Self {
91 display: Rc::clone(&display),
92 id,
93 width,
94 height,
95 })
96 .collect();
97
98 Ok(va_surfaces)
99 }
100
101 /// Blocks until all pending operations on the render target have been completed. Upon return it
102 /// is safe to use the render target for a different picture.
69e6ce02 103 pub fn sync(&self) -> VAResult<()> {
68362724 104 // Safe because `self` represents a valid VASurface.
69e6ce02 105 (unsafe { bindings::vaSyncSurface(self.display.handle(), self.id) }).check()
68362724
KS
106 }
107
108 /// Convenience function to return a VASurfaceID vector. Useful to interface with the C API
109 /// where a surface array might be needed.
110 pub fn as_id_vec(surfaces: &[Self]) -> Vec<bindings::VASurfaceID> {
111 surfaces.iter().map(|surface| surface.id).collect()
112 }
113
114 /// Wrapper over `vaQuerySurfaceStatus` to find out any pending ops on the render target.
36e9827e 115 pub fn query_status(&self) -> VAResult<VASurfaceStatus> {
68362724
KS
116 let mut status: bindings::VASurfaceStatus::Type = 0;
117 // Safe because `self` represents a valid VASurface.
69e6ce02 118 (unsafe {
68362724
KS
119 bindings::vaQuerySurfaceStatus(self.display.handle(), self.id, &mut status)
120 })
121 .check()?;
36e9827e
KS
122 match status {
123 bindings::VASurfaceStatus::VASurfaceRendering => Ok(VASurfaceStatus::Rendering),
124 bindings::VASurfaceStatus::VASurfaceDisplaying => Ok(VASurfaceStatus::Displaying),
125 bindings::VASurfaceStatus::VASurfaceReady => Ok(VASurfaceStatus::Ready),
126 bindings::VASurfaceStatus::VASurfaceSkipped => Ok(VASurfaceStatus::Skipped),
127 _ => Err(VAError::Unknown),
128 }
68362724
KS
129 }
130
131 /// Returns the ID of this surface.
132 pub fn id(&self) -> bindings::VASurfaceID {
133 self.id
134 }
135
136 /// Returns the dimensions of this surface.
137 pub fn size(&self) -> (u32, u32) {
138 (self.width, self.height)
139 }
140}
141
142impl Drop for Surface {
143 fn drop(&mut self) {
144 // Safe because `self` represents a valid VASurface.
145 unsafe { bindings::vaDestroySurfaces(self.display.handle(), &mut self.id, 1) };
146 }
147}