<commit_before>//System includes
#include <fstream>
#include <iostream>
#include <ctime>
#include <string>
#include <cstdlib>
#include <iomanip>

// Point
#include "point.h"

// Ugly fixes
#include <assert.h>
#define KRATOS_ERROR std::cout

// Kratos Independent
#define KRATOS_INDEPENDENT

// Kratos includes
#include "spatial_containers/spatial_containers.h"

#include "points_bins.h"

double GetCurrentTime() {
#ifndef _OPENMP
	return std::clock() / static_cast<double>(CLOCKS_PER_SEC);
#else
	return omp_get_wtime();
#endif
}

template< class T, std::size_t dim >
class PointDistance2 {
public:
	double operator()(T const& p1, T const& p2) {
		double dist = 0.0;
		for (std::size_t i = 0; i < dim; i++) {
			double tmp = p1[i] - p2[i];
			dist += tmp*tmp;
		}
		return dist;
	}
};

template<class SearchStructureType, class PointType, class IteratorType, class DistanceIterator>
void RunTestsOldInterface(char const Title[], IteratorType PBegin, IteratorType PEnd, IteratorType results0, DistanceIterator distances0, std::size_t MaxResults, PointType* allPoints, double radius0, std::size_t numsearch, std::size_t bucket_size) {
	double t0, t1;
	std::size_t n;

	std::size_t npoints = PEnd - PBegin;
	std::vector<std::size_t> numresArray(numsearch);
	PointType& point0 = allPoints[0];

	std::size_t numsearch_nearest = 100 * numsearch;

	t0 = GetCurrentTime();
	SearchStructureType nodes_tree(PBegin, PEnd);
	t1 = GetCurrentTime();
	std::cout << Title << "\t" << t1 - t0 << "\t";

	t0 = GetCurrentTime();
  #pragma omp parallel for
	for (std::size_t i = 0; i < numsearch; i++) {
		n = nodes_tree.SearchInRadius(point0, radius0, results0, distances0, MaxResults);
  }
	t1 = GetCurrentTime();
	std::cout << t1 - t0 << "\t";

	t0 = GetCurrentTime();
	for (std::size_t i = 0; i < numsearch; i++) {
		n = nodes_tree.SearchInRadius(point0, radius0, results0, distances0, MaxResults);
  }
	t1 = GetCurrentTime();
	std::cout << t1 - t0 << "\t";

	PointType** PNearestArray = new PointType*[numsearch];
	std::vector<double> distancesArrayNearest(numsearch);
	PointType* PNearest = PNearestArray[0];

	t0 = GetCurrentTime();
	for (std::size_t i = 0; i < 100; i++) {
		nodes_tree.SearchNearestPoint(allPoints, numsearch, PNearestArray, distancesArrayNearest);
  }
	t1 = GetCurrentTime();

	std::cout << t1 - t0 << "\t";
	double distance = 0;

	t0 = GetCurrentTime();
	for (std::size_t i = 0; i < numsearch_nearest; i++) {
		PNearest = nodes_tree.SearchNearestPoint(point0, distance);
  }
	t1 = GetCurrentTime();
	std::cout << t1 - t0 << "\t";

	std::cout << n << "\t" << *PNearestArray[0] << std::endl;
};

template<class BinsType>
void RunTestsNewInterface(char const Title[], std::vector<Point<3>> & points_vector, const Point<3> & search_point, double radius, std::size_t numsearch, std::size_t numsearch_nearest) {
  double t0 = GetCurrentTime();
  BinsType bins(points_vector.begin(), points_vector.end());
  double t1 = GetCurrentTime();
  std::cout << "Points Bin" << "\t" << t1 - t0 << "\t";

  std::vector<PointsBins<Point<3>>::ResultType> results;
  PointsBins<Point<3>>::ResultType nearest_point_result;

  t0 = GetCurrentTime();
  #pragma omp parallel for firstprivate(results)
  for (std::size_t i = 0; i < numsearch; i++) {
    results.clear();
    bins.SearchInRadius(search_point, radius, results);
  }
  t1 = GetCurrentTime();
  std::cout << t1 - t0 << "\t";

  t0 = GetCurrentTime();
  for (std::size_t i = 0; i < numsearch; i++) {
    results.clear();
    bins.SearchInRadius(search_point, radius, results);
  }
  t1 = GetCurrentTime();
  std::cout << t1 - t0 << "\t";

  t0 = GetCurrentTime();

  #pragma omp parallel for firstprivate(nearest_point_result)
  for (std::size_t i = 0; i < numsearch_nearest; i++) {
    nearest_point_result = bins.SearchNearest(search_point);
  }
  t1 = GetCurrentTime();
  std::cout << t1 - t0 << "\t";

  t0 = GetCurrentTime();
  for (std::size_t i = 0; i < numsearch_nearest; i++) {
    nearest_point_result = bins.SearchNearest(search_point);
  }
  t1 = GetCurrentTime();
  std::cout << t1 - t0 << "\t" << results.size() << "\t" << *nearest_point_result.Get();
  std::cout << std::endl;
}

int main(int arg, char* argv[]) {
	constexpr std::size_t Dim = 3;

	typedef Point<Dim>       PointType;

	typedef PointType *      PtrPointType;
	typedef PtrPointType *   PointVector;
	typedef PtrPointType *   PointIterator;

	typedef double* DistanceVector;
	typedef double* DistanceIterator;

	typedef Kratos::Bucket<Dim, PointType, PointVector, PtrPointType, PointIterator, DistanceIterator, PointDistance2<PointType, Dim>>       bucket_type;  //Bucket;
	typedef Kratos::Bins<Dim, PointType, PointVector, PtrPointType, PointIterator, DistanceIterator, PointDistance2<PointType, Dim>>         StaticBinsType;           //StaticBins;
	typedef Kratos::BinsDynamic<Dim, PointType, PointVector, PtrPointType, PointIterator, DistanceIterator, PointDistance2<PointType, Dim>>  DynamicBinsType; //DynamicBins;

	typedef Kratos::Tree< Kratos::KDTreePartition<bucket_type>>                  kdtree_type;                //Kdtree;
	typedef Kratos::Tree< Kratos::KDTreePartitionAverageSplit<bucket_type>>      kdtree_average_split_type;  //Kdtree;
	typedef Kratos::Tree< Kratos::KDTreePartitionMidPointSplit<bucket_type>>     kdtree_midpoint_split_type; //Kdtree;
	typedef Kratos::Tree< Kratos::OCTreePartition<bucket_type>>                  OctreeType;                 //Octree;
	typedef Kratos::Tree< Kratos::KDTreePartitionMidPointSplit<StaticBinsType>>  kdtree_StaticBinsType;      //KdtreeBins;
	typedef Kratos::Tree< Kratos::OCTreePartition<StaticBinsType>>               octree_StaticBinsType;      //OctreeBins;
	typedef Kratos::Tree< Kratos::KDTreePartitionMidPointSplit<DynamicBinsType>> kdtree_DynamicBinsType;     //KdtreeBins;
	typedef Kratos::Tree< Kratos::OCTreePartition<DynamicBinsType>>              octree_bins_type;           //OctreeBins;

	// Input data
	std::cout << std::setprecision(4) << std::fixed;

	PointVector points;
	std::string filename;

	double radius = 0.02;

	if (arg == 1) {
		std::cout << "Argument not founded " << std::endl;
		return 0;
	}

	filename = argv[1];

	if (arg == 3) {
		radius = atof(argv[2]) / 1000000;
	}

	std::ifstream input;
	input.open(filename.c_str());

	if (!input) {
		std::cout << "Cannot open data file" << std::endl;
		return 0;
	}

	PointType   point;
	std::size_t npoints;

	//Read GiD .post.msh format files NYI
	//     std::string GiD_Header;
	//     std::string Token;
	//
	//     std::getline(input,GiD_Header)  //GiD Header
	//     std::getline(input,Token)       //CoCoordinates

	input >> npoints;

	points = new PointType*[npoints];

	std::size_t pid;

	for (std::size_t i = 0; i < npoints; i++) {
		input >> pid;
		input >> point;

		points[i] = new PointType(point);
		points[i]->id = pid;
	}

	PointType min_point(*points[0]);
	PointType max_point(*points[0]);
	PointType mid_point;

	min_point.id = 0;
	max_point.id = 0;
	mid_point.id = 0;

	for (std::size_t i = 0; i < npoints; i++) {
		for (std::size_t j = 0; j < 3; j++) {
			if (min_point[j] > (*points[i])[j]) min_point[j] = (*points[i])[j];
			if (max_point[j] < (*points[i])[j]) max_point[j] = (*points[i])[j];
		}
	}

	for (std::size_t i = 0; i < Dim; i++) {
		mid_point.coord[i] = (max_point[i] + min_point[i]) / 2.00;
	}

	// Output data Info
	PointType & search_point = mid_point;

	std::size_t numsearch = 100000;
	std::size_t numsearch_nearest = numsearch * 100;

	std::cout << " min point : " << min_point << std::endl;
	std::cout << " max point : " << max_point << std::endl;
	std::cout << " search_point : " << search_point << std::endl;
	std::cout << " search radius : " << radius << std::endl;
	std::cout << std::endl;

	std::cout << " Number of Points : " << npoints << std::endl;
	std::cout << " Number of Repetitions : " << numsearch << std::endl;
	std::cout << std::endl;

	std::cout << "SS\t\tGEN\tSIROMP\tSIRSER\tSNPOMP\tSNPSER\tNOFR\tNP" << std::endl;

	// Data Setup
	PointType * allPoints;
	allPoints = new PointType[numsearch];

	std::size_t max_results = 100;// npoints;
	for (std::size_t i = 0; i < 1; i++) {
		allPoints[i] = search_point;
	}

	//Prepare the search point, search radius and resut arrays
	DistanceIterator distances = new double[npoints];
	PointIterator p_results = new PtrPointType[max_results];

	// Point-Based Search Structures
	std::vector<Point<3>> points_vector;
	for (std::size_t i = 0; i < npoints; i++) {
		points_vector.push_back(*(points[i]));
	}

  // New Interface
  RunTestsNewInterface<PointsBins<Point<3>>>("PointBins", points_vector, search_point, radius, numsearch, numsearch_nearest);

  // Old Interface
	RunTestsOldInterface<StaticBinsType>("StaticBins", points, points + npoints, p_results, distances, max_results, allPoints, radius, numsearch, 1);
	RunTestsOldInterface<DynamicBinsType>("DynamicBins", points, points + npoints, p_results, distances, max_results, allPoints, radius, numsearch, 1);
  RunTestsOldInterface<OctreeType>("OcTree\t", points, points + npoints, p_results, distances, max_results, allPoints, radius, numsearch, 10);

  //RunTestsOldInterface<kdtree_type>("KdTree\t", points, points + npoints, p_results, distances, max_results, allPoints, radius, numsearch, 10);
	//RunTestsOldInterface<kdtree_average_split_type>("KdTreeAverage", points, points + npoints, resultsArray, distancesArray, max_results, allPoints, radiusArray, numsearch, 10);
	//RunTestsOldInterface<kdtree_midpoint_split_type>("KdTreeMidpoint", points, points + npoints, resultsArray, distancesArray, max_results, allPoints, radiusArray, numsearch, 10);

	return 0;
}
<commit_msg>Cleanup<commit_after>//System includes
#include <fstream>
#include <iostream>
#include <ctime>
#include <string>
#include <cstdlib>
#include <iomanip>

