<commit_before>// Copyright 2010-2012 Google
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <string>
#include <vector>

#include "base/integral_types.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/stringprintf.h"
#include "base/stl_util.h"
#include "constraint_solver/constraint_solver.h"
#include "util/string_array.h"

namespace operations_research {

// ----- Base Class -----

void NoGoodManager::EnterSearch() {
  Init();
}

void NoGoodManager::BeginNextDecision(DecisionBuilder* const db) {
  Apply();
}

bool NoGoodManager::AcceptSolution() {
  Apply();
  return true;
}

NoGood* NoGoodManager::MakeNoGood() {
  return new NoGood();
}

// ----- Base class for NoGood terms -----

class NoGoodTerm {
 public:
  enum TermStatus {
    ALWAYS_TRUE,
    ALWAYS_FALSE,
    UNDECIDED
  };
  NoGoodTerm() {}
  virtual ~NoGoodTerm() {}

  virtual TermStatus Evaluate() const = 0;
  virtual void Refute() = 0;
  virtual string DebugString() const = 0;
 private:
  DISALLOW_COPY_AND_ASSIGN(NoGoodTerm);
};

namespace {
// ----- IntegerVariableNoGoodTerm -----

// IntVar == int64 specialization.
class IntegerVariableNoGoodTerm : public NoGoodTerm {
 public:
  IntegerVariableNoGoodTerm(IntVar* const var, int64 value, bool assign)
      : integer_variable_(var), value_(value), assign_(assign) {
    CHECK_NOTNULL(integer_variable_);
  }

  virtual TermStatus Evaluate() const {
    if (!integer_variable_->Contains(value_)) {
      return assign_ ? ALWAYS_FALSE : ALWAYS_TRUE;
    } else if (integer_variable_->Bound()) {
      return assign_ ? ALWAYS_TRUE : ALWAYS_FALSE;
    } else {
      return UNDECIDED;
    }
  }

  virtual void Refute() {
    if (assign_) {
      integer_variable_->RemoveValue(value_);
    } else {
      integer_variable_->SetValue(value_);
    }
  }

  virtual string DebugString() const {
    return StringPrintf("(var_%s %s %lld)",
                        integer_variable_->name().c_str(),
                        assign_ ? "==" : "!=",
                        value_);
  }

  IntVar* integer_variable() const { return integer_variable_; }
  int64 value() const { return value_; }
  bool assign() const { return assign_; }

 private:
  IntVar* const integer_variable_;
  const int64 value_;
  const bool assign_;
  DISALLOW_COPY_AND_ASSIGN(IntegerVariableNoGoodTerm);
};
}  // namespace

// ----- NoGood -----

NoGood::~NoGood() {
  STLDeleteElements(&terms_);
}

void NoGood::AddIntegerVariableEqualValueTerm(IntVar* const var, int64 value) {
  terms_.push_back(new IntegerVariableNoGoodTerm(var, value, true));
}

void NoGood::AddIntegerVariableNotEqualValueTerm(IntVar* const var,
                                                 int64 value) {
  terms_.push_back(new IntegerVariableNoGoodTerm(var, value, false));
}

bool NoGood::Apply(Solver* const solver) {
  NoGoodTerm* first_undecided = NULL;
  for (int i = 0; i < terms_.size(); ++i) {
    switch (terms_[i]->Evaluate()) {
      case NoGoodTerm::ALWAYS_TRUE: {
        break;
      }
      case NoGoodTerm::ALWAYS_FALSE: {
        return false;
      }
      case NoGoodTerm::UNDECIDED: {
        if (first_undecided == NULL) {
          first_undecided = terms_[i];
        } else {
          // more than one undecided, we cannot deduce anything.
          return true;
        }
        break;
      }
    }
  }
  if (first_undecided == NULL && terms_.size() > 0) {
    solver->Fail();
  }
  if (first_undecided != NULL) {
    first_undecided->Refute();
    return false;
  }
  return false;
}

string NoGood::DebugString() const {
  return StringPrintf("(%s)", DebugStringVector(terms_, " && ").c_str());
}

namespace {
// ----- NoGoodManager -----

// This implementation is very naive. It will be kept in the future as
// a reference point.

class NaiveNoGoodManager : public NoGoodManager {
 public:
  explicit NaiveNoGoodManager(Solver* const solver) : NoGoodManager(solver) {}
  virtual ~NaiveNoGoodManager() {
    Clear();
  }

  virtual void Clear() {
    STLDeleteElements(&nogoods_);
  }

  virtual void Init() {}

  virtual void AddNoGood(NoGood* const nogood) {
    nogoods_.push_back(nogood);
  }

  virtual int NoGoodCount() const {
    return nogoods_.size();
  }

  virtual void Apply() {
    Solver* const s = solver();
    for (int i = 0; i < nogoods_.size(); ++i) {
      nogoods_[i]->Apply(s);
    }
  }

  string DebugString() const {
    return StringPrintf("NaiveNoGoodManager(%d)", NoGoodCount());
  }

 private:
  std::vector<NoGood*> nogoods_;
};
}  // namespace

// ----- API -----

NoGoodManager* Solver::MakeNoGoodManager() {
  return RevAlloc(new NaiveNoGoodManager(this));
}

}  // namespace operations_research
<commit_msg>more logging on log based restart<commit_after>// Copyright 2010-2012 Google
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <string>
#include <vector>

#include "base/integral_types.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/stringprintf.h"
#include "base/stl_util.h"
#include "constraint_solver/constraint_solver.h"
#include "util/string_array.h"

namespace operations_research {

// ----- Base Class -----

void NoGoodManager::EnterSearch() {
  Init();
}

void NoGoodManager::BeginNextDecision(DecisionBuilder* const db) {
  Apply();
}

bool NoGoodManager::AcceptSolution() {
  Apply();
  return true;
}

NoGood* NoGoodManager::MakeNoGood() {
  return new NoGood();
}

// ----- Base class for NoGood terms -----

class NoGoodTerm {
 public:
  enum TermStatus {
    ALWAYS_TRUE,
    ALWAYS_FALSE,
    UNDECIDED
  };
  NoGoodTerm() {}
  virtual ~NoGoodTerm() {}

  virtual TermStatus Evaluate() const = 0;
  virtual void Refute() = 0;
  virtual string DebugString() const = 0;
 private:
  DISALLOW_COPY_AND_ASSIGN(NoGoodTerm);
};

namespace {
// ----- IntegerVariableNoGoodTerm -----

// IntVar == int64 specialization.
class IntegerVariableNoGoodTerm : public NoGoodTerm {
 public:
  IntegerVariableNoGoodTerm(IntVar* const var, int64 value, bool assign)
      : integer_variable_(var), value_(value), assign_(assign) {
    CHECK_NOTNULL(integer_variable_);
  }

  virtual TermStatus Evaluate() const {
    if (!integer_variable_->Contains(value_)) {
      return assign_ ? ALWAYS_FALSE : ALWAYS_TRUE;
    } else if (integer_variable_->Bound()) {
      return assign_ ? ALWAYS_TRUE : ALWAYS_FALSE;
    } else {
      return UNDECIDED;
    }
  }

  virtual void Refute() {
    if (assign_) {
      integer_variable_->RemoveValue(value_);
    } else {
      integer_variable_->SetValue(value_);
    }
  }

  virtual string DebugString() const {
    return StringPrintf("(var_%s %s %lld)",
                        integer_variable_->name().c_str(),
                        assign_ ? "==" : "!=",
                        value_);
  }

  IntVar* integer_variable() const { return integer_variable_; }
  int64 value() const { return value_; }
  bool assign() const { return assign_; }

 private:
  IntVar* const integer_variable_;
  const int64 value_;
  const bool assign_;
  DISALLOW_COPY_AND_ASSIGN(IntegerVariableNoGoodTerm);
};
}  // namespace

// ----- NoGood -----

NoGood::~NoGood() {
  STLDeleteElements(&terms_);
}

void NoGood::AddIntegerVariableEqualValueTerm(IntVar* const var, int64 value) {
  terms_.push_back(new IntegerVariableNoGoodTerm(var, value, true));
}

void NoGood::AddIntegerVariableNotEqualValueTerm(IntVar* const var,
                                                 int64 value) {
  terms_.push_back(new IntegerVariableNoGoodTerm(var, value, false));
}

bool NoGood::Apply(Solver* const solver) {
  NoGoodTerm* first_undecided = NULL;
  for (int i = 0; i < terms_.size(); ++i) {
    switch (terms_[i]->Evaluate()) {
      case NoGoodTerm::ALWAYS_TRUE: {
        break;
      }
      case NoGoodTerm::ALWAYS_FALSE: {
        return false;
      }
      case NoGoodTerm::UNDECIDED: {
        if (first_undecided == NULL) {
          first_undecided = terms_[i];
        } else {
          // more than one undecided, we cannot deduce anything.
          return true;
        }
        break;
      }
    }
  }
  if (first_undecided == NULL && terms_.size() > 0) {
    VLOG(1) << "No Good " << DebugString() << " -> Fail";
    solver->Fail();
  }
  if (first_undecided != NULL) {
    VLOG(1) << "No Good " << DebugString() << " -> Refute "
            << first_undecided->DebugString();;
    first_undecided->Refute();
    return false;
  }
  return false;
}

string NoGood::DebugString() const {
  return StringPrintf("(%s)", DebugStringVector(terms_, " && ").c_str());
}

namespace {
// ----- NoGoodManager -----

// This implementation is very naive. It will be kept in the future as
// a reference point.

class NaiveNoGoodManager : public NoGoodManager {
 public:
  explicit NaiveNoGoodManager(Solver* const solver) : NoGoodManager(solver) {}
  virtual ~NaiveNoGoodManager() {
    Clear();
  }

