<commit_before>// Copyright Hugh Perkins 2016

// 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 "cocl/cocl_events.h"

#include "cocl/cocl_error.h"
#include "cocl/cocl_defs.h"
#include "cocl/hostside_opencl_funcs.h"
#include "cocl/cocl_streams.h"
#include "cocl/cocl_context.h"

#include "EasyCL/EasyCL.h"

#include <iostream>
#include <memory>

using namespace std;
using namespace cocl;
using namespace easycl;

#ifdef COCL_SPAM
#undef COCL_PRINT
#define COCL_PRINT(x) std::cout << "[COCL] " << x << std::endl;
#endif

namespace cocl {
    CoclEvent::CoclEvent() {
        COCL_PRINT("CoclEvent() this=" << this);
        event = 0;
    }
    CoclEvent::~CoclEvent() {
        COCL_PRINT("~CoclEvent() this=" << this);
        if(event != 0) {
            COCL_PRINT("~CoclEvent() releasing underlying clevent " << event);
            clReleaseEvent(event);
        }
    }
}

// opencl:
// clCreateUserEvent()   CL_EVENT_COMMAND_ EXECUTION_STATUS
// clWaitForEvents(num_events, event_list);
// clEnqueueMarkerWithWaitList
// clGetEventInfo()
// clReleaseEvent

// cuda:
// cuEventCreate(CUCoclEvent *, flags)
// cuEventRecord(CUEvent, CUstream);  => puts into the stream
// cuEventQuery(CUevent)
// cuEventSynchronize(CUevent)
// cuEventDestroy

size_t cuEventCreate(CoclEvent **pevent, unsigned int flags) {
    CoclEvent *event = new CoclEvent();
    *pevent = event;
    COCL_PRINT("cuEventCreate flags=" << flags << " new CoclEvent=" << event);
    // throw runtime_error("fake stop");
    return 0;
}

size_t cuEventSynchronize(CoclEvent *event) {
    COCL_PRINT("cuEventSynchronize CoclEvent=" << event);
    cl_int err = clWaitForEvents(1, &event->event);
    EasyCL::checkError(err);
    return 0;
}

size_t cuEventRecord(CoclEvent *event, char *_queue) {
    CoclStream *coclStream = (CoclStream *)_queue;
    CLQueue *queue = coclStream->clqueue;
    // CLQueue *queue = (CLQueue *)_queue;
    COCL_PRINT("cuEventRecord CoclEvent=" << event << " queue=" << queue);
    if(queue == 0) {
        cout << "cuEventRecord not implemented for stream 0" << endl;
        throw runtime_error("cuEventRecord not implemented for stream 0");
    }
    cl_event clevent;
    cl_int err = clEnqueueMarkerWithWaitList(queue->queue, 0, 0, &clevent);
    COCL_PRINT("cuEventRecord CoclEvent=" << event << " created clevent=" << clevent);
    EasyCL::checkError(err);
    err = clFlush(queue->queue);
    EasyCL::checkError(err);
    event->event = clevent;
    return 0;
}

size_t cuEventQuery(CoclEvent *event) {
    COCL_PRINT("cuEventQuery CoclEvent=" << event << " clevent=" << event->event);
    cl_int res;
    cl_int err = clGetEventInfo (
        event->event,
        CL_EVENT_COMMAND_EXECUTION_STATUS,
        sizeof(cl_int),
        &res,
        0);
    COCL_PRINT("clGetEventInfo: " << res);
    EasyCL::checkError(err);
    if(res == CL_COMPLETE) { // success
        COCL_PRINT("cuEventQuery, event completed");
        return 0;
    } else if(res > 0) { // not finished yet
        COCL_PRINT("cuEventQuery, event not finished yet");
        return cudaErrorNotReady;
    } else { // error
        COCL_PRINT("cuEventQuery, event error");
        return 1;
    }
}

size_t cuEventDestroy_v2(CoclEvent *event) {
    COCL_PRINT("cuEventDestroy CoclEvent=" << event);
    delete event;
    return 0;
}
<commit_msg>fix crash bug on Mac OS X.<commit_after>// Copyright Hugh Perkins 2016

// 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 "cocl/cocl_events.h"

#include "cocl/cocl_error.h"
#include "cocl/cocl_defs.h"
#include "cocl/hostside_opencl_funcs.h"
#include "cocl/cocl_streams.h"
#include "cocl/cocl_context.h"

#include "EasyCL/EasyCL.h"

#include <iostream>
#include <memory>

using namespace std;
using namespace cocl;
using namespace easycl;

#ifdef COCL_SPAM
#undef COCL_PRINT
#define COCL_PRINT(x) std::cout << "[COCL] " << x << std::endl;
#endif

namespace cocl {
    CoclEvent::CoclEvent() {
        COCL_PRINT("CoclEvent() this=" << this);
        event = 0;
    }
    CoclEvent::~CoclEvent() {
        COCL_PRINT("~CoclEvent() this=" << this);
        if(event != 0) {
            COCL_PRINT("~CoclEvent() releasing underlying clevent " << event);
            clReleaseEvent(event);
        }
    }
}

// opencl:
// clCreateUserEvent()   CL_EVENT_COMMAND_ EXECUTION_STATUS
// clWaitForEvents(num_events, event_list);
// clEnqueueMarkerWithWaitList
// clGetEventInfo()
// clReleaseEvent

// cuda:
// cuEventCreate(CUCoclEvent *, flags)
// cuEventRecord(CUEvent, CUstream);  => puts into the stream
// cuEventQuery(CUevent)
// cuEventSynchronize(CUevent)
// cuEventDestroy

size_t cuEventCreate(CoclEvent **pevent, unsigned int flags) {
    CoclEvent *event = new CoclEvent();
    *pevent = event;
    COCL_PRINT("cuEventCreate flags=" << flags << " new CoclEvent=" << event);
    // throw runtime_error("fake stop");
    return 0;
}

size_t cuEventSynchronize(CoclEvent *event) {
    COCL_PRINT("cuEventSynchronize CoclEvent=" << event);
    cl_int err = clWaitForEvents(1, &event->event);
    EasyCL::checkError(err);
    return 0;
}

size_t cuEventRecord(CoclEvent *event, char *_queue) {
    CoclStream *coclStream = (CoclStream *)_queue;
    CLQueue *queue = coclStream->clqueue;
    // CLQueue *queue = (CLQueue *)_queue;
    COCL_PRINT("cuEventRecord CoclEvent=" << event << " queue=" << queue);
    if(queue == 0) {
        cout << "cuEventRecord not implemented for stream 0" << endl;
        throw runtime_error("cuEventRecord not implemented for stream 0");
    }
    if(event->event != 0) {
        COCL_PRINT("  cuEventRecord releasing existing clevent " << event->event);
        clReleaseEvent(event->event);
        event->event = 0;
        // cout << "cuEventRecrd event is already assigned => error" << endl;
        // throw runtime_error("cuEventRecord: event is already assigned => error");
    }
    cl_event clevent;
    cl_int err = clEnqueueMarkerWithWaitList(queue->queue, 0, 0, &clevent);
    COCL_PRINT("cuEventRecord CoclEvent=" << event << " created clevent=" << clevent);
    EasyCL::checkError(err);
    err = clFlush(queue->queue);
    EasyCL::checkError(err);
    event->event = clevent;
    return 0;
}

size_t cuEventQuery(CoclEvent *event) {
    COCL_PRINT("cuEventQuery CoclEvent=" << event << " clevent=" << event->event);
    cl_int res;
    cl_int err = clGetEventInfo (
        event->event,
        CL_EVENT_COMMAND_EXECUTION_STATUS,
        sizeof(cl_int),
        &res,
        0);
    COCL_PRINT("clGetEventInfo: " << res);
    EasyCL::checkError(err);
    if(res == CL_COMPLETE) { // success
        COCL_PRINT("cuEventQuery, event completed");
        return 0;
    } else if(res > 0) { // not finished yet
        COCL_PRINT("cuEventQuery, event not finished yet");
        return cudaErrorNotReady;
    } else { // error
        COCL_PRINT("cuEventQuery, event error");
        return 1;
    }
}

size_t cuEventDestroy_v2(CoclEvent *event) {
    COCL_PRINT("cuEventDestroy CoclEvent=" << event);
    delete event;
    return 0;
}
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright 2011-2013 The University of North Carolina at Chapel Hill
 *  All rights reserved.
 *
 *  Licensed under the MADAI Software License. You may obtain a copy of
 *  this license at
 *
 *         https://madai-public.cs.unc.edu/visualization/software-license/
 *
 *  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 <ostream>

#include "Sample.h"

namespace madai {

Sample
::Sample( const std::vector< double > & parameterValues,
    const std::vector< double > & outputValues,
    double LogLikelihood,
    const std::vector< double > likelihoodErrorGradient) :
  m_ParameterValues( parameterValues ),
  m_OutputValues( outputValues ),
  m_LogLikelihoodErrorGradient( logLikelihoodErrorGradient ),
  m_LogLikelihoodValueGradient( logLikelihoodValueGradient ),
  m_LogLikelihood( LogLikelihood )
{
}

Sample
::Sample( const std::vector< double > & parameter_values,
    const std::vector< double > & output_values,
    double LogLikelihood ) :
  m_ParameterValues( parameter_values ),
  m_OutputValues( output_values ),
  m_LogLikelihood( LogLikelihood )
{
}

Sample
::Sample( const std::vector< double > & parameter_values,
    const std::vector< double > & output_values ) :
  m_ParameterValues( parameter_values ),
  m_OutputValues( output_values ),
  m_LogLikelihood( 0.0 )
{
}

Sample
::Sample( const std::vector< double > & parameter_values ) :
  m_ParameterValues( parameter_values ),
  m_LogLikelihood( 0.0 )
{
}

Sample
::Sample() :
  m_LogLikelihood(0.0)
{
}

void
Sample
::Reset()
{
  m_ParameterValues.clear();
  m_OutputValues.clear();
  m_Comments.clear();
  m_LogLikelihood= 0.0;
}

bool
Sample
::IsValid() const {
  return ( m_ParameterValues.size() > 0
     || m_OutputValues.size() > 0
     || m_Comments.size() > 0 );
}

/**
   Provide this operator so that we can do:

     void SortSamples(std::vector< Sample > & s) {
       std::sort(s.begin(),s.end());
     }
*/
bool Sample
::operator<(const Sample & rhs) const {
    return (m_LogLikelihood < rhs.m_LogLikelihood);
}

std::ostream & operator<<(std::ostream & os, const Sample & sample) {

  os << "Sample:\n";
  os << "  ParameterValues: [";
  for ( size_t i = 0; i < sample.m_ParameterValues.size(); ++i ) {
    os << sample.m_ParameterValues[i];
    if ( i < sample.m_ParameterValues.size()-1) os << ", ";
  }
  os << "]\n";

  os << "  OutputValues: [";
  for ( size_t i = 0; i < sample.m_OutputValues.size(); ++i ) {
    os << sample.m_OutputValues[i];
    if ( i < sample.m_OutputValues.size()-1) os << ", ";
  }
  os << "]\n";

  os << "  LogLikelihood: [" << sample.m_LogLikelihood << "]\n";

  if ( sample.m_Comments.size() > 0 ) {
    for ( size_t i = 0; i < sample.m_Comments.size(); ++i ) {
      os << sample.m_Comments[i];
      if ( i < sample.m_Comments.size()-1) os << ", ";
    }
  }

  return os;
}

} // end namespace madai
<commit_msg>Updated the Sample << operator to stream the new gradient members.<commit_after>/*=========================================================================
 *
 *  Copyright 2011-2013 The University of North Carolina at Chapel Hill
 *  All rights reserved.
 *
 *  Licensed under the MADAI Software License. You may obtain a copy of
 *  this license at
 *
 *         https://madai-public.cs.unc.edu/visualization/software-license/
 *
 *  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 <ostream>

#include "Sample.h"

namespace madai {

Sample
::Sample( const std::vector< double > & parameterValues,
    const std::vector< double > & outputValues,
    double LogLikelihood,
    const std::vector< double > likelihoodErrorGradient) :
  m_ParameterValues( parameterValues ),
  m_OutputValues( outputValues ),
  m_LogLikelihoodErrorGradient( logLikelihoodErrorGradient ),
  m_LogLikelihoodValueGradient( logLikelihoodValueGradient ),
  m_LogLikelihood( LogLikelihood )
{
}

Sample
::Sample( const std::vector< double > & parameter_values,
    const std::vector< double > & output_values,
    double LogLikelihood ) :
  m_ParameterValues( parameter_values ),
  m_OutputValues( output_values ),
  m_LogLikelihood( LogLikelihood )
{
}

Sample
::Sample( const std::vector< double > & parameter_values,
    const std::vector< double > & output_values ) :
  m_ParameterValues( parameter_values ),
  m_OutputValues( output_values ),
  m_LogLikelihood( 0.0 )
{
}

Sample
::Sample( const std::vector< double > & parameter_values ) :
  m_ParameterValues( parameter_values ),
  m_LogLikelihood( 0.0 )
{
}

Sample
::Sample() :
  m_LogLikelihood(0.0)
{
}

void
Sample
::Reset()
{
  m_ParameterValues.clear();
  m_OutputValues.clear();
  m_Comments.clear();
  m_LogLikelihood= 0.0;
}

bool
Sample
::IsValid() const {
  return ( m_ParameterValues.size() > 0
     || m_OutputValues.size() > 0
     || m_Comments.size() > 0 );
}

/**
   Provide this operator so that we can do:

     void SortSamples(std::vector< Sample > & s) {
       std::sort(s.begin(),s.end());
     }
*/
bool Sample
::operator<(const Sample & rhs) const {
    return (m_LogLikelihood < rhs.m_LogLikelihood);
}