// Point
#include "point.h"

// Ugly fixes
#include <assert.h>
#define KRATOS_ERROR std::cout

// Kratos Independent
#define KRATOS_INDEPENDENT

// Kratos includes
#include "spatial_containers/spatial_containers.h"

#include "points_bins.h"

double GetCurrentTime() {
#ifndef _OPENMP
	return std::clock() / static_cast<double>(CLOCKS_PER_SEC);
#else
	return omp_get_wtime();
#endif
}

template< class T, std::size_t dim >
class PointDistance2 {
public:
	double operator()(T const& p1, T const& p2) {
		double dist = 0.0;
		for (std::size_t i = 0; i < dim; i++) {
			double tmp = p1[i] - p2[i];
			dist += tmp*tmp;
		}
		return dist;
	}
};

template<class SearchStructureType, class PointType, class IteratorType, class DistanceIterator>
void RunTestsOldInterface(char const Title[], IteratorType PBegin, IteratorType PEnd, IteratorType results0, DistanceIterator distances0, std::size_t MaxResults, PointType* allPoints, double radius0, std::size_t numsearch, std::size_t bucket_size) {
	double t0, t1;
	std::size_t n;

	std::size_t npoints = PEnd - PBegin;
	std::vector<std::size_t> numresArray(numsearch);
	PointType& point0 = allPoints[0];

	std::size_t numsearch_nearest = 100 * numsearch;

	t0 = GetCurrentTime();
	SearchStructureType nodes_tree(PBegin, PEnd);
	t1 = GetCurrentTime();
	std::cout << Title << "\t" << t1 - t0 << "\t";

	t0 = GetCurrentTime();
  #pragma omp parallel for
	for (std::size_t i = 0; i < numsearch; i++) {
		n = nodes_tree.SearchInRadius(point0, radius0, results0, distances0, MaxResults);
  }
	t1 = GetCurrentTime();
	std::cout << t1 - t0 << "\t";

	t0 = GetCurrentTime();
	for (std::size_t i = 0; i < numsearch; i++) {
		n = nodes_tree.SearchInRadius(point0, radius0, results0, distances0, MaxResults);
  }
	t1 = GetCurrentTime();
	std::cout << t1 - t0 << "\t";

	PointType** PNearestArray = new PointType*[numsearch];
	std::vector<double> distancesArrayNearest(numsearch);
	PointType* PNearest = PNearestArray[0];

	t0 = GetCurrentTime();
	for (std::size_t i = 0; i < 100; i++) {
		nodes_tree.SearchNearestPoint(allPoints, numsearch, PNearestArray, distancesArrayNearest);
  }
	t1 = GetCurrentTime();

	std::cout << t1 - t0 << "\t";
	double distance = 0;

	t0 = GetCurrentTime();
	for (std::size_t i = 0; i < numsearch_nearest; i++) {
		PNearest = nodes_tree.SearchNearestPoint(point0, distance);
  }
	t1 = GetCurrentTime();
	std::cout << t1 - t0 << "\t";

	std::cout << n << "\t" << *PNearestArray[0] << std::endl;
};

template<class BinsType>
void RunTestsNewInterface(char const Title[], std::vector<Point<3>> & points_vector, const Point<3> & search_point, double radius, std::size_t numsearch, std::size_t numsearch_nearest) {
  double t0 = GetCurrentTime();
  BinsType bins(points_vector.begin(), points_vector.end());
  double t1 = GetCurrentTime();
  std::cout << "Points Bin" << "\t" << t1 - t0 << "\t";

  std::vector<PointsBins<Point<3>>::ResultType> results;
  PointsBins<Point<3>>::ResultType nearest_point_result;

  t0 = GetCurrentTime();
  #pragma omp parallel for firstprivate(results)
  for (std::size_t i = 0; i < numsearch; i++) {
    results.clear();
    bins.SearchInRadius(search_point, radius, results);
  }
  t1 = GetCurrentTime();
  std::cout << t1 - t0 << "\t";

  t0 = GetCurrentTime();
  for (std::size_t i = 0; i < numsearch; i++) {
    results.clear();
    bins.SearchInRadius(search_point, radius, results);
  }
  t1 = GetCurrentTime();
  std::cout << t1 - t0 << "\t";

  t0 = GetCurrentTime();

  #pragma omp parallel for firstprivate(nearest_point_result)
  for (std::size_t i = 0; i < numsearch_nearest; i++) {
    nearest_point_result = bins.SearchNearest(search_point);
  }
  t1 = GetCurrentTime();
  std::cout << t1 - t0 << "\t";

  t0 = GetCurrentTime();
  for (std::size_t i = 0; i < numsearch_nearest; i++) {
    nearest_point_result = bins.SearchNearest(search_point);
  }
  t1 = GetCurrentTime();
  std::cout << t1 - t0 << "\t" << results.size() << "\t" << *nearest_point_result.Get();
  std::cout << std::endl;
}

