|
|
|
@ -32,6 +32,7 @@ |
|
|
|
|
|
|
|
|
|
#include <string.h> |
|
|
|
|
#include <stdlib.h> |
|
|
|
|
#include <assert.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// This is the only glXGetProcAddress variant not declared by glxext.h
|
|
|
|
@ -66,241 +67,283 @@ static _GLFW_TLS _GLFWwindow* _glfwCurrentWindow = NULL; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//========================================================================
|
|
|
|
|
// Returns the specified attribute of the specified GLXFBConfig
|
|
|
|
|
// NOTE: Do not call this unless we have found GLX 1.3+ or GLX_SGIX_fbconfig
|
|
|
|
|
// Error handler used when creating a context with the GLX_ARB_create_context
|
|
|
|
|
// extension set
|
|
|
|
|
//========================================================================
|
|
|
|
|
|
|
|
|
|
static int getFBConfigAttrib(_GLFWwindow* window, GLXFBConfig fbconfig, int attrib) |
|
|
|
|
static int errorHandler(Display *display, XErrorEvent* event) |
|
|
|
|
{ |
|
|
|
|
int value; |
|
|
|
|
_glfwErrorCode = event->error_code; |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//========================================================================
|
|
|
|
|
// Create the OpenGL context using legacy API
|
|
|
|
|
//========================================================================
|
|
|
|
|
|
|
|
|
|
static GLXContext createLegacyContext(_GLFWwindow* window, |
|
|
|
|
GLXFBConfig fbconfig, |
|
|
|
|
GLXContext share) |
|
|
|
|
{ |
|
|
|
|
if (_glfw.glx.SGIX_fbconfig) |
|
|
|
|
{ |
|
|
|
|
_glfw.glx.GetFBConfigAttribSGIX(_glfw.x11.display, |
|
|
|
|
fbconfig, attrib, &value); |
|
|
|
|
return _glfw.glx.CreateContextWithConfigSGIX(_glfw.x11.display, |
|
|
|
|
fbconfig, |
|
|
|
|
GLX_RGBA_TYPE, |
|
|
|
|
share, |
|
|
|
|
True); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
glXGetFBConfigAttrib(_glfw.x11.display, fbconfig, attrib, &value); |
|
|
|
|
|
|
|
|
|
return value; |
|
|
|
|
{ |
|
|
|
|
return glXCreateNewContext(_glfw.x11.display, |
|
|
|
|
fbconfig, |
|
|
|
|
GLX_RGBA_TYPE, |
|
|
|
|
share, |
|
|
|
|
True); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
////// GLFW internal API //////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
//========================================================================
|
|
|
|
|
// Return a list of available and usable framebuffer configs
|
|
|
|
|
// Initialize GLX
|
|
|
|
|
//========================================================================
|
|
|
|
|
|
|
|
|
|
static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) |
|
|
|
|
int _glfwInitOpenGL(void) |
|
|
|
|
{ |
|
|
|
|
GLXFBConfig* fbconfigs; |
|
|
|
|
_GLFWfbconfig* result; |
|
|
|
|
int i, count = 0; |
|
|
|
|
const char* vendor; |
|
|
|
|
GLboolean trustWindowBit = GL_TRUE; |
|
|
|
|
|
|
|
|
|
*found = 0; |
|
|
|
|
#ifdef _GLFW_DLOPEN_LIBGL |
|
|
|
|
int i; |
|
|
|
|
char* libGL_names[ ] = |
|
|
|
|
{ |
|
|
|
|
"libGL.so", |
|
|
|
|
"libGL.so.1", |
|
|
|
|
"/usr/lib/libGL.so", |
|
|
|
|
"/usr/lib/libGL.so.1", |
|
|
|
|
NULL |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
if (_glfw.glx.versionMajor == 1 && _glfw.glx.versionMinor < 3) |
|
|
|
|
for (i = 0; libGL_names[i] != NULL; i++) |
|
|
|
|
{ |
|
|
|
|
if (!_glfw.glx.SGIX_fbconfig) |
|
|
|
|
{ |
|
|
|
|
_glfwInputError(GLFW_API_UNAVAILABLE, |
|
|
|
|
"GLX: GLXFBConfig support not found"); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
_glfw.glx.libGL = dlopen(libGL_names[i], RTLD_LAZY | RTLD_GLOBAL); |
|
|
|
|
if (_glfw.glx.libGL) |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR); |
|
|
|
|
if (!_glfw.glx.libGL) |
|
|
|
|
{ |
|
|
|
|
_glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to find libGL"); |
|
|
|
|
return GL_FALSE; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
if (strcmp(vendor, "Chromium") == 0) |
|
|
|
|
// Check if GLX is supported on this display
|
|
|
|
|
if (!glXQueryExtension(_glfw.x11.display, |
|
|
|
|
&_glfw.glx.errorBase, |
|
|
|
|
&_glfw.glx.eventBase)) |
|
|
|
|
{ |
|
|
|
|
// HACK: This is a (hopefully temporary) workaround for Chromium
|
|
|
|
|
// (VirtualBox GL) not setting the window bit on any GLXFBConfigs
|
|
|
|
|
trustWindowBit = GL_FALSE; |
|
|
|
|
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: GLX support not found"); |
|
|
|
|
return GL_FALSE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (_glfw.glx.SGIX_fbconfig) |
|
|
|
|
if (!glXQueryVersion(_glfw.x11.display, |
|
|
|
|
&_glfw.glx.versionMajor, |
|
|
|
|
&_glfw.glx.versionMinor)) |
|
|
|
|
{ |
|
|
|
|
fbconfigs = _glfw.glx.ChooseFBConfigSGIX(_glfw.x11.display, |
|
|
|
|
_glfw.x11.screen, |
|
|
|
|
NULL, |
|
|
|
|
&count); |
|
|
|
|
if (!count) |
|
|
|
|
{ |
|
|
|
|
_glfwInputError(GLFW_API_UNAVAILABLE, |
|
|
|
|
"GLX: No GLXFBConfigs returned"); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
_glfwInputError(GLFW_API_UNAVAILABLE, |
|
|
|
|
"GLX: Failed to query GLX version"); |
|
|
|
|
return GL_FALSE; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
|
|
|
|
|
if (_glfwPlatformExtensionSupported("GLX_EXT_swap_control")) |
|
|
|
|
{ |
|
|
|
|
fbconfigs = glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &count); |
|
|
|
|
if (!count) |
|
|
|
|
{ |
|
|
|
|
_glfwInputError(GLFW_API_UNAVAILABLE, |
|
|
|
|
"GLX: No GLXFBConfigs returned"); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
_glfw.glx.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) |
|
|
|
|
_glfwPlatformGetProcAddress("glXSwapIntervalEXT"); |
|
|
|
|
|
|
|
|
|
if (_glfw.glx.SwapIntervalEXT) |
|
|
|
|
_glfw.glx.EXT_swap_control = GL_TRUE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
result = (_GLFWfbconfig*) malloc(sizeof(_GLFWfbconfig) * count); |
|
|
|
|
if (!result) |
|
|
|
|
if (_glfwPlatformExtensionSupported("GLX_SGI_swap_control")) |
|
|
|
|
{ |
|
|
|
|
_glfwInputError(GLFW_OUT_OF_MEMORY, NULL); |
|
|
|
|
return NULL; |
|
|
|
|
_glfw.glx.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) |
|
|
|
|
_glfwPlatformGetProcAddress("glXSwapIntervalSGI"); |
|
|
|
|
|
|
|
|
|
if (_glfw.glx.SwapIntervalSGI) |
|
|
|
|
_glfw.glx.SGI_swap_control = GL_TRUE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) |
|
|
|
|
if (_glfwPlatformExtensionSupported("GLX_MESA_swap_control")) |
|
|
|
|
{ |
|
|
|
|
_GLFWfbconfig* f = result + *found; |
|
|
|
|
_glfw.glx.SwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC) |
|
|
|
|
_glfwPlatformGetProcAddress("glXSwapIntervalMESA"); |
|
|
|
|
|
|
|
|
|
if (!getFBConfigAttrib(window, fbconfigs[i], GLX_DOUBLEBUFFER) || |
|
|
|
|
!getFBConfigAttrib(window, fbconfigs[i], GLX_VISUAL_ID)) |
|
|
|
|
{ |
|
|
|
|
// Only consider double-buffered GLXFBConfigs with associated visuals
|
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
if (_glfw.glx.SwapIntervalMESA) |
|
|
|
|
_glfw.glx.MESA_swap_control = GL_TRUE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!(getFBConfigAttrib(window, |
|
|
|
|
fbconfigs[i], |
|
|
|
|
GLX_RENDER_TYPE) & GLX_RGBA_BIT)) |
|
|
|
|
{ |
|
|
|
|
// Only consider RGBA GLXFBConfigs
|
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
if (_glfwPlatformExtensionSupported("GLX_SGIX_fbconfig")) |
|
|
|
|
{ |
|
|
|
|
_glfw.glx.GetFBConfigAttribSGIX = (PFNGLXGETFBCONFIGATTRIBSGIXPROC) |
|
|
|
|
_glfwPlatformGetProcAddress("glXGetFBConfigAttribSGIX"); |
|
|
|
|
_glfw.glx.ChooseFBConfigSGIX = (PFNGLXCHOOSEFBCONFIGSGIXPROC) |
|
|
|
|
_glfwPlatformGetProcAddress("glXChooseFBConfigSGIX"); |
|
|
|
|
_glfw.glx.CreateContextWithConfigSGIX = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) |
|
|
|
|
_glfwPlatformGetProcAddress("glXCreateContextWithConfigSGIX"); |
|
|
|
|
_glfw.glx.GetVisualFromFBConfigSGIX = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) |
|
|
|
|
_glfwPlatformGetProcAddress("glXGetVisualFromFBConfigSGIX"); |
|
|
|
|
|
|
|
|
|
if (!(getFBConfigAttrib(window, fbconfigs[i], GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT)) |
|
|
|
|
if (_glfw.glx.GetFBConfigAttribSGIX && |
|
|
|
|
_glfw.glx.ChooseFBConfigSGIX && |
|
|
|
|
_glfw.glx.CreateContextWithConfigSGIX && |
|
|
|
|
_glfw.glx.GetVisualFromFBConfigSGIX) |
|
|
|
|
{ |
|
|
|
|
if (trustWindowBit) |
|
|
|
|
{ |
|
|
|
|
// Only consider window GLXFBConfigs
|
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
_glfw.glx.SGIX_fbconfig = GL_TRUE; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
f->redBits = getFBConfigAttrib(window, fbconfigs[i], GLX_RED_SIZE); |
|
|
|
|
f->greenBits = getFBConfigAttrib(window, fbconfigs[i], GLX_GREEN_SIZE); |
|
|
|
|
f->blueBits = getFBConfigAttrib(window, fbconfigs[i], GLX_BLUE_SIZE); |
|
|
|
|
|
|
|
|
|
f->alphaBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ALPHA_SIZE); |
|
|
|
|
f->depthBits = getFBConfigAttrib(window, fbconfigs[i], GLX_DEPTH_SIZE); |
|
|
|
|
f->stencilBits = getFBConfigAttrib(window, fbconfigs[i], GLX_STENCIL_SIZE); |
|
|
|
|
|
|
|
|
|
f->accumRedBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_RED_SIZE); |
|
|
|
|
f->accumGreenBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_GREEN_SIZE); |
|
|
|
|
f->accumBlueBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_BLUE_SIZE); |
|
|
|
|
f->accumAlphaBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_ALPHA_SIZE); |
|
|
|
|
|
|
|
|
|
f->auxBuffers = getFBConfigAttrib(window, fbconfigs[i], GLX_AUX_BUFFERS); |
|
|
|
|
f->stereo = getFBConfigAttrib(window, fbconfigs[i], GLX_STEREO); |
|
|
|
|
|
|
|
|
|
if (_glfw.glx.ARB_multisample) |
|
|
|
|
f->samples = getFBConfigAttrib(window, fbconfigs[i], GLX_SAMPLES); |
|
|
|
|
else |
|
|
|
|
f->samples = 0; |
|
|
|
|
if (_glfwPlatformExtensionSupported("GLX_ARB_multisample")) |
|
|
|
|
_glfw.glx.ARB_multisample = GL_TRUE; |
|
|
|
|
|
|
|
|
|
if (_glfw.glx.ARB_framebuffer_sRGB) |
|
|
|
|
f->sRGB = getFBConfigAttrib(window, fbconfigs[i], GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB); |
|
|
|
|
else |
|
|
|
|
f->sRGB = GL_FALSE; |
|
|
|
|
if (_glfwPlatformExtensionSupported("GLX_ARB_framebuffer_sRGB")) |
|
|
|
|
_glfw.glx.ARB_framebuffer_sRGB = GL_TRUE; |
|
|
|
|
|
|
|
|
|
f->platformID = (GLFWintptr) getFBConfigAttrib(window, fbconfigs[i], GLX_FBCONFIG_ID); |
|
|
|
|
if (_glfwPlatformExtensionSupported("GLX_ARB_create_context")) |
|
|
|
|
{ |
|
|
|
|
_glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) |
|
|
|
|
_glfwPlatformGetProcAddress("glXCreateContextAttribsARB"); |
|
|
|
|
|
|
|
|
|
(*found)++; |
|
|
|
|
if (_glfw.glx.CreateContextAttribsARB) |
|
|
|
|
_glfw.glx.ARB_create_context = GL_TRUE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
XFree(fbconfigs); |
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_robustness")) |
|
|
|
|
_glfw.glx.ARB_create_context_robustness = GL_TRUE; |
|
|
|
|
|
|
|
|
|
if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_profile")) |
|
|
|
|
_glfw.glx.ARB_create_context_profile = GL_TRUE; |
|
|
|
|
|
|
|
|
|
//========================================================================
|
|
|
|
|
// Error handler used when creating a context with the GLX_ARB_create_context
|
|
|
|
|
// extension set
|
|
|
|
|
//========================================================================
|
|
|
|
|
if (_glfwPlatformExtensionSupported("GLX_EXT_create_context_es2_profile")) |
|
|
|
|
_glfw.glx.EXT_create_context_es2_profile = GL_TRUE; |
|
|
|
|
|
|
|
|
|
static int errorHandler(Display *display, XErrorEvent* event) |
|
|
|
|
{ |
|
|
|
|
_glfwErrorCode = event->error_code; |
|
|
|
|
return 0; |
|
|
|
|
return GL_TRUE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//========================================================================
|
|
|
|
|
// Create the OpenGL context using legacy API
|
|
|
|
|
// Terminate GLX
|
|
|
|
|
//========================================================================
|
|
|
|
|
|
|
|
|
|
static void createLegacyContext(_GLFWwindow* window, |
|
|
|
|
const _GLFWwndconfig* wndconfig, |
|
|
|
|
GLXFBConfig fbconfig, |
|
|
|
|
GLXContext share) |
|
|
|
|
void _glfwTerminateOpenGL(void) |
|
|
|
|
{ |
|
|
|
|
if (_glfw.glx.SGIX_fbconfig) |
|
|
|
|
{ |
|
|
|
|
window->glx.context = |
|
|
|
|
_glfw.glx.CreateContextWithConfigSGIX(_glfw.x11.display, |
|
|
|
|
fbconfig, |
|
|
|
|
GLX_RGBA_TYPE, |
|
|
|
|
share, |
|
|
|
|
True); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
// Unload libGL.so if necessary
|
|
|
|
|
#ifdef _GLFW_DLOPEN_LIBGL |
|
|
|
|
if (_glfw.glx.libGL != NULL) |
|
|
|
|
{ |
|
|
|
|
window->glx.context = glXCreateNewContext(_glfw.x11.display, |
|
|
|
|
fbconfig, |
|
|
|
|
GLX_RGBA_TYPE, |
|
|
|
|
share, |
|
|
|
|
True); |
|
|
|
|
dlclose(_glfw.glx.libGL); |
|
|
|
|
_glfw.glx.libGL = NULL; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//========================================================================
|
|
|
|
|
// Create the OpenGL context
|
|
|
|
|
// Prepare for creation of the OpenGL context
|
|
|
|
|
//========================================================================
|
|
|
|
|
|
|
|
|
|
#define setGLXattrib(attribName, attribValue) \ |
|
|
|
|
{ \
|
|
|
|
|
attribs[index++] = attribName; \
|
|
|
|
|
attribs[index++] = attribValue; |
|
|
|
|
attribs[index++] = attribValue; \
|
|
|
|
|
assert(index < sizeof(attribs) / sizeof(attribs[0])); \
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int createContext(_GLFWwindow* window, |
|
|
|
|
const _GLFWwndconfig* wndconfig, |
|
|
|
|
GLXFBConfigID fbconfigID) |
|
|
|
|
int _glfwCreateContext(_GLFWwindow* window, |
|
|
|
|
const _GLFWwndconfig* wndconfig, |
|
|
|
|
const _GLFWfbconfig* fbconfig) |
|
|
|
|
{ |
|
|
|
|
int attribs[40]; |
|
|
|
|
GLXFBConfig* fbconfig; |
|
|
|
|
GLXFBConfig* native; |
|
|
|
|
GLXContext share = NULL; |
|
|
|
|
|
|
|
|
|
if (wndconfig->share) |
|
|
|
|
share = wndconfig->share->glx.context; |
|
|
|
|
|
|
|
|
|
// Retrieve the previously selected GLXFBConfig
|
|
|
|
|
// Find a suitable GLXFBConfig
|
|
|
|
|
{ |
|
|
|
|
int dummy, index = 0; |
|
|
|
|
int count, index = 0; |
|
|
|
|
|
|
|
|
|
setGLXattrib(GLX_DOUBLEBUFFER, True); |
|
|
|
|
setGLXattrib(GLX_X_RENDERABLE, True); |
|
|
|
|
|
|
|
|
|
if (fbconfig->redBits) |
|
|
|
|
setGLXattrib(GLX_RED_SIZE, fbconfig->redBits); |
|
|
|
|
if (fbconfig->greenBits) |
|
|
|
|
setGLXattrib(GLX_GREEN_SIZE, fbconfig->greenBits); |
|
|
|
|
if (fbconfig->blueBits) |
|
|
|
|
setGLXattrib(GLX_BLUE_SIZE, fbconfig->blueBits); |
|
|
|
|
if (fbconfig->alphaBits) |
|
|
|
|
setGLXattrib(GLX_BLUE_SIZE, fbconfig->alphaBits); |
|
|
|
|
|
|
|
|
|
if (fbconfig->depthBits) |
|
|
|
|
setGLXattrib(GLX_DEPTH_SIZE, fbconfig->depthBits); |
|
|
|
|
if (fbconfig->stencilBits) |
|
|
|
|
setGLXattrib(GLX_STENCIL_SIZE, fbconfig->stencilBits); |
|
|
|
|
|
|
|
|
|
if (fbconfig->auxBuffers) |
|
|
|
|
setGLXattrib(GLX_AUX_BUFFERS, fbconfig->auxBuffers); |
|
|
|
|
|
|
|
|
|
if (fbconfig->accumRedBits) |
|
|
|
|
setGLXattrib(GLX_ACCUM_RED_SIZE, fbconfig->accumRedBits); |
|
|
|
|
if (fbconfig->accumGreenBits) |
|
|
|
|
setGLXattrib(GLX_ACCUM_GREEN_SIZE, fbconfig->accumGreenBits); |
|
|
|
|
if (fbconfig->accumBlueBits) |
|
|
|
|
setGLXattrib(GLX_ACCUM_BLUE_SIZE, fbconfig->accumBlueBits); |
|
|
|
|
if (fbconfig->accumAlphaBits) |
|
|
|
|
setGLXattrib(GLX_ACCUM_BLUE_SIZE, fbconfig->accumAlphaBits); |
|
|
|
|
|
|
|
|
|
if (fbconfig->stereo) |
|
|
|
|
setGLXattrib(GLX_STEREO, True); |
|
|
|
|
|
|
|
|
|
if (_glfw.glx.ARB_multisample) |
|
|
|
|
{ |
|
|
|
|
if (fbconfig->samples) |
|
|
|
|
{ |
|
|
|
|
setGLXattrib(GLX_SAMPLE_BUFFERS_ARB, 1); |
|
|
|
|
setGLXattrib(GLX_SAMPLES_ARB, fbconfig->samples); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (_glfw.glx.ARB_framebuffer_sRGB) |
|
|
|
|
{ |
|
|
|
|
if (fbconfig->sRGB) |
|
|
|
|
setGLXattrib(GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, True); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
setGLXattrib(GLX_FBCONFIG_ID, (int) fbconfigID); |
|
|
|
|
setGLXattrib(None, None); |
|
|
|
|
|
|
|
|
|
if (_glfw.glx.SGIX_fbconfig) |
|
|
|
|
{ |
|
|
|
|
fbconfig = _glfw.glx.ChooseFBConfigSGIX(_glfw.x11.display, |
|
|
|
|
_glfw.x11.screen, |
|
|
|
|
attribs, |
|
|
|
|
&dummy); |
|
|
|
|
native = _glfw.glx.ChooseFBConfigSGIX(_glfw.x11.display, |
|
|
|
|
_glfw.x11.screen, |
|
|
|
|
attribs, |
|
|
|
|
&count); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
fbconfig = glXChooseFBConfig(_glfw.x11.display, |
|
|
|
|
_glfw.x11.screen, |
|
|
|
|
attribs, |
|
|
|
|
&dummy); |
|
|
|
|
native = glXChooseFBConfig(_glfw.x11.display, |
|
|
|
|
_glfw.x11.screen, |
|
|
|
|
attribs, |
|
|
|
|
&count); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (fbconfig == NULL) |
|
|
|
|
if (native == NULL) |
|
|
|
|
{ |
|
|
|
|
_glfwInputError(GLFW_PLATFORM_ERROR, |
|
|
|
|
"GLX: Failed to retrieve the selected GLXFBConfig"); |
|
|
|
|
"GLX: Failed to find a suitable GLXFBConfig"); |
|
|
|
|
return GL_FALSE; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -309,17 +352,17 @@ static int createContext(_GLFWwindow* window, |
|
|
|
|
if (_glfw.glx.SGIX_fbconfig) |
|
|
|
|
{ |
|
|
|
|
window->glx.visual = |
|
|
|
|
_glfw.glx.GetVisualFromFBConfigSGIX(_glfw.x11.display, *fbconfig); |
|
|
|
|
_glfw.glx.GetVisualFromFBConfigSGIX(_glfw.x11.display, *native); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
window->glx.visual = glXGetVisualFromFBConfig(_glfw.x11.display, |
|
|
|
|
*fbconfig); |
|
|
|
|
*native); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (window->glx.visual == NULL) |
|
|
|
|
{ |
|
|
|
|
XFree(fbconfig); |
|
|
|
|
XFree(native); |
|
|
|
|
|
|
|
|
|
_glfwInputError(GLFW_PLATFORM_ERROR, |
|
|
|
|
"GLX: Failed to retrieve visual for GLXFBConfig"); |
|
|
|
@ -332,6 +375,8 @@ static int createContext(_GLFWwindow* window, |
|
|
|
|
!_glfw.glx.ARB_create_context_profile || |
|
|
|
|
!_glfw.glx.EXT_create_context_es2_profile) |
|
|
|
|
{ |
|
|
|
|
XFree(native); |
|
|
|
|
|
|
|
|
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE, |
|
|
|
|
"GLX: OpenGL ES requested but " |
|
|
|
|
"GLX_EXT_create_context_es2_profile is unavailable"); |
|
|
|
@ -343,6 +388,8 @@ static int createContext(_GLFWwindow* window, |
|
|
|
|
{ |
|
|
|
|
if (!_glfw.glx.ARB_create_context) |
|
|
|
|
{ |
|
|
|
|
XFree(native); |
|
|
|
|
|
|
|
|
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE, |
|
|
|
|
"GLX: Forward compatibility requested but " |
|
|
|
|
"GLX_ARB_create_context_profile is unavailable"); |
|
|
|
@ -355,6 +402,8 @@ static int createContext(_GLFWwindow* window, |
|
|
|
|
if (!_glfw.glx.ARB_create_context || |
|
|
|
|
!_glfw.glx.ARB_create_context_profile) |
|
|
|
|
{ |
|
|
|
|
XFree(native); |
|
|
|
|
|
|
|
|
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE, |
|
|
|
|
"GLX: An OpenGL profile requested but " |
|
|
|
|
"GLX_ARB_create_context_profile is unavailable"); |
|
|
|
@ -428,7 +477,7 @@ static int createContext(_GLFWwindow* window, |
|
|
|
|
|
|
|
|
|
window->glx.context = |
|
|
|
|
_glfw.glx.CreateContextAttribsARB(_glfw.x11.display, |
|
|
|
|
*fbconfig, |
|
|
|
|
*native, |
|
|
|
|
share, |
|
|
|
|
True, |
|
|
|
|
attribs); |
|
|
|
@ -446,14 +495,14 @@ static int createContext(_GLFWwindow* window, |
|
|
|
|
wndconfig->glProfile == GLFW_OPENGL_NO_PROFILE && |
|
|
|
|
wndconfig->glForward == GL_FALSE) |
|
|
|
|
{ |
|
|
|
|
createLegacyContext(window, wndconfig, *fbconfig, share); |
|
|
|
|
window->glx.context = createLegacyContext(window, *native, share); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
createLegacyContext(window, wndconfig, *fbconfig, share); |
|
|
|
|
window->glx.context = createLegacyContext(window, *native, share); |
|
|
|
|
|
|
|
|
|
XFree(fbconfig); |
|
|
|
|
XFree(native); |
|
|
|
|
|
|
|
|
|
if (window->glx.context == NULL) |
|
|
|
|
{ |
|
|
|
@ -467,189 +516,6 @@ static int createContext(_GLFWwindow* window, |
|
|
|
|
#undef setGLXattrib |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
////// GLFW internal API //////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
//========================================================================
|
|
|
|
|
// Initialize GLX
|
|
|
|
|
//========================================================================
|
|
|
|
|
|
|
|
|
|
int _glfwInitOpenGL(void) |
|
|
|
|
{ |
|
|
|
|
#ifdef _GLFW_DLOPEN_LIBGL |
|
|
|
|
int i; |
|
|
|
|
char* libGL_names[ ] = |
|
|
|
|
{ |
|
|
|
|
"libGL.so", |
|
|
|
|
"libGL.so.1", |
|
|
|
|
"/usr/lib/libGL.so", |
|
|
|
|
"/usr/lib/libGL.so.1", |
|
|
|
|
NULL |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
for (i = 0; libGL_names[i] != NULL; i++) |
|
|
|
|
{ |
|
|
|
|
_glfw.glx.libGL = dlopen(libGL_names[i], RTLD_LAZY | RTLD_GLOBAL); |
|
|
|
|
if (_glfw.glx.libGL) |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!_glfw.glx.libGL) |
|
|
|
|
{ |
|
|
|
|
_glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to find libGL"); |
|
|
|
|
return GL_FALSE; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
// Check if GLX is supported on this display
|
|
|
|
|
if (!glXQueryExtension(_glfw.x11.display, |
|
|
|
|
&_glfw.glx.errorBase, |
|
|
|
|
&_glfw.glx.eventBase)) |
|
|
|
|
{ |
|
|
|
|
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: GLX support not found"); |
|
|
|
|
return GL_FALSE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!glXQueryVersion(_glfw.x11.display, |
|
|
|
|
&_glfw.glx.versionMajor, |
|
|
|
|
&_glfw.glx.versionMinor)) |
|
|
|
|
{ |
|
|
|
|
_glfwInputError(GLFW_API_UNAVAILABLE, |
|
|
|
|
"GLX: Failed to query GLX version"); |
|
|
|
|
return GL_FALSE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (_glfwPlatformExtensionSupported("GLX_EXT_swap_control")) |
|
|
|
|
{ |
|
|
|
|
_glfw.glx.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) |
|
|
|
|
_glfwPlatformGetProcAddress("glXSwapIntervalEXT"); |
|
|
|
|
|
|
|
|
|
if (_glfw.glx.SwapIntervalEXT) |
|
|
|
|
_glfw.glx.EXT_swap_control = GL_TRUE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (_glfwPlatformExtensionSupported("GLX_SGI_swap_control")) |
|
|
|
|
{ |
|
|
|
|
_glfw.glx.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) |
|
|
|
|
_glfwPlatformGetProcAddress("glXSwapIntervalSGI"); |
|
|
|
|
|
|
|
|
|
if (_glfw.glx.SwapIntervalSGI) |
|
|
|
|
_glfw.glx.SGI_swap_control = GL_TRUE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (_glfwPlatformExtensionSupported("GLX_MESA_swap_control")) |
|
|
|
|
{ |
|
|
|
|
_glfw.glx.SwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC) |
|
|
|
|
_glfwPlatformGetProcAddress("glXSwapIntervalMESA"); |
|
|
|
|
|
|
|
|
|
if (_glfw.glx.SwapIntervalMESA) |
|
|
|
|
_glfw.glx.MESA_swap_control = GL_TRUE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (_glfwPlatformExtensionSupported("GLX_SGIX_fbconfig")) |
|
|
|
|
{ |
|
|
|
|
_glfw.glx.GetFBConfigAttribSGIX = (PFNGLXGETFBCONFIGATTRIBSGIXPROC) |
|
|
|
|
_glfwPlatformGetProcAddress("glXGetFBConfigAttribSGIX"); |
|
|
|
|
_glfw.glx.ChooseFBConfigSGIX = (PFNGLXCHOOSEFBCONFIGSGIXPROC) |
|
|
|
|
_glfwPlatformGetProcAddress("glXChooseFBConfigSGIX"); |
|
|
|
|
_glfw.glx.CreateContextWithConfigSGIX = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) |
|
|
|
|
_glfwPlatformGetProcAddress("glXCreateContextWithConfigSGIX"); |
|
|
|
|
_glfw.glx.GetVisualFromFBConfigSGIX = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) |
|
|
|
|
_glfwPlatformGetProcAddress("glXGetVisualFromFBConfigSGIX"); |
|
|
|
|
|
|
|
|
|
if (_glfw.glx.GetFBConfigAttribSGIX && |
|
|
|
|
_glfw.glx.ChooseFBConfigSGIX && |
|
|
|
|
_glfw.glx.CreateContextWithConfigSGIX && |
|
|
|
|
_glfw.glx.GetVisualFromFBConfigSGIX) |
|
|
|
|
{ |
|
|
|
|
_glfw.glx.SGIX_fbconfig = GL_TRUE; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (_glfwPlatformExtensionSupported("GLX_ARB_multisample")) |
|
|
|
|
_glfw.glx.ARB_multisample = GL_TRUE; |
|
|
|
|
|
|
|
|
|
if (_glfwPlatformExtensionSupported("GLX_ARB_framebuffer_sRGB")) |
|
|
|
|
_glfw.glx.ARB_framebuffer_sRGB = GL_TRUE; |
|
|
|
|
|
|
|
|
|
if (_glfwPlatformExtensionSupported("GLX_ARB_create_context")) |
|
|
|
|
{ |
|
|
|
|
_glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) |
|
|
|
|
_glfwPlatformGetProcAddress("glXCreateContextAttribsARB"); |
|
|
|
|
|
|
|
|
|
if (_glfw.glx.CreateContextAttribsARB) |
|
|
|
|
_glfw.glx.ARB_create_context = GL_TRUE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_robustness")) |
|
|
|
|
_glfw.glx.ARB_create_context_robustness = GL_TRUE; |
|
|
|
|
|
|
|
|
|
if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_profile")) |
|
|
|
|
_glfw.glx.ARB_create_context_profile = GL_TRUE; |
|
|
|
|
|
|
|
|
|
if (_glfwPlatformExtensionSupported("GLX_EXT_create_context_es2_profile")) |
|
|
|
|
_glfw.glx.EXT_create_context_es2_profile = GL_TRUE; |
|
|
|
|
|
|
|
|
|
return GL_TRUE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//========================================================================
|
|
|
|
|
// Terminate GLX
|
|
|
|
|
//========================================================================
|
|
|
|
|
|
|
|
|
|
void _glfwTerminateOpenGL(void) |
|
|
|
|
{ |
|
|
|
|
// Unload libGL.so if necessary
|
|
|
|
|
#ifdef _GLFW_DLOPEN_LIBGL |
|
|
|
|
if (_glfw.glx.libGL != NULL) |
|
|
|
|
{ |
|
|
|
|
dlclose(_glfw.glx.libGL); |
|
|
|
|
_glfw.glx.libGL = NULL; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//========================================================================
|
|
|
|
|
// Prepare for creation of the OpenGL context
|
|
|
|
|
//========================================================================
|
|
|
|
|
|
|
|
|
|
int _glfwCreateContext(_GLFWwindow* window, |
|
|
|
|
const _GLFWwndconfig* wndconfig, |
|
|
|
|
const _GLFWfbconfig* fbconfig) |
|
|
|
|
{ |
|
|
|
|
_GLFWfbconfig closest; |
|
|
|
|
|
|
|
|
|
// Choose the best available fbconfig
|
|
|
|
|
{ |
|
|
|
|
unsigned int fbcount; |
|
|
|
|
_GLFWfbconfig* fbconfigs; |
|
|
|
|
const _GLFWfbconfig* result; |
|
|
|
|
|
|
|
|
|
fbconfigs = getFBConfigs(window, &fbcount); |
|
|
|
|
if (!fbconfigs) |
|
|
|
|
return GL_FALSE; |
|
|
|
|
|
|
|
|
|
result = _glfwChooseFBConfig(fbconfig, fbconfigs, fbcount); |
|
|
|
|
if (!result) |
|
|
|
|
{ |
|
|
|
|
_glfwInputError(GLFW_PLATFORM_ERROR, |
|
|
|
|
"GLX: No GLXFBConfig matched the criteria"); |
|
|
|
|
|
|
|
|
|
free(fbconfigs); |
|
|
|
|
return GL_FALSE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
closest = *result; |
|
|
|
|
free(fbconfigs); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return createContext(window, wndconfig, closest.platformID); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//========================================================================
|
|
|
|
|
// Destroy the OpenGL context
|
|
|
|
|
//========================================================================
|
|
|
|
|