9999// #include <fontconfig/fontconfig.h>
100100#define internal static
101101
102- #include < GL/glx .h>
103- #include < GL/glext .h>
102+ #include < EGL/egl .h>
103+ #include < EGL/eglext .h>
104104
105105#ifdef INSO_DEBUG
106106#define LINUX_FN_DEBUG (fmt, ...) do { \
@@ -159,6 +159,11 @@ struct Linux_Vars {
159159 Thread_Context tctx;
160160 Arena frame_arena;
161161
162+ EGLDisplay egl_display;
163+ EGLSurface egl_surface;
164+ EGLContext egl_context;
165+ EGLConfig egl_config;
166+
162167 Display* dpy;
163168 Window win;
164169
@@ -622,123 +627,99 @@ font_make_face(Arena* arena, Face_Description* description, f32 scale_factor) {
622627// //////////////////////////
623628
624629internal b32
625- glx_init (void ) {
626- int glx_maj, glx_min;
627-
628- if (!glXQueryVersion (linuxvars.dpy , &glx_maj, &glx_min)) {
629- return false ;
630+ egl_init (void ) {
631+ linuxvars.egl_display = eglGetPlatformDisplay (EGL_PLATFORM_X11_KHR, linuxvars.dpy , 0 );
632+ if (linuxvars.egl_display )
633+ {
634+ int egl_maj, egl_min;
635+ if (eglInitialize (linuxvars.egl_display , &egl_maj, &egl_min) &&
636+ ((egl_maj > 1 ) || ((egl_maj == 1 ) && (egl_min >= 5 ))))
637+ {
638+ return eglBindAPI (EGL_OPENGL_API);
639+ }
630640 }
631641
632- return glx_maj > 1 || (glx_maj == 1 && glx_min >= 3 ) ;
642+ return false ;
633643}
634644
635645internal b32
636- glx_get_config (GLXFBConfig* fb_config, XVisualInfo* vi) {
637-
638- static const int attrs[] = {
639- GLX_X_RENDERABLE , True,
640- GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
641- GLX_RENDER_TYPE , GLX_RGBA_BIT,
642- GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
643- GLX_RED_SIZE , 8 ,
644- GLX_GREEN_SIZE , 8 ,
645- GLX_BLUE_SIZE , 8 ,
646- GLX_ALPHA_SIZE , 8 ,
647- GLX_DEPTH_SIZE , 24 ,
648- GLX_STENCIL_SIZE , 8 ,
649- GLX_DOUBLEBUFFER , True,
650- None
651- };
652-
653- int conf_count = 0 ;
654- GLXFBConfig* conf_list = glXChooseFBConfig (linuxvars.dpy , DefaultScreen (linuxvars.dpy ), attrs, &conf_count);
655- if (!conf_count || conf_count <= 0 ) {
656- return false ;
657- }
658-
659- *fb_config = *conf_list;
660- XFree (conf_list);
661-
662- XVisualInfo* xvi = glXGetVisualFromFBConfig (linuxvars.dpy , *fb_config);
663- if (!xvi) {
664- return false ;
665- }
666-
667- *vi = *xvi;
668- XFree (xvi);
669-
670- return true ;
671- }
672-
673- internal b32 glx_ctx_error;
674-
675- internal int
676- glx_error_handler (Display* dpy, XErrorEvent* ev){
677- glx_ctx_error = true ;
678- return 0 ;
679- }
680-
681- typedef GLXContext (glXCreateContextAttribsARB_Function)(Display*, GLXFBConfig, GLXContext, Bool, const int *);
682- typedef void (glXSwapIntervalEXT_Function) (Display *dpy, GLXDrawable drawable, int interval);
683- typedef int (glXSwapIntervalMESA_Function) (unsigned int interval);
684- typedef int (glXGetSwapIntervalMESA_Function) (void );
685- typedef int (glXSwapIntervalSGI_Function) (int interval);
686-
687- internal b32
688- glx_create_context (GLXFBConfig fb_config){
689- const char *glx_exts = glXQueryExtensionsString (linuxvars.dpy , DefaultScreen (linuxvars.dpy ));
690-
691- glXCreateContextAttribsARB_Function *glXCreateContextAttribsARB = 0 ;
692- glXSwapIntervalEXT_Function *glXSwapIntervalEXT = 0 ;
693- glXSwapIntervalMESA_Function *glXSwapIntervalMESA = 0 ;
694- glXGetSwapIntervalMESA_Function *glXGetSwapIntervalMESA = 0 ;
695- glXSwapIntervalSGI_Function *glXSwapIntervalSGI = 0 ;
646+ egl_create_context (void ){
647+ Scratch_Block scratch (&linuxvars.tctx );
696648
697- #define GLXLOAD (f ) f = (f##_Function*) glXGetProcAddressARB((const GLubyte*) #f);
698- GLXLOAD (glXCreateContextAttribsARB);
649+ EGLint config_attributes[] =
650+ {
651+ EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
652+ EGL_CONFORMANT, EGL_OPENGL_BIT,
653+ EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
654+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
655+
656+ EGL_RED_SIZE, 8 ,
657+ EGL_GREEN_SIZE, 8 ,
658+ EGL_BLUE_SIZE, 8 ,
659+ EGL_ALPHA_SIZE, 8 ,
660+
661+ EGL_DEPTH_SIZE, 24 ,
662+ EGL_STENCIL_SIZE, 8 ,
663+
664+ EGL_NONE,
665+ };
699666
700- GLXContext ctx = NULL ;
701- int (*old_handler)(Display*, XErrorEvent*) = XSetErrorHandler (&glx_error_handler);
667+ EGLAttrib surface_attributes[] =
668+ {
669+ // TODO(maria): decide if we want an sRGB capable surface;
670+ // EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_SRGB,
671+ EGL_NONE,
672+ };
702673
703- if (glXCreateContextAttribsARB == NULL ){
704- // LOG("glXCreateContextAttribsARB() not found, using old-style GLX context\n" );
705- ctx = glXCreateNewContext (linuxvars.dpy , fb_config, GLX_RGBA_TYPE, 0 , True);
706- } else {
707- static const int context_attribs[] = {
708- GLX_CONTEXT_MAJOR_VERSION_ARB, 3 ,
709- GLX_CONTEXT_MINOR_VERSION_ARB, 2 ,
710- GLX_CONTEXT_PROFILE_MASK_ARB , GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
674+ EGLint context_attributes[] =
675+ {
676+ EGL_CONTEXT_MAJOR_VERSION, 3 ,
677+ EGL_CONTEXT_MINOR_VERSION, 2 ,
678+ EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT,
711679#if GL_DEBUG_MODE
712- GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_DEBUG_BIT_ARB ,
680+ EGL_CONTEXT_OPENGL_DEBUG, EGL_TRUE ,
713681#endif
714- None
715- };
716-
717- ctx = glXCreateContextAttribsARB (linuxvars.dpy , fb_config, 0 , True, context_attribs);
718- }
719-
720- XSync (linuxvars.dpy , False);
721- if (glx_ctx_error || !ctx) {
722- return false ;
723- }
724-
725- XSync (linuxvars.dpy , False);
726- XSetErrorHandler (old_handler);
727-
728- // b32 direct = glXIsDirect(linuxvars.dpy, ctx);
729-
730- // LOG("Making context current\n");
731- glXMakeCurrent (linuxvars.dpy , linuxvars.win , ctx);
732-
733- // glx_enable_vsync();
682+ EGL_NONE,
683+ };
734684
735- // NOTE(allen): Load gl functions
736- #define GL_FUNC (f,R,P ) GLXLOAD(f)
685+ EGLint config_count = 0 ;
686+ if (eglChooseConfig (linuxvars.egl_display , config_attributes, 0 , 0 , &config_count) &&
687+ (config_count > 0 ))
688+ {
689+ EGLConfig *configs = push_array (scratch, EGLConfig, config_count);
690+ if (eglChooseConfig (linuxvars.egl_display , config_attributes, configs, config_count, &config_count) &&
691+ (config_count > 0 ))
692+ {
693+ for (i32 config_index = 0 ;
694+ config_index < config_count;
695+ ++config_index)
696+ {
697+ EGLConfig test_config = configs[config_index];
698+ EGLSurface test_surface = eglCreatePlatformWindowSurface (linuxvars.egl_display , test_config, &linuxvars.win , surface_attributes);
699+ if (test_surface)
700+ {
701+ linuxvars.egl_config = test_config;
702+ linuxvars.egl_surface = test_surface;
703+ break ;
704+ }
705+ }
706+
707+ if (linuxvars.egl_surface )
708+ {
709+ linuxvars.egl_context = eglCreateContext (linuxvars.egl_display , linuxvars.egl_config , EGL_NO_CONTEXT, context_attributes);
710+ if (linuxvars.egl_context && eglMakeCurrent (linuxvars.egl_display , linuxvars.egl_surface , linuxvars.egl_surface , linuxvars.egl_context ))
711+ {
712+ // NOTE(allen): Load gl functions
713+ #define GL_FUNC (f,R,P ) f = (f##_Function*)eglGetProcAddress(#f);
737714#include " opengl/4ed_opengl_funcs.h"
715+ #undef GL_FUNC
716+ return true ;
717+ }
718+ }
719+ }
720+ }
738721
739- #undef GLXLOAD
740-
741- return true ;
722+ return false ;
742723}
743724
744725// //////////////////////////
@@ -771,14 +752,8 @@ linux_x11_init(int argc, char** argv, Plat_Settings* settings) {
771752
772753#undef LOAD_ATOM
773754
774- if (!glx_init ()){
775- system_error_box (" Your XServer's GLX version is too old. GLX 1.3+ is required." );
776- }
777-
778- GLXFBConfig fb_config;
779- XVisualInfo vi;
780- if (!glx_get_config (&fb_config, &vi)){
781- system_error_box (" Could not get a matching GLX FBConfig. Check your OpenGL drivers are installed correctly." );
755+ if (!egl_init ()){
756+ system_error_box (" Your EGL version is too old. EGL 1.5+ is required." );
782757 }
783758
784759 // TODO: window size
@@ -795,10 +770,9 @@ linux_x11_init(int argc, char** argv, Plat_Settings* settings) {
795770 swa.backing_store = WhenMapped;
796771 swa.event_mask = StructureNotifyMask;
797772 swa.bit_gravity = NorthWestGravity;
798- swa.colormap = XCreateColormap (dpy, RootWindow (dpy, vi.screen ), vi.visual , AllocNone);
799773
800- u32 CWflags = CWBackingStore|CWBitGravity|CWBackPixel|CWBorderPixel|CWColormap| CWEventMask;
801- linuxvars.win = XCreateWindow (dpy, RootWindow (dpy, vi. screen ), 0 , 0 , w, h, 0 , vi. depth , InputOutput, vi. visual , CWflags, &swa);
774+ u32 CWflags = CWBackingStore|CWBitGravity|CWBackPixel|CWBorderPixel|CWEventMask;
775+ linuxvars.win = XCreateWindow (dpy, DefaultRootWindow (dpy), 0 , 0 , w, h, 0 , CopyFromParent , InputOutput, CopyFromParent , CWflags, &swa);
802776
803777 if (!linuxvars.win ){
804778 system_error_box (" XCreateWindow failed. Make sure your display is set up correctly." );
@@ -855,8 +829,8 @@ linux_x11_init(int argc, char** argv, Plat_Settings* settings) {
855829 // NOTE(inso): make the window visible
856830 XMapWindow (linuxvars.dpy , linuxvars.win );
857831
858- if (!glx_create_context (fb_config )) {
859- system_error_box (" Unable to create GLX context." );
832+ if (!egl_create_context ( )) {
833+ system_error_box (" Unable to create EGL context." );
860834 }
861835
862836 XRaiseWindow (linuxvars.dpy , linuxvars.win );
@@ -2019,7 +1993,7 @@ main(int argc, char **argv){
20191993 }
20201994
20211995 gl_render (&render_target);
2022- glXSwapBuffers (linuxvars.dpy , linuxvars.win );
1996+ eglSwapBuffers (linuxvars.egl_display , linuxvars.egl_surface );
20231997
20241998 // TODO(allen): don't let the screen size change until HERE after the render
20251999
0 commit comments