From patchwork Thu Jul 21 12:36:35 2011 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: 2982 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 8BEB623F4D for ; Thu, 21 Jul 2011 12:43:45 +0000 (UTC) Received: from mail-qy0-f180.google.com (mail-qy0-f180.google.com [209.85.216.180]) by fiordland.canonical.com (Postfix) with ESMTP id 5967CA18287 for ; Thu, 21 Jul 2011 12:43:45 +0000 (UTC) Received: by mail-qy0-f180.google.com with SMTP id 30so845420qyk.11 for ; Thu, 21 Jul 2011 05:43:45 -0700 (PDT) Received: by 10.229.25.212 with SMTP id a20mr175049qcc.148.1311252225068; Thu, 21 Jul 2011 05:43:45 -0700 (PDT) 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.229.217.78 with SMTP id hl14cs139554qcb; Thu, 21 Jul 2011 05:43:44 -0700 (PDT) Received: by 10.216.234.143 with SMTP id s15mr796271weq.66.1311251797169; Thu, 21 Jul 2011 05:36:37 -0700 (PDT) Received: from adelie.canonical.com (adelie.canonical.com [91.189.90.139]) by mx.google.com with ESMTP id x69si2377480weq.107.2011.07.21.05.36.36; Thu, 21 Jul 2011 05:36:37 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.139 as permitted sender) client-ip=91.189.90.139; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.139 as permitted sender) smtp.mail=bounces@canonical.com Received: from loganberry.canonical.com ([91.189.90.37]) by adelie.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1QjsUV-0000D0-VO for ; Thu, 21 Jul 2011 12:36:36 +0000 Received: from loganberry.canonical.com (localhost [127.0.0.1]) by loganberry.canonical.com (Postfix) with ESMTP id EB64A2E890D for ; Thu, 21 Jul 2011 12:36:35 +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: 82 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [Branch ~glmark2-dev/glmark2/trunk] Rev 82: Merge new-arch branch. Message-Id: <20110721123635.17019.39495.launchpad@loganberry.canonical.com> Date: Thu, 21 Jul 2011 12:36:35 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: bulk X-Generated-By: Launchpad (canonical.com); Revision="13475"; Instance="initZopeless config overlay" X-Launchpad-Hash: bf7c81fbb7fd29e43cf63e33c3f8623ff08b592b Merge authors: Alexandros Frantzis (afrantzis) Jesse Barker (jesse-barker) ------------------------------------------------------------ revno: 82 [merge] committer: Alexandros Frantzis timestamp: Fri 2011-06-10 14:35:37 +0300 message: Merge new-arch branch. added: src/benchmark.cpp src/benchmark.h src/log.cpp src/log.h src/options.cpp src/options.h modified: src/main.cpp src/mesh.cpp src/mesh.h src/model.cpp src/scene.cpp src/scene.h src/scenebuild.cpp src/sceneshading.cpp src/scenetexture.cpp src/screen-sdl-gl.cpp src/screen-sdl-glesv2.cpp src/screen.h src/texture.cpp src/texture.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 'src/benchmark.cpp' --- src/benchmark.cpp 1970-01-01 00:00:00 +0000 +++ src/benchmark.cpp 2011-06-09 14:07:23 +0000 @@ -0,0 +1,143 @@ +/* + * 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 "benchmark.h" +#include "log.h" +#include + +using std::string; +using std::vector; +using std::map; + +std::map Benchmark::mSceneMap; + +static void +split(const string &s, char delim, vector &elems) +{ + std::stringstream ss(s); + + string item; + while(std::getline(ss, item, delim)) + elems.push_back(item); +} + +static Scene & +get_scene_from_description(const string &s) +{ + vector elems; + + split(s, ':', elems); + + const string &name = !elems.empty() ? elems[0] : ""; + + return Benchmark::get_scene_by_name(name); +} + +static vector +get_options_from_description(const string &s) +{ + vector options; + vector elems; + + split(s, ':', elems); + + for (vector::const_iterator iter = ++elems.begin(); + iter != elems.end(); + iter++) + { + vector opt; + + split(*iter, '=', opt); + if (opt.size() == 2) + options.push_back(Benchmark::OptionPair(opt[0], opt[1])); + else + Log::info("Warning: ignoring invalid option string '%s' " + "in benchmark description\n", + iter->c_str()); + } + + return options; +} + +void +Benchmark::register_scene(Scene &scene) +{ + mSceneMap[scene.name()] = &scene; +} + +Scene & +Benchmark::get_scene_by_name(const string &name) +{ + map::const_iterator iter; + + if ((iter = mSceneMap.find(name)) != mSceneMap.end()) + return *(iter->second); + else + return Scene::dummy(); +} + +Benchmark::Benchmark(Scene &scene, const vector &options) : + mScene(scene), mOptions(options) +{ +} + +Benchmark::Benchmark(const string &name, const vector &options) : + mScene(Benchmark::get_scene_by_name(name)), mOptions(options) +{ +} + +Benchmark::Benchmark(const string &s) : + mScene(get_scene_from_description(s)), + mOptions(get_options_from_description(s)) +{ +} + +Scene & +Benchmark::setup_scene() +{ + mScene.reset_options(); + load_options(); + + mScene.load(); + mScene.setup(); + + return mScene; +} + +void +Benchmark::teardown_scene() +{ + mScene.teardown(); + mScene.unload(); +} + +void +Benchmark::load_options() +{ + for (vector::iterator iter = mOptions.begin(); + iter != mOptions.end(); + iter++) + { + mScene.set_option(iter->first, iter->second); + } +} + === added file 'src/benchmark.h' --- src/benchmark.h 1970-01-01 00:00:00 +0000 +++ src/benchmark.h 2011-06-09 14:07:23 +0000 @@ -0,0 +1,58 @@ +/* + * 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_BENCHMARK_H_ +#define GLMARK2_BENCHMARK_H_ + +#include +#include +#include + +#include "scene.h" + +class Benchmark +{ +public: + typedef std::pair OptionPair; + + Benchmark(Scene &scene, const std::vector &options); + Benchmark(const std::string &name, const std::vector &options); + // Create a benchmark from a description string of the form: + // scene[:opt1=val1:opt2=val2...] + Benchmark(const std::string &s); + + Scene &setup_scene(); + void teardown_scene(); + + static void register_scene(Scene &scene); + static Scene &get_scene_by_name(const std::string &name); + static const std::map &scenes() { return mSceneMap; } + +private: + Scene &mScene; + std::vector mOptions; + + void load_options(); + + static std::map mSceneMap; +}; + +#endif === added file 'src/log.cpp' --- src/log.cpp 1970-01-01 00:00:00 +0000 +++ src/log.cpp 2011-06-08 11:24:18 +0000 @@ -0,0 +1,58 @@ +/* + * Copyright © 2011 Linaro Limited + * + * This file is part of glcompbench. + * + * glcompbench 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. + * + * glcompbench 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 glcompbench. If not, see . + * + * Authors: + * Alexandros Frantzis + * Jesse Barker + */ + +#include +#include + +#include "options.h" +#include "log.h" + +void +Log::info(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stdout, fmt, ap); + va_end(ap); +} + +void +Log::debug(const char *fmt, ...) +{ + if (!Options::show_debug) + return; + va_list ap; + va_start(ap, fmt); + vfprintf(stdout, fmt, ap); + va_end(ap); +} + +void +Log::error(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + === added file 'src/log.h' --- src/log.h 1970-01-01 00:00:00 +0000 +++ src/log.h 2011-06-08 11:24:18 +0000 @@ -0,0 +1,35 @@ +/* + * Copyright © 2011 Linaro Limited + * + * This file is part of glcompbench. + * + * glcompbench 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. + * + * glcompbench 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 glcompbench. If not, see . + * + * Authors: + * Alexandros Frantzis + * Jesse Barker + */ + +#ifndef LOG_H_ +#define LOG_H_ + +class Log +{ +public: + static void info(const char *fmt, ...); + static void debug(const char *fmt, ...); + static void error(const char *fmt, ...); +}; + +#endif /* LOG_H_ */ === modified file 'src/main.cpp' --- src/main.cpp 2011-01-25 15:00:12 +0000 +++ src/main.cpp 2011-06-10 11:27:56 +0000 @@ -23,6 +23,11 @@ */ #include "oglsdl.h" #include "scene.h" +#include "benchmark.h" +#include "options.h" +#include "log.h" + +#include #if USE_GL #include "screen-sdl-gl.h" @@ -30,16 +35,101 @@ #include "screen-sdl-glesv2.h" #endif -#define UNUSED_PARAM(x) (void)(x) +using std::vector; +using std::map; +using std::string; + +static const char *default_benchmarks[] = { + "build:use-vbo=false", + "build:use-vbo=true", + "texture:texture-filter=nearest", + "texture:texture-filter=linear", + "texture:texture-filter=mipmap", + "shading:shading=gouraud", + "shading:shading=phong", + NULL +}; + +bool should_keep_running() +{ + bool running = true; + SDL_Event event; + + while(SDL_PollEvent(&event)) + { + switch(event.type) + { + case SDL_QUIT: + running = false; + break; + case SDL_KEYDOWN: + if(event.key.keysym.sym == SDLK_ESCAPE) + running = false; + break; + } + } + + return running; +} + +void +add_default_benchmarks(vector &benchmarks) +{ + for (const char **s = default_benchmarks; *s != NULL; s++) + benchmarks.push_back(new Benchmark(*s)); +} + +void +add_custom_benchmarks(vector &benchmarks) +{ + for (vector::const_iterator iter = Options::benchmarks.begin(); + iter != Options::benchmarks.end(); + iter++) + { + benchmarks.push_back(new Benchmark(*iter)); + } +} + +static void +list_scenes() +{ + const map &scenes = Benchmark::scenes(); + + for (map::const_iterator scene_iter = scenes.begin(); + scene_iter != scenes.end(); + scene_iter++) + { + Scene *scene = scene_iter->second; + Log::info("[Scene] %s\n", scene->name().c_str()); + + const map &options = scene->options(); + + for (map::const_iterator opt_iter = options.begin(); + opt_iter != options.end(); + opt_iter++) + { + const Scene::Option &opt = opt_iter->second; + Log::info(" [Option] %s\n" + " Description : %s\n" + " Default Value: %s\n", + opt.name.c_str(), + opt.description.c_str(), + opt.default_value.c_str()); + } + } +} int main(int argc, char *argv[]) { - UNUSED_PARAM(argc); - UNUSED_PARAM(argv); - - SDL_Event event; - int running = 1; - unsigned current_scene = 0; + unsigned score = 0; + + if (!Options::parse_args(argc, argv)) + return 1; + + if (Options::show_help) { + Options::print_help(); + return 0; + } // Create the screen #if USE_GL @@ -53,80 +143,63 @@ return 1; } + // Register the scenes, so they can be looked-up by name + Benchmark::register_scene(*new SceneBuild(screen)); + Benchmark::register_scene(*new SceneTexture(screen)); + Benchmark::register_scene(*new SceneShading(screen)); + + if (Options::list_scenes) { + list_scenes(); + return 0; + } + + // Add the benchmarks to run + vector benchmarks; + + if (Options::benchmarks.empty()) + add_default_benchmarks(benchmarks); + else + add_custom_benchmarks(benchmarks); + printf("=======================================================\n"); printf(" glmark2 %s\n", GLMARK_VERSION); printf("=======================================================\n"); screen.print_info(); printf("=======================================================\n"); - // Create the scenes. - Scene *scene[] = { - new SceneBuild(screen), - new SceneTexture(screen), - new SceneShading(screen), - }; - - unsigned num_scenes = sizeof(scene) / sizeof(*scene); - - // Load the first scene - if (!scene[current_scene]->load()) - return 1; - scene[current_scene]->start(); - - while(running) + // Run the benchmarks + for (vector::iterator bench_iter = benchmarks.begin(); + bench_iter != benchmarks.end(); + bench_iter++) { - while(SDL_PollEvent(&event)) + bool keep_running = true; + Benchmark *bench = *bench_iter; + Scene &scene = bench->setup_scene(); + std::cout << scene.info_string() << std::flush; + + while (scene.is_running() && + (keep_running = should_keep_running())) { - switch(event.type) - { - case SDL_QUIT: - running = 0; - break; - case SDL_KEYDOWN: - if(event.key.keysym.sym == SDLK_ESCAPE) - running = 0; - break; - } - } - - screen.clear(); - - // Update the state of the current scene - scene[current_scene]->update(); - - // If the current scene is still running then draw it, - // otherwise move to the next scene - if (scene[current_scene]->is_running()) { - scene[current_scene]->draw(); - } - else { - // Unload the current scene - scene[current_scene]->unload(); - - current_scene++; - - // Do we have another scene? - if (current_scene < num_scenes) { - // Load and start next scene - if (!scene[current_scene]->load()) - return 1; - scene[current_scene]->start(); - } - else - running = false; - } - - - screen.update(); + screen.clear(); + + scene.draw(); + scene.update(); + + screen.update(); + } + + std::cout << " FPS: " << scene.average_fps() << std::endl; + score += scene.average_fps(); + + bench->teardown_scene(); + + if (!keep_running) + break; } - unsigned score = 0; - for (unsigned i = 0; i < num_scenes; i++) - score += scene[i]->calculate_score(); - printf("=======================================================\n"); printf(" glmark2 Score: %u \n", score); - printf("=======================================================\n"); + printf("=======================================================\n"); return 0; } === modified file 'src/mesh.cpp' --- src/mesh.cpp 2011-01-25 15:00:12 +0000 +++ src/mesh.cpp 2011-06-07 09:40:55 +0000 @@ -44,8 +44,20 @@ Mesh::~Mesh() { + reset(); +} + +void +Mesh::reset() +{ delete [] mVertex; - //deleteArray + + delete_vbo(); + + mPolygonQty = 0; + mVertexQty = 0; + mMode = GL_TRIANGLES; + mVertex = 0; } void Mesh::make_cube() @@ -180,6 +192,14 @@ #endif } +void +Mesh::delete_vbo() +{ + glDeleteBuffers(1, &mVBOVertices); + glDeleteBuffers(1, &mVBONormals); + glDeleteBuffers(1, &mVBOTexCoords); +} + void Mesh::render_vbo() { // Enable the attributes === modified file 'src/mesh.h' --- src/mesh.h 2011-01-25 15:06:04 +0000 +++ src/mesh.h 2011-06-07 09:40:55 +0000 @@ -64,10 +64,12 @@ Mesh(); // Default Constructor, should set pointers to null ~Mesh(); + void reset(); void make_cube(); void make_torus(); void render_array(); void build_vbo(); + void delete_vbo(); void render_vbo(); }; === modified file 'src/model.cpp' --- src/model.cpp 2011-01-25 15:00:12 +0000 +++ src/model.cpp 2011-06-07 09:40:55 +0000 @@ -49,6 +49,8 @@ #ifdef _DEBUG printf("Converting model to mesh... "); #endif + pMesh->reset(); + pMesh->mVertexQty = 3 * mPolygonQty; pMesh->mPolygonQty = mPolygonQty; pMesh->mMode = GL_TRIANGLES; === added file 'src/options.cpp' --- src/options.cpp 1970-01-01 00:00:00 +0000 +++ src/options.cpp 2011-06-09 14:54:24 +0000 @@ -0,0 +1,93 @@ +/* + * Copyright © 2011 Linaro Limited + * + * This file is part of glcompbench. + * + * glcompbench 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. + * + * glcompbench 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 glcompbench. If not, see . + * + * Authors: + * Alexandros Frantzis + * Jesse Barker + */ + +#include +#include +#include +#include + +#include "options.h" + +std::vector Options::benchmarks; +bool Options::swap_buffers = true; +bool Options::list_scenes = false; +bool Options::show_debug = false; +bool Options::show_help = false; + +static struct option long_options[] = { + {"benchmark", 1, 0, 0}, + {"no-swap-buffers", 0, 0, 0}, + {"list-scenes", 0, 0, 0}, + {"debug", 0, 0, 0}, + {"help", 0, 0, 0}, + {0, 0, 0, 0} +}; + +void +Options::print_help() +{ + printf("A benchmark for Open GL (ES) 2.0\n" + "\n" + "Options:\n" + " -b, --benchmark BENCH A benchmark to run: 'scene(:opt1=val1)*'\n" + " (the option can be used multiple times)\n" + " --no-swap-buffers Don't update the screen by swapping the front and\n" + " back buffer, use glFinish() instead\n" + " -l, --list-scenes Display information about the available scenes\n" + " and their options\n" + " -d, --debug Display debug messages\n" + " -h, --help Display help\n"); +} + +bool +Options::parse_args(int argc, char **argv) +{ + while (1) { + int option_index = -1; + int c; + const char *optname = ""; + + c = getopt_long(argc, argv, "b:ldh", + long_options, &option_index); + if (c == -1) + break; + if (c == ':' || c == '?') + return false; + + if (option_index != -1) + optname = long_options[option_index].name; + + if (c == 'b' || !strcmp(optname, "benchmark")) + Options::benchmarks.push_back(optarg); + else if (!strcmp(optname, "no-swap-buffers")) + Options::swap_buffers = false; + else if (c == 'l' || !strcmp(optname, "list-scenes")) + Options::list_scenes = true; + else if (c == 'd' || !strcmp(optname, "debug")) + Options::show_debug = true; + else if (c == 'h' || !strcmp(optname, "help")) + Options::show_help = true; + } + + return true; +} === added file 'src/options.h' --- src/options.h 1970-01-01 00:00:00 +0000 +++ src/options.h 2011-06-09 14:24:50 +0000 @@ -0,0 +1,41 @@ +/* + * Copyright © 2011 Linaro Limited + * + * This file is part of glcompbench. + * + * glcompbench 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. + * + * glcompbench 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 glcompbench. If not, see . + * + * Authors: + * Alexandros Frantzis + * Jesse Barker + */ + +#ifndef OPTIONS_H_ +#define OPTIONS_H_ + +#include +#include + +struct Options { + static bool parse_args(int argc, char **argv); + static void print_help(); + + static std::vector benchmarks; + static bool swap_buffers; + static bool list_scenes; + static bool show_debug; + static bool show_help; +}; + +#endif /* OPTIONS_H_ */ === modified file 'src/scene.cpp' --- src/scene.cpp 2011-01-25 15:00:12 +0000 +++ src/scene.cpp 2011-06-07 21:06:38 +0000 @@ -22,32 +22,23 @@ * Alexandros Frantzis (glmark2) */ #include "scene.h" - -Scene::Scene(Screen &pScreen) : - mScreen(pScreen) +#include + +using std::stringstream; +using std::string; +using std::map; + +Scene::Scene(Screen &pScreen, const string &name) : + mScreen(pScreen), mName(name), + mStartTime(0), mLastUpdateTime(0), mCurrentFrame(0), mAverageFPS(0), + mRunning(0), mDuration(0) { - mPartsQty = 0; - mCurrentPart = 0; - mPartDuration = 0; - - mLastTime = 0; - mCurrentTime = 0; - mDt = 0; - mCurrentFrame = 0; - mRunning = false; - - mAverageFPS = 0; - mScoreScale = 0; - - mStartTime = 0; - mElapsedTime = 0; + mOptions["duration"] = Scene::Option("duration", "10.0", + "The duration of each benchmark in seconds"); } Scene::~Scene() { - delete [] mPartDuration; - delete [] mAverageFPS; - delete [] mScoreScale; } int Scene::load() @@ -59,7 +50,13 @@ { } -void Scene::start() +void Scene::setup() +{ + stringstream ss(mOptions["duration"].value); + ss >> mDuration; +} + +void Scene::teardown() { } @@ -71,14 +68,19 @@ { } -unsigned Scene::calculate_score() -{ - unsigned mScore = 0; - - for(unsigned i = 0; i < mPartsQty; i++) - mScore += mAverageFPS[i] * mScoreScale[i]; - - return mScore; +string +Scene::info_string(const string &title) +{ + stringstream ss; + + ss << "[" << mName << "] " << Scene::construct_title(title) << " "; + + return ss.str(); +} + +unsigned Scene::average_fps() +{ + return mAverageFPS; } @@ -86,3 +88,49 @@ { return mRunning; } + +bool +Scene::set_option(const string &opt, const string &val) +{ + map::iterator iter = mOptions.find(opt); + + if (iter == mOptions.end()) + return false; + + iter->second.value = val; + + return true; +} + +void +Scene::reset_options() +{ + for (map::iterator iter = mOptions.begin(); + iter != mOptions.end(); + iter++) + { + Option &opt = iter->second; + + opt.value = opt.default_value; + } +} + + +string +Scene::construct_title(const string &title) +{ + stringstream ss; + + if (title == "") { + for (map::iterator iter = mOptions.begin(); + iter != mOptions.end(); + iter++) + { + ss << iter->first << "=" << iter->second.value << ":"; + } + } + else + ss << title; + + return ss.str(); +} === modified file 'src/scene.h' --- src/scene.h 2011-01-25 15:06:04 +0000 +++ src/scene.h 2011-06-09 13:07:57 +0000 @@ -33,46 +33,80 @@ #include +#include +#include + class Scene { public: - Scene(Screen &pScreen); ~Scene(); + struct Option { + Option(const std::string &nam, const std::string &val, const std::string &desc) : + name(nam), value(val), default_value(val), description(desc) {} + Option() {} + std::string name; + std::string value; + std::string default_value; + std::string description; + }; + + // load() and unload() handle option-independent configuration. + // It should be safe to call these only once per program execution, + // although you may choose to do so more times to better manage + // resource consumption. virtual int load(); virtual void unload(); - virtual void start(); + + // setup() and teardown() handle option-dependent configuration and + // also prepare a scene for a benchmark run. + // They should be called just before and after running a scene/benchmark. + virtual void setup(); + virtual void teardown(); + virtual void update(); virtual void draw(); + virtual std::string info_string(const std::string &title = ""); - unsigned calculate_score(); + unsigned average_fps(); bool is_running(); + const std::string &name() { return mName; } + bool set_option(const std::string &opt, const std::string &val); + void reset_options(); + const std::map &options() { return mOptions; } + + static Scene &dummy() + { + static Scene dummy_scene(Screen::dummy(), ""); + return dummy_scene; + } + protected: - unsigned mPartsQty; // How many parts for the scene - unsigned mCurrentPart; // The current part being rendered - double *mPartDuration; // Duration per part in seconds - - double mLastTime, mCurrentTime, mDt; + Scene(Screen &pScreen, const std::string &name); + std::string construct_title(const std::string &title); + + Screen &mScreen; + std::string mName; + std::map mOptions; + + double mStartTime; + double mLastUpdateTime; unsigned mCurrentFrame; + unsigned mAverageFPS; // Average FPS of run + bool mRunning; - - unsigned *mAverageFPS; // Average FPS per part - float *mScoreScale; - - double mStartTime; - double mElapsedTime; - - Screen &mScreen; + double mDuration; // Duration of run in seconds }; class SceneBuild : public Scene { public: - SceneBuild(Screen &pScreen) : Scene(pScreen) {} + SceneBuild(Screen &pScreen); int load(); void unload(); - void start(); + void setup(); + void teardown(); void update(); void draw(); @@ -84,15 +118,17 @@ Mesh mMesh; float mRotation; float mRotationSpeed; + bool mUseVbo; }; class SceneTexture : public Scene { public: - SceneTexture(Screen &pScreen) : Scene(pScreen) {} + SceneTexture(Screen &pScreen); int load(); void unload(); - void start(); + void setup(); + void teardown(); void update(); void draw(); @@ -102,7 +138,7 @@ Shader mShader; Mesh mCubeMesh; - GLuint mTexture[3]; + GLuint mTexture; Vector3f mRotation; Vector3f mRotationSpeed; }; @@ -110,17 +146,18 @@ class SceneShading : public Scene { public: - SceneShading(Screen &pScreen) : Scene(pScreen) {} + SceneShading(Screen &pScreen); int load(); void unload(); - void start(); + void setup(); + void teardown(); void update(); void draw(); ~SceneShading(); protected: - Shader mShader[2]; + Shader mShader; Mesh mMesh; float mRotation; === modified file 'src/scenebuild.cpp' --- src/scenebuild.cpp 2011-01-25 15:00:12 +0000 +++ src/scenebuild.cpp 2011-06-07 14:36:16 +0000 @@ -23,6 +23,13 @@ */ #include "scene.h" +SceneBuild::SceneBuild(Screen &pScreen) : + Scene(pScreen, "build") +{ + mOptions["use-vbo"] = Scene::Option("use-vbo", "true", + "Whether to use VBOs for rendering [true,false]"); +} + SceneBuild::~SceneBuild() { } @@ -37,47 +44,38 @@ model.calculate_normals(); model.convert_to_mesh(&mMesh); - mMesh.build_vbo(); - mShader.load(GLMARK_DATA_PATH"/shaders/light-basic.vert", GLMARK_DATA_PATH"/shaders/light-basic.frag"); mRotationSpeed = 36.0f; - mRotation = 0.0; mRunning = false; - mPartsQty = 2; - mPartDuration = new double[mPartsQty]; - mAverageFPS = new unsigned[mPartsQty]; - mScoreScale = new float[mPartsQty]; - - mScoreScale[0] = 1.0f / mPartsQty; - mScoreScale[1] = 1.0f / mPartsQty; - - mPartDuration[0] = 10.0; - mPartDuration[1] = 10.0; - - memset(mAverageFPS, 0, mPartsQty * sizeof(*mAverageFPS)); - - mCurrentPart = 0; - return 1; } void SceneBuild::unload() { + mMesh.reset(); mShader.remove(); mShader.unload(); } -void SceneBuild::start() +void SceneBuild::setup() { + Scene::setup(); + GLfloat lightAmbient[] = {0.0f, 0.0f, 0.0f, 1.0f}; GLfloat lightDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f}; GLfloat lightPosition[] = {20.0f, 20.0f, 10.0f, 1.0f}; GLfloat materialColor[] = {1.0f, 1.0f, 1.0f, 1.0f}; + + mUseVbo = (mOptions["use-vbo"].value == "true"); + + if (mUseVbo) + mMesh.build_vbo(); + mShader.use(); // Load lighting and material uniforms @@ -89,43 +87,37 @@ glUniform4fv(mShader.mLocations.MaterialColor, 1, materialColor); mCurrentFrame = 0; + mRotation = 0.0; mRunning = true; mStartTime = SDL_GetTicks() / 1000.0; - mLastTime = mStartTime; - - if (mCurrentPart == 0) - printf("[Suite] Precompilation\n"); + mLastUpdateTime = mStartTime; +} + +void +SceneBuild::teardown() +{ + mShader.remove(); + + if (mUseVbo) + mMesh.delete_vbo(); + + Scene::teardown(); } void SceneBuild::update() { - mCurrentTime = SDL_GetTicks() / 1000.0; - mDt = mCurrentTime - mLastTime; - mLastTime = mCurrentTime; - - mElapsedTime = mCurrentTime - mStartTime; - - if(mElapsedTime >= mPartDuration[mCurrentPart]) - { - mAverageFPS[mCurrentPart] = mCurrentFrame / mElapsedTime; - - switch(mCurrentPart) - { - case 0: - printf(" [Benchmark] Vertex array FPS: %u\n", mAverageFPS[mCurrentPart]); - break; - case 1: - printf(" [Benchmark] Vertex buffer object FPS: %u\n", mAverageFPS[mCurrentPart]); - break; - } - mCurrentPart++; - if(mCurrentPart >= mPartsQty) - mRunning = false; - else - start(); + double current_time = SDL_GetTicks() / 1000.0; + double dt = current_time - mLastUpdateTime; + double elapsed_time = current_time - mStartTime; + + mLastUpdateTime = current_time; + + if (elapsed_time >= mDuration) { + mAverageFPS = mCurrentFrame / elapsed_time; + mRunning = false; } - mRotation += mRotationSpeed * mDt; + mRotation += mRotationSpeed * dt; mCurrentFrame++; } @@ -149,13 +141,8 @@ glUniformMatrix4fv(mShader.mLocations.NormalMatrix, 1, GL_FALSE, model_view.m); - switch(mCurrentPart) - { - case 0: + if (mUseVbo) + mMesh.render_vbo(); + else mMesh.render_array(); - break; - case 1: - mMesh.render_vbo(); - break; - } } === modified file 'src/sceneshading.cpp' --- src/sceneshading.cpp 2011-01-25 15:00:12 +0000 +++ src/sceneshading.cpp 2011-06-07 21:06:38 +0000 @@ -24,6 +24,13 @@ #include "scene.h" #include "matrix.h" +SceneShading::SceneShading(Screen &pScreen) : + Scene(pScreen, "shading") +{ + mOptions["shading"] = Scene::Option("shading", "gouraud", + "[gouraud, phong]"); +} + SceneShading::~SceneShading() { } @@ -40,44 +47,22 @@ mMesh.build_vbo(); - mShader[0].load(GLMARK_DATA_PATH"/shaders/light-basic.vert", - GLMARK_DATA_PATH"/shaders/light-basic.frag"); - mShader[1].load(GLMARK_DATA_PATH"/shaders/light-advanced.vert", - GLMARK_DATA_PATH"/shaders/light-advanced.frag"); - mRotationSpeed = 36.0f; - mRotation = 0.0f; mRunning = false; - mPartsQty = 2; - mPartDuration = new double[mPartsQty]; - mAverageFPS = new unsigned[mPartsQty]; - mScoreScale = new float[mPartsQty]; - - mScoreScale[0] = 1.0f / mPartsQty; - mScoreScale[1] = 1.0f / mPartsQty; - - mPartDuration[0] = 10.0; - mPartDuration[1] = 10.0; - - memset(mAverageFPS, 0, mPartsQty * sizeof(*mAverageFPS)); - - mCurrentPart = 0; - return 1; } void SceneShading::unload() { - for(unsigned i = 0; i < mPartsQty; i++) { - mShader[i].remove(); - mShader[i].unload(); - } + mMesh.reset(); } -void SceneShading::start() +void SceneShading::setup() { + Scene::setup(); + GLfloat lightAmbient[] = {0.1f, 0.1f, 0.1f, 1.0f}; GLfloat lightDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f}; GLfloat lightSpecular[] = {0.8f, 0.8f, 0.8f, 1.0f}; @@ -88,67 +73,68 @@ float materialSpecular[] = {1.0f, 1.0f, 1.0f, 1.0f}; float materialColor[] = {0.0f, 0.0f, 1.0f, 1.0f}; - mShader[mCurrentPart].use(); + const std::string &shading = mOptions["shading"].value; + + if (shading == "gouraud") { + mShader.load(GLMARK_DATA_PATH"/shaders/light-basic.vert", + GLMARK_DATA_PATH"/shaders/light-basic.frag"); + } + else if (shading == "phong") { + mShader.load(GLMARK_DATA_PATH"/shaders/light-advanced.vert", + GLMARK_DATA_PATH"/shaders/light-advanced.frag"); + } + + mShader.use(); // Load lighting and material uniforms - glUniform4fv(mShader[mCurrentPart].mLocations.LightSourcePosition, 1, lightPosition); - - glUniform3fv(mShader[mCurrentPart].mLocations.LightSourceAmbient, 1, lightAmbient); - glUniform3fv(mShader[mCurrentPart].mLocations.LightSourceDiffuse, 1, lightDiffuse); - glUniform3fv(mShader[mCurrentPart].mLocations.LightSourceSpecular, 1, lightSpecular); - - glUniform3fv(mShader[mCurrentPart].mLocations.MaterialAmbient, 1, materialAmbient); - glUniform3fv(mShader[mCurrentPart].mLocations.MaterialDiffuse, 1, materialDiffuse); - glUniform3fv(mShader[mCurrentPart].mLocations.MaterialSpecular, 1, materialSpecular); - glUniform4fv(mShader[mCurrentPart].mLocations.MaterialColor, 1, materialColor); + glUniform4fv(mShader.mLocations.LightSourcePosition, 1, lightPosition); + + glUniform3fv(mShader.mLocations.LightSourceAmbient, 1, lightAmbient); + glUniform3fv(mShader.mLocations.LightSourceDiffuse, 1, lightDiffuse); + glUniform3fv(mShader.mLocations.LightSourceSpecular, 1, lightSpecular); + + glUniform3fv(mShader.mLocations.MaterialAmbient, 1, materialAmbient); + glUniform3fv(mShader.mLocations.MaterialDiffuse, 1, materialDiffuse); + glUniform3fv(mShader.mLocations.MaterialSpecular, 1, materialSpecular); + glUniform4fv(mShader.mLocations.MaterialColor, 1, materialColor); // Calculate and load the half vector Vector3f halfVector = Vector3f(lightPosition[0], lightPosition[1], lightPosition[2]); halfVector.normalize(); halfVector += Vector3f(0.0, 0.0, 1.0); halfVector.normalize(); - glUniform3fv(mShader[mCurrentPart].mLocations.LightSourceHalfVector, 1, + glUniform3fv(mShader.mLocations.LightSourceHalfVector, 1, (GLfloat *)&halfVector); mCurrentFrame = 0; + mRotation = 0.0f; mRunning = true; mStartTime = SDL_GetTicks() / 1000.0; - mLastTime = mStartTime; - - if (mCurrentPart == 0) - printf("[Suite] Shading\n"); + mLastUpdateTime = mStartTime; +} + +void SceneShading::teardown() +{ + mShader.remove(); + mShader.unload(); + + Scene::teardown(); } void SceneShading::update() { - mCurrentTime = SDL_GetTicks() / 1000.0; - mDt = mCurrentTime - mLastTime; - mLastTime = mCurrentTime; - - mElapsedTime = mCurrentTime - mStartTime; - - if(mElapsedTime >= mPartDuration[mCurrentPart]) - { - mAverageFPS[mCurrentPart] = mCurrentFrame / mElapsedTime; - - switch(mCurrentPart) { - case 0: - printf(" [Benchmark] GLSL per vertex lighting FPS: %u\n", - mAverageFPS[mCurrentPart]); - break; - case 1: - printf(" [Benchmark] GLSL per pixel lighting FPS: %u\n", - mAverageFPS[mCurrentPart]); - break; - } - mCurrentPart++; - if(mCurrentPart >= mPartsQty) - mRunning = false; - else - start(); + double current_time = SDL_GetTicks() / 1000.0; + double dt = current_time - mLastUpdateTime; + double elapsed_time = current_time - mStartTime; + + mLastUpdateTime = current_time; + + if (elapsed_time >= mDuration) { + mAverageFPS = mCurrentFrame / elapsed_time; + mRunning = false; } - mRotation += mRotationSpeed * mDt; + mRotation += mRotationSpeed * dt; mCurrentFrame++; } @@ -163,13 +149,13 @@ model_view.rotate(2 * M_PI * mRotation / 360.0, 0.0f, 1.0f, 0.0f); model_view_proj *= model_view; - glUniformMatrix4fv(mShader[mCurrentPart].mLocations.ModelViewProjectionMatrix, 1, + glUniformMatrix4fv(mShader.mLocations.ModelViewProjectionMatrix, 1, GL_FALSE, model_view_proj.m); // Load the NormalMatrix uniform in the shader. The NormalMatrix is the // inverse transpose of the model view matrix. model_view.invert().transpose(); - glUniformMatrix4fv(mShader[mCurrentPart].mLocations.NormalMatrix, 1, + glUniformMatrix4fv(mShader.mLocations.NormalMatrix, 1, GL_FALSE, model_view.m); mMesh.render_vbo(); === modified file 'src/scenetexture.cpp' --- src/scenetexture.cpp 2011-01-25 15:00:12 +0000 +++ src/scenetexture.cpp 2011-06-07 21:06:38 +0000 @@ -24,10 +24,15 @@ #include "scene.h" #include "matrix.h" +SceneTexture::SceneTexture(Screen &pScreen) : + Scene(pScreen, "texture") +{ + mOptions["texture-filter"] = Scene::Option("texture-filter", "nearest", + "[nearest, linear, mipmap]"); +} + SceneTexture::~SceneTexture() { - for(unsigned i = 0; i < 3; i++) - glDeleteTextures(1, &mTexture[i]); } int SceneTexture::load() @@ -37,9 +42,6 @@ if(!model.load_3ds(GLMARK_DATA_PATH"/models/cube.3ds")) return 0; - if(!load_texture(GLMARK_DATA_PATH"/textures/crate-base.bmp", mTexture)) - return 0; - model.calculate_normals(); model.convert_to_mesh(&mCubeMesh); mCubeMesh.build_vbo(); @@ -51,39 +53,45 @@ mRunning = false; - mPartsQty = 3; - mPartDuration = new double[mPartsQty]; - mAverageFPS = new unsigned[mPartsQty]; - mScoreScale = new float[mPartsQty]; - - mScoreScale[0] = 1.0f / mPartsQty; - mScoreScale[1] = 1.0f / mPartsQty; - mScoreScale[2] = 1.0f / mPartsQty; - - mPartDuration[0] = 10.0; - mPartDuration[1] = 10.0; - mPartDuration[2] = 10.0; - - memset(mAverageFPS, 0, mPartsQty * sizeof(*mAverageFPS)); - - mCurrentPart = 0; - return 1; } void SceneTexture::unload() { - mShader.remove(); + mCubeMesh.reset(); mShader.unload(); } -void SceneTexture::start() +void SceneTexture::setup() { + Scene::setup(); + GLfloat lightAmbient[] = {0.0f, 0.0f, 0.0f, 1.0f}; GLfloat lightDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f}; GLfloat lightPosition[] = {20.0f, 20.0f, 10.0f, 1.0f}; GLfloat materialColor[] = {1.0f, 1.0f, 1.0f, 1.0f}; + // Create texture according to selected filtering + GLint min_filter = GL_NONE; + GLint mag_filter = GL_NONE; + const std::string &filter = mOptions["texture-filter"].value; + + if (filter == "nearest") { + min_filter = GL_NEAREST; + mag_filter = GL_NEAREST; + } + else if (filter == "linear") { + min_filter = GL_LINEAR; + mag_filter = GL_LINEAR; + } + else if (filter == "mipmap") { + min_filter = GL_LINEAR_MIPMAP_LINEAR; + mag_filter = GL_LINEAR; + } + + Texture::load(GLMARK_DATA_PATH"/textures/crate-base.bmp", &mTexture, + min_filter, mag_filter, 0); + mShader.use(); // Load lighting and material uniforms @@ -95,45 +103,34 @@ glUniform4fv(mShader.mLocations.MaterialColor, 1, materialColor); mCurrentFrame = 0; + mRotation = Vector3f(); mRunning = true; mStartTime = SDL_GetTicks() / 1000.0; - mLastTime = mStartTime; - - if (mCurrentPart == 0) - printf("[Suite] Texture filtering\n"); + mLastUpdateTime = mStartTime; +} + +void SceneTexture::teardown() +{ + mShader.remove(); + glDeleteTextures(1, &mTexture); + + Scene::teardown(); } void SceneTexture::update() { - mCurrentTime = SDL_GetTicks() / 1000.0; - mDt = mCurrentTime - mLastTime; - mLastTime = mCurrentTime; - - mElapsedTime = mCurrentTime - mStartTime; - - if(mElapsedTime >= mPartDuration[mCurrentPart]) - { - mAverageFPS[mCurrentPart] = mCurrentFrame / mElapsedTime; - - switch(mCurrentPart) { - case 0: - printf(" [Benchmark] Nearest FPS: %u\n", mAverageFPS[mCurrentPart]); - break; - case 1: - printf(" [Benchmark] Linear FPS: %u\n", mAverageFPS[mCurrentPart]); - break; - case 2: - printf(" [Benchmark] Mipmapped FPS: %u\n", mAverageFPS[mCurrentPart]); - break; - } - mCurrentPart++; - if(mCurrentPart >= mPartsQty) - mRunning = false; - else - start(); + double current_time = SDL_GetTicks() / 1000.0; + double dt = current_time - mLastUpdateTime; + double elapsed_time = current_time - mStartTime; + + mLastUpdateTime = current_time; + + if (elapsed_time >= mDuration) { + mAverageFPS = mCurrentFrame / elapsed_time; + mRunning = false; } - mRotation += mRotationSpeed * mDt; + mRotation += mRotationSpeed * dt; mCurrentFrame++; } @@ -160,7 +157,7 @@ GL_FALSE, model_view.m); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mTexture[mCurrentPart]); + glBindTexture(GL_TEXTURE_2D, mTexture); mCubeMesh.render_vbo(); } === modified file 'src/screen-sdl-gl.cpp' --- src/screen-sdl-gl.cpp 2011-01-25 15:00:12 +0000 +++ src/screen-sdl-gl.cpp 2011-06-09 10:13:18 +0000 @@ -22,6 +22,7 @@ * Alexandros Frantzis (glmark2) */ #include "screen-sdl-gl.h" +#include "options.h" ScreenSDLGL::ScreenSDLGL(int pWidth, int pHeight, int pBpp, int pFullScreen, int pFlags) : ScreenSDL(pWidth, pHeight, pBpp, pFullScreen, pFlags | SDL_OPENGL) @@ -50,7 +51,10 @@ void ScreenSDLGL::update() { - SDL_GL_SwapBuffers(); + if (Options::swap_buffers) + SDL_GL_SwapBuffers(); + else + glFinish(); } void ScreenSDLGL::print_info() === modified file 'src/screen-sdl-glesv2.cpp' --- src/screen-sdl-glesv2.cpp 2011-04-15 18:20:15 +0000 +++ src/screen-sdl-glesv2.cpp 2011-06-09 10:13:18 +0000 @@ -23,6 +23,7 @@ */ #include "screen-sdl-glesv2.h" #include "sdlgles/SDL_gles.h" +#include "options.h" ScreenSDLGLESv2::ScreenSDLGLESv2(int pWidth, int pHeight, int pBpp, int pFullScreen, int pFlags) : ScreenSDL(pWidth, pHeight, pBpp, pFullScreen, pFlags) @@ -96,7 +97,10 @@ void ScreenSDLGLESv2::update() { - SDL_GLES_SwapBuffers(); + if (Options::swap_buffers) + SDL_GLES_SwapBuffers(); + else + glFinish(); } void ScreenSDLGLESv2::print_info() === modified file 'src/screen.h' --- src/screen.h 2011-01-25 15:06:04 +0000 +++ src/screen.h 2011-06-09 13:07:57 +0000 @@ -32,6 +32,8 @@ class Screen { public: + ~Screen() {} + int mWidth; int mHeight; int mBpp; @@ -39,9 +41,18 @@ Matrix4f mProjection; int mInitSuccess; - virtual void clear() = 0; - virtual void update() = 0; - virtual void print_info() = 0; + virtual void clear() {} + virtual void update() {} + virtual void print_info() {} + + static Screen &dummy() + { + static Screen dummy_screen; + return dummy_screen; + } + +protected: + Screen() {} }; #endif === modified file 'src/texture.cpp' --- src/texture.cpp 2011-01-25 15:00:12 +0000 +++ src/texture.cpp 2011-06-08 08:44:03 +0000 @@ -23,13 +23,32 @@ */ #include "texture.h" -int load_texture(const char pFilename[], GLuint *pTexture) +static void +setup_texture(GLuint *tex, GLenum format, SDL_Surface *surface, + GLint min_filter, GLint mag_filter) +{ + glGenTextures(1, tex); + glBindTexture(GL_TEXTURE_2D, *tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); + glTexImage2D(GL_TEXTURE_2D, 0, format, surface->w, surface->h, 0, + format, GL_UNSIGNED_BYTE, surface->pixels); + + if ((min_filter != GL_NEAREST && min_filter != GL_LINEAR) || + (mag_filter != GL_NEAREST && mag_filter != GL_LINEAR)) + { + glGenerateMipmap(GL_TEXTURE_2D); + } +} + +int +Texture::load(const std::string &filename, GLuint *pTexture, ...) { SDL_Surface *surface; GLenum texture_format = GL_RGB; GLint nOfColors; - if ((surface = SDL_LoadBMP(pFilename))) { + if ((surface = SDL_LoadBMP(filename.c_str()))) { if ((surface->w & (surface->w - 1)) != 0) printf("warning: image.bmp's width is not a power of 2\n"); @@ -79,29 +98,17 @@ printf("warning: the image is not truecolor.. this will probably break\n"); } - glGenTextures(3, pTexture); - - // Create Nearest Filtered Texture - glBindTexture(GL_TEXTURE_2D, pTexture[0]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, texture_format, surface->w, surface->h, 0, - texture_format, GL_UNSIGNED_BYTE, surface->pixels); - - // Create Linear Filtered Texture - glBindTexture(GL_TEXTURE_2D, pTexture[1]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, texture_format, surface->w, surface->h, 0, - texture_format, GL_UNSIGNED_BYTE, surface->pixels); - - // Create trilinear filtered mipmapped texture - glBindTexture(GL_TEXTURE_2D, pTexture[2]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, texture_format, surface->w, surface->h, 0, - texture_format, GL_UNSIGNED_BYTE, surface->pixels); - glGenerateMipmap(GL_TEXTURE_2D); + va_list ap; + va_start(ap, pTexture); + GLint arg; + + while ((arg = va_arg(ap, GLint)) != 0) { + GLint arg2 = va_arg(ap, GLint); + setup_texture(pTexture, texture_format, surface, arg, arg2); + pTexture++; + } + + va_end(ap); } else { fprintf(stderr, "SDL could not load image.bmp: %s\n", SDL_GetError()); === modified file 'src/texture.h' --- src/texture.h 2011-01-25 15:06:04 +0000 +++ src/texture.h 2011-06-08 08:44:03 +0000 @@ -26,8 +26,12 @@ #include "oglsdl.h" -#include +#include -int load_texture(const char pFilename[], GLuint *pTexture); +class Texture +{ +public: + static int load(const std::string &filename, GLuint *pTexture, ...); +}; #endif