std::ostream & operator<<(std::ostream & os, const Sample & sample) {

  os << "Sample:\n";
  os << "  ParameterValues: [";
  for ( size_t i = 0; i < sample.m_ParameterValues.size(); ++i ) {
    os << sample.m_ParameterValues[i];
    if ( i < sample.m_ParameterValues.size()-1) os << ", ";
  }
  os << "]\n";

  os << "  OutputValues: [";
  for ( size_t i = 0; i < sample.m_OutputValues.size(); ++i ) {
    os << sample.m_OutputValues[i];
    if ( i < sample.m_OutputValues.size()-1) os << ", ";
  }
  os << "]\n";

  os << "  sigma_observable*dLL/dsigma_observable: [";
  for ( size_t i = 0; i < sample.m_LogLikelihoodErrorGradient.size(); ++i ) {
    os << sample.m_LogLikelihoodErrorGradient[i];
    if ( i < sample.m_LogLikelihoodErrorGradient.size()-1) os << ", ";
  }
  os << "]\n";

  os << "  sigma_observable*dLL/dsigma_observable: [";
  for ( size_t i = 0; i < sample.m_LogLikelihoodValueGradient.size(); ++i ) {
    os << sample.m_LogLikelihoodValueGradient[i];
    if ( i < sample.m_LogLikelihoodValueGradient.size()-1) os << ", ";
  }
  os << "]\n";

  os << "  LogLikelihood: [" << sample.m_LogLikelihood << "]\n";

  if ( sample.m_Comments.size() > 0 ) {
    for ( size_t i = 0; i < sample.m_Comments.size(); ++i ) {
      os << sample.m_Comments[i];
      if ( i < sample.m_Comments.size()-1) os << ", ";
    }
  }

  return os;
}

} // end namespace madai
<|endoftext|>


<commit_before>#include <babylon/meshes/polygonmesh/polygon_mesh_builder.h>

#include <babylon/babylon_stl_util.h>
#include <babylon/engines/engine.h>
#include <babylon/math/path2.h>
#include <babylon/math/vector2.h>
#include <babylon/meshes/mesh.h>
#include <babylon/meshes/polygonmesh/indexed_vector2.h>
#include <babylon/meshes/vertex_buffer.h>
#include <babylon/meshes/vertex_data.h>

#ifdef __GNUC__
#pragma GCC diagnostic push
// Conversion from int to char
#pragma GCC diagnostic ignored "-Wconversion"
#if __GNUC__ > 6
// Use of GNU statement expression extension
#endif
#endif
#if _MSC_VER && !__INTEL_COMPILER
#pragma warning(push)
#pragma warning(disable : 4996)
#endif
#include <earcut.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif

namespace BABYLON {

PolygonMeshBuilder::PolygonMeshBuilder(const std::string& name,
                                       const Path2& contours, Scene* scene)
    : _name{name}
{
  _scene = scene ? scene : Engine::LastCreatedScene();

  auto points = contours.getPoints();
  _addToepoint(points);

  _points.add(points);
  _outlinepoints.add(points);
}

PolygonMeshBuilder::PolygonMeshBuilder(const std::string& name,
                                       const std::vector<Vector2>& contours,
                                       Scene* scene)
    : _name{name}
{
  _scene = scene ? scene : Engine::LastCreatedScene();

  _addToepoint(contours);

  _points.add(contours);
  _outlinepoints.add(contours);
}

PolygonMeshBuilder::~PolygonMeshBuilder() = default;

void PolygonMeshBuilder::_addToepoint(const std::vector<Vector2>& points)
{
  for (auto& p : points) {
    Point2D point{{p.x, p.y}};
    _epoints.emplace_back(point);
  }
}

PolygonMeshBuilder&
PolygonMeshBuilder::addHole(const std::vector<Vector2>& hole)
{
  _points.add(hole);
  PolygonPoints holepoints;
  holepoints.add(hole);
  _holes.emplace_back(holepoints);

  _eholes.emplace_back(static_cast<int32_t>(_epoints.size()));
  _addToepoint(hole);

  return *this;
}

MeshPtr PolygonMeshBuilder::build(bool updatable, float depth)
{
  auto result = Mesh::New(_name, _scene);

  const auto vertexData = buildVertexData(depth);

  result->setVerticesData(VertexBuffer::PositionKind, vertexData->positions,
                          updatable);
  result->setVerticesData(VertexBuffer::NormalKind, vertexData->normals,
                          updatable);
  result->setVerticesData(VertexBuffer::UVKind, vertexData->uvs, updatable);
  result->setIndices(vertexData->indices);

  return result;
}

std::unique_ptr<VertexData> PolygonMeshBuilder::buildVertexData(float depth)
{
  auto result = std::make_unique<VertexData>();

  Float32Array normals;
  Float32Array positions;
  Float32Array uvs;

  auto bounds               = _points.computeBounds();
  const auto& pointElements = _points.elements;
  for (const auto& p : pointElements) {
    stl_util::concat(normals, {0.f, 1.f, 0.f});
    stl_util::concat(positions, {p.x, 0.f, p.y});
    stl_util::concat(uvs, {(p.x - bounds.min.x) / bounds.width,
                           (p.y - bounds.min.y) / bounds.height});
  }

  std::vector<std::vector<Point2D>> polygon;
  // Earcut.hpp has no 'holes' argument, adding the holes to the input array
  addHoles(_epoints, _eholes, polygon);
  auto res = mapbox::earcut<uint32_t>(polygon);

  Uint32Array indices;
  for (auto r : res) {
    indices.emplace_back(r);
  }

  if (depth > 0.f) {
    // get the current pointcount
    auto positionscount = static_cast<uint32_t>(positions.size() / 3);

    for (const auto& p : pointElements) { // add the elements at the depth
      stl_util::concat(normals, {0.f, -1.f, 0.f});
      stl_util::concat(positions, {p.x, -depth, p.y});
      stl_util::concat(uvs, {1.f - (p.x - bounds.min.x) / bounds.width,
                             1.f - (p.y - bounds.min.y) / bounds.height});
    }

    size_t totalCount = indices.size();
    for (size_t i = 0; i < totalCount; i += 3) {
      const auto i0 = indices[i + 0];
      const auto i1 = indices[i + 1];
      const auto i2 = indices[i + 2];

      indices.emplace_back(i2 + positionscount);
      indices.emplace_back(i1 + positionscount);
      indices.emplace_back(i0 + positionscount);
    }

    // Add the sides
    addSide(positions, normals, uvs, indices, bounds, _outlinepoints, depth,
            false);

    for (auto& hole : _holes) {
      addSide(positions, normals, uvs, indices, bounds, hole, depth, true);
    }
  }

  result->indices   = std::move(indices);
  result->positions = std::move(positions);
  result->normals   = std::move(normals);
  result->uvs       = std::move(uvs);

  return result;
}

std::pair<Float32Array, Uint32Array>
PolygonMeshBuilder::buildWall(const Vector3& wall0Corner,
                              const Vector3& wall1Corner)
{
  Float32Array positions;
  Uint32Array indices;
  auto direction = wall1Corner.subtract(wall0Corner).normalize();
  auto angle     = std::acos(direction.x);
  if (direction.z != 0.f) {
    angle *= direction.z / std::abs(direction.z);
  }
  const auto& pointElements = _points.elements;
  for (const auto& p : pointElements) {
    stl_util::concat(positions, {p.x * std::cos(angle) + wall0Corner.x, p.y,
                                 p.x * std::sin(angle) + wall0Corner.z});
  }
  std::vector<std::vector<Point2D>> polygon;
  // Earcut.hpp has no 'holes' argument, adding the holes to the input array
  addHoles(_epoints, _eholes, polygon);
  auto res = mapbox::earcut<int32_t>(polygon);
  for (size_t i = res.size(); i-- > 0;) {
    indices.emplace_back(res[i]);
  }

  return std::make_pair(positions, indices);
}

PolygonPoints& PolygonMeshBuilder::points()
{
  return _points;
}

const PolygonPoints& PolygonMeshBuilder::points() const
{
  return _points;
}

void PolygonMeshBuilder::addSide(Float32Array& positions, Float32Array& normals,
                                 Float32Array& uvs, Uint32Array& indices,
                                 const Bounds& bounds,
                                 const PolygonPoints& points, float depth,
                                 bool flip)
{
  auto startIndex = static_cast<uint32_t>(positions.size() / 3);
  float ulength   = 0.f;
  for (size_t i = 0; i < points.elements.size(); ++i) {
    const auto& p = points.elements[i];
    IndexedVector2 p1;
    if ((i + 1) > points.elements.size() - 1) {
      p1 = points.elements[0];
    }
    else {
      p1 = points.elements[i + 1];
    }

    stl_util::concat(positions, {p.x, 0.f, p.y});
    stl_util::concat(positions, {p.x, -depth, p.y});
    stl_util::concat(positions, {p1.x, 0.f, p1.y});
    stl_util::concat(positions, {p1.x, -depth, p1.y});

    Vector3 v1(p.x, 0.f, p.y);
    Vector3 v2(p1.x, 0.f, p1.y);
    Vector3 v3 = v2.subtract(v1);
    Vector3 v4(0.f, 1.f, 0.f);
    Vector3 vn = Vector3::Cross(v3, v4);
    vn         = vn.normalize();

    stl_util::concat(uvs, {ulength / bounds.width, 0.f});
    stl_util::concat(uvs, {ulength / bounds.width, 1.f});
    ulength += v3.length();
    stl_util::concat(uvs, {(ulength / bounds.width), 0.f});
    stl_util::concat(uvs, {(ulength / bounds.width), 1.f});

    if (!flip) {
      stl_util::concat(normals, {-vn.x, -vn.y, -vn.z});
      stl_util::concat(normals, {-vn.x, -vn.y, -vn.z});
      stl_util::concat(normals, {-vn.x, -vn.y, -vn.z});
      stl_util::concat(normals, {-vn.x, -vn.y, -vn.z});

      indices.emplace_back(startIndex + 0);
      indices.emplace_back(startIndex + 1);
      indices.emplace_back(startIndex + 2);

      indices.emplace_back(startIndex + 1);
      indices.emplace_back(startIndex + 3);
      indices.emplace_back(startIndex + 2);
    }
    else {
      stl_util::concat(normals, {vn.x, vn.y, vn.z});
      stl_util::concat(normals, {vn.x, vn.y, vn.z});
      stl_util::concat(normals, {vn.x, vn.y, vn.z});
      stl_util::concat(normals, {vn.x, vn.y, vn.z});

      indices.emplace_back(startIndex + 0);
      indices.emplace_back(startIndex + 2);
      indices.emplace_back(startIndex + 1);

      indices.emplace_back(startIndex + 1);
      indices.emplace_back(startIndex + 2);
      indices.emplace_back(startIndex + 3);
    }
    startIndex += 4;
  }
}

void PolygonMeshBuilder::addHoles(const std::vector<Point2D>& epoints,
                                  const Uint32Array& holeIndices,
                                  std::vector<std::vector<Point2D>>& polygon)
{
  // Check if polygon has holes
  if (holeIndices.empty()) {
    polygon.emplace_back(epoints);
  }
  else {
    // Determine hole indices
    using IndexRange = std::array<size_t, 2>;
    std::vector<IndexRange> holes;
    for (size_t i = 0, len = holeIndices.size(); i < len; i++) {
      size_t startIndex = holeIndices[i];
      size_t endIndex   = i < len - 1 ? holeIndices[i + 1] : epoints.size();
      IndexRange range{{startIndex, endIndex}};
      holes.emplace_back(range);
    }
    // Add outer ring
    std::vector<Point2D> ring(epoints.begin(),
                              epoints.begin() + static_cast<long>(holes[0][0]));
    polygon.emplace_back(ring);
    // Add holes
    for (auto& holeRange : holes) {
      std::vector<Point2D> hole(
        epoints.begin() + static_cast<long>(holeRange[0]),
        epoints.begin() + static_cast<long>(holeRange[1]));
      polygon.emplace_back(hole);
    }
  }
}

} // end of namespace BABYLON
<commit_msg>polygon_mesh_builder.cpp: added NOLINT to suppress warnings inside earcut.hpp<commit_after>#include <babylon/meshes/polygonmesh/polygon_mesh_builder.h>

