core_video/
metal_texture.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use core_foundation::{
    base::{Boolean, CFTypeID, TCFType},
    string::{CFString, CFStringRef},
};
use metal::{foreign_types::ForeignType, MTLTexture, Texture};

use crate::{
    buffer::TCVBuffer,
    image_buffer::{CVImageBufferRef, TCVImageBuffer},
};

pub type CVMetalTextureRef = CVImageBufferRef;

extern "C" {
    pub fn CVMetalTextureGetTypeID() -> CFTypeID;
    pub fn CVMetalTextureGetTexture(image: CVMetalTextureRef) -> *mut MTLTexture;
    pub fn CVMetalTextureIsFlipped(image: CVMetalTextureRef) -> Boolean;
    pub fn CVMetalTextureGetCleanTexCoords(
        image: CVMetalTextureRef,
        lowerLeft: *mut f32,
        lowerRight: *mut f32,
        upperRight: *mut f32,
        upperLeft: *mut f32,
    );

    pub static kCVMetalTextureUsage: CFStringRef;
    pub static kCVMetalTextureStorageMode: CFStringRef;
}

pub enum CVMetalTextureKeys {
    Usage,
    StorageMode,
}

impl From<CVMetalTextureKeys> for CFStringRef {
    fn from(key: CVMetalTextureKeys) -> Self {
        unsafe {
            match key {
                CVMetalTextureKeys::Usage => kCVMetalTextureUsage,
                CVMetalTextureKeys::StorageMode => kCVMetalTextureStorageMode,
            }
        }
    }
}

impl From<CVMetalTextureKeys> for CFString {
    fn from(key: CVMetalTextureKeys) -> Self {
        unsafe { CFString::wrap_under_get_rule(CFStringRef::from(key)) }
    }
}

impl TCVBuffer for CVMetalTexture {}
impl TCVImageBuffer for CVMetalTexture {}

declare_TCFType! {
    CVMetalTexture, CVMetalTextureRef
}
impl_TCFType!(CVMetalTexture, CVMetalTextureRef, CVMetalTextureGetTypeID);
impl_CFTypeDescription!(CVMetalTexture);

impl CVMetalTexture {
    #[inline]
    pub fn get_texture(&self) -> Option<Texture> {
        unsafe {
            let texture = CVMetalTextureGetTexture(self.as_concrete_TypeRef());
            if texture.is_null() {
                None
            } else {
                Some(Texture::from_ptr(texture))
            }
        }
    }

    #[inline]
    pub fn is_flipped(&self) -> bool {
        unsafe { CVMetalTextureIsFlipped(self.as_concrete_TypeRef()) != 0 }
    }

    #[inline]
    pub fn get_clean_tex_coords(&self) -> (f32, f32, f32, f32) {
        let mut lower_left = 0.0;
        let mut lower_right = 0.0;
        let mut upper_right = 0.0;
        let mut upper_left = 0.0;
        unsafe {
            CVMetalTextureGetCleanTexCoords(self.as_concrete_TypeRef(), &mut lower_left, &mut lower_right, &mut upper_right, &mut upper_left);
        }
        (lower_left, lower_right, upper_right, upper_left)
    }
}