diff mbox

[Branch,~glmark2-dev/glmark2/trunk] Rev 208: CanvasX11*: Allow user configuration of visual used for rendering.

Message ID 20120515084409.21820.27948.launchpad@ackee.canonical.com
State Accepted
Headers show

Commit Message

alexandros.frantzis@linaro.org May 15, 2012, 8:44 a.m. UTC
Merge authors:
  Alexandros Frantzis (afrantzis)
Related merge proposals:
  https://code.launchpad.net/~linaro-graphics-wg/glmark2/configurable-visual/+merge/105642
  proposed by: Alexandros Frantzis (afrantzis)
  review: Approve - Jesse Barker (jesse-barker)
------------------------------------------------------------
revno: 208 [merge]
committer: Alexandros Frantzis <alexandros.frantzis@linaro.org>
branch nick: trunk
timestamp: Tue 2012-05-15 11:40:46 +0300
message:
  CanvasX11*: Allow user configuration of visual used for rendering.
added:
  src/gl-visual-config.cpp
  src/gl-visual-config.h
modified:
  doc/glmark2.1.in
  src/canvas-x11-egl.cpp
  src/canvas-x11-egl.h
  src/canvas-x11-glx.cpp
  src/canvas-x11-glx.h
  src/canvas-x11.cpp
  src/canvas-x11.h
  src/canvas.h
  src/main.cpp
  src/options.cpp
  src/options.h


--
lp:glmark2
https://code.launchpad.net/~glmark2-dev/glmark2/trunk

You are subscribed to branch lp:glmark2.
To unsubscribe from this branch go to https://code.launchpad.net/~glmark2-dev/glmark2/trunk/+edit-subscription
diff mbox

Patch

=== modified file 'doc/glmark2.1.in'
--- doc/glmark2.1.in	2012-03-22 10:37:35 +0000
+++ doc/glmark2.1.in	2012-05-10 09:19:38 +0000
@@ -27,6 +27,11 @@ 
 \fB\-\-off-screen\fR
 Render to an off-screen surface
 .TP
+\fB--visual-config\fR
+The visual configuration to use for the rendering target:
+\'red=R:green=G:blue=B:alpha=A:buffer=BUF'. The parameters may be defined
+in any order, and any omitted parameters assume a default value of '1'
+.TP
 \fB\-\-reuse\-context\fR
 Use a single context for all scenes
 (by default, each scene gets its own context)

=== modified file 'src/canvas-x11-egl.cpp'
--- src/canvas-x11-egl.cpp	2012-03-20 11:16:03 +0000
+++ src/canvas-x11-egl.cpp	2012-05-11 13:53:08 +0000
@@ -25,6 +25,7 @@ 
 
 #include <fstream>
 #include <sstream>