int main(int arg, char* argv[]) {
	constexpr std::size_t Dim = 3;

	typedef Point<Dim>       PointType;

	typedef PointType *      PtrPointType;
	typedef PtrPointType *   PointVector;
	typedef PtrPointType *   PointIterator;

	typedef double* DistanceVector;
	typedef double* DistanceIterator;

	typedef Kratos::Bucket<Dim, PointType, PointVector, PtrPointType, PointIterator, DistanceIterator, PointDistance2<PointType, Dim>>       bucket_type;  //Bucket;
	typedef Kratos::Bins<Dim, PointType, PointVector, PtrPointType, PointIterator, DistanceIterator, PointDistance2<PointType, Dim>>         StaticBinsType;           //StaticBins;
	typedef Kratos::BinsDynamic<Dim, PointType, PointVector, PtrPointType, PointIterator, DistanceIterator, PointDistance2<PointType, Dim>>  DynamicBinsType; //DynamicBins;

	typedef Kratos::Tree< Kratos::KDTreePartition<bucket_type>>                  kdtree_type;                //Kdtree;
	typedef Kratos::Tree< Kratos::KDTreePartitionAverageSplit<bucket_type>>      kdtree_average_split_type;  //Kdtree;
	typedef Kratos::Tree< Kratos::KDTreePartitionMidPointSplit<bucket_type>>     kdtree_midpoint_split_type; //Kdtree;
	typedef Kratos::Tree< Kratos::OCTreePartition<bucket_type>>                  OctreeType;                 //Octree;
	typedef Kratos::Tree< Kratos::KDTreePartitionMidPointSplit<StaticBinsType>>  kdtree_StaticBinsType;      //KdtreeBins;
	typedef Kratos::Tree< Kratos::OCTreePartition<StaticBinsType>>               octree_StaticBinsType;      //OctreeBins;
	typedef Kratos::Tree< Kratos::KDTreePartitionMidPointSplit<DynamicBinsType>> kdtree_DynamicBinsType;     //KdtreeBins;
	typedef Kratos::Tree< Kratos::OCTreePartition<DynamicBinsType>>              octree_bins_type;           //OctreeBins;

	// Input data
	std::cout << std::setprecision(4) << std::fixed;

	PointVector points;
	std::string filename;

	double radius = 0.02;

	if (arg == 1) {
		std::cout << "Argument not founded " << std::endl;
		return 0;
	}

	filename = argv[1];

	if (arg == 3) {
		radius = atof(argv[2]) / 1000000;
	}

	std::ifstream input;
	input.open(filename.c_str());

	if (!input) {
		std::cout << "Cannot open data file" << std::endl;
		return 0;
	}

	PointType   point;
	std::size_t npoints;

	input >> npoints;
	points = new PointType*[npoints];

	std::size_t pid;

	for (std::size_t i = 0; i < npoints; i++) {
		input >> pid;
		input >> point;

		points[i] = new PointType(point);
		points[i]->id = pid;
	}

	PointType min_point(*points[0]);
	PointType max_point(*points[0]);
	PointType mid_point;

	min_point.id = 0;
	max_point.id = 0;
	mid_point.id = 0;

	for (std::size_t i = 0; i < npoints; i++) {
		for (std::size_t j = 0; j < 3; j++) {
			if (min_point[j] > (*points[i])[j]) min_point[j] = (*points[i])[j];
			if (max_point[j] < (*points[i])[j]) max_point[j] = (*points[i])[j];
		}
	}

	for (std::size_t i = 0; i < Dim; i++) {
		mid_point.coord[i] = (max_point[i] + min_point[i]) / 2.00;
	}

	// Output data Info
	PointType & search_point = mid_point;

	std::size_t numsearch = 100000;
	std::size_t numsearch_nearest = numsearch * 100;

	std::cout << " min point : " << min_point << std::endl;
	std::cout << " max point : " << max_point << std::endl;
	std::cout << " search_point : " << search_point << std::endl;
	std::cout << " search radius : " << radius << std::endl;
	std::cout << std::endl;

	std::cout << " Number of Points : " << npoints << std::endl;
	std::cout << " Number of Repetitions : " << numsearch << std::endl;
	std::cout << std::endl;

	std::cout << "SS\t\tGEN\tSIROMP\tSIRSER\tSNPOMP\tSNPSER\tNOFR\tNP" << std::endl;

	// Data Setup
	PointType * allPoints;
	allPoints = new PointType[numsearch];

	std::size_t max_results = 100;// npoints;
	for (std::size_t i = 0; i < 1; i++) {
		allPoints[i] = search_point;
	}

	//Prepare the search point, search radius and resut arrays
	DistanceIterator distances = new double[npoints];
	PointIterator p_results = new PtrPointType[max_results];

	// Point-Based Search Structures
	std::vector<Point<3>> points_vector;
	for (std::size_t i = 0; i < npoints; i++) {
		points_vector.push_back(*(points[i]));
	}

  // New Interface
  RunTestsNewInterface<PointsBins<Point<3>>>("PointBins", points_vector, search_point, radius, numsearch, numsearch_nearest);

  // Old Interface
	RunTestsOldInterface<StaticBinsType>("StaticBins", points, points + npoints, p_results, distances, max_results, allPoints, radius, numsearch, 1);
	RunTestsOldInterface<DynamicBinsType>("DynamicBins", points, points + npoints, p_results, distances, max_results, allPoints, radius, numsearch, 1);
  RunTestsOldInterface<OctreeType>("OcTree\t", points, points + npoints, p_results, distances, max_results, allPoints, radius, numsearch, 10);

  //RunTestsOldInterface<kdtree_type>("KdTree\t", points, points + npoints, p_results, distances, max_results, allPoints, radius, numsearch, 10);
	//RunTestsOldInterface<kdtree_average_split_type>("KdTreeAverage", points, points + npoints, resultsArray, distancesArray, max_results, allPoints, radiusArray, numsearch, 10);
	//RunTestsOldInterface<kdtree_midpoint_split_type>("KdTreeMidpoint", points, points + npoints, resultsArray, distancesArray, max_results, allPoints, radiusArray, numsearch, 10);

	return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "native_client/src/include/portability.h"

#if NACL_OSX
#include <crt_externs.h>
#endif

#ifdef _WIN64  /* TODO(gregoryd): remove this when win64 issues are fixed */
#define NACL_NO_INLINE
#endif

EXTERN_C_BEGIN
#include "native_client/src/shared/platform/nacl_sync.h"
#include "native_client/src/shared/platform/nacl_sync_checked.h"
#include "native_client/src/trusted/service_runtime/nacl_globals.h"
#include "native_client/src/trusted/service_runtime/expiration.h"
#include "native_client/src/trusted/service_runtime/nacl_app.h"
#include "native_client/src/trusted/service_runtime/nacl_all_modules.h"
#include "native_client/src/trusted/service_runtime/sel_ldr.h"
#include "native_client/src/trusted/platform_qualify/nacl_os_qualify.h"
EXTERN_C_END

int verbosity = 0;

#ifdef __GNUC__

/*
 * GDB's canonical overlay managment routine.
 * We need its symbol in the symbol table so don't inline it.
 * Note: _ovly_debug_event has to be an unmangled 'C' style symbol.
 * TODO(dje): add some explanation for the non-GDB person.
 */
EXTERN_C_BEGIN
static void __attribute__ ((noinline)) _ovly_debug_event (void) {
  /*
   * The asm volatile is here as instructed by the GCC docs.
   * It's not enough to declare a function noinline.
   * GCC will still look inside the function to see if it's worth calling.
   */
  asm volatile ("");
}
EXTERN_C_END

#endif

static void StopForDebuggerInit(const struct NaClApp *state) {
  /* Put xlate_base in a place where gdb can find it.  */
  nacl_global_xlate_base = state->mem_start;

#ifdef __GNUC__
  _ovly_debug_event();
#endif
}

int SelMain(const int desc, const NaClHandle handle) {
  char *av[1];
  int ac = 1;

  char                          **envp;
  struct NaClApp                state;
  int                           main_thread_only = 1;
  int                           export_addr_to = -2;

  struct NaClApp                *nap;

  NaClErrorCode                 errcode;

  int                           ret_code = 1;
#if NACL_OSX
  // Mac dynamic libraries cannot access the environ variable directly.
  envp = *_NSGetEnviron();
#else
  extern char                   **environ;
  envp = environ;
#endif

  NaClAllModulesInit();

  /* used to be -P */
  NaClSrpcFileDescriptor = desc;
  /* used to be -X */
  export_addr_to = desc;

  /* to be passed to NaClMain, eventually... */
  av[0] = const_cast<char*>("NaClMain");

  if (!NaClAppCtor(&state)) {
    fprintf(stderr, "Error while constructing app state\n");
    goto done_file_dtor;
  }

  state.restrict_to_main_thread = main_thread_only;

  nap = &state;
  errcode = LOAD_OK;

  /* import IMC handle - used to be "-i" */
  NaClAddImcHandle(nap, handle, desc);

  /*
   * in order to report load error to the browser plugin through the
   * secure command channel, we do not immediate jump to cleanup code
   * on error.  rather, we continue processing (assuming earlier
   * errors do not make it inappropriate) until the secure command
   * channel is set up, and then bail out.
   */

  /*
   * Ensure this operating system platform is supported.
   */
  if (!NaClOsIsSupported()) {
    errcode = LOAD_UNSUPPORTED_OS_PLATFORM;
    nap->module_load_status = errcode;
    fprintf(stderr, "Error while loading in SelMain: %s\n",
            NaClErrorString(errcode));
  }

  /* Give debuggers a well known point at which xlate_base is known.  */
  StopForDebuggerInit(&state);

  /*
   * If export_addr_to is set to a non-negative integer, we create a
   * bound socket and socket address pair and bind the former to
   * descriptor 3 and the latter to descriptor 4.  The socket address
   * is written out to the export_addr_to descriptor.
   *
   * The service runtime also accepts a connection on the bound socket
   * and spawns a secure command channel thread to service it.
   *
   * If export_addr_to is -1, we only create the bound socket and
   * socket address pair, and we do not export to an IMC socket.  This
   * use case is typically only used in testing, where we only "dump"
   * the socket address to stdout or similar channel.
   */
  if (-2 < export_addr_to) {
    NaClCreateServiceSocket(nap);
    if (0 <= export_addr_to) {
      NaClSendServiceAddressTo(nap, export_addr_to);
      /*
       * NB: spawns a thread that uses the command channel.  we do
       * this after NaClAppLoadFile so that NaClApp object is more
       * fully populated.  Hereafter any changes to nap should be done
       * while holding locks.
       */
      NaClSecureCommandChannel(nap);
    }
  }

  NaClXMutexLock(&nap->mu);
  nap->module_load_status = LOAD_OK;
  NaClXCondVarBroadcast(&nap->cv);
  NaClXMutexUnlock(&nap->mu);

  if (NULL != nap->secure_channel) {
    /*
     * wait for start_module RPC call on secure channel thread.
     */
    NaClWaitForModuleStartStatusCall(nap);
  }

  /*
   * error reporting done; can quit now if there was an error earlier.
   */
  if (LOAD_OK != errcode) {
    goto done;
  }

  /*
   * only nap->ehdrs.e_entry is usable, no symbol table is
   * available.
   */
  if (!NaClCreateMainThread(nap,
                            ac,
                            av,
                            envp)) {
    fprintf(stderr, "creating main thread failed\n");
    goto done;
  }

  ret_code = NaClWaitForMainThreadToExit(nap);

  /*
   * exit_group or equiv kills any still running threads while module
   * addr space is still valid.  otherwise we'd have to kill threads
   * before we clean up the address space.
   */
  return ret_code;

 done:
  fflush(stdout);

  NaClAppDtor(&state);

 done_file_dtor:
  fflush(stdout);

  NaClAllModulesFini();

  return ret_code;
}

<commit_msg>NaCl: Remove call to NaClAppDtor()<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "native_client/src/include/portability.h"

#if NACL_OSX
#include <crt_externs.h>
#endif

#ifdef _WIN64  /* TODO(gregoryd): remove this when win64 issues are fixed */
#define NACL_NO_INLINE
#endif

EXTERN_C_BEGIN
#include "native_client/src/shared/platform/nacl_sync.h"
#include "native_client/src/shared/platform/nacl_sync_checked.h"
#include "native_client/src/trusted/service_runtime/nacl_globals.h"
#include "native_client/src/trusted/service_runtime/expiration.h"
#include "native_client/src/trusted/service_runtime/nacl_app.h"
#include "native_client/src/trusted/service_runtime/nacl_all_modules.h"
#include "native_client/src/trusted/service_runtime/sel_ldr.h"
#include "native_client/src/trusted/platform_qualify/nacl_os_qualify.h"
EXTERN_C_END

int verbosity = 0;

#ifdef __GNUC__

/*
 * GDB's canonical overlay managment routine.
 * We need its symbol in the symbol table so don't inline it.
 * Note: _ovly_debug_event has to be an unmangled 'C' style symbol.
 * TODO(dje): add some explanation for the non-GDB person.
 */
EXTERN_C_BEGIN
static void __attribute__ ((noinline)) _ovly_debug_event (void) {
  /*
   * The asm volatile is here as instructed by the GCC docs.
   * It's not enough to declare a function noinline.
   * GCC will still look inside the function to see if it's worth calling.
   */
  asm volatile ("");
}
EXTERN_C_END

#endif

static void StopForDebuggerInit(const struct NaClApp *state) {
  /* Put xlate_base in a place where gdb can find it.  */
  nacl_global_xlate_base = state->mem_start;

#ifdef __GNUC__
  _ovly_debug_event();
#endif
}

int SelMain(const int desc, const NaClHandle handle) {
  char *av[1];
  int ac = 1;

  char                          **envp;
  struct NaClApp                state;
  int                           main_thread_only = 1;
  int                           export_addr_to = -2;

  struct NaClApp                *nap;

  NaClErrorCode                 errcode;

  int                           ret_code = 1;
#if NACL_OSX
  // Mac dynamic libraries cannot access the environ variable directly.
  envp = *_NSGetEnviron();
#else
  extern char                   **environ;
  envp = environ;
#endif

  NaClAllModulesInit();

  /* used to be -P */
  NaClSrpcFileDescriptor = desc;
  /* used to be -X */
  export_addr_to = desc;

  /* to be passed to NaClMain, eventually... */
  av[0] = const_cast<char*>("NaClMain");

  if (!NaClAppCtor(&state)) {
    fprintf(stderr, "Error while constructing app state\n");
    goto done;
  }

  state.restrict_to_main_thread = main_thread_only;

  nap = &state;
  errcode = LOAD_OK;

  /* import IMC handle - used to be "-i" */
  NaClAddImcHandle(nap, handle, desc);

  /*
   * in order to report load error to the browser plugin through the
   * secure command channel, we do not immediate jump to cleanup code
   * on error.  rather, we continue processing (assuming earlier
   * errors do not make it inappropriate) until the secure command
   * channel is set up, and then bail out.
   */

  /*
   * Ensure this operating system platform is supported.
   */
  if (!NaClOsIsSupported()) {
    errcode = LOAD_UNSUPPORTED_OS_PLATFORM;
    nap->module_load_status = errcode;
    fprintf(stderr, "Error while loading in SelMain: %s\n",
            NaClErrorString(errcode));
  }

  /* Give debuggers a well known point at which xlate_base is known.  */
  StopForDebuggerInit(&state);

  /*
   * If export_addr_to is set to a non-negative integer, we create a
   * bound socket and socket address pair and bind the former to
   * descriptor 3 and the latter to descriptor 4.  The socket address
   * is written out to the export_addr_to descriptor.
   *
   * The service runtime also accepts a connection on the bound socket
   * and spawns a secure command channel thread to service it.
   *
   * If export_addr_to is -1, we only create the bound socket and
   * socket address pair, and we do not export to an IMC socket.  This
   * use case is typically only used in testing, where we only "dump"
   * the socket address to stdout or similar channel.
   */
  if (-2 < export_addr_to) {
    NaClCreateServiceSocket(nap);
    if (0 <= export_addr_to) {
      NaClSendServiceAddressTo(nap, export_addr_to);
      /*
       * NB: spawns a thread that uses the command channel.  we do
       * this after NaClAppLoadFile so that NaClApp object is more
       * fully populated.  Hereafter any changes to nap should be done
       * while holding locks.
       */
      NaClSecureCommandChannel(nap);
    }
  }

  NaClXMutexLock(&nap->mu);
  nap->module_load_status = LOAD_OK;
  NaClXCondVarBroadcast(&nap->cv);
  NaClXMutexUnlock(&nap->mu);

  if (NULL != nap->secure_channel) {
    /*
     * wait for start_module RPC call on secure channel thread.
     */
    NaClWaitForModuleStartStatusCall(nap);
  }

  /*
   * error reporting done; can quit now if there was an error earlier.
   */
  if (LOAD_OK != errcode) {
    goto done;
  }

  /*
   * only nap->ehdrs.e_entry is usable, no symbol table is
   * available.
   */
  if (!NaClCreateMainThread(nap,
                            ac,
                            av,
                            envp)) {
    fprintf(stderr, "creating main thread failed\n");
    goto done;
  }

  ret_code = NaClWaitForMainThreadToExit(nap);

  /*
   * exit_group or equiv kills any still running threads while module
   * addr space is still valid.  otherwise we'd have to kill threads
   * before we clean up the address space.
   */
  return ret_code;

 done:
  fflush(stdout);

  NaClAllModulesFini();

  return ret_code;
}

<|endoftext|>


<commit_before>/*
Copyright (c) 2013 Daniele Bartolini, Michele Rossi
Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
OTHER DEALINGS IN THE SOFTWARE.
*/

#include <cstdlib>

#include "Config.h"
#include "Device.h"
#include "Accelerometer.h"
#include "Args.h"
#include "DiskFile.h"
#include "DiskFilesystem.h"
#include "JSONParser.h"
#include "Keyboard.h"
#include "Log.h"
#include "LuaEnvironment.h"
#include "Memory.h"
#include "Mouse.h"
#include "OS.h"
#include "OsWindow.h"
#include "Renderer.h"
#include "ResourceManager.h"
#include "StringSetting.h"
#include "StringUtils.h"
#include "TextReader.h"
#include "Touch.h"
#include "Types.h"
#include "Bundle.h"
#include "TempAllocator.h"
#include "ResourcePackage.h"
#include "ConsoleServer.h"
#include "SoundRenderer.h"
#include "World.h"
#include "LuaStack.h"
#include "WorldManager.h"

#if defined(LINUX) || defined(WINDOWS)
	#include "BundleCompiler.h"
#endif

#if defined(ANDROID)
	#include "ApkFilesystem.h"
#endif

#define MAX_SUBSYSTEMS_HEAP 16 * 1024 * 1024

namespace crown
{
//-----------------------------------------------------------------------------
Device::Device()
	: m_allocator(default_allocator(), MAX_SUBSYSTEMS_HEAP)

	, m_argc(0)
	, m_argv(NULL)

	, m_is_init(false)
	, m_is_running(false)
	, m_is_paused(false)
	, m_is_really_paused(false)

	, m_frame_count(0)

	, m_last_time(0)
	, m_current_time(0)
	, m_last_delta_time(0.0f)
	, m_time_since_start(0.0)

	, m_filesystem(NULL)
	, m_lua_environment(NULL)
	, m_renderer(NULL)
	, m_sound_renderer(NULL)

	, m_bundle_compiler(NULL)
	, m_console(NULL)
	, m_resource_manager(NULL)
	, m_resource_bundle(NULL)

	, m_physx(NULL)
	, m_world_manager(NULL)

	, m_renderer_init_request(false)
{
	// Bundle dir is current dir by default.
	string::strncpy(m_bundle_dir, os::get_cwd(), MAX_PATH_LENGTH);
	string::strncpy(m_source_dir, "", MAX_PATH_LENGTH);
	string::strncpy(m_boot_file, "lua/game", MAX_PATH_LENGTH);
}

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

//-----------------------------------------------------------------------------
void Device::init()
{
	// Initialize
	Log::i("Initializing Crown Engine %d.%d.%d...", CROWN_VERSION_MAJOR, CROWN_VERSION_MINOR, CROWN_VERSION_MICRO);

	// RPC only in debug or development builds
	#if defined(CROWN_DEBUG) || defined(CROWN_DEVELOPMENT)
		m_console = CE_NEW(m_allocator, ConsoleServer);
		m_console->init(false);
	#endif

	// Default bundle filesystem
	#if defined (LINUX) || defined(WINDOWS)
		m_filesystem = CE_NEW(m_allocator, DiskFilesystem)(m_bundle_dir);
	#elif defined(ANDROID)
		m_filesystem = CE_NEW(m_allocator, ApkFilesystem)();
	#endif
	Log::d("Filesystem created.");

	m_resource_bundle = Bundle::create(m_allocator, *m_filesystem);

	// Create resource manager
	m_resource_manager = CE_NEW(m_allocator, ResourceManager)(*m_resource_bundle, 0);
	Log::d("Resource manager created.");
	Log::d("Resource seed: %d", m_resource_manager->seed());

	// Create world manager
	m_world_manager = CE_NEW(m_allocator, WorldManager)();
	Log::d("World manager created.");

	// Create window
	m_window = CE_NEW(m_allocator, OsWindow);

	// Create input devices
	m_keyboard = CE_NEW(m_allocator, Keyboard);
	m_mouse = CE_NEW(m_allocator, Mouse);
	m_touch = CE_NEW(m_allocator, Touch);

	// Create renderer
	m_renderer = CE_NEW(m_allocator, Renderer)(m_allocator);
	m_renderer->init();
	Log::d("Renderer created.");

	m_lua_environment = CE_NEW(m_allocator, LuaEnvironment)();
	m_lua_environment->init();
	Log::d("Lua environment created.");

	m_sound_renderer = CE_NEW(m_allocator, SoundRenderer)(m_allocator);
	m_sound_renderer->init();
	Log::d("SoundRenderer created.");

	m_physx = CE_NEW(m_allocator, Physics)();
	Log::d("Physics created.");

	Log::d("Crown Engine initialized.");
	Log::d("Initializing Game...");

	m_is_init = true;
	start();

	// Execute lua boot file
	if (m_lua_environment->load_and_execute(m_boot_file))
	{
		if (!m_lua_environment->call_global("init", 0))
		{
			pause();
		}
	}
	else
	{
		pause();
	}

	Log::d("Total allocated size: %llu", m_allocator.allocated_size());
}

//-----------------------------------------------------------------------------
void Device::shutdown()
{
	CE_ASSERT(is_init(), "Engine is not initialized");

	// Shutdowns the game
	m_lua_environment->call_global("shutdown", 0);

	Log::d("Releasing Physics...");
	if (m_physx)
	{
		CE_DELETE(m_allocator, m_physx);
	}

	Log::d("Releasing SoundRenderer...");
	if (m_sound_renderer)
	{
		m_sound_renderer->shutdown();

		CE_DELETE(m_allocator, m_sound_renderer);
	}

	Log::d("Releasing LuaEnvironment...");
	if (m_lua_environment)
	{
		m_lua_environment->shutdown();

		CE_DELETE(m_allocator, m_lua_environment);
	}

	Log::d("Releasing Input Devices...");
	CE_DELETE(m_allocator, m_touch);
	CE_DELETE(m_allocator, m_mouse);
	CE_DELETE(m_allocator, m_keyboard);

	Log::d("Releasing Renderer...");
	if (m_renderer)
	{
		m_renderer->shutdown();
		CE_DELETE(m_allocator, m_renderer);
	}

	Log::d("Releasing WorldManager...");
	CE_DELETE(m_allocator, m_world_manager);

	Log::d("Releasing ResourceManager...");
	if (m_resource_manager)
	{
		CE_DELETE(m_allocator, m_resource_manager);
	}

	if (m_resource_bundle)
	{
		Bundle::destroy(m_allocator, m_resource_bundle);
	}

	Log::d("Releasing Filesystem...");
	if (m_filesystem)
	{
		CE_DELETE(m_allocator, m_filesystem);
	}

	#if defined(CROWN_DEBUG) || defined(CROWN_DEVELOPMENT)
		m_console->process_requests();
		m_console->shutdown();
		CE_DELETE(m_allocator, m_console);
		m_console = NULL;
	#endif

	m_allocator.clear();
	m_is_init = false;
}

//-----------------------------------------------------------------------------
bool Device::is_init() const
{
	return m_is_init;
}

//-----------------------------------------------------------------------------
bool Device::is_paused() const
{
	return m_is_paused;
}

//-----------------------------------------------------------------------------
Filesystem* Device::filesystem()
{
	return m_filesystem;
}

//-----------------------------------------------------------------------------
ResourceManager* Device::resource_manager()
{
	return m_resource_manager;
}

//-----------------------------------------------------------------------------
LuaEnvironment* Device::lua_environment()
{
	return m_lua_environment;
}

//-----------------------------------------------------------------------------
OsWindow* Device::window()
{
	return m_window;
}

//-----------------------------------------------------------------------------
Renderer* Device::renderer()
{
	return m_renderer;
}

//-----------------------------------------------------------------------------
SoundRenderer* Device::sound_renderer()
{
	return m_sound_renderer;
}

//-----------------------------------------------------------------------------
Keyboard* Device::keyboard()
{
	return m_keyboard;
}

//-----------------------------------------------------------------------------
Mouse* Device::mouse()
{
	return m_mouse;
}

//-----------------------------------------------------------------------------
Touch* Device::touch()
{
	return m_touch;
}

//-----------------------------------------------------------------------------
Accelerometer* Device::accelerometer()
{
	return NULL;
}

//-----------------------------------------------------------------------------
void Device::start()
{
	CE_ASSERT(m_is_init, "Cannot start uninitialized engine.");

	m_is_running = true;
	m_last_time = os::milliseconds();
}

//-----------------------------------------------------------------------------
void Device::stop()
{
	CE_ASSERT(m_is_init, "Cannot stop uninitialized engine.");

	m_is_running = false;
}

//-----------------------------------------------------------------------------
void Device::pause()
{
	m_is_paused = true;
}

//-----------------------------------------------------------------------------
void Device::unpause()
{
	m_is_paused = false;
}

//-----------------------------------------------------------------------------
bool Device::is_running() const
{
	return m_is_running;
}

//-----------------------------------------------------------------------------
uint64_t Device::frame_count() const
{
	return m_frame_count;
}

//-----------------------------------------------------------------------------
float Device::last_delta_time() const
{
	return m_last_delta_time;
}

//-----------------------------------------------------------------------------
double Device::time_since_start() const
{
	return m_time_since_start;
}

//-----------------------------------------------------------------------------
void Device::frame()
{
	m_current_time = os::microseconds();
	m_last_delta_time = (m_current_time - m_last_time) / 1000000.0f;
	m_last_time = m_current_time;
	m_time_since_start += m_last_delta_time;

	m_console->update();

	if (!m_is_paused)
	{
		m_resource_manager->poll_resource_loader();

		if (!m_lua_environment->call_global("frame", 1, ARGUMENT_FLOAT, last_delta_time()))
		{
			pause();
		}

		m_renderer->frame();

		// FIXME: SoundRenderer should not be updated each frame
		m_sound_renderer->frame();
	}

	m_console->process_requests();

	clear_lua_temporaries();

	m_frame_count++;
}

//-----------------------------------------------------------------------------
void Device::update_world(World* world, float dt)
{
	world->update(dt);
}

//-----------------------------------------------------------------------------
void Device::render_world(World* world, Camera* camera)
{
	world->render(camera);
}

//-----------------------------------------------------------------------------
WorldId Device::create_world()
{
	return m_world_manager->create_world();
}

//-----------------------------------------------------------------------------
void Device::destroy_world(WorldId world)
{
	m_world_manager->destroy_world(world);
}

//-----------------------------------------------------------------------------
ResourcePackage* Device::create_resource_package(const char* name)
{
	CE_ASSERT_NOT_NULL(name);

	ResourceId package_id = m_resource_manager->load("package", name);
	m_resource_manager->flush();

	PackageResource* package_res = (PackageResource*) m_resource_manager->data(package_id);
	ResourcePackage* package = CE_NEW(default_allocator(), ResourcePackage)(*m_resource_manager, package_id, package_res);

	return package;
}

//-----------------------------------------------------------------------------
void Device::destroy_resource_package(ResourcePackage* package)
{
	CE_ASSERT_NOT_NULL(package);

	m_resource_manager->unload(package->resource_id());
	CE_DELETE(default_allocator(), package);
}

//-----------------------------------------------------------------------------
void Device::compile(const char* , const char* , const char* )
{
}

//-----------------------------------------------------------------------------
void Device::reload(const char* type, const char* name)
{
	#if defined(LINUX) || defined(WINDOWS)
		TempAllocator4096 temp;
		DynamicString filename(temp);
		filename += name;
		filename += '.';
		filename += type;

		const void* old_res = m_resource_manager->lookup(type, name);

		if (!m_bundle_compiler->compile(m_bundle_dir, m_source_dir, filename.c_str()))
		{
			Log::d("Compilation failed.");
			return;
		}

		ResourceId res_id = m_resource_manager->load(type, name);
		m_resource_manager->flush();
		const void* new_res = m_resource_manager->data(res_id);

		uint32_t type_hash = hash::murmur2_32(type, string::strlen(type), 0);

		switch (type_hash)
		{
			case UNIT_TYPE:
			{
				Log::d("Reloading unit: %s", name);
				/// Reload unit in all worlds
				for (uint32_t i = 0; i < m_world_manager->worlds().size(); i++)
				{
					m_world_manager->worlds()[i]->reload_units((UnitResource*) old_res, (UnitResource*) new_res);
				}
				break;
			}
			default:
			{
				CE_ASSERT(false, "Oops, unknown resource type: %s", type);
				break;
			}
		}
	#endif
}

static Device* g_device;
void set_device(Device* device)
{
	g_device = device;
}

Device* device()
{
	return g_device;
}

} // namespace crown
<commit_msg>Half the size of preallocated memory for subsystems<commit_after>/*
Copyright (c) 2013 Daniele Bartolini, Michele Rossi
Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
OTHER DEALINGS IN THE SOFTWARE.
*/

#include <cstdlib>

#include "Config.h"
#include "Device.h"
#include "Accelerometer.h"
#include "Args.h"
#include "DiskFile.h"
#include "DiskFilesystem.h"
#include "JSONParser.h"
#include "Keyboard.h"
#include "Log.h"
#include "LuaEnvironment.h"
#include "Memory.h"
#include "Mouse.h"
#include "OS.h"
#include "OsWindow.h"
#include "Renderer.h"
#include "ResourceManager.h"
#include "StringSetting.h"
#include "StringUtils.h"
#include "TextReader.h"
#include "Touch.h"
#include "Types.h"
#include "Bundle.h"
#include "TempAllocator.h"
#include "ResourcePackage.h"
#include "ConsoleServer.h"
#include "SoundRenderer.h"
#include "World.h"
#include "LuaStack.h"
#include "WorldManager.h"

#if defined(LINUX) || defined(WINDOWS)
	#include "BundleCompiler.h"
#endif

#if defined(ANDROID)
	#include "ApkFilesystem.h"
#endif

#define MAX_SUBSYSTEMS_HEAP 8 * 1024 * 1024

namespace crown
{
//-----------------------------------------------------------------------------
Device::Device()
	: m_allocator(default_allocator(), MAX_SUBSYSTEMS_HEAP)

	, m_argc(0)
	, m_argv(NULL)

	, m_is_init(false)
	, m_is_running(false)
	, m_is_paused(false)
	, m_is_really_paused(false)

	, m_frame_count(0)

	, m_last_time(0)
	, m_current_time(0)
	, m_last_delta_time(0.0f)
	, m_time_since_start(0.0)

	, m_filesystem(NULL)
	, m_lua_environment(NULL)
	, m_renderer(NULL)
	, m_sound_renderer(NULL)

	, m_bundle_compiler(NULL)
	, m_console(NULL)
	, m_resource_manager(NULL)
	, m_resource_bundle(NULL)

	, m_physx(NULL)
	, m_world_manager(NULL)

	, m_renderer_init_request(false)
{
	// Bundle dir is current dir by default.
	string::strncpy(m_bundle_dir, os::get_cwd(), MAX_PATH_LENGTH);
	string::strncpy(m_source_dir, "", MAX_PATH_LENGTH);
	string::strncpy(m_boot_file, "lua/game", MAX_PATH_LENGTH);
}

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

//-----------------------------------------------------------------------------
void Device::init()
{
	// Initialize
	Log::i("Initializing Crown Engine %d.%d.%d...", CROWN_VERSION_MAJOR, CROWN_VERSION_MINOR, CROWN_VERSION_MICRO);

	// RPC only in debug or development builds
	#if defined(CROWN_DEBUG) || defined(CROWN_DEVELOPMENT)
		m_console = CE_NEW(m_allocator, ConsoleServer);
		m_console->init(false);
	#endif

	// Default bundle filesystem
	#if defined (LINUX) || defined(WINDOWS)
		m_filesystem = CE_NEW(m_allocator, DiskFilesystem)(m_bundle_dir);
	#elif defined(ANDROID)
		m_filesystem = CE_NEW(m_allocator, ApkFilesystem)();
	#endif
	Log::d("Filesystem created.");

	m_resource_bundle = Bundle::create(m_allocator, *m_filesystem);

	// Create resource manager
	m_resource_manager = CE_NEW(m_allocator, ResourceManager)(*m_resource_bundle, 0);
	Log::d("Resource manager created.");
	Log::d("Resource seed: %d", m_resource_manager->seed());

	// Create world manager
	m_world_manager = CE_NEW(m_allocator, WorldManager)();
	Log::d("World manager created.");

	// Create window
	m_window = CE_NEW(m_allocator, OsWindow);

	// Create input devices
	m_keyboard = CE_NEW(m_allocator, Keyboard);
	m_mouse = CE_NEW(m_allocator, Mouse);
	m_touch = CE_NEW(m_allocator, Touch);

	// Create renderer
	m_renderer = CE_NEW(m_allocator, Renderer)(m_allocator);
	m_renderer->init();
	Log::d("Renderer created.");

	m_lua_environment = CE_NEW(m_allocator, LuaEnvironment)();
	m_lua_environment->init();
	Log::d("Lua environment created.");

	m_sound_renderer = CE_NEW(m_allocator, SoundRenderer)(m_allocator);
	m_sound_renderer->init();
	Log::d("SoundRenderer created.");

	m_physx = CE_NEW(m_allocator, Physics)();
	Log::d("Physics created.");

	Log::d("Crown Engine initialized.");
	Log::d("Initializing Game...");

	m_is_init = true;
	start();

	// Execute lua boot file
	if (m_lua_environment->load_and_execute(m_boot_file))
	{
		if (!m_lua_environment->call_global("init", 0))
		{
			pause();
		}
	}
	else
	{
		pause();
	}

	Log::d("Total allocated size: %llu", m_allocator.allocated_size());
}

//-----------------------------------------------------------------------------
void Device::shutdown()
{
	CE_ASSERT(is_init(), "Engine is not initialized");

	// Shutdowns the game
	m_lua_environment->call_global("shutdown", 0);

	Log::d("Releasing Physics...");
	if (m_physx)
	{
		CE_DELETE(m_allocator, m_physx);
	}

	Log::d("Releasing SoundRenderer...");
	if (m_sound_renderer)
	{
		m_sound_renderer->shutdown();

		CE_DELETE(m_allocator, m_sound_renderer);
	}

	Log::d("Releasing LuaEnvironment...");
	if (m_lua_environment)
	{
		m_lua_environment->shutdown();

		CE_DELETE(m_allocator, m_lua_environment);
	}

	Log::d("Releasing Input Devices...");
	CE_DELETE(m_allocator, m_touch);
	CE_DELETE(m_allocator, m_mouse);
	CE_DELETE(m_allocator, m_keyboard);

	Log::d("Releasing Renderer...");
	if (m_renderer)
	{
		m_renderer->shutdown();
		CE_DELETE(m_allocator, m_renderer);
	}

	Log::d("Releasing WorldManager...");
	CE_DELETE(m_allocator, m_world_manager);

	Log::d("Releasing ResourceManager...");
	if (m_resource_manager)
	{
		CE_DELETE(m_allocator, m_resource_manager);
	}

	if (m_resource_bundle)
	{
		Bundle::destroy(m_allocator, m_resource_bundle);
	}

	Log::d("Releasing Filesystem...");
	if (m_filesystem)
	{
		CE_DELETE(m_allocator, m_filesystem);
	}

	#if defined(CROWN_DEBUG) || defined(CROWN_DEVELOPMENT)
		m_console->process_requests();
		m_console->shutdown();
		CE_DELETE(m_allocator, m_console);
		m_console = NULL;
	#endif

	m_allocator.clear();
	m_is_init = false;
}

//-----------------------------------------------------------------------------
bool Device::is_init() const
{
	return m_is_init;
}

//-----------------------------------------------------------------------------
bool Device::is_paused() const
{
	return m_is_paused;
}

//-----------------------------------------------------------------------------
Filesystem* Device::filesystem()
{
	return m_filesystem;
}

//-----------------------------------------------------------------------------
ResourceManager* Device::resource_manager()
{
	return m_resource_manager;
}

//-----------------------------------------------------------------------------
LuaEnvironment* Device::lua_environment()
{
	return m_lua_environment;
}

//-----------------------------------------------------------------------------
OsWindow* Device::window()
{
	return m_window;
}

//-----------------------------------------------------------------------------
Renderer* Device::renderer()
{
	return m_renderer;
}

//-----------------------------------------------------------------------------
SoundRenderer* Device::sound_renderer()
{
	return m_sound_renderer;
}

//-----------------------------------------------------------------------------
Keyboard* Device::keyboard()
{
	return m_keyboard;
}

//-----------------------------------------------------------------------------
Mouse* Device::mouse()
{
	return m_mouse;
}

//-----------------------------------------------------------------------------
Touch* Device::touch()
{
	return m_touch;
}

//-----------------------------------------------------------------------------
Accelerometer* Device::accelerometer()
{
	return NULL;
}

//-----------------------------------------------------------------------------
void Device::start()
{
	CE_ASSERT(m_is_init, "Cannot start uninitialized engine.");

	m_is_running = true;
	m_last_time = os::milliseconds();
}

//-----------------------------------------------------------------------------
void Device::stop()
{
	CE_ASSERT(m_is_init, "Cannot stop uninitialized engine.");

	m_is_running = false;
}

//-----------------------------------------------------------------------------
void Device::pause()
{
	m_is_paused = true;
}

//-----------------------------------------------------------------------------
void Device::unpause()
{
	m_is_paused = false;
}

//-----------------------------------------------------------------------------
bool Device::is_running() const
{
	return m_is_running;
}

//-----------------------------------------------------------------------------
uint64_t Device::frame_count() const
{
	return m_frame_count;
}

//-----------------------------------------------------------------------------
float Device::last_delta_time() const
{
	return m_last_delta_time;
}

//-----------------------------------------------------------------------------
double Device::time_since_start() const
{
	return m_time_since_start;
}

//-----------------------------------------------------------------------------
void Device::frame()
{
	m_current_time = os::microseconds();
	m_last_delta_time = (m_current_time - m_last_time) / 1000000.0f;
	m_last_time = m_current_time;
	m_time_since_start += m_last_delta_time;

	m_console->update();

	if (!m_is_paused)
	{
		m_resource_manager->poll_resource_loader();

		if (!m_lua_environment->call_global("frame", 1, ARGUMENT_FLOAT, last_delta_time()))
		{
			pause();
		}

		m_renderer->frame();

		// FIXME: SoundRenderer should not be updated each frame
		m_sound_renderer->frame();
	}

	m_console->process_requests();

	clear_lua_temporaries();

	m_frame_count++;
}

//-----------------------------------------------------------------------------
void Device::update_world(World* world, float dt)
{
	world->update(dt);
}

//-----------------------------------------------------------------------------
void Device::render_world(World* world, Camera* camera)
{
	world->render(camera);
}

//-----------------------------------------------------------------------------
WorldId Device::create_world()
{
	return m_world_manager->create_world();
}

//-----------------------------------------------------------------------------
void Device::destroy_world(WorldId world)
{
	m_world_manager->destroy_world(world);
}

//-----------------------------------------------------------------------------
ResourcePackage* Device::create_resource_package(const char* name)
{
	CE_ASSERT_NOT_NULL(name);

	ResourceId package_id = m_resource_manager->load("package", name);
	m_resource_manager->flush();

	PackageResource* package_res = (PackageResource*) m_resource_manager->data(package_id);
	ResourcePackage* package = CE_NEW(default_allocator(), ResourcePackage)(*m_resource_manager, package_id, package_res);

	return package;
}

//-----------------------------------------------------------------------------
void Device::destroy_resource_package(ResourcePackage* package)
{
	CE_ASSERT_NOT_NULL(package);

	m_resource_manager->unload(package->resource_id());
	CE_DELETE(default_allocator(), package);
}

//-----------------------------------------------------------------------------
void Device::compile(const char* , const char* , const char* )
{
}

//-----------------------------------------------------------------------------
void Device::reload(const char* type, const char* name)
{
	#if defined(LINUX) || defined(WINDOWS)
		TempAllocator4096 temp;
		DynamicString filename(temp);
		filename += name;
		filename += '.';
		filename += type;

		const void* old_res = m_resource_manager->lookup(type, name);

		if (!m_bundle_compiler->compile(m_bundle_dir, m_source_dir, filename.c_str()))
		{
			Log::d("Compilation failed.");
			return;
		}

		ResourceId res_id = m_resource_manager->load(type, name);
		m_resource_manager->flush();
		const void* new_res = m_resource_manager->data(res_id);

		uint32_t type_hash = hash::murmur2_32(type, string::strlen(type), 0);

		switch (type_hash)
		{
			case UNIT_TYPE:
			{
				Log::d("Reloading unit: %s", name);
				/// Reload unit in all worlds
				for (uint32_t i = 0; i < m_world_manager->worlds().size(); i++)
				{
					m_world_manager->worlds()[i]->reload_units((UnitResource*) old_res, (UnitResource*) new_res);
				}
				break;
			}
			default:
			{
				CE_ASSERT(false, "Oops, unknown resource type: %s", type);
				break;
			}
		}
	#endif
}

static Device* g_device;
void set_device(Device* device)
{
	g_device = device;
}

Device* device()
{
	return g_device;
}

} // namespace crown
<|endoftext|>


<commit_before>#include "Search.h"
#include "board.hpp"
#include <iostream>

void outbitboard(u64 n);

string Search::RootAlphaBeta(Board gameBoard, int playerColor, int remainingDepth)
{
    vector<Board> possibleMoves = gameBoard.getBoards(playerColor);
    Board curBestMove = possibleMoves[0];
    int maxScore = -1000000;
    int score;
    for (unsigned int i = 0; i < possibleMoves.size(); i++){
        score = -AlphaBeta(possibleMoves[i], -1000000, 1000000, remainingDepth, playerColor*-1);
        if (score > maxScore){
            maxScore = score;
            curBestMove = possibleMoves[i];
        }
    }
    return gameBoard.getmove(curBestMove);
}

int Search::AlphaBeta(Board gameBoard, int alpha, int beta, int remainingDepth, int playerColor)
{
    if (remainingDepth == 0){
        return gameBoard.evalutateBoard()*playerColor;
    }
    int score;
    vector<Board> possibleMoves = gameBoard.getBoards(playerColor);
    if (possibleMoves.size() == 0){
        int colorCode = 6;
        if (playerColor == -1){
            colorCode = 7;
        }
        if (gameBoard.inCheck(colorCode) == true){
            //checkmate
            return (-1000000 - remainingDepth)*playerColor;
        } else {
            //stale mate
            return 0;
        }
    }
    for (unsigned int i = 0; i < possibleMoves.size(); i++){
        score = -AlphaBeta(possibleMoves[i], -beta, -alpha, remainingDepth - 1, playerColor*-1);
        if (score >= beta){
            return beta;
        }
        if (score > alpha){
            alpha = score;
        }
    }
    return alpha;
}

<commit_msg>Update Search.cpp<commit_after>#include "Search.h"
#include "board.hpp"
#include <iostream>

void outbitboard(u64 n);

string Search::RootAlphaBeta(Board gameBoard, int playerColor, int remainingDepth)
{
    vector<Board> possibleMoves = gameBoard.getBoards(playerColor);
    Board curBestMove = possibleMoves[0];
    int maxScore = -1000000;
    int score;
    for (unsigned int i = 0; i < possibleMoves.size(); i++){
        score = -AlphaBeta(possibleMoves[i], -1000000, 1000000, remainingDepth, playerColor*-1);
        if (score > maxScore){
            maxScore = score;
            curBestMove = possibleMoves[i];
        }
    }
    return gameBoard.getmove(curBestMove);
}

int Search::AlphaBeta(Board gameBoard, int alpha, int beta, int remainingDepth, int playerColor)
{
    if (remainingDepth == 0){
        return gameBoard.evalutateBoard()*playerColor;
    }
    int score;
    vector<Board> possibleMoves = gameBoard.getBoards(playerColor);
    if (possibleMoves.size() == 0){
        int colorCode = 6;
        if (playerColor == -1){
            colorCode = 7;
        }
        if (gameBoard.inCheck(colorCode) == true){
            //checkmate
            return (-1000000 - remainingDepth);
        } else {
            //stale mate
            return 0;
        }
    }
    for (unsigned int i = 0; i < possibleMoves.size(); i++){
        score = -AlphaBeta(possibleMoves[i], -beta, -alpha, remainingDepth - 1, playerColor*-1);
        if (score >= beta){
            return beta;
        }
        if (score > alpha){
            alpha = score;
        }
    }
    return alpha;
}

<|endoftext|>


<commit_before>#include "Common.h"
#include "Config.h"
#include "OpenGL.h"
#include "Window.h"

/****** Variables *******/

static GLFWwindow* g_Window = NULL;
static int g_WindowWidth  = 0;
static int g_WindowHeight = 0;
static int g_FramebufferWidth  = 0;
static int g_FramebufferHeight = 0;
static FramebufferResizeFn g_FramebufferResizeFn = NULL;
static CursorMoveFn        g_CursorMoveFn = NULL;
static MouseButtonActionFn g_MouseButtonActionFn = NULL;
static MouseScrollFn       g_MouseScrollFn = NULL;
static KeyActionFn         g_KeyActionFn = NULL;

/****** General *******/

static void OnGLFWError( int code, const char* description );
#if defined(APOAPSIS_GL_DEBUG_FIX)
static void OnDebugEvent( GLenum source,
                          GLenum type,
                          GLuint id,
                          GLenum severity,
                          GLsizei length,
                          const char* message,
                          void* userParam );
#endif
static void OnDebugEvent( GLenum source,
                          GLenum type,
                          GLuint id,
                          GLenum severity,
                          GLsizei length,
                          const char* message,
                          const void* userParam );
static void OnWindowResize( GLFWwindow* window, int width, int height );
static void OnFramebufferResize( GLFWwindow* window, int width, int height );
static void OnMouseButtonAction( GLFWwindow* window, int button, int action, int mods );
static void OnMouseScroll( GLFWwindow* window, double xoffset, double yoffset );
static void OnCursorMove( GLFWwindow* window, double x, double y );
static void OnKeyAction( GLFWwindow* window, int key, int scancode, int action, int mods );

bool InitWindow()
{
    const int width  = GetConfigInt("window.width",  640);
    const int height = GetConfigInt("window.height", 480);
    const char* title = GetConfigString("window.title", "Apoapsis");

    const bool debug = GetConfigBool("opengl.debug", false);
    const bool vsync = GetConfigBool("opengl.vsync", true);

    assert(g_Window == NULL);
    glfwSetErrorCallback(OnGLFWError);
    if(!glfwInit())
    {
        Error("GLFW init failed.");
        return false;
    }

    glfwDefaultWindowHints();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
    glfwWindowHint(GLFW_DEPTH_BITS, GetConfigInt("opengl.depth-bits", 24));
    glfwWindowHint(GLFW_STENCIL_BITS, 0);
    glfwWindowHint(GLFW_SAMPLES, GetConfigInt("opengl.samples", 0));
    glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, debug ? GL_TRUE : GL_FALSE);

    g_Window = glfwCreateWindow(width, height, title, NULL, NULL);
    if(!g_Window)
    {
        Error("Window creation failed.");
        glfwTerminate();
        return false;
    }

    glfwGetWindowSize(g_Window, &g_WindowWidth, &g_WindowHeight);
    glfwGetFramebufferSize(g_Window, &g_FramebufferWidth, &g_FramebufferHeight);

    glfwMakeContextCurrent(g_Window);

    if(!flextInit(g_Window))
    {
        Error("Failed to load OpenGL extensions.");
        return false;
    }

    Log("Using OpenGL %s\n"
        "Vendor: %s\n"
        "Renderer: %s\n"
        "GLSL: %s",
        glGetString(GL_VERSION),
        glGetString(GL_VENDOR),
        glGetString(GL_RENDERER),
        glGetString(GL_SHADING_LANGUAGE_VERSION));

    if(vsync)
    {
        if(FLEXT_EXT_swap_control_tear)
            glfwSwapInterval(-1); // enable vsync (allow the driver to swap even if a frame arrives a little bit late)
        else
            glfwSwapInterval(1); // enable vsync
    }

    glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
    glfwSetInputMode(g_Window, GLFW_STICKY_KEYS, GL_FALSE);
    glfwSetInputMode(g_Window, GLFW_STICKY_MOUSE_BUTTONS, GL_FALSE);

    if(FLEXT_ARB_seamless_cube_map)
    {
        Log("Seamless cubemap filtering supported");
        glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
    }

    if(debug)
    {
        if(FLEXT_ARB_debug_output)
        {
            glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
            glDebugMessageCallbackARB(OnDebugEvent, NULL);
            Log("Debug output supported! You may receive debug messages from your OpenGL driver.");
        }
        else
        {
            Error("Debug output requested, but it's not supported!");
        }
    }

    glfwSetWindowSizeCallback(g_Window, OnWindowResize);
    glfwSetFramebufferSizeCallback(g_Window, OnFramebufferResize);
    glfwSetMouseButtonCallback(g_Window, OnMouseButtonAction);
    glfwSetScrollCallback(g_Window, OnMouseScroll);
    glfwSetCursorPosCallback(g_Window, OnCursorMove);
    glfwSetKeyCallback(g_Window, OnKeyAction);

    return true;
}