#include <babylon/babylon_stl_util.h>
#include <babylon/engines/engine.h>
#include <babylon/math/path2.h>
#include <babylon/math/vector2.h>
#include <babylon/meshes/mesh.h>
#include <babylon/meshes/polygonmesh/indexed_vector2.h>
#include <babylon/meshes/vertex_buffer.h>
#include <babylon/meshes/vertex_data.h>

#ifdef __GNUC__
#pragma GCC diagnostic push
// Conversion from int to char
#pragma GCC diagnostic ignored "-Wconversion"
#if __GNUC__ > 6
// Use of GNU statement expression extension
#endif
#endif
#if _MSC_VER && !__INTEL_COMPILER
#pragma warning(push)
#pragma warning(disable : 4996)
#endif
#include <earcut.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif

namespace BABYLON {

PolygonMeshBuilder::PolygonMeshBuilder(const std::string& name,
                                       const Path2& contours, Scene* scene)
    : _name{name}
{
  _scene = scene ? scene : Engine::LastCreatedScene();

  auto points = contours.getPoints();
  _addToepoint(points);

  _points.add(points);
  _outlinepoints.add(points);
}

PolygonMeshBuilder::PolygonMeshBuilder(const std::string& name,
                                       const std::vector<Vector2>& contours,
                                       Scene* scene)
    : _name{name}
{
  _scene = scene ? scene : Engine::LastCreatedScene();

  _addToepoint(contours);

  _points.add(contours);
  _outlinepoints.add(contours);
}

PolygonMeshBuilder::~PolygonMeshBuilder() = default;

void PolygonMeshBuilder::_addToepoint(const std::vector<Vector2>& points)
{
  for (auto& p : points) {
    Point2D point{{p.x, p.y}};
    _epoints.emplace_back(point);
  }
}

PolygonMeshBuilder&
PolygonMeshBuilder::addHole(const std::vector<Vector2>& hole)
{
  _points.add(hole);
  PolygonPoints holepoints;
  holepoints.add(hole);
  _holes.emplace_back(holepoints);

  _eholes.emplace_back(static_cast<int32_t>(_epoints.size()));
  _addToepoint(hole);

  return *this;
}

MeshPtr PolygonMeshBuilder::build(bool updatable, float depth)
{
  auto result = Mesh::New(_name, _scene);

  const auto vertexData = buildVertexData(depth); // NOLINT (this leads to a clang-tidy warning in external earcut.hpp)

  result->setVerticesData(VertexBuffer::PositionKind, vertexData->positions,
                          updatable);
  result->setVerticesData(VertexBuffer::NormalKind, vertexData->normals,
                          updatable);
  result->setVerticesData(VertexBuffer::UVKind, vertexData->uvs, updatable);
  result->setIndices(vertexData->indices);

  return result;
}

std::unique_ptr<VertexData> PolygonMeshBuilder::buildVertexData(float depth)
{
  auto result = std::make_unique<VertexData>();

  Float32Array normals;
  Float32Array positions;
  Float32Array uvs;

  auto bounds               = _points.computeBounds();
  const auto& pointElements = _points.elements;
  for (const auto& p : pointElements) {
    stl_util::concat(normals, {0.f, 1.f, 0.f});
    stl_util::concat(positions, {p.x, 0.f, p.y});
    stl_util::concat(uvs, {(p.x - bounds.min.x) / bounds.width,
                           (p.y - bounds.min.y) / bounds.height});
  }

  std::vector<std::vector<Point2D>> polygon;
  // Earcut.hpp has no 'holes' argument, adding the holes to the input array
  addHoles(_epoints, _eholes, polygon);
  auto res = mapbox::earcut<uint32_t>(polygon); // NOLINT (this leads to a clang-tidy warning in external earcut.hpp)

  Uint32Array indices;
  for (auto r : res) {
    indices.emplace_back(r);
  }

  if (depth > 0.f) {
    // get the current pointcount
    auto positionscount = static_cast<uint32_t>(positions.size() / 3);

    for (const auto& p : pointElements) { // add the elements at the depth
      stl_util::concat(normals, {0.f, -1.f, 0.f});
      stl_util::concat(positions, {p.x, -depth, p.y});
      stl_util::concat(uvs, {1.f - (p.x - bounds.min.x) / bounds.width,
                             1.f - (p.y - bounds.min.y) / bounds.height});
    }

    size_t totalCount = indices.size();
    for (size_t i = 0; i < totalCount; i += 3) {
      const auto i0 = indices[i + 0];
      const auto i1 = indices[i + 1];
      const auto i2 = indices[i + 2];

      indices.emplace_back(i2 + positionscount);
      indices.emplace_back(i1 + positionscount);
      indices.emplace_back(i0 + positionscount);
    }

    // Add the sides
    addSide(positions, normals, uvs, indices, bounds, _outlinepoints, depth,
            false);

    for (auto& hole : _holes) {
      addSide(positions, normals, uvs, indices, bounds, hole, depth, true);
    }
  }

  result->indices   = std::move(indices);
  result->positions = std::move(positions);
  result->normals   = std::move(normals);
  result->uvs       = std::move(uvs);

  return result;
}

std::pair<Float32Array, Uint32Array>
PolygonMeshBuilder::buildWall(const Vector3& wall0Corner,
                              const Vector3& wall1Corner)
{
  Float32Array positions;
  Uint32Array indices;
  auto direction = wall1Corner.subtract(wall0Corner).normalize();
  auto angle     = std::acos(direction.x);
  if (direction.z != 0.f) {
    angle *= direction.z / std::abs(direction.z);
  }
  const auto& pointElements = _points.elements;
  for (const auto& p : pointElements) {
    stl_util::concat(positions, {p.x * std::cos(angle) + wall0Corner.x, p.y,
                                 p.x * std::sin(angle) + wall0Corner.z});
  }
  std::vector<std::vector<Point2D>> polygon;
  // Earcut.hpp has no 'holes' argument, adding the holes to the input array
  addHoles(_epoints, _eholes, polygon);
  auto res = mapbox::earcut<int32_t>(polygon);
  for (size_t i = res.size(); i-- > 0;) {
    indices.emplace_back(res[i]);
  }

  return std::make_pair(positions, indices);
}

PolygonPoints& PolygonMeshBuilder::points()
{
  return _points;
}

const PolygonPoints& PolygonMeshBuilder::points() const
{
  return _points;
}

void PolygonMeshBuilder::addSide(Float32Array& positions, Float32Array& normals,
                                 Float32Array& uvs, Uint32Array& indices,
                                 const Bounds& bounds,
                                 const PolygonPoints& points, float depth,
                                 bool flip)
{
  auto startIndex = static_cast<uint32_t>(positions.size() / 3);
  float ulength   = 0.f;
  for (size_t i = 0; i < points.elements.size(); ++i) {
    const auto& p = points.elements[i];
    IndexedVector2 p1;
    if ((i + 1) > points.elements.size() - 1) {
      p1 = points.elements[0];
    }
    else {
      p1 = points.elements[i + 1];
    }

    stl_util::concat(positions, {p.x, 0.f, p.y});
    stl_util::concat(positions, {p.x, -depth, p.y});
    stl_util::concat(positions, {p1.x, 0.f, p1.y});
    stl_util::concat(positions, {p1.x, -depth, p1.y});

    Vector3 v1(p.x, 0.f, p.y);
    Vector3 v2(p1.x, 0.f, p1.y);
    Vector3 v3 = v2.subtract(v1);
    Vector3 v4(0.f, 1.f, 0.f);
    Vector3 vn = Vector3::Cross(v3, v4);
    vn         = vn.normalize();

    stl_util::concat(uvs, {ulength / bounds.width, 0.f});
    stl_util::concat(uvs, {ulength / bounds.width, 1.f});
    ulength += v3.length();
    stl_util::concat(uvs, {(ulength / bounds.width), 0.f});
    stl_util::concat(uvs, {(ulength / bounds.width), 1.f});

    if (!flip) {
      stl_util::concat(normals, {-vn.x, -vn.y, -vn.z});
      stl_util::concat(normals, {-vn.x, -vn.y, -vn.z});
      stl_util::concat(normals, {-vn.x, -vn.y, -vn.z});
      stl_util::concat(normals, {-vn.x, -vn.y, -vn.z});

      indices.emplace_back(startIndex + 0);
      indices.emplace_back(startIndex + 1);
      indices.emplace_back(startIndex + 2);

      indices.emplace_back(startIndex + 1);
      indices.emplace_back(startIndex + 3);
      indices.emplace_back(startIndex + 2);
    }
    else {
      stl_util::concat(normals, {vn.x, vn.y, vn.z});
      stl_util::concat(normals, {vn.x, vn.y, vn.z});
      stl_util::concat(normals, {vn.x, vn.y, vn.z});
      stl_util::concat(normals, {vn.x, vn.y, vn.z});

      indices.emplace_back(startIndex + 0);
      indices.emplace_back(startIndex + 2);
      indices.emplace_back(startIndex + 1);

      indices.emplace_back(startIndex + 1);
      indices.emplace_back(startIndex + 2);
      indices.emplace_back(startIndex + 3);
    }
    startIndex += 4;
  }
}

void PolygonMeshBuilder::addHoles(const std::vector<Point2D>& epoints,
                                  const Uint32Array& holeIndices,
                                  std::vector<std::vector<Point2D>>& polygon)
{
  // Check if polygon has holes
  if (holeIndices.empty()) {
    polygon.emplace_back(epoints);
  }
  else {
    // Determine hole indices
    using IndexRange = std::array<size_t, 2>;
    std::vector<IndexRange> holes;
    for (size_t i = 0, len = holeIndices.size(); i < len; i++) {
      size_t startIndex = holeIndices[i];
      size_t endIndex   = i < len - 1 ? holeIndices[i + 1] : epoints.size();
      IndexRange range{{startIndex, endIndex}};
      holes.emplace_back(range);
    }
    // Add outer ring
    std::vector<Point2D> ring(epoints.begin(),
                              epoints.begin() + static_cast<long>(holes[0][0]));
    polygon.emplace_back(ring);
    // Add holes
    for (auto& holeRange : holes) {
      std::vector<Point2D> hole(
        epoints.begin() + static_cast<long>(holeRange[0]),
        epoints.begin() + static_cast<long>(holeRange[1]));
      polygon.emplace_back(hole);
    }
  }
}

} // end of namespace BABYLON
<|endoftext|>