+#include <climits>
 
 /*********************
  * Protected methods *
@@ -87,17 +88,12 @@ 
 }
 
 void
-CanvasX11EGL::get_glvisualinfo(GLVisualInfo &gl_visinfo)
+CanvasX11EGL::get_glvisualconfig(GLVisualConfig &visual_config)
 {
     if (!ensure_egl_config())
         return;
 
-    eglGetConfigAttrib(egl_display_, egl_config_, EGL_BUFFER_SIZE, &gl_visinfo.buffer_size);
-    eglGetConfigAttrib(egl_display_, egl_config_, EGL_RED_SIZE, &gl_visinfo.red_size);
-    eglGetConfigAttrib(egl_display_, egl_config_, EGL_GREEN_SIZE, &gl_visinfo.green_size);
-    eglGetConfigAttrib(egl_display_, egl_config_, EGL_BLUE_SIZE, &gl_visinfo.blue_size);
-    eglGetConfigAttrib(egl_display_, egl_config_, EGL_ALPHA_SIZE, &gl_visinfo.alpha_size);
-    eglGetConfigAttrib(egl_display_, egl_config_, EGL_DEPTH_SIZE, &gl_visinfo.depth_size);
+    get_glvisualconfig_egl(egl_config_, visual_config);
 }
 
 /*******************
@@ -129,12 +125,13 @@ 
 bool
 CanvasX11EGL::ensure_egl_config()
 {
-    static const EGLint attribs[] = {
-        EGL_RED_SIZE, 1,
-        EGL_GREEN_SIZE, 1,
-        EGL_BLUE_SIZE, 1,
-        EGL_ALPHA_SIZE, 1,
-        EGL_DEPTH_SIZE, 1,
+    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
@@ -151,14 +148,32 @@ 
     if (!ensure_egl_display())
         return false;
 
-    if (!eglChooseConfig(egl_display_, attribs, &egl_config_,
-                         1, &num_configs))
+    /* 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))
     {
@@ -281,3 +296,45 @@ 
     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;
+}

=== modified file 'src/canvas-x11-egl.h'
--- src/canvas-x11-egl.h	2012-03-19 16:55:27 +0000
+++ src/canvas-x11-egl.h	2012-05-11 13:53:08 +0000
@@ -25,6 +25,7 @@ 
 #include "canvas-x11.h"
 
 #include <EGL/egl.h>
+#include <vector>
 
 /**
  * Canvas for rendering to an X11 window using EGL.
@@ -43,7 +44,7 @@ 
     bool make_current();
     bool reset_context();
     void swap_buffers() { eglSwapBuffers(egl_display_, egl_surface_); }
-    void get_glvisualinfo(GLVisualInfo &gl_visinfo);
+    void get_glvisualconfig(GLVisualConfig &visual_config);
 
 private:
     bool ensure_egl_display();
@@ -51,6 +52,8 @@ 
     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_;

=== modified file 'src/canvas-x11-glx.cpp'
--- src/canvas-x11-glx.cpp	2012-03-19 16:55:27 +0000
+++ src/canvas-x11-glx.cpp	2012-05-11 13:53:08 +0000
@@ -24,6 +24,7 @@ 
 #include "options.h"
 
 #include <string>
+#include <climits>
 
 static PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT_;
 static PFNGLXSWAPINTERVALMESAPROC glXSwapIntervalMESA_;
@@ -69,17 +70,12 @@ 
 }
 
 void
-CanvasX11GLX::get_glvisualinfo(GLVisualInfo &gl_visinfo)
+CanvasX11GLX::get_glvisualconfig(GLVisualConfig &visual_config)
 {
     if (!ensure_glx_fbconfig())
         return;
 
-    glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_BUFFER_SIZE, &gl_visinfo.buffer_size);
-    glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_RED_SIZE, &gl_visinfo.red_size);
-    glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_GREEN_SIZE, &gl_visinfo.green_size);
-    glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_BLUE_SIZE, &gl_visinfo.blue_size);
-    glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_ALPHA_SIZE, &gl_visinfo.alpha_size);
-    glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_DEPTH_SIZE, &gl_visinfo.depth_size);
+    get_glvisualconfig_glx(glx_fbconfig_, visual_config);
 }
 
 /*******************
@@ -151,11 +147,12 @@ 
         GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
         GLX_RENDER_TYPE, GLX_RGBA_BIT,
         GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
-        GLX_RED_SIZE, 1,
-        GLX_GREEN_SIZE, 1,
-        GLX_BLUE_SIZE, 1,
-        GLX_ALPHA_SIZE, 1,
-        GLX_DEPTH_SIZE, 1,
+        GLX_RED_SIZE, visual_config_.red,
+        GLX_GREEN_SIZE, visual_config_.green,
+        GLX_BLUE_SIZE, visual_config_.blue,
+        GLX_ALPHA_SIZE, visual_config_.alpha,
+        GLX_DEPTH_SIZE, visual_config_.depth,
+        GLX_BUFFER_SIZE, visual_config_.buffer,
         GLX_DOUBLEBUFFER, True,
         None
     };
@@ -174,10 +171,12 @@ 
         return false;
     }
 
+    std::vector<GLXFBConfig> configs(fbc, fbc + num_configs);
+
     Log::debug("Found %d matching FB configs.\n", num_configs);
 
-    /* Get the first matching config */
-    glx_fbconfig_ = fbc[0];
+    /* Select the best matching config */
+    glx_fbconfig_ = select_best_config(configs);
 
     XFree(fbc);
 
@@ -243,3 +242,44 @@ 
     return true;
 }
 
