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