diff --git a/Modules/opengl/opengl.cpp b/Modules/opengl/opengl.cpp --- a/Modules/opengl/opengl.cpp +++ b/Modules/opengl/opengl.cpp @@ -122,6 +122,65 @@ return newItem(parent, NULL, textCol1, textCol2); } +#if KCM_HAVE_GLX +static const int coreProfileCtxAttribs[][7] = { + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 4, + GLX_CONTEXT_MINOR_VERSION_ARB, 5, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + None + }, + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 4, + GLX_CONTEXT_MINOR_VERSION_ARB, 4, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + None + }, + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 4, + GLX_CONTEXT_MINOR_VERSION_ARB, 3, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + None + }, + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 4, + GLX_CONTEXT_MINOR_VERSION_ARB, 2, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + None + }, + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 4, + GLX_CONTEXT_MINOR_VERSION_ARB, 1, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + None + }, + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 4, + GLX_CONTEXT_MINOR_VERSION_ARB, 0, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + None + }, + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 3, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + None + }, + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 2, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + None + }, + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 1, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, /* Ignored in this case but specified to keep the size same */ + None + } +}; +#endif + static bool IsDirect; static struct glinfo { @@ -142,6 +201,7 @@ const char *glVendor; const char *glRenderer; const char *glVersion; + const char *glVersionCoreProfile; const char *glExtensions; #if KCM_HAVE_GLX const char *gluVersion; @@ -588,6 +648,9 @@ l3 = newItem(l2, l3, i18n("OpenGL ES version"), gli.glVersion); #else l3 = newItem(l2, l3, i18n("OpenGL version"), gli.glVersion); + if (gli.glVersionCoreProfile) { + l3 = newItem(l2, l3, i18n("OpenGL version (core profile)"), gli.glVersionCoreProfile); + } #endif if (IsDirect) { @@ -652,6 +715,69 @@ #endif #if KCM_HAVE_GLX +static void get_gl_core_profile_glx(GLXContext &ctx, GLXFBConfig *&fbc, Display *dpy, int scrnum, Window win) +{ + typedef GLXContext (*glXCreateContextAttribsARBProc)(Display *, GLXFBConfig, GLXContext, Bool, const int *); + static const QString extName("GLX_ARB_create_context"); + static const int fbcAttrib[] = { + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + None }; + glXCreateContextAttribsARBProc glXCreateContextAttribsARB; + int glxMajor; + int glxMinor; + int fbcElems; + + gli.glVersionCoreProfile = NULL; + + if (!glXQueryVersion(dpy, &glxMajor, &glxMinor)) { + qDebug() << "Error: glXQueryVersion failed\n"; + return; + } + + if ((glxMajor < 1) || (glxMajor == 1 && glxMinor < 4)) { + qDebug() << "Error: At least GLX 1.4 is required to query OpenGL core profiles\n"; + return; + } + + if (!QString(gli.glxExtensions).contains(extName) || !QString(gli.serverExtensions).contains(extName)) { + qDebug() << "Error:" << extName << "extension is not supported\n"; + return; + } + + glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddressARB((const GLubyte *) "glXCreateContextAttribsARB"); + if (!glXCreateContextAttribsARB) { + qDebug() << "Error: Failed to retrieve glXCreateContextAttribsARB\n"; + return; + } + + fbc = glXChooseFBConfig(dpy, scrnum, fbcAttrib, &fbcElems); + if (!fbc) { + qDebug() << "Error: glXChooseFBConfig failed\n"; + return; + } + + size_t idx; + size_t end = sizeof(coreProfileCtxAttribs) / sizeof(coreProfileCtxAttribs[0]); + for (idx = 0; idx < end; idx++) { + const int *attribs = coreProfileCtxAttribs[idx]; + ctx = glXCreateContextAttribsARB(dpy, *fbc, NULL, IsDirect, attribs); + if (ctx) { + break; + } + } + if (idx == end) { + qDebug() << "Error: glXCreateContextAttribsARB failed\n"; + return; + } + + if (glXMakeCurrent(dpy, win, ctx)) { + gli.glVersionCoreProfile = (const char *) glGetString(GL_VERSION); + } else { + qDebug() << "Error: glXMakeCurrent failed for core profile\n"; + } +} static QTreeWidgetItem *get_gl_info_glx(Display *dpy, int scrnum, Bool allowDirect, QTreeWidgetItem *l1, QTreeWidgetItem *after) { Window win; @@ -659,6 +785,8 @@ unsigned long mask; Window root; XVisualInfo *visinfo; + GLXContext ctxCoreProf = NULL; + GLXFBConfig *fbcCoreProf = NULL; int width = 100, height = 100; QTreeWidgetItem *result = after; @@ -721,13 +849,21 @@ gli.gluExtensions = (const char *) gluGetString(GLU_EXTENSIONS); IsDirect = glXIsDirect(dpy, ctx); - - result = print_screen_info(l1, after, IsDirect ? i18n("Direct Rendering (GLX)") : i18n("Indirect Rendering (GLX)")); } else { qDebug() << "Error: glXMakeCurrent failed\n"; } + get_gl_core_profile_glx(ctxCoreProf, fbcCoreProf, dpy, scrnum, win); + + result = print_screen_info(l1, after, IsDirect ? i18n("Direct Rendering (GLX)") : i18n("Indirect Rendering (GLX)")); + + if (ctxCoreProf) { + glXDestroyContext(dpy, ctxCoreProf); + } + if (fbcCoreProf) { + XFree(fbcCoreProf); + } glXDestroyContext(dpy, ctx); XDestroyWindow(dpy, win); return result;