+void
+CanvasX11GLX::get_glvisualconfig_glx(const GLXFBConfig config, GLVisualConfig &visual_config)
+{
+    glXGetFBConfigAttrib(xdpy_, config, GLX_BUFFER_SIZE, &visual_config.buffer);
+    glXGetFBConfigAttrib(xdpy_, config, GLX_RED_SIZE, &visual_config.red);
+    glXGetFBConfigAttrib(xdpy_, config, GLX_GREEN_SIZE, &visual_config.green);
+    glXGetFBConfigAttrib(xdpy_, config, GLX_BLUE_SIZE, &visual_config.blue);
+    glXGetFBConfigAttrib(xdpy_, config, GLX_ALPHA_SIZE, &visual_config.alpha);
+    glXGetFBConfigAttrib(xdpy_, config, GLX_DEPTH_SIZE, &visual_config.depth);
+}
+
+GLXFBConfig
+CanvasX11GLX::select_best_config(std::vector<GLXFBConfig> configs)
+{
+    int best_score(INT_MIN);
+    GLXFBConfig 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<GLXFBConfig>::const_iterator iter = configs.begin();
+         iter != configs.end();
+         iter++)
+    {
+        const GLXFBConfig config(*iter);
+        GLVisualConfig vc;
+        int score;
+
+        get_glvisualconfig_glx(config, vc);
+
+        score = vc.match_score(visual_config_);
+
+        if (score > best_score) {
+            best_score = score;
+            best_config = config;
+        }
+    }
+
+    return best_config;
+}

=== modified file 'src/canvas-x11-glx.h'
--- src/canvas-x11-glx.h	2012-03-19 16:55:27 +0000
+++ src/canvas-x11-glx.h	2012-05-11 13:53:08 +0000
@@ -27,6 +27,7 @@ 
 #define GLX_GLXEXT_PROTOTYPES
 #include <GL/glx.h>
 #include <GL/glxext.h>
