egls/
apis.rs

1use crate::{
2    egl, EGLAttrib, EGLClientBuffer, EGLConfig, EGLContext, EGLDisplay, EGLImage, EGLImageKHR,
3    EGLNativeDisplayType, EGLNativePixmapType, EGLNativeWindowType, EGLSurface, EGLenum, EGLint,
4    Error,
5};
6use std::ffi::{CStr, CString};
7
8/// Set the current rendering API.
9///
10/// # Parameters
11///
12/// * `api` - Specifies the client API to bind,
13///           one of OPENGL_API, OPENGL_ES_API, or OPENVG_API.
14pub fn bind_api(api: EGLenum) -> Result<bool, Error> {
15    match unsafe { egl::BindAPI(api) } {
16        1 => Ok(true),
17        _ => Err(Error::new()),
18    }
19}
20
21/// Defines a two-dimensional texture image.
22///
23/// # Parameters
24///
25/// * `display` - Specifies the EGL display connection.
26/// * `surface` - Specifies the EGL surface.
27/// * `buffer` - Specifies the texture image data.
28pub fn bind_tex_image(dpy: EGLDisplay, surface: EGLSurface, buffer: EGLint) -> Result<bool, Error> {
29    match unsafe { egl::BindTexImage(dpy, surface, buffer) } {
30        1 => Ok(true),
31        _ => Err(Error::new()),
32    }
33}
34
35/// Return a list of EGL frame buffer configurations that match specified attributes.
36///
37/// # Parameters
38///
39/// * `display` - Specifies the EGL display connection.
40/// * `attrib_list` - Specifies attributes required to match by configs.
41///
42/// # Returns
43///
44/// * An array of frame buffer configurations.
45pub fn choose_config(display: EGLDisplay, attrib_list: &[EGLint]) -> Result<Vec<EGLConfig>, Error> {
46    unsafe {
47        let mut num_config: EGLint = 0;
48        if egl::TRUE
49            != egl::ChooseConfig(
50                display,
51                attrib_list.as_ptr(),
52                std::ptr::null_mut(),
53                0,
54                &mut num_config,
55            )
56        {
57            return Err(Error::new());
58        }
59        let mut configs: Vec<EGLConfig> = vec![std::ptr::null_mut(); num_config as usize];
60        if egl::TRUE
61            != egl::ChooseConfig(
62                display,
63                attrib_list.as_ptr(),
64                configs.as_mut_ptr(),
65                configs.len() as EGLint,
66                &mut num_config,
67            )
68        {
69            return Err(Error::new());
70        }
71        Ok(configs)
72    }
73}
74
75/// Create a new EGL rendering context.
76///
77/// # Parameters
78///
79/// * `display` - Specifies the EGL display connection.
80/// * `config` - Specifies the EGL frame buffer configuration that defines the frame buffer resource available to the rendering context.
81/// * `share_context` - Specifies another EGL rendering context with which to share data, as defined by the client API corresponding to the contexts.
82///    Data is also shared with all other contexts with which share_context shares data.
83///    EGL_NO_CONTEXT indicates that no sharing is to take place.
84/// * `attrib_list` - Specifies attributes and attribute values for the context being created.
85///    Only the attribute EGL_CONTEXT_CLIENT_VERSION may be specified.
86pub fn create_context(
87    display: EGLDisplay,
88    config: EGLConfig,
89    share_context: EGLContext,
90    attrib_list: Option<&[EGLint]>,
91) -> Result<EGLContext, Error> {
92    let aptr = attrib_list.map_or(std::ptr::null(), |v| v.as_ptr());
93    let ctx = unsafe { egl::CreateContext(display, config, share_context, aptr) };
94    if ctx == egl::NO_CONTEXT {
95        Err(Error::new())
96    } else {
97        Ok(ctx)
98    }
99}
100
101/// Create a new EGLImage object.
102///
103/// # Parameters
104///
105/// * `display` - Specifies the EGL display connection.
106/// * `context` - Specifies the client API context for which the image is created.
107/// * `target` - Specifies the type of resource used as the image source.
108/// * `buffer` - Specifies the resource to be used as the image source.
109/// * `attrib_list` - Specifies attributes used to select sub-sections of the resource to be used as the image source.
110pub fn create_image(
111    display: EGLDisplay,
112    context: EGLContext,
113    target: EGLenum,
114    buffer: EGLClientBuffer,
115    attrib_list: Option<&[EGLAttrib]>,
116) -> Result<EGLImage, Error> {
117    let aptr = attrib_list.map_or(std::ptr::null(), |v| v.as_ptr());
118    let img = unsafe { egl::CreateImage(display, context, target, buffer, aptr) };
119    if img == egl::NO_IMAGE {
120        Err(Error::new())
121    } else {
122        Ok(img)
123    }
124}
125
126/// Create a new EGLImage object (KHR Ext).
127///
128/// # Parameters
129///
130/// * `display` - Specifies the EGL display connection.
131/// * `context` - Specifies the client API context for which the image is created.
132/// * `target` - Specifies the type of resource used as the image source.
133/// * `buffer` - Specifies the resource to be used as the image source.
134/// * `attrib_list` - Specifies attributes used to select sub-sections of the resource to be used as the image source.
135pub fn create_image_khr(
136    display: EGLDisplay,
137    context: EGLContext,
138    target: EGLenum,
139    buffer: EGLClientBuffer,
140    attrib_list: Option<&[EGLint]>,
141) -> Result<EGLImage, Error> {
142    let aptr = attrib_list.map_or(std::ptr::null(), |v| v.as_ptr());
143    let val = unsafe { egl::CreateImageKHR(display, context, target, buffer, aptr) };
144    if val == egl::NO_IMAGE {
145        Err(Error::new())
146    } else {
147        Ok(val)
148    }
149}
150
151/// Create a new EGL pixel buffer surface.
152///
153/// # Parameters
154///
155/// * `display` - Specifies the EGL display connection.
156/// * `config` - Specifies the EGL frame buffer configuration that defines the frame buffer resource available to the surface.
157/// * `attrib_list` - Specifies pixel buffer surface attributes. May be NULL or empty (first attribute is EGL_NONE).
158pub fn create_pbuffer_surface(
159    display: EGLDisplay,
160    config: EGLConfig,
161    attrib_list: Option<&[EGLint]>,
162) -> Result<EGLSurface, Error> {
163    let aptr = attrib_list.map_or(std::ptr::null(), |v| v.as_ptr());
164    let val = unsafe { egl::CreatePbufferSurface(display, config, aptr) };
165    if val == egl::NO_SURFACE {
166        Err(Error::new())
167    } else {
168        Ok(val)
169    }
170}
171
172/// Create a new EGL offscreen surface.
173///
174/// # Parameters
175///
176/// * `display` - Specifies the EGL display connection.
177/// * `config` - Specifies the EGL frame buffer configuration that defines the frame buffer resource available to the surface.
178/// * `native_pixmap` - Specifies the native pixmap.
179/// * `attrib_list` - Specifies pixmap surface attributes. May be NULL or empty (first attribute is EGL_NONE).
180pub fn create_pixmap_surface(
181    display: EGLDisplay,
182    config: EGLConfig,
183    pixmap: EGLNativePixmapType,
184    attrib_list: Option<&[EGLint]>,
185) -> Result<EGLSurface, Error> {
186    let aptr = attrib_list.map_or(std::ptr::null(), |v| v.as_ptr());
187    let val = unsafe { egl::CreatePixmapSurface(display, config, pixmap, aptr) };
188    if val == egl::NO_SURFACE {
189        Err(Error::new())
190    } else {
191        Ok(val)
192    }
193}
194
195/// Create a new EGL window surface.
196///
197/// # Parameters
198///
199/// * `display` - Specifies the EGL display connection.
200/// * `config` - Specifies the EGL frame buffer configuration that defines the frame buffer resource available to the surface.
201/// * `native_window` - Specifies the native window.
202/// * `attrib_list` - Specifies window surface attributes. May be NULL or empty (first attribute is EGL_NONE).
203pub fn create_window_surface(
204    display: EGLDisplay,
205    config: EGLConfig,
206    win: EGLNativeWindowType,
207    attrib_list: Option<&[EGLint]>,
208) -> Result<EGLSurface, Error> {
209    let aptr = attrib_list.map_or(std::ptr::null(), |v| v.as_ptr());
210    let val = unsafe { egl::CreateWindowSurface(display, config, win, aptr) };
211    if val == egl::NO_SURFACE {
212        Err(Error::new())
213    } else {
214        Ok(val)
215    }
216}
217
218/// Destroy an EGL rendering context.
219///
220/// # Parameters
221///
222/// * `display` - Specifies the EGL display connection.
223/// * `context` - Specifies the EGL rendering context to be destroyed.
224pub fn destroy_context(display: EGLDisplay, ctx: EGLContext) -> Result<bool, Error> {
225    match unsafe { egl::DestroyContext(display, ctx) } {
226        1 => Ok(true),
227        _ => Err(Error::new()),
228    }
229}
230
231/// Destroy an EGLImage object.
232///
233/// # Parameters
234///
235/// * `display` - Specifies the EGL display connection.
236/// * `image` - Specifies the image to destroy.
237pub fn destroy_image(display: EGLDisplay, image: EGLImage) -> Result<bool, Error> {
238    match unsafe { egl::DestroyImage(display, image) } {
239        1 => Ok(true),
240        _ => Err(Error::new()),
241    }
242}
243
244/// Destroy an EGLImage object (KHR Ext).
245///
246/// # Parameters
247///
248/// * `display` - Specifies the EGL display connection.
249/// * `image` - Specifies the image to destroy.
250pub fn destroy_image_khr(display: EGLDisplay, image: EGLImageKHR) -> Result<bool, Error> {
251    match unsafe { egl::DestroyImageKHR(display, image) } {
252        1 => Ok(true),
253        _ => Err(Error::new()),
254    }
255}
256
257/// Destroy an EGL surface.
258///
259/// # Parameters
260///
261/// * `display` - Specifies the EGL display connection.
262/// * `surface` - Specifies the EGL surface to be destroyed.
263pub fn destroy_surface(display: EGLDisplay, surface: EGLSurface) -> Result<bool, Error> {
264    match unsafe { egl::DestroySurface(display, surface) } {
265        1 => Ok(true),
266        _ => Err(Error::new()),
267    }
268}
269
270/// Return an EGL display connection.
271///
272/// # Parameters
273///
274/// * `native_display` - Specifies the display to connect to.
275///                      EGL_DEFAULT_DISPLAY indicates the default display.
276pub fn get_display(native_display: EGLNativeDisplayType) -> Result<EGLDisplay, Error> {
277    let ptr = unsafe { egl::GetDisplay(native_display) };
278    if ptr.is_null() {
279        Err(Error::new())
280    } else {
281        Ok(ptr)
282    }
283}
284
285/// Return the default EGL display connection.
286#[inline]
287pub fn get_default_display() -> Result<EGLDisplay, Error> {
288    get_display(egl::DEFAULT_DISPLAY)
289}
290
291/// Return a GL or an EGL extension function.
292///
293/// # Parameters
294///
295/// * `procname` - Specifies the name of the function to return.
296pub fn get_proc_address<T: AsRef<str>>(procname: T) -> *mut std::os::raw::c_void {
297    let procname = CString::new(procname.as_ref()).unwrap();
298    unsafe { egl::GetProcAddress(procname.as_ptr()) as *mut std::os::raw::c_void }
299}
300
301/// Initialize an EGL display connection.
302///
303/// # Parameters
304///
305/// * `display` - Specifies the EGL display connection to initialize.
306/// * `major` - Returns the major version number of the EGL implementation. May be NULL.
307/// * `minor` - Returns the minor version number of the EGL implementation. May be NULL.
308pub fn initialize(dpy: EGLDisplay, major: &mut EGLint, minor: &mut EGLint) -> Result<bool, Error> {
309    match unsafe { egl::Initialize(dpy, major, minor) } {
310        1 => Ok(true),
311        _ => Err(Error::new()),
312    }
313}
314
315///  Initialize an EGL display connection with default version.
316///
317/// # Parameters
318///
319/// * `display` - Specifies the EGL display connection to initialize.
320pub fn initialize_default(dpy: EGLDisplay) -> Result<bool, Error> {
321    match unsafe { egl::Initialize(dpy, std::ptr::null_mut(), std::ptr::null_mut()) } {
322        1 => Ok(true),
323        _ => Err(Error::new()),
324    }
325}
326
327/// Attach an EGL rendering context to EGL surfaces.
328///
329/// # Parameters
330///
331/// * `display` - Specifies the EGL display connection.
332/// * `draw` - Specifies the EGL draw surface.
333/// * `read` - Specifies the EGL read surface.
334/// * `context` - Specifies the EGL rendering context to be attached to the surfaces.
335pub fn make_current(
336    display: EGLDisplay,
337    draw: EGLSurface,
338    read: EGLSurface,
339    ctx: EGLContext,
340) -> Result<bool, Error> {
341    match unsafe { egl::MakeCurrent(display, draw, read, ctx) } {
342        1 => Ok(true),
343        _ => Err(Error::new()),
344    }
345}
346
347/// Query the current rendering API.
348///
349/// eglQueryAPI returns the value of the current rendering API for EGL in the thread it is called from.
350/// The current rendering API is set by eglBindAPI, and affects the behavior of other EGL commands.
351/// The value returned will be one of the valid api parameters to eglBindAPI, or EGL_NONE.
352pub fn query_api() -> EGLenum {
353    unsafe { egl::QueryAPI() }
354}
355
356/// Return EGL rendering context information.
357///
358/// # Parameters
359///
360/// * `display` - Specifies the EGL display connection.
361/// * `context` - Specifies the EGL rendering context to query.
362/// * `attribute` - Specifies the EGL rendering context attribute to be returned.
363pub fn query_context(dpy: EGLDisplay, ctx: EGLContext, attr: EGLint) -> Result<EGLint, Error> {
364    let mut value: EGLint = 0;
365    match unsafe { egl::QueryContext(dpy, ctx, attr, &mut value) } {
366        1 => Ok(value),
367        _ => Err(Error::new()),
368    }
369}
370
371/// Return a string describing properties of the EGL client or of an EGL display connection.
372///
373/// # Parameters
374///
375/// * `display` - Specifies the EGL display connection.
376/// * `name` - Specifies a symbolic constant, one of EGL_CLIENT_APIS, EGL_VENDOR, EGL_VERSION, or EGL_EXTENSIONS.
377pub fn query_string(dpy: EGLDisplay, name: EGLint) -> Result<String, Error> {
378    unsafe {
379        let ptr = egl::QueryString(dpy, name);
380        if ptr.is_null() {
381            Err(Error::new())
382        } else {
383            Ok(CStr::from_ptr(ptr).to_string_lossy().into_owned())
384        }
385    }
386}
387
388/// Releases a color buffer that is being used as a texture.
389///
390/// # Parameters
391///
392/// * `display` - Specifies the EGL display connection.
393/// * `surface` - Specifies the EGL surface.
394/// * `buffer` - Specifies the texture image data.
395pub fn release_tex_image(
396    display: EGLDisplay,
397    surface: EGLSurface,
398    buffer: EGLint,
399) -> Result<bool, Error> {
400    match unsafe { egl::ReleaseTexImage(display, surface, buffer) } {
401        1 => Ok(true),
402        _ => Err(Error::new()),
403    }
404}
405
406/// Post EGL surface color buffer to a native window.
407///
408/// # Parameters
409///
410/// * `display` - Specifies the EGL display connection.
411/// * `surface` - Specifies the EGL drawing surface whose buffers are to be swapped.
412pub fn swap_buffers(display: EGLDisplay, surface: EGLSurface) -> Result<bool, Error> {
413    match unsafe { egl::SwapBuffers(display, surface) } {
414        1 => Ok(true),
415        _ => Err(Error::new()),
416    }
417}
418
419/// Specifies the minimum number of video frame periods per buffer swap for the window associated with the current context.
420///
421/// # Parameters
422///
423/// * `display` - Specifies the EGL display connection.
424/// * `interval` - Specifies the minimum number of video frames that are displayed before a buffer swap will occur.
425pub fn swap_interval(display: EGLDisplay, interval: EGLint) -> Result<bool, Error> {
426    match unsafe { egl::SwapInterval(display, interval) } {
427        1 => Ok(true),
428        _ => Err(Error::new()),
429    }
430}
431
432/// Terminate an EGL display connection.
433///
434/// # Parameters
435///
436/// * `display` - Specifies the EGL display connection to terminate.
437pub fn terminate(display: EGLDisplay) -> Result<bool, Error> {
438    match unsafe { egl::Terminate(display) } {
439        1 => Ok(true),
440        _ => Err(Error::new()),
441    }
442}
443
444#[cfg(test)]
445mod tests {
446    use crate::{egl, so};
447
448    fn egl_init() -> (so::SharedObject, egl::EGLDisplay) {
449        #[cfg(feature = "hi3559av100")]
450        {
451            println!("NOTE: You must start HiFB before run tests!!!");
452        }
453        let so = so::SharedObject::load("libEGL.so");
454        egl::load_with(|s| so.get_proc_address(s));
455        egl::load_with_priv(|s| so.get_proc_address(s));
456        let dpy = crate::get_default_display().unwrap();
457        let mut major: egl::EGLint = 3;
458        let mut minor: egl::EGLint = 2;
459        assert!(crate::initialize(dpy, &mut major, &mut minor).unwrap());
460        (so, dpy)
461    }
462
463    #[cfg(feature = "hi3559av100")]
464    #[test]
465    fn test_bind_api() {
466        let (_so, _dpy) = egl_init();
467        assert!(crate::bind_api(egl::OPENGL_ES_API).unwrap());
468    }
469
470    #[cfg(feature = "hi3559av100")]
471    #[test]
472    fn test_query_string() {
473        let (_so, dpy) = egl_init();
474        let apis = crate::query_string(dpy, egl::CLIENT_APIS as egl::EGLint).unwrap();
475        assert_eq!(apis, "OpenGL_ES");
476    }
477}