<commit_before>//===-- Uops.cpp ------------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Uops.h"

#include "Assembler.h"
#include "BenchmarkRunner.h"
#include "MCInstrDescView.h"
#include "PerfHelper.h"

// FIXME: Load constants into registers (e.g. with fld1) to not break
// instructions like x87.

// Ideally we would like the only limitation on executing uops to be the issue
// ports. Maximizing port pressure increases the likelihood that the load is
// distributed evenly across possible ports.

// To achieve that, one approach is to generate instructions that do not have
// data dependencies between them.
//
// For some instructions, this is trivial:
//    mov rax, qword ptr [rsi]
//    mov rax, qword ptr [rsi]
//    mov rax, qword ptr [rsi]
//    mov rax, qword ptr [rsi]
// For the above snippet, haswell just renames rax four times and executes the
// four instructions two at a time on P23 and P0126.
//
// For some instructions, we just need to make sure that the source is
// different from the destination. For example, IDIV8r reads from GPR and
// writes to AX. We just need to ensure that the Var is assigned a
// register which is different from AX:
//    idiv bx
//    idiv bx
//    idiv bx
//    idiv bx
// The above snippet will be able to fully saturate the ports, while the same
// with ax would issue one uop every `latency(IDIV8r)` cycles.
//
// Some instructions make this harder because they both read and write from
// the same register:
//    inc rax
//    inc rax
//    inc rax
//    inc rax
// This has a data dependency from each instruction to the next, limit the
// number of instructions that can be issued in parallel.
// It turns out that this is not a big issue on recent Intel CPUs because they
// have heuristics to balance port pressure. In the snippet above, subsequent
// instructions will end up evenly distributed on {P0,P1,P5,P6}, but some CPUs
// might end up executing them all on P0 (just because they can), or try
// avoiding P5 because it's usually under high pressure from vector
// instructions.
// This issue is even more important for high-latency instructions because
// they increase the idle time of the CPU, e.g. :
//    imul rax, rbx
//    imul rax, rbx
//    imul rax, rbx
//    imul rax, rbx
//
// To avoid that, we do the renaming statically by generating as many
// independent exclusive assignments as possible (until all possible registers
// are exhausted) e.g.:
//    imul rax, rbx
//    imul rcx, rbx
//    imul rdx, rbx
//    imul r8,  rbx
//
// Some instruction even make the above static renaming impossible because
// they implicitly read and write from the same operand, e.g. ADC16rr reads
// and writes from EFLAGS.
// In that case we just use a greedy register assignment and hope for the
// best.

namespace exegesis {

static bool hasUnknownOperand(const llvm::MCOperandInfo &OpInfo) {
  return OpInfo.OperandType == llvm::MCOI::OPERAND_UNKNOWN;
}

// FIXME: Handle memory, see PR36905.
static bool hasMemoryOperand(const llvm::MCOperandInfo &OpInfo) {
  return OpInfo.OperandType == llvm::MCOI::OPERAND_MEMORY;
}

static bool isInfeasible(const Instruction &Instruction, std::string &Error) {
  const auto &MCInstrDesc = Instruction.Description;
  if (MCInstrDesc.isPseudo()) {
    Error = "is pseudo";
    return true;
  }
  if (llvm::any_of(MCInstrDesc.operands(), hasUnknownOperand)) {
    Error = "has unknown operands";
    return true;
  }
  if (llvm::any_of(MCInstrDesc.operands(), hasMemoryOperand)) {
    Error = "has memory operands";
    return true;
  }
  return false;
}

// Returns whether this Variable ties Use and Def operands together.
static bool hasTiedOperands(const Variable *Var) {
  bool HasUse = false;
  bool HasDef = false;
  for (const Operand *Op : Var->TiedOperands) {
    if (Op->IsDef)
      HasDef = true;
    else
      HasUse = true;
  }
  return HasUse && HasDef;
}

static llvm::SmallVector<Variable *, 8>
getTiedVariables(const Instruction &Instruction) {
  llvm::SmallVector<Variable *, 8> Result;
  for (auto *Var : Instruction.Variables)
    if (hasTiedOperands(Var))
      Result.push_back(Var);
  return Result;
}

static void remove(llvm::BitVector &a, const llvm::BitVector &b) {
  assert(a.size() == b.size());
  for (auto I : b.set_bits())
    a.reset(I);
}

UopsBenchmarkRunner::~UopsBenchmarkRunner() = default;

InstructionBenchmark::ModeE UopsBenchmarkRunner::getMode() const {
  return InstructionBenchmark::Uops;
}

llvm::Expected<std::vector<BenchmarkConfiguration>>
UopsBenchmarkRunner::createConfigurations(RegisterAliasingTrackerCache &RATC,
                                          unsigned Opcode) const {
  const llvm::MCInstrDesc &MCInstrDesc = MCInstrInfo.get(Opcode);
  const Instruction Instruction(MCInstrDesc, RATC);

  std::string Error;
  if (isInfeasible(Instruction, Error))
    return llvm::make_error<llvm::StringError>(
        llvm::Twine("Infeasible : ").concat(Error),
        llvm::inconvertibleErrorCode());

  BenchmarkConfiguration Conf;
  const AliasingConfigurations SelfAliasing(Instruction, Instruction);
  if (SelfAliasing.empty()) {
    Conf.Info = "instruction is parallel, repeating a random one.";
    Conf.Snippet = {randomizeUnsetVariablesAndBuild(Instruction)};
    return std::vector<BenchmarkConfiguration>{Conf};
  }
  if (SelfAliasing.hasImplicitAliasing()) {
    Conf.Info = "instruction is serial, repeating a random one.";
    Conf.Snippet = {randomizeUnsetVariablesAndBuild(Instruction)};
    return std::vector<BenchmarkConfiguration>{Conf};
  }
  const auto TiedVariables = getTiedVariables(Instruction);
  if (!TiedVariables.empty()) {
    if (TiedVariables.size() > 1)
      return llvm::make_error<llvm::StringError>(
          "Infeasible : don't know how to handle several tied variables",
          llvm::inconvertibleErrorCode());
    Conf.Info = "instruction has tied variables using static renaming.";
    Variable *Var = TiedVariables.front();
    assert(Var);
    assert(!Var->TiedOperands.empty());
    const Operand &Operand = *Var->TiedOperands.front();
    assert(Operand.Tracker);
    for (const llvm::MCPhysReg Reg : Operand.Tracker->sourceBits().set_bits()) {
      clearVariableAssignments(Instruction);
      Var->AssignedValue = llvm::MCOperand::createReg(Reg);
      Conf.Snippet.push_back(randomizeUnsetVariablesAndBuild(Instruction));
    }
    return std::vector<BenchmarkConfiguration>{Conf};
  }
  // No tied variables, we pick random values for defs.
  llvm::BitVector Defs(MCRegisterInfo.getNumRegs());
  for (const auto &Op : Instruction.Operands) {
    if (Op.Tracker && Op.IsExplicit && Op.IsDef) {
      assert(Op.Var);
      auto PossibleRegisters = Op.Tracker->sourceBits();
      remove(PossibleRegisters, RATC.reservedRegisters());
      assert(PossibleRegisters.any() && "No register left to choose from");
      const auto RandomReg = randomBit(PossibleRegisters);
      Defs.set(RandomReg);
      Op.Var->AssignedValue = llvm::MCOperand::createReg(RandomReg);
    }
  }
  // And pick random use values that are not reserved and don't alias with defs.
  const auto DefAliases = getAliasedBits(MCRegisterInfo, Defs);
  for (const auto &Op : Instruction.Operands) {
    if (Op.Tracker && Op.IsExplicit && !Op.IsDef) {
      assert(Op.Var);
      auto PossibleRegisters = Op.Tracker->sourceBits();
      remove(PossibleRegisters, RATC.reservedRegisters());
      remove(PossibleRegisters, DefAliases);
      assert(PossibleRegisters.any() && "No register left to choose from");
      const auto RandomReg = randomBit(PossibleRegisters);
      Op.Var->AssignedValue = llvm::MCOperand::createReg(RandomReg);
    }
  }
  Conf.Info =
      "instruction has no tied variables picking Uses different from defs";
  Conf.Snippet = {randomizeUnsetVariablesAndBuild(Instruction)};
  return std::vector<BenchmarkConfiguration>{Conf};
}

std::vector<BenchmarkMeasure>
UopsBenchmarkRunner::runMeasurements(const ExecutableFunction &Function,
                                     const unsigned NumRepetitions) const {
  const auto &SchedModel = State.getSubtargetInfo().getSchedModel();

  std::vector<BenchmarkMeasure> Result;
  for (unsigned ProcResIdx = 1;
       ProcResIdx < SchedModel.getNumProcResourceKinds(); ++ProcResIdx) {
    const char *const PfmCounters = SchedModel.getExtraProcessorInfo()
                                        .PfmCounters.IssueCounters[ProcResIdx];
    if (!PfmCounters)
      continue;
    // FIXME: Sum results when there are several counters for a single ProcRes
    // (e.g. P23 on SandyBridge).
    pfm::PerfEvent UopPerfEvent(PfmCounters);
    if (!UopPerfEvent.valid())
      llvm::report_fatal_error(
          llvm::Twine("invalid perf event ").concat(PfmCounters));
    pfm::Counter Counter(UopPerfEvent);
    Counter.start();
    Function();
    Counter.stop();
    Result.push_back({llvm::itostr(ProcResIdx),
                      static_cast<double>(Counter.read()) / NumRepetitions,
                      SchedModel.getProcResource(ProcResIdx)->Name});
  }
  return Result;
}

} // namespace exegesis
<commit_msg>[llvm-exegesis] Sum counter values when several counters are specified for a ProcRes.<commit_after>//===-- Uops.cpp ------------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Uops.h"

#include "Assembler.h"
#include "BenchmarkRunner.h"
#include "MCInstrDescView.h"
#include "PerfHelper.h"

