From patchwork Thu Jan 5 10:18:14 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: alexandros.frantzis@linaro.org X-Patchwork-Id: 6063 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 1FF6923F72 for ; Thu, 5 Jan 2012 10:18:17 +0000 (UTC) Received: from mail-ey0-f180.google.com (mail-ey0-f180.google.com [209.85.215.180]) by fiordland.canonical.com (Postfix) with ESMTP id 12038A18086 for ; Thu, 5 Jan 2012 10:18:17 +0000 (UTC) Received: by eaac11 with SMTP id c11so295591eaa.11 for ; Thu, 05 Jan 2012 02:18:17 -0800 (PST) Received: by 10.204.133.207 with SMTP id g15mr541564bkt.17.1325758696773; Thu, 05 Jan 2012 02:18:16 -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 ac16cs397350bkc; Thu, 5 Jan 2012 02:18:16 -0800 (PST) Received: by 10.216.139.153 with SMTP id c25mr875795wej.25.1325758694982; Thu, 05 Jan 2012 02:18:14 -0800 (PST) Received: from indium.canonical.com (indium.canonical.com. [91.189.90.7]) by mx.google.com with ESMTPS id el4si27745402wbb.111.2012.01.05.02.18.14 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 05 Jan 2012 02:18:14 -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 1RikOk-0001Z0-EG for ; Thu, 05 Jan 2012 10:18:14 +0000 Received: from ackee.canonical.com (localhost [127.0.0.1]) by ackee.canonical.com (Postfix) with ESMTP id 53D08E143A for ; Thu, 5 Jan 2012 10:18:14 +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: 178 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [Branch ~glmark2-dev/glmark2/trunk] Rev 178: Main, Options, TextRenderer: Add support for optionally showing a live FPS counter on screen. Message-Id: <20120105101814.20011.31436.launchpad@ackee.canonical.com> Date: Thu, 05 Jan 2012 10:18:14 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: bulk X-Generated-By: Launchpad (canonical.com); Revision="14625"; Instance="launchpad-lazr.conf" X-Launchpad-Hash: 6c9200b75e015bd51a40bc53d33c4d91e8de6cd0 Merge authors: Alexandros Frantzis (afrantzis) Related merge proposals: https://code.launchpad.net/~glmark2-dev/glmark2/live-fps/+merge/85499 proposed by: Alexandros Frantzis (afrantzis) ------------------------------------------------------------ revno: 178 [merge] committer: Alexandros Frantzis branch nick: trunk timestamp: Thu 2012-01-05 11:46:41 +0200 message: Main,Options,TextRenderer: Add support for optionally showing a live FPS counter on screen. added: data/shaders/text-renderer.frag data/shaders/text-renderer.vert data/textures/glyph-atlas.png src/text-renderer.cpp src/text-renderer.h modified: doc/glmark2.1.in src/main.cpp src/options.cpp src/options.h --- 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 === added file 'data/shaders/text-renderer.frag' --- data/shaders/text-renderer.frag 1970-01-01 00:00:00 +0000 +++ data/shaders/text-renderer.frag 2011-12-13 14:25:41 +0000 @@ -0,0 +1,10 @@ +uniform sampler2D Texture0; + +varying vec2 TextureCoord; + +void main(void) +{ + vec4 texel = texture2D(Texture0, TextureCoord); + gl_FragColor = texel; +} + === added file 'data/shaders/text-renderer.vert' --- data/shaders/text-renderer.vert 1970-01-01 00:00:00 +0000 +++ data/shaders/text-renderer.vert 2011-12-13 14:25:41 +0000 @@ -0,0 +1,10 @@ +attribute vec2 position; +attribute vec2 texcoord; + +varying vec2 TextureCoord; + +void main(void) +{ + TextureCoord = texcoord; + gl_Position = vec4(position, 0.0, 1.0); +} === added file 'data/textures/glyph-atlas.png' Binary files data/textures/glyph-atlas.png 1970-01-01 00:00:00 +0000 and data/textures/glyph-atlas.png 2011-12-13 14:25:41 +0000 differ === modified file 'doc/glmark2.1.in' --- doc/glmark2.1.in 2011-12-15 13:52:04 +0000 +++ doc/glmark2.1.in 2012-01-05 09:46:41 +0000 @@ -36,6 +36,10 @@ Show all scene option values used for benchmarks (only explicitly set options are shown by default) .TP +\fB\-\-show-fps\fR +Show live FPS count on screen (showing live FPS +affects benchmarking results, use with care!) +.TP \fB\-d\fR, \fB\-\-debug\fR Display debug messages .TP === modified file 'src/main.cpp' --- src/main.cpp 2011-11-11 11:07:15 +0000 +++ src/main.cpp 2011-12-13 14:27:23 +0000 @@ -28,6 +28,7 @@ #include "log.h" #include "util.h" #include "default-benchmarks.h" +#include "text-renderer.h" #include #include @@ -149,6 +150,8 @@ void do_benchmark(Canvas &canvas, vector &benchmarks) { + static const unsigned int fps_interval = 500000; + TextRenderer fps_renderer(canvas); unsigned score = 0; unsigned int benchmarks_run = 0; @@ -158,6 +161,7 @@ { bool keep_running = true; Benchmark *bench = *bench_iter; + uint64_t fps_timestamp = Util::get_timestamp_us(); Scene &scene = bench->setup_scene(); if (!scene.name().empty()) { @@ -172,6 +176,17 @@ scene.draw(); scene.update(); + if (Options::show_fps) { + uint64_t now = Util::get_timestamp_us(); + if (now - fps_timestamp >= fps_interval) { + std::stringstream ss; + ss << "FPS: " << scene.average_fps(); + fps_renderer.text(ss.str()); + fps_timestamp = now; + } + fps_renderer.render(); + } + canvas.update(); } === modified file 'src/options.cpp' --- src/options.cpp 2011-11-01 16:46:08 +0000 +++ src/options.cpp 2011-12-13 14:27:23 +0000 @@ -39,6 +39,7 @@ bool Options::list_scenes = false; bool Options::show_all_options = false; bool Options::show_debug = false; +bool Options::show_fps = false; bool Options::show_help = false; static struct option long_options[] = { @@ -49,6 +50,7 @@ {"size", 1, 0, 0}, {"list-scenes", 0, 0, 0}, {"show-all-options", 0, 0, 0}, + {"show-fps", 0, 0, 0}, {"debug", 0, 0, 0}, {"help", 0, 0, 0}, {0, 0, 0, 0} @@ -98,6 +100,8 @@ " and their options\n" " --show-all-options Show all scene option values used for benchmarks\n" " (only explicitly set options are shown by default)\n" + " --show-fps Show live FPS count on screen (showing live FPS\n" + " affects benchmarking results, use with care!)\n" " -d, --debug Display debug messages\n" " -h, --help Display help\n"); } @@ -134,6 +138,8 @@ Options::list_scenes = true; else if (!strcmp(optname, "show-all-options")) Options::show_all_options = true; + else if (!strcmp(optname, "show-fps")) + Options::show_fps = true; else if (c == 'd' || !strcmp(optname, "debug")) Options::show_debug = true; else if (c == 'h' || !strcmp(optname, "help")) === modified file 'src/options.h' --- src/options.h 2011-09-20 12:52:21 +0000 +++ src/options.h 2011-12-13 14:27:23 +0000 @@ -39,6 +39,7 @@ static bool list_scenes; static bool show_all_options; static bool show_debug; + static bool show_fps; static bool show_help; }; === added file 'src/text-renderer.cpp' --- src/text-renderer.cpp 1970-01-01 00:00:00 +0000 +++ src/text-renderer.cpp 2012-01-05 09:35:49 +0000 @@ -0,0 +1,291 @@ +/* + * Copyright © 2011 Linaro Limited + * + * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark. + * + * glmark2 is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * glmark2. If not, see . + * + * Authors: + * Alexandros Frantzis (glmark2) + */ +#include "text-renderer.h" +#include "gl-headers.h" +#include "scene.h" +#include "shader-source.h" +#include "vec.h" +#include "mat.h" +#include "texture.h" + +using LibMatrix::vec2; +using LibMatrix::mat4; + +/* These are specific to the glyph texture atlas we are using */ +static const unsigned int texture_size(512); +static const vec2 glyph_size_pixels(29.0, 57.0); +static const vec2 glyph_size(glyph_size_pixels/texture_size); + +/****************** + * Public methods * + ******************/ + +/** + * TextRenderer default constructor. + */ +TextRenderer::TextRenderer(Canvas& canvas) : + canvas_(canvas), dirty_(false), position_(-1.0, -1.0), + texture_(0) +{ + size(0.03); + + glGenBuffers(2, vbo_); + ShaderSource vtx_source(GLMARK_DATA_PATH"/shaders/text-renderer.vert"); + ShaderSource frg_source(GLMARK_DATA_PATH"/shaders/text-renderer.frag"); + + if (!Scene::load_shaders_from_strings(program_, vtx_source.str(), + frg_source.str())) + { + return; + } + + GLint prev_program; + glGetIntegerv(GL_CURRENT_PROGRAM, &prev_program); + + program_.start(); + program_["Texture0"] = 0; + + glUseProgram(prev_program); + + /* Load the glyph texture atlas */ + Texture::load(GLMARK_DATA_PATH"/textures/glyph-atlas.png", &texture_, + GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR,0); +} + +TextRenderer::~TextRenderer() +{ + glDeleteBuffers(2, vbo_); + glDeleteTextures(1, &texture_); +} + +/** + * Sets the text string to render. + * + * @param t the text string + */ +void +TextRenderer::text(const std::string& t) +{ + if (text_ != t) { + text_ = t; + dirty_ = true; + } +} + +/** + * Sets the screen position to render at. + * + * @param t the position + */ +void +TextRenderer::position(LibMatrix::vec2& p) +{ + if (position_ != p) { + position_ = p; + dirty_ = true; + } +} + +/** + * Sets the size of each rendered glyph. + * + * The size corresponds to the width of each glyph + * in normalized screen coordinates. + * + * @param s the size of each glyph + */ +void +TextRenderer::size(float s) +{ + if (size_.x() != s) { + /* Take into account the glyph and canvas aspect ratio */ + double canvas_aspect = + static_cast(canvas_.width()) / canvas_.height(); + double glyph_aspect_rev = glyph_size.y() / glyph_size.x(); + size_ = vec2(s, s * canvas_aspect * glyph_aspect_rev); + dirty_ = true; + } +} + +/** + * Renders the text. + */ +void +TextRenderer::render() +{ + /* Save state */ + GLint prev_program = 0; + GLint prev_array_buffer = 0; + GLint prev_elem_array_buffer = 0; + GLint prev_blend_src_rgb = 0; + GLint prev_blend_dst_rgb = 0; + GLint prev_blend_src_alpha = 0; + GLint prev_blend_dst_alpha = 0; + GLboolean prev_blend = GL_FALSE; + GLboolean prev_depth_test = GL_FALSE; + glGetIntegerv(GL_CURRENT_PROGRAM, &prev_program); + glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &prev_array_buffer); + glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &prev_elem_array_buffer); + glGetIntegerv(GL_BLEND_SRC_RGB, &prev_blend_src_rgb); + glGetIntegerv(GL_BLEND_DST_RGB, &prev_blend_dst_rgb); + glGetIntegerv(GL_BLEND_SRC_ALPHA, &prev_blend_src_alpha); + glGetIntegerv(GL_BLEND_DST_ALPHA, &prev_blend_dst_alpha); + glGetBooleanv(GL_BLEND, &prev_blend); + glGetBooleanv(GL_DEPTH_TEST, &prev_depth_test); + + /* Set new state */ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture_); + glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_[1]); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_DEPTH_TEST); + + if (dirty_) { + create_geometry(); + dirty_ = false; + } + + program_.start(); + GLint position_loc = program_["position"].location(); + GLint texcoord_loc = program_["texcoord"].location(); + + /* Render */ + glEnableVertexAttribArray(position_loc); + glEnableVertexAttribArray(texcoord_loc); + glVertexAttribPointer(position_loc, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0); + glVertexAttribPointer(texcoord_loc, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), + reinterpret_cast(2 * sizeof(float))); + + glDrawElements(GL_TRIANGLES, 6 * text_.length(), GL_UNSIGNED_SHORT, 0); + + glDisableVertexAttribArray(texcoord_loc); + glDisableVertexAttribArray(position_loc); + + /* Restore state */ + if (prev_depth_test == GL_TRUE) + glEnable(GL_DEPTH_TEST); + if (prev_blend == GL_FALSE) + glDisable(GL_BLEND); + glBlendFuncSeparate(prev_blend_src_rgb, prev_blend_dst_rgb, + prev_blend_src_alpha, prev_blend_dst_alpha); + glBindBuffer(GL_ARRAY_BUFFER, prev_array_buffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prev_elem_array_buffer); + glUseProgram(prev_program); +} + +/******************* + * Private methods * + *******************/ + +/** + * Creates the geometry needed to render the text. + * + * This method assumes that the text VBOs are properly bound. + */ +void +TextRenderer::create_geometry() +{ + std::vector array; + std::vector elem_array; + vec2 pos(position_); + + for (size_t i = 0; i < text_.size(); i++) { + vec2 texcoord = get_glyph_coords(text_[i]); + + /* Emit the elements for this glyph quad */ + /* Lower left */ + array.push_back(pos.x()); + array.push_back(pos.y()); + array.push_back(texcoord.x()); + array.push_back(texcoord.y()); + + /* Lower right */ + pos.x(pos.x() + size_.x()); + texcoord.x(texcoord.x() + glyph_size.x()); + array.push_back(pos.x()); + array.push_back(pos.y()); + array.push_back(texcoord.x()); + array.push_back(texcoord.y()); + + /* Upper left */ + pos.x(pos.x() - size_.x()); + pos.y(pos.y() + size_.y()); + texcoord.x(texcoord.x() - glyph_size.x()); + texcoord.y(texcoord.y() + glyph_size.y()); + array.push_back(pos.x()); + array.push_back(pos.y()); + array.push_back(texcoord.x()); + array.push_back(texcoord.y()); + + /* Upper right */ + pos.x(pos.x() + size_.x()); + texcoord.x(texcoord.x() + glyph_size.x()); + array.push_back(pos.x()); + array.push_back(pos.y()); + array.push_back(texcoord.x()); + array.push_back(texcoord.y()); + + /* Prepare for the next glyph */ + pos.y(pos.y() - size_.y()); + + /* Emit the element indices for this glyph quad */ + elem_array.push_back(4 * i); + elem_array.push_back(4 * i + 1); + elem_array.push_back(4 * i + 2); + elem_array.push_back(4 * i + 2); + elem_array.push_back(4 * i + 1); + elem_array.push_back(4 * i + 3); + } + + /* Load the data into the corresponding VBOs */ + glBufferData(GL_ARRAY_BUFFER, array.size() * sizeof(float), + &array[0], GL_DYNAMIC_DRAW); + + glBufferData(GL_ELEMENT_ARRAY_BUFFER, elem_array.size() * sizeof(GLushort), + &elem_array[0], GL_DYNAMIC_DRAW); +} + +/** + * Gets the texcoords of a glyph in the glyph texture atlas. + * + * @param c the character to get the glyph texcoords of + * + * @return the texcoords + */ +vec2 +TextRenderer::get_glyph_coords(char c) +{ + static const unsigned int glyphs_per_row(texture_size / glyph_size_pixels.x()); + + /* We only support the ASCII printable characters */ + if (c < 32 || c >= 127) + c = 32; + + int n = c - 32; + int row = n / glyphs_per_row; + int col = n % glyphs_per_row; + + return vec2(col * glyph_size.x(), 1.0 - (row + 1) * glyph_size.y()); +} + === added file 'src/text-renderer.h' --- src/text-renderer.h 1970-01-01 00:00:00 +0000 +++ src/text-renderer.h 2011-12-13 14:25:41 +0000 @@ -0,0 +1,60 @@ +/* + * Copyright © 2011 Linaro Limited + * + * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark. + * + * glmark2 is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * glmark2. If not, see . + * + * Authors: + * Alexandros Frantzis (glmark2) + */ +#ifndef GLMARK2_TEXT_RENDERER_H_ +#define GLMARK2_TEXT_RENDERER_H_ + +#include +#include "gl-headers.h" +#include "vec.h" +#include "program.h" +#include "canvas.h" + +/** + * Renders text using OpenGL textures. + */ +class TextRenderer +{ +public: + TextRenderer(Canvas& canvas); + ~TextRenderer(); + + void text(const std::string& t); + void position(LibMatrix::vec2& p); + void size(float s); + + void render(); + +private: + void create_geometry(); + LibMatrix::vec2 get_glyph_coords(char c); + + Canvas& canvas_; + bool dirty_; + std::string text_; + LibMatrix::vec2 position_; + LibMatrix::vec2 size_; + Program program_; + GLuint vbo_[2]; + GLuint texture_; +}; + +#endif