glium/
memory_object.rs

1/*!
2Contains everything related to external API memory objects.
3*/
4
5// TODO: Add Windows support via EXT_external_objects_win32
6
7use crate::GlObject;
8use crate::context::CommandContext;
9use crate::gl;
10use crate::version::Api;
11use crate::version::Version;
12
13use crate::backend::Facade;
14use crate::context::Context;
15use crate::ContextExt;
16use std::rc::Rc;
17
18/// Describes an error encountered during memory object creation
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum MemoryObjectCreationError {
21    /// Driver does not support EXT_memory_object
22    MemoryObjectNotSupported,
23    /// Driver does not support EXT_memory_object_fd
24    MemoryObjectFdNotSupported,
25    /// OpenGL returned a null pointer when creating memory object
26    NullResult,
27}
28
29impl std::fmt::Display for MemoryObjectCreationError {
30    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31        use self::MemoryObjectCreationError::*;
32
33        let desc = match *self {
34            MemoryObjectNotSupported => "Driver does not support EXT_memory_object",
35            MemoryObjectFdNotSupported => "Driver does not support EXT_memory_object_fd",
36            NullResult => "OpenGL returned a null pointer when creating memory object",
37        };
38        f.write_str(desc)
39    }
40}
41
42impl std::error::Error for MemoryObjectCreationError {}
43
44/// Describes a memory object created by an external API. In OpenGL there is no distinction
45/// between a texture or buffer and its underlying memory. However, in other API's like Vulkan
46/// the underlying memory and the image are separate. Thus this type is useful when interfacing
47/// with such APIs, as such a memory object can then be used to create a texture or buffer
48/// which OpenGL can then interact with.
49pub struct MemoryObject {
50    context: Rc<Context>,
51    id: gl::types::GLuint,
52}
53
54impl MemoryObject {
55    /// Creates a memory object form an opaque file descriptor.
56    #[cfg(target_os = "linux")]
57    pub unsafe fn new_from_fd<F: Facade + ?Sized>(
58        facade: &F,
59        dedicated: bool,
60        fd: std::fs::File,
61        size: u64,
62    ) -> Result<Self, MemoryObjectCreationError> {
63        use std::os::unix::io::AsRawFd;
64        let ctxt = facade.get_context().make_current();
65        let mem_obj: Self = Self::new(facade, &ctxt)?;
66
67        if !ctxt.extensions.gl_ext_memory_object_fd {
68            Err(MemoryObjectCreationError::MemoryObjectFdNotSupported)
69        } else {
70            let dedicated: gl::types::GLint = if dedicated {
71                gl::TRUE as i32
72            } else {
73                gl::FALSE as i32
74            };
75
76            ctxt.gl.MemoryObjectParameterivEXT(
77                mem_obj.id,
78                gl::DEDICATED_MEMORY_OBJECT_EXT,
79                &dedicated as *const i32,
80            );
81
82            ctxt.gl.ImportMemoryFdEXT(
83                mem_obj.id,
84                size,
85                gl::HANDLE_TYPE_OPAQUE_FD_EXT,
86                fd.as_raw_fd(),
87            );
88
89            std::mem::forget(fd);
90
91            Ok(mem_obj)
92        }
93    }
94
95    fn new<F: Facade + ?Sized>(
96        facade: &F,
97        ctxt: &CommandContext<'_>,
98    ) -> Result<Self, MemoryObjectCreationError> {
99        if (ctxt.version >= &Version(Api::Gl, 4, 5)
100            || ctxt.version >= &Version(Api::GlEs, 3, 2)
101            || ctxt.extensions.gl_arb_texture_storage)
102            && ctxt.extensions.gl_ext_memory_object
103        {
104            let id = unsafe {
105                let mut id: gl::types::GLuint = 0;
106                ctxt.gl.CreateMemoryObjectsEXT(1, &mut id as *mut u32);
107
108                if ctxt.gl.IsMemoryObjectEXT(id) == gl::FALSE {
109                    return Err(MemoryObjectCreationError::NullResult);
110                } else {
111                    id
112                }
113            };
114
115            Ok(Self {
116                context: facade.get_context().clone(),
117                id,
118            })
119        } else {
120            Err(MemoryObjectCreationError::MemoryObjectNotSupported)
121        }
122    }
123}
124
125impl GlObject for MemoryObject {
126    type Id = gl::types::GLuint;
127
128    #[inline]
129    fn get_id(&self) -> gl::types::GLuint {
130        self.id
131    }
132}
133
134impl Drop for MemoryObject {
135    fn drop(&mut self) {
136        let ctxt = self.context.get_context().make_current();
137        unsafe { ctxt.gl.DeleteMemoryObjectsEXT(1, &mut self.id as *mut u32) };
138    }
139}