// FIXME: Load constants into registers (e.g. with fld1) to not break
// instructions like x87.

// Ideally we would like the only limitation on executing uops to be the issue
// ports. Maximizing port pressure increases the likelihood that the load is
// distributed evenly across possible ports.

// To achieve that, one approach is to generate instructions that do not have
// data dependencies between them.
//
// For some instructions, this is trivial:
//    mov rax, qword ptr [rsi]
//    mov rax, qword ptr [rsi]
//    mov rax, qword ptr [rsi]
//    mov rax, qword ptr [rsi]
// For the above snippet, haswell just renames rax four times and executes the
// four instructions two at a time on P23 and P0126.
//
// For some instructions, we just need to make sure that the source is
// different from the destination. For example, IDIV8r reads from GPR and
// writes to AX. We just need to ensure that the Var is assigned a
// register which is different from AX:
//    idiv bx
//    idiv bx
//    idiv bx
//    idiv bx
// The above snippet will be able to fully saturate the ports, while the same
// with ax would issue one uop every `latency(IDIV8r)` cycles.
//
// Some instructions make this harder because they both read and write from
// the same register:
//    inc rax
//    inc rax
//    inc rax
//    inc rax
// This has a data dependency from each instruction to the next, limit the
// number of instructions that can be issued in parallel.
// It turns out that this is not a big issue on recent Intel CPUs because they
// have heuristics to balance port pressure. In the snippet above, subsequent
// instructions will end up evenly distributed on {P0,P1,P5,P6}, but some CPUs
// might end up executing them all on P0 (just because they can), or try
// avoiding P5 because it's usually under high pressure from vector
// instructions.
// This issue is even more important for high-latency instructions because
// they increase the idle time of the CPU, e.g. :
//    imul rax, rbx
//    imul rax, rbx
//    imul rax, rbx
//    imul rax, rbx
//
// To avoid that, we do the renaming statically by generating as many
// independent exclusive assignments as possible (until all possible registers
// are exhausted) e.g.:
//    imul rax, rbx
//    imul rcx, rbx
//    imul rdx, rbx
//    imul r8,  rbx
//
// Some instruction even make the above static renaming impossible because
// they implicitly read and write from the same operand, e.g. ADC16rr reads
// and writes from EFLAGS.
// In that case we just use a greedy register assignment and hope for the
// best.

namespace exegesis {

static bool hasUnknownOperand(const llvm::MCOperandInfo &OpInfo) {
  return OpInfo.OperandType == llvm::MCOI::OPERAND_UNKNOWN;
}

// FIXME: Handle memory, see PR36905.
static bool hasMemoryOperand(const llvm::MCOperandInfo &OpInfo) {
  return OpInfo.OperandType == llvm::MCOI::OPERAND_MEMORY;
}

static bool isInfeasible(const Instruction &Instruction, std::string &Error) {
  const auto &MCInstrDesc = Instruction.Description;
  if (MCInstrDesc.isPseudo()) {
    Error = "is pseudo";
    return true;
  }
  if (llvm::any_of(MCInstrDesc.operands(), hasUnknownOperand)) {
    Error = "has unknown operands";
    return true;
  }
  if (llvm::any_of(MCInstrDesc.operands(), hasMemoryOperand)) {
    Error = "has memory operands";
    return true;
  }
  return false;
}

// Returns whether this Variable ties Use and Def operands together.
static bool hasTiedOperands(const Variable *Var) {
  bool HasUse = false;
  bool HasDef = false;
  for (const Operand *Op : Var->TiedOperands) {
    if (Op->IsDef)
      HasDef = true;
    else
      HasUse = true;
  }
  return HasUse && HasDef;
}

static llvm::SmallVector<Variable *, 8>
getTiedVariables(const Instruction &Instruction) {
  llvm::SmallVector<Variable *, 8> Result;
  for (auto *Var : Instruction.Variables)
    if (hasTiedOperands(Var))
      Result.push_back(Var);
  return Result;
}

static void remove(llvm::BitVector &a, const llvm::BitVector &b) {
  assert(a.size() == b.size());
  for (auto I : b.set_bits())
    a.reset(I);
}

UopsBenchmarkRunner::~UopsBenchmarkRunner() = default;

InstructionBenchmark::ModeE UopsBenchmarkRunner::getMode() const {
  return InstructionBenchmark::Uops;
}

llvm::Expected<std::vector<BenchmarkConfiguration>>
UopsBenchmarkRunner::createConfigurations(RegisterAliasingTrackerCache &RATC,
                                          unsigned Opcode) const {
  const llvm::MCInstrDesc &MCInstrDesc = MCInstrInfo.get(Opcode);
  const Instruction Instruction(MCInstrDesc, RATC);

  std::string Error;
  if (isInfeasible(Instruction, Error))
    return llvm::make_error<llvm::StringError>(
        llvm::Twine("Infeasible : ").concat(Error),
        llvm::inconvertibleErrorCode());

  BenchmarkConfiguration Conf;
  const AliasingConfigurations SelfAliasing(Instruction, Instruction);
  if (SelfAliasing.empty()) {
    Conf.Info = "instruction is parallel, repeating a random one.";
    Conf.Snippet = {randomizeUnsetVariablesAndBuild(Instruction)};
    return std::vector<BenchmarkConfiguration>{Conf};
  }
  if (SelfAliasing.hasImplicitAliasing()) {
    Conf.Info = "instruction is serial, repeating a random one.";
    Conf.Snippet = {randomizeUnsetVariablesAndBuild(Instruction)};
    return std::vector<BenchmarkConfiguration>{Conf};
  }
  const auto TiedVariables = getTiedVariables(Instruction);
  if (!TiedVariables.empty()) {
    if (TiedVariables.size() > 1)
      return llvm::make_error<llvm::StringError>(
          "Infeasible : don't know how to handle several tied variables",
          llvm::inconvertibleErrorCode());
    Conf.Info = "instruction has tied variables using static renaming.";
    Variable *Var = TiedVariables.front();
    assert(Var);
    assert(!Var->TiedOperands.empty());
    const Operand &Operand = *Var->TiedOperands.front();
    assert(Operand.Tracker);
    for (const llvm::MCPhysReg Reg : Operand.Tracker->sourceBits().set_bits()) {
      clearVariableAssignments(Instruction);
      Var->AssignedValue = llvm::MCOperand::createReg(Reg);
      Conf.Snippet.push_back(randomizeUnsetVariablesAndBuild(Instruction));
    }
    return std::vector<BenchmarkConfiguration>{Conf};
  }
  // No tied variables, we pick random values for defs.
  llvm::BitVector Defs(MCRegisterInfo.getNumRegs());
  for (const auto &Op : Instruction.Operands) {
    if (Op.Tracker && Op.IsExplicit && Op.IsDef) {
      assert(Op.Var);
      auto PossibleRegisters = Op.Tracker->sourceBits();
      remove(PossibleRegisters, RATC.reservedRegisters());
      assert(PossibleRegisters.any() && "No register left to choose from");
      const auto RandomReg = randomBit(PossibleRegisters);
      Defs.set(RandomReg);
      Op.Var->AssignedValue = llvm::MCOperand::createReg(RandomReg);
    }
  }
  // And pick random use values that are not reserved and don't alias with defs.
  const auto DefAliases = getAliasedBits(MCRegisterInfo, Defs);
  for (const auto &Op : Instruction.Operands) {
    if (Op.Tracker && Op.IsExplicit && !Op.IsDef) {
      assert(Op.Var);
      auto PossibleRegisters = Op.Tracker->sourceBits();
      remove(PossibleRegisters, RATC.reservedRegisters());
      remove(PossibleRegisters, DefAliases);
      assert(PossibleRegisters.any() && "No register left to choose from");
      const auto RandomReg = randomBit(PossibleRegisters);
      Op.Var->AssignedValue = llvm::MCOperand::createReg(RandomReg);
    }
  }
  Conf.Info =
      "instruction has no tied variables picking Uses different from defs";
  Conf.Snippet = {randomizeUnsetVariablesAndBuild(Instruction)};
  return std::vector<BenchmarkConfiguration>{Conf};
}

std::vector<BenchmarkMeasure>
UopsBenchmarkRunner::runMeasurements(const ExecutableFunction &Function,
                                     const unsigned NumRepetitions) const {
  const auto &SchedModel = State.getSubtargetInfo().getSchedModel();

  std::vector<BenchmarkMeasure> Result;
  for (unsigned ProcResIdx = 1;
       ProcResIdx < SchedModel.getNumProcResourceKinds(); ++ProcResIdx) {
    const char *const PfmCounters = SchedModel.getExtraProcessorInfo()
                                        .PfmCounters.IssueCounters[ProcResIdx];
    if (!PfmCounters)
      continue;
    // We sum counts when there are several counters for a single ProcRes
    // (e.g. P23 on SandyBridge).
    int64_t CounterValue = 0;
    llvm::SmallVector<llvm::StringRef, 2> CounterNames;
    llvm::StringRef(PfmCounters).split(CounterNames, ',');
    for (const auto& CounterName : CounterNames) {
      pfm::PerfEvent UopPerfEvent(CounterName);
      if (!UopPerfEvent.valid())
        llvm::report_fatal_error(
            llvm::Twine("invalid perf event ").concat(PfmCounters));
      pfm::Counter Counter(UopPerfEvent);
      Counter.start();
      Function();
      Counter.stop();
      CounterValue += Counter.read();
    }
    Result.push_back({llvm::itostr(ProcResIdx),
                      static_cast<double>(CounterValue) / NumRepetitions,
                      SchedModel.getProcResource(ProcResIdx)->Name});
  }
  return Result;
}

} // namespace exegesis
<|endoftext|>


<commit_before>#ifndef _COTL_STD_ID_HPP
#define _COTL_STD_ID_HPP

#include "cotl_helper.hpp"