void DestroyWindow()
{
    assert(g_Window != NULL);
    glfwDestroyWindow(g_Window);
    glfwTerminate();
}

void SwapBuffers()
{
    glfwSwapBuffers(g_Window);
    glfwPollEvents();
}

void SetWindowTitle( const char* title )
{
    glfwSetWindowTitle(g_Window, title);
}

void FlagWindowForClose()
{
    glfwSetWindowShouldClose(g_Window, GL_TRUE);
}

bool WindowShouldClose()
{
    return glfwWindowShouldClose(g_Window) == GL_TRUE;
}

void* GetGLFWwindow()
{
    return g_Window;
}

glm::ivec2 GetFramebufferSize()
{
    return glm::ivec2(g_FramebufferWidth, g_FramebufferHeight);
}

/****** Input ******/

void SetCursorMode( int mode )
{
    glfwSetInputMode(g_Window, GLFW_CURSOR, mode);
}

/******* Callback Setter *******/

void SetFrambufferFn( FramebufferResizeFn fn )
{
    g_FramebufferResizeFn = fn;
    OnFramebufferResize(NULL, g_FramebufferWidth, g_FramebufferHeight);
}

void SetCursorMoveFn( CursorMoveFn fn )
{
    g_CursorMoveFn = fn;
}

void SetMouseButtonActionFn( MouseButtonActionFn fn )
{
    g_MouseButtonActionFn = fn;
}

