/* * Copyright © 2012 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 */ #include "options.h" #include "main-loop.h" #include "util.h" #include "log.h" #include #include /************ * MainLoop * ************/ MainLoop::MainLoop(Canvas &canvas, const std::vector &benchmarks) : canvas_(canvas), benchmarks_(benchmarks) { reset(); } void MainLoop::reset() { scene_ = 0; score_ = 0; benchmarks_run_ = 0; bench_iter_ = benchmarks_.begin(); } unsigned int MainLoop::score() { if (benchmarks_run_) return score_ / benchmarks_run_; else return score_; } bool MainLoop::step() { /* Find the next normal scene */ if (!scene_) { /* Find a normal scene */ while (bench_iter_ != benchmarks_.end()) { scene_ = &(*bench_iter_)->scene(); /* * Scenes with empty names are option-setting scenes. * Just set them up and continue with the search. */ if (scene_->name().empty()) (*bench_iter_)->setup_scene(); else break; next_benchmark(); } /* If we have found a valid scene, set it up */ if (bench_iter_ != benchmarks_.end()) { if (!Options::reuse_context) canvas_.reset(); before_scene_setup(); scene_ = &(*bench_iter_)->setup_scene(); after_scene_setup(); log_scene_info(); } else { /* ... otherwise we are done */ return false; } } bool should_quit = canvas_.should_quit(); if (scene_ ->running() && !should_quit) draw(); /* * Need to recheck whether the scene is still running, because code * in draw() may have changed the state. */ if (!scene_->running() || should_quit) { score_ += scene_->average_fps(); log_scene_result(); (*bench_iter_)->teardown_scene(); scene_ = 0; next_benchmark(); benchmarks_run_++; } return !should_quit; } void MainLoop::draw() { canvas_.clear(); scene_->draw(); scene_->update(); canvas_.update(); } void MainLoop::log_scene_info() { Log::info("%s", scene_->info_string().c_str()); Log::flush(); } void MainLoop::log_scene_result() { static const std::string format_fps(Log::continuation_prefix + " FPS: %u"); static const std::string format_ms(Log::continuation_prefix + " FrameTime: %.3f ms\n"); Log::info(format_fps.c_str(), scene_->average_fps()); Log::info(format_ms.c_str(), 1000.0 / scene_->average_fps()); } void MainLoop::next_benchmark() { bench_iter_++; if (bench_iter_ == benchmarks_.end() && Options::run_forever) bench_iter_ = benchmarks_.begin(); } /********************** * MainLoopDecoration * **********************/ MainLoopDecoration::MainLoopDecoration(Canvas &canvas, const std::vector &benchmarks) : MainLoop(canvas, benchmarks), show_fps_(false), show_title_(false), fps_renderer_(0), title_renderer_(0), last_fps_(0) { } MainLoopDecoration::~MainLoopDecoration() { delete fps_renderer_; fps_renderer_ = 0; delete title_renderer_; title_renderer_ = 0; } void MainLoopDecoration::draw() { static const unsigned int fps_interval = 500000; canvas_.clear(); scene_->draw(); scene_->update(); if (show_fps_) { uint64_t now = Util::get_timestamp_us(); if (now - fps_timestamp_ >= fps_interval) { last_fps_ = scene_->average_fps(); fps_renderer_update_text(last_fps_); fps_timestamp_ = now; } fps_renderer_->render(); } if (show_title_) title_renderer_->render(); canvas_.update(); } void MainLoopDecoration::before_scene_setup() { delete fps_renderer_; fps_renderer_ = 0; delete title_renderer_; title_renderer_ = 0; } void MainLoopDecoration::after_scene_setup() { const Scene::Option &show_fps_option(scene_->options().find("show-fps")->second); const Scene::Option &title_option(scene_->options().find("title")->second); show_fps_ = show_fps_option.value == "true"; show_title_ = !title_option.value.empty(); if (show_fps_) { const Scene::Option &fps_pos_option(scene_->options().find("fps-pos")->second); const Scene::Option &fps_size_option(scene_->options().find("fps-size")->second); fps_renderer_ = new TextRenderer(canvas_); fps_renderer_->position(vec2_from_pos_string(fps_pos_option.value)); fps_renderer_->size(Util::fromString(fps_size_option.value)); fps_renderer_update_text(last_fps_); fps_timestamp_ = Util::get_timestamp_us(); } if (show_title_) { const Scene::Option &title_pos_option(scene_->options().find("title-pos")->second); const Scene::Option &title_size_option(scene_->options().find("title-size")->second); title_renderer_ = new TextRenderer(canvas_); title_renderer_->position(vec2_from_pos_string(title_pos_option.value)); title_renderer_->size(Util::fromString(title_size_option.value)); if (title_option.value == "#info#") title_renderer_->text(scene_->info_string()); else if (title_option.value == "#name#") title_renderer_->text(scene_->name()); else if (title_option.value == "#r2d2#") title_renderer_->text("Help me, Obi-Wan Kenobi. You're my only hope."); else title_renderer_->text(title_option.value); } } void MainLoopDecoration::fps_renderer_update_text(unsigned int fps) { std::stringstream ss; ss << "FPS: " << fps; fps_renderer_->text(ss.str()); } LibMatrix::vec2 MainLoopDecoration::vec2_from_pos_string(const std::string &s) { LibMatrix::vec2 v(0.0, 0.0); std::vector elems; Util::split(s, ',', elems, Util::SplitModeNormal); if (elems.size() > 0) v.x(Util::fromString(elems[0])); if (elems.size() > 1) v.y(Util::fromString(elems[1])); return v; } /********************** * MainLoopValidation * **********************/ MainLoopValidation::MainLoopValidation(Canvas &canvas, const std::vector &benchmarks) : MainLoop(canvas, benchmarks) { } void MainLoopValidation::draw() { /* Draw only the first frame of the scene and stop */ canvas_.clear(); scene_->draw(); canvas_.update(); scene_->running(false); } void MainLoopValidation::log_scene_result() { static const std::string format(Log::continuation_prefix + " Validation: %s\n"); std::string result; switch(scene_->validate()) { case Scene::ValidationSuccess: result = "Success"; break; case Scene::ValidationFailure: result = "Failure"; break; case Scene::ValidationUnknown: result = "Unknown"; break; default: break; } Log::info(format.c_str(), result.c_str()); }