namespace cotlstd {

enum {
    // the range of id
    IDX_BASE = -2333333,
    IDX_TOP = 0
};

enum {
    // std lib

    // types (int, real, arr, stack, null, true etc.)
    IDX_TYPE        = IDX_BASE + 23,
    IDX_TYPE_TOP    = IDX_BASE + 232,
    // core functions
    IDX_RUNTIME     = IDX_BASE + 233,
    IDX_RUNTIME_TOP = IDX_BASE + 2332,
    // library functions
    IDX_FUNC        = IDX_BASE + 2333,
    IDX_FUNC_TOP    = IDX_BASE + 23332,

    // non-std

    // user-defined native types / functions
    IDX_NATIVE      = IDX_BASE + 23333,
    IDX_NATIVE_TOP  = IDX_BASE + 233332,
    // user-defined values in cotl code
    IDX_USER        = IDX_BASE + 233333,
    IDX_USER_TOP    = IDX_BASE + 2333332
};

inline
namespace published {

enum {
    // atom
    id_atom = IDX_TYPE,
    id_null,
    id_false,
    id_true,

    // int
    id_int  = IDX_TYPE + 16,
    id_increment,
    id_decrement,

    // real
    id_real = IDX_TYPE + 32,

    // func
    id_func = IDX_TYPE + 48,

    // ptr
    id_ptr  = IDX_TYPE + 64,
    id_refptr,

    // pair
    id_pair = IDX_TYPE + 80,

    // str
    id_str  = IDX_TYPE + 96,

    // arr
    id_arr  = IDX_TYPE + 112,
    id_stack,

    // map
    id_map  = IDX_TYPE + 128,

    // special
    id_error = IDX_TYPE + 144
};

enum {
    // atom
    ID_NULLARY = IDX_RUNTIME,

    // ptr
    ID_UNARY   = IDX_RUNTIME + 256,
    id_quote,
    id_contain,

    // pair
    ID_BINARY  = IDX_RUNTIME + 512,

    // any
    id_VARARY  = IDX_RUNTIME + 768,
    id_auto,
    id_literal,
    id_bind
};

}

}

#endif
<commit_msg>modify id structure<commit_after>#ifndef _COTL_STD_ID_HPP
#define _COTL_STD_ID_HPP

#include "cotl_helper.hpp"

namespace cotlstd {

enum {
    // the range of id
    IDX_BASE = -2333333,
    IDX_TOP = 0
};

enum {
    // std lib

    // types (int, real, arr, stack, null, true etc.)
    IDX_TYPE       = IDX_BASE + 23,
    IDX_TYPE_TOP   = IDX_BASE + 232,
    // core functions
    IDX_CORE       = IDX_BASE + 233,
    IDX_CORE_TOP   = IDX_BASE + 2332,
    // library functions
    IDX_LIB        = IDX_BASE + 2333,
    IDX_LIB_TOP    = IDX_BASE + 23332,

    // non-std

    // user-defined native types / functions
    IDX_NATIVE     = IDX_BASE + 23333,
    IDX_NATIVE_TOP = IDX_BASE + 233332,
    // user-defined values in cotl code
    IDX_USER       = IDX_BASE + 233333,
    IDX_USER_TOP   = IDX_BASE + 2333332
};

inline
namespace published {

enum {
    id_type = IDX_TYPE, // TODO: add lib for id_error

        // atom
        id_atom  = IDX_TYPE + 16,
        id_null,
        id_false,
        id_true,

        // int
        id_int   = IDX_TYPE + 32,
        id_increment,
        id_decrement,

        // real
        id_real  = IDX_TYPE + 48,

        // func
        id_func  = IDX_TYPE + 64,

        // ptr
        id_ptr   = IDX_TYPE + 80,
        id_refptr,

        // pair
        id_pair  = IDX_TYPE + 96,

        // str
        id_str   = IDX_TYPE + 112,

        // arr
        id_arr   = IDX_TYPE + 128,
        id_stack,

        // map
        id_map   = IDX_TYPE + 144,

        // special
        id_error = IDX_TYPE + 160,

        // override packages
        id_type_wrap = IDX_TYPE + 176,
            /* override: non-special types */
        id_type_lib,
            /* override: func, map */
};

enum {
    ID_STD = IDX_CORE,
        id_runtime,
            id_auto,
            id_literal,
            id_bind,
            id_quote,
            id_contain,

        id_math,
            id_add, // TODO: both int and real (auto detect)
            id_sub,
            id_mul,
            id_div,

            id_math_int,
                /* override: add, sub, mul, div */
                id_mod,

            id_math_real
                /* override: add, sub, mul, div */
};

}

}

#endif
<|endoftext|>


<commit_before>/*
 * pv_example.cpp
 *
 *  Example of a PetaVision application.
 *
 */

#include <stdlib.h>

#include "include/pv_common.h"
#include "columns/HyPerCol.hpp"

#include "layers/Image.hpp"
#include "layers/Retina.hpp"
#include "layers/LIF.hpp"

using namespace PV;

int main(int argc, char* argv[])
{
   HyPerCol * hc = new HyPerCol("column", argc, argv, ".");

   // construct layers
   Image * image = new Image("Image", hc, hc->inputFile());
   HyPerLayer * retina  = new Retina("Retina", hc);
   HyPerLayer * l1      = new LIF("L1", hc);

   // connect the layers
   new PV::HyPerConn("Retina to L1", hc, retina, l1, CHANNEL_EXC);

   // finish initialization now that everything is connected
   hc->initFinish();

   // run the simulation for 2 time steps
   hc->run(1);

   // clean up (HyPerCol owns the layers, so don't delete them here)
   delete hc;

   return 0;
}

<commit_msg>Added a connection so that the Image layer is connected to the others<commit_after>/*
 * pv_example.cpp
 *
 *  Example of a PetaVision application.
 *
 */

#include <stdlib.h>

#include "include/pv_common.h"
#include "columns/HyPerCol.hpp"

#include "layers/Image.hpp"
#include "layers/Retina.hpp"
#include "layers/LIF.hpp"

using namespace PV;

int main(int argc, char* argv[])
{
   HyPerCol * hc = new HyPerCol("column", argc, argv, ".");

   // construct layers
   Image * image = new Image("Image", hc, hc->inputFile());
   HyPerLayer * retina  = new Retina("Retina", hc);
   HyPerLayer * l1      = new LIF("L1", hc);

   // connect the layers
   new PV::HyPerConn("Image to Retina", hc, image, retina, CHANNEL_EXC);
   new PV::HyPerConn("Retina to L1", hc, retina, l1, CHANNEL_EXC);

   // finish initialization now that everything is connected
   hc->initFinish();

   // run the simulation for 2 time steps
   hc->run(1);

   // clean up (HyPerCol owns the layers, so don't delete them here)
   delete hc;

   return 0;
}

<|endoftext|>


<commit_before>/*****************************************************************************

    (c) 2013 Hobu, Inc. hobu.inc@gmail.com

    Author: Andrew Bell andrew.bell.ia at gmail.com

    This is free software; you can redistribute and/or modify it under the
    terms of the GNU Lesser General Licence as published by the Free Software
    Foundation. See the COPYING file for more information.

    This software is distributed WITHOUT ANY WARRANTY and without even the
    implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

*****************************************************************************/

#define HEXER_VERSION_MAJOR    1
#define HEXER_VERSION_MINOR    0
#define HEXER_VERSION_REVISION 0

#include <hexer/hexer_defines.h><commit_msg>add a hexer_error, derived from std::runtime_error to throw when interesting things happen<commit_after>/*****************************************************************************

    (c) 2013 Hobu, Inc. hobu.inc@gmail.com

    Author: Andrew Bell andrew.bell.ia at gmail.com

    This is free software; you can redistribute and/or modify it under the
    terms of the GNU Lesser General Licence as published by the Free Software
    Foundation. See the COPYING file for more information.

    This software is distributed WITHOUT ANY WARRANTY and without even the
    implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

*****************************************************************************/

#define HEXER_VERSION_MAJOR    1
#define HEXER_VERSION_MINOR    0
#define HEXER_VERSION_REVISION 0

#include <hexer/hexer_defines.h>

#include <stdexcept>

namespace hexer
{

class hexer_error : public std::runtime_error
{
public:
    hexer_error(std::string const& msg)
        : std::runtime_error(msg)
    {}
};

}
<|endoftext|>


<commit_before>// This file is part of libigl, a simple c++ geometry processing library.
//
// Copyright (C) 2014 Daniele Panozzo <daniele.panozzo@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.
#include "igl/dot_row.h"

template <typename DerivedA, typename DerivedB, typename Derv>
IGL_INLINE Eigen::PlainObjectBase<DerivedV> igl::dot_row(
  const Eigen::PlainObjectBase<DerivedV>& A,
  const Eigen::PlainObjectBase<DerivedV>& B
  )
{
  assert(A.rows() == B.rows());
  assert(A.cols() == B.cols());

  return (A.array() * B.array()).rowwise().sum();
}

#ifndef IGL_HEADER_ONLY
// Explicit template specialization
// generated by autoexplicit.sh
#endif
<commit_msg>fix new bug in dot_row<commit_after>// This file is part of libigl, a simple c++ geometry processing library.
//
// Copyright (C) 2014 Daniele Panozzo <daniele.panozzo@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.
#include "igl/dot_row.h"

template <typename DerivedV>
IGL_INLINE Eigen::PlainObjectBase<DerivedV> igl::dot_row(
  const Eigen::PlainObjectBase<DerivedV>& A,
  const Eigen::PlainObjectBase<DerivedV>& B
  )
{
  assert(A.rows() == B.rows());
  assert(A.cols() == B.cols());

  return (A.array() * B.array()).rowwise().sum();
}

#ifndef IGL_HEADER_ONLY
// Explicit template specialization
// generated by autoexplicit.sh
#endif
<|endoftext|>