void SetMouseScrollFn( MouseScrollFn fn )
{
    g_MouseScrollFn = fn;
}

void SetKeyActionFn( KeyActionFn fn )
{
    g_KeyActionFn = fn;
}

/******* Callbacks ********/

static void OnGLFWError( int code, const char* description )
{
    Error("GLFW error %d: %s", code, description);
}

#if defined(APOAPSIS_GL_DEBUG_FIX)
static void OnDebugEvent( GLenum source,
                          GLenum type,
                          GLuint id,
                          GLenum severity,
                          GLsizei length,
                          const char* message,
                          void* userParam )
{
    OnDebugEvent(source, type, id, severity, length, message, (const void*)userParam);
}
#endif

static void OnDebugEvent( GLenum source,
                          GLenum type,
                          GLuint id,
                          GLenum severity,
                          GLsizei length,
                          const char* message,
                          const void* userParam )
{
    const char* sourceName = "";
    switch(source)
    {
        case GL_DEBUG_SOURCE_API_ARB: sourceName = "API"; break;
        case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: sourceName = "window system"; break;
        case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: sourceName = "shader"; break;
        case GL_DEBUG_SOURCE_THIRD_PARTY_ARB: sourceName = "third party"; break;
        case GL_DEBUG_SOURCE_APPLICATION_ARB: sourceName = "application"; break;
        case GL_DEBUG_SOURCE_OTHER_ARB: sourceName = ""; break;
    }

    const char* typeName = "unknown issue";
    switch(type)
    {
        case GL_DEBUG_TYPE_ERROR_ARB: typeName = "error"; break;
        case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: typeName = "deprecated behavior"; break;
        case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: typeName = "undefined behavior"; break;
        case GL_DEBUG_TYPE_PORTABILITY_ARB: typeName = "partability issue"; break;
        case GL_DEBUG_TYPE_PERFORMANCE_ARB: typeName = "performance issue"; break;
        case GL_DEBUG_TYPE_OTHER_ARB: typeName = "unknown issue"; break;
    }

    const char* severityName = "";
    switch(severity)
    {
        case GL_DEBUG_SEVERITY_HIGH_ARB: severityName = "High"; break;
        case GL_DEBUG_SEVERITY_MEDIUM_ARB: severityName = "Medium"; break;
        case GL_DEBUG_SEVERITY_LOW_ARB: severityName = "Low"; break;
    }

    Error("%s severity %s %s %d, %s", severityName, sourceName, typeName, id, message);
}

