Merge lp:~linaro-graphics-wg/glmark2/desktop into lp:glmark2/2011.11

Proposed by Alexandros Frantzis
Status: Merged
Merged at revision: 130
Proposed branch: lp:~linaro-graphics-wg/glmark2/desktop
Merge into: lp:glmark2/2011.11
Diff against target: 958 lines (+848/-8)
9 files modified
data/shaders/desktop-blur.frag (+17/-0)
data/shaders/desktop.frag (+14/-0)
data/shaders/desktop.vert (+11/-0)
src/android.cpp (+2/-0)
src/canvas-android.cpp (+2/-2)
src/canvas-x11.cpp (+6/-6)
src/main.cpp (+2/-0)
src/scene-desktop.cpp (+775/-0)
src/scene.h (+19/-0)
To merge this branch: bzr merge lp:~linaro-graphics-wg/glmark2/desktop
Reviewer Review Type Date Requested Status
Jesse Barker Pending
Review via email: mp+75039@code.launchpad.net

Description of the change

New "desktop" benchmarking scene and one effect (blur).

To post a comment you must log in.
Revision history for this message
Jesse Barker (jesse-barker) wrote :
Download full text (31.3 KiB)

Overall, looks really good. I like it. A few very small nits inline,
none of which should hold up the merge (and are all optional)...

On Mon, Sep 12, 2011 at 9:40 AM, Alexandros Frantzis <email address hidden> wrote:
> Alexandros Frantzis has proposed merging lp:~linaro-graphics-wg/glmark2/desktop into lp:glmark2.
>
> Requested reviews:
>  Jesse Barker (jesse-barker)
>
> For more details, see:
> https://code.launchpad.net/~linaro-graphics-wg/glmark2/desktop/+merge/75039
>
> New "desktop" benchmarking scene and one effect (blur).
> --
> https://code.launchpad.net/~linaro-graphics-wg/glmark2/desktop/+merge/75039
> You are requested to review the proposed merge of lp:~linaro-graphics-wg/glmark2/desktop into lp:glmark2.
>
> === added file 'data/shaders/desktop-blur.frag'
> --- data/shaders/desktop-blur.frag      1970-01-01 00:00:00 +0000
> +++ data/shaders/desktop-blur.frag      2011-09-12 16:40:37 +0000
> @@ -0,0 +1,17 @@
> +#ifdef GL_ES
> +precision mediump float;
> +#endif
> +
> +uniform sampler2D Texture0;
> +
> +varying vec2 TextureCoord;
> +
> +void main(void)
> +{
> +    vec4 result;
> +
> +    $CONVOLUTION$
> +
> +    gl_FragColor = result;
> +}
> +
>
> === added file 'data/shaders/desktop.frag'
> --- data/shaders/desktop.frag   1970-01-01 00:00:00 +0000
> +++ data/shaders/desktop.frag   2011-09-12 16:40:37 +0000
> @@ -0,0 +1,14 @@
> +#ifdef GL_ES
> +precision mediump float;
> +#endif
> +
> +uniform sampler2D MaterialTexture0;
> +
> +varying vec2 TextureCoord;
> +
> +void main(void)
> +{
> +    vec4 texel = texture2D(MaterialTexture0, TextureCoord);
> +    gl_FragColor = texel;
> +}
> +
>
> === added file 'data/shaders/desktop.vert'
> --- data/shaders/desktop.vert   1970-01-01 00:00:00 +0000
> +++ data/shaders/desktop.vert   2011-09-12 16:40:37 +0000
> @@ -0,0 +1,11 @@
> +attribute vec2 position;
> +attribute vec2 texcoord;
> +
> +varying vec2 TextureCoord;
> +
> +void main(void)
> +{
> +    gl_Position = vec4(position, 0.0, 1.0);
> +
> +    TextureCoord = texcoord;
> +}
>
> === added file 'data/textures/desktop-window.png'
> Binary files data/textures/desktop-window.png   1970-01-01 00:00:00 +0000 and data/textures/desktop-window.png  2011-09-12 16:40:37 +0000 differ
> === modified file 'src/android.cpp'
> --- src/android.cpp     2011-08-18 15:03:40 +0000
> +++ src/android.cpp     2011-09-12 16:40:37 +0000
> @@ -44,6 +44,7 @@
>     "effect2d:kernel=0,1,0;1,-4,1;0,1,0;",
>     "effect2d:kernel=1,1,1,1,1;1,1,1,1,1;1,1,1,1,1;",
>     "pulsar:quads=5:texture=false:light=false",
> +    "desktop:windows=4:effect=blur:blur-radius=5:passes=1:separable=true",
>     "conditionals:vertex-steps=0:fragment-steps=0",
>     "conditionals:vertex-steps=0:fragment-steps=5",
>     "conditionals:vertex-steps=5:fragment-steps=0",
> @@ -85,6 +86,7 @@
>     Benchmark::register_scene(*new SceneBump(*g_canvas));
>     Benchmark::register_scene(*new SceneEffect2D(*g_canvas));
>     Benchmark::register_scene(*new ScenePulsar(*g_canvas));
> +    Benchmark::register_scene(*new SceneDesktop(canvas));
>
>     add_default_benchmarks(g_benchmarks);
>
>
> === modified file 'src/canvas-android.cpp'
> --- src/canvas-android.cpp      2011-08-10 18:00:03 +0000
> +++ src/canv...

