1use crate::{egl, Environment, Error, Pixmap};
2
3pub type Finalizer<'a> = Box<dyn Fn(&Image) + 'a>;
5
6#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd)]
8pub enum NativeHandle {
9 EglImage(egl::EGLImage),
10 EglImageKHR(egl::EGLImageKHR),
11}
12
13impl Default for NativeHandle {
14 fn default() -> Self {
15 NativeHandle::EglImage(std::ptr::null())
16 }
17}
18
19impl From<NativeHandle> for usize {
20 fn from(val: NativeHandle) -> Self {
21 match val {
22 NativeHandle::EglImage(v) => v as usize,
23 NativeHandle::EglImageKHR(v) => v as usize,
24 }
25 }
26}
27
28impl From<NativeHandle> for *const std::ffi::c_void {
29 fn from(val: NativeHandle) -> *const std::ffi::c_void {
30 match val {
31 NativeHandle::EglImage(v) => v as *const std::ffi::c_void,
32 NativeHandle::EglImageKHR(v) => v as *const std::ffi::c_void,
33 }
34 }
35}
36
37#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd)]
39pub enum Target {
40 GlTexture2D = egl::GL_TEXTURE_2D as isize,
42 GlTextureCubeMapPositiveX = egl::GL_TEXTURE_CUBE_MAP_POSITIVE_X as isize,
44 GlTextureCubeMapNegativeX = egl::GL_TEXTURE_CUBE_MAP_NEGATIVE_X as isize,
46 GlTextureCubeMapPositiveY = egl::GL_TEXTURE_CUBE_MAP_POSITIVE_Y as isize,
48 GlTextureCubeMapNegativeY = egl::GL_TEXTURE_CUBE_MAP_NEGATIVE_Y as isize,
50 GlTextureCubeMapPositiveZ = egl::GL_TEXTURE_CUBE_MAP_POSITIVE_Z as isize,
52 GlTextureCubeMapNegativeZ = egl::GL_TEXTURE_CUBE_MAP_NEGATIVE_Z as isize,
54 GlTexture3D = egl::GL_TEXTURE_3D as isize,
56 GlRenderBuffer = egl::GL_RENDERBUFFER as isize,
58 NativePixmapKHR = egl::NATIVE_PIXMAP_KHR as isize,
60}
61
62impl Default for Target {
63 fn default() -> Self {
64 Target::GlTexture2D
65 }
66}
67
68impl From<Target> for egl::EGLenum {
69 fn from(val: Target) -> egl::EGLenum {
70 match val {
71 Target::GlTexture2D => egl::GL_TEXTURE_2D,
72 Target::GlTextureCubeMapPositiveX => egl::GL_TEXTURE_CUBE_MAP_POSITIVE_X,
73 Target::GlTextureCubeMapNegativeX => egl::GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
74 Target::GlTextureCubeMapPositiveY => egl::GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
75 Target::GlTextureCubeMapNegativeY => egl::GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
76 Target::GlTextureCubeMapPositiveZ => egl::GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
77 Target::GlTextureCubeMapNegativeZ => egl::GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
78 Target::GlTexture3D => egl::GL_TEXTURE_3D,
79 Target::GlRenderBuffer => egl::GL_RENDERBUFFER,
80 Target::NativePixmapKHR => egl::NATIVE_PIXMAP_KHR,
81 }
82 }
83}
84
85#[derive(Debug)]
87pub enum ImageBuffer<'a> {
88 EglClientBuffer(egl::EGLClientBuffer),
89 Pixmap(Pixmap<'a>),
90}
91
92impl<'a> Default for ImageBuffer<'a> {
93 fn default() -> Self {
94 ImageBuffer::EglClientBuffer(std::ptr::null())
95 }
96}
97
98#[allow(dead_code)]
100pub struct Image<'a> {
101 display: egl::EGLDisplay,
102 context: egl::EGLContext,
103 target: Target,
104 buffer: ImageBuffer<'a>,
105 finalizer: Option<Finalizer<'a>>,
106 native: NativeHandle,
107}
108
109impl<'a> Image<'a> {
113 pub fn new(
114 env: &'_ Environment,
115 target: Target,
116 buffer: ImageBuffer<'a>,
117 finalizer: Option<Finalizer<'a>>,
118 ) -> Self {
119 let mut _native: NativeHandle = Default::default();
120 match buffer {
121 ImageBuffer::EglClientBuffer(client_buffer) => {
122 let a = crate::create_image(
123 env.get_display(),
124 env.get_context(),
125 target.into(),
126 client_buffer,
127 None,
128 )
129 .unwrap();
130 _native = NativeHandle::EglImage(a);
131 }
132 ImageBuffer::Pixmap(ref pixmap) => {
133 let a = crate::create_image(
134 env.get_display(),
135 env.get_context(),
136 target.into(),
137 pixmap.id() as egl::EGLClientBuffer,
138 None,
139 )
140 .unwrap();
141 _native = NativeHandle::EglImageKHR(a);
142 }
143 }
144 Self {
145 display: env.get_display(),
146 context: env.get_context(),
147 target,
148 buffer,
149 finalizer,
150 native: _native,
151 }
152 }
153
154 pub fn new_khr(
155 env: &'_ Environment,
156 target: Target,
157 buffer: ImageBuffer<'a>,
158 finalizer: Option<Finalizer<'a>>,
159 ) -> Self {
160 let mut ctx = env.get_context();
161 let mut _native: NativeHandle = Default::default();
162 if let Target::NativePixmapKHR = target {
163 ctx = egl::NO_CONTEXT;
164 }
165 match buffer {
166 ImageBuffer::EglClientBuffer(client_buffer) => {
167 let a = crate::create_image_khr(
168 env.get_display(),
169 ctx,
170 target as egl::EGLenum,
171 client_buffer,
172 None,
173 )
174 .unwrap();
175 _native = NativeHandle::EglImageKHR(a);
176 }
177 ImageBuffer::Pixmap(ref pixmap) => {
178 let a = crate::create_image_khr(
179 env.get_display(),
180 ctx,
181 target as egl::EGLenum,
182 pixmap.id() as egl::EGLClientBuffer,
183 None,
184 )
185 .unwrap();
186 _native = NativeHandle::EglImageKHR(a);
187 }
188 }
189 Self {
190 display: env.get_display(),
191 context: env.get_context(),
192 target,
193 buffer,
194 finalizer,
195 native: _native,
196 }
197 }
198
199 pub fn id(&self) -> usize {
200 self.native.into()
201 }
202
203 pub fn native(&self) -> NativeHandle {
204 self.native
205 }
206}
207
208impl<'a> Default for Image<'a> {
209 fn default() -> Self {
210 Self {
211 display: egl::NO_DISPLAY,
212 context: egl::NO_CONTEXT,
213 target: Default::default(),
214 buffer: Default::default(),
215 finalizer: None,
216 native: Default::default(),
217 }
218 }
219}
220
221impl<'a> Drop for Image<'a> {
222 fn drop(&mut self) {
223 if let Some(ref f) = self.finalizer {
224 (f)(self);
225 }
226 match self.native {
227 NativeHandle::EglImage(v) => {
228 crate::destroy_image(self.display, v).unwrap();
229 self.native = Default::default();
230 }
231 NativeHandle::EglImageKHR(v) => {
232 crate::destroy_image_khr(self.display, v).unwrap();
233 self.native = Default::default();
234 }
235 }
236 }
237}
238
239impl<'a> std::fmt::Debug for Image<'a> {
240 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
241 match self.finalizer {
242 Some(ref finalizer) => write!(
243 f,
244 "Image {{ native: {:?}, buffer: {:?}, finalizer: {:p} }}",
245 self.native, self.buffer, finalizer
246 ),
247 None => write!(
248 f,
249 "Image {{ native: {:?}, buffer: {:?}, finalizer: None }}",
250 self.native, self.buffer
251 ),
252 }
253 }
254}
255
256#[derive(Default)]
258pub struct ImageBuilder<'a> {
259 display: Option<egl::EGLDisplay>,
260 context: Option<egl::EGLContext>,
261 target: Option<Target>,
262 buffer: Option<ImageBuffer<'a>>,
263 is_khr: bool,
264 finalizer: Option<Finalizer<'a>>,
265}
266
267impl<'a> ImageBuilder<'a> {
268 pub fn new() -> Self {
269 Self {
270 display: None,
271 context: None,
272 target: Some(Default::default()),
273 buffer: Some(Default::default()),
274 is_khr: false,
275 finalizer: None,
276 }
277 }
278
279 pub fn with_display(mut self, display: egl::EGLDisplay) -> Self {
280 self.display = Some(display);
281 self
282 }
283
284 pub fn with_context(mut self, context: egl::EGLContext) -> Self {
285 self.context = Some(context);
286 self
287 }
288
289 pub fn with_target(mut self, target: Target) -> Self {
290 self.target = Some(target);
291 self
292 }
293
294 pub fn with_buffer(mut self, buffer: ImageBuffer<'a>) -> Self {
295 match buffer {
297 ImageBuffer::Pixmap(_) => {
298 self.target = Some(Target::NativePixmapKHR);
299 }
300 ImageBuffer::EglClientBuffer(_) => {}
301 }
302 self.buffer = Some(buffer);
303 self
304 }
305
306 pub fn with_khr(mut self) -> Self {
307 self.is_khr = true;
308 self
309 }
310
311 pub fn with_finalizer<F>(mut self, finalizer: F) -> Self
312 where
313 F: Fn(&Image) + 'a,
314 {
315 self.finalizer = Some(Box::new(finalizer));
316 self
317 }
318
319 pub fn build(self, env: &'_ Environment) -> Result<Image<'a>, Error> {
320 if self.is_khr {
321 Ok(Image::new_khr(
322 env,
323 self.target.unwrap_or_default(),
324 self.buffer.unwrap_or_default(),
325 self.finalizer,
326 ))
327 } else {
328 Ok(Image::new(
329 env,
330 self.target.unwrap_or_default(),
331 self.buffer.unwrap_or_default(),
332 self.finalizer,
333 ))
334 }
335 }
336}