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}