X-Git-Url: https://git.ralfj.de/gltest.git/blobdiff_plain/aa8d6f63cc3b8ce1d8c7473ab59bbc2b2f92010c..ce1b46da645fdcac80fc9c71082bb5cb40166576:/glxbackend.cpp diff --git a/glxbackend.cpp b/glxbackend.cpp index 7841bbe..e40e90c 100644 --- a/glxbackend.cpp +++ b/glxbackend.cpp @@ -1,4 +1,23 @@ +/* gltest - small OpenGL tearing test program + * Copyright (C) 2012-2013 Ralf Jung + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + #include "glxbackend.h" +#include "glutil.h" #include #include @@ -6,17 +25,32 @@ #include #include -/* attributes for a double buffered visual in RGBA format with at least -* 4 bits per color */ -static int attrList[] = -{ - GLX_RGBA, GLX_DOUBLEBUFFER, - GLX_RED_SIZE, 4, - GLX_GREEN_SIZE, 4, +#if !defined(CON_GL1) && !defined(CON_GL3) +#error "Valid GL contexts for GLX are: GL1, GL3" +#endif + +// attributes for a double buffered framebuffer in RGBA format with at least 4 bits per color +static int configAttribs[] = +{ + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_DOUBLEBUFFER, True, + GLX_RED_SIZE, 4, + GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, - None + None }; +#ifdef CON_GL3 +// attributes for a GL3 context +static int contextAttribs[] = +{ + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 0, + GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, + None +}; +#endif + VisualID GLXBackend::initialize(Display *display) { if (this->display == NULL) { // this implies that the context is also unitialized @@ -24,27 +58,47 @@ VisualID GLXBackend::initialize(Display *display) // debugging: show version information int glxMajor, glxMinor; glXQueryVersion(display, &glxMajor, &glxMinor); - printf("Using GLX version %d.%d\n", glxMajor, glxMinor); - // check for swap control functions - const char *extensions = glXQueryExtensionsString(display, DefaultScreen(display)); - if (std::string(extensions).find("GLX_MESA_swap_control") != std::string::npos) { - funSwapIntervalMesa = (PFNGLXSWAPINTERVALMESAPROC)glXGetProcAddress((const GLubyte*)"glXSwapIntervalMESA"); - if (funSwapIntervalMesa) printf("glXSwapIntervalMESA is present\n"); - } - else { - funSwapIntervalMesa = 0; + printf("Using GLX version: %d.%d\n", glxMajor, glxMinor); + if (glxMajor < 1 || (glxMajor == 1 && glxMinor < 3)) { + // glXChooseFBConfig and glXCreateNewContext require GLX 1.3 + fprintf(stderr, "Need at least GLX 1.3 to function properly\n"); + exit(1); } - if (std::string(extensions).find("GLX_EXT_swap_control") != std::string::npos) { - funSwapIntervalExt = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddress((const GLubyte*)"glXSwapIntervalEXT"); - if (funSwapIntervalExt) printf("glXSwapIntervalEXT is present\n"); + // check for extension-based functions + funSwapIntervalMesa = (PFNGLXSWAPINTERVALMESAPROC)resolveGLXFunction("GLX_MESA_swap_control", "glXSwapIntervalMESA"); + funSwapIntervalExt = (PFNGLXSWAPINTERVALEXTPROC)resolveGLXFunction("GLX_EXT_swap_control", "glXSwapIntervalEXT"); + funCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)resolveGLXFunction("GLX_ARB_create_context", "glXCreateContextAttribsARB"); + // get the first usable framebuffer configuration + int count = 0; + GLXFBConfig *configs = glXChooseFBConfig(display, DefaultScreen(display), configAttribs, &count); + if (count < 1) { + fprintf(stderr, "Failed to choose framebuffer configuration\n"); + exit(1); } - else { - funSwapIntervalExt = 0; - } - // get the visual - vi = glXChooseVisual(display, DefaultScreen(display), attrList); + config = configs[0]; + XFree(configs); } - return vi->visualid; + // return visual ID + XVisualInfo *vi = glXGetVisualFromFBConfig(display, config); + VisualID visualid = vi->visualid; + XFree(vi); + return visualid; +} + +bool GLXBackend::haveGLXExtension(const std::string &name) +{ + assert(display != NULL); + std::string extensions = glXQueryExtensionsString(display, DefaultScreen(display)); + return (std::string(" "+extensions+" ").find(" "+name+" ") != std::string::npos); +} + +T_proc GLXBackend::resolveGLXFunction(const char *extension, const char *function) +{ + if (!haveGLXExtension(extension)) return NULL; + T_proc f = glXGetProcAddress((const GLubyte*)function); + if (f) + printf("%s is supported, using it for %s\n", extension, function); + return f; } void GLXBackend::createContext(Window window) @@ -52,9 +106,24 @@ void GLXBackend::createContext(Window window) assert(display != NULL && context == None); this->window = window; // create context with that window - context = glXCreateContext(display, vi, 0, GL_TRUE); +#ifdef CON_GL1 + context = glXCreateNewContext(display, config, GLX_RGBA_TYPE, NULL, GL_TRUE); +#else + if (!funCreateContextAttribsARB) { + fprintf(stderr, "Cannot create GL3 context: GLX_ARB_create_context not supported\n"); + exit(1); + } + context = funCreateContextAttribsARB(display, config, NULL, GL_TRUE, contextAttribs); +#endif + if (!context) { + fprintf(stderr, "Error creating context\n"); + exit(1); + } glXMakeCurrent(display, window, context); assert(glXIsDirect(display, context)); + printf("Using GL version: %s\n", glGetString(GL_VERSION)); + // initialise GL utilities + resolveFunctionPointers((T_glGetProcAddress)glXGetProcAddress); } GLXBackend::~GLXBackend() @@ -64,7 +133,6 @@ GLXBackend::~GLXBackend() glXMakeCurrent(display, None, NULL); glXDestroyContext(display, context); } - XFree(vi); } } @@ -77,12 +145,18 @@ void GLXBackend::swapBuffers() const void GLXBackend::setSwapInterval(int i) const { assert(context != None); + // check if swap interval value is supported + if (i < 0) { + fprintf(stderr, "Cannot set swap interval to %d, must not be negative\n", i); + exit(1); + } + // set it if (funSwapIntervalExt) funSwapIntervalExt(display, window, i); else if (funSwapIntervalMesa) funSwapIntervalMesa(i); else { - fprintf(stderr, "At least one of glXSwapIntervalMESA, glXSwapIntervalEXT must be provided by the system\n"); + fprintf(stderr, "At least one of GLX_EXT_swap_control, GLX_MESA_swap_control must be supported by the system\n"); abort(); } }