139. By Alexandros Frantzis

SceneDesktop: Set texture and fbo variables to 0 after deleting their resources.

140. By Alexandros Frantzis

SceneDesktop: Code cleanup.

Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

> > +protected:
> > +    void draw_quad_with_program(const GLfloat *position, const GLfloat
> *texcoord,
> > +                                Program &program)
>
> Why not make this take "const vector<vec2>& position" and "const
> vector<vec2>& texcoord"? Works just fine with the GL interfaces....

The reasons I am not keen on this are:

1. Currently (ie not C++11) there is no simple way to initialize a static const std::vector.
2. Due to the way the vector is going to be used in the function (&vector[0]), all safety benefits of using std::vector are essentially lost.
3. We don't really need a variable-size container in this case.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'data/shaders/desktop-blur.frag'
2--- data/shaders/desktop-blur.frag 1970-01-01 00:00:00 +0000
3+++ data/shaders/desktop-blur.frag 2011-09-13 09:41:05 +0000
4@@ -0,0 +1,17 @@
5+#ifdef GL_ES
6+precision mediump float;
7+#endif
8+
9+uniform sampler2D Texture0;
10+
11+varying vec2 TextureCoord;
12+
13+void main(void)
14+{
15+ vec4 result;
16+
17+ $CONVOLUTION$
18+
19+ gl_FragColor = result;
20+}
21+
22
23=== added file 'data/shaders/desktop.frag'
24--- data/shaders/desktop.frag 1970-01-01 00:00:00 +0000
25+++ data/shaders/desktop.frag 2011-09-13 09:41:05 +0000
26@@ -0,0 +1,14 @@
27+#ifdef GL_ES
28+precision mediump float;
29+#endif
30+
31+uniform sampler2D MaterialTexture0;
32+
33+varying vec2 TextureCoord;
34+
35+void main(void)
36+{
37+ vec4 texel = texture2D(MaterialTexture0, TextureCoord);
38+ gl_FragColor = texel;
39+}
40+
41
42=== added file 'data/shaders/desktop.vert'
43--- data/shaders/desktop.vert 1970-01-01 00:00:00 +0000
44+++ data/shaders/desktop.vert 2011-09-13 09:41:05 +0000
45@@ -0,0 +1,11 @@
46+attribute vec2 position;
47+attribute vec2 texcoord;
48+
49+varying vec2 TextureCoord;
50+
51+void main(void)
52+{
53+ gl_Position = vec4(position, 0.0, 1.0);
54+
55+ TextureCoord = texcoord;
56+}
57
58=== added file 'data/textures/desktop-window.png'
59Binary files data/textures/desktop-window.png 1970-01-01 00:00:00 +0000 and data/textures/desktop-window.png 2011-09-13 09:41:05 +0000 differ
60=== modified file 'src/android.cpp'
61--- src/android.cpp 2011-08-18 15:03:40 +0000
62+++ src/android.cpp 2011-09-13 09:41:05 +0000
63@@ -44,6 +44,7 @@
64 "effect2d:kernel=0,1,0;1,-4,1;0,1,0;",
65 "effect2d:kernel=1,1,1,1,1;1,1,1,1,1;1,1,1,1,1;",
66 "pulsar:quads=5:texture=false:light=false",
67+ "desktop:windows=4:effect=blur:blur-radius=5:passes=1:separable=true",
68 "conditionals:vertex-steps=0:fragment-steps=0",
69 "conditionals:vertex-steps=0:fragment-steps=5",
70 "conditionals:vertex-steps=5:fragment-steps=0",
71@@ -85,6 +86,7 @@
72 Benchmark::register_scene(*new SceneBump(*g_canvas));
73 Benchmark::register_scene(*new SceneEffect2D(*g_canvas));
74 Benchmark::register_scene(*new ScenePulsar(*g_canvas));
75+ Benchmark::register_scene(*new SceneDesktop(canvas));
76
77 add_default_benchmarks(g_benchmarks);
78
79
80=== modified file 'src/canvas-android.cpp'
81--- src/canvas-android.cpp 2011-08-10 18:00:03 +0000
82+++ src/canvas-android.cpp 2011-09-13 09:41:05 +0000
83@@ -35,8 +35,6 @@
84 if (!eglSwapInterval(eglGetCurrentDisplay(), 0))
85 Log::info("** Failed to set swap interval. Results may be bounded above by refresh rate.\n");
86
87- glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
88- glClearDepthf(1.0f);
89 glEnable(GL_DEPTH_TEST);
90 glDepthFunc(GL_LEQUAL);
91 glEnable(GL_CULL_FACE);
92@@ -56,6 +54,8 @@
93 void
94 CanvasAndroid::clear()
95 {
96+ glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
97+ glClearDepthf(1.0f);
98 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
99 }
100
101
102=== modified file 'src/canvas-x11.cpp'
103--- src/canvas-x11.cpp 2011-08-09 10:51:03 +0000
104+++ src/canvas-x11.cpp 2011-09-13 09:41:05 +0000
105@@ -84,12 +84,6 @@
106 if (!make_current())
107 return false;
108
109- glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
110-#if USE_GL
111- glClearDepth(1.0f);
112-#elif USE_GLESv2
113- glClearDepthf(1.0f);
114-#endif
115 glEnable(GL_DEPTH_TEST);
116 glDepthFunc(GL_LEQUAL);
117 glEnable(GL_CULL_FACE);
118@@ -110,6 +104,12 @@
119 void
120 CanvasX11::clear()
121 {
122+ glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
123+#if USE_GL
124+ glClearDepth(1.0f);
125+#elif USE_GLESv2
126+ glClearDepthf(1.0f);
127+#endif
128 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
129 }
130
131
132=== modified file 'src/main.cpp'
133--- src/main.cpp 2011-09-07 09:40:57 +0000
134+++ src/main.cpp 2011-09-13 09:41:05 +0000
135@@ -54,6 +54,7 @@
136 "effect2d:kernel=0,1,0;1,-4,1;0,1,0;",
137 "effect2d:kernel=1,1,1,1,1;1,1,1,1,1;1,1,1,1,1;",
138 "pulsar:quads=5:texture=false:light=false",
139+ "desktop:windows=4:effect=blur:blur-radius=5:passes=1:separable=true",
140 "conditionals:vertex-steps=0:fragment-steps=0",
141 "conditionals:vertex-steps=0:fragment-steps=5",
142 "conditionals:vertex-steps=5:fragment-steps=0",
143@@ -96,6 +97,7 @@
144 scenes.push_back(new SceneBump(canvas));
145 scenes.push_back(new SceneEffect2D(canvas));
146 scenes.push_back(new ScenePulsar(canvas));
147+ scenes.push_back(new SceneDesktop(canvas));
148
149 for (vector<Scene*>::const_iterator iter = scenes.begin();
150 iter != scenes.end();
151
152=== added file 'src/scene-desktop.cpp'
153--- src/scene-desktop.cpp 1970-01-01 00:00:00 +0000
154+++ src/scene-desktop.cpp 2011-09-13 09:41:05 +0000
155@@ -0,0 +1,775 @@
156+/*
157+ * Copyright © 2010-2011 Linaro Limited
158+ *
159+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
160+ *
161+ * glmark2 is free software: you can redistribute it and/or modify it under the
162+ * terms of the GNU General Public License as published by the Free Software
163+ * Foundation, either version 3 of the License, or (at your option) any later
164+ * version.
165+ *
166+ * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
167+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
168+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
169+ * details.
170+ *
171+ * You should have received a copy of the GNU General Public License along with
172+ * glmark2. If not, see <http://www.gnu.org/licenses/>.
173+ *
174+ * Authors:
175+ * Alexandros Frantzis (glmark2)
176+ */
177+#include <cmath>
178+
179+#include "scene.h"
180+#include "mat.h"
181+#include "stack.h"
182+#include "vec.h"
183+#include "log.h"
184+#include "program.h"
185+#include "shader-source.h"
186+#include "util.h"
187+
188+enum BlurDirection {
189+ BlurDirectionHorizontal,
190+ BlurDirectionVertical,
191+ BlurDirectionBoth
192+};
193+
194+static void
195+create_blur_shaders(ShaderSource& vtx_source, ShaderSource& frg_source,
196+ unsigned int radius, float sigma, BlurDirection direction)
197+{
198+ vtx_source.append_file(GLMARK_DATA_PATH"/shaders/desktop.vert");
199+ frg_source.append_file(GLMARK_DATA_PATH"/shaders/desktop-blur.frag");
200+
201+ /* Don't let the gaussian curve become too narrow */
202+ if (sigma < 1.0)
203+ sigma = 1.0;
204+
205+ unsigned int side = 2 * radius + 1;
206+
207+ for (size_t i = 0; i < radius + 1; i++) {
208+ float s2 = 2.0 * sigma * sigma;
209+ float k = 1.0 / std::sqrt(M_PI * s2) * std::exp( - ((float)i * i) / s2);
210+ std::stringstream ss_tmp;
211+ ss_tmp << "Kernel" << i;
212+ frg_source.add_const(ss_tmp.str(), k);
213+ }
214+
215+ std::stringstream ss;
216+ ss << "result = " << std::endl;
217+
218+ if (direction == BlurDirectionHorizontal) {
219+ for (size_t i = 0; i < side; i++) {
220+ int offset = (int)(i - radius);
221+ ss << "texture2D(Texture0, TextureCoord + vec2(" <<
222+ offset << ".0 * TextureStepX, 0.0)) * Kernel" <<
223+ std::abs(offset) << " +" << std::endl;
224+ }
225+ ss << "0.0 ;" << std::endl;
226+ }
227+ else if (direction == BlurDirectionVertical) {
228+ for (size_t i = 0; i < side; i++) {
229+ int offset = (int)(i - radius);
230+ ss << "texture2D(Texture0, TextureCoord + vec2(0.0, " <<
231+ offset << ".0 * TextureStepY)) * Kernel" <<
232+ std::abs(offset) << " +" << std::endl;
233+ }
234+ ss << "0.0 ;" << std::endl;
235+ }
236+ else if (direction == BlurDirectionBoth) {
237+ for (size_t i = 0; i < side; i++) {
238+ int ioffset = (int)(i - radius);
239+ for (size_t j = 0; j < side; j++) {
240+ int joffset = (int)(j - radius);
241+ ss << "texture2D(Texture0, TextureCoord + vec2(" <<
242+ ioffset << ".0 * TextureStepX, " <<
243+ joffset << ".0 * TextureStepY))" <<
244+ " * Kernel" << std::abs(ioffset) <<
245+ " * Kernel" << std::abs(joffset) << " +" << std::endl;
246+ }
247+ }
248+ ss << " 0.0;" << std::endl;
249+ }
250+
251+ frg_source.replace("$CONVOLUTION$", ss.str());
252+}
253+
254+/**
255+ * A RenderObject represents a source and target of rendering
256+ * operations.
257+ */
258+class RenderObject
259+{
260+public:
261+ RenderObject() : texture_(0), fbo_(0) { }
262+
263+ virtual ~RenderObject() { release(); }
264+
265+ virtual void init()
266+ {
267+ /* Create a texture to draw to */
268+ glGenTextures(1, &texture_);
269+ glBindTexture(GL_TEXTURE_2D, texture_);
270+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
271+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
272+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
273+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
274+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size_.x(), size_.y(), 0,
275+ GL_RGBA, GL_UNSIGNED_BYTE, 0);
276+
277+ /* Create a FBO */
278+ glGenFramebuffers(1, &fbo_);
279+ glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
280+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
281+ GL_TEXTURE_2D, texture_, 0);
282+
283+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
284+
285+ /* Load the shader program when this class if first used */
286+ if (RenderObject::use_count == 0) {
287+ ShaderSource vtx_source(GLMARK_DATA_PATH"/shaders/desktop.vert");
288+ ShaderSource frg_source(GLMARK_DATA_PATH"/shaders/desktop.frag");
289+ Scene::load_shaders_from_strings(main_program, vtx_source.str(),
290+ frg_source.str());
291+ }
292+
293+ RenderObject::use_count++;
294+ }
295+
296+ virtual void release()
297+ {
298+ /* Release resources */
299+ glDeleteTextures(1, &texture_);
300+ glDeleteFramebuffers(1, &fbo_);
301+ texture_ = 0;
302+ fbo_ = 0;
303+
304+ /*
305+ * Release the shader program when object of this class
306+ * are no longer in use.
307+ */
308+ RenderObject::use_count--;
309+ if (RenderObject::use_count == 0)
310+ RenderObject::main_program.release();
311+ }
312+
313+ void make_current()
314+ {
315+ glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
316+ glViewport(0, 0, size_.x(), size_.y());
317+ }
318+
319+ void position(const LibMatrix::vec2& pos) { pos_ = pos; }
320+ const LibMatrix::vec2& position() { return pos_; }
321+
322+
323+ virtual void size(const LibMatrix::vec2& size)
324+ {
325+ /* Recreate the backing texture with correct size */
326+ if (size_.x() != size.x() || size_.y() != size.y()) {
327+ size_ = size;
328+ glBindTexture(GL_TEXTURE_2D, texture_);
329+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size_.x(), size_.y(), 0,
330+ GL_RGBA, GL_UNSIGNED_BYTE, 0);
331+ clear();
332+ }
333+ }
334+
335+ const LibMatrix::vec2& size() { return size_; }
336+
337+ const LibMatrix::vec2& speed() { return speed_; }
338+ void speed(const LibMatrix::vec2& speed) { speed_ = speed; }
339+
340+ GLuint texture() { return texture_; }
341+
342+ virtual void clear()
343+ {
344+ make_current();
345+ glClear(GL_COLOR_BUFFER_BIT);
346+ }
347+
348+ virtual void render_to(RenderObject& target, Program& program = main_program)
349+ {
350+ LibMatrix::vec2 final_pos(pos_ + size_);
351+ LibMatrix::vec2 ll(target.normalize_position(pos_));
352+ LibMatrix::vec2 ur(target.normalize_position(final_pos));
353+
354+ GLfloat position[2 * 4] = {
355+ ll.x(), ll.y(),
356+ ur.x(), ll.y(),
357+ ll.x(), ur.y(),
358+ ur.x(), ur.y(),
359+ };
360+
361+ static const GLfloat texcoord[2 * 4] = {
362+ 0.0, 0.0,
363+ 1.0, 0.0,
364+ 0.0, 1.0,
365+ 1.0, 1.0,
366+ };
367+
368+ target.make_current();
369+
370+ glActiveTexture(GL_TEXTURE0);
371+ glBindTexture(GL_TEXTURE_2D, texture_);
372+ draw_quad_with_program(position, texcoord, program);
373+ }
374+
375+ virtual void render_from(RenderObject& target, Program& program = main_program)
376+ {
377+ LibMatrix::vec2 final_pos(pos_ + size_);
378+ LibMatrix::vec2 ll_tex(target.normalize_texcoord(pos_));
379+ LibMatrix::vec2 ur_tex(target.normalize_texcoord(final_pos));
380+
381+ static const GLfloat position_blur[2 * 4] = {
382+ -1.0, -1.0,
383+ 1.0, -1.0,
384+ -1.0, 1.0,
385+ 1.0, 1.0,
386+ };
387+ GLfloat texcoord_blur[2 * 4] = {
388+ ll_tex.x(), ll_tex.y(),
389+ ur_tex.x(), ll_tex.y(),
390+ ll_tex.x(), ur_tex.y(),
391+ ur_tex.x(), ur_tex.y(),
392+ };
393+
394+ make_current();
395+ glBindTexture(GL_TEXTURE_2D, target.texture());
396+ draw_quad_with_program(position_blur, texcoord_blur, program);
397+ }
398+
399+ /**
400+ * Normalizes a position from [0, size] to [-1.0, 1.0]
401+ */
402+ LibMatrix::vec2 normalize_position(LibMatrix::vec2& pos)
403+ {
404+ return LibMatrix::vec2(2.0 * pos.x() / size_.x() - 1.0,
405+ 2.0 * pos.y() / size_.y() - 1.0);
406+ }
407+
408+ /**
409+ * Normalizes a position from [0, size] to [0.0, 1.0]
410+ */
411+ LibMatrix::vec2 normalize_texcoord(LibMatrix::vec2& pos)
412+ {
413+ return LibMatrix::vec2(pos.x() / size_.x(),
414+ pos.y() / size_.y());
415+ }
416+
417+
418+protected:
419+ void draw_quad_with_program(const GLfloat *position, const GLfloat *texcoord,
420+ Program &program)
421+ {
422+ int pos_index = program["position"].location();
423+ int tex_index = program["texcoord"].location();
424+
425+ program.start();
426+
427+ glEnableVertexAttribArray(pos_index);
428+ glEnableVertexAttribArray(tex_index);
429+ glVertexAttribPointer(pos_index, 2,
430+ GL_FLOAT, GL_FALSE, 0, position);
431+ glVertexAttribPointer(tex_index, 2,
432+ GL_FLOAT, GL_FALSE, 0, texcoord);
433+
434+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
435+
436+ glDisableVertexAttribArray(tex_index);
437+ glDisableVertexAttribArray(pos_index);
438+
439+ program.stop();
440+ }
441+
442+ static Program main_program;
443+
444+ LibMatrix::vec2 pos_;
445+ LibMatrix::vec2 size_;
446+ LibMatrix::vec2 speed_;
447+ GLuint texture_;
448+ GLuint fbo_;
449+
450+private:
451+ static int use_count;
452+
453+};
454+
455+int RenderObject::use_count = 0;
456+Program RenderObject::main_program;
457+
458+/**
459+ * A RenderObject representing the screen.
460+ *
461+ * Rendering to this objects renders to the screen framebuffer.
462+ */
463+class RenderScreen : public RenderObject
464+{
465+public:
466+ virtual void init() {}
467+};
468+
469+/**
470+ * A RenderObject with a background image.
471+ *
472+ * The image is drawn to the RenderObject automatically when the
473+ * object is cleared, resized etc
474+ */
475+class RenderClearImage : public RenderObject
476+{
477+public:
478+ RenderClearImage(const std::string& texture) :
479+ RenderObject(), background_texture_name(texture),
480+ background_texture_(0) {}
481+
482+ virtual void init()
483+ {
484+ RenderObject::init();
485+
486+ /* Load the image into a texture */
487+ Texture::load(background_texture_name,
488+ &background_texture_, GL_LINEAR, GL_LINEAR, 0);
489+
490+ }
491+
492+ virtual void release()
493+ {
494+ glDeleteTextures(1, &background_texture_);
495+ background_texture_ = 0;
496+
497+ RenderObject::release();
498+ }
499+
500+ virtual void clear()
501+ {
502+ static const GLfloat position[2 * 4] = {
503+ -1.0, -1.0,
504+ 1.0, -1.0,
505+ -1.0, 1.0,
506+ 1.0, 1.0,
507+ };
508+ static const GLfloat texcoord[2 * 4] = {
509+ 0.0, 0.0,
510+ 1.0, 0.0,
511+ 0.0, 1.0,
512+ 1.0, 1.0,
513+ };
514+
515+ make_current();
516+ glClear(GL_COLOR_BUFFER_BIT);
517+
518+ glActiveTexture(GL_TEXTURE0);
519+ glBindTexture(GL_TEXTURE_2D, background_texture_);
520+
521+ glEnable(GL_BLEND);
522+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
523+ draw_quad_with_program(position, texcoord, main_program);
524+ glDisable(GL_BLEND);
525+ }
526+
527+private:
528+ std::string background_texture_name;
529+ GLuint background_texture_;
530+};
531+
532+/**
533+ * A RenderObject that blurs the target it is drawn to.
534+ */
535+class RenderWindowBlur : public RenderObject
536+{
537+public:
538+ RenderWindowBlur(unsigned int passes, unsigned int radius, bool separable,
539+ bool draw_contents = true) :
540+ RenderObject(), passes_(passes), radius_(radius), separable_(separable),
541+ draw_contents_(draw_contents) {}
542+
543+ virtual void init()
544+ {
545+ RenderObject::init();
546+
547+ /* Only have one instance of the window contents data */
548+ if (draw_contents_ && RenderWindowBlur::use_count == 0)
549+ window_contents_.init();
550+
551+ RenderWindowBlur::use_count++;
552+ }
553+
554+ virtual void release()
555+ {
556+ RenderWindowBlur::use_count--;
557+
558+ /* Only have one instance of the window contents data */
559+ if (draw_contents_ && RenderWindowBlur::use_count == 0)
560+ window_contents_.release();
561+
562+ RenderObject::release();
563+ }
564+
565+ virtual void size(const LibMatrix::vec2& size)
566+ {
567+ RenderObject::size(size);
568+ if (draw_contents_)
569+ window_contents_.size(size);
570+ }
571+
572+ virtual void render_to(RenderObject& target, Program& program)
573+ {
574+ (void)program;
575+
576+ if (separable_) {
577+ Program& blur_program_h1 = blur_program_h(target.size().x());
578+ Program& blur_program_v1 = blur_program_v(target.size().y());
579+
580+ for (unsigned int i = 0; i < passes_; i++) {
581+ render_from(target, blur_program_h1);
582+ RenderObject::render_to(target, blur_program_v1);
583+ }
584+ }
585+ else {
586+ Program& blur_program1 = blur_program(target.size().x(), target.size().y());
587+
588+ for (unsigned int i = 0; i < passes_; i++) {
589+ if (i % 2 == 0)
590+ render_from(target, blur_program1);
591+ else
592+ RenderObject::render_to(target, blur_program1);
593+ }
594+
595+ if (passes_ % 2 == 1)
596+ RenderObject::render_to(target);
597+ }
598+
599+ /*
600+ * Blend the window contents with the target texture.
601+ */
602+ if (draw_contents_) {
603+ glEnable(GL_BLEND);
604+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
605+ window_contents_.position(position());
606+ window_contents_.render_to(target);
607+ glDisable(GL_BLEND);
608+ }
609+ }
610+
611+private:
612+ Program& blur_program(unsigned int w, unsigned int h)
613+ {
614+ /*
615+ * If the size of the window has changed we must recreate
616+ * the shader to contain the correct texture step values.
617+ */
618+ if (blur_program_dim_.x() != w || blur_program_dim_.y() != h ||
619+ !blur_program_.ready())
620+ {
621+ blur_program_dim_.x(w);
622+ blur_program_dim_.y(h);
623+
624+ blur_program_.release();
625+
626+ ShaderSource vtx_source;
627+ ShaderSource frg_source;
628+ create_blur_shaders(vtx_source, frg_source, radius_,
629+ radius_ / 3.0, BlurDirectionBoth);
630+ frg_source.add_const("TextureStepX", 1.0 / w);
631+ frg_source.add_const("TextureStepY", 1.0 / h);
632+ Scene::load_shaders_from_strings(blur_program_, vtx_source.str(),
633+ frg_source.str());
634+ }
635+
636+ return blur_program_;
637+ }
638+
639+ Program& blur_program_h(unsigned int w)
640+ {
641+ /*
642+ * If the size of the window has changed we must recreate
643+ * the shader to contain the correct texture step values.
644+ */
645+ if (blur_program_dim_.x() != w ||
646+ !blur_program_h_.ready())
647+ {
648+ blur_program_dim_.x(w);
649+
650+ blur_program_h_.release();
651+
652+ ShaderSource vtx_source;
653+ ShaderSource frg_source;
654+ create_blur_shaders(vtx_source, frg_source, radius_,
655+ radius_ / 3.0, BlurDirectionHorizontal);
656+ frg_source.add_const("TextureStepX", 1.0 / w);
657+ Scene::load_shaders_from_strings(blur_program_h_, vtx_source.str(),
658+ frg_source.str());
659+ }
660+
661+ return blur_program_h_;
662+ }
663+
664+ Program& blur_program_v(unsigned int h)
665+ {
666+ /*
667+ * If the size of the window has changed we must recreate
668+ * the shader to contain the correct texture step values.
669+ */
670+ if (blur_program_dim_.y() != h ||
671+ !blur_program_v_.ready())
672+ {
673+ blur_program_dim_.y(h);
674+
675+ blur_program_v_.release();
676+
677+ ShaderSource vtx_source;
678+ ShaderSource frg_source;
679+ create_blur_shaders(vtx_source, frg_source, radius_,
680+ radius_ / 3.0, BlurDirectionVertical);
681+ frg_source.add_const("TextureStepY", 1.0 / h);
682+ Scene::load_shaders_from_strings(blur_program_v_, vtx_source.str(),
683+ frg_source.str());
684+ }
685+
686+ return blur_program_v_;
687+ }
688+
689+ LibMatrix::uvec2 blur_program_dim_;
690+ Program blur_program_;
691+ Program blur_program_h_;
692+ Program blur_program_v_;
693+ unsigned int passes_;
694+ unsigned int radius_;
695+ bool separable_;
696+ bool draw_contents_;
697+
698+ static int use_count;
699+ static RenderClearImage window_contents_;
700+
701+};
702+
703+int RenderWindowBlur::use_count = 0;
704+RenderClearImage RenderWindowBlur::window_contents_(GLMARK_DATA_PATH"/textures/desktop-window.png");
705+
706+/*******************************
707+ * SceneDesktop implementation *
708+ *******************************/
709+
710+/**
711+ * Private structure used to avoid contaminating scene.h with all of the
712+ * SceneDesktop internal classes.
713+ */
714+struct SceneDesktopPrivate
715+{
716+ RenderScreen screen;
717+ RenderClearImage desktop;
718+ std::vector<RenderObject *> windows;
719+
720+ SceneDesktopPrivate() :
721+ desktop(GLMARK_DATA_PATH"/textures/effect-2d.png") {}
722+
723+ ~SceneDesktopPrivate() { Util::dispose_pointer_vector(windows); }
724+
725+};
726+
727+
728+SceneDesktop::SceneDesktop(Canvas &canvas) :
729+ Scene(canvas, "desktop")
730+{
731+ priv_ = new SceneDesktopPrivate();
732+ mOptions["effect"] = Scene::Option("effect", "blur",
733+ "the effect to use [blur]");
734+ mOptions["windows"] = Scene::Option("windows", "4",
735+ "the number of windows");
736+ mOptions["window-size"] = Scene::Option("window-size", "0.35",
737+ "the window size as a percentage of the minimum screen dimension [0.0 - 0.5]");
738+ mOptions["passes"] = Scene::Option("passes", "1",
739+ "the number of effect passes (effect dependent)");
740+ mOptions["blur-radius"] = Scene::Option("blur-radius", "5",
741+ "the blur effect radius (in pixels)");
742+ mOptions["separable"] = Scene::Option("separable", "true",
743+ "use separable convolution for the blur effect");
744+}
745+
746+SceneDesktop::~SceneDesktop()
747+{
748+ delete priv_;
749+}
750+
751+int
752+SceneDesktop::load()
753+{
754+ priv_->screen.init();
755+ priv_->desktop.init();
756+ return 1;
757+}
758+
759+void
760+SceneDesktop::unload()
761+{
762+ priv_->desktop.release();
763+ priv_->screen.release();
764+}
765+
766+void
767+SceneDesktop::setup()
768+{
769+ Scene::setup();
770+
771+ std::stringstream ss;
772+ unsigned int windows(0);
773+ unsigned int passes(0);
774+ unsigned int blur_radius(0);
775+ float window_size_factor(0.0);
776+ bool separable(mOptions["separable"].value == "true");
777+
778+ ss << mOptions["windows"].value;
779+ ss >> windows;
780+ ss.clear();
781+ ss << mOptions["window-size"].value;
782+ ss >> window_size_factor;
783+ ss.clear();
784+ ss << mOptions["passes"].value;
785+ ss >> passes;
786+ ss.clear();
787+ ss << mOptions["blur-radius"].value;
788+ ss >> blur_radius;
789+
790+ /* Ensure we get a transparent clear color for all following operations */
791+ glClearColor(0.0, 0.0, 0.0, 0.0);
792+ glDisable(GL_DEPTH_TEST);
793+ glDepthMask(GL_FALSE);
794+
795+ /* Set up the screen and desktop RenderObjects */
796+ priv_->screen.size(LibMatrix::vec2(mCanvas.width(), mCanvas.height()));
797+ priv_->desktop.size(LibMatrix::vec2(mCanvas.width(), mCanvas.height()));
798+
799+ /* Create the windows */
800+ float angular_step(2.0 * M_PI / windows);
801+ unsigned int min_dimension = std::min(mCanvas.width(), mCanvas.height());
802+ float window_size(min_dimension * window_size_factor);
803+ static const LibMatrix::vec2 corner_offset(window_size / 2.0,
804+ window_size / 2.0);
805+
806+ for (unsigned int i = 0; i < windows; i++) {
807+ LibMatrix::vec2 center(mCanvas.width() * (0.5 + 0.25 * cos(i * angular_step)),
808+ mCanvas.height() * (0.5 + 0.25 * sin(i * angular_step)));
809+ RenderObject* win(new RenderWindowBlur(passes, blur_radius, separable));
810+ (void)angular_step;
811+
812+ win->init();
813+ win->position(center - corner_offset);
814+ win->size(LibMatrix::vec2(window_size, window_size));
815+ /*
816+ * Set the speed in increments of about 30 degrees (but not exactly,
817+ * so we don't get windows moving just on the X axis or Y axis).
818+ */
819+ win->speed(LibMatrix::vec2(cos(0.1 + i * M_PI / 6.0) * mCanvas.width() / 3,
820+ sin(0.1 + i * M_PI / 6.0) * mCanvas.height() / 3));
821+ /*
822+ * Perform a dummy rendering to ensure internal shaders are initialized
823+ * now, in order not to affect the benchmarking.
824+ */
825+ win->render_to(priv_->desktop);
826+ priv_->windows.push_back(win);
827+ }
828+
829+ /*
830+ * Ensure the screen is the current rendering target (it might have changed
831+ * to a FBO in the previous steps).
832+ */
833+ priv_->screen.make_current();
834+
835+ mCurrentFrame = 0;
836+ mRunning = true;
837+ mStartTime = Scene::get_timestamp_us() / 1000000.0;
838+ mLastUpdateTime = mStartTime;
839+}
840+
841+void
842+SceneDesktop::teardown()
843+{
844+ Util::dispose_pointer_vector(priv_->windows);
845+ priv_->screen.make_current();
846+
847+ glEnable(GL_DEPTH_TEST);
848+ glDepthMask(GL_TRUE);
849+
850+ Scene::teardown();
851+}
852+
853+void
854+SceneDesktop::update()
855+{
856+ double current_time = Scene::get_timestamp_us() / 1000000.0;
857+ double dt = current_time - mLastUpdateTime;
858+ double elapsed_time = current_time - mStartTime;
859+
860+ mLastUpdateTime = current_time;
861+
862+ std::vector<RenderObject *>& windows(priv_->windows);
863+
864+ /*
865+ * Move the windows around the screen, bouncing them back when
866+ * they reach the edge.
867+ */
868+ for (std::vector<RenderObject *>::const_iterator iter = windows.begin();
869+ iter != windows.end();
870+ iter++)
871+ {
872+ bool should_update = true;
873+ RenderObject *win = *iter;
874+ LibMatrix::vec2 new_pos(
875+ win->position().x() + win->speed().x() * dt,
876+ win->position().y() + win->speed().y() * dt);
877+
878+ if (new_pos.x() < 0.0 ||
879+ new_pos.x() + win->size().x() > ((float)mCanvas.width()))
880+ {
881+ win->speed(LibMatrix::vec2(-win->speed().x(), win->speed().y()));
882+ should_update = false;
883+ }
884+
885+ if (new_pos.y() < 0.0 ||
886+ new_pos.y() + win->size().y() > ((float)mCanvas.height()))
887+ {
888+ win->speed(LibMatrix::vec2(win->speed().x(), -win->speed().y()));
889+ should_update = false;
890+ }
891+
892+ if (should_update)
893+ win->position(new_pos);
894+ }
895+
896+ if (elapsed_time >= mDuration) {
897+ mAverageFPS = mCurrentFrame / elapsed_time;
898+ mRunning = false;
899+ }
900+
901+ mCurrentFrame++;
902+}
903+
904+void
905+SceneDesktop::draw()
906+{
907+ std::vector<RenderObject *>& windows(priv_->windows);
908+
909+ /* Ensure we get a transparent clear color for all following operations */
910+ glClearColor(0.0, 0.0, 0.0, 0.0);
911+
912+ priv_->desktop.clear();
913+
914+ for (std::vector<RenderObject *>::const_iterator iter = windows.begin();
915+ iter != windows.end();
916+ iter++)
917+ {
918+ RenderObject *win = *iter;
919+ win->render_to(priv_->desktop);
920+ }
921+
922+ priv_->desktop.render_to(priv_->screen);
923+
924+}
925+
926+Scene::ValidationResult
927+SceneDesktop::validate()
928+{
929+ return ValidationUnknown;
930+}
931
932=== modified file 'src/scene.h'
933--- src/scene.h 2011-08-18 13:20:04 +0000
934+++ src/scene.h 2011-09-13 09:41:05 +0000
935@@ -331,4 +331,23 @@
936 void create_and_setup_mesh();
937 };
938
939+struct SceneDesktopPrivate;
940+
941+class SceneDesktop : public Scene
942+{
943+public:
944+ SceneDesktop(Canvas &canvas);
945+ int load();
946+ void unload();
947+ void setup();
948+ void teardown();
949+ void update();
950+ void draw();
951+ ValidationResult validate();
952+
953+ ~SceneDesktop();
954+
955+private:
956+ SceneDesktopPrivate *priv_;
957+};
958 #endif

Subscribers

People subscribed via source and target branches