Skip to main content

core_video/
metal_texture.rs

1use core_foundation::{
2    base::{Boolean, CFTypeID, TCFType},
3    declare_TCFType, impl_CFTypeDescription, impl_TCFType,
4    string::{CFString, CFStringRef},
5};
6use metal::{foreign_types::ForeignType, MTLTexture, Texture};
7
8use crate::{
9    buffer::TCVBuffer,
10    image_buffer::{CVImageBufferRef, TCVImageBuffer},
11};
12
13pub type CVMetalTextureRef = CVImageBufferRef;
14
15extern "C" {
16    pub fn CVMetalTextureGetTypeID() -> CFTypeID;
17    pub fn CVMetalTextureGetTexture(image: CVMetalTextureRef) -> *mut MTLTexture;
18    pub fn CVMetalTextureIsFlipped(image: CVMetalTextureRef) -> Boolean;
19    pub fn CVMetalTextureGetCleanTexCoords(
20        image: CVMetalTextureRef,
21        lowerLeft: *mut f32,
22        lowerRight: *mut f32,
23        upperRight: *mut f32,
24        upperLeft: *mut f32,
25    );
26
27    pub static kCVMetalTextureUsage: CFStringRef;
28    pub static kCVMetalTextureStorageMode: CFStringRef;
29}
30
31pub enum CVMetalTextureKeys {
32    Usage,
33    StorageMode,
34}
35
36impl From<CVMetalTextureKeys> for CFStringRef {
37    fn from(key: CVMetalTextureKeys) -> Self {
38        unsafe {
39            match key {
40                CVMetalTextureKeys::Usage => kCVMetalTextureUsage,
41                CVMetalTextureKeys::StorageMode => kCVMetalTextureStorageMode,
42            }
43        }
44    }
45}
46
47impl From<CVMetalTextureKeys> for CFString {
48    fn from(key: CVMetalTextureKeys) -> Self {
49        unsafe { CFString::wrap_under_get_rule(CFStringRef::from(key)) }
50    }
51}
52
53declare_TCFType!(CVMetalTexture, CVMetalTextureRef);
54impl_TCFType!(CVMetalTexture, CVMetalTextureRef, CVMetalTextureGetTypeID);
55impl_CFTypeDescription!(CVMetalTexture);
56
57impl TCVBuffer for CVMetalTexture {}
58impl TCVImageBuffer for CVMetalTexture {}
59
60impl CVMetalTexture {
61    #[inline]
62    pub fn get_texture(&self) -> Option<Texture> {
63        unsafe {
64            let texture = CVMetalTextureGetTexture(self.as_concrete_TypeRef());
65            if texture.is_null() {
66                None
67            } else {
68                Some(Texture::from_ptr(texture))
69            }
70        }
71    }
72
73    #[inline]
74    pub fn is_flipped(&self) -> bool {
75        unsafe { CVMetalTextureIsFlipped(self.as_concrete_TypeRef()) != 0 }
76    }
77
78    #[inline]
79    pub fn get_clean_tex_coords(&self) -> (f32, f32, f32, f32) {
80        let mut lower_left = 0.0;
81        let mut lower_right = 0.0;
82        let mut upper_right = 0.0;
83        let mut upper_left = 0.0;
84        unsafe {
85            CVMetalTextureGetCleanTexCoords(self.as_concrete_TypeRef(), &mut lower_left, &mut lower_right, &mut upper_right, &mut upper_left);
86        }
87        (lower_left, lower_right, upper_right, upper_left)
88    }
89}