1use 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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum MemoryObjectCreationError {
21 MemoryObjectNotSupported,
23 MemoryObjectFdNotSupported,
25 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
44pub struct MemoryObject {
50 context: Rc<Context>,
51 id: gl::types::GLuint,
52}
53
54impl MemoryObject {
55 #[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}