<commit_before>/**
 * REXUS PIOneERS - Pi_1
 * pipes.cpp
 * Purpose: Function declarations for implementation of pipes class for data
 *			communication between processes
 *
 * @author David Amison
 * @version 1.0 10/10/2017
 */
#include <string>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#include <signal.h>

#include "pipes.h"

namespace comms {

	/**
	 * Check whether a file descriptor is ready for reading
	 *
	 * @param fd, file descriptor to be checked
	 * @return boolean indicating whether fd is ready for read
	 */
	bool poll_read(const int fd) {
		// Checks a file descriptor is ready for reading
		struct pollfd fds[1];
		int timeout = 0;
		fds[0].fd = fd;
		fds[0].events = POLLIN;
		// Check if the file descriptor is ready for reading
		if (poll(fds, 1, timeout))
			return fds[0].revents & POLLIN;
	}

	/**
	 * Check whether a file descriptor is ready for writing
	 *
	 * @param fd: File descriptor to be checked
	 * @return Boolean indicating whether fd is ready for write
	 */
	bool poll_write(const int fd) {
		// Checks if a file descriptor is available for reading to
		struct pollfd fds[1];
		int timeout = 0;
		fds[0].fd = fd;
		fds[0].events = POLLOUT | POLLHUP;
		if (poll(fds, 1, timeout)) {
			if (fds[0].revents & POLLHUP)
				return false;
			else if (fds[0].revents & POLLOUT)
				return true;
			else
				return false;
		}
	}

	Pipe::Pipe() {
		// We'll handle pipe problems ourself!
		signal(SIGPIPE, SIG_IGN);
		pipe(m_pipes1);
		pipe(m_pipes2);
		m_ch_read = m_pipes1[0];
		m_par_write = m_pipes1[1];
		m_par_read = m_pipes2[0];
		m_ch_write = m_pipes2[1];
	}

	int Pipe::Fork() {
		// Forks the process and closes pipes that are not for use by that process
		if ((m_pid = fork()) == 0) {
			// This is the child process
			close(m_par_read);
			close(m_par_write);
			return m_pid;
		} else {
			close(m_ch_read);
			close(m_ch_write);
			return m_pid;
		}
	}

	int Pipe::getReadfd() {
		if (m_pid < 0)
			return -1;
		return (m_pid > 0) ? m_par_read : m_ch_read;
	}

	int Pipe::getWritefd() {
		if (m_pid < 0)
			return -1;
		return (m_pid > 0) ? m_par_write : m_ch_write;
	}

	int Pipe::binwrite(const void* data, int n) {
		// Write n bytes of data to the pipe.
		int fd = getWritefd();
		if (fd < 0)
			return -1; // process not forked
		if (!poll_write(fd))
			return -2; // pipe unavailable for write
		if (n == write(fd, data, n))
			return n;
		else
			return -3; // error writing to pipe
	}

	int Pipe::binread(void* data, int n) {
		// Reads upto n bytes into the character array, returns number of bytes read
		int fd = getReadfd();
		if (fd < 0)
			return -1; // Process not forked
		throw PipeException("ERROR process not forked");
		if (!poll_read(fd))
			return 0;
		int bytes_read = read(fd, data, n);
		if (bytes_read == -1)
			return -3; // Error reading from pipe
		else
			return bytes_read;
	}

	void Pipe::close_pipes() {
		if (m_pid < 0) {
			close(m_ch_read);
			close(m_ch_write);
			close(m_par_read);
			close(m_par_write);
		} else if (m_pid == 0) {
			close(m_ch_read);
			close(m_ch_write);
		} else {
			close(m_par_read);
			close(m_par_write);
		}
	}

	Pipe::~Pipe() {
	}

}<commit_msg>Debugging<commit_after>/**
 * REXUS PIOneERS - Pi_1
 * pipes.cpp
 * Purpose: Function declarations for implementation of pipes class for data
 *			communication between processes
 *
 * @author David Amison
 * @version 1.0 10/10/2017
 */
#include <string>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#include <signal.h>

#include "pipes.h"

namespace comms {

	/**
	 * Check whether a file descriptor is ready for reading
	 *
	 * @param fd, file descriptor to be checked
	 * @return boolean indicating whether fd is ready for read
	 */
	bool poll_read(const int fd) {
		// Checks a file descriptor is ready for reading
		struct pollfd fds[1];
		int timeout = 0;
		fds[0].fd = fd;
		fds[0].events = POLLIN;
		// Check if the file descriptor is ready for reading
		if (poll(fds, 1, timeout))
			return fds[0].revents & POLLIN;
	}

	/**
	 * Check whether a file descriptor is ready for writing
	 *
	 * @param fd: File descriptor to be checked
	 * @return Boolean indicating whether fd is ready for write
	 */
	bool poll_write(const int fd) {
		// Checks if a file descriptor is available for reading to
		struct pollfd fds[1];
		int timeout = 0;
		fds[0].fd = fd;
		fds[0].events = POLLOUT | POLLHUP;
		if (poll(fds, 1, timeout)) {
			if (fds[0].revents & POLLHUP)
				return false;
			else if (fds[0].revents & POLLOUT)
				return true;
			else
				return false;
		}
	}

	Pipe::Pipe() {
		// We'll handle pipe problems ourself!
		signal(SIGPIPE, SIG_IGN);
		pipe(m_pipes1);
		pipe(m_pipes2);
		m_ch_read = m_pipes1[0];
		m_par_write = m_pipes1[1];
		m_par_read = m_pipes2[0];
		m_ch_write = m_pipes2[1];
	}

	int Pipe::Fork() {
		// Forks the process and closes pipes that are not for use by that process
		if ((m_pid = fork()) == 0) {
			// This is the child process
			close(m_par_read);
			close(m_par_write);
			return m_pid;
		} else {
			close(m_ch_read);
			close(m_ch_write);
			return m_pid;
		}
	}

	int Pipe::getReadfd() {
		if (m_pid < 0)
			return -1;
		return (m_pid > 0) ? m_par_read : m_ch_read;
	}

	int Pipe::getWritefd() {
		if (m_pid < 0)
			return -1;
		return (m_pid > 0) ? m_par_write : m_ch_write;
	}

	int Pipe::binwrite(const void* data, int n) {
		// Write n bytes of data to the pipe.
		int fd = getWritefd();
		if (fd < 0)
			return -1; // process not forked
		if (!poll_write(fd))
			return -2; // pipe unavailable for write
		if (n == write(fd, data, n))
			return n;
		else
			return -3; // error writing to pipe
	}

	int Pipe::binread(void* data, int n) {
		// Reads upto n bytes into the character array, returns number of bytes read
		int fd = getReadfd();
		if (fd < 0)
			return -1; // Process not forked
		if (!poll_read(fd))
			return 0;
		int bytes_read = read(fd, data, n);
		if (bytes_read == -1)
			return -3; // Error reading from pipe
		else
			return bytes_read;
	}

	void Pipe::close_pipes() {
		if (m_pid < 0) {
			close(m_ch_read);
			close(m_ch_write);
			close(m_par_read);
			close(m_par_write);
		} else if (m_pid == 0) {
			close(m_ch_read);
			close(m_ch_write);
		} else {
			close(m_par_read);
			close(m_par_write);
		}
	}

	Pipe::~Pipe() {
	}

}<|endoftext|>


<commit_before>#include "..\include\Sprite.h"
namespace FGF
{
	Sprite::Sprite(float x, float y, float w, float h, float fps, Texture* aTex)
		:QuadSceneNode(0,0,w,h)
	{
		tex = aTex;

		this->setOrigin(0,0);

		texCoord1 = new float[4];
		texCoord2 = new float[4];

		framesX = (aTex->getXRes()/w);
		framesY = (aTex->getYRes()/h);
		frames = framesX*framesY;
		tcW = w/aTex->getXRes();
		tcH = h/aTex->getYRes();

		setFrame(0);
		frame = 0;
		TTL = 1.0/fps;
		FPS = fps;
		frame = 0;

		start = 0;
		end = frames-1;
	}

	Sprite::~Sprite(void)
	{
		delete[] texCoord1;
		delete[] texCoord2;
	}

	void Sprite::Update( float dt )
	{
		if(FPS > 0)
		{
			TTL -= dt;
			if(TTL <= 0.0f)
			{
				frame++;
				if(frame > end) frame = start;
				setFrame(frame);
				TTL = 1.0/FPS;
			}
		}
	}

	void Sprite::Render()
	{
		glPushMatrix();
		prepare();

		if(tex != NULL)
		{
			glEnable(GL_TEXTURE_2D);
			tex->Activate();
			glBegin(GL_TRIANGLE_STRIP);
				for(int i = 0; i < 4; i++)
				{
					color[i].activate();
					glTexCoord2f(texCoord1[i],texCoord2[i]);
					vertex[i].render();
				}
			glEnd();
		}
		renderChildren();
		glPopMatrix();
	}

	void Sprite::setAnimationSequence( int aStart, int aEnd )
	{
		if ((aStart < 0) || (aEnd >= frames))
			return Logger::getInstance()->Log("Frame sequence exceeds [0..(frames-1)].");
		if (aStart > aEnd)
			return Logger::getInstance()->Log("Sequence start > sequence end. FAIL.");
		start = aStart;
		frame = start;
		setFrame(start);
		end = aEnd;
	}

	void Sprite::setFrame( int next )
	{
		if (next >= frames)
			return Logger::getInstance()->Log("Frame number too large.");
		float tc_origin_x = 0.0f;
		float tc_origin_y = 1.0f;

		while(next > (framesX-1))
		{
			next -= framesX;
			tc_origin_y -= tcH;
		}

		while (next > 0)
		{
			tc_origin_x += tcW;
			next--;
		}

		texCoord1[0] = tc_origin_x;
		texCoord1[1] = tc_origin_x;
		texCoord1[2] = tc_origin_x + tcW;
		texCoord1[3] = tc_origin_x + tcW;

		texCoord2[0] = tc_origin_y - tcH;
		texCoord2[1] = tc_origin_y;
		texCoord2[2] = tc_origin_y - tcH;
		texCoord2[3] = tc_origin_y;
	}
}
<commit_msg>окончательно выпилено!<commit_after>#include "..\include\Sprite.h"
namespace FGF
{
	Sprite::Sprite(float w, float h, float fps, Texture* aTex)
		:QuadSceneNode(0,0,w,h)
	{
		tex = aTex;

		this->setOrigin(0,0);

		texCoord1 = new float[4];
		texCoord2 = new float[4];

		framesX = (aTex->getXRes()/w);
		framesY = (aTex->getYRes()/h);
		frames = framesX*framesY;
		tcW = w/aTex->getXRes();
		tcH = h/aTex->getYRes();

		setFrame(0);
		frame = 0;
		TTL = 1.0/fps;
		FPS = fps;
		frame = 0;

		start = 0;
		end = frames-1;
	}

	Sprite::~Sprite(void)
	{
		delete[] texCoord1;
		delete[] texCoord2;
	}

	void Sprite::Update( float dt )
	{
		if(FPS > 0)
		{
			TTL -= dt;
			if(TTL <= 0.0f)
			{
				frame++;
				if(frame > end) frame = start;
				setFrame(frame);
				TTL = 1.0/FPS;
			}
		}
	}

	void Sprite::Render()
	{
		glPushMatrix();
		prepare();

		if(tex != NULL)
		{
			glEnable(GL_TEXTURE_2D);
			tex->Activate();
			glBegin(GL_TRIANGLE_STRIP);
				for(int i = 0; i < 4; i++)
				{
					color[i].activate();
					glTexCoord2f(texCoord1[i],texCoord2[i]);
					vertex[i].render();
				}
			glEnd();
		}
		renderChildren();
		glPopMatrix();
	}