<commit_before>/*  Sirikata
 *  StreamEcho.cpp
 *
 *  Copyright (c) 2010, Ewen Cheslack-Postava
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of Sirikata nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <sirikata/core/util/Platform.hpp>
#include <sirikata/core/network/Stream.hpp>
#include <sirikata/core/network/StreamListener.hpp>
#include <sirikata/core/network/StreamListenerFactory.hpp>
#include <sirikata/core/options/CommonOptions.hpp>
#include <sirikata/core/util/PluginManager.hpp>
#include <sirikata/core/network/IOServiceFactory.hpp>
#include <sirikata/core/network/IOService.hpp>

#include "Protocol_Empty.pbj.hpp"

void handleConnectionEvent(Sirikata::Network::Stream* strm, Sirikata::Network::Stream::ConnectionStatus, const std::string&reason);
void handleSubstream(Sirikata::Network::Stream* substream, Sirikata::Network::Stream::SetCallbacks&);
void handlePBJSubstream(Sirikata::Network::Stream* substream, Sirikata::Network::Stream::SetCallbacks&);
void handleReceived(Sirikata::Network::Stream* strm, Sirikata::Network::Chunk& payload, const Sirikata::Network::Stream::PauseReceiveCallback& pausecb);
void handlePBJReceived(Sirikata::Network::Stream* strm, Sirikata::Network::Chunk& payload, const Sirikata::Network::Stream::PauseReceiveCallback& pausecb);
void handleReadySend(Sirikata::Network::Stream* strm);

void handleNewConnection(Sirikata::Network::Stream* strm, Sirikata::Network::Stream::SetCallbacks& sc) {
    printf("Received connection\n");
    // Do same for main connection stream and substreams
    handleSubstream(strm, sc);
}

void handleNewPBJConnection(Sirikata::Network::Stream* strm, Sirikata::Network::Stream::SetCallbacks& sc) {
    printf("Received PBJ connection\n");
    // Do same for main connection stream and substreams
    handlePBJSubstream(strm, sc);
}

void handleConnectionEvent(Sirikata::Network::Stream* strm, Sirikata::Network::Stream::ConnectionStatus status, const std::string&reason) {
    if (status == Sirikata::Network::Stream::Disconnected)
        printf("Stream disconnected\n");
}

void handleSubstream(Sirikata::Network::Stream* substream, Sirikata::Network::Stream::SetCallbacks& sc) {
    using std::tr1::placeholders::_1;
    using std::tr1::placeholders::_2;

    printf("New substream\n");
    sc(
        std::tr1::bind(handleConnectionEvent, substream, _1, _2),
        std::tr1::bind(handleReceived, substream, _1, _2),
        std::tr1::bind(handleReadySend, substream)
    );
}

void handlePBJSubstream(Sirikata::Network::Stream* substream, Sirikata::Network::Stream::SetCallbacks& sc) {
    using std::tr1::placeholders::_1;
    using std::tr1::placeholders::_2;

    printf("New PBJ substream\n");
    sc(
        std::tr1::bind(handleConnectionEvent, substream, _1, _2),
        std::tr1::bind(handlePBJReceived, substream, _1, _2),
        std::tr1::bind(handleReadySend, substream)
    );
}

void handleReceived(Sirikata::Network::Stream* strm, Sirikata::Network::Chunk& payload, const Sirikata::Network::Stream::PauseReceiveCallback& pausecb) {
    printf("Received %d bytes\n", (int)payload.size());
    strm->send(payload, Sirikata::Network::ReliableOrdered);
}

void handlePBJReceived(Sirikata::Network::Stream* strm, Sirikata::Network::Chunk& payload, const Sirikata::Network::Stream::PauseReceiveCallback& pausecb) {
    printf("Received %d PBJ bytes: ", (int)payload.size());

    Sirikata::Protocol::Empty msg;
    if (!msg.ParseFromArray(payload.data(), payload.size())) {
        printf(" parsing PBJ failed.\n");
        // Indicate error to other side
        const char* error_msg = "Error"; // "Error" in base 64
        strm->send(Sirikata::MemoryReference(error_msg, strlen(error_msg)), Sirikata::Network::ReliableOrdered);
        return;
    }

    printf("%d fields\n", msg.unknown_fields().field_count());

    for(int i = 0; i < msg.unknown_fields().field_count(); i++) {
#define __FIELD(i) msg.unknown_fields().field(i)
        switch(__FIELD(i).type()) {
          case ::google::protobuf::UnknownField::TYPE_VARINT:
            printf(" %d varint %ld\n", __FIELD(i).number(), __FIELD(i).varint());
            break;
          case ::google::protobuf::UnknownField::TYPE_FIXED32:
            printf(" %d fixed32 %d\n", __FIELD(i).number(), __FIELD(i).fixed32());
            break;
          case ::google::protobuf::UnknownField::TYPE_FIXED64:
            printf(" %d fixed64 %ld\n", __FIELD(i).number(), __FIELD(i).fixed64());
            break;
          case ::google::protobuf::UnknownField::TYPE_LENGTH_DELIMITED:
            printf(" %d length %d\n", __FIELD(i).number(), (int) __FIELD(i).length_delimited().size());
            break;
          case ::google::protobuf::UnknownField::TYPE_GROUP:
            printf(" %d group\n", __FIELD(i).number());
            // FIXME recurse
            break;
          default:
            printf(" %d unknown\n", __FIELD(i).number());
            break;
        };
    }

    // Finally, reply. Reserialize to test encoding consistency.
    std::string return_payload;
    bool serialized_success = msg.SerializeToString(&return_payload);
    strm->send(Sirikata::MemoryReference(return_payload.data(), return_payload.size()), Sirikata::Network::ReliableOrdered);
}

void handleReadySend(Sirikata::Network::Stream* strm) {
}

int main(int argc, char** argv) {
    using namespace Sirikata;
    using std::tr1::placeholders::_1;
    using std::tr1::placeholders::_2;

    InitOptions();
    ParseOptions(argc, argv);

    PluginManager plugins;
    plugins.loadList( GetOptionValue<String>(OPT_PLUGINS) );

    Network::IOService* ios = Network::IOServiceFactory::makeIOService();

    String stream_type = GetOptionValue<String>("ohstreamlib");
    String stream_opts = GetOptionValue<String>("ohstreamoptions");

    Sirikata::Network::StreamListener* listener =
        Sirikata::Network::StreamListenerFactory::getSingleton()
        .getConstructor(stream_type)
        (ios,
            Sirikata::Network::StreamListenerFactory::getSingleton()
            .getOptionParser(stream_type)
            (stream_opts));
    Sirikata::Network::Address addr("localhost", "9999");
    listener->listen(
        addr,
        std::tr1::bind(handleNewConnection,_1,_2)
    );

    Sirikata::Network::StreamListener* pbj_listener =
        Sirikata::Network::StreamListenerFactory::getSingleton()
        .getConstructor(stream_type)
        (ios,
            Sirikata::Network::StreamListenerFactory::getSingleton()
            .getOptionParser(stream_type)
            (stream_opts));
    Sirikata::Network::Address pbj_addr("localhost", "9998");
    pbj_listener->listen(
        pbj_addr,
        std::tr1::bind(handleNewPBJConnection,_1,_2)
    );

    ios->run();

    Network::IOServiceFactory::destroyIOService(ios);

    return 0;
}
<commit_msg>Build fix for Mac, where std::vector doesn't have data().<commit_after>/*  Sirikata
 *  StreamEcho.cpp
 *
 *  Copyright (c) 2010, Ewen Cheslack-Postava
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of Sirikata nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <sirikata/core/util/Platform.hpp>
#include <sirikata/core/network/Stream.hpp>
#include <sirikata/core/network/StreamListener.hpp>
#include <sirikata/core/network/StreamListenerFactory.hpp>
#include <sirikata/core/options/CommonOptions.hpp>
#include <sirikata/core/util/PluginManager.hpp>
#include <sirikata/core/network/IOServiceFactory.hpp>
#include <sirikata/core/network/IOService.hpp>

#include "Protocol_Empty.pbj.hpp"

void handleConnectionEvent(Sirikata::Network::Stream* strm, Sirikata::Network::Stream::ConnectionStatus, const std::string&reason);
void handleSubstream(Sirikata::Network::Stream* substream, Sirikata::Network::Stream::SetCallbacks&);
void handlePBJSubstream(Sirikata::Network::Stream* substream, Sirikata::Network::Stream::SetCallbacks&);
void handleReceived(Sirikata::Network::Stream* strm, Sirikata::Network::Chunk& payload, const Sirikata::Network::Stream::PauseReceiveCallback& pausecb);
void handlePBJReceived(Sirikata::Network::Stream* strm, Sirikata::Network::Chunk& payload, const Sirikata::Network::Stream::PauseReceiveCallback& pausecb);
void handleReadySend(Sirikata::Network::Stream* strm);

void handleNewConnection(Sirikata::Network::Stream* strm, Sirikata::Network::Stream::SetCallbacks& sc) {
    printf("Received connection\n");
    // Do same for main connection stream and substreams
    handleSubstream(strm, sc);
}

void handleNewPBJConnection(Sirikata::Network::Stream* strm, Sirikata::Network::Stream::SetCallbacks& sc) {
    printf("Received PBJ connection\n");
    // Do same for main connection stream and substreams
    handlePBJSubstream(strm, sc);
}

void handleConnectionEvent(Sirikata::Network::Stream* strm, Sirikata::Network::Stream::ConnectionStatus status, const std::string&reason) {
    if (status == Sirikata::Network::Stream::Disconnected)
        printf("Stream disconnected\n");
}

void handleSubstream(Sirikata::Network::Stream* substream, Sirikata::Network::Stream::SetCallbacks& sc) {
    using std::tr1::placeholders::_1;
    using std::tr1::placeholders::_2;

    printf("New substream\n");
    sc(
        std::tr1::bind(handleConnectionEvent, substream, _1, _2),
        std::tr1::bind(handleReceived, substream, _1, _2),
        std::tr1::bind(handleReadySend, substream)
    );
}

void handlePBJSubstream(Sirikata::Network::Stream* substream, Sirikata::Network::Stream::SetCallbacks& sc) {
    using std::tr1::placeholders::_1;
    using std::tr1::placeholders::_2;

    printf("New PBJ substream\n");
    sc(
        std::tr1::bind(handleConnectionEvent, substream, _1, _2),
        std::tr1::bind(handlePBJReceived, substream, _1, _2),
        std::tr1::bind(handleReadySend, substream)
    );
}

void handleReceived(Sirikata::Network::Stream* strm, Sirikata::Network::Chunk& payload, const Sirikata::Network::Stream::PauseReceiveCallback& pausecb) {
    printf("Received %d bytes\n", (int)payload.size());
    strm->send(payload, Sirikata::Network::ReliableOrdered);
}

void handlePBJReceived(Sirikata::Network::Stream* strm, Sirikata::Network::Chunk& payload, const Sirikata::Network::Stream::PauseReceiveCallback& pausecb) {
    printf("Received %d PBJ bytes: ", (int)payload.size());

    Sirikata::Protocol::Empty msg;
    if (!msg.ParseFromArray(&payload[0], payload.size())) {
        printf(" parsing PBJ failed.\n");
        // Indicate error to other side
        const char* error_msg = "Error"; // "Error" in base 64
        strm->send(Sirikata::MemoryReference(error_msg, strlen(error_msg)), Sirikata::Network::ReliableOrdered);
        return;
    }

    printf("%d fields\n", msg.unknown_fields().field_count());

    for(int i = 0; i < msg.unknown_fields().field_count(); i++) {
#define __FIELD(i) msg.unknown_fields().field(i)
        switch(__FIELD(i).type()) {
          case ::google::protobuf::UnknownField::TYPE_VARINT:
            printf(" %d varint %ld\n", __FIELD(i).number(), __FIELD(i).varint());
            break;
          case ::google::protobuf::UnknownField::TYPE_FIXED32:
            printf(" %d fixed32 %d\n", __FIELD(i).number(), __FIELD(i).fixed32());
            break;
          case ::google::protobuf::UnknownField::TYPE_FIXED64:
            printf(" %d fixed64 %ld\n", __FIELD(i).number(), __FIELD(i).fixed64());
            break;
          case ::google::protobuf::UnknownField::TYPE_LENGTH_DELIMITED:
            printf(" %d length %d\n", __FIELD(i).number(), (int) __FIELD(i).length_delimited().size());
            break;
          case ::google::protobuf::UnknownField::TYPE_GROUP:
            printf(" %d group\n", __FIELD(i).number());
            // FIXME recurse
            break;
          default:
            printf(" %d unknown\n", __FIELD(i).number());
            break;
        };
    }

    // Finally, reply. Reserialize to test encoding consistency.
    std::string return_payload;
    bool serialized_success = msg.SerializeToString(&return_payload);
    strm->send(Sirikata::MemoryReference(return_payload.data(), return_payload.size()), Sirikata::Network::ReliableOrdered);
}

void handleReadySend(Sirikata::Network::Stream* strm) {
}

int main(int argc, char** argv) {
    using namespace Sirikata;
    using std::tr1::placeholders::_1;
    using std::tr1::placeholders::_2;

    InitOptions();
    ParseOptions(argc, argv);

    PluginManager plugins;
    plugins.loadList( GetOptionValue<String>(OPT_PLUGINS) );

    Network::IOService* ios = Network::IOServiceFactory::makeIOService();

    String stream_type = GetOptionValue<String>("ohstreamlib");
    String stream_opts = GetOptionValue<String>("ohstreamoptions");

    Sirikata::Network::StreamListener* listener =
        Sirikata::Network::StreamListenerFactory::getSingleton()
        .getConstructor(stream_type)
        (ios,
            Sirikata::Network::StreamListenerFactory::getSingleton()
            .getOptionParser(stream_type)
            (stream_opts));
    Sirikata::Network::Address addr("localhost", "9999");
    listener->listen(
        addr,
        std::tr1::bind(handleNewConnection,_1,_2)
    );

    Sirikata::Network::StreamListener* pbj_listener =
        Sirikata::Network::StreamListenerFactory::getSingleton()
        .getConstructor(stream_type)
        (ios,
            Sirikata::Network::StreamListenerFactory::getSingleton()
            .getOptionParser(stream_type)
            (stream_opts));
    Sirikata::Network::Address pbj_addr("localhost", "9998");
    pbj_listener->listen(
        pbj_addr,
        std::tr1::bind(handleNewPBJConnection,_1,_2)
    );

    ios->run();

    Network::IOServiceFactory::destroyIOService(ios);

    return 0;
}
<|endoftext|>


<commit_before>/*
 * W.J. van der Laan 2011-2012
 */
