egls/
image.rs

1use crate::{egl, Environment, Error, Pixmap};
2
3/// Callback for Image cleanup native resources.
4pub type Finalizer<'a> = Box<dyn Fn(&Image) + 'a>;
5
6/// Native Handle of the EGLImage.
7#[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/// Type of resource used as the image source.
38#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd)]
39pub enum Target {
40    /// Used for GL 2D texture images
41    GlTexture2D = egl::GL_TEXTURE_2D as isize,
42    /// Used for the +X face of GL cubemap texture images
43    GlTextureCubeMapPositiveX = egl::GL_TEXTURE_CUBE_MAP_POSITIVE_X as isize,
44    /// Used for the -X face of GL cubemap texture images
45    GlTextureCubeMapNegativeX = egl::GL_TEXTURE_CUBE_MAP_NEGATIVE_X as isize,
46    /// Used for the +Y face of GL cubemap texture images
47    GlTextureCubeMapPositiveY = egl::GL_TEXTURE_CUBE_MAP_POSITIVE_Y as isize,
48    /// Used for the -Y face of GL cubemap texture images
49    GlTextureCubeMapNegativeY = egl::GL_TEXTURE_CUBE_MAP_NEGATIVE_Y as isize,
50    /// Used for the +Z face of GL cubemap texture images
51    GlTextureCubeMapPositiveZ = egl::GL_TEXTURE_CUBE_MAP_POSITIVE_Z as isize,
52    /// Used for the -Z face of GL cubemap texture images
53    GlTextureCubeMapNegativeZ = egl::GL_TEXTURE_CUBE_MAP_NEGATIVE_Z as isize,
54    /// Used for OpenGL and OpenGL ES 3D texture images
55    GlTexture3D = egl::GL_TEXTURE_3D as isize,
56    /// Used for OpenGL and OpenGL ES renderbuffer images
57    GlRenderBuffer = egl::GL_RENDERBUFFER as isize,
58    /// Used for EGLNativePixmapType objects
59    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/// The Buffer of the Image.
86#[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/// Image with native resources.
99#[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
109// unsafe impl<'a> Send for Image<'a> {}
110// unsafe impl<'a> Sync for Image<'a> {}
111
112impl<'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/// Build an Image with Chain style.
257#[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        // Fix the Target if Use Pixmap Buffer
296        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}