Merge lp:~glmark2-dev/glmark2/canvas-reset into lp:glmark2/2011.11

Proposed by Jesse Barker
Status: Merged
Merged at revision: 189
Proposed branch: lp:~glmark2-dev/glmark2/canvas-reset
Merge into: lp:glmark2/2011.11
Diff against target: 399 lines (+132/-24)
12 files modified
doc/glmark2.1.in (+4/-0)
src/canvas-x11-egl.cpp (+46/-10)
src/canvas-x11-egl.h (+2/-0)
src/canvas-x11-glx.cpp (+9/-0)
src/canvas-x11-glx.h (+1/-0)
src/canvas-x11.cpp (+17/-9)
src/canvas-x11.h (+10/-0)
src/canvas.h (+10/-0)
src/main.cpp (+6/-0)
src/options.cpp (+6/-0)
src/options.h (+1/-0)
src/scene-desktop.cpp (+20/-5)
To merge this branch: bzr merge lp:~glmark2-dev/glmark2/canvas-reset
Reviewer Review Type Date Requested Status
Alexandros Frantzis Pending
Review via email: mp+88963@code.launchpad.net

Description of the change

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).

To post a comment you must log in.
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

Thansk for the fix!

Unfortunately, I am still getting artifacts when running shadow,shadow or blur,blur. Strange...

lp:~glmark2-dev/glmark2/canvas-reset updated
183. By Alexandros Frantzis

SceneDesktop: Allow RenderObjects to be safely reused after a GL context change.

