Merge lp:~glmark2-dev/glmark2/live-fps into lp:glmark2/2011.11

Proposed by Alexandros Frantzis
Status: Merged
Merged at revision: 178
Proposed branch: lp:~glmark2-dev/glmark2/live-fps
Merge into: lp:glmark2/2011.11
Diff against target: 504 lines (+397/-0)
8 files modified
data/shaders/text-renderer.frag (+10/-0)
data/shaders/text-renderer.vert (+10/-0)
doc/glmark2.1.in (+4/-0)
src/main.cpp (+15/-0)
src/options.cpp (+6/-0)
src/options.h (+1/-0)
src/text-renderer.cpp (+291/-0)
src/text-renderer.h (+60/-0)
To merge this branch: bzr merge lp:~glmark2-dev/glmark2/live-fps
Reviewer Review Type Date Requested Status
Jesse Barker Pending
Review via email: mp+85499@code.launchpad.net

Description of the change

Add support for optionally showing a live FPS counter on screen.

To post a comment you must log in.
lp:~glmark2-dev/glmark2/live-fps updated
179. By Alexandros Frantzis

TextRenderer: Avoid setting/restoring the VBO state more than once.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'data/shaders/text-renderer.frag'
2--- data/shaders/text-renderer.frag 1970-01-01 00:00:00 +0000
3+++ data/shaders/text-renderer.frag 2012-01-05 09:43:24 +0000
4@@ -0,0 +1,10 @@
5+uniform sampler2D Texture0;
6+
7+varying vec2 TextureCoord;
8+
9+void main(void)
10+{
11+ vec4 texel = texture2D(Texture0, TextureCoord);
12+ gl_FragColor = texel;
13+}
14+
15
16=== added file 'data/shaders/text-renderer.vert'
17--- data/shaders/text-renderer.vert 1970-01-01 00:00:00 +0000
18+++ data/shaders/text-renderer.vert 2012-01-05 09:43:24 +0000
19@@ -0,0 +1,10 @@
20+attribute vec2 position;
21+attribute vec2 texcoord;
22+
23+varying vec2 TextureCoord;
24+
25+void main(void)
26+{
27+ TextureCoord = texcoord;
28+ gl_Position = vec4(position, 0.0, 1.0);
29+}
30
31=== added file 'data/textures/glyph-atlas.png'
32Binary files data/textures/glyph-atlas.png 1970-01-01 00:00:00 +0000 and data/textures/glyph-atlas.png 2012-01-05 09:43:24 +0000 differ
33=== modified file 'doc/glmark2.1.in'
34--- doc/glmark2.1.in 2011-12-15 13:52:04 +0000
35+++ doc/glmark2.1.in 2012-01-05 09:43:24 +0000
36@@ -36,6 +36,10 @@
37 Show all scene option values used for benchmarks
38 (only explicitly set options are shown by default)
39 .TP
40+\fB\-\-show-fps\fR
41+Show live FPS count on screen (showing live FPS
42+affects benchmarking results, use with care!)
43+.TP
44 \fB\-d\fR, \fB\-\-debug\fR
45 Display debug messages
46 .TP
47
48=== modified file 'src/main.cpp'
49--- src/main.cpp 2011-11-11 11:07:15 +0000
50+++ src/main.cpp 2012-01-05 09:43:24 +0000
51@@ -28,6 +28,7 @@
52 #include "log.h"
53 #include "util.h"
54 #include "default-benchmarks.h"
55+#include "text-renderer.h"
56
57 #include <iostream>
58 #include <fstream>
59@@ -149,6 +150,8 @@
60 void
61 do_benchmark(Canvas &canvas, vector<Benchmark *> &benchmarks)
62 {
63+ static const unsigned int fps_interval = 500000;
64+ TextRenderer fps_renderer(canvas);
65 unsigned score = 0;
66 unsigned int benchmarks_run = 0;
67
68@@ -158,6 +161,7 @@
69 {
70 bool keep_running = true;
71 Benchmark *bench = *bench_iter;
72+ uint64_t fps_timestamp = Util::get_timestamp_us();
73 Scene &scene = bench->setup_scene();
74
75 if (!scene.name().empty()) {
76@@ -172,6 +176,17 @@
77 scene.draw();
78 scene.update();
79
80+ if (Options::show_fps) {
81+ uint64_t now = Util::get_timestamp_us();
82+ if (now - fps_timestamp >= fps_interval) {
83+ std::stringstream ss;
84+ ss << "FPS: " << scene.average_fps();
85+ fps_renderer.text(ss.str());
86+ fps_timestamp = now;
87+ }
88+ fps_renderer.render();
89+ }
90+
91 canvas.update();
92 }
93
94
95=== modified file 'src/options.cpp'
96--- src/options.cpp 2011-11-01 16:46:08 +0000
97+++ src/options.cpp 2012-01-05 09:43:24 +0000
98@@ -39,6 +39,7 @@
99 bool Options::list_scenes = false;
100 bool Options::show_all_options = false;
101 bool Options::show_debug = false;
102+bool Options::show_fps = false;
103 bool Options::show_help = false;
104
105 static struct option long_options[] = {
106@@ -49,6 +50,7 @@
107 {"size", 1, 0, 0},
108 {"list-scenes", 0, 0, 0},
109 {"show-all-options", 0, 0, 0},
110+ {"show-fps", 0, 0, 0},
111 {"debug", 0, 0, 0},
112 {"help", 0, 0, 0},
113 {0, 0, 0, 0}
114@@ -98,6 +100,8 @@
115 " and their options\n"
116 " --show-all-options Show all scene option values used for benchmarks\n"
117 " (only explicitly set options are shown by default)\n"
118+ " --show-fps Show live FPS count on screen (showing live FPS\n"
119+ " affects benchmarking results, use with care!)\n"
120 " -d, --debug Display debug messages\n"
121 " -h, --help Display help\n");
122 }
123@@ -134,6 +138,8 @@
124 Options::list_scenes = true;
125 else if (!strcmp(optname, "show-all-options"))
126 Options::show_all_options = true;
127+ else if (!strcmp(optname, "show-fps"))
128+ Options::show_fps = true;
129 else if (c == 'd' || !strcmp(optname, "debug"))
130 Options::show_debug = true;
131 else if (c == 'h' || !strcmp(optname, "help"))
132
133=== modified file 'src/options.h'
134--- src/options.h 2011-09-20 12:52:21 +0000
135+++ src/options.h 2012-01-05 09:43:24 +0000
136@@ -39,6 +39,7 @@
137 static bool list_scenes;
138 static bool show_all_options;
139 static bool show_debug;
140+ static bool show_fps;
141 static bool show_help;
142 };
143
144
145=== added file 'src/text-renderer.cpp'
146--- src/text-renderer.cpp 1970-01-01 00:00:00 +0000
147+++ src/text-renderer.cpp 2012-01-05 09:43:24 +0000
148@@ -0,0 +1,291 @@
149+/*
150+ * Copyright © 2011 Linaro Limited
151+ *
152+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
153+ *
154+ * glmark2 is free software: you can redistribute it and/or modify it under the
155+ * terms of the GNU General Public License as published by the Free Software
156+ * Foundation, either version 3 of the License, or (at your option) any later
157+ * version.
158+ *
159+ * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
160+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
161+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
162+ * details.
163+ *
164+ * You should have received a copy of the GNU General Public License along with
165+ * glmark2. If not, see <http://www.gnu.org/licenses/>.
166+ *
167+ * Authors:
168+ * Alexandros Frantzis (glmark2)
169+ */
170+#include "text-renderer.h"
171+#include "gl-headers.h"
172+#include "scene.h"
173+#include "shader-source.h"
174+#include "vec.h"
175+#include "mat.h"
176+#include "texture.h"
177+
178+using LibMatrix::vec2;
179+using LibMatrix::mat4;
180+
181+/* These are specific to the glyph texture atlas we are using */
182+static const unsigned int texture_size(512);
183+static const vec2 glyph_size_pixels(29.0, 57.0);
184+static const vec2 glyph_size(glyph_size_pixels/texture_size);
185+
186+/******************
187+ * Public methods *
188+ ******************/
189+
190+/**
191+ * TextRenderer default constructor.
192+ */
193+TextRenderer::TextRenderer(Canvas& canvas) :
194+ canvas_(canvas), dirty_(false), position_(-1.0, -1.0),
195+ texture_(0)
196+{
197+ size(0.03);
198+
199+ glGenBuffers(2, vbo_);
200+ ShaderSource vtx_source(GLMARK_DATA_PATH"/shaders/text-renderer.vert");
201+ ShaderSource frg_source(GLMARK_DATA_PATH"/shaders/text-renderer.frag");
202+
203+ if (!Scene::load_shaders_from_strings(program_, vtx_source.str(),
204+ frg_source.str()))
205+ {
206+ return;
207+ }
208+
209+ GLint prev_program;
210+ glGetIntegerv(GL_CURRENT_PROGRAM, &prev_program);
211+
212+ program_.start();
213+ program_["Texture0"] = 0;
214+
215+ glUseProgram(prev_program);
216+
217+ /* Load the glyph texture atlas */
218+ Texture::load(GLMARK_DATA_PATH"/textures/glyph-atlas.png", &texture_,
219+ GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR,0);
220+}
221+
222+TextRenderer::~TextRenderer()
223+{
224+ glDeleteBuffers(2, vbo_);
225+ glDeleteTextures(1, &texture_);
226+}
227+
228+/**
229+ * Sets the text string to render.
230+ *
231+ * @param t the text string
232+ */
233+void
234+TextRenderer::text(const std::string& t)
235+{
236+ if (text_ != t) {
237+ text_ = t;
238+ dirty_ = true;
239+ }
240+}
241+
242+/**
243+ * Sets the screen position to render at.
244+ *
245+ * @param t the position
246+ */
247+void
248+TextRenderer::position(LibMatrix::vec2& p)
249+{
250+ if (position_ != p) {
251+ position_ = p;
252+ dirty_ = true;
253+ }
254+}
255+
256+/**
257+ * Sets the size of each rendered glyph.
258+ *
259+ * The size corresponds to the width of each glyph
260+ * in normalized screen coordinates.
261+ *
262+ * @param s the size of each glyph
263+ */
264+void
265+TextRenderer::size(float s)
266+{
267+ if (size_.x() != s) {
268+ /* Take into account the glyph and canvas aspect ratio */
269+ double canvas_aspect =
270+ static_cast<double>(canvas_.width()) / canvas_.height();
271+ double glyph_aspect_rev = glyph_size.y() / glyph_size.x();
272+ size_ = vec2(s, s * canvas_aspect * glyph_aspect_rev);
273+ dirty_ = true;
274+ }
275+}
276+
277+/**
278+ * Renders the text.
279+ */
280+void
281+TextRenderer::render()
282+{
283+ /* Save state */
284+ GLint prev_program = 0;
285+ GLint prev_array_buffer = 0;
286+ GLint prev_elem_array_buffer = 0;
287+ GLint prev_blend_src_rgb = 0;
288+ GLint prev_blend_dst_rgb = 0;
289+ GLint prev_blend_src_alpha = 0;
290+ GLint prev_blend_dst_alpha = 0;
291+ GLboolean prev_blend = GL_FALSE;
292+ GLboolean prev_depth_test = GL_FALSE;
293+ glGetIntegerv(GL_CURRENT_PROGRAM, &prev_program);
294+ glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &prev_array_buffer);
295+ glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &prev_elem_array_buffer);
296+ glGetIntegerv(GL_BLEND_SRC_RGB, &prev_blend_src_rgb);
297+ glGetIntegerv(GL_BLEND_DST_RGB, &prev_blend_dst_rgb);
298+ glGetIntegerv(GL_BLEND_SRC_ALPHA, &prev_blend_src_alpha);
299+ glGetIntegerv(GL_BLEND_DST_ALPHA, &prev_blend_dst_alpha);
300+ glGetBooleanv(GL_BLEND, &prev_blend);
301+ glGetBooleanv(GL_DEPTH_TEST, &prev_depth_test);
302+
303+ /* Set new state */
304+ glActiveTexture(GL_TEXTURE0);
305+ glBindTexture(GL_TEXTURE_2D, texture_);
306+ glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]);
307+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_[1]);
308+ glEnable(GL_BLEND);
309+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
310+ glDisable(GL_DEPTH_TEST);
311+
312+ if (dirty_) {
313+ create_geometry();
314+ dirty_ = false;
315+ }
316+
317+ program_.start();
318+ GLint position_loc = program_["position"].location();
319+ GLint texcoord_loc = program_["texcoord"].location();
320+
321+ /* Render */
322+ glEnableVertexAttribArray(position_loc);
323+ glEnableVertexAttribArray(texcoord_loc);
324+ glVertexAttribPointer(position_loc, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
325+ glVertexAttribPointer(texcoord_loc, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float),
326+ reinterpret_cast<const GLvoid *>(2 * sizeof(float)));
327+
328+ glDrawElements(GL_TRIANGLES, 6 * text_.length(), GL_UNSIGNED_SHORT, 0);
329+
330+ glDisableVertexAttribArray(texcoord_loc);
331+ glDisableVertexAttribArray(position_loc);
332+
333+ /* Restore state */
334+ if (prev_depth_test == GL_TRUE)
335+ glEnable(GL_DEPTH_TEST);
336+ if (prev_blend == GL_FALSE)
337+ glDisable(GL_BLEND);
338+ glBlendFuncSeparate(prev_blend_src_rgb, prev_blend_dst_rgb,
339+ prev_blend_src_alpha, prev_blend_dst_alpha);
340+ glBindBuffer(GL_ARRAY_BUFFER, prev_array_buffer);
341+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prev_elem_array_buffer);
342+ glUseProgram(prev_program);
343+}
344+
345+/*******************
346+ * Private methods *
347+ *******************/
348+
349+/**
350+ * Creates the geometry needed to render the text.
351+ *
352+ * This method assumes that the text VBOs are properly bound.
353+ */
354+void
355+TextRenderer::create_geometry()
356+{
357+ std::vector<float> array;
358+ std::vector<GLushort> elem_array;
359+ vec2 pos(position_);
360+
361+ for (size_t i = 0; i < text_.size(); i++) {
362+ vec2 texcoord = get_glyph_coords(text_[i]);
363+
364+ /* Emit the elements for this glyph quad */
365+ /* Lower left */
366+ array.push_back(pos.x());
367+ array.push_back(pos.y());
368+ array.push_back(texcoord.x());
369+ array.push_back(texcoord.y());
370+
371+ /* Lower right */
372+ pos.x(pos.x() + size_.x());
373+ texcoord.x(texcoord.x() + glyph_size.x());
374+ array.push_back(pos.x());
375+ array.push_back(pos.y());
376+ array.push_back(texcoord.x());
377+ array.push_back(texcoord.y());
378+
379+ /* Upper left */
380+ pos.x(pos.x() - size_.x());
381+ pos.y(pos.y() + size_.y());
382+ texcoord.x(texcoord.x() - glyph_size.x());
383+ texcoord.y(texcoord.y() + glyph_size.y());
384+ array.push_back(pos.x());
385+ array.push_back(pos.y());
386+ array.push_back(texcoord.x());
387+ array.push_back(texcoord.y());
388+
389+ /* Upper right */
390+ pos.x(pos.x() + size_.x());
391+ texcoord.x(texcoord.x() + glyph_size.x());
392+ array.push_back(pos.x());
393+ array.push_back(pos.y());
394+ array.push_back(texcoord.x());
395+ array.push_back(texcoord.y());
396+
397+ /* Prepare for the next glyph */
398+ pos.y(pos.y() - size_.y());
399+
400+ /* Emit the element indices for this glyph quad */
401+ elem_array.push_back(4 * i);
402+ elem_array.push_back(4 * i + 1);
403+ elem_array.push_back(4 * i + 2);
404+ elem_array.push_back(4 * i + 2);
405+ elem_array.push_back(4 * i + 1);
406+ elem_array.push_back(4 * i + 3);
407+ }
408+
409+ /* Load the data into the corresponding VBOs */
410+ glBufferData(GL_ARRAY_BUFFER, array.size() * sizeof(float),
411+ &array[0], GL_DYNAMIC_DRAW);
412+
413+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, elem_array.size() * sizeof(GLushort),
414+ &elem_array[0], GL_DYNAMIC_DRAW);
415+}
416+
417+/**
418+ * Gets the texcoords of a glyph in the glyph texture atlas.
419+ *
420+ * @param c the character to get the glyph texcoords of
421+ *
422+ * @return the texcoords
423+ */
424+vec2
425+TextRenderer::get_glyph_coords(char c)
426+{
427+ static const unsigned int glyphs_per_row(texture_size / glyph_size_pixels.x());
428+
429+ /* We only support the ASCII printable characters */
430+ if (c < 32 || c >= 127)
431+ c = 32;
432+
433+ int n = c - 32;
434+ int row = n / glyphs_per_row;
435+ int col = n % glyphs_per_row;
436+
437+ return vec2(col * glyph_size.x(), 1.0 - (row + 1) * glyph_size.y());
438+}
439+
440
441=== added file 'src/text-renderer.h'
442--- src/text-renderer.h 1970-01-01 00:00:00 +0000
443+++ src/text-renderer.h 2012-01-05 09:43:24 +0000
444@@ -0,0 +1,60 @@
445+/*
446+ * Copyright © 2011 Linaro Limited
447+ *
448+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
449+ *
450+ * glmark2 is free software: you can redistribute it and/or modify it under the
451+ * terms of the GNU General Public License as published by the Free Software
452+ * Foundation, either version 3 of the License, or (at your option) any later
453+ * version.
454+ *
455+ * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
456+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
457+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
458+ * details.
459+ *
460+ * You should have received a copy of the GNU General Public License along with
461+ * glmark2. If not, see <http://www.gnu.org/licenses/>.
462+ *
463+ * Authors:
464+ * Alexandros Frantzis (glmark2)
465+ */
466+#ifndef GLMARK2_TEXT_RENDERER_H_
467+#define GLMARK2_TEXT_RENDERER_H_
468+
469+#include <string>
470+#include "gl-headers.h"
471+#include "vec.h"
472+#include "program.h"
473+#include "canvas.h"
474+
475+/**
476+ * Renders text using OpenGL textures.
477+ */
478+class TextRenderer
479+{
480+public:
481+ TextRenderer(Canvas& canvas);
482+ ~TextRenderer();
483+
484+ void text(const std::string& t);
485+ void position(LibMatrix::vec2& p);
486+ void size(float s);
487+
488+ void render();
489+
490+private:
491+ void create_geometry();
492+ LibMatrix::vec2 get_glyph_coords(char c);
493+
494+ Canvas& canvas_;
495+ bool dirty_;
496+ std::string text_;
497+ LibMatrix::vec2 position_;
498+ LibMatrix::vec2 size_;
499+ Program program_;
500+ GLuint vbo_[2];
501+ GLuint texture_;
502+};
503+
504+#endif

Subscribers

People subscribed via source and target branches

to all changes: