diff options
Diffstat (limited to 'intern/ghost/intern/GHOST_ContextGLX.cpp')
-rw-r--r-- | intern/ghost/intern/GHOST_ContextGLX.cpp | 120 |
1 files changed, 114 insertions, 6 deletions
diff --git a/intern/ghost/intern/GHOST_ContextGLX.cpp b/intern/ghost/intern/GHOST_ContextGLX.cpp index 02b43abec6c..90d810b7986 100644 --- a/intern/ghost/intern/GHOST_ContextGLX.cpp +++ b/intern/ghost/intern/GHOST_ContextGLX.cpp @@ -40,6 +40,13 @@ #include <cstdio> #include <cstring> +/* needed for intel drivers (works w/ mesa-swrast & nvidia) */ +#define USE_GLXEW_INIT_WORKAROUND + +#ifdef USE_GLXEW_INIT_WORKAROUND +static GLuint _glewStrLen(const GLubyte *s); +static GLboolean _glewSearchExtension(const char *name, const GLubyte *start, const GLubyte *end); +#endif #ifdef WITH_GLEW_MX GLXEWContext *glxewContext = NULL; @@ -87,7 +94,7 @@ GHOST_ContextGLX::~GHOST_ContextGLX() if (m_context != None) { if (m_window != 0 && m_context == ::glXGetCurrentContext()) - ::glXMakeCurrent(m_display, m_window, NULL); + ::glXMakeCurrent(m_display, None, NULL); if (m_context != s_sharedContext || s_sharedCount == 1) { assert(s_sharedCount > 0); @@ -154,10 +161,54 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext() XIOErrorHandler old_handler_io = XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler); #endif - /* needed so 'GLXEW_ARB_create_context' is valid */ - mxIgnoreNoVersion(1); - initContextGLXEW(); - mxIgnoreNoVersion(0); + + + /* -------------------------------------------------------------------- */ + /* Begin Inline Glew */ + +#ifdef USE_GLXEW_INIT_WORKAROUND + const GLubyte *extStart = (GLubyte *)""; + const GLubyte *extEnd; + if (glXQueryExtension(m_display, NULL, NULL)) { + extStart = (const GLubyte *)glXGetClientString(m_display, GLX_EXTENSIONS); + if ((extStart == NULL) || + (glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)glXGetProcAddressARB( + (const GLubyte *)"glXChooseFBConfig")) == NULL || + (glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddressARB( + (const GLubyte *)"glXCreateContextAttribsARB")) == NULL) + { + extStart = (GLubyte *)""; + } + } + extEnd = extStart + _glewStrLen(extStart); + +#undef GLXEW_ARB_create_context + const bool GLXEW_ARB_create_context = + _glewSearchExtension("GLX_ARB_create_context", extStart, extEnd); +#undef GLXEW_ARB_create_context_profile + const bool GLXEW_ARB_create_context_profile = + _glewSearchExtension("GLX_ARB_create_context_profile", extStart, extEnd); +#undef GLXEW_ARB_create_context_robustness +const bool GLXEW_ARB_create_context_robustness = + _glewSearchExtension("GLX_ARB_create_context_robustness", extStart, extEnd); +#ifdef WITH_GLEW_ES +#undef GLXEW_EXT_create_context_es_profile + const bool GLXEW_EXT_create_context_es_profile = + _glewSearchExtension("GLX_EXT_create_context_es_profile", extStart, extEnd); +#undef GLXEW_EXT_create_context_es2_profile + const bool GLXEW_EXT_create_context_es2_profile = + _glewSearchExtension("GLX_EXT_create_context_es2_profile", extStart, extEnd); +#endif /* WITH_GLEW_ES */ + + /* End Inline Glew */ + /* -------------------------------------------------------------------- */ +#else + /* important to initialize only glxew (_not_ glew), + * since this breaks w/ Mesa's `swrast`, see: T46431 */ + glxewInit(); +#endif /* USE_GLXEW_INIT_WORKAROUND */ + + if (GLXEW_ARB_create_context) { int profileBitCore = m_contextProfileMask & GLX_CONTEXT_CORE_PROFILE_BIT_ARB; @@ -257,6 +308,8 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext() GHOST_TSuccess success; if (m_context != NULL) { + const unsigned char *version; + if (!s_sharedContext) s_sharedContext = m_context; @@ -264,13 +317,26 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext() glXMakeCurrent(m_display, m_window, m_context); + // Seems that this has to be called after MakeCurrent, + // which means we cannot use glX extensions until after we create a context + initContextGLXEW(); + initClearGL(); ::glXSwapBuffers(m_display, m_window); /* re initialize to get the extensions properly */ initContextGLXEW(); - success = GHOST_kSuccess; + version = glGetString(GL_VERSION); + + if (!version || version[0] < '2' || ((version[0] == '2') && (version[2] < '1'))) { + fprintf(stderr, "Error! Blender requires OpenGL 2.1 to run. Try updating your drivers.\n"); + fflush(stderr); + /* ugly, but we get crashes unless a whole bunch of systems are patched. */ + exit(0); + } + else + success = GHOST_kSuccess; } else { /* freeing well clean up the context initialized above */ @@ -409,3 +475,45 @@ int GHOST_X11_GL_GetAttributes( return i; } + + +/* excuse inlining part of glew */ +#ifdef USE_GLXEW_INIT_WORKAROUND +static GLuint _glewStrLen(const GLubyte *s) +{ + GLuint i = 0; + if (s == NULL) return 0; + while (s[i] != '\0') i++; + return i; +} + +static GLuint _glewStrCLen(const GLubyte *s, GLubyte c) +{ + GLuint i = 0; + if (s == NULL) return 0; + while (s[i] != '\0' && s[i] != c) i++; + return (s[i] == '\0' || s[i] == c) ? i : 0; +} + +static GLboolean _glewStrSame(const GLubyte *a, const GLubyte *b, GLuint n) +{ + GLuint i = 0; + if (a == NULL || b == NULL) + return (a == NULL && b == NULL && n == 0) ? GL_TRUE : GL_FALSE; + while (i < n && a[i] != '\0' && b[i] != '\0' && a[i] == b[i]) i++; + return i == n ? GL_TRUE : GL_FALSE; +} + +static GLboolean _glewSearchExtension(const char *name, const GLubyte *start, const GLubyte *end) +{ + const GLubyte *p; + GLuint len = _glewStrLen((const GLubyte *)name); + p = start; + while (p < end) { + GLuint n = _glewStrCLen(p, ' '); + if (len == n && _glewStrSame((const GLubyte *)name, p, n)) return GL_TRUE; + p += n + 1; + } + return GL_FALSE; +} +#endif /* USE_GLXEW_INIT_WORKAROUND */ |