diff mbox

[Branch,~glmark2-dev/glmark2/trunk] Rev 189: Canvas: This adds logic to the canvas and its derivatives to allow a "reset" of the canvas betwee...

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

Commit Message

Jesse Barker Jan. 18, 2012, 5:17 p.m. UTC
Merge authors:
  Alexandros Frantzis (afrantzis)
  Jesse Barker (jesse-barker)
Related merge proposals:
  https://code.launchpad.net/~glmark2-dev/glmark2/canvas-reset/+merge/88963
  proposed by: Jesse Barker (jesse-barker)
------------------------------------------------------------
revno: 189 [merge]
committer: Jesse Barker <jesse.barker@linaro.org>
branch nick: trunk
timestamp: Wed 2012-01-18 09:13:28 -0800
message:
  Canvas: This adds logic to the canvas and its derivatives to allow a "reset" of the canvas between scenes. In practice what this does is to create a fresh context for each scene. This puts each scene on a level playing field and insulates the scenes from any resource leakage and any resultant performance degradation. Also included is an option to reuse one context for all scenes (the way things have worked up to now) for the sake of being able to test for resource leakage, etc.
  
  SceneDesktop: A latent bug in the init/release symmetry in the RenderObject and its derivatives was detected as a direct result of the Canvas reset changes. This is also fixed in this branch (these changes should be taken regardless).
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
  src/scene-desktop.cpp


--
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-01-05 09:46:41 +0000
+++ doc/glmark2.1.in	2012-01-18 17:13:28 +0000
@@ -25,6 +25,10 @@ 
 Don't update the screen by swapping the front and
 back buffer, use glFinish() instead
 .TP
+\fB\-\-reuse\-context\fR
+Use a single context for all scenes
+(by default, each scene gets its own context)
+.TP
 \fB\-s\fR, \fB\-\-size WxH\fR
 Size of the output window (default: 800x600)
 .TP

=== modified file 'src/canvas-x11-egl.cpp'
--- src/canvas-x11-egl.cpp	2011-11-02 14:56:58 +0000
+++ src/canvas-x11-egl.cpp	2012-01-04 16:51:20 +0000
@@ -67,6 +67,9 @@ 
     if (!ensure_egl_surface())
         return false;
 
+    if (!ensure_egl_context())
+        return false;
+
     if (egl_context_ == eglGetCurrentContext())
         return true;
 
@@ -175,8 +178,35 @@ 
 }
 
 bool
-CanvasX11EGL::ensure_egl_surface()
-{
+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,
@@ -184,6 +214,20 @@ 
         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;
 
@@ -196,14 +240,6 @@ 
     eglBindAPI(EGL_OPENGL_API);
 #endif
 
-    egl_context_ = eglCreateContext(egl_display_, egl_config_,
-                                    EGL_NO_CONTEXT, ctx_attribs);
-    if (!egl_context_) {
-        Log::error("eglCreateContext() failed with error: %d\n",
-                     eglGetError());
-        return false;
-    }
-
     egl_surface_ = eglCreateWindowSurface(egl_display_, egl_config_,
                                           (EGLNativeWindowType) xwin_,
                                           NULL);

=== modified file 'src/canvas-x11-egl.h'
--- src/canvas-x11-egl.h	2011-11-01 16:49:42 +0000
+++ src/canvas-x11-egl.h	2012-01-04 00:37:12 +0000
@@ -41,11 +41,13 @@ 
 protected:
     XVisualInfo *get_xvisualinfo();
     bool make_current();
+    bool reset_context();
     void swap_buffers() { eglSwapBuffers(egl_display_, egl_surface_); }
 
 private:
     bool ensure_egl_display();
     bool ensure_egl_config();
+    bool ensure_egl_context();
     bool ensure_egl_surface();
     void init_gl_extensions();
 

=== modified file 'src/canvas-x11-glx.cpp'
--- src/canvas-x11-glx.cpp	2011-11-11 11:07:15 +0000
+++ src/canvas-x11-glx.cpp	2012-01-04 00:37:12 +0000
@@ -201,6 +201,15 @@ 
 }
 
 bool