+#include <vector>
 
 /**
  * Canvas for rendering to an X11 window using GLX.
@@ -43,7 +44,7 @@ 
     bool make_current();
     bool reset_context();
     void swap_buffers() { glXSwapBuffers(xdpy_, xwin_); }
-    void get_glvisualinfo(GLVisualInfo &gl_visinfo);
+    void get_glvisualconfig(GLVisualConfig &visual_config);
 
 private:
     bool check_glx_version();
@@ -51,6 +52,8 @@ 
     bool ensure_glx_fbconfig();
     bool ensure_glx_context();
     void init_gl_extensions();
+    void get_glvisualconfig_glx(GLXFBConfig config, GLVisualConfig &visual_config);
+    GLXFBConfig select_best_config(std::vector<GLXFBConfig> configs);
 
     GLXFBConfig glx_fbconfig_;
     GLXContext glx_context_;

=== modified file 'src/canvas-x11.cpp'
--- src/canvas-x11.cpp	2012-05-07 12:45:34 +0000
+++ src/canvas-x11.cpp	2012-05-11 11:02:37 +0000
@@ -350,8 +350,8 @@ 
     if (gl_color_format_ && gl_depth_format_)
         return true;
 
-    GLVisualInfo gl_visinfo;
-    get_glvisualinfo(gl_visinfo);
+    GLVisualConfig vc;
+    get_glvisualconfig(vc);
 
     gl_color_format_ = 0;
     gl_depth_format_ = 0;
@@ -382,41 +382,41 @@ 
     supports_depth32 = true;
 #endif
 
-    if (gl_visinfo.buffer_size == 32) {
+    if (vc.buffer == 32) {
         if (supports_rgba8)
             gl_color_format_ = GL_RGBA8;
         else
             gl_color_format_ = GL_RGBA4;
     }
-    else if (gl_visinfo.buffer_size == 24) {
+    else if (vc.buffer == 24) {
         if (supports_rgb8)
             gl_color_format_ = GL_RGB8;
         else
             gl_color_format_ = GL_RGB565;
     }
-    else if (gl_visinfo.buffer_size == 16) {
-        if (gl_visinfo.red_size == 4 && gl_visinfo.green_size == 4 &&
-            gl_visinfo.blue_size == 4 && gl_visinfo.alpha_size == 4)
+    else if (vc.buffer == 16) {
+        if (vc.red == 4 && vc.green == 4 &&
+            vc.blue == 4 && vc.alpha == 4)
         {
             gl_color_format_ = GL_RGBA4;
         }
-        else if (gl_visinfo.red_size == 5 && gl_visinfo.green_size == 5 &&
-                 gl_visinfo.blue_size == 5 && gl_visinfo.alpha_size == 1)
+        else if (vc.red == 5 && vc.green == 5 &&
+                 vc.blue == 5 && vc.alpha == 1)
         {
             gl_color_format_ = GL_RGB5_A1;
         }
-        else if (gl_visinfo.red_size == 5 && gl_visinfo.green_size == 6 &&
-                 gl_visinfo.blue_size == 5 && gl_visinfo.alpha_size == 0)
+        else if (vc.red == 5 && vc.green == 6 &&
+                 vc.blue == 5 && vc.alpha == 0)
         {
             gl_color_format_ = GL_RGB565;
         }
     }
 
-    if (gl_visinfo.depth_size == 32 && supports_depth32)
+    if (vc.depth == 32 && supports_depth32)
         gl_depth_format_ = GL_DEPTH_COMPONENT32;
-    else if (gl_visinfo.depth_size >= 24 && supports_depth24)
+    else if (vc.depth >= 24 && supports_depth24)
         gl_depth_format_ = GL_DEPTH_COMPONENT24;
-    else if (gl_visinfo.depth_size == 16)
+    else if (vc.depth == 16)
         gl_depth_format_ = GL_DEPTH_COMPONENT16;
 
     Log::debug("Selected Renderbuffer ColorFormat: %s DepthFormat: %s\n",

=== modified file 'src/canvas-x11.h'
--- src/canvas-x11.h	2012-03-20 11:29:09 +0000
+++ src/canvas-x11.h	2012-05-11 11:02:37 +0000
@@ -53,18 +53,6 @@ 
         color_renderbuffer_(0), depth_renderbuffer_(0), fbo_(0) {}
 
     /**
-     * Information about a GL visual.
-     */
-    struct GLVisualInfo {
-        int buffer_size;
-        int red_size;
-        int green_size;
-        int blue_size;
-        int alpha_size;
-        int depth_size;
-    };
-
-    /**
      * Gets the XVisualInfo to use for creating the X window with.
      *
      * The caller should XFree() the returned XVisualInfo when done.
@@ -107,7 +95,7 @@ 
      *
      * This method should be implemented in derived classes.
      */
-    virtual void get_glvisualinfo(GLVisualInfo &gl_visinfo) = 0;
+    virtual void get_glvisualconfig(GLVisualConfig &visual_config) = 0;
 
     /**
      * Whether the current implementation supports GL(ES) 2.0.

=== modified file 'src/canvas.h'
--- src/canvas.h	2012-03-15 12:17:22 +0000
+++ src/canvas.h	2012-05-10 09:03:12 +0000
@@ -27,6 +27,7 @@ 
 
 #include "gl-headers.h"
 #include "mat.h"
+#include "gl-visual-config.h"
 
 #include <sys/types.h>
 #include <string>
@@ -86,6 +87,7 @@ 
         uint8_t a;
     };
 
+
     /**
      * Initializes the canvas and makes it the target of GL operations.
      *
@@ -238,6 +240,13 @@ 
      */
     void offscreen(bool offscreen) { offscreen_ = offscreen; }
 
+    /**
+     * Sets the preferred visual configuration.
+     *
+     * This takes effect after the next init()/reset().
+     */
+    void visual_config(GLVisualConfig &config) { visual_config_ = config; }
+
 protected:
     Canvas(int width, int height) :
         width_(width), height_(height), offscreen_(false) {}
@@ -246,6 +255,7 @@ 
     int height_;
     LibMatrix::mat4 projection_;
     bool offscreen_;
+    GLVisualConfig visual_config_;
 };
 
 #endif