static void OnWindowResize( GLFWwindow* window, int width, int height )
{
    g_WindowWidth = width;
    g_WindowHeight = height;
    // TODO: Update cursor position
}

static void OnFramebufferResize( GLFWwindow* window, int width, int height )
{
    g_FramebufferWidth = width;
    g_FramebufferHeight = height;
    // TODO: Update cursor position
    if(g_FramebufferResizeFn)
        g_FramebufferResizeFn(width, height);
}

static void OnMouseButtonAction( GLFWwindow* window, int button, int action, int mods )
{
    if(g_MouseButtonActionFn)
        g_MouseButtonActionFn(button, action==GLFW_PRESS);
}

static void OnMouseScroll( GLFWwindow* window, double xoffset, double yoffset )
{
    if(g_MouseScrollFn)
        g_MouseScrollFn(xoffset, yoffset);
}

static void OnCursorMove( GLFWwindow* window, double x, double y )
{
    x *= g_FramebufferWidth / g_WindowWidth;
    y *= g_FramebufferHeight / g_WindowHeight;

    if(g_CursorMoveFn)
        g_CursorMoveFn(x, y);
}

static void OnKeyAction( GLFWwindow* window, int key, int scancode, int action, int mods )
{
    if(action != GLFW_REPEAT && g_KeyActionFn)
        g_KeyActionFn(key, scancode, action==GLFW_PRESS);
}
<commit_msg>Windows needs special treatment<commit_after>#include "Common.h"
#include "Config.h"
#include "OpenGL.h"
#include "Window.h"

