X-Git-Url: https://git.ralfj.de/gltest.git/blobdiff_plain/aa4575e1aa768daff8ca10c7a8a06aa0603e998f..HEAD:/eglbackend.cpp?ds=sidebyside diff --git a/eglbackend.cpp b/eglbackend.cpp index 359d54a..47e0384 100644 --- a/eglbackend.cpp +++ b/eglbackend.cpp @@ -1,11 +1,33 @@ +/* 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 "eglbackend.h" +#include "glutil.h" -#include #include #include #include +#if !defined(CON_GL1) && !defined(CON_GL3) && !defined(CON_GLES2) +#error "Valid GL contexts for EGL are: GL1, GL3, GLES2" +#endif + static const char *eglErrorToString(EGLint e) { #define CASE(name) case name: return #name @@ -24,22 +46,33 @@ static const char *eglErrorToString(EGLint e) #undef CASE } -static void exitEglError(const char *what) +static void dieEgl(const char *what) { EGLint e = eglGetError(); - fprintf(stderr, "EGL error %d (%s): %s\n", e, eglErrorToString(e), what); - exit(1); + die("EGL error %d (%s): %s\n", e, eglErrorToString(e), what); } -/* attributes for a double buffered visual in RGBA format with at least -* 4 bits per color */ -static const EGLint config_attribs[] = { +static const EGLint configAttribs[] = { EGL_RED_SIZE, 4, EGL_GREEN_SIZE, 4, EGL_BLUE_SIZE, 4, +#ifdef CON_GLES2 + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, +#else EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, +#endif EGL_NONE, }; +static const EGLint contextAttribs[] = { +#ifdef CON_GLES2 + EGL_CONTEXT_CLIENT_VERSION, 2, +#elif CON_GL3 + EGL_CONTEXT_MAJOR_VERSION_KHR, 3, + EGL_CONTEXT_MINOR_VERSION_KHR, 0, + EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR, +#endif + EGL_NONE +}; VisualID EGLBackend::initialize(Display *xDisplay) { @@ -47,17 +80,36 @@ VisualID EGLBackend::initialize(Display *xDisplay) // get connection and bind API EGLint eglMajor, eglMinor; display = eglGetDisplay(xDisplay); - if (display == EGL_NO_DISPLAY) - exitEglError("Failed to get EGL display"); - if (eglInitialize(display, &eglMajor, &eglMinor) == EGL_FALSE) - exitEglError("Failed to initialize EGL"); - printf("Using EGL version %d.%d\n", eglMajor, eglMinor); - eglBindAPI(EGL_OPENGL_API); + if (display == EGL_NO_DISPLAY) + dieEgl("Failed to get EGL display"); + if (eglInitialize(display, &eglMajor, &eglMinor) == EGL_FALSE) + dieEgl("Failed to initialize EGL"); + printf("Using EGL version: %d.%d\n", eglMajor, eglMinor); + if (eglMajor == 1 && eglMinor < 4) { + // Choosing the GL context version requires EGL 1.3, creating an OpenGL 3 context requires EGL 1.4 + die("Need at least EGL 1.4 to function properly\n"); + } +#ifdef CON_GLES2 + if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) +#else + if (eglBindAPI(EGL_OPENGL_API) == EGL_FALSE) +#endif + dieEgl("Failed to bind API"); + // check for the extension we need +#ifdef CON_GL3 + if (!haveEGLExtension("EGL_KHR_create_context")) { + die("Required EGL extension EGL_KHR_create_context is not supported\n"); + } +#endif // get an appropriate config EGLConfig configs[1]; EGLint count; - if (eglChooseConfig(display, config_attribs, configs, 1, &count) == EGL_FALSE || count == 0) - exitEglError("Failed to choose config"); + if (eglChooseConfig(display, configAttribs, configs, 1, &count) == EGL_FALSE){ + dieEgl("Failed to choose framebuffer configuration"); + } + if (count == 0) { + die("Found no matching framebuffer configuration\n"); + } config = configs[0]; } // return visual ID @@ -66,16 +118,26 @@ VisualID EGLBackend::initialize(Display *xDisplay) return (VisualID)val; } +bool EGLBackend::haveEGLExtension(const std::string &name) +{ + assert(display != EGL_NO_DISPLAY); + std::string extensions = eglQueryString(display, EGL_EXTENSIONS); + return (std::string(" "+extensions+" ").find(" "+name+" ") != std::string::npos); +} + void EGLBackend::createContext(Window window) { assert(display != EGL_NO_DISPLAY && context == EGL_NO_CONTEXT); surface = eglCreateWindowSurface(display, config, window, NULL); - /* create an EGL context and use it with the surface */ - context = eglCreateContext(display, config, EGL_NO_CONTEXT, NULL); + // create an EGL context and use it with the surface + context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs); if (context == EGL_NO_CONTEXT) - exitEglError("Failed to create context"); + dieEgl("Failed to create context"); if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) - exitEglError("Failed to make context current"); + dieEgl("Failed to make context current"); + printf("Using GL version: %s\n", glGetString(GL_VERSION)); + // initialise GL utilities + resolveFunctionPointers(eglGetProcAddress); } EGLBackend::~EGLBackend() @@ -94,11 +156,23 @@ EGLBackend::~EGLBackend() void EGLBackend::swapBuffers() const { assert(context != EGL_NO_CONTEXT); // this implies the display is also initialized - eglSwapBuffers(display, surface); + if (eglSwapBuffers(display, surface) == EGL_FALSE) + dieEgl("Failed to swap buffers"); } void EGLBackend::setSwapInterval(int i) const { assert(context != EGL_NO_CONTEXT); - eglSwapInterval(display, i); + // check if swap interval value is supported + if (i < 0) { + die("Cannot set swap interval to %d, must not be negative\n", i); + } + EGLint val; + eglGetConfigAttrib(display, config, EGL_MAX_SWAP_INTERVAL, &val); + if (i > val) { + die("Cannot set swap interval to %d, maximum supported value is %d\n", i, val); + } + // use it + if (eglSwapInterval(display, i) == EGL_FALSE) + dieEgl("Failed to set swap interval"); }