#include "bitcoingui.h"
#include "clientmodel.h"
#include "walletmodel.h"
#include "optionsmodel.h"
#include "guiutil.h"
#include "guiconstants.h"

#include "init.h"
#include "ui_interface.h"
#include "qtipcserver.h"

#include <QApplication>
#include <QMessageBox>
#include <QTextCodec>
#include <QLocale>
#include <QTranslator>
#include <QSplashScreen>
#include <QLibraryInfo>

#if defined(BITCOIN_NEED_QT_PLUGINS) && !defined(_BITCOIN_QT_PLUGINS_INCLUDED)
#define _BITCOIN_QT_PLUGINS_INCLUDED
#define __INSURE__
#include <QtPlugin>
Q_IMPORT_PLUGIN(qcncodecs)
Q_IMPORT_PLUGIN(qjpcodecs)
Q_IMPORT_PLUGIN(qtwcodecs)
Q_IMPORT_PLUGIN(qkrcodecs)
Q_IMPORT_PLUGIN(qtaccessiblewidgets)
#endif

// Need a global reference for the notifications to find the GUI
static BitcoinGUI *guiref;
static QSplashScreen *splashref;

static void ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style)
{
    // Message from network thread
    if(guiref)
    {
        bool modal = (style & CClientUIInterface::MODAL);
        // in case of modal message, use blocking connection to wait for user to click OK
        QMetaObject::invokeMethod(guiref, "error",
                                   modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
                                   Q_ARG(QString, QString::fromStdString(caption)),
                                   Q_ARG(QString, QString::fromStdString(message)),
                                   Q_ARG(bool, modal));
    }
    else
    {
        printf("%s: %s\n", caption.c_str(), message.c_str());
        fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str());
    }
}

static bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption)
{
    if(!guiref)
        return false;
    if(nFeeRequired < MIN_TX_FEE || nFeeRequired <= nTransactionFee || fDaemon)
        return true;
    bool payFee = false;

    QMetaObject::invokeMethod(guiref, "askFee", GUIUtil::blockingGUIThreadConnection(),
                               Q_ARG(qint64, nFeeRequired),
                               Q_ARG(bool*, &payFee));

    return payFee;
}

static void ThreadSafeHandleURI(const std::string& strURI)
{
    if(!guiref)
        return;

    QMetaObject::invokeMethod(guiref, "handleURI", GUIUtil::blockingGUIThreadConnection(),
                               Q_ARG(QString, QString::fromStdString(strURI)));
}

static void InitMessage(const std::string &message)
{
    if(splashref)
    {
        splashref->showMessage(QString::fromStdString(message), Qt::AlignBottom|Qt::AlignHCenter, QColor(255,255,200));
        QApplication::instance()->processEvents();
    }
}

static void QueueShutdown()
{
    QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection);
}

/*
   Translate string to current locale using Qt.
 */
static std::string Translate(const char* psz)
{
    return QCoreApplication::translate("bitcoin-core", psz).toStdString();
}

/* Handle runaway exceptions. Shows a message box with the problem and quits the program.
 */
static void handleRunawayException(std::exception *e)
{
    PrintExceptionContinue(e, "Runaway exception");
    QMessageBox::critical(0, "Runaway exception", BitcoinGUI::tr("A fatal error occurred. YbCoin can no longer continue safely and will quit.") + QString("\n\n") + QString::fromStdString(strMiscWarning));
    exit(1);
}

