blob: 96928cdcb9ea968a2e3045b3e36542d7aab6d28a [file] [log] [blame]
/*
* Copyright © 2008 Ben Smith
* Copyright © 2010-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 <http://www.gnu.org/licenses/>.
*
* Authors:
* Ben Smith (original glmark benchmark)
* Alexandros Frantzis (glmark2)
*/
#include "scene.h"
#include "log.h"
#include "shader-source.h"
#include "options.h"
#include "util.h"
#include <sstream>
#include <cmath>
#include <sys/time.h>
using std::stringstream;
using std::string;
using std::map;
Scene::Scene(Canvas &pCanvas, const string &name) :
canvas_(pCanvas), name_(name),
startTime_(0), lastUpdateTime_(0), currentFrame_(0), averageFPS_(0),
running_(0), duration_(0)
{
options_["duration"] = Scene::Option("duration", "10.0",
"The duration of each benchmark in seconds");
options_["vertex-precision"] = Scene::Option("vertex-precision",
"default,default,default,default",
"The precision values for the vertex shader (\"int,float,sampler2d,samplercube\")");
options_["fragment-precision"] = Scene::Option("fragment-precision",
"default,default,default,default",
"The precision values for the fragment shader (\"int,float,sampler2d,samplercube\")");
}
Scene::~Scene()
{
}
int
Scene::load()
{
return 1;
}
void
Scene::unload()
{
}
void
Scene::setup()
{
duration_ = Util::fromString<double>(options_["duration"].value);
ShaderSource::default_precision(
ShaderSource::Precision(options_["vertex-precision"].value),
ShaderSource::ShaderTypeVertex
);
ShaderSource::default_precision(
ShaderSource::Precision(options_["fragment-precision"].value),
ShaderSource::ShaderTypeFragment
);
}
void
Scene::teardown()
{
}
void
Scene::update()
{
}
void
Scene::draw()
{
}
string
Scene::info_string(const string &title)
{
stringstream ss;
ss << "[" << name_ << "] " << Scene::construct_title(title) << " ";
return ss.str();
}
unsigned
Scene::average_fps()
{
return averageFPS_;
}
bool
Scene::is_running()
{
return running_;
}
bool
Scene::set_option(const string &opt, const string &val)
{
map<string, Option>::iterator iter = options_.find(opt);
if (iter == options_.end())
return false;
iter->second.value = val;
iter->second.set = true;
return true;
}
void
Scene::reset_options()
{
for (map<string, Option>::iterator iter = options_.begin();
iter != options_.end();
iter++)
{
Option &opt = iter->second;
opt.value = opt.default_value;
opt.set = false;
}
}
bool
Scene::set_option_default(const string &opt, const string &val)
{
map<string, Option>::iterator iter = options_.find(opt);
if (iter == options_.end())
return false;
iter->second.default_value = val;
return true;
}
string
Scene::construct_title(const string &title)
{
stringstream ss;
if (title == "") {
for (map<string, Option>::iterator iter = options_.begin();
iter != options_.end();
iter++)
{
if (Options::show_all_options || iter->second.set)
{
ss << iter->first << "=" << iter->second.value << ":";
}
}
if (ss.str().empty())
ss << "<default>:";
}
else
ss << title;
return ss.str();
}
double
Scene::pixel_value_distance(Canvas::Pixel p1, Canvas::Pixel p2,
bool use_alpha)
{
double s(0.0);
// These work without casts because of integer promotion rules
// (the Uint8s are promoted to ints)
s += (p1.r - p2.r) * (p1.r - p2.r);
s += (p1.g - p2.g) * (p1.g - p2.g);
s += (p1.b - p2.b) * (p1.b - p2.b);
if (use_alpha)
s += (p1.a - p2.a) * (p1.a - p2.a);
return std::sqrt(s);
}
bool
Scene::load_shaders_from_strings(Program &program,
const std::string &vtx_shader,
const std::string &frg_shader,
const std::string &vtx_shader_filename,
const std::string &frg_shader_filename)
{
program.init();
Log::debug("Loading vertex shader from file %s:\n%s",
vtx_shader_filename.c_str(), vtx_shader.c_str());
program.addShader(GL_VERTEX_SHADER, vtx_shader);
if (!program.valid()) {
Log::error("Failed to add vertex shader from file %s:\n %s\n",
vtx_shader_filename.c_str(),
program.errorMessage().c_str());
program.release();
return false;
}
Log::debug("Loading fragment shader from file %s:\n%s",
frg_shader_filename.c_str(), frg_shader.c_str());
program.addShader(GL_FRAGMENT_SHADER, frg_shader);
if (!program.valid()) {
Log::error("Failed to add fragment shader from file %s:\n %s\n",
frg_shader_filename.c_str(),
program.errorMessage().c_str());
program.release();
return false;
}
program.build();
if (!program.ready()) {
Log::error("Failed to link program created from files %s and %s: %s\n",
vtx_shader_filename.c_str(),
frg_shader_filename.c_str(),
program.errorMessage().c_str());
program.release();
return false;
}
return true;
}
bool
Scene::load_shaders_from_files(Program &program,
const std::string &vtx_shader_filename,
const std::string &frg_shader_filename)
{
std::string vtx_shader;
std::string frg_shader;
if (!gotSource(vtx_shader_filename, vtx_shader))
return false;
if (!gotSource(frg_shader_filename, frg_shader))
return false;
return Scene::load_shaders_from_strings(program, vtx_shader, frg_shader,
vtx_shader_filename,
frg_shader_filename);
}
uint64_t
Scene::get_timestamp_us()
{
struct timeval tv;
gettimeofday(&tv, NULL);
uint64_t now = static_cast<uint64_t>(tv.tv_sec) * 1000000 +
static_cast<double>(tv.tv_usec);
return now;
}