1use std::fmt;
2
3use skia_bindings::{self as sb, GrBackendFormat, GrBackendRenderTarget, GrBackendTexture};
4
5use crate::gpu;
6use crate::{interop::AsStr, prelude::*, ISize};
7#[cfg(feature = "d3d")]
8use gpu::d3d;
9#[cfg(feature = "gl")]
10use gpu::gl;
11#[cfg(feature = "metal")]
12use gpu::mtl;
13#[cfg(feature = "vulkan")]
14use gpu::vk;
15use gpu::{BackendAPI, Mipmapped, MutableTextureState};
16
17pub type BackendFormat = Handle<GrBackendFormat>;
18unsafe_send_sync!(BackendFormat);
19
20impl NativeDrop for GrBackendFormat {
21 fn drop(&mut self) {
22 unsafe { sb::C_GrBackendFormat_destruct(self) }
23 }
24}
25
26impl NativeClone for GrBackendFormat {
27 fn clone(&self) -> Self {
28 unsafe { GrBackendFormat::new1(self) }
29 }
30}
31
32impl fmt::Debug for BackendFormat {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 let mut d = f.debug_struct("BackendFormat");
35 d.field("backend", &self.backend());
36 d.field("channel_mask", &self.channel_mask());
37 #[cfg(feature = "gl")]
38 d.field("gl_format", &self.as_gl_format());
39 #[cfg(feature = "vulkan")]
40 d.field("vk_format", &self.as_vk_format());
41 #[cfg(feature = "metal")]
42 d.field("mtl_format", &self.as_mtl_format());
43 #[cfg(feature = "d3d")]
44 d.field("dxgi_format", &self.as_dxgi_format());
45 d.finish()
46 }
47}
48
49impl BackendFormat {
50 #[deprecated(
51 note = "The creation of invalid BackendFormats isn't supported anymore",
52 since = "0.37.0"
53 )]
54 pub fn new() -> Self {
55 Self::new_invalid()
56 }
57
58 pub(crate) fn new_invalid() -> Self {
59 Self::construct(|bf| unsafe { sb::C_GrBackendFormat_Construct(bf) })
60 }
61
62 #[cfg(feature = "gl")]
63 pub fn new_gl(format: gl::Enum, target: gl::Enum) -> Self {
64 Self::construct(|bf| unsafe { sb::C_GrBackendFormats_ConstructGL(bf, format, target) })
65 .assert_valid()
66 }
67
68 #[cfg(feature = "vulkan")]
69 #[deprecated(since = "0.67.0", note = "use gpu::backend_formats::make_vk()")]
70 pub fn new_vulkan(
71 format: vk::Format,
72 will_use_drm_format_modifiers: impl Into<Option<bool>>,
73 ) -> Self {
74 gpu::backend_formats::make_vk(format, will_use_drm_format_modifiers)
75 }
76
77 #[cfg(feature = "vulkan")]
78 #[deprecated(since = "0.67.0", note = "use gpu::backend_formats::make_vk_ycbcr()")]
79 pub fn new_vulkan_ycbcr(
80 conversion_info: &vk::YcbcrConversionInfo,
81 will_use_drm_format_modifiers: impl Into<Option<bool>>,
82 ) -> Self {
83 gpu::backend_formats::make_vk_ycbcr(conversion_info, will_use_drm_format_modifiers)
84 }
85
86 #[cfg(feature = "metal")]
87 #[deprecated(since = "0.74.0", note = "use gpu::backend_formats::make_mtl()")]
88 pub fn new_metal(format: mtl::PixelFormat) -> Self {
89 gpu::backend_formats::make_mtl(format)
90 }
91
92 #[cfg(feature = "d3d")]
93 #[deprecated(since = "0.95.0", note = "use gpu::backend_formats::make_d3d()")]
94 pub fn new_dxgi(format: d3d::DXGI_FORMAT) -> Self {
95 gpu::backend_formats::make_d3d(format)
96 }
97
98 #[cfg(feature = "d3d")]
99 #[deprecated(since = "0.95.0", note = "use gpu::backend_formats::make_d3d()")]
100 pub fn new_d3d(format: d3d::DXGI_FORMAT) -> Self {
101 gpu::backend_formats::make_d3d(format)
102 }
103
104 pub fn backend(&self) -> BackendAPI {
105 self.native().fBackend
106 }
107
108 pub fn channel_mask(&self) -> u32 {
109 unsafe { self.native().channelMask() }
110 }
111
112 #[cfg(feature = "gl")]
115 pub fn as_gl_format(&self) -> gl::Format {
116 gpu::backend_formats::as_gl_format(self)
117 }
118
119 #[cfg(feature = "gl")]
120 pub fn as_gl_format_enum(&self) -> gl::Enum {
121 gpu::backend_formats::as_gl_format_enum(self)
122 }
123
124 #[cfg(feature = "vulkan")]
126 pub fn as_vk_format(&self) -> Option<vk::Format> {
127 gpu::backend_formats::as_vk_format(self)
128 }
129
130 #[cfg(feature = "metal")]
131 pub fn as_mtl_format(&self) -> Option<mtl::PixelFormat> {
132 gpu::backend_formats::as_mtl_format(self)
133 }
134
135 #[cfg(feature = "d3d")]
136 pub fn as_dxgi_format(&self) -> Option<d3d::DXGI_FORMAT> {
137 gpu::backend_formats::as_dxgi_format(self)
138 }
139
140 #[must_use]
141 pub fn to_texture_2d(&self) -> Self {
142 let mut new = Self::new_invalid();
143 unsafe { sb::C_GrBackendFormat_makeTexture2D(self.native(), new.native_mut()) };
144 assert!(Self::native_is_valid(new.native()));
145 new
146 }
147
148 #[deprecated(
149 note = "Invalid BackendFormats are not supported anymore",
150 since = "0.37.0"
151 )]
152 pub fn is_valid(&self) -> bool {
153 self.native().fValid
154 }
155
156 pub(crate) fn native_is_valid(format: &GrBackendFormat) -> bool {
157 format.fValid
158 }
159
160 pub(crate) fn assert_valid(self) -> Self {
161 assert!(Self::native_is_valid(self.native()));
162 self
163 }
164}
165
166pub type BackendTexture = RefHandle<GrBackendTexture>;
169unsafe_send_sync!(BackendTexture);
170
171impl NativeDrop for GrBackendTexture {
172 fn drop(&mut self) {
173 unsafe { sb::C_GrBackendTexture_delete(self) }
174 }
175}
176
177impl Clone for BackendTexture {
178 fn clone(&self) -> Self {
179 unsafe { Self::from_ptr(sb::C_GrBackendTexture_Clone(self.native())) }.unwrap()
180 }
181}
182
183impl fmt::Debug for BackendTexture {
184 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185 let mut d = f.debug_struct("BackendTexture");
186 d.field("dimensions", &self.dimensions());
187 d.field("label", &self.label());
188 d.field("mipmapped", &self.mipmapped());
189 d.field("backend", &self.backend());
190 #[cfg(feature = "gl")]
191 d.field("gl_texture_info", &self.gl_texture_info());
192 #[cfg(feature = "vulkan")]
193 d.field("vulkan_image_info", &self.vulkan_image_info());
194 #[cfg(feature = "metal")]
195 d.field("metal_texture_info", &self.metal_texture_info());
196 #[cfg(feature = "d3d")]
197 d.field(
198 "d3d_texture_resource_info",
199 &self.d3d_texture_resource_info(),
200 );
201 d.field("backend_format", &self.backend_format());
202 d.field("is_protected", &self.is_protected());
203 d.finish()
204 }
205}
206
207impl BackendTexture {
208 pub(crate) fn new_invalid() -> Self {
209 Self::from_ptr(unsafe { sb::C_GrBackendTexture_new() }).unwrap()
210 }
211
212 #[cfg(feature = "gl")]
213 #[allow(clippy::missing_safety_doc)]
214 #[deprecated(since = "0.67.0", note = "use gpu::backend_textures::make_gl()")]
215 pub unsafe fn new_gl(
216 (width, height): (i32, i32),
217 mipmapped: gpu::Mipmapped,
218 gl_info: gl::TextureInfo,
219 ) -> Self {
220 gpu::backend_textures::make_gl((width, height), mipmapped, gl_info, "")
221 }
222
223 #[cfg(feature = "gl")]
224 #[allow(clippy::missing_safety_doc)]
225 #[deprecated(since = "0.67.0", note = "use gpu::backend_textures::make_gl()")]
226 pub unsafe fn new_gl_with_label(
227 (width, height): (i32, i32),
228 mipmapped: gpu::Mipmapped,
229 gl_info: gl::TextureInfo,
230 label: impl AsRef<str>,
231 ) -> Self {
232 gpu::backend_textures::make_gl((width, height), mipmapped, gl_info, label)
233 }
234
235 #[cfg(feature = "vulkan")]
236 #[allow(clippy::missing_safety_doc)]
237 #[deprecated(since = "0.67.0", note = "use gpu::backend_textures::make_vk()")]
238 pub unsafe fn new_vulkan((width, height): (i32, i32), vk_info: &vk::ImageInfo) -> Self {
239 gpu::backend_textures::make_vk((width, height), vk_info, "")
240 }
241
242 #[cfg(feature = "vulkan")]
243 #[allow(clippy::missing_safety_doc)]
244 #[deprecated(since = "0.67.0", note = "use gpu::backend_textures::make_vk()")]
245 pub unsafe fn new_vulkan_with_label(
246 (width, height): (i32, i32),
247 vk_info: &vk::ImageInfo,
248 label: impl AsRef<str>,
249 ) -> Self {
250 gpu::backend_textures::make_vk((width, height), vk_info, label)
251 }
252
253 #[cfg(feature = "metal")]
254 #[allow(clippy::missing_safety_doc)]
255 #[deprecated(since = "0.74.0", note = "use gpu::backend_textures::make_mtl()")]
256 pub unsafe fn new_metal(
257 (width, height): (i32, i32),
258 mipmapped: gpu::Mipmapped,
259 mtl_info: &mtl::TextureInfo,
260 ) -> Self {
261 gpu::backend_textures::make_mtl((width, height), mipmapped, mtl_info, "")
262 }
263
264 #[cfg(feature = "metal")]
265 #[allow(clippy::missing_safety_doc)]
266 #[deprecated(since = "0.74.0", note = "use gpu::backend_textures::make_mtl()")]
267 pub unsafe fn new_metal_with_label(
268 (width, height): (i32, i32),
269 mipmapped: gpu::Mipmapped,
270 mtl_info: &mtl::TextureInfo,
271 label: impl AsRef<str>,
272 ) -> Self {
273 gpu::backend_textures::make_mtl((width, height), mipmapped, mtl_info, label)
274 }
275
276 #[cfg(feature = "d3d")]
277 #[deprecated(since = "0.95.0", note = "use gpu::backend_textures::make_d3d()")]
278 pub fn new_d3d((width, height): (i32, i32), d3d_info: &d3d::TextureResourceInfo) -> Self {
279 gpu::backend_textures::make_d3d((width, height), d3d_info, "")
280 }
281
282 #[cfg(feature = "d3d")]
283 #[deprecated(since = "0.95.0", note = "use gpu::backend_textures::make_d3d()")]
284 pub fn new_d3d_with_label(
285 (width, height): (i32, i32),
286 d3d_info: &d3d::TextureResourceInfo,
287 label: impl AsRef<str>,
288 ) -> Self {
289 gpu::backend_textures::make_d3d((width, height), d3d_info, label)
290 }
291
292 pub(crate) unsafe fn from_native_if_valid(
293 backend_texture: *mut GrBackendTexture,
294 ) -> Option<BackendTexture> {
295 Self::native_is_valid(backend_texture)
296 .then(|| BackendTexture::from_ptr(backend_texture).unwrap())
297 }
298
299 pub fn dimensions(&self) -> ISize {
300 ISize::new(self.width(), self.height())
301 }
302
303 pub fn width(&self) -> i32 {
304 self.native().fWidth
305 }
306
307 pub fn height(&self) -> i32 {
308 self.native().fHeight
309 }
310
311 pub fn label(&self) -> &str {
312 self.native().fLabel.as_str()
313 }
314
315 pub fn mipmapped(&self) -> Mipmapped {
316 self.native().fMipmapped
317 }
318
319 #[deprecated(since = "0.35.0", note = "Use has_mipmaps()")]
320 pub fn has_mip_maps(&self) -> bool {
321 self.has_mipmaps()
322 }
323
324 pub fn has_mipmaps(&self) -> bool {
325 self.native().fMipmapped == Mipmapped::Yes
326 }
327
328 pub fn backend(&self) -> BackendAPI {
329 self.native().fBackend
330 }
331
332 #[cfg(feature = "gl")]
334 pub fn gl_texture_info(&self) -> Option<gl::TextureInfo> {
335 gpu::backend_textures::get_gl_texture_info(self)
336 }
337
338 #[cfg(feature = "gl")]
340 pub fn gl_texture_parameters_modified(&mut self) {
341 gpu::backend_textures::gl_texture_parameters_modified(self)
342 }
343
344 #[cfg(feature = "vulkan")]
346 pub fn vulkan_image_info(&self) -> Option<vk::ImageInfo> {
347 gpu::backend_textures::get_vk_image_info(self)
348 }
349
350 #[cfg(feature = "vulkan")]
352 pub fn set_vulkan_image_layout(&mut self, layout: vk::ImageLayout) -> &mut Self {
353 gpu::backend_textures::set_vk_image_layout(self, layout)
354 }
355
356 #[cfg(feature = "metal")]
357 pub fn metal_texture_info(&self) -> Option<mtl::TextureInfo> {
358 gpu::backend_textures::get_mtl_texture_info(self)
359 }
360
361 #[cfg(feature = "d3d")]
362 pub fn d3d_texture_resource_info(&self) -> Option<d3d::TextureResourceInfo> {
363 gpu::backend_textures::get_d3d_texture_resource_info(self)
364 }
365
366 #[cfg(feature = "d3d")]
367 pub fn set_d3d_resource_state(&mut self, resource_state: d3d::ResourceStateEnum) -> &mut Self {
368 gpu::backend_textures::set_d3d_resource_state(self, resource_state)
369 }
370
371 pub fn backend_format(&self) -> BackendFormat {
372 let mut format = BackendFormat::new_invalid();
373 unsafe { sb::C_GrBackendTexture_getBackendFormat(self.native(), format.native_mut()) };
374 assert!(BackendFormat::native_is_valid(format.native()));
375 format
376 }
377
378 pub fn set_mutable_state(&mut self, state: &MutableTextureState) {
379 unsafe { self.native_mut().setMutableState(state.native()) }
380 }
381
382 pub fn is_protected(&self) -> bool {
383 unsafe { self.native().isProtected() }
384 }
385
386 #[deprecated(note = "Invalid BackendTextures aren't supported", since = "0.37.0")]
387 pub fn is_valid(&self) -> bool {
388 self.native().fIsValid
389 }
390
391 pub(crate) unsafe fn native_is_valid(texture: *const GrBackendTexture) -> bool {
392 (*texture).fIsValid
393 }
394
395 #[allow(clippy::wrong_self_convention)]
396 pub fn is_same_texture(&mut self, texture: &BackendTexture) -> bool {
397 unsafe { self.native_mut().isSameTexture(texture.native()) }
398 }
399}
400
401pub type BackendRenderTarget = Handle<GrBackendRenderTarget>;
402unsafe_send_sync!(BackendRenderTarget);
403
404impl NativeDrop for GrBackendRenderTarget {
405 fn drop(&mut self) {
406 unsafe { sb::C_GrBackendRenderTarget_destruct(self) }
407 }
408}
409
410impl NativeClone for GrBackendRenderTarget {
411 fn clone(&self) -> Self {
412 construct(|render_target| unsafe {
413 sb::C_GrBackendRenderTarget_CopyConstruct(render_target, self)
414 })
415 }
416}
417
418impl fmt::Debug for BackendRenderTarget {
419 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
420 let mut d = f.debug_struct("BackendRenderTarget");
421 d.field("dimensions", &self.dimensions());
422 d.field("sample_count", &self.sample_count());
423 d.field("stencil_bits", &self.stencil_bits());
424 d.field("backend", &self.backend());
425 d.field("is_framebuffer_only", &self.is_framebuffer_only());
426 #[cfg(feature = "gl")]
427 d.field("gl_framebuffer_info", &self.gl_framebuffer_info());
428 #[cfg(feature = "vulkan")]
429 d.field("vulkan_image_info", &self.vulkan_image_info());
430 #[cfg(feature = "metal")]
431 d.field("metal_texture_info", &self.metal_texture_info());
432 #[cfg(feature = "d3d")]
433 d.field(
434 "d3d_texture_resource_info",
435 &self.d3d_texture_resource_info(),
436 );
437 d.field("backend_format", &self.backend_format());
438 d.field("is_protected", &self.is_protected());
439 d.finish()
440 }
441}
442
443impl BackendRenderTarget {
444 #[cfg(feature = "gl")]
445 #[deprecated(since = "0.67.0", note = "use gpu::backend_render_targets::make_gl()")]
446 pub fn new_gl(
447 (width, height): (i32, i32),
448 sample_count: impl Into<Option<usize>>,
449 stencil_bits: usize,
450 info: gl::FramebufferInfo,
451 ) -> Self {
452 gpu::backend_render_targets::make_gl((width, height), sample_count, stencil_bits, info)
453 }
454
455 #[cfg(feature = "vulkan")]
456 #[deprecated(since = "0.67.0", note = "use gpu::backend_render_targets::make_vk()")]
457 pub fn new_vulkan((width, height): (i32, i32), info: &vk::ImageInfo) -> Self {
458 gpu::backend_render_targets::make_vk((width, height), info)
459 }
460
461 #[cfg(feature = "metal")]
462 #[deprecated(since = "0.74.0", note = "use gpu::backend_render_targets::make_mtl()")]
463 pub fn new_metal((width, height): (i32, i32), mtl_info: &mtl::TextureInfo) -> Self {
464 gpu::backend_render_targets::make_mtl((width, height), mtl_info)
465 }
466
467 #[cfg(feature = "d3d")]
468 #[deprecated(since = "0.95.0", note = "use gpu::backend_render_targets::make_d3d()")]
469 pub fn new_d3d((width, height): (i32, i32), d3d_info: &d3d::TextureResourceInfo) -> Self {
470 gpu::backend_render_targets::make_d3d((width, height), d3d_info)
471 }
472
473 pub(crate) fn from_native_c_if_valid(
474 native: GrBackendRenderTarget,
475 ) -> Option<BackendRenderTarget> {
476 let backend_render_target = BackendRenderTarget::from_native_c(native);
477 Self::native_is_valid(backend_render_target.native()).then_some(backend_render_target)
478 }
479
480 pub fn dimensions(&self) -> ISize {
481 ISize::new(self.width(), self.height())
482 }
483
484 pub fn width(&self) -> i32 {
485 self.native().fWidth
486 }
487
488 pub fn height(&self) -> i32 {
489 self.native().fHeight
490 }
491
492 pub fn sample_count(&self) -> usize {
493 self.native().fSampleCnt.try_into().unwrap()
494 }
495
496 pub fn stencil_bits(&self) -> usize {
497 self.native().fStencilBits.try_into().unwrap()
498 }
499
500 pub fn backend(&self) -> BackendAPI {
501 self.native().fBackend
502 }
503
504 pub fn is_framebuffer_only(&self) -> bool {
505 self.native().fFramebufferOnly
506 }
507
508 #[cfg(feature = "gl")]
510 pub fn gl_framebuffer_info(&self) -> Option<gl::FramebufferInfo> {
511 gpu::backend_render_targets::get_gl_framebuffer_info(self)
512 }
513
514 #[cfg(feature = "vulkan")]
516 pub fn vulkan_image_info(&self) -> Option<vk::ImageInfo> {
517 gpu::backend_render_targets::get_vk_image_info(self)
518 }
519
520 #[cfg(feature = "vulkan")]
522 pub fn set_vulkan_image_layout(&mut self, layout: vk::ImageLayout) -> &mut Self {
523 gpu::backend_render_targets::set_vk_image_layout(self, layout)
524 }
525
526 #[cfg(feature = "metal")]
527 pub fn metal_texture_info(&self) -> Option<mtl::TextureInfo> {
528 gpu::backend_render_targets::get_mtl_texture_info(self)
529 }
530
531 #[cfg(feature = "d3d")]
532 pub fn d3d_texture_resource_info(&self) -> Option<d3d::TextureResourceInfo> {
533 gpu::backend_render_targets::get_d3d_texture_resource_info(self)
534 }
535
536 #[cfg(feature = "d3d")]
537 pub fn set_d3d_resource_state(&mut self, resource_state: d3d::ResourceStateEnum) -> &mut Self {
538 gpu::backend_render_targets::set_d3d_resource_state(self, resource_state)
539 }
540
541 pub fn backend_format(&self) -> BackendFormat {
542 BackendFormat::construct(|format| unsafe {
543 sb::C_GrBackendRenderTarget_getBackendFormat(self.native(), format)
544 })
545 }
546
547 pub fn set_mutable_state(&mut self, state: &MutableTextureState) {
548 unsafe { self.native_mut().setMutableState(state.native()) }
549 }
550
551 pub fn is_protected(&self) -> bool {
552 unsafe { self.native().isProtected() }
553 }
554
555 #[deprecated(
556 since = "0.37.0",
557 note = "Exposed BackendRenderTargets are always valid."
558 )]
559 pub fn is_valid(&self) -> bool {
560 self.native().fIsValid
561 }
562
563 pub(crate) fn native_is_valid(rt: &GrBackendRenderTarget) -> bool {
564 rt.fIsValid
565 }
566}
567
568#[cfg(test)]
569mod tests {
570 use super::BackendTexture;
571 use std::hint::black_box;
572
573 #[test]
575 fn create_move_and_drop_backend_texture() {
576 let texture = force_move(BackendTexture::new_invalid());
577 drop(texture);
578 }
579
580 fn force_move<V>(src: V) -> V {
581 let src = black_box(src);
582 *black_box(Box::new(src))
583 }
584}