When setting the size of a RenderObject, "clear" the texture contents if
they were invalidated, even if the texture size didn't change.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'doc/glmark2.1.in'
2--- doc/glmark2.1.in 2012-01-05 09:46:41 +0000
3+++ doc/glmark2.1.in 2012-01-18 16:44:23 +0000
4@@ -25,6 +25,10 @@
5 Don't update the screen by swapping the front and
6 back buffer, use glFinish() instead
7 .TP
8+\fB\-\-reuse\-context\fR
9+Use a single context for all scenes
10+(by default, each scene gets its own context)
11+.TP
12 \fB\-s\fR, \fB\-\-size WxH\fR
13 Size of the output window (default: 800x600)
14 .TP
15
16=== modified file 'src/canvas-x11-egl.cpp'
17--- src/canvas-x11-egl.cpp 2011-11-02 14:56:58 +0000
18+++ src/canvas-x11-egl.cpp 2012-01-18 16:44:23 +0000
19@@ -67,6 +67,9 @@
20 if (!ensure_egl_surface())
21 return false;
22
23+ if (!ensure_egl_context())
24+ return false;
25+
26 if (egl_context_ == eglGetCurrentContext())
27 return true;
28
29@@ -175,8 +178,35 @@
30 }
31
32 bool
33-CanvasX11EGL::ensure_egl_surface()
34-{
35+CanvasX11EGL::reset_context()
36+{
37+ if (!ensure_egl_display())
38+ return false;
39+
40+ if (!egl_context_)
41+ return true;
42+
43+ if (eglDestroyContext(egl_display_, egl_context_) == EGL_FALSE) {
44+ Log::debug("eglDestroyContext() failed with error: 0x%x\n",
45+ eglGetError());
46+ }
47+
48+ egl_context_ = 0;
49+ return true;
50+}
51+
52+bool
53+CanvasX11EGL::ensure_egl_context()
54+{
55+ if (egl_context_)
56+ return true;
57+
58+ if (!ensure_egl_display())
59+ return false;
60+
61+ if (!ensure_egl_config())
62+ return false;
63+
64 static const EGLint ctx_attribs[] = {
65 #ifdef USE_GLESv2
66 EGL_CONTEXT_CLIENT_VERSION, 2,
67@@ -184,6 +214,20 @@
68 EGL_NONE
69 };
70
71+ egl_context_ = eglCreateContext(egl_display_, egl_config_,
72+ EGL_NO_CONTEXT, ctx_attribs);
73+ if (!egl_context_) {
74+ Log::error("eglCreateContext() failed with error: 0x%x\n",
75+ eglGetError());
76+ return false;
77+ }
78+
79+ return true;
80+}
81+
82+bool
83+CanvasX11EGL::ensure_egl_surface()
84+{
85 if (egl_surface_)
86 return true;
87
88@@ -196,14 +240,6 @@
89 eglBindAPI(EGL_OPENGL_API);
90 #endif
91
92- egl_context_ = eglCreateContext(egl_display_, egl_config_,
93- EGL_NO_CONTEXT, ctx_attribs);
94- if (!egl_context_) {
95- Log::error("eglCreateContext() failed with error: %d\n",
96- eglGetError());
97- return false;
98- }
99-
100 egl_surface_ = eglCreateWindowSurface(egl_display_, egl_config_,
101 (EGLNativeWindowType) xwin_,
102 NULL);
103
104=== modified file 'src/canvas-x11-egl.h'
105--- src/canvas-x11-egl.h 2011-11-01 16:49:42 +0000
106+++ src/canvas-x11-egl.h 2012-01-18 16:44:23 +0000
107@@ -41,11 +41,13 @@
108 protected:
109 XVisualInfo *get_xvisualinfo();
110 bool make_current();
111+ bool reset_context();
112 void swap_buffers() { eglSwapBuffers(egl_display_, egl_surface_); }
113
114 private:
115 bool ensure_egl_display();
116 bool ensure_egl_config();
117+ bool ensure_egl_context();
118 bool ensure_egl_surface();
119 void init_gl_extensions();
120
121
122=== modified file 'src/canvas-x11-glx.cpp'
123--- src/canvas-x11-glx.cpp 2011-11-11 11:07:15 +0000
124+++ src/canvas-x11-glx.cpp 2012-01-18 16:44:23 +0000
125@@ -201,6 +201,15 @@
126 }
127
128 bool
129+CanvasX11GLX::reset_context()
130+{
131+ glXDestroyContext(xdpy_, glx_context_);
132+ glx_context_ = 0;
133+
134+ return true;
135+}
136+
137+bool
138 CanvasX11GLX::ensure_glx_context()
139 {
140 if (glx_context_)
141
142=== modified file 'src/canvas-x11-glx.h'
143--- src/canvas-x11-glx.h 2011-11-01 16:49:42 +0000
144+++ src/canvas-x11-glx.h 2012-01-18 16:44:23 +0000
145@@ -41,6 +41,7 @@
146 protected:
147 XVisualInfo *get_xvisualinfo();
148 bool make_current();
149+ bool reset_context();
150 void swap_buffers() { glXSwapBuffers(xdpy_, xwin_); }
151
152 private:
153
154=== modified file 'src/canvas-x11.cpp'
155--- src/canvas-x11.cpp 2011-11-24 15:52:33 +0000
156+++ src/canvas-x11.cpp 2012-01-18 16:44:23 +0000
157@@ -32,17 +32,10 @@
158 /******************
159 * Public methods *
160 ******************/
161-
162 bool
163-CanvasX11::init()
164+CanvasX11::reset()
165 {
166- xdpy_ = XOpenDisplay(NULL);
167- if (!xdpy_)
168- return false;
169-
170- resize_no_viewport(width_, height_);
171-
172- if (!xwin_)
173+ if (!reset_context())
174 return false;
175
176 if (!make_current())
177@@ -67,6 +60,21 @@
178 return true;
179 }
180
181+bool
182+CanvasX11::init()
183+{
184+ xdpy_ = XOpenDisplay(NULL);
185+ if (!xdpy_)
186+ return false;
187+
188+ resize_no_viewport(width_, height_);
189+
190+ if (!xwin_)
191+ return false;
192+
193+ return reset();
194+}
195+
196 void
197 CanvasX11::visible(bool visible)
198 {
199
200=== modified file 'src/canvas-x11.h'
201--- src/canvas-x11.h 2011-11-24 15:52:33 +0000
202+++ src/canvas-x11.h 2012-01-18 16:44:23 +0000
203@@ -35,6 +35,7 @@
204 ~CanvasX11() {}
205
206 virtual bool init();
207+ virtual bool reset();
208 virtual void visible(bool visible);
209 virtual void clear();
210 virtual void update();
211@@ -69,6 +70,15 @@
212 virtual bool make_current() = 0;
213
214 /**
215+ * Resets the underlying GL context for rendering.
216+ *
217+ * This method should be implemented in derived classes.
218+ *
219+ * @return whether the operation succeeded
220+ */
221+ virtual bool reset_context() = 0;
222+
223+ /**
224 * Swaps the GL buffers (assuming double buffering is used).
225 *
226 * This method should be implemented in derived classes.
227
228=== modified file 'src/canvas.h'
229--- src/canvas.h 2011-11-10 10:33:26 +0000
230+++ src/canvas.h 2012-01-18 16:44:23 +0000
231@@ -96,6 +96,16 @@
232 virtual bool init() { return false; }
233
234 /**
235+ * Resets the canvas, destroying and recreating resources to give each new
236+ * test scenario a fresh context for rendering.
237+ *
238+ * This method should be implemented in derived classes.
239+ *
240+ * @return whether reset succeeded
241+ */
242+ virtual bool reset() { return false; }
243+
244+ /**
245 * Changes the visibility of the canvas.
246 *
247 * The canvas is initially not visible.
248
249=== modified file 'src/main.cpp'
250--- src/main.cpp 2012-01-17 15:44:04 +0000
251+++ src/main.cpp 2012-01-18 16:44:23 +0000
252@@ -174,6 +174,9 @@
253 bench_iter != benchmarks.end();
254 bench_iter++)
255 {
256+ if (!Options::reuse_context)
257+ canvas.reset();
258+
259 bool keep_running = true;
260 Benchmark *bench = *bench_iter;
261 uint64_t fps_timestamp = Util::get_timestamp_us();
262@@ -232,6 +235,9 @@
263 bench_iter != benchmarks.end();
264 bench_iter++)
265 {
266+ if (!Options::reuse_context)
267+ canvas.reset();
268+
269 Benchmark *bench = *bench_iter;
270 Scene &scene = bench->setup_scene();
271
272
273=== modified file 'src/options.cpp'
274--- src/options.cpp 2011-12-13 14:27:23 +0000
275+++ src/options.cpp 2012-01-18 16:44:23 +0000
276@@ -41,12 +41,14 @@
277 bool Options::show_debug = false;
278 bool Options::show_fps = false;
279 bool Options::show_help = false;
280+bool Options::reuse_context = false;
281
282 static struct option long_options[] = {
283 {"benchmark", 1, 0, 0},
284 {"benchmark-file", 1, 0, 0},
285 {"validate", 0, 0, 0},
286 {"no-swap-buffers", 0, 0, 0},
287+ {"reuse-context", 0, 0, 0},
288 {"size", 1, 0, 0},
289 {"list-scenes", 0, 0, 0},
290 {"show-all-options", 0, 0, 0},
291@@ -95,6 +97,8 @@
292 " running the benchmarks\n"
293 " --no-swap-buffers Don't update the canvas by swapping the front and\n"
294 " back buffer, use glFinish() instead\n"
295+ " --reuse-context Use a single context for all scenes\n"
296+ " (by default, each scene gets its own context)\n"
297 " -s, --size WxH Size of the output window (default: 800x600)\n"
298 " -l, --list-scenes Display information about the available scenes\n"
299 " and their options\n"
300@@ -132,6 +136,8 @@
301 Options::validate = true;
302 else if (!strcmp(optname, "no-swap-buffers"))
303 Options::swap_buffers = false;
304+ else if (!strcmp(optname, "reuse-context"))
305+ Options::reuse_context = true;
306 else if (c == 's' || !strcmp(optname, "size"))
307 parse_size(optarg, Options::size);
308 else if (c == 'l' || !strcmp(optname, "list-scenes"))
309
310=== modified file 'src/options.h'
311--- src/options.h 2011-12-13 14:27:23 +0000
312+++ src/options.h 2012-01-18 16:44:23 +0000
313@@ -41,6 +41,7 @@
314 static bool show_debug;
315 static bool show_fps;
316 static bool show_help;
317+ static bool reuse_context;
318 };
319
320 #endif /* OPTIONS_H_ */
321
322=== modified file 'src/scene-desktop.cpp'
323--- src/scene-desktop.cpp 2011-12-08 11:09:09 +0000
324+++ src/scene-desktop.cpp 2012-01-18 16:44:23 +0000
325@@ -106,9 +106,9 @@
326 class RenderObject
327 {
328 public:
329- RenderObject() : texture_(0), fbo_(0), rotation_rad_(0) { }
330-
331- virtual ~RenderObject() { release(); }
332+ RenderObject() :
333+ texture_(0), fbo_(0), rotation_rad_(0),
334+ texture_contents_invalid_(true) { }
335
336 virtual void init()
337 {
338@@ -138,6 +138,7 @@
339 frg_source.str());
340 }
341
342+ texture_contents_invalid_ = true;
343 RenderObject::use_count++;
344 }
345
346@@ -182,7 +183,12 @@
347 glBindTexture(GL_TEXTURE_2D, texture_);
348 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size_.x(), size_.y(), 0,
349 GL_RGBA, GL_UNSIGNED_BYTE, 0);
350+ texture_contents_invalid_ = true;
351+ }
352+
353+ if (texture_contents_invalid_) {
354 clear();
355+ texture_contents_invalid_ = false;
356 }
357 }
358
359@@ -332,6 +338,7 @@
360 }
361
362 float rotation_rad_;
363+ bool texture_contents_invalid_;
364 static int use_count;
365
366 };
367@@ -348,6 +355,7 @@
368 {
369 public:
370 virtual void init() {}
371+ virtual void release() {}
372 };
373
374 /**
375@@ -625,7 +633,6 @@
376 shadow_v_.release();
377 shadow_corner_.release();
378 if (draw_contents_)
379- if (draw_contents_)
380 window_contents_.release();
381 }
382
383@@ -849,7 +856,15 @@
384 void
385 SceneDesktop::teardown()
386 {
387- Util::dispose_pointer_vector(priv_->windows);
388+ for (std::vector<RenderObject*>::iterator winIt = priv_->windows.begin();
389+ winIt != priv_->windows.end();
390+ winIt++)
391+ {
392+ RenderObject* curObj = *winIt;
393+ curObj->release();
394+ delete curObj;
395+ }
396+ priv_->windows.clear();
397 priv_->screen.make_current();
398
399 glEnable(GL_DEPTH_TEST);

Subscribers

People subscribed via source and target branches

to all changes: