From 9fd15b13acef0cf8a5ff45bd1470a6b1a56e0846 Mon Sep 17 00:00:00 2001 From: Jesse Barker Date: Tue, 13 Nov 2012 08:53:41 -0800 Subject: EGLState: Consolidate all EGL interactions into a separate object. This cleans up the canvas implementation and paves the way for additional window system integrations (raw KMS device, Wayland, etc.). --- src/egl-state.cpp | 550 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/egl-state.h | 130 +++++++++++++ src/wscript_build | 5 +- 3 files changed, 683 insertions(+), 2 deletions(-) create mode 100644 src/egl-state.cpp create mode 100644 src/egl-state.h diff --git a/src/egl-state.cpp b/src/egl-state.cpp new file mode 100644 index 0000000..b045962 --- /dev/null +++ b/src/egl-state.cpp @@ -0,0 +1,550 @@ +// +// Copyright © 2012 Linaro Limited +// +// This file is part of the glmark2 OpenGL (ES) 2.0 benchmark. +// +// glmark2 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 3 of the License, or (at your option) any later +// version. +// +// glmark2 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 +// glmark2. If not, see . +// +// Authors: +// Jesse Barker +// +#include "egl-state.h" +#include "log.h" +#include "options.h" +#include "limits.h" +#include +#include + +using std::vector; +using std::string; + +EglConfig::EglConfig(EGLDisplay dpy, EGLConfig config) : + handle_(config), + bufferSize_(0), + redSize_(0), + greenSize_(0), + blueSize_(0), + luminanceSize_(0), + alphaSize_(0), + alphaMaskSize_(0), + bufferType_(EGL_RGB_BUFFER), + caveat_(0), + configID_(0), + depthSize_(0), + nativeID_(0), + nativeType_(0), + nativeRenderable_(false), + sampleBuffers_(0), + samples_(0), + stencilSize_(0), + surfaceType_(0), + xparentType_(0), + xparentRedValue_(0), + xparentGreenValue_(0), + xparentBlueValue_(0) +{ + vector badAttribVec; + if (!eglGetConfigAttrib(dpy, handle_, EGL_CONFIG_ID, &configID_)) + { + badAttribVec.push_back("EGL_CONFIG_ID"); + } + if (!eglGetConfigAttrib(dpy, handle_, EGL_CONFIG_CAVEAT, &caveat_)) + { + badAttribVec.push_back("EGL_CONFIG_CAVEAT"); + } + if (!eglGetConfigAttrib(dpy, handle_, EGL_COLOR_BUFFER_TYPE, &bufferType_)) + { + badAttribVec.push_back("EGL_COLOR_BUFFER_TYPE"); + } + if (!eglGetConfigAttrib(dpy, handle_, EGL_BUFFER_SIZE, &bufferSize_)) + { + badAttribVec.push_back("EGL_BUFFER_SIZE"); + } + + if (bufferType_ == EGL_RGB_BUFFER) + { + if (!eglGetConfigAttrib(dpy, handle_, EGL_RED_SIZE, &redSize_)) + { + badAttribVec.push_back("EGL_RED_SIZE"); + } + if (!eglGetConfigAttrib(dpy, handle_, EGL_GREEN_SIZE, &greenSize_)) + { + badAttribVec.push_back("EGL_GREEN_SIZE"); + } + if (!eglGetConfigAttrib(dpy, handle_, EGL_BLUE_SIZE, &blueSize_)) + { + badAttribVec.push_back("EGL_BLUE_SIZE"); + } + } + else + { + if (!eglGetConfigAttrib(dpy, handle_, EGL_LUMINANCE_SIZE, &luminanceSize_)) + { + badAttribVec.push_back("EGL_LUMINANCE_SIZE"); + } + } + if (!eglGetConfigAttrib(dpy, handle_, EGL_ALPHA_SIZE, &alphaSize_)) + { + badAttribVec.push_back("EGL_ALPHA_SIZE"); + } + if (!eglGetConfigAttrib(dpy, handle_, EGL_DEPTH_SIZE, &depthSize_)) + { + badAttribVec.push_back("EGL_DEPTH_SIZE"); + } + if (!eglGetConfigAttrib(dpy, handle_, EGL_STENCIL_SIZE, &stencilSize_)) + { + badAttribVec.push_back("EGL_STENCIL_SIZE"); + } + EGLint doNative(EGL_FALSE); + if (!eglGetConfigAttrib(dpy, handle_, EGL_NATIVE_RENDERABLE, &doNative)) + { + badAttribVec.push_back("EGL_NATIVE_RENDERABLE"); + } + if (doNative == EGL_TRUE) + { + nativeRenderable_ = true; + } + if (!eglGetConfigAttrib(dpy, handle_, EGL_NATIVE_VISUAL_TYPE, &nativeType_)) + { + badAttribVec.push_back("EGL_NATIVE_VISUAL_TYPE"); + } + if (!eglGetConfigAttrib(dpy, handle_, EGL_NATIVE_VISUAL_ID, &nativeID_)) + { + badAttribVec.push_back("EGL_NATIVE_VISUAL_ID"); + } + if (!eglGetConfigAttrib(dpy, handle_, EGL_SURFACE_TYPE, &surfaceType_)) + { + badAttribVec.push_back("EGL_SURFACE_TYPE"); + } + if (!eglGetConfigAttrib(dpy, handle_, EGL_SAMPLE_BUFFERS, &sampleBuffers_)) + { + badAttribVec.push_back("EGL_SAMPLE_BUFFERS"); + } + if (sampleBuffers_) + { + if (!eglGetConfigAttrib(dpy, handle_, EGL_SAMPLES, &samples_)) + { + badAttribVec.push_back("EGL_SAMPLES"); + } + } + if (!eglGetConfigAttrib(dpy, handle_, EGL_TRANSPARENT_TYPE, &xparentType_)) + { + badAttribVec.push_back("EGL_TRANSPARENT_TYPE"); + } + //if (xparentType_ != EGL_NONE) + { + if (!eglGetConfigAttrib(dpy, handle_, EGL_TRANSPARENT_RED_VALUE, &xparentRedValue_)) + { + badAttribVec.push_back("EGL_TRANSPARENT_RED_VALUE"); + } + if (!eglGetConfigAttrib(dpy, handle_, EGL_TRANSPARENT_GREEN_VALUE, &xparentGreenValue_)) + { + badAttribVec.push_back("EGL_TRANSPARENT_GREEN_VALUE"); + } + if (!eglGetConfigAttrib(dpy, handle_, EGL_TRANSPARENT_BLUE_VALUE, &xparentBlueValue_)) + { + badAttribVec.push_back("EGL_TRANSPARENT_BLUE_VALUE"); + } + } + + if (!badAttribVec.empty()) + { + Log::error("Failed to get the following config attributes for config 0x%x:\n", + config); + for (vector::const_iterator attribIt = badAttribVec.begin(); + attribIt != badAttribVec.end(); + attribIt++) + { + Log::error("%s\n", attribIt->c_str()); + } + } +} + +void +EglConfig::print_header() +{ + Log::debug("\n"); + Log::debug(" cfg buf rgb colorbuffer dp st config native support surface sample\n"); + Log::debug(" id sz lum r g b a th cl caveat render type id type buf ns\n"); + Log::debug("------------------------------------------------------------------------\n"); +} + +void +EglConfig::print() const +{ + std::ostringstream s; + s << std::setw(5) << "0x" << std::hex << configID_; + s << " " << std::dec << bufferSize_ << " "; + if (bufferType_ == EGL_RGB_BUFFER) + { + s << "rgb"; + s << " " << redSize_; + s << " " << greenSize_; + s << " " << blueSize_; + } + else + { + s << "lum"; + s << " " << luminanceSize_; + s << " "; + } + s << " " << alphaSize_; + s << " " << std::setw(2) << depthSize_; + s << " " << std::setw(2) << stencilSize_; + string caveat("None"); + switch (caveat_) + { + case EGL_SLOW_CONFIG: + caveat = string("Slow"); + break; + case EGL_NON_CONFORMANT_CONFIG: + caveat = string("Ncon"); + break; + case EGL_NONE: + // Initialized to none. + break; + } + s << " " << caveat; + string doNative(nativeRenderable_ ? "true" : "false"); + s << std::setw(7) << doNative; + string visType("tc"); + switch (nativeType_) + { + case StaticGray: + case GrayScale: + case StaticColor: + case PseudoColor: + // OpenGL ES doesn't support these, and we do not expect to see + // them in the modern era, but... + visType = string("ci"); + break; + case TrueColor: + // Initialized to TrueColor + break; + case DirectColor: + visType = string("dc"); + break; + } + s << " " << std::setw(2) << visType; + s << std::setw(3) << "0x" << std::hex << nativeID_; + s << std::setw(5) << "0x" << std::hex << surfaceType_; + s << std::dec << std::setw(4) << sampleBuffers_; + s << std::dec << std::setw(3) << samples_; + Log::debug("%s\n", s.str().c_str()); +} + + +bool +EGLState::init_display(EGLNativeDisplayType native_display, GLVisualConfig& visual_config) +{ + native_display_ = native_display; + visual_config_ = visual_config; + + return gotValidDisplay(); +} + +bool +EGLState::init_surface(EGLNativeWindowType native_window) +{ + native_window_ = reinterpret_cast(native_window); + + return gotValidSurface(); +} + +void +EGLState::swap() +{ + eglSwapBuffers(egl_display_, egl_surface_); +} + +bool +EGLState::gotValidDisplay() +{ + if (egl_display_) + return true; + + egl_display_ = eglGetDisplay(native_display_); + if (!egl_display_) { + Log::error("eglGetDisplay() failed with error: 0x%x\n", eglGetError()); + return false; + } + int egl_major(-1); + int egl_minor(-1); + if (!eglInitialize(egl_display_, &egl_major, &egl_minor)) { + Log::error("eglInitialize() failed with error: 0x%x\n", eglGetError()); + egl_display_ = 0; + return false; + } + + Log::info("Using display %p with EGL version %d.%d\n", egl_display_, egl_major, egl_minor); + Log::info("EGL Version \"%s\"\n", eglQueryString(egl_display_, EGL_VERSION)); + Log::info("EGL Vendor \"%s\"\n", eglQueryString(egl_display_, EGL_VENDOR)); + Log::info("EGL Extensions \"%s\"\n", eglQueryString(egl_display_, EGL_EXTENSIONS)); + +#if USE_GLESv2 + EGLenum apiType(EGL_OPENGL_ES_API); +#elif USE_GL + EGLenum apiType(EGL_OPENGL_API); +#endif + if (!eglBindAPI(apiType)) { + Log::error("Failed to bind api EGL_OPENGL_ES_API\n"); + return false; + } + + return true; +} + +void +EGLState::get_glvisualconfig(EGLConfig config, GLVisualConfig& visual_config) +{ + eglGetConfigAttrib(egl_display_, config, EGL_BUFFER_SIZE, &visual_config.buffer); + eglGetConfigAttrib(egl_display_, config, EGL_RED_SIZE, &visual_config.red); + eglGetConfigAttrib(egl_display_, config, EGL_GREEN_SIZE, &visual_config.green); + eglGetConfigAttrib(egl_display_, config, EGL_BLUE_SIZE, &visual_config.blue); + eglGetConfigAttrib(egl_display_, config, EGL_ALPHA_SIZE, &visual_config.alpha); + eglGetConfigAttrib(egl_display_, config, EGL_DEPTH_SIZE, &visual_config.depth); +} + +EGLConfig +EGLState::select_best_config(std::vector& configs) +{ + int best_score(INT_MIN); + EGLConfig best_config(0); + + /* + * Go through all the configs and choose the one with the best score, + * i.e., the one better matching the requested config. + */ + for (std::vector::const_iterator iter = configs.begin(); + iter != configs.end(); + iter++) + { + const EGLConfig config(*iter); + GLVisualConfig vc; + int score; + + get_glvisualconfig(config, vc); + + score = vc.match_score(visual_config_); + + if (score > best_score) { + best_score = score; + best_config = config; + } + } + + return best_config; +} + +bool +EGLState::gotValidConfig() +{ + if (egl_config_) + return true; + + if (!gotValidDisplay()) + return false; + + const EGLint config_attribs[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RED_SIZE, 1, + EGL_GREEN_SIZE, 1, + EGL_BLUE_SIZE, 1, + EGL_ALPHA_SIZE, 1, + EGL_DEPTH_SIZE, 1, +#if USE_GLESv2 + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, +#elif USE_GL + EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, +#endif + EGL_NONE + }; + + // Find out how many configs match the attributes. + EGLint num_configs(0); + if (!eglChooseConfig(egl_display_, config_attribs, 0, 0, &num_configs)) { + Log::error("eglChooseConfig() (count query) failed with error: %d\n", + eglGetError()); + return false; + } + + if (num_configs == 0) { + Log::error("eglChooseConfig() didn't return any configs\n"); + return false; + } + + // Get all the matching configs + vector configs(num_configs); + if (!eglChooseConfig(egl_display_, config_attribs, &configs.front(), + num_configs, &num_configs)) + { + Log::error("eglChooseConfig() failed with error: %d\n", + eglGetError()); + return false; + } + + // Select the best matching config + egl_config_ = select_best_config(configs); + get_glvisualconfig(egl_config_, visual_config_); + + vector configVec; + for (vector::const_iterator configIt = configs.begin(); + configIt != configs.end(); + configIt++) + { + EglConfig cfg(egl_display_, *configIt); + configVec.push_back(cfg); + if (*configIt == egl_config_) { + best_config_ = cfg; + } + } + + // Print out the config information, and let the user know the decision + // about the "best" one with respect to the options. + unsigned int lineNumber(0); + Log::debug("Got %u suitable EGLConfigs:\n", num_configs); + for (vector::const_iterator configIt = configVec.begin(); + configIt != configVec.end(); + configIt++, lineNumber++) + { + if (!(lineNumber % 32)) + { + configIt->print_header(); + } + configIt->print(); + } + Log::debug("\n"); + Log::debug("Best EGLConfig ID: 0x%x\n", best_config_.configID()); + + return true; +} + +bool +EGLState::gotValidSurface() +{ + if (egl_surface_) + return true; + + if (!gotValidDisplay()) + return false; + + if (!gotValidConfig()) + return false; + + egl_surface_ = eglCreateWindowSurface(egl_display_, egl_config_, native_window_, 0); + if (!egl_surface_) { + Log::error("eglCreateWindowSurface failed with error: 0x%x\n", eglGetError()); + return false; + } + + return true; +} + +bool +EGLState::gotValidContext() +{ + if (egl_context_) + return true; + + if (!gotValidDisplay()) + return false; + + if (!gotValidConfig()) + return false; + + static const EGLint context_attribs[] = { +#ifdef USE_GLESv2 + EGL_CONTEXT_CLIENT_VERSION, 2, +#endif + EGL_NONE + }; + + egl_context_ = eglCreateContext(egl_display_, egl_config_, + EGL_NO_CONTEXT, context_attribs); + if (!egl_context_) { + Log::error("eglCreateContext() failed with error: 0x%x\n", + eglGetError()); + return false; + } + + return true; +} + +bool +EGLState::valid() +{ + if (!gotValidDisplay()) + return false; + + if (!gotValidConfig()) + return false; + + if (!gotValidSurface()) + return false; + + if (!gotValidContext()) + return false; + + if (egl_context_ == eglGetCurrentContext()) + return true; + + if (!eglMakeCurrent(egl_display_, egl_surface_, egl_surface_, egl_context_)) { + Log::error("eglMakeCurrent failed with error: 0x%x\n", eglGetError()); + return false; + } + + if (!eglSwapInterval(egl_display_, 0)) { + Log::info("** Failed to set swap interval. Results may be bounded above by refresh rate.\n"); + } + + return true; +} + +bool +EGLState::gotNativeConfig(int& vid) +{ + if (!gotValidConfig()) + return false; + + EGLint native_id; + if (!eglGetConfigAttrib(egl_display_, egl_config_, EGL_NATIVE_VISUAL_ID, + &native_id)) + { + Log::debug("Failed to get native visual id for EGLConfig 0x%x\n", egl_config_); + return false; + } + + vid = native_id; + return true; +} + +bool +EGLState::reset() +{ + if (!gotValidDisplay()) { + return false; + } + + if (!egl_context_) { + return true; + } + + if (EGL_FALSE == eglDestroyContext(egl_display_, egl_context_)) { + Log::debug("eglDestroyContext failed with error: 0x%x\n", eglGetError()); + } + + egl_context_ = 0; + + return true; +} diff --git a/src/egl-state.h b/src/egl-state.h new file mode 100644 index 0000000..bd21e8d --- /dev/null +++ b/src/egl-state.h @@ -0,0 +1,130 @@ +// +// Copyright © 2012 Linaro Limited +// +// This file is part of the glmark2 OpenGL (ES) 2.0 benchmark. +// +// glmark2 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 3 of the License, or (at your option) any later +// version. +// +// glmark2 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 +// glmark2. If not, see . +// +// Authors: +// Jesse Barker +// +#ifndef EGL_STATE_H_ +#define EGL_STATE_H_ + +#include +#include +#include "gl-visual-config.h" + +class EglConfig +{ + EGLConfig handle_; + // Color buffer attributes. + EGLint bufferSize_; + EGLint redSize_; + EGLint greenSize_; + EGLint blueSize_; + EGLint luminanceSize_; + EGLint alphaSize_; + EGLint alphaMaskSize_; + EGLint bufferType_; + // Base config attributes + EGLint caveat_; + EGLint configID_; + // Depth buffer + EGLint depthSize_; + // Native window system attributes. + EGLint nativeID_; + EGLint nativeType_; + bool nativeRenderable_; + // Multisample support + EGLint sampleBuffers_; + EGLint samples_; + // Stencil buffer + EGLint stencilSize_; + EGLint surfaceType_; + // Transparency + EGLint xparentType_; // Should be RGB or NONE + EGLint xparentRedValue_; + EGLint xparentGreenValue_; + EGLint xparentBlueValue_; + +public: + EglConfig() : + handle_(0), + bufferSize_(0), + redSize_(0), + greenSize_(0), + blueSize_(0), + luminanceSize_(0), + alphaSize_(0), + alphaMaskSize_(0), + bufferType_(EGL_RGB_BUFFER), + caveat_(0), + configID_(0), + depthSize_(0), + nativeID_(0), + nativeType_(0), + nativeRenderable_(false), + sampleBuffers_(0), + samples_(0), + stencilSize_(0), + surfaceType_(0), + xparentType_(0), + xparentRedValue_(0), + xparentGreenValue_(0), + xparentBlueValue_(0) {} + EglConfig(EGLDisplay dpy, EGLConfig config); + ~EglConfig() {} + void print() const; + static void print_header(); + bool isWindowConfig() const { return surfaceType_ & EGL_WINDOW_BIT; } + EGLint configID() const { return configID_; } +}; + +class EGLState +{ + EGLNativeDisplayType native_display_; + EGLNativeWindowType native_window_; + EGLDisplay egl_display_; + EGLConfig egl_config_; + EGLContext egl_context_; + EGLSurface egl_surface_; + GLVisualConfig visual_config_; + EglConfig best_config_; + bool gotValidDisplay(); + bool gotValidConfig(); + bool gotValidSurface(); + bool gotValidContext(); + void get_glvisualconfig(EGLConfig config, GLVisualConfig& visual_config); + EGLConfig select_best_config(std::vector& configs); +public: + EGLState() : + native_display_(0), + native_window_(0), + egl_display_(0), + egl_config_(0), + egl_context_(0), + egl_surface_(0) {} + ~EGLState() {} + bool valid(); + bool init_display(EGLNativeDisplayType native_display, GLVisualConfig& config_pref); + bool init_surface(EGLNativeWindowType native_window); + bool reset(); + void swap(); + // Performs a config search, returning a native visual ID on success + bool gotNativeConfig(int& vid); + void getVisualConfig(GLVisualConfig& vc) { vc = visual_config_; } +}; + +#endif // EGL_STATE_H_ diff --git a/src/wscript_build b/src/wscript_build index d1d11c4..f0c233f 100644 --- a/src/wscript_build +++ b/src/wscript_build @@ -1,8 +1,9 @@ all_sources = bld.path.ant_glob('*.cpp scene-ideas/*.cc scene-terrain/*.cpp') common_sources = [f for f in all_sources if f.name.find('canvas-') == -1 and - f.name.find('android') == -1 ] + f.name.find('android') == -1 and + f.name.find('egl-') == -1] gl_sources = ['canvas-x11.cpp', 'canvas-x11-glx.cpp'] -glesv2_sources = ['canvas-x11.cpp', 'canvas-x11-egl.cpp'] +glesv2_sources = ['canvas-x11.cpp', 'canvas-x11-egl.cpp', 'egl-state.cpp'] libmatrix_sources = [f for f in bld.path.ant_glob('libmatrix/*.cc') if not f.name.endswith('test.cc')] includes = ['.', 'scene-ideas', 'scene-terrain'] -- cgit v1.2.3 From ce690269c4e456a618b388d4c18a8462d8bae2ee Mon Sep 17 00:00:00 2001 From: Jesse Barker Date: Tue, 13 Nov 2012 08:56:32 -0800 Subject: CanvasX11{EGL,GLX}: Integrate new EGLState object. This requires a small bit of new plumbing so that there is an explicit acknowledgement of the window system integration layer (::init_gl_winsys()). Additional canvas objects that do not integrate through X11 will not need this as there won't be the added legacy of GLX. --- src/canvas-x11-egl.cpp | 264 ++++--------------------------------------------- src/canvas-x11-egl.h | 25 ++--- src/canvas-x11-glx.h | 1 + src/canvas-x11.cpp | 3 + src/canvas-x11.h | 9 ++ 5 files changed, 40 insertions(+), 262 deletions(-) diff --git a/src/canvas-x11-egl.cpp b/src/canvas-x11-egl.cpp index 3f23fc8..0844b74 100644 --- a/src/canvas-x11-egl.cpp +++ b/src/canvas-x11-egl.cpp @@ -31,6 +31,14 @@ * Protected methods * *********************/ +bool +CanvasX11EGL::init_gl_winsys() +{ + egl_.init_display(reinterpret_cast(xdpy_), + visual_config_); + return true; +} + XVisualInfo * CanvasX11EGL::get_xvisualinfo() { @@ -39,14 +47,9 @@ CanvasX11EGL::get_xvisualinfo() int num_visuals; EGLint vid; - if (!ensure_egl_config()) - return 0; - - if (!eglGetConfigAttrib(egl_display_, egl_config_, - EGL_NATIVE_VISUAL_ID, &vid)) + if (!egl_.gotNativeConfig(vid)) { - Log::error("eglGetConfigAttrib() failed with error: %d\n", - eglGetError()); + Log::error("Failed to get a native-renderable EGLConfig\n"); return 0; } @@ -65,220 +68,37 @@ CanvasX11EGL::get_xvisualinfo() bool CanvasX11EGL::make_current() { - if (!ensure_egl_surface()) - return false; - - if (!ensure_egl_context()) - return false; - - if (egl_context_ == eglGetCurrentContext()) - return true; - - if (!eglMakeCurrent(egl_display_, egl_surface_, egl_surface_, egl_context_)) { - Log::error("Error: eglMakeCurrent failed with error %d\n", eglGetError()); + egl_.init_surface(reinterpret_cast(xwin_)); + if (!egl_.valid()) { + Log::error("CanvasX11EGL: Invalid EGL state\n"); return false; } - if (!eglSwapInterval(egl_display_, 0)) - Log::info("** Failed to set swap interval. Results may be bounded above by refresh rate.\n"); - init_gl_extensions(); return true; } void -CanvasX11EGL::get_glvisualconfig(GLVisualConfig &visual_config) +CanvasX11EGL::swap_buffers() { - if (!ensure_egl_config()) - return; + egl_.swap(); +} - get_glvisualconfig_egl(egl_config_, visual_config); +void +CanvasX11EGL::get_glvisualconfig(GLVisualConfig &visual_config) +{ + egl_.getVisualConfig(visual_config); } /******************* * Private methods * *******************/ -bool -CanvasX11EGL::ensure_egl_display() -{ - if (egl_display_) - return true; - - egl_display_ = eglGetDisplay((EGLNativeDisplayType) xdpy_); - if (!egl_display_) { - Log::error("eglGetDisplay() failed with error: %d\n", - eglGetError()); - return false; - } - if (!eglInitialize(egl_display_, NULL, NULL)) { - Log::error("eglInitialize() failed with error: %d\n", - eglGetError()); - return false; - egl_display_ = 0; - } - - return true; -} - -bool -CanvasX11EGL::ensure_egl_config() -{ - const EGLint attribs[] = { - EGL_RED_SIZE, visual_config_.red, - EGL_GREEN_SIZE, visual_config_.green, - EGL_BLUE_SIZE, visual_config_.blue, - EGL_ALPHA_SIZE, visual_config_.alpha, - EGL_DEPTH_SIZE, visual_config_.depth, - EGL_BUFFER_SIZE, visual_config_.buffer, -#ifdef USE_GLESv2 - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, -#elif USE_GL - EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, -#endif - EGL_NONE - }; - EGLint num_configs; - EGLint vid; - - if (egl_config_) - return true; - - if (!ensure_egl_display()) - return false; - - /* Find out how many configs match the attributes */ - if (!eglChooseConfig(egl_display_, attribs, 0, 0, &num_configs)) { - Log::error("eglChooseConfig() (explore) failed with error: %d\n", - eglGetError()); - return false; - } - - if (num_configs == 0) { - Log::error("eglChooseConfig() didn't return any configs\n"); - return false; - } - - /* Get all the matching configs */ - std::vector configs(num_configs); - - if (!eglChooseConfig(egl_display_, attribs, &(configs[0]), - num_configs, &num_configs)) - { - Log::error("eglChooseConfig() failed with error: %d\n", - eglGetError()); - return false; - } - - /* Select the best matching config */ - egl_config_ = select_best_config(configs); - - if (!eglGetConfigAttrib(egl_display_, egl_config_, - EGL_NATIVE_VISUAL_ID, &vid)) - { - Log::error("eglGetConfigAttrib() failed with error: %d\n", - eglGetError()); - return false; - } - - if (Options::show_debug) { - int buf, red, green, blue, alpha, depth, id, native_id; - eglGetConfigAttrib(egl_display_, egl_config_, EGL_CONFIG_ID, &id); - eglGetConfigAttrib(egl_display_, egl_config_, EGL_NATIVE_VISUAL_ID, &native_id); - eglGetConfigAttrib(egl_display_, egl_config_, EGL_BUFFER_SIZE, &buf); - eglGetConfigAttrib(egl_display_, egl_config_, EGL_RED_SIZE, &red); - eglGetConfigAttrib(egl_display_, egl_config_, EGL_GREEN_SIZE, &green); - eglGetConfigAttrib(egl_display_, egl_config_, EGL_BLUE_SIZE, &blue); - eglGetConfigAttrib(egl_display_, egl_config_, EGL_ALPHA_SIZE, &alpha); - eglGetConfigAttrib(egl_display_, egl_config_, EGL_DEPTH_SIZE, &depth); - Log::debug("EGL chosen config ID: 0x%x Native Visual ID: 0x%x\n" - " Buffer: %d bits\n" - " Red: %d bits\n" - " Green: %d bits\n" - " Blue: %d bits\n" - " Alpha: %d bits\n" - " Depth: %d bits\n", - id, native_id, - buf, red, green, blue, alpha, depth); - } - - return true; -} - bool CanvasX11EGL::reset_context() { - if (!ensure_egl_display()) - return false; - - if (!egl_context_) - return true; - - if (eglDestroyContext(egl_display_, egl_context_) == EGL_FALSE) { - Log::debug("eglDestroyContext() failed with error: 0x%x\n", - eglGetError()); - } - - egl_context_ = 0; - return true; -} - -bool -CanvasX11EGL::ensure_egl_context() -{ - if (egl_context_) - return true; - - if (!ensure_egl_display()) - return false; - - if (!ensure_egl_config()) - return false; - - static const EGLint ctx_attribs[] = { -#ifdef USE_GLESv2 - EGL_CONTEXT_CLIENT_VERSION, 2, -#endif - EGL_NONE - }; - - egl_context_ = eglCreateContext(egl_display_, egl_config_, - EGL_NO_CONTEXT, ctx_attribs); - if (!egl_context_) { - Log::error("eglCreateContext() failed with error: 0x%x\n", - eglGetError()); - return false; - } - - return true; -} - -bool -CanvasX11EGL::ensure_egl_surface() -{ - if (egl_surface_) - return true; - - if (!ensure_egl_display()) - return false; - -#ifdef USE_GLESv2 - eglBindAPI(EGL_OPENGL_ES_API); -#elif USE_GL - eglBindAPI(EGL_OPENGL_API); -#endif - - egl_surface_ = eglCreateWindowSurface(egl_display_, egl_config_, - (EGLNativeWindowType) xwin_, - NULL); - if (!egl_surface_) { - Log::error("eglCreateWindowSurface failed with error: %d\n", - eglGetError()); - return false; - } - - return true; + return egl_.reset(); } void @@ -296,45 +116,3 @@ CanvasX11EGL::init_gl_extensions() GLExtensions::UnmapBuffer = glUnmapBuffer; #endif } - -void -CanvasX11EGL::get_glvisualconfig_egl(EGLConfig config, GLVisualConfig &visual_config) -{ - eglGetConfigAttrib(egl_display_, config, EGL_BUFFER_SIZE, &visual_config.buffer); - eglGetConfigAttrib(egl_display_, config, EGL_RED_SIZE, &visual_config.red); - eglGetConfigAttrib(egl_display_, config, EGL_GREEN_SIZE, &visual_config.green); - eglGetConfigAttrib(egl_display_, config, EGL_BLUE_SIZE, &visual_config.blue); - eglGetConfigAttrib(egl_display_, config, EGL_ALPHA_SIZE, &visual_config.alpha); - eglGetConfigAttrib(egl_display_, config, EGL_DEPTH_SIZE, &visual_config.depth); -} - -EGLConfig -CanvasX11EGL::select_best_config(std::vector configs) -{ - int best_score(INT_MIN); - EGLConfig best_config(0); - - /* - * Go through all the configs and choose the one with the best score, - * i.e., the one better matching the requested config. - */ - for (std::vector::const_iterator iter = configs.begin(); - iter != configs.end(); - iter++) - { - const EGLConfig config(*iter); - GLVisualConfig vc; - int score; - - get_glvisualconfig_egl(config, vc); - - score = vc.match_score(visual_config_); - - if (score > best_score) { - best_score = score; - best_config = config; - } - } - - return best_config; -} diff --git a/src/canvas-x11-egl.h b/src/canvas-x11-egl.h index d1ebf5f..d5f581c 100644 --- a/src/canvas-x11-egl.h +++ b/src/canvas-x11-egl.h @@ -18,14 +18,13 @@ * * Authors: * Alexandros Frantzis (glmark2) + * Jesse Barker */ #ifndef GLMARK2_CANVAS_X11_EGL_H_ #define GLMARK2_CANVAS_X11_EGL_H_ #include "canvas-x11.h" - -#include -#include +#include "egl-state.h" /** * Canvas for rendering to an X11 window using EGL. @@ -34,32 +33,20 @@ class CanvasX11EGL : public CanvasX11 { public: CanvasX11EGL(int width, int height) : - CanvasX11(width, height), egl_display_(EGL_NO_DISPLAY), - egl_surface_(EGL_NO_SURFACE), egl_config_(0), - egl_context_(EGL_NO_CONTEXT) {} + CanvasX11(width, height) {} ~CanvasX11EGL() {} protected: XVisualInfo *get_xvisualinfo(); bool make_current(); bool reset_context(); - void swap_buffers() { eglSwapBuffers(egl_display_, egl_surface_); } + void swap_buffers(); void get_glvisualconfig(GLVisualConfig &visual_config); + bool init_gl_winsys(); private: - bool ensure_egl_display(); - bool ensure_egl_config(); - bool ensure_egl_context(); - bool ensure_egl_surface(); void init_gl_extensions(); - void get_glvisualconfig_egl(EGLConfig config, GLVisualConfig &visual_config); - EGLConfig select_best_config(std::vector configs); - - EGLDisplay egl_display_; - EGLSurface egl_surface_; - EGLConfig egl_config_; - EGLContext egl_context_; + EGLState egl_; }; #endif - diff --git a/src/canvas-x11-glx.h b/src/canvas-x11-glx.h index 8eb3f93..f787087 100644 --- a/src/canvas-x11-glx.h +++ b/src/canvas-x11-glx.h @@ -45,6 +45,7 @@ protected: bool reset_context(); void swap_buffers() { glXSwapBuffers(xdpy_, xwin_); } void get_glvisualconfig(GLVisualConfig &visual_config); + bool init_gl_winsys() { return true; } private: bool check_glx_version(); diff --git a/src/canvas-x11.cpp b/src/canvas-x11.cpp index 29d7ce6..c1b19c0 100644 --- a/src/canvas-x11.cpp +++ b/src/canvas-x11.cpp @@ -70,6 +70,9 @@ CanvasX11::init() if (!xdpy_) return false; + if (!init_gl_winsys()) + return false; + resize_no_viewport(width_, height_); if (!xwin_) diff --git a/src/canvas-x11.h b/src/canvas-x11.h index 4bf26bd..7b3b456 100644 --- a/src/canvas-x11.h +++ b/src/canvas-x11.h @@ -63,6 +63,15 @@ protected: */ virtual XVisualInfo *get_xvisualinfo() = 0; + /** + * Initializes window system interfaces for GL rendering. + * + * This method should be implemented in derived classes. + * + * @return whether the operation succeeded + */ + virtual bool init_gl_winsys() = 0; + /** * Makes the canvas the current target for GL rendering. * -- cgit v1.2.3 From c18cafd62d6d17832c0d15d949251345e239145c Mon Sep 17 00:00:00 2001 From: Jesse Barker Date: Tue, 13 Nov 2012 11:17:46 -0800 Subject: EGLState: Clean up config handling and output so that it builds properly and works well for both an X11-based and a DRM-based canvas. --- src/egl-state.cpp | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/src/egl-state.cpp b/src/egl-state.cpp index b045962..293cf5f 100644 --- a/src/egl-state.cpp +++ b/src/egl-state.cpp @@ -25,6 +25,7 @@ #include "limits.h" #include #include +#include // for the Native visual type definitions using std::vector; using std::string; @@ -184,24 +185,27 @@ void EglConfig::print() const { std::ostringstream s; - s << std::setw(5) << "0x" << std::hex << configID_; - s << " " << std::dec << bufferSize_ << " "; + s.setf(std::ios::showbase); + s.fill(' '); + s << std::setw(7) << std::hex << configID_; + s << std::setw(4) << std::dec << bufferSize_; if (bufferType_ == EGL_RGB_BUFFER) { - s << "rgb"; - s << " " << redSize_; - s << " " << greenSize_; - s << " " << blueSize_; + s << std::setw(5) << "rgb"; + s << std::setw(3) << redSize_; + s << std::setw(3) << greenSize_; + s << std::setw(3) << blueSize_; } else { - s << "lum"; - s << " " << luminanceSize_; - s << " "; - } - s << " " << alphaSize_; - s << " " << std::setw(2) << depthSize_; - s << " " << std::setw(2) << stencilSize_; + s << std::setw(5) << "lum"; + s << std::setw(3) << luminanceSize_; + s << std::setw(3) << 0; + s << std::setw(3) << 0; + } + s << std::setw(3) << alphaSize_; + s << std::setw(4) << depthSize_; + s << std::setw(3) << stencilSize_; string caveat("None"); switch (caveat_) { @@ -215,7 +219,7 @@ EglConfig::print() const // Initialized to none. break; } - s << " " << caveat; + s << std::setw(7) << caveat; string doNative(nativeRenderable_ ? "true" : "false"); s << std::setw(7) << doNative; string visType("tc"); @@ -230,17 +234,18 @@ EglConfig::print() const visType = string("ci"); break; case TrueColor: + case EGL_NONE: // Initialized to TrueColor break; case DirectColor: visType = string("dc"); break; } - s << " " << std::setw(2) << visType; - s << std::setw(3) << "0x" << std::hex << nativeID_; - s << std::setw(5) << "0x" << std::hex << surfaceType_; - s << std::dec << std::setw(4) << sampleBuffers_; - s << std::dec << std::setw(3) << samples_; + s << std::setw(3) << visType; + s << std::setw(5) << std::hex << nativeID_; + s << std::setw(8) << std::hex << surfaceType_; + s << std::setw(4) << std::dec << sampleBuffers_; + s << std::setw(3) << std::dec << samples_; Log::debug("%s\n", s.str().c_str()); } -- cgit v1.2.3 From 4e668272c2dac465afce05c3c057c7f9493a5e6c Mon Sep 17 00:00:00 2001 From: Jesse Barker Date: Thu, 15 Nov 2012 15:06:53 -0800 Subject: EGLState: A few bits of clean up based upon review comments. - Remove X11-specific native visual type info as it breaks Android build (and is not likely to be of interest anyway). - Remove 'info' level EGL info around extensions, vendor, etc. We don't do it for GLX apart from minimum version requirements (which we don't have for EGL). - Tweak config initialization to match more closely what was originally in CanvasX11EGL, in particular, define the config attribs according to the GLVisualConfig we were given and don't override it. --- src/egl-state.cpp | 42 +++++++----------------------------------- 1 file changed, 7 insertions(+), 35 deletions(-) diff --git a/src/egl-state.cpp b/src/egl-state.cpp index 293cf5f..40cb837 100644 --- a/src/egl-state.cpp +++ b/src/egl-state.cpp @@ -25,7 +25,6 @@ #include "limits.h" #include #include -#include // for the Native visual type definitions using std::vector; using std::string; @@ -177,7 +176,7 @@ EglConfig::print_header() { Log::debug("\n"); Log::debug(" cfg buf rgb colorbuffer dp st config native support surface sample\n"); - Log::debug(" id sz lum r g b a th cl caveat render type id type buf ns\n"); + Log::debug(" id sz lum r g b a th cl caveat render visid type buf ns\n"); Log::debug("------------------------------------------------------------------------\n"); } @@ -222,27 +221,7 @@ EglConfig::print() const s << std::setw(7) << caveat; string doNative(nativeRenderable_ ? "true" : "false"); s << std::setw(7) << doNative; - string visType("tc"); - switch (nativeType_) - { - case StaticGray: - case GrayScale: - case StaticColor: - case PseudoColor: - // OpenGL ES doesn't support these, and we do not expect to see - // them in the modern era, but... - visType = string("ci"); - break; - case TrueColor: - case EGL_NONE: - // Initialized to TrueColor - break; - case DirectColor: - visType = string("dc"); - break; - } - s << std::setw(3) << visType; - s << std::setw(5) << std::hex << nativeID_; + s << std::setw(8) << std::hex << nativeID_; s << std::setw(8) << std::hex << surfaceType_; s << std::setw(4) << std::dec << sampleBuffers_; s << std::setw(3) << std::dec << samples_; @@ -292,11 +271,6 @@ EGLState::gotValidDisplay() return false; } - Log::info("Using display %p with EGL version %d.%d\n", egl_display_, egl_major, egl_minor); - Log::info("EGL Version \"%s\"\n", eglQueryString(egl_display_, EGL_VERSION)); - Log::info("EGL Vendor \"%s\"\n", eglQueryString(egl_display_, EGL_VENDOR)); - Log::info("EGL Extensions \"%s\"\n", eglQueryString(egl_display_, EGL_EXTENSIONS)); - #if USE_GLESv2 EGLenum apiType(EGL_OPENGL_ES_API); #elif USE_GL @@ -362,12 +336,11 @@ EGLState::gotValidConfig() return false; const EGLint config_attribs[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_RED_SIZE, 1, - EGL_GREEN_SIZE, 1, - EGL_BLUE_SIZE, 1, - EGL_ALPHA_SIZE, 1, - EGL_DEPTH_SIZE, 1, + EGL_RED_SIZE, visual_config_.red, + EGL_GREEN_SIZE, visual_config_.green, + EGL_BLUE_SIZE, visual_config_.blue, + EGL_ALPHA_SIZE, visual_config_.alpha, + EGL_DEPTH_SIZE, visual_config_.depth, #if USE_GLESv2 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, #elif USE_GL @@ -401,7 +374,6 @@ EGLState::gotValidConfig() // Select the best matching config egl_config_ = select_best_config(configs); - get_glvisualconfig(egl_config_, visual_config_); vector configVec; for (vector::const_iterator configIt = configs.begin(); -- cgit v1.2.3