=== added file 'src/gl-visual-config.cpp'
--- src/gl-visual-config.cpp	1970-01-01 00:00:00 +0000
+++ src/gl-visual-config.cpp	2012-05-11 13:49:53 +0000
@@ -0,0 +1,120 @@ 
+/*
+ * 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:
+ *  Alexandros Frantzis <alexandros.frantzis@linaro.org>
+ */
+#include "gl-visual-config.h"
+#include "util.h"
+#include "log.h"
+
+#include <vector>
+
+GLVisualConfig::GLVisualConfig(const std::string &s) :
+    red(1), green(1), blue(1), alpha(1), depth(1), buffer(1)
+{
+    std::vector<std::string> elems;
+
+    Util::split(s, ':', elems);
+
+    for (std::vector<std::string>::const_iterator iter = elems.begin();
+         iter != elems.end();
+         iter++)
+    {
+        std::vector<std::string> opt;
+
+        Util::split(*iter, '=', opt);
+        if (opt.size() == 2) {
+            if (opt[0] == "r" || opt[0] == "red")
+                red = Util::fromString<int>(opt[1]);
+            else if (opt[0] == "g" || opt[0] == "green")
+                green = Util::fromString<int>(opt[1]);
+            else if (opt[0] == "b" || opt[0] == "blue")
+                blue = Util::fromString<int>(opt[1]);
+            else if (opt[0] == "a" || opt[0] == "alpha")
+                alpha = Util::fromString<int>(opt[1]);
+            else if (opt[0] == "d" || opt[0] == "depth")
+                depth = Util::fromString<int>(opt[1]);
+            else if (opt[0] == "buf" || opt[0] == "buffer")
+                buffer = Util::fromString<int>(opt[1]);
+        }
+        else
+            Log::info("Warning: ignoring invalid option string '%s' "
+                      "in GLVisualConfig description\n",
+                      iter->c_str());
+    }
+}
+
+int
+GLVisualConfig::match_score(const GLVisualConfig &target) const
+{
+    int score(0);
+
+    /* 
+     * R,G,B,A integer values are at most 8 bits wide (for current widespread
+     * hardware), so we need to scale them by 4 to get them in the [0,32] range.
+     */
+    score += score_component(red, target.red, 4);
+    score += score_component(green, target.green, 4);
+    score += score_component(blue, target.blue, 4);
+    score += score_component(alpha, target.alpha, 4);
+    score += score_component(depth, target.depth, 1);
+    score += score_component(buffer, target.buffer, 1);
+
+    return score;
+}
+
+int
+GLVisualConfig::score_component(int component, int target, int scale) const
+{
+    /* 
+     * The maximum (positive) score that can be returned is based
+     * on the maximum bit width of the components. We assume this to
+     * be 32 bits, which is a reasonable assumption for current platforms.
+     */
+    static const int MAXIMUM_COMPONENT_SCORE = 32;
+    static const int UNACCEPTABLE_COMPONENT_PENALTY = -1000;
+    int score(0);
+
+    if ((component > 0 && target == 0) ||
+        (component == 0 && target > 0))
+    {
+        /* 
+         * Penalize components that are not present but have been requested,
+         * and components that have been excluded but are present.
+         */
+        score = UNACCEPTABLE_COMPONENT_PENALTY;
+    }
+    else if (component == target)
+    {
+        /* Reward exact matches with the maximum per component score */
+        score = MAXIMUM_COMPONENT_SCORE;
+    }
+    else
+    {
+        /* 
+         * Reward deeper than requested component values, penalize shallower
+         * than requested component values. Because the ranges of component
+         * values vary we use a scaling factor to even them out, so that the
+         * score for all components ranges from [0,MAXIMUM_COMPONENT_SCORE).
+         */
+        score = scale * (component - target);
+    }
+
+    return score;
+}

