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 = Handle<GrYUVABackendTextures>;
113unsafe_send_sync!(YUVABackendTextures);
114
115impl NativeDrop for GrYUVABackendTextures {
116 fn drop(&mut self) {
117 unsafe { sb::C_GrYUVABackendTextures_destruct(self) }
118 }
119}
120
121impl fmt::Debug for YUVABackendTextures {
122 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123 f.debug_struct("YUVABackendTextures")
124 .field("yuva_info", &self.yuva_info())
125 .field("texture_origin", &self.texture_origin())
126 .field("textures", &self.textures())
127 .finish()
128 }
129}
130
131impl YUVABackendTextures {
132 pub fn new(
133 info: &YUVAInfo,
134 textures: &[BackendTexture],
135 texture_origin: SurfaceOrigin,
136 ) -> Option<Self> {
137 if textures.len() != info.num_planes() {
138 return None;
139 }
140 let new_invalid = BackendTexture::new_invalid();
141 let new_invalid_ptr = new_invalid.native() as *const _;
142
143 let mut texture_handles = textures
144 .iter()
145 .map(|tex| tex.native() as *const _)
146 .collect::<Vec<_>>();
147 texture_handles.extend(iter::repeat_n(
148 new_invalid_ptr,
149 YUVAInfo::MAX_PLANES - textures.len(),
150 ));
151 assert_eq!(texture_handles.len(), YUVAInfo::MAX_PLANES);
152
153 let n = construct(|cloned| unsafe {
154 sb::C_GrYUVABackendTextures_construct(
155 cloned,
156 info.native(),
157 texture_handles.as_ptr(),
158 texture_origin,
159 )
160 });
161 Self::native_is_valid(&n).then(|| Self::from_native_c(n))
162 }
163
164 pub fn textures(&self) -> Vec<BackendTexture> {
165 unsafe {
166 let textures_ptr = sb::C_GrYUVABackendTextures_textures(self.native());
167 let textures = safer::from_raw_parts(textures_ptr, self.num_planes());
168 textures
169 .iter()
170 .map(|native_texture_ref| {
171 BackendTexture::from_ptr(sb::C_GrBackendTexture_Clone(native_texture_ref))
172 .unwrap()
173 })
174 .collect()
175 }
176 }
177
178 pub fn texture(&self, i: usize) -> Option<BackendTexture> {
179 self.textures().get(i).cloned()
180 }
181
182 pub fn yuva_info(&self) -> &YUVAInfo {
183 YUVAInfo::from_native_ref(unsafe { &*sb::C_GrYUVABackendTextures_yuvaInfo(self.native()) })
184 }
185
186 pub fn num_planes(&self) -> usize {
187 self.yuva_info().num_planes()
188 }
189
190 pub fn texture_origin(&self) -> SurfaceOrigin {
191 unsafe { sb::C_GrYUVABackendTextures_textureOrigin(self.native()) }
192 }
193
194 pub(crate) fn native_is_valid(n: &GrYUVABackendTextures) -> bool {
195 YUVAInfo::native_is_valid(unsafe { &*sb::C_GrYUVABackendTextures_yuvaInfo(n) })
196 }
197}