#if defined(WIN32)
#define CALLBACK_API __attribute__((__stdcall__))
#else
#define CALLBACK_API
#endif

/****** Variables *******/

static GLFWwindow* g_Window = NULL;
static int g_WindowWidth  = 0;
static int g_WindowHeight = 0;
static int g_FramebufferWidth  = 0;
static int g_FramebufferHeight = 0;
static FramebufferResizeFn g_FramebufferResizeFn = NULL;
static CursorMoveFn        g_CursorMoveFn = NULL;
static MouseButtonActionFn g_MouseButtonActionFn = NULL;
static MouseScrollFn       g_MouseScrollFn = NULL;
static KeyActionFn         g_KeyActionFn = NULL;

/****** General *******/

static void OnGLFWError( int code, const char* description );
#if defined(APOAPSIS_GL_DEBUG_FIX)
CALLBACK_API static void OnDebugEvent( GLenum source,
                                       GLenum type,
                                       GLuint id,
                                       GLenum severity,
                                       GLsizei length,
                                       const char* message,
                                       void* userParam );
#endif
CALLBACK_API static void OnDebugEvent( GLenum source,
                                       GLenum type,
                                       GLuint id,
                                       GLenum severity,
                                       GLsizei length,
                                       const char* message,
                                       const void* userParam );
