From 341f04dca0008c290cf065c4b36348fd80fe9700 Mon Sep 17 00:00:00 2001 From: Fathi Boudra Date: Sat, 30 Mar 2013 17:38:14 +0200 Subject: Imported Upstream version 2012.12 --- src/egl-state.cpp | 578 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 578 insertions(+) create mode 100644 src/egl-state.cpp (limited to 'src/egl-state.cpp') diff --git a/src/egl-state.cpp b/src/egl-state.cpp new file mode 100644 index 0000000..639421a --- /dev/null +++ b/src/egl-state.cpp @@ -0,0 +1,578 @@ +// +// 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), + bindTexRGB_(false), + bindTexRGBA_(false), + bufferType_(EGL_RGB_BUFFER), + caveat_(0), + configID_(0), + conformant_(0), + depthSize_(0), + level_(0), + pbufferWidth_(0), + pbufferHeight_(0), + pbufferPixels_(0), + minSwapInterval_(0), + maxSwapInterval_(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_CONFORMANT, &conformant_)) + { + badAttribVec.push_back("EGL_CONFORMANT"); + } + 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_ALPHA_MASK_SIZE, &alphaMaskSize_)) + { + badAttribVec.push_back("EGL_ALPHA_MASK_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 doBind(EGL_FALSE); + if (!eglGetConfigAttrib(dpy, handle_, EGL_BIND_TO_TEXTURE_RGB, &doBind)) + { + badAttribVec.push_back("EGL_BIND_TO_TEXTURE_RGB"); + } + bindTexRGB_ = (doBind == EGL_TRUE); + if (!eglGetConfigAttrib(dpy, handle_, EGL_BIND_TO_TEXTURE_RGBA, &doBind)) + { + badAttribVec.push_back("EGL_BIND_TO_TEXTURE_RGBA"); + } + bindTexRGBA_ = (doBind == EGL_TRUE); + if (!eglGetConfigAttrib(dpy, handle_, EGL_LEVEL, &level_)) + { + badAttribVec.push_back("EGL_LEVEL"); + } + if (!eglGetConfigAttrib(dpy, handle_, EGL_MAX_PBUFFER_WIDTH, &pbufferWidth_)) + { + badAttribVec.push_back("EGL_MAX_PBUFFER_WIDTH"); + } + if (!eglGetConfigAttrib(dpy, handle_, EGL_MAX_PBUFFER_HEIGHT, &pbufferHeight_)) + { + badAttribVec.push_back("EGL_MAX_PBUFFER_HEIGHT"); + } + if (!eglGetConfigAttrib(dpy, handle_, EGL_MAX_PBUFFER_PIXELS, &pbufferPixels_)) + { + badAttribVec.push_back("EGL_MAX_PBUFFER_PIXELS"); + } + if (!eglGetConfigAttrib(dpy, handle_, EGL_MIN_SWAP_INTERVAL, &minSwapInterval_)) + { + badAttribVec.push_back("EGL_MIN_SWAP_INTERVAL"); + } + if (!eglGetConfigAttrib(dpy, handle_, EGL_MAX_SWAP_INTERVAL, &maxSwapInterval_)) + { + badAttribVec.push_back("EGL_MAX_SWAP_INTERVAL"); + } + EGLint doNative(EGL_FALSE); + if (!eglGetConfigAttrib(dpy, handle_, EGL_NATIVE_RENDERABLE, &doNative)) + { + badAttribVec.push_back("EGL_NATIVE_RENDERABLE"); + } + nativeRenderable_ = (doNative == EGL_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 visid type buf ns\n"); + Log::debug("------------------------------------------------------------------------\n"); +} + +void +EglConfig::print() const +{ + std::ostringstream s; + 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 << std::setw(5) << "rgb"; + s << std::setw(3) << redSize_; + s << std::setw(3) << greenSize_; + s << std::setw(3) << blueSize_; + } + else + { + 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_) + { + 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 << std::setw(7) << caveat; + string doNative(nativeRenderable_ ? "true" : "false"); + s << std::setw(7) << doNative; + 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_; + 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; + } + +#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); + eglGetConfigAttrib(egl_display_, config, EGL_STENCIL_SIZE, &visual_config.stencil); +} + +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_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_STENCIL_SIZE, visual_config_.stencil, +#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); + + 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; +} -- cgit v1.2.3