  virtual void Clear() {
    STLDeleteElements(&nogoods_);
  }

  virtual void Init() {}

  virtual void AddNoGood(NoGood* const nogood) {
    nogoods_.push_back(nogood);
  }

  virtual int NoGoodCount() const {
    return nogoods_.size();
  }

  virtual void Apply() {
    Solver* const s = solver();
    for (int i = 0; i < nogoods_.size(); ++i) {
      nogoods_[i]->Apply(s);
    }
  }

  string DebugString() const {
    return StringPrintf("NaiveNoGoodManager(%d)", NoGoodCount());
  }

 private:
  std::vector<NoGood*> nogoods_;
};
}  // namespace

// ----- API -----

NoGoodManager* Solver::MakeNoGoodManager() {
  return RevAlloc(new NaiveNoGoodManager(this));
}

}  // namespace operations_research
<|endoftext|>


<commit_before>#include "application.hpp"
#include "log.hpp"
#include "argumentsystem.hpp"
#include <algorithm>

#include FILESYSTEM_HEADER
namespace fs = FILESYSTEM_NAMESPACE;

namespace OpenBFME {

Application::Application(int argc, const char *argv[]) : fullArguments(argv + 1, argv + argc),
    startTime(std::chrono::duration_cast<TimePoint>(Clock::now().time_since_epoch())) {
    if(app == nullptr){
        app = this;

        executablePath = fs::canonical(fs::path(argv[0])).string();
    }else{
        /* TODO - This may be cause for aborting. Just remember not to create an instance of this class anywhere but in main. */
        Log::error("A second instance of Application class was created!");
    }
}

Application::~Application(){
    /* Close log file and reset the static pointer when Application instance is destroyed. */
    if(app == this){
        Log::info("Shutting down.");

        for(Log::Output output : logOutputs)
            if(output.fp != stdout && output.fp != stderr)
                fclose(output.fp);

        logOutputs.clear();

        app = nullptr;
    }
}

void Application::initLog(const string &filename, bool verbose, bool silent){
#ifndef NDEBUG
    /* Debug output is always on in debug builds. */
    verbose = true;
#endif

    logOutputs.push_back(Log::Output(Log::Error, stderr));

    if(!silent){
        logOutputs.push_back(Log::Output(Log::OutputLevel(Log::Info | Log::Warning | (verbose ? Log::Debug : 0)), stdout));
    }

    FILE* file = fopen(filename.c_str(), "w");
    if(file != nullptr){
        logOutputs.push_back(Log::Output(silent ? Log::Error : Log::OutputLevel(Log::All & (verbose ? ~0 : ~Log::Debug)), file));
    }
}

void Application::parseArguments(){
    auto verbose =  registerBoolArgument({"verbose","v"},   "Write all messages to the log.");
    auto silent =   registerBoolArgument({"silent","s"},    "Only write \"ERROR\" level messages to the log.");
    auto help =     registerBoolArgument({"help","h"},      "Show this help message and quit.");

    for(auto i = fullArguments.begin(); i != fullArguments.end(); ++i){
        const string& arg = *i;

        /* Any argument that starts with a '-' is handled by the parser. */
        if(arg.size() > 1 && arg[0] == '-'){
            /* It doesn't matter whether one or two dashes start the argument. */
            string::size_type start = (arg[1] == '-') ? 2 : 1;
            string::size_type equals = arg.find('=');

            string name = arg.substr(start, equals - start);

            auto iter = std::find_if(parsedArguments.begin(), parsedArguments.end(), [&](std::shared_ptr<StringArgument> def){
                return def->containsName(name);
            });
            if(iter != parsedArguments.end()){
                auto& def = *iter;
                if(equals != string::npos)
                    def->result = arg.substr(equals + 1);
                else if(def->expectsValue && (i+1) != fullArguments.end() && (i+1)->front() != '-')
                    def->result = *++i;
                else
                    def->result.clear();

                def->parse(name);
            }
        }else{
            remainingArguments.push_back(arg);
        }
    }

    if(help->valid && help->boolResult){
        /* Help messages are console only, with no timestamp.
         * TODO - make a way to customize this message. */
        puts(format("Usage: %s [OPTIONS]\n\nOptions:", executablePath.substr(executablePath.find_last_of("/\\") + 1)).c_str());

        for(auto argdef : parsedArguments){
            argdef->printHelp();
        }

        /* TODO - Make a normal way to do this. */
        exit(EXIT_SUCCESS);
    }

    /* The log is stored in "logs/<executable name>.log". */
    fs::path logDir = executablePath;
    fs::path logName = logDir.replace_extension(string(".log")).filename();
    logDir = logDir.parent_path() / fs::path("logs");

    if(!fs::exists(logDir))
        fs::create_directories(logDir);

    initLog((logDir / logName).string(), verbose->valid ? verbose->boolResult : false, silent->valid ? silent->boolResult : false);

    Log::info("Starting \"%s\"", executablePath);

    for(auto& argDef : parsedArguments){
        if(argDef->errorMessage.size() != 0)
            /* TODO - Does this warrant quiting? Probably... */
            Log::error(argDef->errorMessage);
    }
}

std::shared_ptr<const BoolArgument> Application::registerBoolArgument(const std::initializer_list<string>& names, const string& desc) {
    std::shared_ptr<BoolArgument> pointer(new BoolArgument(names, desc));
    parsedArguments.emplace_back(pointer);

    return pointer;
}

std::shared_ptr<const IntegerArgument> Application::registerIntegerArgument(const std::initializer_list<string>& names, const string& desc) {
    std::shared_ptr<IntegerArgument> pointer(new IntegerArgument(names, desc));
    parsedArguments.emplace_back(pointer);

    return pointer;
}

std::shared_ptr<const DecimalArgument> Application::registerDecimalArgument(const std::initializer_list<string>& names, const string& desc) {
    std::shared_ptr<DecimalArgument> pointer(new DecimalArgument(names, desc));
    parsedArguments.emplace_back(pointer);

    return pointer;
}

std::shared_ptr<const StringArgument> Application::registerStringArgument(const std::initializer_list<string>& names, const string& desc) {
    std::shared_ptr<StringArgument> pointer(new StringArgument(names, desc));
    parsedArguments.emplace_back(pointer);

    return pointer;
}

Application* Application::app = nullptr;

}
<commit_msg>Don't ignore verbose in debug builds.<commit_after>#include "application.hpp"
#include "log.hpp"
#include "argumentsystem.hpp"
#include <algorithm>

#include FILESYSTEM_HEADER
namespace fs = FILESYSTEM_NAMESPACE;

namespace OpenBFME {

Application::Application(int argc, const char *argv[]) : fullArguments(argv + 1, argv + argc),
    startTime(std::chrono::duration_cast<TimePoint>(Clock::now().time_since_epoch())) {
    if(app == nullptr){
        app = this;

        executablePath = fs::canonical(fs::path(argv[0])).string();
    }else{
        /* TODO - This may be cause for aborting. Just remember not to create an instance of this class anywhere but in main. */
        Log::error("A second instance of Application class was created!");
    }
}

Application::~Application(){
    /* Close log file and reset the static pointer when Application instance is destroyed. */
    if(app == this){
        Log::info("Shutting down.");

        for(Log::Output output : logOutputs)
            if(output.fp != stdout && output.fp != stderr)
                fclose(output.fp);

        logOutputs.clear();

        app = nullptr;
    }
}

void Application::initLog(const string &filename, bool verbose, bool silent){
    logOutputs.push_back(Log::Output(Log::Error, stderr));

    if(!silent){
        logOutputs.push_back(Log::Output(Log::OutputLevel(Log::Info | Log::Warning | (verbose ? Log::Debug : 0)), stdout));
    }

    FILE* file = fopen(filename.c_str(), "w");
    if(file != nullptr){
        logOutputs.push_back(Log::Output(silent ? Log::Error : Log::OutputLevel(Log::All & (verbose ? ~0 : ~Log::Debug)), file));
    }
}

void Application::parseArguments(){
    auto verbose =  registerBoolArgument({"verbose","v"},   "Write all messages to the log.");
    auto silent =   registerBoolArgument({"silent","s"},    "Only write \"ERROR\" level messages to the log.");
    auto help =     registerBoolArgument({"help","h"},      "Show this help message and quit.");

    for(auto i = fullArguments.begin(); i != fullArguments.end(); ++i){
        const string& arg = *i;

        /* Any argument that starts with a '-' is handled by the parser. */
        if(arg.size() > 1 && arg[0] == '-'){
            /* It doesn't matter whether one or two dashes start the argument. */
            string::size_type start = (arg[1] == '-') ? 2 : 1;
            string::size_type equals = arg.find('=');

            string name = arg.substr(start, equals - start);

            auto iter = std::find_if(parsedArguments.begin(), parsedArguments.end(), [&](std::shared_ptr<StringArgument> def){
                return def->containsName(name);
            });
            if(iter != parsedArguments.end()){
                auto& def = *iter;
                if(equals != string::npos)
                    def->result = arg.substr(equals + 1);
                else if(def->expectsValue && (i+1) != fullArguments.end() && (i+1)->front() != '-')
                    def->result = *++i;
                else
                    def->result.clear();

                def->parse(name);
            }
        }else{
            remainingArguments.push_back(arg);
        }
    }

    if(help->valid && help->boolResult){
        /* Help messages are console only, with no timestamp.
         * TODO - make a way to customize this message. */
        puts(format("Usage: %s [OPTIONS]\n\nOptions:", executablePath.substr(executablePath.find_last_of("/\\") + 1)).c_str());

        for(auto argdef : parsedArguments){
            argdef->printHelp();
        }

        /* TODO - Make a normal way to do this. */
        exit(EXIT_SUCCESS);
    }

    /* The log is stored in "logs/<executable name>.log". */
    fs::path logDir = executablePath;
    fs::path logName = logDir.replace_extension(string(".log")).filename();
    logDir = logDir.parent_path() / fs::path("logs");

    if(!fs::exists(logDir))
        fs::create_directories(logDir);

     /* Debug output is on by default in debug builds. */
#ifndef NDEBUG
    #define VERBOSE_DEFAULT true
#else
    #define VERBOSE_DEFAULT false
#endif

    initLog((logDir / logName).string(), verbose->valid ? verbose->boolResult : VERBOSE_DEFAULT, silent->valid ? silent->boolResult : false);

    Log::info("Starting \"%s\"", executablePath);

    for(auto& argDef : parsedArguments){
        if(argDef->errorMessage.size() != 0)
            /* TODO - Does this warrant quiting? Probably... */
            Log::error(argDef->errorMessage);
    }
}

std::shared_ptr<const BoolArgument> Application::registerBoolArgument(const std::initializer_list<string>& names, const string& desc) {
    std::shared_ptr<BoolArgument> pointer(new BoolArgument(names, desc));
    parsedArguments.emplace_back(pointer);

    return pointer;
}

std::shared_ptr<const IntegerArgument> Application::registerIntegerArgument(const std::initializer_list<string>& names, const string& desc) {
    std::shared_ptr<IntegerArgument> pointer(new IntegerArgument(names, desc));
    parsedArguments.emplace_back(pointer);

    return pointer;
}

std::shared_ptr<const DecimalArgument> Application::registerDecimalArgument(const std::initializer_list<string>& names, const string& desc) {
    std::shared_ptr<DecimalArgument> pointer(new DecimalArgument(names, desc));
    parsedArguments.emplace_back(pointer);

    return pointer;
}

std::shared_ptr<const StringArgument> Application::registerStringArgument(const std::initializer_list<string>& names, const string& desc) {
    std::shared_ptr<StringArgument> pointer(new StringArgument(names, desc));
    parsedArguments.emplace_back(pointer);

    return pointer;
}

Application* Application::app = nullptr;

}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 Shanghai Jiao Tong University.
 *     All rights reserved.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an "AS
 *  IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 *  express or implied.  See the License for the specific language
 *  governing permissions and limitations under the License.
 *
 * For more about this software visit:
 *
 *      http://ipads.se.sjtu.edu.cn/projects/wukong
 *
 */

