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
use {
    super::unexpected_result,
    crate::{
        out_of_host_memory,
        surface::{SurfaceError, SurfaceInfo},
        OutOfMemory,
    },
    erupt::{extensions::khr_surface::SurfaceKHR, vk1_0},
    std::{
        fmt::Debug,
        sync::atomic::{AtomicBool, Ordering},
    },
};

#[derive(Debug)]
pub(crate) struct Inner {
    pub handle: SurfaceKHR,
    pub used: AtomicBool,
    pub info: SurfaceInfo,
}

#[derive(Clone, Debug)]
#[repr(transparent)]
pub struct Surface {
    inner: std::sync::Arc<Inner>,
}

impl std::cmp::PartialEq for Surface {
    fn eq(&self, other: &Self) -> bool {
        std::ptr::eq(&*self.inner, &*other.inner)
    }
}

impl std::cmp::Eq for Surface {}

impl std::hash::Hash for Surface {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        std::ptr::hash(&*self.inner, state)
    }
}

impl Surface {
    pub(crate) fn make(handle: SurfaceKHR, used: AtomicBool, info: SurfaceInfo) -> Self {
        Surface {
            inner: std::sync::Arc::new(Inner { handle, used, info }),
        }
    }

    pub(crate) fn handle(&self) -> SurfaceKHR {
        self.inner.handle
    }

    pub(crate) fn mark_used(&self) -> Result<(), SurfaceError> {
        if self.inner.used.fetch_or(true, Ordering::SeqCst) {
            return Err(SurfaceError::AlreadyUsed);
        } else {
            Ok(())
        }
    }

    pub fn info(&self) -> &SurfaceInfo {
        &self.inner.info
    }
}

#[track_caller]
pub(crate) fn surface_error_from_erupt(err: vk1_0::Result) -> SurfaceError {
    match err {
        vk1_0::Result::ERROR_OUT_OF_HOST_MEMORY => out_of_host_memory(),
        vk1_0::Result::ERROR_OUT_OF_DEVICE_MEMORY => SurfaceError::OutOfMemory {
            source: OutOfMemory,
        },
        vk1_0::Result::ERROR_SURFACE_LOST_KHR => SurfaceError::SurfaceLost,
        vk1_0::Result::ERROR_NATIVE_WINDOW_IN_USE_KHR => SurfaceError::WindowIsInUse,
        vk1_0::Result::ERROR_INITIALIZATION_FAILED => SurfaceError::InitializationFailed,
        _ => unexpected_result(err),
    }
}