diff --git a/code/bin/4ed_build.cpp b/code/bin/4ed_build.cpp index 90f0117c..20bc249d 100644 --- a/code/bin/4ed_build.cpp +++ b/code/bin/4ed_build.cpp @@ -323,7 +323,7 @@ build(Arena *arena, u32 flags, u32 arch, char *code_path, char **code_files, cha # define GCC_LIBS_COMMON \ "-lX11 -lpthread -lm -lrt " \ -"-lGL -ldl -lXfixes -lfreetype -lfontconfig" +"-lGL -lEGL -ldl -lXfixes -lfreetype -lfontconfig" # define GCC_LIBS_X64 GCC_LIBS_COMMON # define GCC_LIBS_X86 GCC_LIBS_COMMON diff --git a/code/platform_linux/linux_4ed.cpp b/code/platform_linux/linux_4ed.cpp index c31a9b6c..9ce373ad 100644 --- a/code/platform_linux/linux_4ed.cpp +++ b/code/platform_linux/linux_4ed.cpp @@ -99,8 +99,8 @@ //#include #define internal static -#include -#include +#include +#include #ifdef INSO_DEBUG #define LINUX_FN_DEBUG(fmt, ...) do { \ @@ -221,6 +221,13 @@ struct Linux_Vars { Atom atom_WM_DELETE_WINDOW; Log_Function *log_string; + + struct + { + EGLDisplay display; + EGLContext context; + EGLSurface surface; + } egl; }; global Linux_Vars linuxvars; @@ -617,123 +624,94 @@ font_make_face(Arena* arena, Face_Description* description, f32 scale_factor) { //////////////////////////// internal b32 -glx_init(void) { - int glx_maj, glx_min; - - if(!glXQueryVersion(linuxvars.dpy, &glx_maj, &glx_min)) { - return false; - } - - return glx_maj > 1 || (glx_maj == 1 && glx_min >= 3); -} - -internal b32 -glx_get_config(GLXFBConfig* fb_config, XVisualInfo* vi) { - - static const int attrs[] = { - GLX_X_RENDERABLE , True, - GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, - GLX_RENDER_TYPE , GLX_RGBA_BIT, - GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, - GLX_RED_SIZE , 8, - GLX_GREEN_SIZE , 8, - GLX_BLUE_SIZE , 8, - GLX_ALPHA_SIZE , 8, - GLX_DEPTH_SIZE , 24, - GLX_STENCIL_SIZE , 8, - GLX_DOUBLEBUFFER , True, - None - }; - - int conf_count = 0; - GLXFBConfig* conf_list = glXChooseFBConfig(linuxvars.dpy, DefaultScreen(linuxvars.dpy), attrs, &conf_count); - if(!conf_count || conf_count <= 0) { - return false; - } - - *fb_config = *conf_list; - XFree(conf_list); - - XVisualInfo* xvi = glXGetVisualFromFBConfig(linuxvars.dpy, *fb_config); - if(!xvi) { - return false; +egl_init(void) { + b32 result = false; + + linuxvars.egl.display = eglGetPlatformDisplay(EGL_PLATFORM_X11_KHR, linuxvars.dpy, 0); + if(linuxvars.egl.display != EGL_NO_DISPLAY) { + int egl_maj = 0; + int egl_min = 0; + if(eglInitialize(linuxvars.egl.display, &egl_maj, &egl_min) == EGL_TRUE) { + if((egl_maj > 1) || (egl_maj == 1 && egl_min >= 5)) { + eglBindAPI(EGL_OPENGL_API); + EGLint ContextAttributes[] = { + EGL_CONTEXT_MAJOR_VERSION, 3, + EGL_CONTEXT_MINOR_VERSION, 2, + EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT, +#if GL_DEBUG_MODE + EGL_CONTEXT_OPENGL_DEBUG +#endif + EGL_NONE, + }; + + linuxvars.egl.context = eglCreateContext(linuxvars.egl.display, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT, ContextAttributes); + + if(linuxvars.egl.context != EGL_NO_CONTEXT) { + +#define GL_FUNC(f,R,P) f = (f##_Function *)eglGetProcAddress(#f); +#include "opengl/4ed_opengl_funcs.h" + + result = true; + } + } + } } - *vi = *xvi; - XFree(xvi); - - return true; -} - -internal b32 glx_ctx_error; - -internal int -glx_error_handler(Display* dpy, XErrorEvent* ev){ - glx_ctx_error = true; - return 0; + return result; } -typedef GLXContext (glXCreateContextAttribsARB_Function)(Display*, GLXFBConfig, GLXContext, Bool, const int*); -typedef void (glXSwapIntervalEXT_Function) (Display *dpy, GLXDrawable drawable, int interval); -typedef int (glXSwapIntervalMESA_Function) (unsigned int interval); -typedef int (glXGetSwapIntervalMESA_Function) (void); -typedef int (glXSwapIntervalSGI_Function) (int interval); - internal b32 -glx_create_context(GLXFBConfig fb_config){ - const char *glx_exts = glXQueryExtensionsString(linuxvars.dpy, DefaultScreen(linuxvars.dpy)); - - glXCreateContextAttribsARB_Function *glXCreateContextAttribsARB = 0; - glXSwapIntervalEXT_Function *glXSwapIntervalEXT = 0; - glXSwapIntervalMESA_Function *glXSwapIntervalMESA = 0; - glXGetSwapIntervalMESA_Function *glXGetSwapIntervalMESA = 0; - glXSwapIntervalSGI_Function *glXSwapIntervalSGI = 0; - -#define GLXLOAD(f) f = (f##_Function*) glXGetProcAddressARB((const GLubyte*) #f); - GLXLOAD(glXCreateContextAttribsARB); +egl_create_surface(void) { + b32 result = false; - GLXContext ctx = NULL; - int (*old_handler)(Display*, XErrorEvent*) = XSetErrorHandler(&glx_error_handler); + Scratch_Block scratch(&linuxvars.tctx); - if (glXCreateContextAttribsARB == NULL){ - //LOG("glXCreateContextAttribsARB() not found, using old-style GLX context\n" ); - ctx = glXCreateNewContext(linuxvars.dpy, fb_config, GLX_RGBA_TYPE, 0, True); - } else { - static const int context_attribs[] = { - GLX_CONTEXT_MAJOR_VERSION_ARB, 3, - GLX_CONTEXT_MINOR_VERSION_ARB, 2, - GLX_CONTEXT_PROFILE_MASK_ARB , GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, -#if GL_DEBUG_MODE - GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_DEBUG_BIT_ARB, -#endif - None - }; + EGLint config_attributes[] = { + EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER, + EGL_CONFORMANT, EGL_OPENGL_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - ctx = glXCreateContextAttribsARB(linuxvars.dpy, fb_config, 0, True, context_attribs); - } - - XSync(linuxvars.dpy, False); - if(glx_ctx_error || !ctx) { - return false; - } - - XSync(linuxvars.dpy, False); - XSetErrorHandler(old_handler); - - //b32 direct = glXIsDirect(linuxvars.dpy, ctx); + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + + EGL_DEPTH_SIZE, 24, + EGL_STENCIL_SIZE, 8, + + EGL_NONE, + }; - //LOG("Making context current\n"); - glXMakeCurrent(linuxvars.dpy, linuxvars.win, ctx); + EGLAttrib surface_attributes[] = { + EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_SRGB, + EGL_RENDER_BUFFER, EGL_BACK_BUFFER, + + // NOTE(maria): for wayland later + //EGL_PRESENT_OPAQUE_EXT, EGL_TRUE, + + EGL_NONE, + }; - //glx_enable_vsync(); + EGLint config_count = 0; + eglChooseConfig(linuxvars.egl.display, config_attributes, 0, 0, &config_count); - // NOTE(allen): Load gl functions -#define GL_FUNC(f,R,P) GLXLOAD(f) -#include "opengl/4ed_opengl_funcs.h" + EGLConfig *configs = push_array(scratch, EGLConfig, config_count); + eglChooseConfig(linuxvars.egl.display, config_attributes, configs, config_count, &config_count); -#undef GLXLOAD + for(int config_index = 0; + config_index < config_count; + ++config_index) { + EGLConfig test_config = configs[config_index]; + EGLSurface test_surface = eglCreatePlatformWindowSurface(linuxvars.egl.display, test_config, &linuxvars.win, surface_attributes); + if(test_surface != EGL_NO_SURFACE) { + linuxvars.egl.surface = test_surface; + result = true; + break; + } + } - return true; + return result; } //////////////////////////// @@ -766,14 +744,8 @@ linux_x11_init(int argc, char** argv, Plat_Settings* settings) { #undef LOAD_ATOM - if (!glx_init()){ - system_error_box("Your XServer's GLX version is too old. GLX 1.3+ is required."); - } - - GLXFBConfig fb_config; - XVisualInfo vi; - if (!glx_get_config(&fb_config, &vi)){ - system_error_box("Could not get a matching GLX FBConfig. Check your OpenGL drivers are installed correctly."); + if (!egl_init()){ + system_error_box("Your EGL version is too old. EGL 1.5+ is required."); } // TODO: window size @@ -790,10 +762,9 @@ linux_x11_init(int argc, char** argv, Plat_Settings* settings) { swa.backing_store = WhenMapped; swa.event_mask = StructureNotifyMask; swa.bit_gravity = NorthWestGravity; - swa.colormap = XCreateColormap(dpy, RootWindow(dpy, vi.screen), vi.visual, AllocNone); u32 CWflags = CWBackingStore|CWBitGravity|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask; - linuxvars.win = XCreateWindow(dpy, RootWindow(dpy, vi.screen), 0, 0, w, h, 0, vi.depth, InputOutput, vi.visual, CWflags, &swa); + linuxvars.win = XCreateWindow(dpy, DefaultRootWindow(dpy), 0, 0, w, h, 0, CopyFromParent, InputOutput, CopyFromParent, CWflags, &swa); if (!linuxvars.win){ system_error_box("XCreateWindow failed. Make sure your display is set up correctly."); @@ -850,10 +821,12 @@ linux_x11_init(int argc, char** argv, Plat_Settings* settings) { // NOTE(inso): make the window visible XMapWindow(linuxvars.dpy, linuxvars.win); - if(!glx_create_context(fb_config)) { - system_error_box("Unable to create GLX context."); + if(!egl_create_surface()) { + system_error_box("Unable to create EGL surface."); } + eglMakeCurrent(linuxvars.egl.display, linuxvars.egl.surface, linuxvars.egl.surface, linuxvars.egl.context); + XRaiseWindow(linuxvars.dpy, linuxvars.win); if (settings->set_window_pos){ @@ -2014,7 +1987,7 @@ main(int argc, char **argv){ } gl_render(&render_target); - glXSwapBuffers(linuxvars.dpy, linuxvars.win); + eglSwapBuffers(linuxvars.egl.display, linuxvars.egl.surface); // TODO(allen): don't let the screen size change until HERE after the render