#pragma once

#ifdef USE_JEMALLOC

#include "mm/malloc_interface.hpp"
#include <jemalloc/jemalloc.h>

class JeMalloc : public MAInterface {
private:
    vector<unsigned> arena_inds;
    vector<unsigned> tcache_inds;
    uint64_t memsize;
    extent_hooks_t *new_hooks;

public:
    static char *start_ptr;
    static char *end_ptr;
    static char *top_of_heap;
    static pthread_spinlock_t jelock;

    // custom extent hooks which comprises function pointers
    extent_hooks_t hooks = {
        JeMalloc::extent_alloc_hook,
        JeMalloc::extent_dalloc_hook,
        JeMalloc::extent_destroy_hook,
        JeMalloc::extent_commit_hook,
        JeMalloc::extent_decommit_hook,
        JeMalloc::extent_purge_lazy_hook,
        JeMalloc::extent_purge_forced_hook,
        JeMalloc::extent_split_hook,
        JeMalloc::extent_merge_hook
    };

    //hook functions which manage extent lifetime
    static void *extent_alloc_hook(extent_hooks_t *extent_hooks, void *new_addr, size_t size,
                                   size_t alignment, bool *zero, bool *commit, unsigned arena_ind) {
        logstream(LOG_DEBUG) << __func__ << "(extent_hooks = " << extent_hooks
                             << " , new_addr = " << new_addr << ", size = " << size
                             <<  " , alignment = " << alignment
                             << " , *zero = " << *zero << " , *commit = " << *commit
                             << " , arena_ind = " << arena_ind << ")" << LOG_endl;

        pthread_spin_lock(&jelock);
        char *ret = (char*)top_of_heap;
        //align the return address
        if ((uintptr_t)ret % alignment != 0) {
            ret = ret + (alignment - (uintptr_t)ret % alignment);
        }
        if ((char*)ret + size >= (char*)end_ptr) {
            logstream(LOG_ERROR) << "Out of memory, can not allocate any extent." << LOG_endl;
            ASSERT(false);
            pthread_spin_unlock(&jelock);
            return NULL;
        }
        top_of_heap = ret + size;
        pthread_spin_unlock(&jelock);
        if (*zero) //extent should be zeroed
            memset(ret, size, 0);

        if ((uintptr_t)ret % alignment != 0) {
            logstream(LOG_ERROR) << "Alignment error." << LOG_endl;
        }
        return ret;
    }

    static bool extent_dalloc_hook(extent_hooks_t *extent_hooks, void *addr, size_t size,
                                   bool committed, unsigned arena_ind) {
        logstream(LOG_DEBUG) << __func__ << "(extent_hooks = " << extent_hooks
                             << " , addr = " << addr << ", size = " << size
                             <<  " , committed = " << committed
                             << " , arena_ind = " << arena_ind << ")" << LOG_endl;

        // opt out from dalloc
        return true;
    }

    static void extent_destroy_hook(extent_hooks_t *extent_hooks, void *addr, size_t size,
                                    bool committed, unsigned arena_ind) {
        logstream(LOG_DEBUG) << __func__ << "(extent_hooks = " << extent_hooks
                             << " , addr = " << addr << ", size = " << size
                             <<  " , committed = " << committed
                             << " , arena_ind = " << arena_ind << ")" << LOG_endl;

        return;
    }

    static bool extent_commit_hook(extent_hooks_t *extent_hooks, void *addr, size_t size,
                                   size_t offset, size_t length, unsigned arena_ind) {
        logstream(LOG_DEBUG) << __func__ << "(extent_hooks = " << extent_hooks
                             << " , addr = " << addr << ", size = " << size
                             <<  " , offset = " << offset << " , length = " << length
                             << " , arena_ind = " << arena_ind << ")" << LOG_endl;

        // commit should always succeed
        return false;
    }

    static bool extent_decommit_hook(extent_hooks_t *extent_hooks, void *addr, size_t size,
                                     size_t offset, size_t length, unsigned arena_ind) {
        logstream(LOG_DEBUG) << __func__ << "(extent_hooks = " << extent_hooks
                             << " , addr = " << addr << ", size = " << size
                             <<  " , offset = " << offset << " , length = " << length
                             << " , arena_ind = " << arena_ind << ")" << LOG_endl;

        // decommit should always succeed
        return false;
    }

    static bool extent_purge_lazy_hook(extent_hooks_t *extent_hooks, void *addr, size_t size,
                                       size_t offset, size_t length, unsigned arena_ind) {
        logstream(LOG_DEBUG) << __func__ << "(extent_hooks = " << extent_hooks
                             << " , addr = " << addr << ", size = " << size
                             <<  " , offset = " << offset << " , length = " << length
                             << " , arena_ind = " << arena_ind << ")" << LOG_endl;

        // opt out
        return true;
    }

    static bool extent_purge_forced_hook(extent_hooks_t *extent_hooks, void *addr, size_t size,
                                         size_t offset, size_t length, unsigned arena_ind) {
        logstream(LOG_DEBUG) << __func__ << "(extent_hooks = " << extent_hooks
                             << " , addr = " << addr << ", size = " << size
                             <<  " , offset = " << offset << " , length = " << length
                             << " , arena_ind = " << arena_ind << ")" << LOG_endl;

        // opt out
        return true;
    }

    static bool extent_split_hook(extent_hooks_t *extent_hooks, void *addr, size_t size,
                                  size_t size_a, size_t size_b, bool committed, unsigned arena_ind) {
        logstream(LOG_DEBUG) << __func__ << "(extent_hooks = " << extent_hooks
                             << " , addr = " << addr << ", size = " << size
                             <<  " , size_a = " << size_a << " , size_b = " << size_b
                             << " , committed = " << committed << " , arena_ind = " << arena_ind << ")" << LOG_endl;

        // split should always succeed
        return false;
    }

    static bool extent_merge_hook(extent_hooks_t *extent_hooks, void *addr_a, size_t size_a,
                                  void *addr_b, size_t size_b, bool committed, unsigned arena_ind) {
        logstream(LOG_DEBUG) << __func__ << "(extent_hooks = " << extent_hooks
                             << " , addr_a = " << addr_a << ", size_a = " << size_a
                             <<  " , addr_b = " << addr_b << " , size_b = " << size_b
                             << " , committed = " << committed << " , arena_ind = " << arena_ind << ")" << LOG_endl;

        // merge should always succeed
        return false;
    }

    void init(void *start, uint64_t size, uint64_t n) {
        start_ptr = top_of_heap = (char*)start;
        memsize = size;
        end_ptr = start_ptr + memsize;
        pthread_spin_init(&jelock, 0);
        size_t hooks_len = sizeof(extent_hooks_t *);
        size_t  sz = sizeof(unsigned);
        arena_inds.resize(n);
        tcache_inds.resize(n);
        new_hooks = &hooks;
        //create new arena for each engine and install custom extent hooks on it
        for (int i = 0; i < n; i++)
            mallctl("arenas.create", (void *)&arena_inds[i], &sz,
                    (void *)&new_hooks, sizeof(extent_hooks_t *));

        //create thread-specific cache for each engine
        for (int i = 0; i < n; i++)
            mallctl("tcache.create", (void *)&tcache_inds[i], &sz, NULL, 0);
    }

