aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Barker <jesse.barker@linaro.org>2012-11-16 10:26:15 -0800
committerJesse Barker <jesse.barker@linaro.org>2012-11-16 10:26:15 -0800
commit66fef1313790c36aba33c6d5921b1b86ccaeea7e (patch)
treeca69f2517d2bd4580c7607fa4755f5c590536dda
parentee9d0ecff70999701cc02867c9d93be07a6cfcb7 (diff)
parent4e668272c2dac465afce05c3c057c7f9493a5e6c (diff)
downloadglmark2-66fef1313790c36aba33c6d5921b1b86ccaeea7e.tar.gz
Merge of lp:~glmark2-dev/glmark2/egl-state.
Adds EGLState object, which consolidates all EGL interactions.
-rw-r--r--src/canvas-x11-egl.cpp264
-rw-r--r--src/canvas-x11-egl.h25
-rw-r--r--src/canvas-x11-glx.h1
-rw-r--r--src/canvas-x11.cpp3
-rw-r--r--src/canvas-x11.h9
-rw-r--r--src/egl-state.cpp527
-rw-r--r--src/egl-state.h130
-rw-r--r--src/wscript_build5
8 files changed, 700 insertions, 264 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<EGLNativeDisplayType>(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,35 +68,27 @@ 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<EGLNativeWindowType>(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);
}
/*******************
@@ -101,184 +96,9 @@ CanvasX11EGL::get_glvisualconfig(GLVisualConfig &visual_config)
*******************/
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<EGLConfig> 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<EGLConfig> 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<EGLConfig>::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 <EGL/egl.h>
-#include <vector>
+#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<EGLConfig> 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
@@ -64,6 +64,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.
*
* This method should be implemented in derived classes.
diff --git a/src/egl-state.cpp b/src/egl-state.cpp
new file mode 100644
index 0000000..40cb837
--- /dev/null
+++ b/src/egl-state.cpp
@@ -0,0 +1,527 @@
+//
+// 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 <http://www.gnu.org/licenses/>.
+//
+// Authors:
+// Jesse Barker
+//
+#include "egl-state.h"
+#include "log.h"
+#include "options.h"
+#include "limits.h"
+#include <iomanip>
+#include <sstream>
+
+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<string> 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<string>::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<EGLNativeWindowType>(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);
+}
+
+EGLConfig
+EGLState::select_best_config(std::vector<EGLConfig>& 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<EGLConfig>::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,
+#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<EGLConfig> 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<EglConfig> configVec;
+ for (vector<EGLConfig>::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<EglConfig>::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 <http://www.gnu.org/licenses/>.
+//
+// Authors:
+// Jesse Barker
+//
+#ifndef EGL_STATE_H_
+#define EGL_STATE_H_
+
+#include <vector>
+#include <EGL/egl.h>
+#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<EGLConfig>& 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']