From patchwork Wed Jan 18 17:17:13 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jesse Barker X-Patchwork-Id: 6281 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 77E0723FE9 for ; Wed, 18 Jan 2012 17:17:16 +0000 (UTC) Received: from mail-bk0-f52.google.com (mail-bk0-f52.google.com [209.85.214.52]) by fiordland.canonical.com (Postfix) with ESMTP id 5B7F9A1801B for ; Wed, 18 Jan 2012 17:17:16 +0000 (UTC) Received: by bkbzt4 with SMTP id zt4so3284026bkb.11 for ; Wed, 18 Jan 2012 09:17:16 -0800 (PST) Received: by 10.204.10.73 with SMTP id o9mr3283661bko.99.1326907035972; Wed, 18 Jan 2012 09:17:15 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.205.82.144 with SMTP id ac16cs154144bkc; Wed, 18 Jan 2012 09:17:15 -0800 (PST) Received: by 10.216.138.206 with SMTP id a56mr2163279wej.29.1326907033842; Wed, 18 Jan 2012 09:17:13 -0800 (PST) Received: from indium.canonical.com (indium.canonical.com. [91.189.90.7]) by mx.google.com with ESMTPS id l83si16418884weq.59.2012.01.18.09.17.13 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 18 Jan 2012 09:17:13 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) client-ip=91.189.90.7; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) smtp.mail=bounces@canonical.com Received: from ackee.canonical.com ([91.189.89.26]) by indium.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1RnZ8L-000257-GM for ; Wed, 18 Jan 2012 17:17:13 +0000 Received: from ackee.canonical.com (localhost [127.0.0.1]) by ackee.canonical.com (Postfix) with ESMTP id 5A0AFE0286 for ; Wed, 18 Jan 2012 17:17:13 +0000 (UTC) MIME-Version: 1.0 X-Launchpad-Project: glmark2 X-Launchpad-Branch: ~glmark2-dev/glmark2/trunk X-Launchpad-Message-Rationale: Subscriber X-Launchpad-Branch-Revision-Number: 189 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [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> Date: Wed, 18 Jan 2012 17:17:13 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: bulk X-Generated-By: Launchpad (canonical.com); Revision="14681"; Instance="launchpad-lazr.conf" X-Launchpad-Hash: c4cd0ed791d1c9aede98e22d97c41320d2221b5c 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 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 === 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::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);