    uint64_t malloc(uint64_t size, int64_t tid) {
        // malloc from engine's own arena and tcache
        void *ptr = mallocx(size, MALLOCX_ARENA(arena_inds[tid]) | MALLOCX_TCACHE(tcache_inds[tid]));
        if ((char*)ptr < start_ptr || (char*)ptr + size > end_ptr) {
            logstream(LOG_ERROR) << "memory range false" << LOG_endl;
            ASSERT(false);
        }
        uint64_t ret = (uint64_t)((char*)ptr - start_ptr);
        return ret;
    }

    void free(uint64_t idx) {
        void* ptr = (void*)(start_ptr + idx);
        //make the memory be available for future allocations
        dallocx(ptr, 0);
        return;
    }

    uint64_t sz_to_blksz(uint64_t size) {
        // get the real size of the allocation at ptr.
        return (uint64_t)nallocx(size, 0);
    }

    //to be suited with buddy malloc
    void merge_freelists() { return; }

    void print_memory_usage() {
        uint64_t allocated_size = ((char*)top_of_heap - (char*)start_ptr) / (1024 * 1024);

        logstream(LOG_INFO) << "graph_storage edge memory status:" << LOG_endl;
        logstream(LOG_INFO) << "allocated " << allocated_size << " MB" << LOG_endl;
        return;
    }
};

// needed to provide a definition for static member variables
char* JeMalloc::start_ptr = NULL;
char* JeMalloc::end_ptr = NULL;
char* JeMalloc::top_of_heap = NULL;
pthread_spinlock_t JeMalloc::jelock;

#endif
<commit_msg>remove wrong comment<commit_after>/*
 * Copyright (c) 2016 Shanghai Jiao Tong University.
 *     All rights reserved.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an "AS
 *  IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 *  express or implied.  See the License for the specific language
 *  governing permissions and limitations under the License.
 *
 * For more about this software visit:
 *
 *      http://ipads.se.sjtu.edu.cn/projects/wukong
 *
 */

#pragma once

#ifdef USE_JEMALLOC

#include "mm/malloc_interface.hpp"
#include <jemalloc/jemalloc.h>

class JeMalloc : public MAInterface {
private:
    vector<unsigned> arena_inds;
    vector<unsigned> tcache_inds;
    uint64_t memsize;
    extent_hooks_t *new_hooks;

public:
    static char *start_ptr;
    static char *end_ptr;
    static char *top_of_heap;
    static pthread_spinlock_t jelock;

    // custom extent hooks which comprises function pointers
    extent_hooks_t hooks = {
        JeMalloc::extent_alloc_hook,
        JeMalloc::extent_dalloc_hook,
        JeMalloc::extent_destroy_hook,
        JeMalloc::extent_commit_hook,
        JeMalloc::extent_decommit_hook,
        JeMalloc::extent_purge_lazy_hook,
        JeMalloc::extent_purge_forced_hook,
        JeMalloc::extent_split_hook,
        JeMalloc::extent_merge_hook
    };

    //hook functions which manage extent lifetime
    static void *extent_alloc_hook(extent_hooks_t *extent_hooks, void *new_addr, size_t size,
                                   size_t alignment, bool *zero, bool *commit, unsigned arena_ind) {
        logstream(LOG_DEBUG) << __func__ << "(extent_hooks = " << extent_hooks
                             << " , new_addr = " << new_addr << ", size = " << size
                             <<  " , alignment = " << alignment
                             << " , *zero = " << *zero << " , *commit = " << *commit
                             << " , arena_ind = " << arena_ind << ")" << LOG_endl;

        pthread_spin_lock(&jelock);
        char *ret = (char*)top_of_heap;
        //align the return address
        if ((uintptr_t)ret % alignment != 0) {
            ret = ret + (alignment - (uintptr_t)ret % alignment);
        }
        if ((char*)ret + size >= (char*)end_ptr) {
            logstream(LOG_ERROR) << "Out of memory, can not allocate any extent." << LOG_endl;
            ASSERT(false);
            pthread_spin_unlock(&jelock);
            return NULL;
        }
        top_of_heap = ret + size;
        pthread_spin_unlock(&jelock);
        if (*zero) //extent should be zeroed
            memset(ret, size, 0);

        if ((uintptr_t)ret % alignment != 0) {
            logstream(LOG_ERROR) << "Alignment error." << LOG_endl;
        }
        return ret;
    }

    static bool extent_dalloc_hook(extent_hooks_t *extent_hooks, void *addr, size_t size,
                                   bool committed, unsigned arena_ind) {
        logstream(LOG_DEBUG) << __func__ << "(extent_hooks = " << extent_hooks
                             << " , addr = " << addr << ", size = " << size
                             <<  " , committed = " << committed
                             << " , arena_ind = " << arena_ind << ")" << LOG_endl;

        // opt out from dalloc
        return true;
    }

    static void extent_destroy_hook(extent_hooks_t *extent_hooks, void *addr, size_t size,
                                    bool committed, unsigned arena_ind) {
        logstream(LOG_DEBUG) << __func__ << "(extent_hooks = " << extent_hooks
                             << " , addr = " << addr << ", size = " << size
                             <<  " , committed = " << committed
                             << " , arena_ind = " << arena_ind << ")" << LOG_endl;

        return;
    }

    static bool extent_commit_hook(extent_hooks_t *extent_hooks, void *addr, size_t size,
                                   size_t offset, size_t length, unsigned arena_ind) {
        logstream(LOG_DEBUG) << __func__ << "(extent_hooks = " << extent_hooks
                             << " , addr = " << addr << ", size = " << size
                             <<  " , offset = " << offset << " , length = " << length
                             << " , arena_ind = " << arena_ind << ")" << LOG_endl;

        // commit should always succeed
        return false;
    }

    static bool extent_decommit_hook(extent_hooks_t *extent_hooks, void *addr, size_t size,
                                     size_t offset, size_t length, unsigned arena_ind) {
        logstream(LOG_DEBUG) << __func__ << "(extent_hooks = " << extent_hooks
                             << " , addr = " << addr << ", size = " << size
                             <<  " , offset = " << offset << " , length = " << length
                             << " , arena_ind = " << arena_ind << ")" << LOG_endl;

        // decommit should always succeed
        return false;
    }

    static bool extent_purge_lazy_hook(extent_hooks_t *extent_hooks, void *addr, size_t size,
                                       size_t offset, size_t length, unsigned arena_ind) {
        logstream(LOG_DEBUG) << __func__ << "(extent_hooks = " << extent_hooks
                             << " , addr = " << addr << ", size = " << size
                             <<  " , offset = " << offset << " , length = " << length
                             << " , arena_ind = " << arena_ind << ")" << LOG_endl;

        // opt out
        return true;
    }

    static bool extent_purge_forced_hook(extent_hooks_t *extent_hooks, void *addr, size_t size,
                                         size_t offset, size_t length, unsigned arena_ind) {
        logstream(LOG_DEBUG) << __func__ << "(extent_hooks = " << extent_hooks
                             << " , addr = " << addr << ", size = " << size
                             <<  " , offset = " << offset << " , length = " << length
                             << " , arena_ind = " << arena_ind << ")" << LOG_endl;

        // opt out
        return true;
    }

    static bool extent_split_hook(extent_hooks_t *extent_hooks, void *addr, size_t size,
                                  size_t size_a, size_t size_b, bool committed, unsigned arena_ind) {
        logstream(LOG_DEBUG) << __func__ << "(extent_hooks = " << extent_hooks
                             << " , addr = " << addr << ", size = " << size
                             <<  " , size_a = " << size_a << " , size_b = " << size_b
                             << " , committed = " << committed << " , arena_ind = " << arena_ind << ")" << LOG_endl;

        // split should always succeed
        return false;
    }

    static bool extent_merge_hook(extent_hooks_t *extent_hooks, void *addr_a, size_t size_a,
                                  void *addr_b, size_t size_b, bool committed, unsigned arena_ind) {
        logstream(LOG_DEBUG) << __func__ << "(extent_hooks = " << extent_hooks
                             << " , addr_a = " << addr_a << ", size_a = " << size_a
                             <<  " , addr_b = " << addr_b << " , size_b = " << size_b
                             << " , committed = " << committed << " , arena_ind = " << arena_ind << ")" << LOG_endl;

        // merge should always succeed
        return false;
    }

    void init(void *start, uint64_t size, uint64_t n) {
        start_ptr = top_of_heap = (char*)start;
        memsize = size;
        end_ptr = start_ptr + memsize;
        pthread_spin_init(&jelock, 0);
        size_t hooks_len = sizeof(extent_hooks_t *);
        size_t  sz = sizeof(unsigned);
        arena_inds.resize(n);
        tcache_inds.resize(n);
        new_hooks = &hooks;
        //create new arena for each engine and install custom extent hooks on it
        for (int i = 0; i < n; i++)
            mallctl("arenas.create", (void *)&arena_inds[i], &sz,
                    (void *)&new_hooks, sizeof(extent_hooks_t *));

        //create thread-specific cache for each engine
        for (int i = 0; i < n; i++)
            mallctl("tcache.create", (void *)&tcache_inds[i], &sz, NULL, 0);
    }

    uint64_t malloc(uint64_t size, int64_t tid) {
        // malloc from engine's own arena and tcache
        void *ptr = mallocx(size, MALLOCX_ARENA(arena_inds[tid]) | MALLOCX_TCACHE(tcache_inds[tid]));
        if ((char*)ptr < start_ptr || (char*)ptr + size > end_ptr) {
            logstream(LOG_ERROR) << "memory range false" << LOG_endl;
            ASSERT(false);
        }
        uint64_t ret = (uint64_t)((char*)ptr - start_ptr);
        return ret;
    }

    void free(uint64_t idx) {
        void* ptr = (void*)(start_ptr + idx);
        //make the memory be available for future allocations
        dallocx(ptr, 0);
        return;
    }

    uint64_t sz_to_blksz(uint64_t size) {
        return (uint64_t)nallocx(size, 0);
    }