#ifndef BITCOIN_QT_TEST
int main(int argc, char *argv[])
{
    // Do this early as we don't want to bother initializing if we are just calling IPC
    ipcScanRelay(argc, argv);

    // Internal string conversion is all UTF-8
    QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
    QTextCodec::setCodecForCStrings(QTextCodec::codecForTr());

    Q_INIT_RESOURCE(bitcoin);
    QApplication app(argc, argv);

    // Install global event filter that makes sure that long tooltips can be word-wrapped
    app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));

    // Command-line options take precedence:
    ParseParameters(argc, argv);

    // ... then bitcoin.conf:
    if (!boost::filesystem::is_directory(GetDataDir(false)))
    {
        // This message can not be translated, as translation is not initialized yet
        // (which not yet possible because lang=XX can be overridden in bitcoin.conf in the data directory)
        QMessageBox::critical(0, "YbCoin",
                              QString("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(mapArgs["-datadir"])));
        return 1;
    }
    ReadConfigFile(mapArgs, mapMultiArgs);

    // Application identification (must be set before OptionsModel is initialized,
    // as it is used to locate QSettings)
    app.setOrganizationName("YbCoin");
    app.setOrganizationDomain("ybcoin.org");
    if(GetBoolArg("-testnet")) // Separate UI settings for testnet
        app.setApplicationName("YbCoin-Qt-testnet");
    else
        app.setApplicationName("YbCoin-Qt");

    // ... then GUI settings:
    OptionsModel optionsModel;

    // Get desired locale (e.g. "de_DE") from command line or use system locale
    QString lang_territory = QString::fromStdString(GetArg("-lang", QLocale::system().name().toStdString()));
    QString lang = lang_territory;
    // Convert to "de" only by truncating "_DE"
    lang.truncate(lang_territory.lastIndexOf('_'));

    QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
    // Load language files for configured locale:
    // - First load the translator for the base language, without territory
    // - Then load the more specific locale translator

    // Load e.g. qt_de.qm
    if (qtTranslatorBase.load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
        app.installTranslator(&qtTranslatorBase);

    // Load e.g. qt_de_DE.qm
    if (qtTranslator.load("qt_" + lang_territory, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
        app.installTranslator(&qtTranslator);

    // Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc)
    if (translatorBase.load(lang, ":/translations/"))
        app.installTranslator(&translatorBase);

    // Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in bitcoin.qrc)
    if (translator.load(lang_territory, ":/translations/"))
        app.installTranslator(&translator);

    // Subscribe to global signals from core
    uiInterface.ThreadSafeMessageBox.connect(ThreadSafeMessageBox);
    uiInterface.ThreadSafeAskFee.connect(ThreadSafeAskFee);
    uiInterface.ThreadSafeHandleURI.connect(ThreadSafeHandleURI);
    uiInterface.InitMessage.connect(InitMessage);
    uiInterface.QueueShutdown.connect(QueueShutdown);
    uiInterface.Translate.connect(Translate);

    // Show help message immediately after parsing command-line options (for "-lang") and setting locale,
    // but before showing splash screen.
    if (mapArgs.count("-?") || mapArgs.count("--help"))
    {
        GUIUtil::HelpMessageBox help;
        help.showOrPrint();
        return 1;
    }

    QSplashScreen splash(QPixmap(":/images/splash"), 0);
    if (GetBoolArg("-splash", true) && !GetBoolArg("-min"))
    {
        splash.show();
        splash.setAutoFillBackground(true);
        splashref = &splash;
    }

    app.processEvents();

    app.setQuitOnLastWindowClosed(false);

    try
    {
        // Regenerate startup link, to fix links to old versions
        if (GUIUtil::GetStartOnSystemStartup())
            GUIUtil::SetStartOnSystemStartup(true);

        BitcoinGUI window;
        guiref = &window;
        if(AppInit2())
        {
            {
                // Put this in a block, so that the Model objects are cleaned up before
                // calling Shutdown().

                optionsModel.Upgrade(); // Must be done after AppInit2

                if (splashref)
                    splash.finish(&window);

                ClientModel clientModel(&optionsModel);
                WalletModel walletModel(pwalletMain, &optionsModel);

                window.setClientModel(&clientModel);
                window.setWalletModel(&walletModel);

                // If -min option passed, start window minimized.
                if(GetBoolArg("-min"))
                {
                    window.showMinimized();
                }
                else
                {
                    window.show();
                }

                // Place this here as guiref has to be defined if we don't want to lose URIs
                ipcInit(argc, argv);

                app.exec();

                window.hide();
                window.setClientModel(0);
                window.setWalletModel(0);
                guiref = 0;
            }
            // Shutdown the core and its threads, but don't exit Bitcoin-Qt here
            Shutdown(NULL);
        }
        else
        {
            return 1;
        }
    } catch (std::exception& e) {
        handleRunawayException(&e);
    } catch (...) {
        handleRunawayException(NULL);
    }
    return 0;
}
#endif // BITCOIN_QT_TEST
<commit_msg>Fix:initial splash window failed<commit_after>/*
 * W.J. van der Laan 2011-2012
 */
#include "bitcoingui.h"
#include "clientmodel.h"
#include "walletmodel.h"
#include "optionsmodel.h"
#include "guiutil.h"
#include "guiconstants.h"

#include "init.h"
#include "ui_interface.h"
#include "qtipcserver.h"

#include <QApplication>
#include <QMessageBox>
#include <QTextCodec>
#include <QLocale>
#include <QTranslator>
#include <QSplashScreen>
#include <QLibraryInfo>

#if defined(BITCOIN_NEED_QT_PLUGINS) && !defined(_BITCOIN_QT_PLUGINS_INCLUDED)
#define _BITCOIN_QT_PLUGINS_INCLUDED
#define __INSURE__
#include <QtPlugin>
Q_IMPORT_PLUGIN(qcncodecs)
Q_IMPORT_PLUGIN(qjpcodecs)
Q_IMPORT_PLUGIN(qtwcodecs)
Q_IMPORT_PLUGIN(qkrcodecs)
Q_IMPORT_PLUGIN(qtaccessiblewidgets)
#endif

// Need a global reference for the notifications to find the GUI
static BitcoinGUI *guiref;
static QSplashScreen *splashref;

static void ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style)
{
    // Message from network thread
    if(guiref)
    {
        bool modal = (style & CClientUIInterface::MODAL);
        // in case of modal message, use blocking connection to wait for user to click OK
        QMetaObject::invokeMethod(guiref, "error",
                                   modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
                                   Q_ARG(QString, QString::fromStdString(caption)),
                                   Q_ARG(QString, QString::fromStdString(message)),
                                   Q_ARG(bool, modal));
    }
    else
    {
        printf("%s: %s\n", caption.c_str(), message.c_str());
        fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str());
    }
}

static bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption)
{
    if(!guiref)
        return false;
    if(nFeeRequired < MIN_TX_FEE || nFeeRequired <= nTransactionFee || fDaemon)
        return true;
    bool payFee = false;

    QMetaObject::invokeMethod(guiref, "askFee", GUIUtil::blockingGUIThreadConnection(),
                               Q_ARG(qint64, nFeeRequired),
                               Q_ARG(bool*, &payFee));

    return payFee;
}

static void ThreadSafeHandleURI(const std::string& strURI)
{
    if(!guiref)
        return;

    QMetaObject::invokeMethod(guiref, "handleURI", GUIUtil::blockingGUIThreadConnection(),
                               Q_ARG(QString, QString::fromStdString(strURI)));
}

static void InitMessage(const std::string &message)
{
    if(splashref)
    {
        splashref->showMessage(QString::fromStdString(message), Qt::AlignBottom|Qt::AlignHCenter, QColor(255,255,200));
        QApplication::instance()->processEvents();
    }
}

static void QueueShutdown()
{
    QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection);
}

/*
   Translate string to current locale using Qt.
 */
static std::string Translate(const char* psz)
{
    return QCoreApplication::translate("bitcoin-core", psz).toStdString();
}

/* Handle runaway exceptions. Shows a message box with the problem and quits the program.
 */
static void handleRunawayException(std::exception *e)
{
    PrintExceptionContinue(e, "Runaway exception");
    QMessageBox::critical(0, "Runaway exception", BitcoinGUI::tr("A fatal error occurred. YbCoin can no longer continue safely and will quit.") + QString("\n\n") + QString::fromStdString(strMiscWarning));
    exit(1);
}

