skia_safe/gpu/ganesh/
yuva_backend_textures.rs1use crate::gpu::{BackendFormat, BackendTexture, Mipmapped, SurfaceOrigin};
2use crate::{prelude::*, YUVAInfo, YUVColorSpace};
3use skia_bindings::{self as sb, GrYUVABackendTextureInfo, GrYUVABackendTextures};
4use std::{fmt, iter};
5
6pub type YUVABackendTextureInfo = Handle<GrYUVABackendTextureInfo>;
8unsafe_send_sync!(YUVABackendTextureInfo);
9
10impl NativeDrop for GrYUVABackendTextureInfo {
11 fn drop(&mut self) {
12 unsafe { sb::C_GrYUVABackendTextureInfo_destruct(self) }
13 }
14}
15
16impl NativeClone for GrYUVABackendTextureInfo {
17 fn clone(&self) -> Self {
18 construct(|cloned| unsafe { sb::C_GrYUVABackendTextureInfo_CopyConstruct(cloned, self) })
19 }
20}
21
22impl NativePartialEq for GrYUVABackendTextureInfo {
23 fn eq(&self, rhs: &Self) -> bool {
24 unsafe { sb::C_GrYUVABackendTextureInfo_equals(self, rhs) }
25 }
26}
27
28impl fmt::Debug for YUVABackendTextureInfo {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 f.debug_struct("YUVABackendTextureInfo")
31 .field("yuva_info", &self.yuva_info())
32 .field("yuv_color_space", &self.yuv_color_space())
33 .field("mipmapped", &self.mipmapped())
34 .field("texture_origin", &self.texture_origin())
35 .field("plane_formats", &self.plane_formats())
36 .finish()
37 }
38}
39
40impl YUVABackendTextureInfo {
41 pub const MAX_PLANES: usize = YUVAInfo::MAX_PLANES;
42
43 pub fn new(
49 info: &YUVAInfo,
50 formats: &[BackendFormat],
51 mip_mapped: Mipmapped,
52 origin: SurfaceOrigin,
53 ) -> Option<Self> {
54 if formats.len() != info.num_planes() {
55 return None;
56 }
57
58 let mut formats = formats.to_vec();
59 formats.extend(
60 iter::repeat_with(BackendFormat::new_invalid).take(Self::MAX_PLANES - formats.len()),
61 );
62 assert_eq!(formats.len(), Self::MAX_PLANES);
63
64 let n = unsafe {
65 GrYUVABackendTextureInfo::new(info.native(), formats[0].native(), mip_mapped, origin)
66 };
67 Self::native_is_valid(&n).then(|| Self::from_native_c(n))
68 }
69
70 pub fn yuva_info(&self) -> &YUVAInfo {
71 YUVAInfo::from_native_ref(&self.native().fYUVAInfo)
72 }
73
74 pub fn yuv_color_space(&self) -> YUVColorSpace {
75 self.yuva_info().yuv_color_space()
76 }
77
78 pub fn mipmapped(&self) -> Mipmapped {
79 self.native().fMipmapped
80 }
81
82 pub fn texture_origin(&self) -> SurfaceOrigin {
83 self.native().fTextureOrigin
84 }
85
86 pub fn num_planes(&self) -> usize {
88 self.yuva_info().num_planes()
89 }
90
91 pub fn plane_format(&self, i: usize) -> Option<&BackendFormat> {
93 (i < self.num_planes())
94 .then(|| BackendFormat::from_native_ref(&self.native().fPlaneFormats[i]))
95 }
96
97 pub fn plane_formats(&self) -> &[BackendFormat] {
99 unsafe {
100 let formats = BackendFormat::from_native_ref(&self.native().fPlaneFormats[0]);
101 safer::from_raw_parts(formats, self.num_planes())
102 }
103 }
104
105 pub(crate) fn native_is_valid(info: &GrYUVABackendTextureInfo) -> bool {
107 YUVAInfo::native_is_valid(&info.fYUVAInfo)
108 }
109}
110
111pub type YUVABackendTextures = RefHandle<GrYUVABackendTextures>;
116unsafe_send_sync!(YUVABackendTextures);
117
118impl NativeDrop for GrYUVABackendTextures {
119 fn drop(&mut self) {
120 unsafe { sb::C_GrYUVABackendTextures_delete(self) }
121 }
122}
123
124impl fmt::Debug for YUVABackendTextures {
125 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126 f.debug_struct("YUVABackendTextures")
127 .field("yuva_info", &self.yuva_info())
128 .field("texture_origin", &self.texture_origin())
129 .field("textures", &self.textures())
130 .finish()
131 }
132}
133
134impl YUVABackendTextures {
135 pub fn new(
136 info: &YUVAInfo,
137 textures: &[BackendTexture],
138 texture_origin: SurfaceOrigin,
139 ) -> Option<Self> {
140 if textures.len() != info.num_planes() {
141 return None;
142 }
143 let new_invalid = BackendTexture::new_invalid();
144 let new_invalid_ptr = new_invalid.native() as *const _;
145
146 let mut texture_handles = textures
147 .iter()
148 .map(|tex| tex.native() as *const _)
149 .collect::<Vec<_>>();
150 texture_handles.extend(iter::repeat_n(
151 new_invalid_ptr,
152 YUVAInfo::MAX_PLANES - textures.len(),
153 ));
154 assert_eq!(texture_handles.len(), YUVAInfo::MAX_PLANES);
155
156 let textures = Self::from_ptr(unsafe {
157 sb::C_GrYUVABackendTextures_new(info.native(), texture_handles.as_ptr(), texture_origin)
158 })?;
159 Self::native_is_valid(textures.native()).then_some(textures)
160 }
161
162 pub fn textures(&self) -> Vec<BackendTexture> {
163 unsafe {
164 let textures_ptr = sb::C_GrYUVABackendTextures_textures(self.native());
165 let textures = safer::from_raw_parts(textures_ptr, self.num_planes());
166 textures
167 .iter()
168 .map(|native_texture_ref| {
169 BackendTexture::from_ptr(sb::C_GrBackendTexture_Clone(native_texture_ref))
170 .unwrap()
171 })
172 .collect()
173 }
174 }
175
176 pub fn texture(&self, i: usize) -> Option<BackendTexture> {
177 self.textures().get(i).cloned()
178 }
179
180 pub fn yuva_info(&self) -> &YUVAInfo {
181 YUVAInfo::from_native_ref(unsafe { &*sb::C_GrYUVABackendTextures_yuvaInfo(self.native()) })
182 }
183
184 pub fn num_planes(&self) -> usize {
185 self.yuva_info().num_planes()
186 }
187
188 pub fn texture_origin(&self) -> SurfaceOrigin {
189 unsafe { sb::C_GrYUVABackendTextures_textureOrigin(self.native()) }
190 }
191
192 pub(crate) fn native_is_valid(n: &GrYUVABackendTextures) -> bool {
193 YUVAInfo::native_is_valid(unsafe { &*sb::C_GrYUVABackendTextures_yuvaInfo(n) })
194 }
195}