    //to be suited with buddy malloc
    void merge_freelists() { return; }

    void print_memory_usage() {
        uint64_t allocated_size = ((char*)top_of_heap - (char*)start_ptr) / (1024 * 1024);

        logstream(LOG_INFO) << "graph_storage edge memory status:" << LOG_endl;
        logstream(LOG_INFO) << "allocated " << allocated_size << " MB" << LOG_endl;
        return;
    }
};

// needed to provide a definition for static member variables
char* JeMalloc::start_ptr = NULL;
char* JeMalloc::end_ptr = NULL;
char* JeMalloc::top_of_heap = NULL;
pthread_spinlock_t JeMalloc::jelock;

#endif
<|endoftext|>


<commit_before>#include "tangram.h"

#include <memory>
#include <utility>
#include <cmath>
#include <set>

#include "platform.h"
#include "tile/tileManager.h"
#include "view/view.h"
#include "data/geoJsonSource.h"
#include "data/protobufSource.h"

#include "style/polygonStyle.h"
#include "style/polylineStyle.h"
#include "style/fontStyle.h"
#include "style/debugStyle.h"
#include "scene/scene.h"
#include "scene/lights.h"
#include "util/error.h"
#include "stl_util.hpp"

namespace Tangram {

    std::unique_ptr<TileManager> m_tileManager;
    std::shared_ptr<Scene> m_scene;
    std::shared_ptr<View> m_view;
    std::shared_ptr<LabelContainer> m_labelContainer;
    std::shared_ptr<FontContext> m_ftContext;
    std::shared_ptr<DebugStyle> m_debugStyle;

    static float g_time = 0.0;
    static unsigned long g_flags = 0;

    void initialize() {

        logMsg("initialize\n");

        // Create view
        if (!m_view) {
            m_view = std::make_shared<View>();

            // Move the view to coordinates in Manhattan so we have something interesting to test
            glm::dvec2 target = m_view->getMapProjection().LonLatToMeters(glm::dvec2(-74.00796, 40.70361));
            m_view->setPosition(target.x, target.y);
        }

        // Create a scene object
        if (!m_scene) {
            m_scene = std::make_shared<Scene>();

            // Load style(s); hard-coded for now
            std::unique_ptr<Style> polyStyle(new PolygonStyle("Polygon"));
            polyStyle->addLayers({
                "buildings",
                "water",
                "earth",
                "landuse"
            });
            m_scene->addStyle(std::move(polyStyle));

            std::unique_ptr<Style> linesStyle(new PolylineStyle("Polyline"));
            linesStyle->addLayers({"roads"});
            m_scene->addStyle(std::move(linesStyle));

            m_ftContext = std::make_shared<FontContext>();
            m_ftContext->addFont("Roboto-Regular.ttf", "Roboto-Regular");
            m_labelContainer = LabelContainer::GetInstance();
            m_labelContainer->setFontContext(m_ftContext);

            std::unique_ptr<Style> fontStyle(new FontStyle("Roboto-Regular", "FontStyle", 14.0f, true));
            fontStyle->addLayers({"roads"});
            m_scene->addStyle(std::move(fontStyle));

            std::unique_ptr<DebugStyle> debugStyle(new DebugStyle("Debug"));
            m_scene->addStyle(std::move(debugStyle));

            //  Directional light with white diffuse color pointing Northeast and down
            auto directionalLight = std::make_shared<DirectionalLight>("dLight");
            directionalLight->setAmbientColor({0.3, 0.3, 0.3, 1.0});
            directionalLight->setDiffuseColor({0.7, 0.7, 0.7, 1.0});
            directionalLight->setDirection({1.0, 1.0, -1.0});
            m_scene->addLight(directionalLight);
        }

        // Create a tileManager
        if (!m_tileManager) {
            m_tileManager = TileManager::GetInstance();

            // Pass references to the view and scene into the tile manager
            m_tileManager->setView(m_view);
            m_tileManager->setScene(m_scene);

            // Add a tile data source
            // json tile source
            // std::unique_ptr<DataSource> dataSource(new GeoJsonTile());
            // protobuf tile source
            std::unique_ptr<DataSource> dataSource(new ProtobufSource());
            m_tileManager->addDataSource(std::move(dataSource));
        }

        // Set up openGL state
        glDisable(GL_BLEND);
        glDisable(GL_STENCIL_TEST);
        glEnable(GL_DEPTH_TEST);
        glClearDepthf(1.0);
        glDepthRangef(0.0, 1.0);
        glDepthMask(GL_TRUE);
        glDepthFunc(GL_LEQUAL);
        glEnable(GL_CULL_FACE);
        glFrontFace(GL_CCW);
        glCullFace(GL_BACK);
        glClearColor(0.3f, 0.3f, 0.3f, 1.0f);

        while (Error::hadGlError("Tangram::initialize()")) {}

        logMsg("finish initialize\n");

    }

    void resize(int _newWidth, int _newHeight) {

        logMsg("resize: %d x %d\n", _newWidth, _newHeight);

        glViewport(0, 0, _newWidth, _newHeight);

        if (m_view) {
            m_view->setSize(_newWidth, _newHeight);
        }

        if (m_ftContext) {
            m_ftContext->setScreenSize(m_view->getWidth(), m_view->getHeight());
        }

        while (Error::hadGlError("Tangram::resize()")) {}

    }

    void update(float _dt) {

        g_time += _dt;

        if (m_view) {
            m_view->update();

            m_tileManager->updateTileSet();

            if (m_view->changedOnLastUpdate()) {

                for (const auto& style : m_scene->getStyles()) {

                    for (const auto& mapIDandTile : m_tileManager->getVisibleTiles()) {
                        const std::shared_ptr<MapTile>& tile = mapIDandTile.second;
                        tile->update(_dt, *style, *m_view);
                    }
                }
            }
        }

        if(m_scene) {
            // Update lights and styles
        }
    }

    void render() {

        // Set up openGL for new frame
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Loop over all styles
        for (const auto& style : m_scene->getStyles()) {
            style->setupFrame(m_view, m_scene);

            // Loop over all tiles in m_tileSet
            for (const auto& mapIDandTile : m_tileManager->getVisibleTiles()) {
                const std::shared_ptr<MapTile>& tile = mapIDandTile.second;
                if (tile->hasGeometry()) {
                    // Draw tile!
                    style->setupTile(tile);
                    tile->draw(*style, *m_view);
                }
            }

            style->teardown();
        }

        while (Error::hadGlError("Tangram::render()")) {}

    }

    void setPixelScale(float _pixelsPerPoint) {

        if (m_view) {
            m_view->setPixelScale(_pixelsPerPoint);
        }

        for (auto& style : m_scene->getStyles()) {
            style->setPixelScale(_pixelsPerPoint);
        }

    }

    void handleTapGesture(float _posX, float _posY) {

        float viewCenterX = 0.5f * m_view->getWidth();
        float viewCenterY = 0.5f * m_view->getHeight();

        m_view->screenToGroundPlane(viewCenterX, viewCenterY);
        m_view->screenToGroundPlane(_posX, _posY);

        m_view->translate((_posX - viewCenterX), (_posY - viewCenterY));

    }

    void handleDoubleTapGesture(float _posX, float _posY) {

        m_view->zoom(1.0);
    }

    void handlePanGesture(float _startX, float _startY, float _endX, float _endY) {

        m_view->screenToGroundPlane(_startX, _startY);
        m_view->screenToGroundPlane(_endX, _endY);

        m_view->translate(_startX - _endX, _startY - _endY);

    }

    void handlePinchGesture(float _posX, float _posY, float _scale) {
        m_view->zoom(log2f(_scale));
    }

    void handleRotateGesture(float _posX, float _posY, float _radians) {

        m_view->screenToGroundPlane(_posX, _posY);
        m_view->orbit(_posX, _posY, _radians);

    }

    void handleShoveGesture(float _distance) {

        m_view->pitch(_distance);

    }

    void setDebugFlag(DebugFlags _flag, bool _on) {

        if (_on) {
            g_flags |= (1 << _flag); // |ing with a bitfield that is 0 everywhere except index _flag; sets index _flag to 1
        } else {
            g_flags &= ~(1 << _flag); // &ing with a bitfield that is 1 everywhere except index _flag; sets index _flag to 0
        }

        m_view->setZoom(m_view->getZoom()); // Force the view to refresh

    }

    bool getDebugFlag(DebugFlags _flag) {

        return (g_flags & (1 << _flag)) != 0; // &ing with a bitfield that is 0 everywhere except index _flag will yield 0 iff index _flag is 0

    }

    void teardown() {
        // Release resources!
        logMsg("teardown\n");
        m_tileManager.reset();
        m_scene.reset();
        m_view.reset();
    }

    void onContextDestroyed() {

        logMsg("context destroyed\n");

        // The OpenGL context has been destroyed since the last time resources were created,
        // so we invalidate all data that depends on OpenGL object handles.

        // ShaderPrograms are invalidated and immediately rebuilt
        ShaderProgram::invalidateAllPrograms();

        // Buffer objects are invalidated and re-uploaded the next time they are used
        VboMesh::invalidateAllVBOs();

    }

}
<commit_msg>Weird test configuration for LOD; revert later<commit_after>#include "tangram.h"

#include <memory>
#include <utility>
#include <cmath>
#include <set>

#include "platform.h"
#include "tile/tileManager.h"
#include "view/view.h"
#include "data/geoJsonSource.h"
#include "data/protobufSource.h"

#include "style/polygonStyle.h"
#include "style/polylineStyle.h"
#include "style/fontStyle.h"
#include "style/debugStyle.h"
#include "scene/scene.h"
#include "scene/lights.h"
#include "util/error.h"
#include "stl_util.hpp"

namespace Tangram {