	void Sprite::setAnimationSequence( int aStart, int aEnd )
	{
		if ((aStart < 0) || (aEnd >= frames))
			return Logger::getInstance()->Log("Frame sequence exceeds [0..(frames-1)].");
		if (aStart > aEnd)
			return Logger::getInstance()->Log("Sequence start > sequence end. FAIL.");
		start = aStart;
		frame = start;
		setFrame(start);
		end = aEnd;
	}

	void Sprite::setFrame( int next )
	{
		if (next >= frames)
			return Logger::getInstance()->Log("Frame number too large.");
		float tc_origin_x = 0.0f;
		float tc_origin_y = 1.0f;

		while(next > (framesX-1))
		{
			next -= framesX;
			tc_origin_y -= tcH;
		}

		while (next > 0)
		{
			tc_origin_x += tcW;
			next--;
		}

		texCoord1[0] = tc_origin_x;
		texCoord1[1] = tc_origin_x;
		texCoord1[2] = tc_origin_x + tcW;
		texCoord1[3] = tc_origin_x + tcW;

		texCoord2[0] = tc_origin_y - tcH;
		texCoord2[1] = tc_origin_y;
		texCoord2[2] = tc_origin_y - tcH;
		texCoord2[3] = tc_origin_y;
	}
}
<|endoftext|>


<commit_before>#include "colors.hpp"
#include "ifs.hpp"
#include "variations.hpp"

#include <future>
#include <iostream>

#include <boost/gil/extension/io/png_dynamic_io.hpp>
#include <boost/gil/typedefs.hpp>
#include <boost/program_options.hpp>

int main(int argc, const char *argv[]) {
  using namespace math;
  using namespace boost::gil;
  using rgb8 = rgb8_pixel_t;
  namespace opts = boost::program_options;

  colors::color_theme_iterator colors({40, 140, 140}, 6);
  ifs::iterated_function_system<rgb8> funcs = {
    { handkerchief, translate(0.5, -0.75)*identity(), *colors++ },
    { handkerchief, translate(0.75, -0.5)*rotate(M_PI), *colors++ },
    { linear, translate(-0.1, 0.1)*scale(0.3), *colors++ },
    { linear, translate(0.1, -0.1)*scale(0.35)*rotate(M_PI/2), *colors++ },
    { spiral, translate(-0.5, 0.1)*scale(0.5), *colors++ },
    { spiral, translate(0.5, -0.1)*scale(0.5), *colors++ },
    { spiral, translate(-0.5, 0.1)*scale(0.5)*rotate(M_PI/2), *colors++ },
    { spiral, translate(0.5, -0.1)*scale(0.5)*rotate(M_PI/2), *colors++ },
    { spiral, translate(0.1, -0.5)*scale(0.5), *colors++ },
    { spiral, translate(-0.1, 0.5)*scale(0.5), *colors++ },
    { spiral, translate(0.1, -0.5)*scale(0.5)*rotate(M_PI/2), *colors++ },
    { spiral, translate(-0.1, 0.5)*scale(0.5)*rotate(M_PI/2), *colors++ },
    { swirl, translate(-0.5, -0.5)*scale(-0.75), *colors++ },
  };

  bool show_help = false;
  size_t steps = 1000000;
  ptrdiff_t size = 666;
  size_t num_jobs = 1;
  double gamma = 1.0;
  bool hdr = false;

  opts::options_description desc;
  desc.add_options()
    ("help,h", opts::value(&show_help)->zero_tokens(), "show help")
    ("steps,n", opts::value(&steps), "number of iterations")
    ("size,s", opts::value(&size), "image size")
    ("jobs,j", opts::value(&num_jobs), "number of parallel jobs")
    ("gamma,g", opts::value(&gamma), "gamma adjustment")
    ("hdr,H", opts::value(&hdr)->zero_tokens(), "enable HDR")
  ;

  try {
    auto parsed = opts::command_line_parser(argc, argv).options(desc).run();

    opts::variables_map vm;
    opts::store(parsed, vm);
    opts::notify(vm);
  } catch(const std::exception &e) {
    std::cerr << e.what() << std::endl;
    return 2;
  }

  if(show_help) {
    std::cout << desc << std::endl;
    return 0;
  }

  std::vector< std::future<images::raw_image_data<rgb8>> > jobs;
  for(size_t i = 0; i < num_jobs; i++) {
    jobs.push_back(std::async(
      std::launch::async, ifs::chaos_game<rgb8>,
      funcs, point2<ptrdiff_t>{size, size}, steps
    ));
  }
  std::vector<images::raw_image_data<rgb8>> data;
  for(auto &job : jobs)
    data.push_back(job.get());
  auto combined = images::combine(data);

  rgb8_image_t image(size, size, rgb8(0), 0);
  images::render(view(image), images::log_alpha(combined), gamma);

  if(hdr) {
    rgb8_image_t gray(size, size, rgb8(0), 0);
    images::render_monochrome(
      view(gray), images::linear_alpha(combined), rgb8(255, 255, 255), gamma
    );
    images::lighten(view(image), const_view(gray));
  }

  png_write_view("output.png", const_view(image));

  return 0;
}
<commit_msg>Allow specifying a separate gamma for the "HDR" high-pass<commit_after>#include "colors.hpp"
#include "ifs.hpp"
#include "variations.hpp"

#include <future>
#include <iostream>
#include <experimental/optional>

#include <boost/gil/extension/io/png_dynamic_io.hpp>
#include <boost/gil/typedefs.hpp>
#include <boost/program_options.hpp>

// Put this in the boost namespace so that ADL picks them up (via the
// boost::any parameter).
namespace boost {

template<typename T>
void validate(boost::any &v, const std::vector<std::string> &values,
              std::experimental::optional<T>*, int) {
  using namespace boost::program_options;
  using optional_t = std::experimental::optional<T>;

  if(v.empty())
    v = optional_t();
  auto *val = boost::any_cast<optional_t>(&v);
  assert(val);

  boost::any a;
  validate(a, values, static_cast<T*>(nullptr), 0);
  *val = boost::any_cast<T>(a);
}

} // namespace boost

