diff options
| author | Manolo Gouy <Manolo> | 2018-08-20 15:12:10 +0000 |
|---|---|---|
| committer | Manolo Gouy <Manolo> | 2018-08-20 15:12:10 +0000 |
| commit | c0e04da27f29a989b65958de4deb7566d172bdbe (patch) | |
| tree | 95ce7015015051e63823cccb0941a16d98bdb7c5 /src | |
| parent | b26ace4b18be5450c4b3ba248a5c9df08652679d (diff) | |
Fix creation of OpenGL3+ context under X11 platform
The procedure given in https://www.khronos.org/opengl/wiki/Tutorial:_OpenGL_3.0_Context_Creation_(GLX)
is now followed. This gives access to contexts for the highest OpenGL version supported by the hardware
when flag FL_OPENGL3 is used in the call to Fl_Gl_Window::mode(int).
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@13021 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src')
| -rw-r--r-- | src/Fl_Gl_Choice.H | 8 | ||||
| -rw-r--r-- | src/Fl_Gl_Choice.cxx | 108 |
2 files changed, 107 insertions, 9 deletions
diff --git a/src/Fl_Gl_Choice.H b/src/Fl_Gl_Choice.H index bdee1c6c8..5c5b339ef 100644 --- a/src/Fl_Gl_Choice.H +++ b/src/Fl_Gl_Choice.H @@ -3,7 +3,7 @@ // // OpenGL definitions for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2016 by Bill Spitzak and others. +// Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -50,9 +50,13 @@ #ifdef FL_CFG_GFX_XLIB # include <GL/glx.h> +# if ! defined(GLX_VERSION_1_3) +# typedef void *GLXFBConfig; +# endif # define FL_GL_CHOICE_PLATFORM_SPECIFIC_MEMBERS \ XVisualInfo *vis; /* the visual to use */ \ - Colormap colormap; // a colormap for that visual + Colormap colormap; /* a colormap for that visual */ \ + GLXFBConfig best_fb; #endif // FL_CFG_GFX_XLIB*/ diff --git a/src/Fl_Gl_Choice.cxx b/src/Fl_Gl_Choice.cxx index 014635e14..3fbce41f7 100644 --- a/src/Fl_Gl_Choice.cxx +++ b/src/Fl_Gl_Choice.cxx @@ -231,6 +231,53 @@ void Fl_WinAPI_Gl_Window_Driver::delete_gl_context(GLContext context) { #ifdef FL_CFG_GFX_XLIB # include <FL/platform.H> +static XVisualInfo *gl3_getvisual(const int *blist, GLXFBConfig *pbestFB) +{ + int glx_major, glx_minor; + + // FBConfigs were added in GLX version 1.3. + if ( !glXQueryVersion(fl_display, &glx_major, &glx_minor) || + ( ( glx_major == 1 ) && ( glx_minor < 3 ) ) || ( glx_major < 1 ) ) { + return NULL; + } + + //printf( "Getting matching framebuffer configs\n" ); + int fbcount; + GLXFBConfig* fbc = glXChooseFBConfig(fl_display, DefaultScreen(fl_display), blist, &fbcount); + if (!fbc) { + //printf( "Failed to retrieve a framebuffer config\n" ); + return NULL; + } + //printf( "Found %d matching FB configs.\n", fbcount ); + + // Pick the FB config/visual with the most samples per pixel + int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999; + for (int i = 0; i < fbcount; ++i) + { + XVisualInfo *vi = glXGetVisualFromFBConfig( fl_display, fbc[i] ); + if (vi) { + int samp_buf, samples; + glXGetFBConfigAttrib(fl_display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf); + glXGetFBConfigAttrib(fl_display, fbc[i], GLX_SAMPLES , &samples ); + /*printf( " Matching fbconfig %d, visual ID 0x%2lx: SAMPLE_BUFFERS = %d, SAMPLES = %d\n", + i, vi -> visualid, samp_buf, samples );*/ + if ( best_fbc < 0 || (samp_buf && samples > best_num_samp) ) + best_fbc = i, best_num_samp = samples; + if ( worst_fbc < 0 || !samp_buf || samples < worst_num_samp ) + worst_fbc = i, worst_num_samp = samples; + } + XFree(vi); + } + + GLXFBConfig bestFbc = fbc[ best_fbc ]; + // Be sure to free the FBConfig list allocated by glXChooseFBConfig() + XFree(fbc); + // Get a visual + XVisualInfo *vi = glXGetVisualFromFBConfig(fl_display, bestFbc); + *pbestFB = bestFbc; + return vi; +} + Fl_Gl_Choice *Fl_X11_Gl_Window_Driver::find(int m, const int *alistp) { Fl_Gl_Choice *g = Fl_Gl_Window_Driver::find_begin(m, alistp); @@ -286,18 +333,26 @@ Fl_Gl_Choice *Fl_X11_Gl_Window_Driver::find(int m, const int *alistp) } fl_open_display(); - XVisualInfo *visp = glXChooseVisual(fl_display, fl_screen, (int *)blist); + XVisualInfo *visp = NULL; + GLXFBConfig best_fb = NULL; + if (m & FL_OPENGL3) { + visp = gl3_getvisual((const int *)blist, &best_fb); + } if (!visp) { -# if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample) - if (m&FL_MULTISAMPLE) return find(m&~FL_MULTISAMPLE,0); -# endif - return 0; + visp = glXChooseVisual(fl_display, fl_screen, (int *)blist); + if (!visp) { +# if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample) + if (m&FL_MULTISAMPLE) return find(m&~FL_MULTISAMPLE, 0); +# endif + return 0; + } } g = new Fl_Gl_Choice(m, alistp, first); first = g; g->vis = visp; + g->best_fb = best_fb; if (/*MaxCmapsOfScreen(ScreenOfDisplay(fl_display,fl_screen))==1 && */ visp->visualid == fl_visual->visualid && @@ -306,13 +361,52 @@ Fl_Gl_Choice *Fl_X11_Gl_Window_Driver::find(int m, const int *alistp) else g->colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen), visp->visual, AllocNone); - return g; } +static bool ctxErrorOccurred = false; +static int ctxErrorHandler( Display *dpy, XErrorEvent *ev ) +{ + ctxErrorOccurred = true; + return 0; +} GLContext Fl_X11_Gl_Window_Driver::create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer) { - return create_gl_context(g->vis); + GLContext shared_ctx = 0; + if (context_list && nContext) shared_ctx = context_list[0]; + + typedef GLContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLContext, Bool, const int*); + // It is not necessary to create or make current to a context before calling glXGetProcAddressARB + static glXCreateContextAttribsARBProc glXCreateContextAttribsARB = + (glXCreateContextAttribsARBProc)glXGetProcAddressARB((const GLubyte *)"glXCreateContextAttribsARB"); + + GLContext ctx = 0; + // Check for the GLX_ARB_create_context extension string and the function. + // If either is not present, use GLX 1.3 context creation method. + const char *glxExts = glXQueryExtensionsString(fl_display, fl_screen); + if (g->best_fb && strstr(glxExts, "GLX_ARB_create_context") && glXCreateContextAttribsARB ) { + int context_attribs[] = + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 2, + //GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, + //GLX_CONTEXT_PROFILE_MASK_ARB , GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + None + }; + ctxErrorOccurred = false; + XErrorHandler oldHandler = XSetErrorHandler(&ctxErrorHandler); + ctx = glXCreateContextAttribsARB(fl_display, g->best_fb, shared_ctx, true, context_attribs); + XSync(fl_display, false); // Sync to ensure any errors generated are processed. + if (ctxErrorOccurred) ctx = 0; + XSetErrorHandler(oldHandler); + } + if (!ctx) { // use OpenGL 1-style context creation + ctx = glXCreateContext(fl_display, g->vis, shared_ctx, true); + } + if (ctx) + add_context(ctx); +//glXMakeCurrent(fl_display, fl_xid(window), ctx);printf("%s\n", glGetString(GL_VERSION)); + return ctx; } GLContext Fl_X11_Gl_Window_Driver::create_gl_context(XVisualInfo *vis) { |