#ifndef BITCOIN_QT_TEST
int main(int argc, char *argv[])
{
    // Do this early as we don't want to bother initializing if we are just calling IPC
    ipcScanRelay(argc, argv);

    // Internal string conversion is all UTF-8
    QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
    QTextCodec::setCodecForCStrings(QTextCodec::codecForTr());

    Q_INIT_RESOURCE(bitcoin);
    QApplication app(argc, argv);

    // Install global event filter that makes sure that long tooltips can be word-wrapped
    app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));

    // Command-line options take precedence:
    ParseParameters(argc, argv);

    // ... then bitcoin.conf:
    if (!boost::filesystem::is_directory(GetDataDir(false)))
    {
        // This message can not be translated, as translation is not initialized yet
        // (which not yet possible because lang=XX can be overridden in bitcoin.conf in the data directory)
        QMessageBox::critical(0, "YbCoin",
                              QString("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(mapArgs["-datadir"])));
        return 1;
    }
    ReadConfigFile(mapArgs, mapMultiArgs);

    // Application identification (must be set before OptionsModel is initialized,
    // as it is used to locate QSettings)
    app.setOrganizationName("YbCoin");
    app.setOrganizationDomain("ybcoin.org");
    if(GetBoolArg("-testnet")) // Separate UI settings for testnet
        app.setApplicationName("YbCoin-Qt-testnet");
    else
        app.setApplicationName("YbCoin-Qt");

    // ... then GUI settings:
    OptionsModel optionsModel;

    // Get desired locale (e.g. "de_DE") from command line or use system locale
    QString lang_territory = QString::fromStdString(GetArg("-lang", QLocale::system().name().toStdString()));
    QString lang = lang_territory;
    // Convert to "de" only by truncating "_DE"
    lang.truncate(lang_territory.lastIndexOf('_'));

    QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
    // Load language files for configured locale:
    // - First load the translator for the base language, without territory
    // - Then load the more specific locale translator

    // Load e.g. qt_de.qm
    if (qtTranslatorBase.load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
        app.installTranslator(&qtTranslatorBase);

    // Load e.g. qt_de_DE.qm
    if (qtTranslator.load("qt_" + lang_territory, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
        app.installTranslator(&qtTranslator);

    // Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc)
    if (translatorBase.load(lang, ":/translations/"))
        app.installTranslator(&translatorBase);

    // Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in bitcoin.qrc)
    if (translator.load(lang_territory, ":/translations/"))
        app.installTranslator(&translator);

    // Subscribe to global signals from core
    uiInterface.ThreadSafeMessageBox.connect(ThreadSafeMessageBox);
    uiInterface.ThreadSafeAskFee.connect(ThreadSafeAskFee);
    uiInterface.ThreadSafeHandleURI.connect(ThreadSafeHandleURI);
    uiInterface.InitMessage.connect(InitMessage);
    uiInterface.QueueShutdown.connect(QueueShutdown);
    uiInterface.Translate.connect(Translate);

    // Show help message immediately after parsing command-line options (for "-lang") and setting locale,
    // but before showing splash screen.
    if (mapArgs.count("-?") || mapArgs.count("--help"))
    {
        GUIUtil::HelpMessageBox help;
        help.showOrPrint();
        return 1;
    }

    QImage img(":/images/splash");
    QPixmap amap = QPixmap::fromImage(img);
    QSplashScreen splash(amap);
    if (GetBoolArg("-splash", true) && !GetBoolArg("-min"))
    {
        splash.show();
        splash.setAutoFillBackground(true);
        splashref = &splash;
    }

    app.processEvents();
    app.setQuitOnLastWindowClosed(false);

    try
    {
        // Regenerate startup link, to fix links to old versions
        if (GUIUtil::GetStartOnSystemStartup())
            GUIUtil::SetStartOnSystemStartup(true);

        BitcoinGUI window;
        guiref = &window;
        if(AppInit2())
        {
            {
                // Put this in a block, so that the Model objects are cleaned up before
                // calling Shutdown().

                optionsModel.Upgrade(); // Must be done after AppInit2

                if (splashref)
                    splash.finish(&window);

                ClientModel clientModel(&optionsModel);
                WalletModel walletModel(pwalletMain, &optionsModel);

                window.setClientModel(&clientModel);
                window.setWalletModel(&walletModel);

                // If -min option passed, start window minimized.
                if(GetBoolArg("-min"))
                {
                    window.showMinimized();
                }
                else
                {
                    window.show();
                }

                // Place this here as guiref has to be defined if we don't want to lose URIs
                ipcInit(argc, argv);

                app.exec();

                window.hide();
                window.setClientModel(0);
                window.setWalletModel(0);
                guiref = 0;
            }
            // Shutdown the core and its threads, but don't exit Bitcoin-Qt here
            Shutdown(NULL);
        }
        else
        {
            return 1;
        }
    } catch (std::exception& e) {
        handleRunawayException(&e);
    } catch (...) {
        handleRunawayException(NULL);
    }
    return 0;
}
#endif // BITCOIN_QT_TEST
<|endoftext|>


<commit_before>/*
 * Copyright 2011, Blender Foundation.
 *
 * This program 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 2
 * of the License, or (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "background.h"
#include "buffers.h"
#include "camera.h"
#include "device.h"
#include "integrator.h"
#include "film.h"
#include "light.h"
#include "scene.h"
#include "session.h"
#include "shader.h"

#include "util_color.h"
#include "util_foreach.h"
#include "util_function.h"
#include "util_progress.h"
#include "util_time.h"

#include "blender_sync.h"
#include "blender_session.h"
#include "blender_util.h"

CCL_NAMESPACE_BEGIN

BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::Scene b_scene_)
: b_engine(b_engine_), b_data(b_data_), b_scene(b_scene_), b_v3d(PointerRNA_NULL), b_rv3d(PointerRNA_NULL),
  b_rr(PointerRNA_NULL), b_rlay(PointerRNA_NULL)
{
	/* offline render */
	BL::RenderSettings r = b_scene.render();

	width = (int)(r.resolution_x()*r.resolution_percentage()*0.01f);
	height = (int)(r.resolution_y()*r.resolution_percentage()*0.01f);
	background = true;
	last_redraw_time = 0.0f;

	create_session();
}

BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::Scene b_scene_,
	BL::SpaceView3D b_v3d_, BL::RegionView3D b_rv3d_, int width_, int height_)
: b_engine(b_engine_), b_data(b_data_), b_scene(b_scene_), b_v3d(b_v3d_), b_rv3d(b_rv3d_),
  b_rr(PointerRNA_NULL), b_rlay(PointerRNA_NULL)
{
	/* 3d view render */
	width = width_;
	height = height_;
	background = false;
	last_redraw_time = 0.0f;

	create_session();
	session->start();
}

BlenderSession::~BlenderSession()
{
	free_session();
}

void BlenderSession::create_session()
{
	SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
	SessionParams session_params = BlenderSync::get_session_params(b_scene, background);

	/* reset status/progress */
	last_status= "";
	last_progress= -1.0f;

	/* create scene */
	scene = new Scene(scene_params);

	/* create sync */
	sync = new BlenderSync(b_data, b_scene, scene, !background);
	sync->sync_data(b_v3d);

	if(b_rv3d)
		sync->sync_view(b_v3d, b_rv3d, width, height);
	else
		sync->sync_camera(width, height);

	/* create session */
	session = new Session(session_params);
	session->scene = scene;
	session->progress.set_update_callback(function_bind(&BlenderSession::tag_redraw, this));
	session->progress.set_cancel_callback(function_bind(&BlenderSession::test_cancel, this));
	session->set_pause(BlenderSync::get_session_pause(b_scene, background));

	/* set buffer parameters */
	BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);
	session->reset(buffer_params, session_params.samples);
}

void BlenderSession::free_session()
{
	delete sync;
	delete session;
}

void BlenderSession::render()
{
	/* get buffer parameters */
	BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);
	int w = buffer_params.width, h = buffer_params.height;

	/* create render result */
	RenderResult *rrp = RE_engine_begin_result((RenderEngine*)b_engine.ptr.data, 0, 0, w, h);
	PointerRNA rrptr;
	RNA_pointer_create(NULL, &RNA_RenderResult, rrp, &rrptr);
	b_rr = BL::RenderResult(rrptr);

	BL::RenderSettings r = b_scene.render();
	BL::RenderResult::layers_iterator b_iter;
	BL::RenderLayers b_rr_layers(r.ptr);

	int active = 0;

	/* render each layer */
	for(b_rr.layers.begin(b_iter); b_iter != b_rr.layers.end(); ++b_iter, ++active) {
		/* single layer render */
		if(r.use_single_layer())
			active = b_rr_layers.active_index();

		/* set layer */
		b_rlay = *b_iter;

		/* update scene */
		sync->sync_data(b_v3d, active);

		/* render */
		session->start();
		session->wait();

		if(session->progress.get_cancel())
			break;

		/* write result */
		write_render_result();
	}

	/* delete render result */
	RE_engine_end_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data);
}

void BlenderSession::write_render_result()
{
	/* get state */
	RenderBuffers *buffers = session->buffers;
	float exposure = scene->film->exposure;
	double total_time, sample_time;
	int sample;
	session->progress.get_sample(sample, total_time, sample_time);

	/* get pixels */
	float4 *pixels = buffers->copy_from_device(exposure, sample);

	if(!pixels)
		return;

	/* write pixels */
	rna_RenderLayer_rect_set(&b_rlay.ptr, (float*)pixels);
	RE_engine_update_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data);

	delete [] pixels;
}

void BlenderSession::synchronize()
{
	/* on session/scene parameter changes, we recreate session entirely */
	SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
	SessionParams session_params = BlenderSync::get_session_params(b_scene, background);

	if(session->params.modified(session_params) ||
	   scene->params.modified(scene_params)) {
		free_session();
		create_session();
		session->start();
		return;
	}

	/* increase samples, but never decrease */
	session->set_samples(session_params.samples);
	session->set_pause(BlenderSync::get_session_pause(b_scene, background));

	/* copy recalc flags, outside of mutex so we can decide to do the real
	   synchronization at a later time to not block on running updates */
	sync->sync_recalc();

	/* try to acquire mutex. if we don't want to or can't, come back later */
	if(!session->ready_to_reset() || !session->scene->mutex.try_lock()) {
		tag_update();
		return;
	}

	/* data and camera synchronize */
	sync->sync_data(b_v3d);

	if(b_rv3d)
		sync->sync_view(b_v3d, b_rv3d, width, height);
	else
		sync->sync_camera(width, height);

	/* unlock */
	session->scene->mutex.unlock();

	/* reset if needed */
	if(scene->need_reset()) {
		BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);
		session->reset(buffer_params, session_params.samples);
	}
}

bool BlenderSession::draw(int w, int h)
{
	/* before drawing, we verify camera and viewport size changes, because
	   we do not get update callbacks for those, we must detect them here */
	if(session->ready_to_reset()) {
		bool reset = false;

		/* try to acquire mutex. if we can't, come back later */
		if(!session->scene->mutex.try_lock()) {
			tag_update();
		}
		else {
			/* update camera from 3d view */
			bool need_update = scene->camera->need_update;

			sync->sync_view(b_v3d, b_rv3d, w, h);

			if(scene->camera->need_update && !need_update)
				reset = true;

			session->scene->mutex.unlock();
		}

		/* if dimensions changed, reset */
		if(width != w || height != h) {
			width = w;
			height = h;
			reset = true;
		}

		/* reset if requested */
		if(reset) {
			SessionParams session_params = BlenderSync::get_session_params(b_scene, background);
			BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);

			session->reset(buffer_params, session_params.samples);
		}
	}

	/* update status and progress for 3d view draw */
	update_status_progress();

	/* draw */
	BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);

	return !session->draw(buffer_params);
}

void BlenderSession::get_status(string& status, string& substatus)
{
	session->progress.get_status(status, substatus);
}

void BlenderSession::get_progress(float& progress, double& total_time)
{
	double sample_time;
	int sample;

	session->progress.get_sample(sample, total_time, sample_time);
	progress = ((float)sample/(float)session->params.samples);
}

void BlenderSession::update_status_progress()
{
	string status, substatus;
	float progress;
	double total_time;
	char time_str[128];

	get_status(status, substatus);
	get_progress(progress, total_time);

	if(!background) {
		BLI_timestr(total_time, time_str);
		status = "Time: " + string(time_str) + " | " + status;
	}

	if(substatus.size() > 0)
		status += " | " + substatus;

	if(status != last_status) {
		RE_engine_update_stats((RenderEngine*)b_engine.ptr.data, "", status.c_str());
		last_status = status;
	}
	if(progress != last_progress) {
		RE_engine_update_progress((RenderEngine*)b_engine.ptr.data, progress);
		last_progress = progress;
	}
}

