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