=== added file 'src/gl-visual-config.h'
--- src/gl-visual-config.h	1970-01-01 00:00:00 +0000
+++ src/gl-visual-config.h	2012-05-11 13:49:53 +0000
@@ -0,0 +1,64 @@ 
+/*
+ * 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:
+ *  Alexandros Frantzis <alexandros.frantzis@linaro.org>
+ */
+#ifndef GLMARK2_GL_VISUAL_CONFIG_H_
+#define GLMARK2_GL_VISUAL_CONFIG_H_
+
+#include <string>
+
+/**
+ * Configuration parameters for a GL visual
+ */
+class GLVisualConfig
+{
+public:
+    GLVisualConfig():
+        red(1), green(1), blue(1), alpha(1), depth(1), buffer(1) {}
+    GLVisualConfig(int r, int g, int b, int a, int d, int buf):
+        red(r), green(g), blue(b), alpha(a), depth(d), buffer(buf) {}
+    GLVisualConfig(const std::string &s);
+
+    /**
+     * How well a GLVisualConfig matches another target config.
+     *
+     * The returned score has no meaning on its own. Its only purpose is
+     * to allow comparison of how well different configs match a target
+     * config, with a higher scores denoting a better match.
+     *
+     * Also note that this operation is not commutative:
+     * a.match_score(b) != b.match_score(a)
+     *
+     * @return the match score
+     */
+    int match_score(const GLVisualConfig &target) const;
+
+    int red;
+    int green;
+    int blue;
+    int alpha;
+    int depth;
+    int buffer;
+
+private:
+    int score_component(int component, int target, int scale) const;
+};
+
+#endif

=== modified file 'src/main.cpp'
--- src/main.cpp	2012-04-27 18:00:45 +0000
+++ src/main.cpp	2012-05-15 08:40:46 +0000
@@ -168,6 +168,8 @@ 
 
     canvas.offscreen(Options::offscreen);
 
+    canvas.visual_config(Options::visual_config);
+
     vector<Scene*> scenes;
 
     // Register the scenes, so they can be looked up by name

=== modified file 'src/options.cpp'
--- src/options.cpp	2012-03-20 12:55:49 +0000
+++ src/options.cpp	2012-05-10 09:18:53 +0000
@@ -43,6 +43,7 @@ 
 bool Options::run_forever = false;
 bool Options::annotate = false;
 bool Options::offscreen = false;
+GLVisualConfig Options::visual_config;
 
 static struct option long_options[] = {
     {"annotate", 0, 0, 0},
@@ -51,6 +52,7 @@ 
     {"validate", 0, 0, 0},
     {"frame-end", 1, 0, 0},
     {"off-screen", 0, 0, 0},
+    {"visual-config", 1, 0, 0},
     {"reuse-context", 0, 0, 0},
     {"run-forever", 0, 0, 0},
     {"size", 1, 0, 0},
@@ -109,7 +111,6 @@ 
     return m;
 }
 
-
 void
 Options::print_help()
 {
@@ -125,6 +126,10 @@ 
            "                         running the benchmarks\n"
            "      --frame-end METHOD How to end a frame [default,none,swap,finish,readpixels]\n"
            "      --off-screen       Render to an off-screen surface\n"
+           "      --visual-config C  The visual configuration to use for the rendering\n"
+           "                         target: 'red=R:green=G:blue=B:alpha=A:buffer=BUF'.\n"
+           "                         The parameters may be defined in any order, and any\n"
+           "                         omitted parameters assume a default value of '1'\n"
            "      --reuse-context    Use a single context for all scenes\n"
            "                         (by default, each scene gets its own context)\n"
            "  -s, --size WxH         Size of the output window (default: 800x600)\n"
@@ -170,6 +175,8 @@ 
             Options::frame_end = frame_end_from_str(optarg);
         else if (!strcmp(optname, "off-screen"))
             Options::offscreen = true;
+        else if (!strcmp(optname, "visual-config"))
+            Options::visual_config = GLVisualConfig(optarg);
         else if (!strcmp(optname, "reuse-context"))
             Options::reuse_context = true;
         else if (c == 's' || !strcmp(optname, "size"))

=== modified file 'src/options.h'
--- src/options.h	2012-03-20 12:55:49 +0000
+++ src/options.h	2012-05-10 09:18:53 +0000
@@ -26,6 +26,7 @@ 
 
 #include <string>
 #include <vector>
+#include "gl-visual-config.h"
 
 struct Options {
     enum FrameEnd {
@@ -52,6 +53,7 @@ 
     static bool run_forever;
     static bool annotate;
     static bool offscreen;
+    static GLVisualConfig visual_config;
 };
 
 #endif /* OPTIONS_H_ */