int main(int argc, const char *argv[]) {
  using namespace math;
  using namespace boost::gil;
  using rgb8 = rgb8_pixel_t;
  namespace opts = boost::program_options;

  colors::color_theme_iterator colors({40, 140, 140}, 6);
  ifs::iterated_function_system<rgb8> funcs = {
    { handkerchief, translate(0.5, -0.75)*identity(), *colors++ },
    { handkerchief, translate(0.75, -0.5)*rotate(M_PI), *colors++ },
    { linear, translate(-0.1, 0.1)*scale(0.3), *colors++ },
    { linear, translate(0.1, -0.1)*scale(0.35)*rotate(M_PI/2), *colors++ },
    { spiral, translate(-0.5, 0.1)*scale(0.5), *colors++,
      translate(0.1, 0.9) },
    { spiral, translate(0.5, -0.1)*scale(0.5), *colors++,
      translate(0.2, -0.8) },
    { spiral, translate(-0.5, 0.1)*scale(0.5)*rotate(M_PI/2), *colors++,
      translate(-0.3, -0.7) },
    { spiral, translate(0.5, -0.1)*scale(0.5)*rotate(M_PI/2), *colors++,
      translate(-0.4, 0.6) },
    { spiral, translate(0.1, -0.5)*scale(0.5), *colors++,
      translate(0.5, 0.5) },
    { spiral, translate(-0.1, 0.5)*scale(0.5), *colors++,
      translate(0.6, -0.4) },
    { spiral, translate(0.1, -0.5)*scale(0.5)*rotate(M_PI/2), *colors++,
      translate(-0.7, -0.3) },
    { spiral, translate(-0.1, 0.5)*scale(0.5)*rotate(M_PI/2), *colors++,
      translate(-0.8, 0.2) },
    { swirl, translate(-0.5, -0.5)*scale(-0.75), *colors++ },
  };

  bool show_help = false;
  size_t steps = 1000000;
  ptrdiff_t size = 666;
  size_t num_jobs = 1;
  double gamma = 1.0;
  std::experimental::optional<double> hdr;

  opts::options_description desc;
  desc.add_options()
    ("help,h", opts::value(&show_help)->zero_tokens(), "show help")
    ("steps,n", opts::value(&steps), "number of iterations")
    ("size,s", opts::value(&size), "image size")
    ("jobs,j", opts::value(&num_jobs), "number of parallel jobs")
    ("gamma,g", opts::value(&gamma), "gamma adjustment")
    ("hdr,H", opts::value(&hdr)->implicit_value(1.0, "1.0"), "enable HDR")
  ;

  try {
    auto parsed = opts::command_line_parser(argc, argv).options(desc).run();

    opts::variables_map vm;
    opts::store(parsed, vm);
    opts::notify(vm);
  } catch(const std::exception &e) {
    std::cerr << e.what() << std::endl;
    return 2;
  }

  if(show_help) {
    std::cout << desc << std::endl;
    return 0;
  }

  std::vector< std::future<images::raw_image_data<rgb8>> > jobs;
  for(size_t i = 0; i < num_jobs; i++) {
    jobs.push_back(std::async(
      std::launch::async, ifs::chaos_game<rgb8>,
      funcs, point2<ptrdiff_t>{size, size}, steps
    ));
  }
  std::vector<images::raw_image_data<rgb8>> data;
  for(auto &job : jobs)
    data.push_back(job.get());
  auto combined = images::combine(data);

  rgb8_image_t image(size, size, rgb8(0), 0);
  images::render(view(image), images::log_alpha(combined), gamma);

  if(hdr) {
    rgb8_image_t gray(size, size, rgb8(0), 0);
    images::render_monochrome(
      view(gray), images::linear_alpha(combined), rgb8(255, 255, 255), *hdr
    );
    images::lighten(view(image), const_view(gray));
  }

  png_write_view("output.png", const_view(image));

  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015, 2016, 2017, 2018, 2019, Intel Corporation
 *
 * 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 Intel Corporation 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 LOG OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <unistd.h>
#include <limits.h>
#include <string.h>
#include <cctype>
#include <iomanip>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <time.h>

#include "Tracer.hpp"
#include "PlatformIO.hpp"
#include "PlatformTopo.hpp"
#include "Exception.hpp"
#include "Helper.hpp"
#include "geopm_env.h"
#include "geopm_hash.h"
#include "geopm_version.h"
#include "geopm.h"
#include "geopm_internal.h"
#include "geopm_region_id.h"
#include "config.h"

using geopm::IPlatformTopo;

namespace geopm
{
    Tracer::Tracer(const std::string &start_time)
        : Tracer(start_time, geopm_env_trace(), hostname(), geopm_env_agent(),
                 geopm_env_profile(), geopm_env_do_trace(), platform_io(),
                 {}, 16)
    {

    }

    Tracer::Tracer(const std::string &start_time,
                   const std::string &file_path,
                   const std::string &hostname,
                   const std::string &agent,
                   const std::string &profile_name,
                   bool do_trace,
                   IPlatformIO &platform_io,
                   const std::vector<std::string> &env_column,
                   int precision)
        : m_file_path(file_path)
        , m_hostname(hostname)
        , m_is_trace_enabled(do_trace)
        , m_buffer_limit(134217728) // 128 MiB
        , m_platform_io(platform_io)
        , m_env_column(env_column)
        , m_precision(precision)
    {
        if (m_env_column.empty()) {
            auto num_extra_cols = geopm_env_num_trace_signal();
            for (int i = 0; i < num_extra_cols; ++i) {
                m_env_column.push_back(geopm_env_trace_signal(i));
            }
        }

        if (m_is_trace_enabled) {
            std::ostringstream output_path;
            output_path << m_file_path << "-" << m_hostname;
            m_stream.open(output_path.str());
            if (!m_stream.good()) {
                std::cerr << "Warning: unable to open trace file '" << output_path.str()
                          << "': " << strerror(errno) << std::endl;
                m_is_trace_enabled = false;
            }

            // Header
            m_buffer << "# \"geopm_version\" : \"" << geopm_version() << "\",\n"
                     << "# \"start_time\" : \"" << start_time << "\",\n"
                     << "# \"profile_name\" : \"" << profile_name << "\",\n"
                     << "# \"node_name\" : \"" << m_hostname << "\",\n"
                     << "# \"agent\" : \"" << agent << "\"\n";
        }
    }

    Tracer::~Tracer()
    {
        if (m_stream.good() && m_is_trace_enabled) {
            m_stream << m_buffer.str();
            m_stream.close();
        }
    }

    void Tracer::columns(const std::vector<std::string> &agent_cols)
    {
        if (m_is_trace_enabled) {
            bool first = true;

            // default columns
            std::vector<IPlatformIO::m_request_s> base_columns({
                    {"TIME", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"EPOCH_COUNT", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"REGION_HASH", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"REGION_HINT", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"REGION_PROGRESS", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"REGION_RUNTIME", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"ENERGY_PACKAGE", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"ENERGY_DRAM", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"POWER_PACKAGE", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"POWER_DRAM", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"FREQUENCY", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"CYCLES_THREAD", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"CYCLES_REFERENCE", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"TEMPERATURE", IPlatformTopo::M_DOMAIN_BOARD, 0}});
            // for region entry/exit, make sure region index is known
            m_region_hash_idx = 2;
            m_region_hint_idx = 3;
            m_region_progress_idx = 4;
            m_region_runtime_idx = 5;

            // extra columns from environment
            for (const auto &extra : m_env_column) {
                base_columns.push_back({extra, IPlatformTopo::M_DOMAIN_BOARD, 0});
            }

            // set up columns to be sampled by Tracer
            for (const auto &col : base_columns) {
                m_column_idx.push_back(m_platform_io.push_signal(col.name,
                                                                 col.domain_type,
                                                                 col.domain_idx));
                if (col.name.find("#") != std::string::npos ||
                    col.name == "REGION_HASH" || col.name == "REGION_HINT") {
                    m_hex_column.insert(m_column_idx.back());
                }
                if (first) {
                    m_buffer << pretty_name(col);
                    first = false;
                }
                else {
                    m_buffer << "|" << pretty_name(col);
                }
            }

            // columns from agent; will be sampled by agent
            for (const auto &name : agent_cols) {
                m_buffer << "|" << name;
            }
            m_buffer << "\n";

            m_last_telemetry.resize(base_columns.size() + agent_cols.size());
        }
    }

    void Tracer::write_line(void)
    {
        m_buffer << std::setprecision(m_precision) << std::scientific;
        for (size_t idx = 0; idx < m_last_telemetry.size(); ++idx) {
            if (idx != 0) {
                m_buffer << "|";
            }
            if (m_hex_column.find(m_column_idx[idx]) != m_hex_column.end()) {
#ifdef GEOPM_DEBUG
                if ((uint64_t) m_last_telemetry[idx] == 0) {
                    throw Exception("Tracer::write_line(): Invalid hash or hint value detected.",
                                    GEOPM_ERROR_LOGIC, __FILE__, __LINE__);
                }
#endif
                m_buffer << "0x" << std::hex << std::setfill('0') << std::setw(16) << std::fixed;
                m_buffer << (uint64_t) m_last_telemetry[idx];
                m_buffer << std::setfill('\0') << std::setw(0) << std::scientific;
            }
            else if ((int)idx == m_region_progress_idx) {
                m_buffer << std::setprecision(1) << std::fixed
                         << m_last_telemetry[idx]
                         << std::setprecision(m_precision) << std::scientific;
            }
            else {
                m_buffer << m_last_telemetry[idx];
            }
        }
        m_buffer << "\n";
    }

    void Tracer::update(const std::vector<double> &agent_values,
                        std::list<geopm_region_info_s> region_entry_exit)
    {
        if (m_is_trace_enabled) {
#ifdef GEOPM_DEBUG
            if (m_column_idx.size() == 0) {
                throw Exception("Tracer::update(): No columns added to trace.",
                                GEOPM_ERROR_LOGIC, __FILE__, __LINE__);
            }
            if (m_column_idx.size() + agent_values.size() != m_last_telemetry.size()) {
                throw Exception("Tracer::update(): Last telemetry buffer not sized correctly.",
                                GEOPM_ERROR_LOGIC, __FILE__, __LINE__);
            }
#endif
            // save values to be reused for region entry/exit
            size_t col_idx = 0;
            for (; col_idx < m_column_idx.size(); ++col_idx) {
                m_last_telemetry[col_idx] = m_platform_io.sample(m_column_idx[col_idx]);
            }
            for (const auto &val : agent_values) {
                m_last_telemetry[col_idx] = val;
                ++col_idx;
            }
            // save region id and progress, which will get written over by entry/exit
            double region_hash = geopm_region_id_hash(m_last_telemetry[m_region_hash_idx]);
            double region_hint = geopm_region_id_hint(m_last_telemetry[m_region_hint_idx]);
            double region_progress = m_last_telemetry[m_region_progress_idx];
            double region_runtime = m_last_telemetry[m_region_runtime_idx];

            // insert samples for region entry/exit
            size_t idx = 0;
            for (const auto &reg : region_entry_exit) {
                // skip the last region entry if it matches the
                // sampled telemetry region hash, hint, and progress
                if (!((idx == region_entry_exit.size() - 1) &&
                      region_progress == reg.progress &&
                      region_progress == 0.0 &&
                      region_hash == geopm_region_id_hash(reg.region_id) &&
                      region_hint == geopm_region_id_hint(reg.region_id) )) {
                    m_last_telemetry[m_region_hash_idx] = geopm_region_id_hash(reg.region_id);
                    m_last_telemetry[m_region_hint_idx] = geopm_region_id_hint(reg.region_id);
                    m_last_telemetry[m_region_progress_idx] = reg.progress;
                    m_last_telemetry[m_region_runtime_idx] = reg.runtime;
                    write_line();
                }
                ++idx;
            }
            // print sampled data last
            m_last_telemetry[m_region_hash_idx] = region_hash;
            m_last_telemetry[m_region_hint_idx] = region_hint;
            m_last_telemetry[m_region_progress_idx] = region_progress;
            m_last_telemetry[m_region_runtime_idx] = region_runtime;
            write_line();
        }

        // if buffer is full, flush to file
        if (m_buffer.tellp() > m_buffer_limit) {
            m_stream << m_buffer.str();
            m_buffer.str("");
        }
    }

    void Tracer::flush(void)
    {
        m_stream << m_buffer.str();
        m_buffer.str("");
        m_stream.close();
        m_is_trace_enabled = false;
    }

    std::string ITracer::pretty_name(const IPlatformIO::m_request_s &col) {
        std::ostringstream result;
        std::string name = col.name;
        if (name.find("#") == name.length() - 1) {
            name = name.substr(0, name.length() - 1);
        }
        std::transform(name.begin(), name.end(), name.begin(),
                       [](unsigned char c){ return std::tolower(c); });
        result << name;
        if (col.domain_type != IPlatformTopo::M_DOMAIN_BOARD) {
            result << "-" << IPlatformTopo::domain_type_to_name(col.domain_type)
                   << "-" << col.domain_idx;
        }
        return result.str();
    }
}
<commit_msg>Fix throw in Tracer when reading hash and hint.<commit_after>/*
 * Copyright (c) 2015, 2016, 2017, 2018, 2019, Intel Corporation
 *
 * 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 Intel Corporation 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 LOG OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <unistd.h>
#include <limits.h>
#include <string.h>
#include <cctype>
#include <iomanip>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <time.h>

#include "Tracer.hpp"
#include "PlatformIO.hpp"
#include "PlatformTopo.hpp"
#include "Exception.hpp"
#include "Helper.hpp"
#include "geopm_env.h"
#include "geopm_hash.h"
#include "geopm_version.h"
#include "geopm.h"
#include "geopm_internal.h"
#include "geopm_region_id.h"
#include "config.h"

using geopm::IPlatformTopo;

namespace geopm
{
    Tracer::Tracer(const std::string &start_time)
        : Tracer(start_time, geopm_env_trace(), hostname(), geopm_env_agent(),
                 geopm_env_profile(), geopm_env_do_trace(), platform_io(),
                 {}, 16)
    {

    }

    Tracer::Tracer(const std::string &start_time,
                   const std::string &file_path,
                   const std::string &hostname,
                   const std::string &agent,
                   const std::string &profile_name,
                   bool do_trace,
                   IPlatformIO &platform_io,
                   const std::vector<std::string> &env_column,
                   int precision)
        : m_file_path(file_path)
        , m_hostname(hostname)
        , m_is_trace_enabled(do_trace)
        , m_buffer_limit(134217728) // 128 MiB
        , m_platform_io(platform_io)
        , m_env_column(env_column)
        , m_precision(precision)
    {
        if (m_env_column.empty()) {
            auto num_extra_cols = geopm_env_num_trace_signal();
            for (int i = 0; i < num_extra_cols; ++i) {
                m_env_column.push_back(geopm_env_trace_signal(i));
            }
        }

        if (m_is_trace_enabled) {
            std::ostringstream output_path;
            output_path << m_file_path << "-" << m_hostname;
            m_stream.open(output_path.str());
            if (!m_stream.good()) {
                std::cerr << "Warning: unable to open trace file '" << output_path.str()
                          << "': " << strerror(errno) << std::endl;
                m_is_trace_enabled = false;
            }

            // Header
            m_buffer << "# \"geopm_version\" : \"" << geopm_version() << "\",\n"
                     << "# \"start_time\" : \"" << start_time << "\",\n"
                     << "# \"profile_name\" : \"" << profile_name << "\",\n"
                     << "# \"node_name\" : \"" << m_hostname << "\",\n"
                     << "# \"agent\" : \"" << agent << "\"\n";
        }
    }

    Tracer::~Tracer()
    {
        if (m_stream.good() && m_is_trace_enabled) {
            m_stream << m_buffer.str();
            m_stream.close();
        }
    }

    void Tracer::columns(const std::vector<std::string> &agent_cols)
    {
        if (m_is_trace_enabled) {
            bool first = true;

            // default columns
            std::vector<IPlatformIO::m_request_s> base_columns({
                    {"TIME", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"EPOCH_COUNT", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"REGION_HASH", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"REGION_HINT", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"REGION_PROGRESS", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"REGION_RUNTIME", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"ENERGY_PACKAGE", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"ENERGY_DRAM", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"POWER_PACKAGE", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"POWER_DRAM", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"FREQUENCY", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"CYCLES_THREAD", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"CYCLES_REFERENCE", IPlatformTopo::M_DOMAIN_BOARD, 0},
                    {"TEMPERATURE", IPlatformTopo::M_DOMAIN_BOARD, 0}});
            // for region entry/exit, make sure region index is known
            m_region_hash_idx = 2;
            m_region_hint_idx = 3;
            m_region_progress_idx = 4;
            m_region_runtime_idx = 5;

            // extra columns from environment
            for (const auto &extra : m_env_column) {
                base_columns.push_back({extra, IPlatformTopo::M_DOMAIN_BOARD, 0});
            }

            // set up columns to be sampled by Tracer
            for (const auto &col : base_columns) {
                m_column_idx.push_back(m_platform_io.push_signal(col.name,
                                                                 col.domain_type,
                                                                 col.domain_idx));
                if (col.name.find("#") != std::string::npos ||
                    col.name == "REGION_HASH" || col.name == "REGION_HINT") {
                    m_hex_column.insert(m_column_idx.back());
                }
                if (first) {
                    m_buffer << pretty_name(col);
                    first = false;
                }
                else {
                    m_buffer << "|" << pretty_name(col);
                }
            }

            // columns from agent; will be sampled by agent
            for (const auto &name : agent_cols) {
                m_buffer << "|" << name;
            }
            m_buffer << "\n";

            m_last_telemetry.resize(base_columns.size() + agent_cols.size());
        }
    }

    void Tracer::write_line(void)
    {
        m_buffer << std::setprecision(m_precision) << std::scientific;
        for (size_t idx = 0; idx < m_last_telemetry.size(); ++idx) {
            if (idx != 0) {
                m_buffer << "|";
            }
            if (m_hex_column.find(m_column_idx[idx]) != m_hex_column.end()) {
#ifdef GEOPM_DEBUG
                if (((uint64_t) m_region_hash_idx == idx ||
                     (uint64_t) m_region_hint_idx == idx) &&
                    (uint64_t) m_last_telemetry[idx] == GEOPM_REGION_HASH_INVALID) {
                    throw Exception("Tracer::write_line(): Invalid hash or hint value detected.",
                                    GEOPM_ERROR_LOGIC, __FILE__, __LINE__);
                }
#endif
                m_buffer << "0x" << std::hex << std::setfill('0') << std::setw(16) << std::fixed;
                m_buffer << (uint64_t) m_last_telemetry[idx];
                m_buffer << std::setfill('\0') << std::setw(0) << std::scientific;
            }
            else if ((int)idx == m_region_progress_idx) {
                m_buffer << std::setprecision(1) << std::fixed
                         << m_last_telemetry[idx]
                         << std::setprecision(m_precision) << std::scientific;
            }
            else {
                m_buffer << m_last_telemetry[idx];
            }
        }
        m_buffer << "\n";
    }

    void Tracer::update(const std::vector<double> &agent_values,
                        std::list<geopm_region_info_s> region_entry_exit)
    {
        if (m_is_trace_enabled) {
#ifdef GEOPM_DEBUG
            if (m_column_idx.size() == 0) {
                throw Exception("Tracer::update(): No columns added to trace.",
                                GEOPM_ERROR_LOGIC, __FILE__, __LINE__);
            }
            if (m_column_idx.size() + agent_values.size() != m_last_telemetry.size()) {
                throw Exception("Tracer::update(): Last telemetry buffer not sized correctly.",
                                GEOPM_ERROR_LOGIC, __FILE__, __LINE__);
            }
#endif
            // save values to be reused for region entry/exit
            size_t col_idx = 0;
            for (; col_idx < m_column_idx.size(); ++col_idx) {
                m_last_telemetry[col_idx] = m_platform_io.sample(m_column_idx[col_idx]);
            }
            for (const auto &val : agent_values) {
                m_last_telemetry[col_idx] = val;
                ++col_idx;
            }
            // save region id and progress, which will get written over by entry/exit
            double region_hash = geopm_region_id_hash(m_last_telemetry[m_region_hash_idx]);
            double region_hint = geopm_region_id_hint(m_last_telemetry[m_region_hint_idx]);
            double region_progress = m_last_telemetry[m_region_progress_idx];
            double region_runtime = m_last_telemetry[m_region_runtime_idx];

            // insert samples for region entry/exit
            size_t idx = 0;
            for (const auto &reg : region_entry_exit) {
                // skip the last region entry if it matches the
                // sampled telemetry region hash, hint, and progress
                if (!((idx == region_entry_exit.size() - 1) &&
                      region_progress == reg.progress &&
                      region_progress == 0.0 &&
                      region_hash == geopm_region_id_hash(reg.region_id) &&
                      region_hint == geopm_region_id_hint(reg.region_id) )) {
                    m_last_telemetry[m_region_hash_idx] = geopm_region_id_hash(reg.region_id);
                    m_last_telemetry[m_region_hint_idx] = geopm_region_id_hint(reg.region_id);
                    m_last_telemetry[m_region_progress_idx] = reg.progress;
                    m_last_telemetry[m_region_runtime_idx] = reg.runtime;
                    write_line();
                }
                ++idx;
            }
            // print sampled data last
            m_last_telemetry[m_region_hash_idx] = region_hash;
            m_last_telemetry[m_region_hint_idx] = region_hint;
            m_last_telemetry[m_region_progress_idx] = region_progress;
            m_last_telemetry[m_region_runtime_idx] = region_runtime;
            write_line();
        }

        // if buffer is full, flush to file
        if (m_buffer.tellp() > m_buffer_limit) {
            m_stream << m_buffer.str();
            m_buffer.str("");
        }
    }

    void Tracer::flush(void)
    {
        m_stream << m_buffer.str();
        m_buffer.str("");
        m_stream.close();
        m_is_trace_enabled = false;
    }

    std::string ITracer::pretty_name(const IPlatformIO::m_request_s &col) {
        std::ostringstream result;
        std::string name = col.name;
        if (name.find("#") == name.length() - 1) {
            name = name.substr(0, name.length() - 1);
        }
        std::transform(name.begin(), name.end(), name.begin(),
                       [](unsigned char c){ return std::tolower(c); });
        result << name;
        if (col.domain_type != IPlatformTopo::M_DOMAIN_BOARD) {
            result << "-" << IPlatformTopo::domain_type_to_name(col.domain_type)
                   << "-" << col.domain_idx;
        }
        return result.str();
    }
}
<|endoftext|>


<commit_before>#include "Viewer.hpp"

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/freeglut.h>

#include <iostream>

Viewer* Viewer::instance_ = NULL;

Viewer::Viewer(std::string name, int width, int height) : name_(name), width_(width),
	height_(height), running_(false), thetaX_(0.0f), thetaY_(0.0f) {
}

Viewer::~Viewer() {
}

void Viewer::initGlut(int argc, char** argv) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
	glutInitWindowSize(width_, height_);
	glutInitWindowPosition((glutGet(GLUT_SCREEN_WIDTH) - width_) / 2, (glutGet(GLUT_SCREEN_HEIGHT) - height_) / 2);
	glutCreateWindow(name_.c_str());
}

void Viewer::initGl() {
	glEnable(GL_TEXTURE_2D);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);

	glCullFace(GL_BACK);
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
	glClearDepth(1.0f);
	glDepthFunc(GL_LEQUAL);
	glShadeModel(GL_SMOOTH);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f, (GLfloat)width_/(GLfloat)height_, 0.1f, 100.0f);
	glMatrixMode(GL_MODELVIEW);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_COLOR_MATERIAL);
}

void Viewer::setModel(const SmartPtr<Model>& model) {
	model_ = model;
}

void Viewer::start() {
	if (!running_) {
		running_ = true;
		glutMainLoop();
	}
}

void Viewer::stop() {
	if (running_)
		glutLeaveMainLoop();
}

void Viewer::idle() {
	glutPostRedisplay();
}

void Viewer::display() {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(0.0f, 0.0f, -5.0f);
	glRotatef(thetaX_, 1.0f, 0.0f, 0.0f);
	glRotatef(thetaY_, 0.0f, 1.0f, 0.0f);

	model_->render();

	glutSwapBuffers();
}

void Viewer::resize(int width, int height) {
	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION);
    glLoadIdentity();				// Reset The Projection Matrix
    gluPerspective(45.0f, (GLfloat)width_/(GLfloat)height_, 0.1f, 100.0f);
    glMatrixMode(GL_MODELVIEW);
}

void Viewer::keyDown(unsigned char key, int x, int y) {
	if (27 == key) {
		stop();
	}
}

void Viewer::specialKey(int key, int x, int y) {
	switch(key)	{
		case GLUT_KEY_UP:
			thetaX_ += 5.0f;
			break;

		case GLUT_KEY_DOWN:
			thetaX_ -= 5.0f;
			break;

		case GLUT_KEY_LEFT:
			thetaY_ -= 5.0f;
			break;

		case GLUT_KEY_RIGHT:
			thetaY_ += 5.0f;
			break;
	}
}

/*
 * Static callbacks
 */
void Viewer::setInstance(Viewer* instance) {
	instance_ = instance;
	glutIdleFunc(idleCallback);
	glutDisplayFunc(displayCallback);
	glutKeyboardFunc(keyDownCallback);
	glutSpecialFunc(specialKeyCallback);
}

void Viewer::idleCallback() {
	instance_->idle();
}

void Viewer::displayCallback() {
	instance_->display();
}

void Viewer::resizeCallback(int width, int height) {
	instance_->resize(width, height);
}

void Viewer::keyDownCallback(unsigned char key, int x, int y) {
	instance_->keyDown(key, x, y);
}

void Viewer::specialKeyCallback(int key, int x, int y) {
	instance_->specialKey(key, x, y);
}
<commit_msg>Minor formatting change.<commit_after>#include "Viewer.hpp"

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/freeglut.h>

#include <iostream>

Viewer* Viewer::instance_ = NULL;

Viewer::Viewer(std::string name, int width, int height) : name_(name), width_(width),
	height_(height), running_(false), thetaX_(0.0f), thetaY_(0.0f) {
}

Viewer::~Viewer() {
}

void Viewer::initGlut(int argc, char** argv) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
	glutInitWindowSize(width_, height_);
	glutInitWindowPosition((glutGet(GLUT_SCREEN_WIDTH) - width_) / 2, (glutGet(GLUT_SCREEN_HEIGHT) - height_) / 2);
	glutCreateWindow(name_.c_str());
}