    std::unique_ptr<TileManager> m_tileManager;
    std::shared_ptr<Scene> m_scene;
    std::shared_ptr<View> m_view;
    std::shared_ptr<LabelContainer> m_labelContainer;
    std::shared_ptr<FontContext> m_ftContext;
    std::shared_ptr<DebugStyle> m_debugStyle;

    static float g_time = 0.0;
    static unsigned long g_flags = 0;

    void initialize() {

        logMsg("initialize\n");

        // Create view
        if (!m_view) {
            m_view = std::make_shared<View>();

            // Move the view to coordinates in Manhattan so we have something interesting to test
            glm::dvec2 target = m_view->getMapProjection().LonLatToMeters(glm::dvec2(-1, -1));
            m_view->setPosition(target.x, target.y);
        }

        // Create a scene object
        if (!m_scene) {
            m_scene = std::make_shared<Scene>();

            // Load style(s); hard-coded for now
            std::unique_ptr<Style> polyStyle(new PolygonStyle("Polygon"));
            polyStyle->addLayers({
                "buildings",
                "water",
                "earth",
                "landuse"
            });
            m_scene->addStyle(std::move(polyStyle));

            std::unique_ptr<Style> linesStyle(new PolylineStyle("Polyline"));
            linesStyle->addLayers({"roads"});
            m_scene->addStyle(std::move(linesStyle));

            m_ftContext = std::make_shared<FontContext>();
            m_ftContext->addFont("Roboto-Regular.ttf", "Roboto-Regular");
            m_labelContainer = LabelContainer::GetInstance();
            m_labelContainer->setFontContext(m_ftContext);

            std::unique_ptr<Style> fontStyle(new FontStyle("Roboto-Regular", "FontStyle", 14.0f, true));
            fontStyle->addLayers({"roads"});
            m_scene->addStyle(std::move(fontStyle));

            std::unique_ptr<DebugStyle> debugStyle(new DebugStyle("Debug"));
            m_scene->addStyle(std::move(debugStyle));

            //  Directional light with white diffuse color pointing Northeast and down
            auto directionalLight = std::make_shared<DirectionalLight>("dLight");
            directionalLight->setAmbientColor({0.3, 0.3, 0.3, 1.0});
            directionalLight->setDiffuseColor({0.7, 0.7, 0.7, 1.0});
            directionalLight->setDirection({1.0, 1.0, -1.0});
            m_scene->addLight(directionalLight);
        }

        // Create a tileManager
        if (!m_tileManager) {
            m_tileManager = TileManager::GetInstance();

            // Pass references to the view and scene into the tile manager
            m_tileManager->setView(m_view);
            m_tileManager->setScene(m_scene);

            // Add a tile data source
            // json tile source
            // std::unique_ptr<DataSource> dataSource(new GeoJsonTile());
            // protobuf tile source
            std::unique_ptr<DataSource> dataSource(new ProtobufSource());
            m_tileManager->addDataSource(std::move(dataSource));
        }

        // Set up openGL state
        glDisable(GL_BLEND);
        glDisable(GL_STENCIL_TEST);
        glEnable(GL_DEPTH_TEST);
        glClearDepthf(1.0);
        glDepthRangef(0.0, 1.0);
        glDepthMask(GL_TRUE);
        glDepthFunc(GL_LEQUAL);
        glEnable(GL_CULL_FACE);
        glFrontFace(GL_CCW);
        glCullFace(GL_BACK);
        glClearColor(0.3f, 0.3f, 0.3f, 1.0f);

        while (Error::hadGlError("Tangram::initialize()")) {}

        logMsg("finish initialize\n");

        m_view->pitch(0.75);
        setDebugFlag(DebugFlags::TILE_BOUNDS, true);
        setDebugFlag(DebugFlags::PROXY_COLORS, true);

    }

    void resize(int _newWidth, int _newHeight) {

        logMsg("resize: %d x %d\n", _newWidth, _newHeight);

        glViewport(0, 0, _newWidth, _newHeight);

        if (m_view) {
            m_view->setSize(_newWidth, _newHeight);
        }

        if (m_ftContext) {
            m_ftContext->setScreenSize(m_view->getWidth(), m_view->getHeight());
        }

        while (Error::hadGlError("Tangram::resize()")) {}

    }

    void update(float _dt) {

        g_time += _dt;

        if (m_view) {
            m_view->update();

            m_tileManager->updateTileSet();

            if (m_view->changedOnLastUpdate()) {

                for (const auto& style : m_scene->getStyles()) {

                    for (const auto& mapIDandTile : m_tileManager->getVisibleTiles()) {
                        const std::shared_ptr<MapTile>& tile = mapIDandTile.second;
                        tile->update(_dt, *style, *m_view);
                    }
                }
            }
        }

        if(m_scene) {
            // Update lights and styles
        }
    }

    void render() {

        // Set up openGL for new frame
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Loop over all styles
        for (const auto& style : m_scene->getStyles()) {
            style->setupFrame(m_view, m_scene);

            // Loop over all tiles in m_tileSet
            for (const auto& mapIDandTile : m_tileManager->getVisibleTiles()) {
                const std::shared_ptr<MapTile>& tile = mapIDandTile.second;
                if (tile->hasGeometry()) {
                    // Draw tile!
                    style->setupTile(tile);
                    tile->draw(*style, *m_view);
                }
            }

            style->teardown();
        }

        while (Error::hadGlError("Tangram::render()")) {}

    }

    void setPixelScale(float _pixelsPerPoint) {

        if (m_view) {
            m_view->setPixelScale(_pixelsPerPoint);
        }

        for (auto& style : m_scene->getStyles()) {
            style->setPixelScale(_pixelsPerPoint);
        }

    }

    void handleTapGesture(float _posX, float _posY) {

        float viewCenterX = 0.5f * m_view->getWidth();
        float viewCenterY = 0.5f * m_view->getHeight();

        m_view->screenToGroundPlane(viewCenterX, viewCenterY);
        m_view->screenToGroundPlane(_posX, _posY);

        m_view->translate((_posX - viewCenterX), (_posY - viewCenterY));

    }

    void handleDoubleTapGesture(float _posX, float _posY) {

        m_view->zoom(1.0);
    }

    void handlePanGesture(float _startX, float _startY, float _endX, float _endY) {

        m_view->screenToGroundPlane(_startX, _startY);
        m_view->screenToGroundPlane(_endX, _endY);

        m_view->translate(_startX - _endX, _startY - _endY);

    }

    void handlePinchGesture(float _posX, float _posY, float _scale) {
        m_view->zoom(log2f(_scale));
    }

    void handleRotateGesture(float _posX, float _posY, float _radians) {

        m_view->screenToGroundPlane(_posX, _posY);
        m_view->orbit(_posX, _posY, _radians);

    }

    void handleShoveGesture(float _distance) {

        m_view->pitch(_distance);

    }

    void setDebugFlag(DebugFlags _flag, bool _on) {

        if (_on) {
            g_flags |= (1 << _flag); // |ing with a bitfield that is 0 everywhere except index _flag; sets index _flag to 1
        } else {
            g_flags &= ~(1 << _flag); // &ing with a bitfield that is 1 everywhere except index _flag; sets index _flag to 0
        }

        m_view->setZoom(m_view->getZoom()); // Force the view to refresh

    }

    bool getDebugFlag(DebugFlags _flag) {

        return (g_flags & (1 << _flag)) != 0; // &ing with a bitfield that is 0 everywhere except index _flag will yield 0 iff index _flag is 0

    }

    void teardown() {
        // Release resources!
        logMsg("teardown\n");
        m_tileManager.reset();
        m_scene.reset();
        m_view.reset();
    }

    void onContextDestroyed() {

        logMsg("context destroyed\n");

        // The OpenGL context has been destroyed since the last time resources were created,
        // so we invalidate all data that depends on OpenGL object handles.

        // ShaderPrograms are invalidated and immediately rebuilt
        ShaderProgram::invalidateAllPrograms();

        // Buffer objects are invalidated and re-uploaded the next time they are used
        VboMesh::invalidateAllVBOs();

    }

}
<|endoftext|>


<commit_before>#include <core/stdafx.h>
#include <core/utility/cli.h>
#include <core/utility/strings.h>
#include <queue>

namespace cli
{
	OptParser GetParser(int clSwitch, const std::vector<OptParser>& parsers)
	{
		for (const auto& parser : parsers)
		{
			if (clSwitch == parser.clSwitch) return parser;
		}

		return {};
	}

	// Checks if szArg is an option, and if it is, returns which option it is
	// We return the first match, so switches should be ordered appropriately
	// The first switch should be our "no match" switch
	int ParseArgument(const std::wstring& szArg, const std::vector<COMMANDLINE_SWITCH>& switches)
	{
		if (szArg.empty()) return 0;

		auto szSwitch = std::wstring{};

		// Check if this is a switch at all
		switch (szArg[0])
		{
		case L'-':
		case L'/':
		case L'\\':
			if (szArg[1] != 0) szSwitch = strings::wstringToLower(&szArg[1]);
			break;
		default:
			return 0;
		}

		for (const auto& s : switches)
		{
			// If we have a match
			if (strings::beginsWith(s.szSwitch, szSwitch))
			{
				return s.iSwitch;
			}
		}

		return 0;
	}

	// If the mode isn't set (is 0), then we can set it to any mode
	// If the mode IS set (non 0), then we can only set it to the same mode
	// IE trying to change the mode from anything but unset will fail
	bool bSetMode(_In_ int& pMode, _In_ int targetMode)
	{
		if (0 == pMode || targetMode == pMode)
		{
			pMode = targetMode;
			return true;
		}

		return false;
	}

