makepad_platform/os/linux/
egl_sys.rs

1#![allow(non_camel_case_types, non_snake_case, dead_code)]
2
3pub type EGLNativeDisplayType = *mut ();
4pub type EGLNativePixmapType = ::std::os::raw::c_ulong;
5pub type EGLNativeWindowType = ::std::os::raw::c_ulong;
6
7pub use core::ptr::null_mut;
8
9pub const EGL_NO_CONTEXT: EGLContext = 0 as EGLContext;
10pub const EGL_NO_SURFACE: EGLSurface = 0 as EGLSurface;
11
12pub const EGL_WINDOW_BIT: u32 = 4;
13
14pub const EGL_OPENGL_ES2_BIT: u32 = 4;
15
16pub const EGL_SUCCESS: u32 = 12288;
17pub const EGL_ALPHA_SIZE: u32 = 12321;
18pub const EGL_BLUE_SIZE: u32 = 12322;
19pub const EGL_GREEN_SIZE: u32 = 12323;
20pub const EGL_RED_SIZE: u32 = 12324;
21pub const EGL_DEPTH_SIZE: u32 = 12325;
22pub const EGL_STENCIL_SIZE: u32 = 12326;
23pub const EGL_NATIVE_VISUAL_ID: u32 = 12334;
24pub const EGL_SURFACE_TYPE: u32 = 12339;
25pub const EGL_NONE: u32 = 0x3038;
26pub const EGL_RENDERABLE_TYPE: u32 = 12352;
27pub const EGL_HEIGHT: u32 = 12374;
28pub const EGL_WIDTH: u32 = 12375;
29pub const EGL_CONTEXT_MAJOR_VERSION: u32 = 0x3098;
30pub const EGL_CONTEXT_MINOR_VERSION_KHR: u32 = 0x30FB;
31pub const EGL_OPENGL_ES_API: u32 = 12448;
32pub const EGL_CONTEXT_OPENGL_PROFILE_MASK: u32 = 0x30FD;
33pub const EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT: u32 = 0x0002;
34pub const EGL_SAMPLES: u32 = 0x3031;
35pub const EGL_OPENGL_ES3_BIT_KHR: u32 = 0x0040;
36pub const EGL_COLOR_BUFFER_TYPE: u32 = 0x303F;
37pub const EGL_RGB_BUFFER: u32 = 0x308E;
38pub const EGL_PBUFFER_BIT: u32 = 0x0001;
39
40pub const EGL_GL_TEXTURE_2D_KHR: u32 = 12465;
41
42pub const EGL_PLATFORM_X11_EXT: u32 = 12757;
43pub const EGL_PLATFORM_GBM_KHR: u32 = 12759;
44
45pub const EGL_LINUX_DMA_BUF_EXT: u32 = 12912;
46pub const EGL_LINUX_DRM_FOURCC_EXT: u32 = 12913;
47pub const EGL_DMA_BUF_PLANE0_FD_EXT: u32 = 12914;
48pub const EGL_DMA_BUF_PLANE0_OFFSET_EXT: u32 = 12915;
49pub const EGL_DMA_BUF_PLANE0_PITCH_EXT: u32 = 12916;
50pub const EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT: u32 = 13379;
51pub const EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT: u32 = 13380;
52pub const EGL_SWAP_BEHAVIOR: i32 = 0x3093;
53pub const EGL_BUFFER_PRESERVED: i32 = 0x3094;
54pub const EGL_BUFFER_DESTROYED: i32 = 0x3095;
55pub type NativeDisplayType = EGLNativeDisplayType;
56pub type NativePixmapType = EGLNativePixmapType;
57pub type NativeWindowType = EGLNativeWindowType;
58pub type EGLint = i32;
59pub type EGLuint64KHR = u64;
60pub type EGLenum = ::std::os::raw::c_uint;
61pub type EGLBoolean = ::std::os::raw::c_uint;
62pub type EGLDisplay = *mut ::std::os::raw::c_void;
63pub type EGLConfig = *mut ::std::os::raw::c_void;
64pub type EGLSurface = *mut ::std::os::raw::c_void;
65pub type EGLContext = *mut ::std::os::raw::c_void;
66pub type EGLClientBuffer = *mut ::std::os::raw::c_void;
67pub type EGLImageKHR = *mut ::std::os::raw::c_void;
68pub type __eglMustCastToProperFunctionPointerType = ::std::option::Option<unsafe extern "C" fn()>;
69pub type PFNEGLBINDAPIPROC = ::std::option::Option<unsafe extern "C" fn(api: EGLenum) -> EGLBoolean>;
70pub type PFNEGLCHOOSECONFIGPROC = ::std::option::Option<
71unsafe extern "C" fn(
72    dpy: EGLDisplay,
73    attrib_list: *const EGLint,
74    configs: *mut EGLConfig,
75    config_size: EGLint,
76    num_config: *mut EGLint,
77) -> EGLBoolean,
78>;
79pub type PFNEGLCOPYBUFFERSPROC = ::std::option::Option<
80unsafe extern "C" fn(
81    dpy: EGLDisplay,
82    surface: EGLSurface,
83    target: EGLNativePixmapType,
84) -> EGLBoolean,
85>;
86pub type PFNEGLCREATECONTEXTPROC = ::std::option::Option<
87unsafe extern "C" fn(
88    dpy: EGLDisplay,
89    config: EGLConfig,
90    share_context: EGLContext,
91    attrib_list: *const EGLint,
92) -> EGLContext,
93>;
94pub type PFNEGLCREATEIMAGEKHRPROC = ::std::option::Option<
95unsafe extern "C" fn(
96    dpy: EGLDisplay,
97    ctx: EGLContext,
98    target: EGLenum,
99    buffer: EGLClientBuffer,
100    attrib_list: *const EGLint,
101) -> EGLImageKHR,
102>;
103pub type PFNEGLDESTROYIMAGEKHRPROC = ::std::option::Option<
104unsafe extern "C" fn(
105    dpy: EGLDisplay,
106    image: EGLImageKHR,
107) -> EGLBoolean,
108>;
109pub type PFNEGLCREATEPBUFFERSURFACEPROC = ::std::option::Option<
110unsafe extern "C" fn(
111    dpy: EGLDisplay,
112    config: EGLConfig,
113    attrib_list: *const EGLint,
114) -> EGLSurface,
115>;
116pub type PFNEGLCREATEPIXMAPSURFACEPROC = ::std::option::Option<
117unsafe extern "C" fn(
118    dpy: EGLDisplay,
119    config: EGLConfig,
120    pixmap: EGLNativePixmapType,
121    attrib_list: *const EGLint,
122) -> EGLSurface,
123>;
124pub type PFNEGLCREATEWINDOWSURFACEPROC = ::std::option::Option<
125unsafe extern "C" fn(
126    dpy: EGLDisplay,
127    config: EGLConfig,
128    win: EGLNativeWindowType,
129    attrib_list: *const EGLint,
130) -> EGLSurface,
131>;
132pub type PFNEGLDESTROYCONTEXTPROC =
133::std::option::Option<unsafe extern "C" fn(dpy: EGLDisplay, ctx: EGLContext) -> EGLBoolean>;
134pub type PFNEGLDESTROYSURFACEPROC =
135::std::option::Option<unsafe extern "C" fn(dpy: EGLDisplay, surface: EGLSurface) -> EGLBoolean>;
136pub type PFNEGLGETCONFIGATTRIBPROC = ::std::option::Option<
137unsafe extern "C" fn(
138    dpy: EGLDisplay,
139    config: EGLConfig,
140    attribute: EGLint,
141    value: *mut EGLint,
142) -> EGLBoolean,
143>;
144pub type PFNEGLGETCONFIGSPROC = ::std::option::Option<
145unsafe extern "C" fn(
146    dpy: EGLDisplay,
147    configs: *mut EGLConfig,
148    config_size: EGLint,
149    num_config: *mut EGLint,
150) -> EGLBoolean,
151>;
152pub type PFNEGLGETCURRENTDISPLAYPROC = ::std::option::Option<unsafe extern "C" fn() -> EGLDisplay>;
153pub type PFNEGLGETCURRENTSURFACEPROC =
154::std::option::Option<unsafe extern "C" fn(readdraw: EGLint) -> EGLSurface>;
155pub type PFNEGLGETDISPLAYPROC =
156::std::option::Option<unsafe extern "C" fn(display_id: EGLNativeDisplayType) -> EGLDisplay>;
157pub type PFNEGLGETERRORPROC = ::std::option::Option<unsafe extern "C" fn() -> EGLint>;
158pub type PFNEGLGETPROCADDRESSPROC = ::std::option::Option<
159unsafe extern "C" fn(
160    procname: *const ::std::os::raw::c_char,
161) -> *mut ::std::os::raw::c_void,
162>;
163pub type PFNEGLINITIALIZEPROC = ::std::option::Option<
164unsafe extern "C" fn(dpy: EGLDisplay, major: *mut EGLint, minor: *mut EGLint) -> EGLBoolean,
165>;
166pub type PFNEGLMAKECURRENTPROC = ::std::option::Option<
167unsafe extern "C" fn(
168    dpy: EGLDisplay,
169    draw: EGLSurface,
170    read: EGLSurface,
171    ctx: EGLContext,
172) -> EGLBoolean,
173>;
174pub type PFNEGLQUERYCONTEXTPROC = ::std::option::Option<
175unsafe extern "C" fn(
176    dpy: EGLDisplay,
177    ctx: EGLContext,
178    attribute: EGLint,
179    value: *mut EGLint,
180) -> EGLBoolean,
181>;
182pub type PFNEGLQUERYSTRINGPROC = ::std::option::Option<
183unsafe extern "C" fn(dpy: EGLDisplay, name: EGLint) -> *const ::std::os::raw::c_char,
184>;
185pub type PFNEGLQUERYSURFACEPROC = ::std::option::Option<
186unsafe extern "C" fn(
187    dpy: EGLDisplay,
188    surface: EGLSurface,
189    attribute: EGLint,
190    value: *mut EGLint,
191) -> EGLBoolean,
192>;
193pub type PFNEGLSWAPBUFFERSPROC =
194::std::option::Option<unsafe extern "C" fn(dpy: EGLDisplay, surface: EGLSurface) -> EGLBoolean>;
195pub type PFNEGLTERMINATEPROC =
196::std::option::Option<unsafe extern "C" fn(dpy: EGLDisplay) -> EGLBoolean>;
197pub type PFNEGLWAITGLPROC = ::std::option::Option<unsafe extern "C" fn() -> EGLBoolean>;
198pub type PFNEGLWAITNATIVEPROC =
199::std::option::Option<unsafe extern "C" fn(engine: EGLint) -> EGLBoolean>;
200pub type PFNEGLBINDTEXIMAGEPROC = ::std::option::Option<
201unsafe extern "C" fn(dpy: EGLDisplay, surface: EGLSurface, buffer: EGLint) -> EGLBoolean,
202>;
203pub type PFNEGLRELEASETEXIMAGEPROC = ::std::option::Option<
204unsafe extern "C" fn(dpy: EGLDisplay, surface: EGLSurface, buffer: EGLint) -> EGLBoolean,
205>;
206pub type PFNEGLSURFACEATTRIBPROC = ::std::option::Option<
207unsafe extern "C" fn(
208    dpy: EGLDisplay,
209    surface: EGLSurface,
210    attribute: EGLint,
211    value: EGLint,
212) -> EGLBoolean,
213>;
214pub type PFNEGLSWAPINTERVALPROC =
215::std::option::Option<unsafe extern "C" fn(dpy: EGLDisplay, interval: EGLint) -> EGLBoolean>;
216
217pub type PFNEGLGETPLATFORMDISPLAYEXTPROC = ::std::option::Option<
218unsafe extern "C" fn(
219    platform: EGLenum,
220    native_display: *mut ::std::os::raw::c_void,
221    attrib_list: *const EGLint,
222) -> EGLDisplay,
223>;
224
225pub type PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC = ::std::option::Option<
226unsafe extern "C" fn(
227    dpy: EGLDisplay,
228    image: EGLImageKHR,
229    fourcc: *mut i32,
230    num_planes: *mut i32,
231    modifiers: *mut EGLuint64KHR,
232) -> EGLBoolean,
233>;
234pub type PFNEGLEXPORTDMABUFIMAGEMESAPROC = ::std::option::Option<
235unsafe extern "C" fn(
236    dpy: EGLDisplay,
237    image: EGLImageKHR,
238    fds: *mut i32,
239    strides: *mut EGLint,
240    offsets: *mut EGLint,
241) -> EGLBoolean,
242>;
243
244// HACK(eddyb) this is actually an OpenGL extension function.
245type PFNGLEGLIMAGETARGETTEXTURE2DOESPROC = ::std::option::Option<
246unsafe extern "C" fn(
247    super::gl_sys::GLenum,
248    EGLImageKHR,
249),
250>;
251
252type PFNEGLPRESENTATIONTIMEANDROID = ::std::option::Option<
253unsafe extern "C" fn(
254    dpy: EGLDisplay,
255    surface: EGLSurface,
256    time: i64
257),
258>;
259
260type PFNEGLSURFACEATTRIB = ::std::option::Option<
261unsafe extern "C" fn(
262    dpy: EGLDisplay,
263    surface: EGLSurface,
264    attrib: EGLint,
265    value: EGLint
266)->EGLBoolean,
267>;
268
269pub struct LibEgl {
270    pub eglPresentationTimeANDROID: PFNEGLPRESENTATIONTIMEANDROID,
271    pub eglBindAPI: PFNEGLBINDAPIPROC,
272    pub eglChooseConfig: PFNEGLCHOOSECONFIGPROC,
273    pub eglCopyBuffers: PFNEGLCOPYBUFFERSPROC,
274    pub eglCreateContext: PFNEGLCREATECONTEXTPROC,
275    pub eglCreatePbufferSurface: PFNEGLCREATEPBUFFERSURFACEPROC,
276    pub eglCreatePixmapSurface: PFNEGLCREATEPIXMAPSURFACEPROC,
277    pub eglCreateWindowSurface: PFNEGLCREATEWINDOWSURFACEPROC,
278    pub eglDestroyContext: PFNEGLDESTROYCONTEXTPROC,
279    pub eglDestroySurface: PFNEGLDESTROYSURFACEPROC,
280    pub eglGetConfigAttrib: PFNEGLGETCONFIGATTRIBPROC,
281    pub eglGetConfigs: PFNEGLGETCONFIGSPROC,
282    pub eglGetCurrentDisplay: PFNEGLGETCURRENTDISPLAYPROC,
283    pub eglGetCurrentSurface: PFNEGLGETCURRENTSURFACEPROC,
284    pub eglGetDisplay: PFNEGLGETDISPLAYPROC,
285    pub eglGetError: PFNEGLGETERRORPROC,
286    pub eglGetProcAddress: PFNEGLGETPROCADDRESSPROC,
287    pub eglInitialize: PFNEGLINITIALIZEPROC,
288    pub eglMakeCurrent: PFNEGLMAKECURRENTPROC,
289    pub eglQueryContext: PFNEGLQUERYCONTEXTPROC,
290    pub eglQueryString: PFNEGLQUERYSTRINGPROC,
291    pub eglQuerySurface: PFNEGLQUERYSURFACEPROC,
292    pub eglSwapBuffers: PFNEGLSWAPBUFFERSPROC,
293    pub eglTerminate: PFNEGLTERMINATEPROC,
294    pub eglWaitGL: PFNEGLWAITGLPROC,
295    pub eglWaitNative: PFNEGLWAITNATIVEPROC,
296    pub eglBindTexImage: PFNEGLBINDTEXIMAGEPROC,
297    pub eglReleaseTexImage: PFNEGLRELEASETEXIMAGEPROC,
298    pub eglSurfaceAttrib: PFNEGLSURFACEATTRIBPROC,
299    pub eglSwapInterval: PFNEGLSWAPINTERVALPROC,
300
301    pub eglCreateImageKHR: PFNEGLCREATEIMAGEKHRPROC,
302    pub eglDestroyImageKHR: PFNEGLDESTROYIMAGEKHRPROC,
303    pub eglExportDMABUFImageQueryMESA: PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC,
304    pub eglExportDMABUFImageMESA: PFNEGLEXPORTDMABUFIMAGEMESAPROC,
305    pub eglGetPlatformDisplayEXT: PFNEGLGETPLATFORMDISPLAYEXTPROC,
306
307    // HACK(eddyb) this is actually an OpenGL extension function.
308    pub glEGLImageTargetTexture2DOES: PFNGLEGLIMAGETARGETTEXTURE2DOESPROC,
309
310    _keep_module_alive: ModuleLoader,
311}
312
313use std::ffi::CStr;
314
315use crate::module_loader::ModuleLoader;
316
317impl LibEgl {
318    pub fn try_load() -> Option<LibEgl> {
319        
320        let module = ModuleLoader::load("libEGL.so").or_else(|_| ModuleLoader::load("libEGL.so.1")).ok()?;
321
322        let eglGetProcAddress: PFNEGLGETPROCADDRESSPROC = module.get_symbol("eglGetProcAddress").ok();
323        macro_rules! get_ext_fn {
324            ($name:literal) => {
325                eglGetProcAddress.and_then(|gpa| unsafe {
326                    std::mem::transmute(gpa(CStr::from_bytes_with_nul(concat!($name, "\0").as_bytes()).unwrap().as_ptr()))
327                })
328            }
329        }
330
331        Some(LibEgl {
332            eglPresentationTimeANDROID: module.get_symbol("eglPresentationTimeANDROID").ok(),
333            eglBindAPI: module.get_symbol("eglBindAPI").ok(),
334            eglChooseConfig: module.get_symbol("eglChooseConfig").ok(),
335            eglCopyBuffers: module.get_symbol("eglCopyBuffers").ok(),
336            eglCreateContext: module.get_symbol("eglCreateContext").ok(),
337            eglCreatePbufferSurface: module.get_symbol("eglCreatePbufferSurface").ok(),
338            eglCreatePixmapSurface: module.get_symbol("eglCreatePixmapSurface").ok(),
339            eglCreateWindowSurface: module.get_symbol("eglCreateWindowSurface").ok(),
340            eglDestroyContext: module.get_symbol("eglDestroyContext").ok(),
341            eglDestroySurface: module.get_symbol("eglDestroySurface").ok(),
342            eglGetConfigAttrib: module.get_symbol("eglGetConfigAttrib").ok(),
343            eglGetConfigs: module.get_symbol("eglGetConfigs").ok(),
344            eglGetCurrentDisplay: module.get_symbol("eglGetCurrentDisplay").ok(),
345            eglGetCurrentSurface: module.get_symbol("eglGetCurrentSurface").ok(),
346            eglGetDisplay: module.get_symbol("eglGetDisplay").ok(),
347            eglGetError: module.get_symbol("eglGetError").ok(),
348            eglGetProcAddress,
349            eglInitialize: module.get_symbol("eglInitialize").ok(),
350            eglMakeCurrent: module.get_symbol("eglMakeCurrent").ok(),
351            eglQueryContext: module.get_symbol("eglQueryContext").ok(),
352            eglQueryString: module.get_symbol("eglQueryString").ok(),
353            eglQuerySurface: module.get_symbol("eglQuerySurface").ok(),
354            eglSwapBuffers: module.get_symbol("eglSwapBuffers").ok(),
355            eglTerminate: module.get_symbol("eglTerminate").ok(),
356            eglWaitGL: module.get_symbol("eglWaitGL").ok(),
357            eglWaitNative: module.get_symbol("eglWaitNative").ok(),
358            eglBindTexImage: module.get_symbol("eglBindTexImage").ok(),
359            eglReleaseTexImage: module.get_symbol("eglReleaseTexImage").ok(),
360            eglSurfaceAttrib: module.get_symbol("eglSurfaceAttrib").ok(),
361            eglSwapInterval: module.get_symbol("eglSwapInterval").ok(),
362
363            eglCreateImageKHR: get_ext_fn!("eglCreateImageKHR"),
364            eglDestroyImageKHR: get_ext_fn!("eglDestroyImageKHR"),
365            eglExportDMABUFImageQueryMESA: get_ext_fn!("eglExportDMABUFImageQueryMESA"),
366            eglExportDMABUFImageMESA: get_ext_fn!("eglExportDMABUFImageMESA"),
367            eglGetPlatformDisplayEXT: get_ext_fn!("eglGetPlatformDisplayEXT"),
368
369            glEGLImageTargetTexture2DOES: get_ext_fn!("glEGLImageTargetTexture2DOES"),
370
371            _keep_module_alive: module,
372        })
373    }
374}
375
376#[derive(Debug)]
377pub enum EglError {
378    NoDisplay,
379    InitializeFailed,
380    CreateContextFailed,
381    ChooseConfigFailed,
382}
383
384pub struct Egl {}
385
386#[cfg(target_os="android")]
387pub unsafe fn create_egl_context(
388    egl: &mut LibEgl,
389    display: *mut std::ffi::c_void,
390) -> Result<(EGLContext, EGLConfig, EGLDisplay), EglError> {
391
392    let display = (egl.eglGetDisplay.unwrap())(display as _);
393    if display == /* EGL_NO_DISPLAY */ null_mut() {
394        return Err(EglError::NoDisplay);
395    }
396
397    if (egl.eglInitialize.unwrap())(display, null_mut(), null_mut()) == 0 {
398        return Err(EglError::InitializeFailed);
399    }
400
401    #[rustfmt::skip]
402    let cfg_attributes = vec![
403        EGL_SURFACE_TYPE,
404        EGL_WINDOW_BIT,
405        EGL_RED_SIZE,
406        8,
407        EGL_GREEN_SIZE,
408        8,
409        EGL_BLUE_SIZE,
410        8,
411        EGL_ALPHA_SIZE,
412        0,
413        EGL_DEPTH_SIZE,
414        24,
415        EGL_STENCIL_SIZE,
416        0,
417        EGL_NONE,
418    ];
419    let mut available_cfgs: Vec<EGLConfig> = vec![null_mut(); 32];
420    let mut cfg_count = 0;
421
422    (egl.eglChooseConfig.unwrap())(
423        display,
424        cfg_attributes.as_ptr() as _,
425        available_cfgs.as_ptr() as _,
426        32,
427        &mut cfg_count as *mut _ as *mut _,
428    );
429    assert!(cfg_count > 0);
430    assert!(cfg_count <= 32);
431    
432    // find config with 8-bit rgb buffer if available, ndk sample does not trust egl spec
433    let mut config: EGLConfig = null_mut();
434    let mut exact_cfg_found = false;
435    for c in &mut available_cfgs[0..cfg_count] {
436        let mut r: i32 = 0;
437        let mut g: i32 = 0;
438        let mut b: i32 = 0;
439        let mut a: i32 = 0;
440        let mut d: i32 = 0;
441        if (egl.eglGetConfigAttrib.unwrap())(display, *c, EGL_RED_SIZE as _, &mut r) == 1
442            && (egl.eglGetConfigAttrib.unwrap())(display, *c, EGL_GREEN_SIZE as _, &mut g) == 1
443            && (egl.eglGetConfigAttrib.unwrap())(display, *c, EGL_BLUE_SIZE as _, &mut b) == 1
444            && (egl.eglGetConfigAttrib.unwrap())(display, *c, EGL_ALPHA_SIZE as _, &mut a) == 1
445            && (egl.eglGetConfigAttrib.unwrap())(display, *c, EGL_DEPTH_SIZE as _, &mut d) == 1
446            && r == 8
447            && g == 8
448            && b == 8
449            && a == 0
450            && d == 16
451        {
452            exact_cfg_found = true;
453            config = *c;
454            break;
455        }
456    }
457    if !exact_cfg_found {
458        config = available_cfgs[0];
459    }
460    #[cfg(use_gles_3)]
461    let ctx_attributes = vec![EGL_CONTEXT_MAJOR_VERSION, 3, EGL_NONE];
462    #[cfg(not(use_gles_3))]
463    let ctx_attributes = vec![EGL_CONTEXT_MAJOR_VERSION, 2, EGL_NONE];
464        
465    let context = (egl.eglCreateContext.unwrap())(
466        display,
467        config,
468        /* EGL_NO_CONTEXT */ null_mut(),
469        ctx_attributes.as_ptr() as _,
470    );
471    if context.is_null() {
472        return Err(EglError::CreateContextFailed);
473    }
474    
475    return Ok((context, config, display));
476}
477
478#[cfg(target_os="android")]
479pub unsafe fn create_egl_context_openxr(
480    egl: &mut LibEgl,
481    display: *mut std::ffi::c_void,
482) -> Result<(EGLContext, EGLConfig, EGLDisplay), EglError> {
483    
484    let display = (egl.eglGetDisplay.unwrap())(display as _);
485    if display == /* EGL_NO_DISPLAY */ null_mut() {
486        return Err(EglError::NoDisplay);
487    }
488    
489    if (egl.eglInitialize.unwrap())(display, null_mut(), null_mut()) == 0 {
490        return Err(EglError::InitializeFailed);
491    }
492    
493    
494    #[rustfmt::skip]
495    let cfg_attributes = vec![
496        EGL_RED_SIZE,
497        8,
498        EGL_GREEN_SIZE,
499        8,
500        EGL_BLUE_SIZE,
501        8,
502        EGL_ALPHA_SIZE,
503        8,
504        EGL_DEPTH_SIZE,
505        0,
506        EGL_STENCIL_SIZE,
507        0,
508        EGL_SAMPLES,
509        0,
510        EGL_NONE,
511    ];
512    let mut available_cfgs: Vec<EGLConfig> = vec![null_mut(); 1024];
513    let mut cfg_count = 0;
514    
515    (egl.eglGetConfigs.unwrap())(
516         display,
517         available_cfgs.as_ptr() as _,
518         available_cfgs.len() as _,
519         &mut cfg_count as *mut _ as *mut _,
520    );
521    /*
522    (egl.eglChooseConfig.unwrap())(
523        display,
524        cfg_attributes.as_ptr() as _,
525        available_cfgs.as_ptr() as _,
526        32,
527        &mut cfg_count as *mut _ as *mut _,
528    );
529    assert!(cfg_count > 0);
530    assert!(cfg_count <= 32);
531      */  
532    // find config with 8-bit rgb buffer if available, ndk sample does not trust egl spec
533    let mut config: EGLConfig = null_mut();
534    let mut exact_cfg_found = false;
535        
536    
537    for c in &mut available_cfgs[0..cfg_count] {
538        let mut value = 0u32;
539        (egl.eglGetConfigAttrib.unwrap())(display, *c, EGL_RENDERABLE_TYPE as _, &mut value as *mut _ as *mut _); 
540        if (value & EGL_OPENGL_ES3_BIT_KHR) != EGL_OPENGL_ES3_BIT_KHR{
541            continue;
542        }
543        (egl.eglGetConfigAttrib.unwrap())(display, *c, EGL_SURFACE_TYPE as _, &mut value as *mut _ as *mut _); 
544        if (value & (EGL_WINDOW_BIT | EGL_PBUFFER_BIT)) != (EGL_WINDOW_BIT | EGL_PBUFFER_BIT) {
545            continue;
546        }
547        
548        let mut j = 0;
549        while cfg_attributes[j] != EGL_NONE{
550            let mut value = 0u32;
551            (egl.eglGetConfigAttrib.unwrap())(display, *c, cfg_attributes[j] as _, &mut value as *mut _ as *mut _); 
552            if value != cfg_attributes[j+1]{
553                crate::log!("FAILED AT {} {} {}", value, cfg_attributes[j+1], j);
554                break; 
555            }
556            j+=2;
557        }
558        if cfg_attributes[j] == EGL_NONE{
559            exact_cfg_found = true;
560            config = *c;
561            break;
562        }
563    }
564    
565    if !exact_cfg_found {
566        config = available_cfgs[0];
567    }
568    let ctx_attributes = vec![EGL_CONTEXT_MAJOR_VERSION, 3, EGL_NONE];
569    let context = (egl.eglCreateContext.unwrap())(
570        display,
571        config,
572        /* EGL_NO_CONTEXT */ null_mut(),
573        ctx_attributes.as_ptr() as _,
574    );
575    if context.is_null() {
576        return Err(EglError::CreateContextFailed);
577    }
578        
579    return Ok((context, config, display));
580}
581
582
583#[cfg(target_env="ohos")]
584pub unsafe  fn create_egl_context(
585    egl: &mut LibEgl
586) -> Result<(EGLContext, EGLConfig, EGLDisplay), EglError> {
587    let display = (egl.eglGetDisplay.unwrap())(null_mut());
588    if display == null_mut() {
589        return Err(EglError::NoDisplay);
590    }
591
592    if (egl.eglInitialize.unwrap())(display,null_mut(),null_mut()) == 0 {
593        return Err(EglError::InitializeFailed);
594    }
595
596    #[rustfmt::skip]
597    let cfg_attributes = vec![
598        EGL_SURFACE_TYPE,
599        EGL_WINDOW_BIT,
600        EGL_RED_SIZE, 8,
601        EGL_GREEN_SIZE, 8,
602        EGL_BLUE_SIZE, 8,
603        EGL_ALPHA_SIZE, 8,
604        EGL_RENDERABLE_TYPE,
605        EGL_OPENGL_ES2_BIT,
606        EGL_DEPTH_SIZE, 0,
607        EGL_STENCIL_SIZE, 0,
608        EGL_NONE
609    ];
610    let available_cfgs: Vec<EGLConfig> = vec![null_mut(); 1];
611    let mut cfg_count = 0;
612
613    if (egl.eglChooseConfig.unwrap())(
614        display,
615        cfg_attributes.as_ptr() as _,
616        available_cfgs.as_ptr() as _,
617        1,&mut cfg_count as *mut _ as *mut _,
618    ) == 0 {
619        return Err(EglError::ChooseConfigFailed);
620    }
621
622    assert!(cfg_count > 0);
623
624    let config = available_cfgs[0];
625
626    #[cfg(ohos_sim)]
627    let ctx_attributes = vec![
628        EGL_CONTEXT_MAJOR_VERSION, 2, // version 1 and 3 also work
629        EGL_CONTEXT_MINOR_VERSION_KHR , 0,
630        // The rest of this was taken from servo's OpenGL config for OpenHarmony.
631        EGL_CONTEXT_OPENGL_PROFILE_MASK,
632        EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT, // allows use of deprecated features
633        EGL_NONE, 0, 0, 0,
634    ];
635
636    #[cfg(not(ohos_sim))]
637    let ctx_attributes = vec![
638        EGL_CONTEXT_MAJOR_VERSION, 
639        #[cfg(use_gles_3)]
640        3, // version 1 and 3 also work
641        #[cfg(not(use_gles_3))]
642        2, // version 1 and 3 also work
643        EGL_CONTEXT_MINOR_VERSION_KHR , 0,
644        EGL_NONE,
645    ];
646
647    let context = (egl.eglCreateContext.unwrap())(
648        display,
649        config,
650        /* EGL_NO_CONTEXT */ null_mut(),
651        ctx_attributes.as_ptr() as _
652    );
653    if context.is_null(){
654        return Err(EglError::CreateContextFailed);
655    }
656    crate::log!("create elg context success");
657    return Ok((context, config, display));
658}