void Viewer::initGl() {
	glEnable(GL_TEXTURE_2D);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);

	glCullFace(GL_BACK);
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
	glClearDepth(1.0f);
	glDepthFunc(GL_LEQUAL);
	glShadeModel(GL_SMOOTH);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f, (GLfloat)width_/(GLfloat)height_, 0.1f, 100.0f);
	glMatrixMode(GL_MODELVIEW);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_COLOR_MATERIAL);
}

void Viewer::setModel(const SmartPtr<Model>& model) {
	model_ = model;
}

void Viewer::start() {
	if (!running_) {
		running_ = true;
		glutMainLoop();
	}
}

void Viewer::stop() {
	if (running_)
		glutLeaveMainLoop();
}

void Viewer::idle() {
	glutPostRedisplay();
}

void Viewer::display() {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(0.0f, 0.0f, -5.0f);
	glRotatef(thetaX_, 1.0f, 0.0f, 0.0f);
	glRotatef(thetaY_, 0.0f, 1.0f, 0.0f);

	model_->render();

	glutSwapBuffers();
}

void Viewer::resize(int width, int height) {
	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f, (GLfloat)width_/(GLfloat)height_, 0.1f, 100.0f);
	glMatrixMode(GL_MODELVIEW);
}

void Viewer::keyDown(unsigned char key, int x, int y) {
	if (27 == key) {
		stop();
	}
}

void Viewer::specialKey(int key, int x, int y) {
	switch(key)	{
		case GLUT_KEY_UP:
			thetaX_ += 5.0f;
			break;

		case GLUT_KEY_DOWN:
			thetaX_ -= 5.0f;
			break;

		case GLUT_KEY_LEFT:
			thetaY_ -= 5.0f;
			break;

		case GLUT_KEY_RIGHT:
			thetaY_ += 5.0f;
			break;
	}
}

/*
 * Static callbacks
 */
void Viewer::setInstance(Viewer* instance) {
	instance_ = instance;
	glutIdleFunc(idleCallback);
	glutDisplayFunc(displayCallback);
	glutKeyboardFunc(keyDownCallback);
	glutSpecialFunc(specialKeyCallback);
}

void Viewer::idleCallback() {
	instance_->idle();
}

void Viewer::displayCallback() {
	instance_->display();
}

void Viewer::resizeCallback(int width, int height) {
	instance_->resize(width, height);
}

void Viewer::keyDownCallback(unsigned char key, int x, int y) {
	instance_->keyDown(key, x, y);
}

void Viewer::specialKeyCallback(int key, int x, int y) {
	instance_->specialKey(key, x, y);
}
<|endoftext|>


<commit_before>/************************************************************************************\
This source file is part of the Awesome Portable Rendering Interface Library         *
For latest info, see http://libapril.sourceforge.net/                                *
**************************************************************************************
Copyright (c) 2010 Ivan Vucica (ivan@vucica.net)                                     *
*                                                                                *
* This program is free software; you can redistribute it and/or modify it under      *
* the terms of the BSD license: http://www.opensource.org/licenses/bsd-license.php   *
\************************************************************************************/

#ifdef __APPLE__
#include <TargetConditionals.h>
#endif

#ifdef _WIN32
#include <windows.h>
#endif

#if !defined(__APPLE__) || defined(__APPLE__) && (TARGET_OS_MAC) && !(TARGET_OS_IPHONE)
	#ifdef HAVE_GLUT
		#include "GLUTWindow.h"
	#endif
	#ifdef HAVE_SDL
		#include "SDLWindow.h"
	#endif
	#ifdef _WIN32
		#include "Win32Window.h"
	#endif