	// Converts an argc/argv style command line to a vector
	std::deque<std::wstring> GetCommandLine(_In_ int argc, _In_count_(argc) const char* const argv[])
	{
		auto args = std::deque<std::wstring>{};

		for (auto i = 1; i < argc; i++)
		{
			args.emplace_back(strings::LPCSTRToWstring(argv[i]));
		}

		return args;
	}

	// Assumes that our no switch case is 0
	_Check_return_ bool CheckMinArgs(
		cli::OptParser opt,
		const std::deque<std::wstring> args,
		const std::vector<COMMANDLINE_SWITCH>& switches)
	{
		if (opt.minArgs == 0) return true;
		if (args.size() <= opt.minArgs) return false;

		// TODO: Rebuild this without array access
		for (auto iArg = UINT{1}; iArg <= opt.minArgs; iArg++)
		{
			if (0 != ParseArgument(args[iArg], switches))
			{
				return false;
			}
		}

		return true;
	}
} // namespace cli<commit_msg>eliminate array access from check<commit_after>#include <core/stdafx.h>
#include <core/utility/cli.h>
#include <core/utility/strings.h>
#include <queue>

namespace cli
{
	OptParser GetParser(int clSwitch, const std::vector<OptParser>& parsers)
	{
		for (const auto& parser : parsers)
		{
			if (clSwitch == parser.clSwitch) return parser;
		}

		return {};
	}

	// Checks if szArg is an option, and if it is, returns which option it is
	// We return the first match, so switches should be ordered appropriately
	// The first switch should be our "no match" switch
	int ParseArgument(const std::wstring& szArg, const std::vector<COMMANDLINE_SWITCH>& switches)
	{
		if (szArg.empty()) return 0;

		auto szSwitch = std::wstring{};

		// Check if this is a switch at all
		switch (szArg[0])
		{
		case L'-':
		case L'/':
		case L'\\':
			if (szArg[1] != 0) szSwitch = strings::wstringToLower(&szArg[1]);
			break;
		default:
			return 0;
		}

		for (const auto& s : switches)
		{
			// If we have a match
			if (strings::beginsWith(s.szSwitch, szSwitch))
			{
				return s.iSwitch;
			}
		}

		return 0;
	}

	// If the mode isn't set (is 0), then we can set it to any mode
	// If the mode IS set (non 0), then we can only set it to the same mode
	// IE trying to change the mode from anything but unset will fail
	bool bSetMode(_In_ int& pMode, _In_ int targetMode)
	{
		if (0 == pMode || targetMode == pMode)
		{
			pMode = targetMode;
			return true;
		}

		return false;
	}

	// Converts an argc/argv style command line to a vector
	std::deque<std::wstring> GetCommandLine(_In_ int argc, _In_count_(argc) const char* const argv[])
	{
		auto args = std::deque<std::wstring>{};

		for (auto i = 1; i < argc; i++)
		{
			args.emplace_back(strings::LPCSTRToWstring(argv[i]));
		}

		return args;
	}

	// Assumes that our no switch case is 0
	_Check_return_ bool CheckMinArgs(
		cli::OptParser opt,
		const std::deque<std::wstring> args,
		const std::vector<COMMANDLINE_SWITCH>& switches)
	{
		if (opt.minArgs == 0) return true;
		if (args.size() <= opt.minArgs) return false;

		auto c = UINT{0};
		for (auto it = args.cbegin() + 1; it != args.cend() && c < opt.minArgs; it++, c++)
		{
			if (ParseArgument(*it, switches) != 0)
			{
				return false;
			}
		}

		return true;
	}
} // namespace cli<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#ifndef XENSTORE_HH_
#define XENSTORE_HH_

extern "C" {
    #include <xenstore.h>
}

class xenstore {
public:
    class xenstore_transaction {
    private:
        xenstore *_x;
    protected:
        xs_transaction_t _t = 0;
    public:
        explicit xenstore_transaction(xenstore *x) : _x(x)
                                                   , _t(x->start_transaction()) {}
        explicit xenstore_transaction() {}

        ~xenstore_transaction() { if (_t) { _x->end_transaction(_t);  } }

        xs_transaction_t t() { return _t; }
        friend class xenstore;
    };

protected:
    xs_transaction_t start_transaction();
    void end_transaction(xs_transaction_t t);

    static xenstore_transaction _xs_null; // having it here simplify forward decls

private:
    static xenstore *_instance;
    struct xs_handle *_h;
    explicit xenstore();
    ~xenstore();

public:
    static xenstore *instance();

    virtual void write(std::string path, std::string value, xenstore_transaction &t = _xs_null);
    virtual void remove(std::string path, xenstore_transaction &t = _xs_null);

    virtual std::string read(std::string path, xenstore_transaction &t = _xs_null);

    virtual std::list<std::string> ls(std::string path, xenstore_transaction &t = _xs_null);
    template <typename T>
    T read(std::string path, xenstore_transaction &t = _xs_null) { return boost::lexical_cast<T>(read(path, t)); }

    template <typename T>
    void write(std::string path, T val, xenstore_transaction &t = _xs_null) { return write(path, std::to_string(val), t); }
};

#endif /* XENSTORE_HH_ */
<commit_msg>xen: provide xenstore::read_or_default()<commit_after>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#ifndef XENSTORE_HH_
#define XENSTORE_HH_

extern "C" {
    #include <xenstore.h>
}

class xenstore {
public:
    class xenstore_transaction {
    private:
        xenstore *_x;
    protected:
        xs_transaction_t _t = 0;
    public:
        explicit xenstore_transaction(xenstore *x) : _x(x)
                                                   , _t(x->start_transaction()) {}
        explicit xenstore_transaction() {}

        ~xenstore_transaction() { if (_t) { _x->end_transaction(_t);  } }

        xs_transaction_t t() { return _t; }
        friend class xenstore;
    };

protected:
    xs_transaction_t start_transaction();
    void end_transaction(xs_transaction_t t);

    static xenstore_transaction _xs_null; // having it here simplify forward decls

private:
    static xenstore *_instance;
    struct xs_handle *_h;
    explicit xenstore();
    ~xenstore();

public:
    static xenstore *instance();

    virtual void write(std::string path, std::string value, xenstore_transaction &t = _xs_null);
    virtual void remove(std::string path, xenstore_transaction &t = _xs_null);

    virtual std::string read(std::string path, xenstore_transaction &t = _xs_null);

    virtual std::list<std::string> ls(std::string path, xenstore_transaction &t = _xs_null);
    template <typename T>
    T read(std::string path, xenstore_transaction &t = _xs_null) { return boost::lexical_cast<T>(read(path, t)); }
    template <typename T>
    T read_or_default(std::string path, T deflt = T(), xenstore_transaction &t = _xs_null) {
        auto val = read(path, t);
        if (val.empty()) {
            return deflt;
        } else {
            return boost::lexical_cast<T>(val);
        }
    }

    template <typename T>
    void write(std::string path, T val, xenstore_transaction &t = _xs_null) { return write(path, std::to_string(val), t); }
};

#endif /* XENSTORE_HH_ */
<|endoftext|>


