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 5 use std::rc::Rc; 6 7 use anyhow::Result; 8 9 use crate::bindings; 10 use crate::display::Display; 11 use crate::status::Status; 12 use crate::UsageHint; 13 14 /// An owned VA surface that is tied to the lifetime of a particular VADisplay 15 pub struct Surface { 16 display: Rc<Display>, 17 id: bindings::VASurfaceID, 18 } 19 20 impl Surface { 21 /// Create `Surfaces` by wrapping around a `vaCreateSurfaces` call. This is just a helper for 22 /// [`Display::create_surfaces`]. new( display: Rc<Display>, rt_format: u32, va_fourcc: Option<u32>, width: u32, height: u32, usage_hint: Option<UsageHint>, num_surfaces: u32, ) -> Result<Vec<Self>>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, 31 ) -> Result<Vec<Self>> { 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. 67 Status(unsafe { 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 }) 93 .collect(); 94 95 Ok(va_surfaces) 96 } 97 98 /// Blocks until all pending operations on the render target have been completed. Upon return it 99 /// is safe to use the render target for a different picture. sync(&self) -> Result<()>100 pub fn sync(&self) -> Result<()> { 101 // Safe because `self` represents a valid VASurface. 102 Status(unsafe { bindings::vaSyncSurface(self.display.handle(), self.id) }).check() 103 } 104 105 /// Convenience function to return a VASurfaceID vector. Useful to interface with the C API 106 /// where a surface array might be needed. as_id_vec(surfaces: &[Self]) -> Vec<bindings::VASurfaceID>107 pub fn as_id_vec(surfaces: &[Self]) -> Vec<bindings::VASurfaceID> { 108 surfaces.iter().map(|surface| surface.id).collect() 109 } 110 111 /// Wrapper over `vaQuerySurfaceStatus` to find out any pending ops on the render target. query_status(&self) -> Result<bindings::VASurfaceStatus::Type>112 pub fn query_status(&self) -> Result<bindings::VASurfaceStatus::Type> { 113 let mut status: bindings::VASurfaceStatus::Type = 0; 114 // Safe because `self` represents a valid VASurface. 115 Status(unsafe { 116 bindings::vaQuerySurfaceStatus(self.display.handle(), self.id, &mut status) 117 }) 118 .check()?; 119 Ok(status) 120 } 121 122 /// Returns the ID of this surface. id(&self) -> bindings::VASurfaceID123 pub fn id(&self) -> bindings::VASurfaceID { 124 self.id 125 } 126 } 127 128 impl Drop for Surface { drop(&mut self)129 fn drop(&mut self) { 130 // Safe because `self` represents a valid VASurface. 131 unsafe { bindings::vaDestroySurfaces(self.display.handle(), &mut self.id, 1) }; 132 } 133 } 134