+CanvasX11GLX::reset_context()
+{
+    glXDestroyContext(xdpy_, glx_context_);
+    glx_context_ = 0;
+
+    return true;
+}
+
+bool
 CanvasX11GLX::ensure_glx_context()
 {
     if (glx_context_)

=== modified file 'src/canvas-x11-glx.h'
--- src/canvas-x11-glx.h	2011-11-01 16:49:42 +0000
+++ src/canvas-x11-glx.h	2012-01-04 00:37:12 +0000
@@ -41,6 +41,7 @@ 
 protected:
     XVisualInfo *get_xvisualinfo();
     bool make_current();
+    bool reset_context();
     void swap_buffers() { glXSwapBuffers(xdpy_, xwin_); }
 
 private:

=== modified file 'src/canvas-x11.cpp'
--- src/canvas-x11.cpp	2011-11-24 15:52:33 +0000
+++ src/canvas-x11.cpp	2012-01-04 00:37:12 +0000
@@ -32,17 +32,10 @@ 
 /******************
  * Public methods *
  ******************/
-
 bool
-CanvasX11::init()
+CanvasX11::reset()
 {
-    xdpy_ = XOpenDisplay(NULL);
-    if (!xdpy_)
-        return false;
-
-    resize_no_viewport(width_, height_);
-
-    if (!xwin_)
+    if (!reset_context())
         return false;
 
     if (!make_current())
@@ -67,6 +60,21 @@ 
     return true;
 }
 
+bool
+CanvasX11::init()
+{
+    xdpy_ = XOpenDisplay(NULL);
+    if (!xdpy_)
+        return false;
+
+    resize_no_viewport(width_, height_);
+
+    if (!xwin_)
+        return false;
+
+    return reset();
+}
+
 void
 CanvasX11::visible(bool visible)
 {

=== modified file 'src/canvas-x11.h'
--- src/canvas-x11.h	2011-11-24 15:52:33 +0000
+++ src/canvas-x11.h	2012-01-04 00:37:12 +0000
@@ -35,6 +35,7 @@ 
     ~CanvasX11() {}
 
     virtual bool init();
+    virtual bool reset();
     virtual void visible(bool visible);
     virtual void clear();
     virtual void update();
@@ -69,6 +70,15 @@ 
     virtual bool make_current() = 0;
 
     /**
+     * Resets the underlying GL context for rendering.
+     *
+     * This method should be implemented in derived classes.
+     *
+     * @return whether the operation succeeded
+     */
+    virtual bool reset_context() = 0;
+
+    /**
      * Swaps the GL buffers (assuming double buffering is used).
      *
      * This method should be implemented in derived classes.

=== modified file 'src/canvas.h'
--- src/canvas.h	2011-11-10 10:33:26 +0000
+++ src/canvas.h	2012-01-04 00:37:12 +0000
@@ -96,6 +96,16 @@ 
     virtual bool init() { return false; }
 
     /**
+     * Resets the canvas, destroying and recreating resources to give each new
+     * test scenario a fresh context for rendering.
+     *
+     * This method should be implemented in derived classes.
+     *
+     * @return whether reset succeeded
+     */
+    virtual bool reset() { return false; }
+
+    /**
      * Changes the visibility of the canvas.
      *
      * The canvas is initially not visible.

=== modified file 'src/main.cpp'
--- src/main.cpp	2012-01-17 15:44:04 +0000
+++ src/main.cpp	2012-01-18 17:13:28 +0000
@@ -174,6 +174,9 @@ 
          bench_iter != benchmarks.end();
          bench_iter++)
     {
+        if (!Options::reuse_context)
+            canvas.reset();
+
         bool keep_running = true;
         Benchmark *bench = *bench_iter;
         uint64_t fps_timestamp = Util::get_timestamp_us();
@@ -232,6 +235,9 @@ 
          bench_iter != benchmarks.end();
          bench_iter++)
     {
+        if (!Options::reuse_context)
+            canvas.reset();
+
         Benchmark *bench = *bench_iter;
         Scene &scene = bench->setup_scene();
 

=== modified file 'src/options.cpp'
--- src/options.cpp	2011-12-13 14:27:23 +0000
+++ src/options.cpp	2012-01-18 17:13:28 +0000
@@ -41,12 +41,14 @@ 
 bool Options::show_debug = false;
 bool Options::show_fps = false;
 bool Options::show_help = false;
+bool Options::reuse_context = false;
 
 static struct option long_options[] = {
     {"benchmark", 1, 0, 0},
     {"benchmark-file", 1, 0, 0},
     {"validate", 0, 0, 0},
     {"no-swap-buffers", 0, 0, 0},
+    {"reuse-context", 0, 0, 0},
     {"size", 1, 0, 0},
     {"list-scenes", 0, 0, 0},
     {"show-all-options", 0, 0, 0},
@@ -95,6 +97,8 @@ 
            "                         running the benchmarks\n"
            "      --no-swap-buffers  Don't update the canvas by swapping the front and\n"
            "                         back buffer, use glFinish() instead\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"
            "  -l, --list-scenes      Display information about the available scenes\n"
            "                         and their options\n"
@@ -132,6 +136,8 @@ 
             Options::validate = true;
         else if (!strcmp(optname, "no-swap-buffers"))
             Options::swap_buffers = false;
+        else if (!strcmp(optname, "reuse-context"))
+            Options::reuse_context = true;
         else if (c == 's' || !strcmp(optname, "size"))
             parse_size(optarg, Options::size);
         else if (c == 'l' || !strcmp(optname, "list-scenes"))

=== modified file 'src/options.h'
--- src/options.h	2011-12-13 14:27:23 +0000
+++ src/options.h	2012-01-18 17:13:28 +0000
@@ -41,6 +41,7 @@ 
     static bool show_debug;
     static bool show_fps;
     static bool show_help;
+    static bool reuse_context;
 };
 
 #endif /* OPTIONS_H_ */

=== modified file 'src/scene-desktop.cpp'
--- src/scene-desktop.cpp	2011-12-08 11:09:09 +0000
+++ src/scene-desktop.cpp	2012-01-18 16:40:14 +0000
@@ -106,9 +106,9 @@ 
 class RenderObject
 {
 public:
-    RenderObject() : texture_(0), fbo_(0), rotation_rad_(0) { }
-
-    virtual ~RenderObject() { release(); }
+    RenderObject() :
+        texture_(0), fbo_(0), rotation_rad_(0),
+        texture_contents_invalid_(true) { }
 
     virtual void init()
     {
@@ -138,6 +138,7 @@ 
                                              frg_source.str());
         }
 
+        texture_contents_invalid_ = true;
         RenderObject::use_count++;
     }
 
@@ -182,7 +183,12 @@ 
             glBindTexture(GL_TEXTURE_2D, texture_);
             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size_.x(), size_.y(), 0,
                          GL_RGBA, GL_UNSIGNED_BYTE, 0);
+            texture_contents_invalid_ = true;
+        }
+
+        if (texture_contents_invalid_) {
             clear();
+            texture_contents_invalid_ = false;
         }
     }
 
@@ -332,6 +338,7 @@ 
     }
 
     float rotation_rad_;
+    bool texture_contents_invalid_;
     static int use_count;
 
 };
@@ -348,6 +355,7 @@ 
 {
 public:
     virtual void init() {}
+    virtual void release() {}
 };
 
 /**
@@ -625,7 +633,6 @@ 
             shadow_v_.release();
             shadow_corner_.release();
             if (draw_contents_)
-            if (draw_contents_)
                 window_contents_.release();
         }
 
@@ -849,7 +856,15 @@ 
 void
 SceneDesktop::teardown()
 {
-    Util::dispose_pointer_vector(priv_->windows);
+    for (std::vector<RenderObject*>::iterator winIt = priv_->windows.begin();
+         winIt != priv_->windows.end();
+         winIt++)
+    {
+        RenderObject* curObj = *winIt;
+        curObj->release();
+        delete curObj;
+    }
+    priv_->windows.clear();
     priv_->screen.make_current();
 
     glEnable(GL_DEPTH_TEST);