void BlenderSession::tag_update()
{
	/* tell blender that we want to get another update callback */
	engine_tag_update((RenderEngine*)b_engine.ptr.data);
}

void BlenderSession::tag_redraw()
{
	if(background) {
		/* update stats and progress, only for background here because
		   in 3d view we do it in draw for thread safety reasons */
		update_status_progress();

		/* offline render, redraw if timeout passed */
		if(time_dt() - last_redraw_time > 1.0f) {
			write_render_result();
			engine_tag_redraw((RenderEngine*)b_engine.ptr.data);
			last_redraw_time = time_dt();
		}
	}
	else {
		/* tell blender that we want to redraw */
		engine_tag_redraw((RenderEngine*)b_engine.ptr.data);
	}
}

void BlenderSession::test_cancel()
{
	/* test if we need to cancel rendering */
	if(background)
		if(RE_engine_test_break((RenderEngine*)b_engine.ptr.data))
			session->progress.set_cancel("Cancelled");
}

CCL_NAMESPACE_END

<commit_msg>Fix #29760: cycles border render issue on 32 bit linux.<commit_after>/*
 * Copyright 2011, Blender Foundation.
 *
 * This program 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 2
 * of the License, or (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "background.h"
#include "buffers.h"
#include "camera.h"
#include "device.h"
#include "integrator.h"
#include "film.h"
#include "light.h"
#include "scene.h"
#include "session.h"
#include "shader.h"

#include "util_color.h"
#include "util_foreach.h"
#include "util_function.h"
#include "util_progress.h"
#include "util_time.h"

#include "blender_sync.h"
#include "blender_session.h"
#include "blender_util.h"

CCL_NAMESPACE_BEGIN

BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::Scene b_scene_)
: b_engine(b_engine_), b_data(b_data_), b_scene(b_scene_), b_v3d(PointerRNA_NULL), b_rv3d(PointerRNA_NULL),
  b_rr(PointerRNA_NULL), b_rlay(PointerRNA_NULL)
{
	/* offline render */
	BL::RenderSettings r = b_scene.render();

	width = (int)(r.resolution_x()*r.resolution_percentage()/100);
	height = (int)(r.resolution_y()*r.resolution_percentage()/100);
	background = true;
	last_redraw_time = 0.0f;

	create_session();
}

BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::Scene b_scene_,
	BL::SpaceView3D b_v3d_, BL::RegionView3D b_rv3d_, int width_, int height_)
: b_engine(b_engine_), b_data(b_data_), b_scene(b_scene_), b_v3d(b_v3d_), b_rv3d(b_rv3d_),
  b_rr(PointerRNA_NULL), b_rlay(PointerRNA_NULL)
{
	/* 3d view render */
	width = width_;
	height = height_;
	background = false;
	last_redraw_time = 0.0f;

	create_session();
	session->start();
}

BlenderSession::~BlenderSession()
{
	free_session();
}

void BlenderSession::create_session()
{
	SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
	SessionParams session_params = BlenderSync::get_session_params(b_scene, background);

	/* reset status/progress */
	last_status= "";
	last_progress= -1.0f;

	/* create scene */
	scene = new Scene(scene_params);

	/* create sync */
	sync = new BlenderSync(b_data, b_scene, scene, !background);
	sync->sync_data(b_v3d);

	if(b_rv3d)
		sync->sync_view(b_v3d, b_rv3d, width, height);
	else
		sync->sync_camera(width, height);

	/* create session */
	session = new Session(session_params);
	session->scene = scene;
	session->progress.set_update_callback(function_bind(&BlenderSession::tag_redraw, this));
	session->progress.set_cancel_callback(function_bind(&BlenderSession::test_cancel, this));
	session->set_pause(BlenderSync::get_session_pause(b_scene, background));

	/* set buffer parameters */
	BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);
	session->reset(buffer_params, session_params.samples);
}

void BlenderSession::free_session()
{
	delete sync;
	delete session;
}

void BlenderSession::render()
{
	/* get buffer parameters */
	BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);
	int w = buffer_params.width, h = buffer_params.height;

	/* create render result */
	RenderResult *rrp = RE_engine_begin_result((RenderEngine*)b_engine.ptr.data, 0, 0, w, h);
	PointerRNA rrptr;
	RNA_pointer_create(NULL, &RNA_RenderResult, rrp, &rrptr);
	b_rr = BL::RenderResult(rrptr);

	BL::RenderSettings r = b_scene.render();
	BL::RenderResult::layers_iterator b_iter;
	BL::RenderLayers b_rr_layers(r.ptr);

	int active = 0;

	/* render each layer */
	for(b_rr.layers.begin(b_iter); b_iter != b_rr.layers.end(); ++b_iter, ++active) {
		/* single layer render */
		if(r.use_single_layer())
			active = b_rr_layers.active_index();

		/* set layer */
		b_rlay = *b_iter;

		/* update scene */
		sync->sync_data(b_v3d, active);

		/* render */
		session->start();
		session->wait();

		if(session->progress.get_cancel())
			break;

		/* write result */
		write_render_result();
	}

	/* delete render result */
	RE_engine_end_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data);
}

void BlenderSession::write_render_result()
{
	/* get state */
	RenderBuffers *buffers = session->buffers;
	float exposure = scene->film->exposure;
	double total_time, sample_time;
	int sample;
	session->progress.get_sample(sample, total_time, sample_time);

	/* get pixels */
	float4 *pixels = buffers->copy_from_device(exposure, sample);

	if(!pixels)
		return;

	/* write pixels */
	rna_RenderLayer_rect_set(&b_rlay.ptr, (float*)pixels);
	RE_engine_update_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data);

	delete [] pixels;
}

void BlenderSession::synchronize()
{
	/* on session/scene parameter changes, we recreate session entirely */
	SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
	SessionParams session_params = BlenderSync::get_session_params(b_scene, background);

	if(session->params.modified(session_params) ||
	   scene->params.modified(scene_params)) {
		free_session();
		create_session();
		session->start();
		return;
	}

	/* increase samples, but never decrease */
	session->set_samples(session_params.samples);
	session->set_pause(BlenderSync::get_session_pause(b_scene, background));

	/* copy recalc flags, outside of mutex so we can decide to do the real
	   synchronization at a later time to not block on running updates */
	sync->sync_recalc();

	/* try to acquire mutex. if we don't want to or can't, come back later */
	if(!session->ready_to_reset() || !session->scene->mutex.try_lock()) {
		tag_update();
		return;
	}

	/* data and camera synchronize */
	sync->sync_data(b_v3d);

	if(b_rv3d)
		sync->sync_view(b_v3d, b_rv3d, width, height);
	else
		sync->sync_camera(width, height);

	/* unlock */
	session->scene->mutex.unlock();

	/* reset if needed */
	if(scene->need_reset()) {
		BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);
		session->reset(buffer_params, session_params.samples);
	}
}

bool BlenderSession::draw(int w, int h)
{
	/* before drawing, we verify camera and viewport size changes, because
	   we do not get update callbacks for those, we must detect them here */
	if(session->ready_to_reset()) {
		bool reset = false;

		/* try to acquire mutex. if we can't, come back later */
		if(!session->scene->mutex.try_lock()) {
			tag_update();
		}
		else {
			/* update camera from 3d view */
			bool need_update = scene->camera->need_update;

			sync->sync_view(b_v3d, b_rv3d, w, h);

			if(scene->camera->need_update && !need_update)
				reset = true;

			session->scene->mutex.unlock();
		}

		/* if dimensions changed, reset */
		if(width != w || height != h) {
			width = w;
			height = h;
			reset = true;
		}

		/* reset if requested */
		if(reset) {
			SessionParams session_params = BlenderSync::get_session_params(b_scene, background);
			BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);

			session->reset(buffer_params, session_params.samples);
		}
	}

	/* update status and progress for 3d view draw */
	update_status_progress();

	/* draw */
	BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);

	return !session->draw(buffer_params);
}

void BlenderSession::get_status(string& status, string& substatus)
{
	session->progress.get_status(status, substatus);
}

void BlenderSession::get_progress(float& progress, double& total_time)
{
	double sample_time;
	int sample;

	session->progress.get_sample(sample, total_time, sample_time);
	progress = ((float)sample/(float)session->params.samples);
}

void BlenderSession::update_status_progress()
{
	string status, substatus;
	float progress;
	double total_time;
	char time_str[128];

	get_status(status, substatus);
	get_progress(progress, total_time);

	if(!background) {
		BLI_timestr(total_time, time_str);
		status = "Time: " + string(time_str) + " | " + status;
	}

	if(substatus.size() > 0)
		status += " | " + substatus;

	if(status != last_status) {
		RE_engine_update_stats((RenderEngine*)b_engine.ptr.data, "", status.c_str());
		last_status = status;
	}
	if(progress != last_progress) {
		RE_engine_update_progress((RenderEngine*)b_engine.ptr.data, progress);
		last_progress = progress;
	}
}

void BlenderSession::tag_update()
{
	/* tell blender that we want to get another update callback */
	engine_tag_update((RenderEngine*)b_engine.ptr.data);
}

void BlenderSession::tag_redraw()
{
	if(background) {
		/* update stats and progress, only for background here because
		   in 3d view we do it in draw for thread safety reasons */
		update_status_progress();

		/* offline render, redraw if timeout passed */
		if(time_dt() - last_redraw_time > 1.0f) {
			write_render_result();
			engine_tag_redraw((RenderEngine*)b_engine.ptr.data);
			last_redraw_time = time_dt();
		}
	}
	else {
		/* tell blender that we want to redraw */
		engine_tag_redraw((RenderEngine*)b_engine.ptr.data);
	}
}

void BlenderSession::test_cancel()
{
	/* test if we need to cancel rendering */
	if(background)
		if(RE_engine_test_break((RenderEngine*)b_engine.ptr.data))
			session->progress.set_cancel("Cancelled");
}

CCL_NAMESPACE_END

<|endoftext|>