#elif (TARGET_OS_IPHONE)
	#import <UIKit/UIKit.h>
	#include "iOSWindow.h"
#endif

#if TARGET_OS_MAC && !TARGET_OS_IPHONE
	#import <AppKit/NSScreen.h>
#endif

#include "Window.h"
#include "Keys.h"
#include "RenderSystem.h"

namespace April
{
	Window::Window()
	{
		mUpdateCallback=0;
		mMouseDownCallback=0;
		mMouseUpCallback=0;
		mMouseMoveCallback=0;
		mKeyDownCallback=0;
		mKeyUpCallback=0;
		mCharCallback=0;
		mQuitCallback=0;
		mFocusCallback=0;
	}

	void Window::setUpdateCallback(bool (*callback)(float))
	{
		mUpdateCallback=callback;
	}

	void Window::setMouseCallbacks(void (*mouse_dn)(float,float,int),
										void (*mouse_up)(float,float,int),
										void (*mouse_move)(float,float))
	{
		mMouseDownCallback=mouse_dn;
		mMouseUpCallback=mouse_up;
		mMouseMoveCallback=mouse_move;
	}
	void Window::setKeyboardCallbacks(void (*key_dn)(unsigned int),
									  void (*key_up)(unsigned int),
									  void (*char_callback)(unsigned int))
	{
		mKeyDownCallback=key_dn;
		mKeyUpCallback=key_up;
		mCharCallback=char_callback;
	}
	void Window::setQuitCallback(bool (*quit_callback)(bool))
	{
		mQuitCallback = quit_callback;
	}
	void Window::setWindowFocusCallback(void (*focus_callback)(bool))
	{
		mFocusCallback = focus_callback;
	}

	bool Window::isFullscreen()
	{
		return mFullscreen;
	}

	bool Window::performUpdate(float time_increase)
	{
		return mUpdateCallback(time_increase);
	}

	void Window::handleKeyEvent(KeyEventType type, KeySym keycode, unsigned int unicode)
	{
		if(keycode == AK_UNKNOWN)
		{
			mRenderSystem->logMessage("key event on unknown key");
			keycode = AK_NONE;
		}

		switch (type) {
			case AKEYEVT_DOWN:
				if (mKeyDownCallback && keycode != AK_NONE)
					mKeyDownCallback(keycode);

				if(unicode && mCharCallback)
					mCharCallback(unicode);
				break;
			case AKEYEVT_UP:
				if (mKeyUpCallback && keycode != AK_NONE)
					mKeyUpCallback(keycode);
			default:
				break;
		}
	}

	void Window::handleMouseEvent(MouseEventType event,float x,float y, MouseButton button)
	{

		switch (event) {
			case AMOUSEEVT_DOWN:
				if (mMouseDownCallback)
					mMouseDownCallback(x,y,button);

				break;
			case AMOUSEEVT_UP:
				if (mMouseUpCallback)
					mMouseUpCallback(x,y,button);
				break;

			case AMOUSEEVT_MOVE:
				if (mMouseMoveCallback)
					mMouseMoveCallback(x,y);
				break;
		}
	}

	bool Window::handleQuitRequest(bool can_reject)
	{
		// returns whether or not the windowing system is permitted to close the window
		if(mQuitCallback)
		{
			return mQuitCallback(can_reject);
		}
		return true;
	}

	void Window::handleFocusEvent(bool has_focus)
	{
		if(has_focus)
		{
			printf("GAINED FOCUS\n");
		}
		else
		{
			printf("LOST FOCUS\n");
		}

		if(mFocusCallback)
		{
			mFocusCallback(has_focus);
		}
	}

	void Window::beginKeyboardHandling()
	{
		// ignore by default
		// used only for softkeyboards, e.g. iOS
	}
	void Window::terminateKeyboardHandling()
	{
		// ignore by default
		// used only for softkeyboards, e.g. iOS
	}

	///////////////////////
	// non members
	///////////////////////

	Window* createAprilWindow(chstr winsysname, int w, int h, bool fullscreen, chstr title)
	{
#if !defined(__APPLE__) || defined(__APPLE__) && (TARGET_OS_MAC) && !(TARGET_OS_IPHONE)
		// desktop
	#ifdef HAVE_SDL
		if (winsysname=="SDL") {
			return new SDLWindow(w,h,fullscreen,title);
		}
	#endif
	#ifdef _WIN32
		if(winsysname=="Win32") {
			return new Win32Window(w,h,fullscreen,title);
		}
	#endif
	#ifdef HAVE_GLUT
		return new GLUTWindow(w,h,fullscreen,title);
	#endif

#elif (TARGET_OS_IPHONE)
		// iOS
		return new iOSWindow(w,h,fullscreen,title);
#endif
		return 0;
	}

	gtypes::Vector2 getDesktopResolution()
	{
#ifdef _WIN32
		return gtypes::Vector2(GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN));
#elif (TARGET_OS_IPHONE)

		UIScreen* mainScreen = [UIScreen mainScreen];
		float scale=1;

		if ([mainScreen respondsToSelector:@selector(scale:)]) {
			scale = [mainScreen scale];
		}

		// TODO dont flip width and height when in portrait mode
		int w = mainScreen.bounds.size.height * scale;
		int h = mainScreen.bounds.size.width * scale;
		return gtypes::Vector2(w, h);
#elif (TARGET_OS_MAC)
		NSScreen* mainScreen = [NSScreen mainScreen];

		NSRect rect = [mainScreen frame];
		return gtypes::Vector2(rect.size.width, rect.size.height);
#else
		return gtypes::Vector2(1024,768);
#endif
	}

}
<commit_msg>Removed some unneeded output<commit_after>/************************************************************************************\
This source file is part of the Awesome Portable Rendering Interface Library         *
For latest info, see http://libapril.sourceforge.net/                                *
**************************************************************************************
Copyright (c) 2010 Ivan Vucica (ivan@vucica.net)                                     *
*                                                                                *
* This program is free software; you can redistribute it and/or modify it under      *
* the terms of the BSD license: http://www.opensource.org/licenses/bsd-license.php   *
\************************************************************************************/

#ifdef __APPLE__
#include <TargetConditionals.h>
#endif

#ifdef _WIN32
#include <windows.h>
#endif

#if !defined(__APPLE__) || defined(__APPLE__) && (TARGET_OS_MAC) && !(TARGET_OS_IPHONE)
	#ifdef HAVE_GLUT
		#include "GLUTWindow.h"
	#endif
	#ifdef HAVE_SDL
		#include "SDLWindow.h"
	#endif
	#ifdef _WIN32
		#include "Win32Window.h"
	#endif
#elif (TARGET_OS_IPHONE)
	#import <UIKit/UIKit.h>
	#include "iOSWindow.h"
#endif

#if TARGET_OS_MAC && !TARGET_OS_IPHONE
	#import <AppKit/NSScreen.h>
#endif

#include "Window.h"
#include "Keys.h"
#include "RenderSystem.h"

namespace April
{
	Window::Window()
	{
		mUpdateCallback=0;
		mMouseDownCallback=0;
		mMouseUpCallback=0;
		mMouseMoveCallback=0;
		mKeyDownCallback=0;
		mKeyUpCallback=0;
		mCharCallback=0;
		mQuitCallback=0;
		mFocusCallback=0;
	}

	void Window::setUpdateCallback(bool (*callback)(float))
	{
		mUpdateCallback=callback;
	}

	void Window::setMouseCallbacks(void (*mouse_dn)(float,float,int),
										void (*mouse_up)(float,float,int),
										void (*mouse_move)(float,float))
	{
		mMouseDownCallback=mouse_dn;
		mMouseUpCallback=mouse_up;
		mMouseMoveCallback=mouse_move;
	}
	void Window::setKeyboardCallbacks(void (*key_dn)(unsigned int),
									  void (*key_up)(unsigned int),
									  void (*char_callback)(unsigned int))
	{
		mKeyDownCallback=key_dn;
		mKeyUpCallback=key_up;
		mCharCallback=char_callback;
	}
	void Window::setQuitCallback(bool (*quit_callback)(bool))
	{
		mQuitCallback = quit_callback;
	}
	void Window::setWindowFocusCallback(void (*focus_callback)(bool))
	{
		mFocusCallback = focus_callback;
	}

	bool Window::isFullscreen()
	{
		return mFullscreen;
	}

	bool Window::performUpdate(float time_increase)
	{
		return mUpdateCallback(time_increase);
	}

	void Window::handleKeyEvent(KeyEventType type, KeySym keycode, unsigned int unicode)
	{
		if(keycode == AK_UNKNOWN)
		{
			mRenderSystem->logMessage("key event on unknown key");
			keycode = AK_NONE;
		}

		switch (type) {
			case AKEYEVT_DOWN:
				if (mKeyDownCallback && keycode != AK_NONE)
					mKeyDownCallback(keycode);

				if(unicode && mCharCallback)
					mCharCallback(unicode);
				break;
			case AKEYEVT_UP:
				if (mKeyUpCallback && keycode != AK_NONE)
					mKeyUpCallback(keycode);
			default:
				break;
		}
	}

	void Window::handleMouseEvent(MouseEventType event,float x,float y, MouseButton button)
	{

		switch (event) {
			case AMOUSEEVT_DOWN:
				if (mMouseDownCallback)
					mMouseDownCallback(x,y,button);

				break;
			case AMOUSEEVT_UP:
				if (mMouseUpCallback)
					mMouseUpCallback(x,y,button);
				break;

			case AMOUSEEVT_MOVE:
				if (mMouseMoveCallback)
					mMouseMoveCallback(x,y);
				break;
		}
	}

	bool Window::handleQuitRequest(bool can_reject)
	{
		// returns whether or not the windowing system is permitted to close the window
		if(mQuitCallback)
		{
			return mQuitCallback(can_reject);
		}
		return true;
	}

	void Window::handleFocusEvent(bool has_focus)
	{
		if(mFocusCallback)
		{
			mFocusCallback(has_focus);
		}
	}

	void Window::beginKeyboardHandling()
	{
		// ignore by default
		// used only for softkeyboards, e.g. iOS
	}
	void Window::terminateKeyboardHandling()
	{
		// ignore by default
		// used only for softkeyboards, e.g. iOS
	}

	///////////////////////
	// non members
	///////////////////////

	Window* createAprilWindow(chstr winsysname, int w, int h, bool fullscreen, chstr title)
	{
#if !defined(__APPLE__) || defined(__APPLE__) && (TARGET_OS_MAC) && !(TARGET_OS_IPHONE)
		// desktop
	#ifdef HAVE_SDL
		if (winsysname=="SDL") {
			return new SDLWindow(w,h,fullscreen,title);
		}
	#endif
	#ifdef _WIN32
		if(winsysname=="Win32") {
			return new Win32Window(w,h,fullscreen,title);
		}
	#endif
	#ifdef HAVE_GLUT
		return new GLUTWindow(w,h,fullscreen,title);
	#endif

#elif (TARGET_OS_IPHONE)
		// iOS
		return new iOSWindow(w,h,fullscreen,title);
#endif
		return 0;
	}

	gtypes::Vector2 getDesktopResolution()
	{
#ifdef _WIN32
		return gtypes::Vector2(GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN));
#elif (TARGET_OS_IPHONE)

		UIScreen* mainScreen = [UIScreen mainScreen];
		float scale=1;

		if ([mainScreen respondsToSelector:@selector(scale:)]) {
			scale = [mainScreen scale];
		}

		// TODO dont flip width and height when in portrait mode
		int w = mainScreen.bounds.size.height * scale;
		int h = mainScreen.bounds.size.width * scale;
		return gtypes::Vector2(w, h);
#elif (TARGET_OS_MAC)
		NSScreen* mainScreen = [NSScreen mainScreen];

		NSRect rect = [mainScreen frame];
		return gtypes::Vector2(rect.size.width, rect.size.height);
#else
		return gtypes::Vector2(1024,768);
#endif
	}

}
<|endoftext|>