<commit_before>/***********************************************************************
    filename:   GL3ShaderWrapper.cpp
    created:    18th July 2013
    author:     Lukas Meindl
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2013 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include <GL/glew.h>

#include "glm/gtc/type_ptr.hpp"

#include "CEGUI/RendererModules/OpenGL/GL3ShaderWrapper.h"
#include "CEGUI/RendererModules/OpenGL/Shader.h"
#include "CEGUI/RendererModules/OpenGL/Texture.h"
#include "CEGUI/RendererModules/OpenGL/StateChangeWrapper.h"
#include "CEGUI/ShaderParameterBindings.h"
#include "CEGUI/Exceptions.h"

// Start of CEGUI namespace section
namespace CEGUI
{

//----------------------------------------------------------------------------//
OpenGL3ShaderWrapper::OpenGL3ShaderWrapper(OpenGL3Shader& shader, OpenGL3StateChangeWrapper* stateChangeWrapper)
    : d_shader(shader)
    , d_glStateChangeWrapper(stateChangeWrapper)
{
}

//----------------------------------------------------------------------------//
OpenGL3ShaderWrapper::~OpenGL3ShaderWrapper()
{
}

//----------------------------------------------------------------------------//
void OpenGL3ShaderWrapper::addUniformVariable(const std::string& uniformName)
{
    GLuint variable_location = d_shader.getUniformLocation(uniformName);

    d_uniformVariables.insert(std::pair<std::string, GLuint>(uniformName, variable_location));
}

//----------------------------------------------------------------------------//
void OpenGL3ShaderWrapper::addTextureUniformVariable(const std::string& uniformName, GLint textureUnitIndex)
{
    GLuint variable_location = d_shader.getUniformLocation(uniformName);

    d_uniformVariables.insert(std::pair<std::string, GLuint>(uniformName, textureUnitIndex));

    d_shader.bind();
    glUniform1i(variable_location, textureUnitIndex);
}

//----------------------------------------------------------------------------//
void OpenGL3ShaderWrapper::addAttributeVariable(const std::string& attributeName)
{
    GLuint variable_location = d_shader.getAttribLocation(attributeName);

    if(variable_location == -1)
        CEGUI_THROW(RendererException("An attribute with the name \"" + attributeName + "\" does not exist in the shader."));

    d_attributeVariables.insert(std::pair<std::string, GLuint>(attributeName, variable_location));
}

//----------------------------------------------------------------------------//
void OpenGL3ShaderWrapper::prepareForRendering(const ShaderParameterBindings* shaderParameterBindings)
{
    d_shader.bind();

    const ShaderParameterBindings::ShaderParameterBindingsMap& shader_parameter_bindings = shaderParameterBindings->getShaderParameterBindings();
    ShaderParameterBindings::ShaderParameterBindingsMap::const_iterator iter = shader_parameter_bindings.begin();
    ShaderParameterBindings::ShaderParameterBindingsMap::const_iterator end = shader_parameter_bindings.end();

    while(iter != end)
    {
        const CEGUI::ShaderParameter* parameter = iter->second;

        if(parameter->getType() != SPT_TEXTURE)
        {
            std::map<std::string, ShaderParameter*>::iterator found_iterator = d_shaderParameterStates.find(iter->first);
            if(found_iterator != d_shaderParameterStates.end())
            {
                ShaderParameter* last_shader_parameter = found_iterator->second;
                if(parameter->equal(last_shader_parameter))
                {
                    ++iter;
                    continue;
                }
                else
                {
                    if(parameter->getType() == last_shader_parameter->getType())
                        last_shader_parameter->takeOverParameterValue(parameter);
                    else
                    {
                        delete found_iterator->second;
                        found_iterator->second = parameter->clone();
                    }
                }
            }
            else
            {
                d_shaderParameterStates[iter->first] = parameter->clone();
            }
        }

        const GLint& location = d_uniformVariables.find(iter->first)->second;

        CEGUI::ShaderParamType parameter_type = parameter->getType();

        switch(parameter_type)
        {
        case SPT_INT:
            {
                const CEGUI::ShaderParameterInt* parameterInt = static_cast<const CEGUI::ShaderParameterInt*>(parameter);
                glUniform1i(location, parameterInt->d_parameterValue);
            }
            break;
        case SPT_FLOAT:
            {
                const CEGUI::ShaderParameterFloat* parameterFloat = static_cast<const CEGUI::ShaderParameterFloat*>(parameter);
                glUniform1f(location, parameterFloat->d_parameterValue);
            }
            break;
        case SPT_MATRIX:
            {
                const CEGUI::ShaderParameterMatrix* parameterMatrix = static_cast<const CEGUI::ShaderParameterMatrix*>(parameter);
                glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(parameterMatrix->d_parameterValue));
            }
            break;
        case SPT_TEXTURE:
            {
                const CEGUI::ShaderParameterTexture* parameterTexture = static_cast<const CEGUI::ShaderParameterTexture*>(parameter);
                const CEGUI::OpenGLTexture* openglTexture = static_cast<const CEGUI::OpenGLTexture*>(parameterTexture->d_parameterValue);

                d_glStateChangeWrapper->activeTexture(location);
                d_glStateChangeWrapper->bindTexture(GL_TEXTURE_2D, openglTexture->getOpenGLTexture());
            }
            break;
        default:
            break;
        }

        ++iter;
    }
}

//----------------------------------------------------------------------------//
GLint OpenGL3ShaderWrapper::getAttributeLocation(const std::string& attributeName)
{
    std::map<std::string, GLint>::const_iterator iter = d_attributeVariables.find(attributeName);
    if(iter != d_attributeVariables.end())
    {
        return iter->second;
    }
    else
    {
        addAttributeVariable(attributeName);
        iter = d_attributeVariables.find(attributeName);
        return iter->second;
    }
}

//----------------------------------------------------------------------------//
GLint OpenGL3ShaderWrapper::getUniformLocation(const std::string& uniformName)
{
    std::map<std::string, GLint>::const_iterator iter = d_uniformVariables.find(uniformName);
    if(iter != d_uniformVariables.end())
    {
        return iter->second;
    }
    else
    {
        addUniformVariable(uniformName);
        iter = d_uniformVariables.find(uniformName);
        return iter->second;
    }
}

//----------------------------------------------------------------------------//

} // End of  CEGUI namespace section

<commit_msg>MOD: Changed a variable type to the correct one<commit_after>/***********************************************************************
    filename:   GL3ShaderWrapper.cpp
    created:    18th July 2013
    author:     Lukas Meindl
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2013 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include <GL/glew.h>

#include "CEGUI/RendererModules/OpenGL/GL3ShaderWrapper.h"
#include "CEGUI/RendererModules/OpenGL/Shader.h"
#include "CEGUI/RendererModules/OpenGL/Texture.h"
#include "CEGUI/RendererModules/OpenGL/StateChangeWrapper.h"
#include "CEGUI/ShaderParameterBindings.h"
#include "CEGUI/Exceptions.h"

#include <glm/gtc/type_ptr.hpp>

// Start of CEGUI namespace section
namespace CEGUI
{

//----------------------------------------------------------------------------//
OpenGL3ShaderWrapper::OpenGL3ShaderWrapper(OpenGL3Shader& shader, OpenGL3StateChangeWrapper* stateChangeWrapper)
    : d_shader(shader)
    , d_glStateChangeWrapper(stateChangeWrapper)
{
}

//----------------------------------------------------------------------------//
OpenGL3ShaderWrapper::~OpenGL3ShaderWrapper()
{
}

//----------------------------------------------------------------------------//
void OpenGL3ShaderWrapper::addUniformVariable(const std::string& uniformName)
{
    GLuint variable_location = d_shader.getUniformLocation(uniformName);

    d_uniformVariables.insert(std::pair<std::string, GLuint>(uniformName, variable_location));
}

//----------------------------------------------------------------------------//
void OpenGL3ShaderWrapper::addTextureUniformVariable(const std::string& uniformName, GLint textureUnitIndex)
{
    GLuint variable_location = d_shader.getUniformLocation(uniformName);

    d_uniformVariables.insert(std::pair<std::string, GLint>(uniformName, textureUnitIndex));

    d_shader.bind();
    glUniform1i(variable_location, textureUnitIndex);
}

//----------------------------------------------------------------------------//
void OpenGL3ShaderWrapper::addAttributeVariable(const std::string& attributeName)
{
    GLuint variable_location = d_shader.getAttribLocation(attributeName);

    if(variable_location == -1)
        CEGUI_THROW(RendererException("An attribute with the name \"" + attributeName + "\" does not exist in the shader."));

    d_attributeVariables.insert(std::pair<std::string, GLuint>(attributeName, variable_location));
}

//----------------------------------------------------------------------------//
void OpenGL3ShaderWrapper::prepareForRendering(const ShaderParameterBindings* shaderParameterBindings)
{
    d_shader.bind();

    const ShaderParameterBindings::ShaderParameterBindingsMap& shader_parameter_bindings = shaderParameterBindings->getShaderParameterBindings();
    ShaderParameterBindings::ShaderParameterBindingsMap::const_iterator iter = shader_parameter_bindings.begin();
    ShaderParameterBindings::ShaderParameterBindingsMap::const_iterator end = shader_parameter_bindings.end();

    while(iter != end)
    {
        const CEGUI::ShaderParameter* parameter = iter->second;

        if(parameter->getType() != SPT_TEXTURE)
        {
            std::map<std::string, ShaderParameter*>::iterator found_iterator = d_shaderParameterStates.find(iter->first);
            if(found_iterator != d_shaderParameterStates.end())
            {
                ShaderParameter* last_shader_parameter = found_iterator->second;
                if(parameter->equal(last_shader_parameter))
                {
                    ++iter;
                    continue;
                }
                else
                {
                    if(parameter->getType() == last_shader_parameter->getType())
                        last_shader_parameter->takeOverParameterValue(parameter);
                    else
                    {
                        delete found_iterator->second;
                        found_iterator->second = parameter->clone();
                    }
                }
            }
            else
            {
                d_shaderParameterStates[iter->first] = parameter->clone();
            }
        }

        const GLint& location = d_uniformVariables.find(iter->first)->second;

        CEGUI::ShaderParamType parameter_type = parameter->getType();

        switch(parameter_type)
        {
        case SPT_INT:
            {
                const CEGUI::ShaderParameterInt* parameterInt = static_cast<const CEGUI::ShaderParameterInt*>(parameter);
                glUniform1i(location, parameterInt->d_parameterValue);
            }
            break;
        case SPT_FLOAT:
            {
                const CEGUI::ShaderParameterFloat* parameterFloat = static_cast<const CEGUI::ShaderParameterFloat*>(parameter);
                glUniform1f(location, parameterFloat->d_parameterValue);
            }
            break;
        case SPT_MATRIX:
            {
                const CEGUI::ShaderParameterMatrix* parameterMatrix = static_cast<const CEGUI::ShaderParameterMatrix*>(parameter);
                glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(parameterMatrix->d_parameterValue));
            }
            break;
        case SPT_TEXTURE:
            {
                const CEGUI::ShaderParameterTexture* parameterTexture = static_cast<const CEGUI::ShaderParameterTexture*>(parameter);
                const CEGUI::OpenGLTexture* openglTexture = static_cast<const CEGUI::OpenGLTexture*>(parameterTexture->d_parameterValue);

                d_glStateChangeWrapper->activeTexture(location);
                d_glStateChangeWrapper->bindTexture(GL_TEXTURE_2D, openglTexture->getOpenGLTexture());
            }
            break;
        default:
            break;
        }

        ++iter;
    }
}

//----------------------------------------------------------------------------//
GLint OpenGL3ShaderWrapper::getAttributeLocation(const std::string& attributeName)
{
    std::map<std::string, GLint>::const_iterator iter = d_attributeVariables.find(attributeName);
    if(iter != d_attributeVariables.end())
    {
        return iter->second;
    }
    else
    {
        addAttributeVariable(attributeName);
        iter = d_attributeVariables.find(attributeName);
        return iter->second;
    }
}

//----------------------------------------------------------------------------//
GLint OpenGL3ShaderWrapper::getUniformLocation(const std::string& uniformName)
{
    std::map<std::string, GLint>::const_iterator iter = d_uniformVariables.find(uniformName);
    if(iter != d_uniformVariables.end())
    {
        return iter->second;
    }
    else
    {
        addUniformVariable(uniformName);
        iter = d_uniformVariables.find(uniformName);
        return iter->second;
    }
}

//----------------------------------------------------------------------------//

} // End of  CEGUI namespace section

<|endoftext|>