X11 + OpenGL: new procedure to create OpenGL3+ contexts giving access to the highest OpenGL version supported by GLX.

The ABI compatibility was checked with the abi-compliance-checker tool.
The same code has already been committed in the 1.4 branch.

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@13043 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Manolo Gouy 2018-09-06 16:51:31 +00:00
parent 121abf4ca9
commit 226b64e9bd
4 changed files with 146 additions and 27 deletions

View File

@ -149,7 +149,7 @@ public:
- \c FL_DEPTH - depth buffer
- \c FL_STENCIL - stencil buffer
- \c FL_MULTISAMPLE - multisample antialiasing
- \c FL_OPENGL3 - use OpenGL version 3.0 or more when running Mac OS.
- \c FL_OPENGL3 - use OpenGL version 3.0 or more.
FL_RGB and FL_SINGLE have a value of zero, so they
are "on" unless you give FL_INDEX or FL_DOUBLE.
@ -169,16 +169,9 @@ public:
mode() must not be called within draw() since it
changes the current context.
\note On the <b>MSWindows and Unix/Linux platforms</b>, FLTK produces
contexts for the highest OpenGL version supported by the hardware. Such contexts
are also compatible with lower OpenGL versions. On the <b>Apple OS X
platform</b>, it is necessary to decide whether the source code targets
OpenGL versions higher or lower than 3.0. By default, FLTK
creates contexts adequate for OpenGL versions 1 and 2. To get contexts
for OpenGL 3.0 or higher, the <tt>FL_OPENGL3</tt> flag and Mac OS
version 10.7 or higher are required (in that case the context is NOT
compatible with OpenGL versions 1 or 2). The <tt>FL_OPENGL3</tt> flag has no
effect on non-Apple platforms.
The FL_OPENGL3 flag is required to access OpenGL version 3 or more
under the X11 and MacOS platforms; it's optional under Windows.
See more details in \ref opengl3.
\version the <tt>FL_OPENGL3</tt> flag appeared in version 1.3.4
*/

View File

@ -456,14 +456,21 @@ showing how to use OpenGL 3.0 (or higher versions) with FLTK in a cross-platform
It contains also OpenGL3-glut-test.cxx which shows how to use FLTK's GLUT compatibility
and OpenGL 3.
<b>On the MSWindows and Unix/Linux platforms</b>, FLTK creates contexts implementing
the highest OpenGL version supported by the hardware,
which are also compatible with lower OpenGL versions. Thus, FLTK allows
source code targeting any version of OpenGL. Access to functions from OpenGL versions above 1.1 requires to load function pointers at runtime on these platforms. FLTK recommends to use the GLEW library to perform this. It is therefore
necessary to install the GLEW library (see below). <b>On the Mac OS X platform</b>,
FLTK creates by default contexts implementing OpenGL versions 1 or 2.
To access OpenGL 3.0 (or higher versions), use the <tt>FL_OPENGL3</tt> flag (see below).
Mac OS 10.7 or above is required; GLEW is possible but not necessary.
To access OpenGL 3.0 (or higher versions), use the <tt>FL_OPENGL3</tt> flag
when calling Fl_Gl_Window::mode(int a) or glutInitDisplayMode().
<b>On the Windows and Unix/Linux platforms</b>, FLTK creates contexts
implementing the highest OpenGL version supported by the hardware.
Such contexts may also be compatible with lower OpenGL versions.
Access to functions from OpenGL
versions above 1.1 requires to load function pointers at runtime on these platforms.
FLTK recommends to use the GLEW library to perform this. It is therefore
necessary to install the GLEW library (see below).
<b>On the macOS platform</b>, MacOS 10.7 or above is required;
GLEW is possible but not necessary. FLTK creates contexts for OpenGL
versions 1 and 2 without the FL_OPENGL3
flag and for OpenGL versions 3.2 and above with it.
\par GLEW installation (Unix/Linux and MSWindows platforms)
GLEW is available as a package for most Linux distributions and in source form at http://glew.sourceforge.net/.

View File

@ -3,7 +3,7 @@
//
// OpenGL definitions for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2010 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
@ -64,6 +64,9 @@ typedef NSOpenGLContext* FLOpenGLContextPtr;
#else
# include <GL/glx.h>
# define GLContext GLXContext
# if ! defined(GLX_VERSION_1_3)
# typedef void *GLXFBConfig;
# endif
#endif
// Describes crap needed to create a GLContext.
@ -80,6 +83,7 @@ public:
#else
XVisualInfo *vis; // the visual to use
Colormap colormap; // a colormap for that visual
GLXFBConfig best_fb;
#endif
// Return one of these structures for a given gl mode.
// The second argument is a glX attribute list, and is used if mode is
@ -101,10 +105,10 @@ GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice*, int layer=0);
GLContext fl_create_gl_context(XVisualInfo* vis);
static inline
GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice* g) {
//static inline
GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice* g);/* {
return fl_create_gl_context(g->vis);
}
}*/
#endif

View File

@ -3,7 +3,7 @@
//
// OpenGL visual selection code for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2010 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
@ -33,6 +33,63 @@ void fl_save_dc(HWND, HDC);
extern void gl_texture_reset();
#endif
#if defined(USE_X11)
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 ) )
{
//printf("Invalid GLX version");
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;
int i;
for (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;
}
#endif
static Fl_Gl_Choice *first;
// this assumes one of the two arguments is zero:
@ -96,12 +153,19 @@ Fl_Gl_Choice *Fl_Gl_Choice::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) {
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);
if (m&FL_MULTISAMPLE) return find(m&~FL_MULTISAMPLE,0);
# endif
return 0;
return 0;
}
}
#elif defined(__APPLE_QUARTZ__)
@ -155,6 +219,7 @@ Fl_Gl_Choice *Fl_Gl_Choice::find(int m, const int *alistp) {
#if defined(USE_X11)
g->vis = visp;
g->best_fb = best_fb;
if (/*MaxCmapsOfScreen(ScreenOfDisplay(fl_display,fl_screen))==1 && */
visp->visualid == fl_visual->visualid &&
@ -204,6 +269,56 @@ static void del_context(GLContext ctx) {
#if defined(USE_X11)
static bool ctxErrorOccurred = false;
static int ctxErrorHandler( Display *dpy, XErrorEvent *ev )
{
ctxErrorOccurred = true;
return 0;
}
GLContext fl_create_gl_context(Fl_Window *window, const Fl_Gl_Choice* g) {
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 );
// Sync to ensure any errors generated are processed.
XSync( fl_display, False );
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_create_gl_context(XVisualInfo* vis) {
GLContext shared_ctx = 0;
if (context_list && nContext) shared_ctx = context_list[0];