static void OnWindowResize( GLFWwindow* window, int width, int height );
static void OnFramebufferResize( GLFWwindow* window, int width, int height );
static void OnMouseButtonAction( GLFWwindow* window, int button, int action, int mods );
static void OnMouseScroll( GLFWwindow* window, double xoffset, double yoffset );
static void OnCursorMove( GLFWwindow* window, double x, double y );
static void OnKeyAction( GLFWwindow* window, int key, int scancode, int action, int mods );

bool InitWindow()
{
    const int width  = GetConfigInt("window.width",  640);
    const int height = GetConfigInt("window.height", 480);
    const char* title = GetConfigString("window.title", "Apoapsis");

    const bool debug = GetConfigBool("opengl.debug", false);
    const bool vsync = GetConfigBool("opengl.vsync", true);

    assert(g_Window == NULL);
    glfwSetErrorCallback(OnGLFWError);
    if(!glfwInit())
    {
        Error("GLFW init failed.");
        return false;
    }

    glfwDefaultWindowHints();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
    glfwWindowHint(GLFW_DEPTH_BITS, GetConfigInt("opengl.depth-bits", 24));
    glfwWindowHint(GLFW_STENCIL_BITS, 0);
    glfwWindowHint(GLFW_SAMPLES, GetConfigInt("opengl.samples", 0));
    glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, debug ? GL_TRUE : GL_FALSE);

    g_Window = glfwCreateWindow(width, height, title, NULL, NULL);
    if(!g_Window)
    {
        Error("Window creation failed.");
        glfwTerminate();
        return false;
    }

    glfwGetWindowSize(g_Window, &g_WindowWidth, &g_WindowHeight);
    glfwGetFramebufferSize(g_Window, &g_FramebufferWidth, &g_FramebufferHeight);

    glfwMakeContextCurrent(g_Window);

    if(!flextInit(g_Window))
    {
        Error("Failed to load OpenGL extensions.");
        return false;
    }

    Log("Using OpenGL %s\n"
        "Vendor: %s\n"
        "Renderer: %s\n"
        "GLSL: %s",
        glGetString(GL_VERSION),
        glGetString(GL_VENDOR),
        glGetString(GL_RENDERER),
        glGetString(GL_SHADING_LANGUAGE_VERSION));

    if(vsync)
    {
        if(FLEXT_EXT_swap_control_tear)
            glfwSwapInterval(-1); // enable vsync (allow the driver to swap even if a frame arrives a little bit late)
        else
            glfwSwapInterval(1); // enable vsync
    }

    glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
    glfwSetInputMode(g_Window, GLFW_STICKY_KEYS, GL_FALSE);
    glfwSetInputMode(g_Window, GLFW_STICKY_MOUSE_BUTTONS, GL_FALSE);

    if(FLEXT_ARB_seamless_cube_map)
    {
        Log("Seamless cubemap filtering supported");
        glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
    }

    if(debug)
    {
        if(FLEXT_ARB_debug_output)
        {
            glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
            glDebugMessageCallbackARB(OnDebugEvent, NULL);
            Log("Debug output supported! You may receive debug messages from your OpenGL driver.");
        }
        else
        {
            Error("Debug output requested, but it's not supported!");
        }
    }

    glfwSetWindowSizeCallback(g_Window, OnWindowResize);
    glfwSetFramebufferSizeCallback(g_Window, OnFramebufferResize);
    glfwSetMouseButtonCallback(g_Window, OnMouseButtonAction);
    glfwSetScrollCallback(g_Window, OnMouseScroll);
    glfwSetCursorPosCallback(g_Window, OnCursorMove);
    glfwSetKeyCallback(g_Window, OnKeyAction);

    return true;
}

void DestroyWindow()
{
    assert(g_Window != NULL);
    glfwDestroyWindow(g_Window);
    glfwTerminate();
}

void SwapBuffers()
{
    glfwSwapBuffers(g_Window);
    glfwPollEvents();
}

void SetWindowTitle( const char* title )
{
    glfwSetWindowTitle(g_Window, title);
}

void FlagWindowForClose()
{
    glfwSetWindowShouldClose(g_Window, GL_TRUE);
}

bool WindowShouldClose()
{
    return glfwWindowShouldClose(g_Window) == GL_TRUE;
}

void* GetGLFWwindow()
{
    return g_Window;
}

glm::ivec2 GetFramebufferSize()
{
    return glm::ivec2(g_FramebufferWidth, g_FramebufferHeight);
}

/****** Input ******/

void SetCursorMode( int mode )
{
    glfwSetInputMode(g_Window, GLFW_CURSOR, mode);
}

/******* Callback Setter *******/

void SetFrambufferFn( FramebufferResizeFn fn )
{
    g_FramebufferResizeFn = fn;
    OnFramebufferResize(NULL, g_FramebufferWidth, g_FramebufferHeight);
}

void SetCursorMoveFn( CursorMoveFn fn )
{
    g_CursorMoveFn = fn;
}

void SetMouseButtonActionFn( MouseButtonActionFn fn )
{
    g_MouseButtonActionFn = fn;
}

void SetMouseScrollFn( MouseScrollFn fn )
{
    g_MouseScrollFn = fn;
}

void SetKeyActionFn( KeyActionFn fn )
{
    g_KeyActionFn = fn;
}

/******* Callbacks ********/

static void OnGLFWError( int code, const char* description )
{
    Error("GLFW error %d: %s", code, description);
}

#if defined(APOAPSIS_GL_DEBUG_FIX)
CALLBACK_API static void OnDebugEvent( GLenum source,
                                       GLenum type,
                                       GLuint id,
                                       GLenum severity,
                                       GLsizei length,
                                       const char* message,
                                       void* userParam )
{
    OnDebugEvent(source, type, id, severity, length, message, (const void*)userParam);
}
#endif

CALLBACK_API static void OnDebugEvent( GLenum source,
                                       GLenum type,
                                       GLuint id,
                                       GLenum severity,
                                       GLsizei length,
                                       const char* message,
                                       const void* userParam )
{
    const char* sourceName = "";
    switch(source)
    {
        case GL_DEBUG_SOURCE_API_ARB: sourceName = "API"; break;
        case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: sourceName = "window system"; break;
        case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: sourceName = "shader"; break;
        case GL_DEBUG_SOURCE_THIRD_PARTY_ARB: sourceName = "third party"; break;
        case GL_DEBUG_SOURCE_APPLICATION_ARB: sourceName = "application"; break;
        case GL_DEBUG_SOURCE_OTHER_ARB: sourceName = ""; break;
    }

    const char* typeName = "unknown issue";
    switch(type)
    {
        case GL_DEBUG_TYPE_ERROR_ARB: typeName = "error"; break;
        case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: typeName = "deprecated behavior"; break;
        case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: typeName = "undefined behavior"; break;
        case GL_DEBUG_TYPE_PORTABILITY_ARB: typeName = "partability issue"; break;
        case GL_DEBUG_TYPE_PERFORMANCE_ARB: typeName = "performance issue"; break;
        case GL_DEBUG_TYPE_OTHER_ARB: typeName = "unknown issue"; break;
    }

    const char* severityName = "";
    switch(severity)
    {
        case GL_DEBUG_SEVERITY_HIGH_ARB: severityName = "High"; break;
        case GL_DEBUG_SEVERITY_MEDIUM_ARB: severityName = "Medium"; break;
        case GL_DEBUG_SEVERITY_LOW_ARB: severityName = "Low"; break;
    }

    Error("%s severity %s %s %d, %s", severityName, sourceName, typeName, id, message);
}

static void OnWindowResize( GLFWwindow* window, int width, int height )
{
    g_WindowWidth = width;
    g_WindowHeight = height;
    // TODO: Update cursor position
}

static void OnFramebufferResize( GLFWwindow* window, int width, int height )
{
    g_FramebufferWidth = width;
    g_FramebufferHeight = height;
    // TODO: Update cursor position
    if(g_FramebufferResizeFn)
        g_FramebufferResizeFn(width, height);
}

static void OnMouseButtonAction( GLFWwindow* window, int button, int action, int mods )
{
    if(g_MouseButtonActionFn)
        g_MouseButtonActionFn(button, action==GLFW_PRESS);
}

static void OnMouseScroll( GLFWwindow* window, double xoffset, double yoffset )
{
    if(g_MouseScrollFn)
        g_MouseScrollFn(xoffset, yoffset);
}

static void OnCursorMove( GLFWwindow* window, double x, double y )
{
    x *= g_FramebufferWidth / g_WindowWidth;
    y *= g_FramebufferHeight / g_WindowHeight;

    if(g_CursorMoveFn)
        g_CursorMoveFn(x, y);
}

static void OnKeyAction( GLFWwindow* window, int key, int scancode, int action, int mods )
{
    if(action != GLFW_REPEAT && g_KeyActionFn)
        g_KeyActionFn(key, scancode, action==GLFW_PRESS);
}
<|endoftext|>