<commit_before>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * 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.
 *
 ***************************************************************/

#ifdef _NO_CONDOR_
#include <sys/types.h> // for fstat, struct stat
#include <sys/stat.h> // for fstat, struct stat
#include <unistd.h> // for fstat, struct stat
#include <limits.h> // for _POSIX_PATH_MAX
#include <string.h> // for strcpy
#include <stdlib.h> // for atol
#include <assert.h> // for assert
#include <errno.h> // for errno
#include <syslog.h> // for syslog, LOG_ERR, LOG_DEBUG
#else
#include "condor_common.h"
#endif

#include "ClassAdLogEntry.h"
#include "ClassAdLogProber.h"
#include "ClassAdLogParser.h"

//! constructor
ClassAdLogProber::ClassAdLogProber()
{
	last_mod_time = 0;
	last_size = 0;
	last_seq_num = 0;
	last_creation_time = 0;

	cur_probed_mod_time = 0;
	cur_probed_size = 0;
	cur_probed_seq_num = 0;
	cur_probed_creation_time = 0;
	job_queue_name[0] = '\0';
}

//! destructor
ClassAdLogProber::~ClassAdLogProber()
{}

//**************************************************************************
// Accessors
//**************************************************************************
void
ClassAdLogProber::setJobQueueName(const char* jqn)
{
	assert(jqn);
	strcpy(job_queue_name, jqn);
}

char*
ClassAdLogProber::getJobQueueName()
{
	return job_queue_name;
}

void
ClassAdLogProber::setLastModifiedTime(time_t t)
{
	last_mod_time = t;
}

time_t
ClassAdLogProber::getLastModifiedTime()
{
	return last_mod_time;
}

void
ClassAdLogProber::setLastSize(size_t s)
{
	last_size = s;
}

size_t
ClassAdLogProber::getLastSize()
{
	return last_size;
}

long int
ClassAdLogProber::getLastSequenceNumber()
{
	return last_seq_num;
}

void
ClassAdLogProber::setLastSequenceNumber(long int seq_num)
{
	last_seq_num = seq_num;
}

time_t
ClassAdLogProber::getLastCreationTime()
{
	return last_creation_time;
}

void
ClassAdLogProber::setLastCreationTime(time_t ctime)
{
	last_creation_time = ctime;
}

long int
ClassAdLogProber::getCurProbedSequenceNumber() {
	return cur_probed_seq_num;
}

long int
ClassAdLogProber::getCurProbedCreationTime() {
	return cur_probed_creation_time;
}

//! probe job_queue.log file
ProbeResultType
ClassAdLogProber::probe(ClassAdLogEntry *curCALogEntry,
			  FILE * job_queue_fd)
Prober::probe(ClassAdLogEntry *curCALogEntry,
			  FILE* job_queue_fp)
{
	FileOpErrCode   st;
	int op_type;
	struct stat filestat;
	int job_queue_fd = fileno(job_queue_fp);
	//TODO: uncomment and possibly change
	/*
	if (job_queue_fd == -1) {
		return PROBE_ERROR;
	}
	*/

	//TODO: should use condor's StatInfo instead.
	if (fstat(job_queue_fd, &filestat) == -1)
#ifdef _NO_CONDOR_
		syslog(LOG_ERR, "ERROR: calling stat(): errno=%d (%m)", errno);

	syslog(LOG_DEBUG, "=== Current Probing Information ===");
	syslog(LOG_DEBUG,
		   "fsize: %ld\t\tmtime: %ld",
		   (long)filestat.st_size, (long)filestat.st_mtime);
#else
		dprintf(D_ALWAYS,"ERROR: calling stat()\n");

	dprintf(D_FULLDEBUG, "=== Current Probing Information ===\n");
	dprintf(D_FULLDEBUG, "fsize: %ld\t\tmtime: %ld\n",
				(long)filestat.st_size, (long)filestat.st_mtime);
#endif

	// get the new state
	cur_probed_mod_time = filestat.st_mtime;
	cur_probed_size = filestat.st_size;

	ClassAdLogParser caLogParser;

	caLogParser.setFilePointer(job_queue_fp);
	caLogParser.setNextOffset(0);
	st = caLogParser.readLogEntry(op_type);

	if (FILE_FATAL_ERROR == st) {
		return PROBE_FATAL_ERROR;
	}
	if (st != FILE_READ_SUCCESS) {
		return PROBE_ERROR;
	}

	if ( caLogParser.getCurCALogEntry()->op_type !=
		 CondorLogOp_LogHistoricalSequenceNumber )
	{
#ifdef _NO_CONDOR_
		syslog(LOG_ERR,
			   "ERROR: prober expects first classad log entry to be "
			   "type %d, but sees %d instead.",
			   CondorLogOp_LogHistoricalSequenceNumber,
			   caLogParser.getCurCALogEntry()->op_type);
#else
		dprintf(D_ALWAYS,
				"ERROR: quill prober expects first classad log entry to be "
				"type %d, but sees %d instead.",
				CondorLogOp_LogHistoricalSequenceNumber,
				caLogParser.getCurCALogEntry()->op_type);
#endif
		return PROBE_FATAL_ERROR;
	}

#ifdef _NO_CONDOR_
	syslog(LOG_DEBUG,
		   "first log entry: %s %s %s",
		   ((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->key,
		   ((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->name,
		   ((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->value);
#else
	dprintf(D_FULLDEBUG, "first log entry: %s %s %s\n",
			((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->key,
			((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->name,
			((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->value);
#endif
	cur_probed_seq_num =
		atol(((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->key);
	cur_probed_creation_time =
		atol(((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->value);

	if (last_size == 0) {
			// starting phase
		return INIT_QUILL;
	}

	if(cur_probed_seq_num != last_seq_num) {
		return COMPRESSED;
	}

	caLogParser.setNextOffset(curCALogEntry->offset);
	st = caLogParser.readLogEntry(op_type);

	if (FILE_FATAL_ERROR == st) {
		return PROBE_FATAL_ERROR;
	}
	if (st != FILE_READ_EOF && st != FILE_READ_SUCCESS) {
		return PROBE_ERROR;
	}

	if((filestat.st_size == last_size) &&
	   caLogParser.getCurCALogEntry()->equal(curCALogEntry)) {
			// File size and contents stay the same
		return NO_CHANGE;
	}
	else if((filestat.st_size > last_size) &&
			caLogParser.getCurCALogEntry()->equal(curCALogEntry)) {
			// File has been increased and new entries have been added
		return ADDITION;
	}
		//if it wasn't captured by any of the above cases,
		//it must have been an error
	return PROBE_ERROR;
}

void
ClassAdLogProber::incrementProbeInfo() {
	// store the currently probed stat
	last_mod_time = cur_probed_mod_time;
	last_size = cur_probed_size;

	last_seq_num = cur_probed_seq_num;
	last_creation_time = cur_probed_creation_time;
}
<commit_msg>Fix bad merge of #1909<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * 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.
 *
 ***************************************************************/

#ifdef _NO_CONDOR_
#include <sys/types.h> // for fstat, struct stat
#include <sys/stat.h> // for fstat, struct stat
#include <unistd.h> // for fstat, struct stat
#include <limits.h> // for _POSIX_PATH_MAX
#include <string.h> // for strcpy
#include <stdlib.h> // for atol
#include <assert.h> // for assert
#include <errno.h> // for errno
#include <syslog.h> // for syslog, LOG_ERR, LOG_DEBUG
#else
#include "condor_common.h"
#endif

#include "ClassAdLogEntry.h"
#include "ClassAdLogProber.h"
#include "ClassAdLogParser.h"

//! constructor
ClassAdLogProber::ClassAdLogProber()
{
	last_mod_time = 0;
	last_size = 0;
	last_seq_num = 0;
	last_creation_time = 0;

	cur_probed_mod_time = 0;
	cur_probed_size = 0;
	cur_probed_seq_num = 0;
	cur_probed_creation_time = 0;
	job_queue_name[0] = '\0';
}

//! destructor
ClassAdLogProber::~ClassAdLogProber()
{}

//**************************************************************************
// Accessors
//**************************************************************************
void
ClassAdLogProber::setJobQueueName(const char* jqn)
{
	assert(jqn);
	strcpy(job_queue_name, jqn);
}

char*
ClassAdLogProber::getJobQueueName()
{
	return job_queue_name;
}

void
ClassAdLogProber::setLastModifiedTime(time_t t)
{
	last_mod_time = t;
}

time_t
ClassAdLogProber::getLastModifiedTime()
{
	return last_mod_time;
}

void
ClassAdLogProber::setLastSize(size_t s)
{
	last_size = s;
}

size_t
ClassAdLogProber::getLastSize()
{
	return last_size;
}

long int
ClassAdLogProber::getLastSequenceNumber()
{
	return last_seq_num;
}

void
ClassAdLogProber::setLastSequenceNumber(long int seq_num)
{
	last_seq_num = seq_num;
}

time_t
ClassAdLogProber::getLastCreationTime()
{
	return last_creation_time;
}

void
ClassAdLogProber::setLastCreationTime(time_t ctime)
{
	last_creation_time = ctime;
}

long int
ClassAdLogProber::getCurProbedSequenceNumber() {
	return cur_probed_seq_num;
}

long int
ClassAdLogProber::getCurProbedCreationTime() {
	return cur_probed_creation_time;
}

//! probe job_queue.log file
ProbeResultType
ClassAdLogProber::probe(ClassAdLogEntry *curCALogEntry,
			  FILE * job_queue_fp)
{
	FileOpErrCode   st;
	int op_type;
	struct stat filestat;
	int job_queue_fd = fileno(job_queue_fp);
	//TODO: uncomment and possibly change
	/*
	if (job_queue_fd == -1) {
		return PROBE_ERROR;
	}
	*/

	//TODO: should use condor's StatInfo instead.
	if (fstat(job_queue_fd, &filestat) == -1)
#ifdef _NO_CONDOR_
		syslog(LOG_ERR, "ERROR: calling stat(): errno=%d (%m)", errno);

	syslog(LOG_DEBUG, "=== Current Probing Information ===");
	syslog(LOG_DEBUG,
		   "fsize: %ld\t\tmtime: %ld",
		   (long)filestat.st_size, (long)filestat.st_mtime);
#else
		dprintf(D_ALWAYS,"ERROR: calling stat()\n");

	dprintf(D_FULLDEBUG, "=== Current Probing Information ===\n");
	dprintf(D_FULLDEBUG, "fsize: %ld\t\tmtime: %ld\n",
				(long)filestat.st_size, (long)filestat.st_mtime);
#endif

	// get the new state
	cur_probed_mod_time = filestat.st_mtime;
	cur_probed_size = filestat.st_size;

	ClassAdLogParser caLogParser;

	caLogParser.setFilePointer(job_queue_fp);
	caLogParser.setNextOffset(0);
	st = caLogParser.readLogEntry(op_type);

	if (FILE_FATAL_ERROR == st) {
		return PROBE_FATAL_ERROR;
	}
	if (st != FILE_READ_SUCCESS) {
		return PROBE_ERROR;
	}

	if ( caLogParser.getCurCALogEntry()->op_type !=
		 CondorLogOp_LogHistoricalSequenceNumber )
	{
#ifdef _NO_CONDOR_
		syslog(LOG_ERR,
			   "ERROR: prober expects first classad log entry to be "
			   "type %d, but sees %d instead.",
			   CondorLogOp_LogHistoricalSequenceNumber,
			   caLogParser.getCurCALogEntry()->op_type);
#else
		dprintf(D_ALWAYS,
				"ERROR: quill prober expects first classad log entry to be "
				"type %d, but sees %d instead.",
				CondorLogOp_LogHistoricalSequenceNumber,
				caLogParser.getCurCALogEntry()->op_type);
#endif
		return PROBE_FATAL_ERROR;
	}

#ifdef _NO_CONDOR_
	syslog(LOG_DEBUG,
		   "first log entry: %s %s %s",
		   ((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->key,
		   ((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->name,
		   ((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->value);
#else
	dprintf(D_FULLDEBUG, "first log entry: %s %s %s\n",
			((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->key,
			((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->name,
			((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->value);
#endif
	cur_probed_seq_num =
		atol(((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->key);
	cur_probed_creation_time =
		atol(((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->value);

	if (last_size == 0) {
			// starting phase
		return INIT_QUILL;
	}

	if(cur_probed_seq_num != last_seq_num) {
		return COMPRESSED;
	}

	caLogParser.setNextOffset(curCALogEntry->offset);
	st = caLogParser.readLogEntry(op_type);

	if (FILE_FATAL_ERROR == st) {
		return PROBE_FATAL_ERROR;
	}
	if (st != FILE_READ_EOF && st != FILE_READ_SUCCESS) {
		return PROBE_ERROR;
	}

	if((filestat.st_size == last_size) &&
	   caLogParser.getCurCALogEntry()->equal(curCALogEntry)) {
			// File size and contents stay the same
		return NO_CHANGE;
	}
	else if((filestat.st_size > last_size) &&
			caLogParser.getCurCALogEntry()->equal(curCALogEntry)) {
			// File has been increased and new entries have been added
		return ADDITION;
	}
		//if it wasn't captured by any of the above cases,
		//it must have been an error
	return PROBE_ERROR;
}

void
ClassAdLogProber::incrementProbeInfo() {
	// store the currently probed stat
	last_mod_time = cur_probed_mod_time;
	last_size = cur_probed_size;

	last_seq_num = cur_probed_seq_num;
	last_creation_time = cur_probed_creation_time;
}
<|endoftext|>


<commit_before>#include <iostream>
#include "jcl/cl_include.h"
#include "jcl/jcl.h"
#include "jcl/opencl_context.h"

namespace jcl {

  std::mutex JCL::context_lock_;

  JCL::JCL(const CLDevice device, const CLVendor vendor,
    const bool strict_float) {
    context_ = nullptr;
    device_ = device;
    vendor_ = vendor;
    strict_float_ = strict_float;

#if defined(DEBUG) || defined(_DEBUG)
    std::cout << "\tCreating OpenCL Context..." << std::endl
#endif

    // Aquire lock to prevent multiple initilizations:
    std::lock_guard<std::mutex> lock(context_lock_);

    context_ .reset(new OpenCLContext());
    context_->createContext(device, vendor);
    context_->InitDevices(device);
    context_->createCommandQueues();  // For each device
  }

  JCL::~JCL() {
#if defined(DEBUG) || defined(_DEBUG)
    std::cout << "\tShutting down OpenCL Context..." << std::endl;
#endif
  }

  bool JCL::queryDeviceExists(const CLDevice device, const CLVendor vendor) {
    // Aquire lock to prevent multiple initilizations:
    std::lock_guard<std::mutex> lock(context_lock_);
    return OpenCLContext::queryDeviceExists(device, vendor);
  }

  uint32_t JCL::getNumDevices() {
    return context_->getNumDevices();
  }

  std::string JCL::getDeviceName(const uint32_t device_index) {
    return context_->getDeviceName(device_index);
  }

  uint32_t JCL::getMaxWorkgroupSize(const uint32_t device_index) {
    return context_->getMaxWorkgroupSize(device_index);
  }

  uint32_t JCL::getMaxWorkitemSize(const uint32_t device_index, const uint32_t dim) {
    return context_->getMaxWorkitemSize(device_index, dim);
  }

  CLDevice JCL::getDeviceType(const uint32_t device_index) {
    return context_->getDeviceType(device_index);
  }

  JCLBuffer JCL::allocateBuffer(const CLBufferType type,
    const uint32_t nelems) {
    return context_->allocateBuffer(type, nelems);
  }

  void JCL::releaseReference(const JCLBuffer buffer) {
    context_->releaseReference(buffer);
  }

  void JCL::addReference(const JCLBuffer buffer) {
    context_->addReference(buffer);
  }

  void JCL::writeToBuffer(const float* data, const uint32_t device_index,
    const JCLBuffer buffer, const bool blocking) {
    context_->writeToBuffer<float>(data, device_index, buffer, blocking);
  }

  void JCL::readFromBuffer(float* data, const uint32_t device_index,
    const JCLBuffer buffer, const bool blocking) {
    context_->readFromBuffer<float>(data, device_index, buffer, blocking);
  }

  void JCL::writeToBuffer(const int* data, const uint32_t device_index,
    const JCLBuffer buffer, const bool blocking) {
    context_->writeToBuffer<int>(data, device_index, buffer, blocking);
  }

  void JCL::readFromBuffer(int* data, const uint32_t device_index,
    const JCLBuffer buffer, const bool blocking) {
    context_->readFromBuffer<int>(data, device_index, buffer, blocking);
  }

  void JCL::writeToBuffer(const int16_t* data, const uint32_t device_index,
    const JCLBuffer buffer, const bool blocking) {
    context_->writeToBuffer<int16_t>(data, device_index, buffer, blocking);
  }

  void JCL::readFromBuffer(int16_t* data, const uint32_t device_index,
    const JCLBuffer buffer, const bool blocking) {
    context_->readFromBuffer<int16_t>(data, device_index, buffer, blocking);
  }

  void JCL::writeToBuffer(const uint8_t* data, const uint32_t device_index,
    const JCLBuffer buffer, const bool blocking) {
    context_->writeToBuffer<uint8_t>(data, device_index, buffer, blocking);
  }

  void JCL::readFromBuffer(uint8_t* data, const uint32_t device_index,
    const JCLBuffer buffer, const bool blocking) {
    context_->readFromBuffer<uint8_t>(data, device_index, buffer, blocking);
  }

  void JCL::useKernel(const char* filename, const char* kernel_name) {
    context_->useKernel(filename, kernel_name, strict_float_);
  }

  void JCL::useKernelCStr(const char* kernel_c_str, const char* kernel_name) {
    context_->useKernelCStr(kernel_c_str, kernel_name, strict_float_);
  }

  void JCL::setArg(const uint32_t index, JCLBuffer buf) {
    context_->setArg(index, buf);
  }

  void JCL::setArg(const uint32_t index, int val) {
    context_->setArg(index, val);
  }

  void JCL::setArg(const uint32_t index, float val) {
    context_->setArg(index, val);
  }

  void JCL::setArg(const uint32_t index, const uint32_t size, void* data) {
    context_->setArg(index, size, data);
  }

  void JCL::runKernel(const uint32_t device_index,
    const uint32_t dim,  const uint32_t* global_work_size,
    const uint32_t* local_work_size, const bool blocking) {
    context_->runKernel(device_index, dim, global_work_size,
      local_work_size, blocking);
  }

  void* JCL::queue(const uint32_t device_index) {
    return context_->queues[device_index]();
  }

  void* JCL::getCLMem(const JCLBuffer buffer) {
    return context_->getCLMem(buffer);
  }

  std::string JCL::getErrorString(signed int err) {
    switch (err) {
    case 0: return "CL_SUCCESS";
    case -1: return "CL_DEVICE_NOT_FOUND";
    case -2: return "CL_DEVICE_NOT_AVAILABLE";
    case -3: return "CL_COMPILER_NOT_AVAILABLE";
    case -4: return "CL_MEM_OBJECT_ALLOCATION_FAILURE";
    case -5: return "CL_OUT_OF_RESOURCES";
    case -6: return "CL_OUT_OF_HOST_MEMORY";
    case -7: return "CL_PROFILING_INFO_NOT_AVAILABLE";
    case -8: return "CL_MEM_COPY_OVERLAP";
    case -9: return "CL_IMAGE_FORMAT_MISMATCH";
    case -10: return "CL_IMAGE_FORMAT_NOT_SUPPORTED";
    case -11: return "CL_BUILD_PROGRAM_FAILURE";
    case -12: return "CL_MAP_FAILURE";

    case -30: return "CL_INVALID_VALUE";
    case -31: return "CL_INVALID_DEVICE_TYPE";
    case -32: return "CL_INVALID_PLATFORM";
    case -33: return "CL_INVALID_DEVICE";
    case -34: return "CL_INVALID_CONTEXT";
    case -35: return "CL_INVALID_QUEUE_PROPERTIES";
    case -36: return "CL_INVALID_COMMAND_QUEUE";
    case -37: return "CL_INVALID_HOST_PTR";
    case -38: return "CL_INVALID_MEM_OBJECT";
    case -39: return "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR";
    case -40: return "CL_INVALID_IMAGE_SIZE";
    case -41: return "CL_INVALID_SAMPLER";
    case -42: return "CL_INVALID_BINARY";
    case -43: return "CL_INVALID_BUILD_OPTIONS";
    case -44: return "CL_INVALID_PROGRAM";
    case -45: return "CL_INVALID_PROGRAM_EXECUTABLE";
    case -46: return "CL_INVALID_KERNEL_NAME";
    case -47: return "CL_INVALID_KERNEL_DEFINITION";
    case -48: return "CL_INVALID_KERNEL";
    case -49: return "CL_INVALID_ARG_INDEX";
    case -50: return "CL_INVALID_ARG_VALUE";
    case -51: return "CL_INVALID_ARG_SIZE";
    case -52: return "CL_INVALID_KERNEL_ARGS";
    case -53: return "CL_INVALID_WORK_DIMENSION";
    case -54: return "CL_INVALID_WORK_GROUP_SIZE";
    case -55: return "CL_INVALID_WORK_ITEM_SIZE";
    case -56: return "CL_INVALID_GLOBAL_OFFSET";
    case -57: return "CL_INVALID_EVENT_WAIT_LIST";
    case -58: return "CL_INVALID_EVENT";
    case -59: return "CL_INVALID_OPERATION";
    case -60: return "CL_INVALID_GL_OBJECT";
    case -61: return "CL_INVALID_BUFFER_SIZE";
    case -62: return "CL_INVALID_MIP_LEVEL";
    case -63: return "CL_INVALID_GLOBAL_WORK_SIZE";
    default: return "Unknown OpenCL error";
    }
  }

  void JCL::sync(const uint32_t device_index) {
    context_->sync(device_index);
  }

  void JCL::runKernel(const uint32_t device_index,
    const uint32_t dim, const uint32_t* global_work_size,
    const bool blocking) {
    context_->runKernel(device_index, dim, global_work_size, blocking);
  }

  uint32_t JCL::queryMaxWorkgroupSizeForCurKernel(const uint32_t device_index) {
    return context_->queryMaxWorkgroupSizeForCurKernel(device_index);
  }

  std::string JCL::CLDeviceToString(const CLDevice device) {
    switch (device) {
    case CLDeviceDefault:
      return "CLDeviceDefault";
    case CLDeviceAll:
      return "CLDeviceAll";
    case CLDeviceCPU:
      return "CLDeviceCPU";
    case CLDeviceGPU:
      return "CLDeviceGPU";
    case CLDeviceAccelerator:
      return "CLDeviceDefault";
    default:
      std::cout << "Bad CLDevice" << std::endl;
      RASSERT(false);
      return "Bad CLDevice";
    }
  }

  std::string JCL::CLVendorToString(const CLVendor vendor) {
    switch (vendor) {
    case CLVendorAny:
      return "CLVendorAny";
    case CLDeviceNVidia:
      return "CLDeviceNVidia";
    case CLDeviceAMD:
      return "CLDeviceAMD";
    case CLDeviceIntel:
      return "CLDeviceIntel";
    default:
      std::cout << "Bad CLVendor" << std::endl;
      RASSERT(false);
      return "Bad CLVendor";
    }
  }

}  // namespace jcl
<commit_msg>fix compiler error<commit_after>#include <iostream>
#include "jcl/cl_include.h"
#include "jcl/jcl.h"
#include "jcl/opencl_context.h"

namespace jcl {

  std::mutex JCL::context_lock_;

  JCL::JCL(const CLDevice device, const CLVendor vendor,
    const bool strict_float) {
    context_ = nullptr;
    device_ = device;
    vendor_ = vendor;
    strict_float_ = strict_float;

#if defined(DEBUG) || defined(_DEBUG)
    std::cout << "\tCreating OpenCL Context..." << std::endl;
#endif

    // Aquire lock to prevent multiple initilizations:
    std::lock_guard<std::mutex> lock(context_lock_);

    context_ .reset(new OpenCLContext());
    context_->createContext(device, vendor);
    context_->InitDevices(device);
    context_->createCommandQueues();  // For each device
  }

  JCL::~JCL() {
#if defined(DEBUG) || defined(_DEBUG)
    std::cout << "\tShutting down OpenCL Context..." << std::endl;
#endif
  }

  bool JCL::queryDeviceExists(const CLDevice device, const CLVendor vendor) {
    // Aquire lock to prevent multiple initilizations:
    std::lock_guard<std::mutex> lock(context_lock_);
    return OpenCLContext::queryDeviceExists(device, vendor);
  }

  uint32_t JCL::getNumDevices() {
    return context_->getNumDevices();
  }

  std::string JCL::getDeviceName(const uint32_t device_index) {
    return context_->getDeviceName(device_index);
  }

  uint32_t JCL::getMaxWorkgroupSize(const uint32_t device_index) {
    return context_->getMaxWorkgroupSize(device_index);
  }

  uint32_t JCL::getMaxWorkitemSize(const uint32_t device_index, const uint32_t dim) {
    return context_->getMaxWorkitemSize(device_index, dim);
  }

  CLDevice JCL::getDeviceType(const uint32_t device_index) {
    return context_->getDeviceType(device_index);
  }

  JCLBuffer JCL::allocateBuffer(const CLBufferType type,
    const uint32_t nelems) {
    return context_->allocateBuffer(type, nelems);
  }

  void JCL::releaseReference(const JCLBuffer buffer) {
    context_->releaseReference(buffer);
  }

  void JCL::addReference(const JCLBuffer buffer) {
    context_->addReference(buffer);
  }

  void JCL::writeToBuffer(const float* data, const uint32_t device_index,
    const JCLBuffer buffer, const bool blocking) {
    context_->writeToBuffer<float>(data, device_index, buffer, blocking);
  }

  void JCL::readFromBuffer(float* data, const uint32_t device_index,
    const JCLBuffer buffer, const bool blocking) {
    context_->readFromBuffer<float>(data, device_index, buffer, blocking);
  }

  void JCL::writeToBuffer(const int* data, const uint32_t device_index,
    const JCLBuffer buffer, const bool blocking) {
    context_->writeToBuffer<int>(data, device_index, buffer, blocking);
  }

  void JCL::readFromBuffer(int* data, const uint32_t device_index,
    const JCLBuffer buffer, const bool blocking) {
    context_->readFromBuffer<int>(data, device_index, buffer, blocking);
  }

  void JCL::writeToBuffer(const int16_t* data, const uint32_t device_index,
    const JCLBuffer buffer, const bool blocking) {
    context_->writeToBuffer<int16_t>(data, device_index, buffer, blocking);
  }

  void JCL::readFromBuffer(int16_t* data, const uint32_t device_index,
    const JCLBuffer buffer, const bool blocking) {
    context_->readFromBuffer<int16_t>(data, device_index, buffer, blocking);
  }

  void JCL::writeToBuffer(const uint8_t* data, const uint32_t device_index,
    const JCLBuffer buffer, const bool blocking) {
    context_->writeToBuffer<uint8_t>(data, device_index, buffer, blocking);
  }

  void JCL::readFromBuffer(uint8_t* data, const uint32_t device_index,
    const JCLBuffer buffer, const bool blocking) {
    context_->readFromBuffer<uint8_t>(data, device_index, buffer, blocking);
  }

  void JCL::useKernel(const char* filename, const char* kernel_name) {
    context_->useKernel(filename, kernel_name, strict_float_);
  }

  void JCL::useKernelCStr(const char* kernel_c_str, const char* kernel_name) {
    context_->useKernelCStr(kernel_c_str, kernel_name, strict_float_);
  }

  void JCL::setArg(const uint32_t index, JCLBuffer buf) {
    context_->setArg(index, buf);
  }

  void JCL::setArg(const uint32_t index, int val) {
    context_->setArg(index, val);
  }

  void JCL::setArg(const uint32_t index, float val) {
    context_->setArg(index, val);
  }

  void JCL::setArg(const uint32_t index, const uint32_t size, void* data) {
    context_->setArg(index, size, data);
  }

  void JCL::runKernel(const uint32_t device_index,
    const uint32_t dim,  const uint32_t* global_work_size,
    const uint32_t* local_work_size, const bool blocking) {
    context_->runKernel(device_index, dim, global_work_size,
      local_work_size, blocking);
  }

  void* JCL::queue(const uint32_t device_index) {
    return context_->queues[device_index]();
  }

  void* JCL::getCLMem(const JCLBuffer buffer) {
    return context_->getCLMem(buffer);
  }

  std::string JCL::getErrorString(signed int err) {
    switch (err) {
    case 0: return "CL_SUCCESS";
    case -1: return "CL_DEVICE_NOT_FOUND";
    case -2: return "CL_DEVICE_NOT_AVAILABLE";
    case -3: return "CL_COMPILER_NOT_AVAILABLE";
    case -4: return "CL_MEM_OBJECT_ALLOCATION_FAILURE";
    case -5: return "CL_OUT_OF_RESOURCES";
    case -6: return "CL_OUT_OF_HOST_MEMORY";
    case -7: return "CL_PROFILING_INFO_NOT_AVAILABLE";
    case -8: return "CL_MEM_COPY_OVERLAP";
    case -9: return "CL_IMAGE_FORMAT_MISMATCH";
    case -10: return "CL_IMAGE_FORMAT_NOT_SUPPORTED";
    case -11: return "CL_BUILD_PROGRAM_FAILURE";
    case -12: return "CL_MAP_FAILURE";

    case -30: return "CL_INVALID_VALUE";
    case -31: return "CL_INVALID_DEVICE_TYPE";
    case -32: return "CL_INVALID_PLATFORM";
    case -33: return "CL_INVALID_DEVICE";
    case -34: return "CL_INVALID_CONTEXT";
    case -35: return "CL_INVALID_QUEUE_PROPERTIES";
    case -36: return "CL_INVALID_COMMAND_QUEUE";
    case -37: return "CL_INVALID_HOST_PTR";
    case -38: return "CL_INVALID_MEM_OBJECT";
    case -39: return "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR";
    case -40: return "CL_INVALID_IMAGE_SIZE";
    case -41: return "CL_INVALID_SAMPLER";
    case -42: return "CL_INVALID_BINARY";
    case -43: return "CL_INVALID_BUILD_OPTIONS";
    case -44: return "CL_INVALID_PROGRAM";
    case -45: return "CL_INVALID_PROGRAM_EXECUTABLE";
    case -46: return "CL_INVALID_KERNEL_NAME";
    case -47: return "CL_INVALID_KERNEL_DEFINITION";
    case -48: return "CL_INVALID_KERNEL";
    case -49: return "CL_INVALID_ARG_INDEX";
    case -50: return "CL_INVALID_ARG_VALUE";
    case -51: return "CL_INVALID_ARG_SIZE";
    case -52: return "CL_INVALID_KERNEL_ARGS";
    case -53: return "CL_INVALID_WORK_DIMENSION";
    case -54: return "CL_INVALID_WORK_GROUP_SIZE";
    case -55: return "CL_INVALID_WORK_ITEM_SIZE";
    case -56: return "CL_INVALID_GLOBAL_OFFSET";
    case -57: return "CL_INVALID_EVENT_WAIT_LIST";
    case -58: return "CL_INVALID_EVENT";
    case -59: return "CL_INVALID_OPERATION";
    case -60: return "CL_INVALID_GL_OBJECT";
    case -61: return "CL_INVALID_BUFFER_SIZE";
    case -62: return "CL_INVALID_MIP_LEVEL";
    case -63: return "CL_INVALID_GLOBAL_WORK_SIZE";
    default: return "Unknown OpenCL error";
    }
  }

  void JCL::sync(const uint32_t device_index) {
    context_->sync(device_index);
  }

  void JCL::runKernel(const uint32_t device_index,
    const uint32_t dim, const uint32_t* global_work_size,
    const bool blocking) {
    context_->runKernel(device_index, dim, global_work_size, blocking);
  }

  uint32_t JCL::queryMaxWorkgroupSizeForCurKernel(const uint32_t device_index) {
    return context_->queryMaxWorkgroupSizeForCurKernel(device_index);
  }

  std::string JCL::CLDeviceToString(const CLDevice device) {
    switch (device) {
    case CLDeviceDefault:
      return "CLDeviceDefault";
    case CLDeviceAll:
      return "CLDeviceAll";
    case CLDeviceCPU:
      return "CLDeviceCPU";
    case CLDeviceGPU:
      return "CLDeviceGPU";
    case CLDeviceAccelerator:
      return "CLDeviceDefault";
    default:
      std::cout << "Bad CLDevice" << std::endl;
      RASSERT(false);
      return "Bad CLDevice";
    }
  }

  std::string JCL::CLVendorToString(const CLVendor vendor) {
    switch (vendor) {
    case CLVendorAny:
      return "CLVendorAny";
    case CLDeviceNVidia:
      return "CLDeviceNVidia";
    case CLDeviceAMD:
      return "CLDeviceAMD";
    case CLDeviceIntel:
      return "CLDeviceIntel";
    default:
      std::cout << "Bad CLVendor" << std::endl;
      RASSERT(false);
      return "Bad CLVendor";
    }
  }

}  // namespace jcl
<|endoftext|>


<commit_before>#include "core/raytracer.h"

#include "core/image.h"

#include "core/intersection.h"
#include "core/sphere.h"
#include "core/random.h"
#include "core/polarcoord.h"
#include "core/numeric.h"

#include <limits>

namespace euphoria::core::raytracer
{
    HitResult::HitResult
    (
        bool acollided,
        float aray_distance,
        const vec3f& aposition,
        const unit3f& anormal
    )
        : collided(acollided)
        , ray_distance(aray_distance)
        , position(aposition)
        , normal(anormal)
    {
    }

    HitResult
    NoCollision
    (
    )
    {
        return HitResult
        {
            false,
            10000.0f,
            vec3f::Zero(),
            unit3f::Up()
        };
    }

    HitResult
    Collision
    (
        float ray_distance,
        const vec3f& position,
        const unit3f& normal
    )
    {
        return HitResult
        {
            true,
            ray_distance,
            position,
            normal
        };
    }

    struct SphereObject : public Object
    {
        Sphere sphere;
        vec3f position;

        SphereObject(const Sphere& asphere, const vec3f& aposition)
            : sphere(asphere)
            , position(aposition)
        {
        }

        HitResult
        Hit(const UnitRay3f& ray, const Range<float>& range) const override
        {
            const auto hit_index = GetIntersection
            (
                ray,
                sphere,
                position
            );
            if(IsWithin(range, hit_index))
            {
                const auto hit_position = ray.GetPoint(hit_index);
                const auto hit_normal = vec3f::FromTo(position, hit_position).GetNormalized();
                return Collision
                (
                    hit_index,
                    hit_position,
                    hit_normal
                );
            }
            else
            {
                return NoCollision();
            }
        }
    };

    std::shared_ptr<Object>
    CreateSphere(const Sphere& sphere, const vec3f& position)
    {
        return std::make_shared<SphereObject>
        (
            sphere,
            position
        );
    }

    HitResult
    Scene::Hit(const UnitRay3f& ray, const Range<float>& range) const
    {
        auto r = NoCollision();

        for(const auto o: objects)
        {
            const auto h = o->Hit(ray, range);
            if(r.collided == false)
            {
                r = h;
            }
            else
            {
                if(h.collided)
                {
                    if(h.ray_distance < r.ray_distance)
                    {
                        r = h;
                    }
                }
            }
        }

        return r;
    }

    Rgb
    rgb(const unit3f& normal)
    {
        return Rgb
        {
            (normal.x + 1)/2,
            (normal.y + 1)/2,
            (normal.z + 1)/2
        };
    }

    vec3f RandomInUnitSphere(Random* random)
    {
        return RandomUnit3(random) * random->NextFloat01();
    }

    Rgb
    GetColor(const Scene& scene, const UnitRay3f& ray, Random* random)
    {
        const auto h = scene.Hit
        (
            ray,
            MakeRange(0.0f, std::numeric_limits<float>::max())
        );
        if(h.collided)
        {
            const auto target = h.position + h.normal + RandomInUnitSphere(random);
            const auto reflected_ray = UnitRay3f::FromTo(h.position, target);
            return 0.5f * GetColor(scene, reflected_ray, random);
            // return rgb(h.normal);
        }
        const auto t = (ray.dir.y+1)/2.0f;
        return RgbTransform::Transform
        (
            Rgb(1.0f, 1.0f, 1.0f),
            t,
            Rgb(0.5f, 0.7f, 1.0f)
        );
    }

    struct Camera
    {
        vec3f lower_left_corner = vec3f{-2.0f, -1.0f, -1.0f};
        vec3f horizontal = vec3f{4.0f, 0.0f, 0.0f};
        vec3f vertical = vec3f{0.0f, 2.0f, 0.0f};
        vec3f origin = vec3f{0.0f, 0.0f, 0.0f};

        UnitRay3f GetRay(float u, float v) const
        {
            return UnitRay3f::FromTo(origin, lower_left_corner + u*horizontal + v*vertical);
        }
    };

    Rgb
    Gamma2CorrectColor(Rgb color)
    {
        return {Sqrt(color.r), Sqrt(color.g), Sqrt(color.b)};
    }

    void
    Raytrace(Image* aimage, const Scene& scene, int number_of_samples)
    {
        Image& img = *aimage;

        auto random = Random{};
        const auto camera = Camera{};

        for(int y=0; y<img.GetHeight(); y+=1)
        for(int x=0; x<img.GetWidth(); x+=1)
        {
            Rgb color = Color::Black;
            for(int sample = 0; sample < number_of_samples; sample += 1)
            {
                const auto u = (x + random.NextFloat01()) / static_cast<float>(img.GetWidth());
                const auto v = (y + random.NextFloat01()) / static_cast<float>(img.GetHeight());
                const auto ray = camera.GetRay(u, v);
                const auto sample_color = GetColor(scene, ray, &random);
                color += sample_color;
            }
            color = color/number_of_samples;
            color = Gamma2CorrectColor(color);
            img.SetPixel(x,y, rgbi(color));
        }
    }
}

<commit_msg>raytracer step 11: avoiding shadow acne<commit_after>#include "core/raytracer.h"

#include "core/image.h"

#include "core/intersection.h"
#include "core/sphere.h"
#include "core/random.h"
#include "core/polarcoord.h"
#include "core/numeric.h"

#include <limits>

namespace euphoria::core::raytracer
{
    HitResult::HitResult
    (
        bool acollided,
        float aray_distance,
        const vec3f& aposition,
        const unit3f& anormal
    )
        : collided(acollided)
        , ray_distance(aray_distance)
        , position(aposition)
        , normal(anormal)
    {
    }

    HitResult
    NoCollision
    (
    )
    {
        return HitResult
        {
            false,
            10000.0f,
            vec3f::Zero(),
            unit3f::Up()
        };
    }

    HitResult
    Collision
    (
        float ray_distance,
        const vec3f& position,
        const unit3f& normal
    )
    {
        return HitResult
        {
            true,
            ray_distance,
            position,
            normal
        };
    }

    struct SphereObject : public Object
    {
        Sphere sphere;
        vec3f position;

        SphereObject(const Sphere& asphere, const vec3f& aposition)
            : sphere(asphere)
            , position(aposition)
        {
        }

        HitResult
        Hit(const UnitRay3f& ray, const Range<float>& range) const override
        {
            const auto hit_index = GetIntersection
            (
                ray,
                sphere,
                position
            );
            if(IsWithin(range, hit_index))
            {
                const auto hit_position = ray.GetPoint(hit_index);
                const auto hit_normal = vec3f::FromTo(position, hit_position).GetNormalized();
                return Collision
                (
                    hit_index,
                    hit_position,
                    hit_normal
                );
            }
            else
            {
                return NoCollision();
            }
        }
    };

    std::shared_ptr<Object>
    CreateSphere(const Sphere& sphere, const vec3f& position)
    {
        return std::make_shared<SphereObject>
        (
            sphere,
            position
        );
    }

    HitResult
    Scene::Hit(const UnitRay3f& ray, const Range<float>& range) const
    {
        auto r = NoCollision();

        for(const auto o: objects)
        {
            const auto h = o->Hit(ray, range);
            if(r.collided == false)
            {
                r = h;
            }
            else
            {
                if(h.collided)
                {
                    if(h.ray_distance < r.ray_distance)
                    {
                        r = h;
                    }
                }
            }
        }

        return r;
    }

    Rgb
    rgb(const unit3f& normal)
    {
        return Rgb
        {
            (normal.x + 1)/2,
            (normal.y + 1)/2,
            (normal.z + 1)/2
        };
    }

    vec3f RandomInUnitSphere(Random* random)
    {
        return RandomUnit3(random) * random->NextFloat01();
    }

    Rgb
    GetColor(const Scene& scene, const UnitRay3f& ray, Random* random)
    {
        const auto h = scene.Hit
        (
            ray,
            MakeRange(0.001f, std::numeric_limits<float>::max())
        );
        if(h.collided)
        {
            const auto target = h.position + h.normal + RandomInUnitSphere(random);
            const auto reflected_ray = UnitRay3f::FromTo(h.position, target);
            return 0.5f * GetColor(scene, reflected_ray, random);
            // return rgb(h.normal);
        }
        const auto t = (ray.dir.y+1)/2.0f;
        return RgbTransform::Transform
        (
            Rgb(1.0f, 1.0f, 1.0f),
            t,
            Rgb(0.5f, 0.7f, 1.0f)
        );
    }

    struct Camera
    {
        vec3f lower_left_corner = vec3f{-2.0f, -1.0f, -1.0f};
        vec3f horizontal = vec3f{4.0f, 0.0f, 0.0f};
        vec3f vertical = vec3f{0.0f, 2.0f, 0.0f};
        vec3f origin = vec3f{0.0f, 0.0f, 0.0f};

        UnitRay3f GetRay(float u, float v) const
        {
            return UnitRay3f::FromTo(origin, lower_left_corner + u*horizontal + v*vertical);
        }
    };

    Rgb
    Gamma2CorrectColor(Rgb color)
    {
        return {Sqrt(color.r), Sqrt(color.g), Sqrt(color.b)};
    }

    void
    Raytrace(Image* aimage, const Scene& scene, int number_of_samples)
    {
        Image& img = *aimage;

        auto random = Random{};
        const auto camera = Camera{};

        for(int y=0; y<img.GetHeight(); y+=1)
        for(int x=0; x<img.GetWidth(); x+=1)
        {
            Rgb color = Color::Black;
            for(int sample = 0; sample < number_of_samples; sample += 1)
            {
                const auto u = (x + random.NextFloat01()) / static_cast<float>(img.GetWidth());
                const auto v = (y + random.NextFloat01()) / static_cast<float>(img.GetHeight());
                const auto ray = camera.GetRay(u, v);
                const auto sample_color = GetColor(scene, ray, &random);
                color += sample_color;
            }
            color = color/number_of_samples;
            color = Gamma2CorrectColor(color);
            img.SetPixel(x,y, rgbi(color));
        }
    }
}

<|endoftext|>


<commit_before>#include <array>
#include <atomic>
#include <string>
#include <iostream>
#include <vector>
#include <limits>
#include <memory>
#include <cstdio>
#include "linalg/util.h"
#include "render/render_target.h"

/*
 * Perform an atomic addition to the float via spin-locking
 * on compare_exchange_weak. Memory ordering is release on write
 * consume on read
 */
static float atomic_addf(std::atomic<float> &f, float d){
	float old = f.load(std::memory_order_consume);
	float desired = old + d;
	while (!f.compare_exchange_weak(old, desired,
		std::memory_order_release, std::memory_order_consume))
	{
		desired = old + d;
	}
	return desired;
}

Pixel::Pixel() : r(0), g(0), b(0), weight(0){}
Pixel::Pixel(const Pixel &p) : r(p.r.load(std::memory_order_consume)), g(p.g.load(std::memory_order_consume)),
	b(p.b.load(std::memory_order_consume)), weight(p.weight.load(std::memory_order_consume))
{}

RenderTarget::RenderTarget(size_t width, size_t height, std::unique_ptr<Filter> f)
	: width(width), height(height), filter(std::move(f)), pixels(width * height),
	float_buf(width * height, std::numeric_limits<float>::infinity())
{
	//Pre-compute the filter table values
	for (int y = 0; y < FILTER_TABLE_SIZE; ++y){
		float fy = (y + .5f) * filter->h / FILTER_TABLE_SIZE;
		for (int x = 0; x < FILTER_TABLE_SIZE; ++x){
			float fx = (x + .5f) * filter->w / FILTER_TABLE_SIZE;
			filter_table[y * FILTER_TABLE_SIZE + x] = filter->weight(fx, fy);
		}
	}
}
void RenderTarget::write_pixel(float x, float y, const Colorf &c){
	//Compute the discrete pixel coordinates which the sample hits
	float img_x = x - 0.5f;
	float img_y = y - 0.5f;
	std::array<int, 2> x_range = {static_cast<int>(std::ceil(img_x - filter->w)),
		static_cast<int>(std::floor(img_x + filter->w))};
	std::array<int, 2> y_range = {static_cast<int>(std::ceil(img_y - filter->h)),
		static_cast<int>(std::floor(img_y + filter->h))};
	//Keep pixel coordinates in range and ignore degenerate ranges
	x_range[0] = std::max(x_range[0], 0);
	x_range[1] = std::min(x_range[1], static_cast<int>(width) - 1);
	y_range[0] = std::max(y_range[0], 0);
	y_range[1] = std::min(y_range[1], static_cast<int>(height) - 1);
	if (x_range[1] - x_range[0] < 0 || y_range[1] - y_range[0] < 0){
		return;
	}
	//Filter this sample to apply it to the pixels in the image affected by it
	for (int iy = y_range[0]; iy <= y_range[1]; ++iy){
		float fy = std::abs(iy - img_y) * filter->inv_h * FILTER_TABLE_SIZE;
		int fy_idx = std::min(static_cast<int>(fy), FILTER_TABLE_SIZE - 1);
		for (int ix = x_range[0]; ix <= x_range[1]; ++ix){
			//Compute location of this sample in the pre-computed filter values
			float fx = std::abs(ix - img_x) * filter->inv_w * FILTER_TABLE_SIZE;
			int fx_idx = std::min(static_cast<int>(fx), FILTER_TABLE_SIZE - 1);
			float fweight = filter_table[fy_idx * FILTER_TABLE_SIZE + fx_idx];
			Pixel &p = pixels[iy * width + ix];
			atomic_addf(p.r, fweight * c.r);
			atomic_addf(p.g, fweight * c.g);
			atomic_addf(p.b, fweight * c.b);
			atomic_addf(p.weight, fweight);
		}
	}
}
void RenderTarget::write_float(size_t x, size_t y, float d){
	float_buf[y * width + x] = d;
}
bool RenderTarget::save_image(const std::string &file) const {
	//Compute the correct image from the saved pixel data
	std::vector<Color24> img(width * height);
	for (size_t y = 0; y < height; ++y){
		for (size_t x = 0; x < width; ++x){
			const Pixel &p = pixels[y * width + x];
			float weight = p.weight.load(std::memory_order_consume);
			if (weight != 0){
				Colorf c{p.r.load(std::memory_order_consume),
					p.g.load(std::memory_order_consume),
					p.b.load(std::memory_order_consume)};
				c /= weight;
				c.normalize();
				img[y * width + x] = c;
			}
		}
	}
	return save_ppm(file, &img[0].r);
}
bool RenderTarget::save_depth(const std::string &file) const {
	std::vector<uint8_t> depth_norm = generate_depth_img();
	return save_pgm(file, depth_norm.data());
}
bool RenderTarget::save_heat(const std::string &file) const {
	std::vector<Color24> heat_map = generate_heat_img();
	return save_ppm(file, &heat_map[0].r);
}
size_t RenderTarget::get_width() const {
	return width;
}
size_t RenderTarget::get_height() const {
	return height;
}
void RenderTarget::get_colorbuf(std::vector<Color24> &img) const {
	//Compute the correct image from the saved pixel data
	img.resize(width * height);
	for (size_t y = 0; y < height; ++y){
		for (size_t x = 0; x < width; ++x){
			const Pixel &p = pixels[y * width + x];
			float weight = p.weight.load(std::memory_order_consume);
			if (weight != 0){
				Colorf c{p.r.load(std::memory_order_consume),
					p.g.load(std::memory_order_consume),
					p.b.load(std::memory_order_consume)};
				c /= weight;
				c.normalize();
				img[y * width + x] = c;
			}
		}
	}
}
const std::vector<float>& RenderTarget::get_floatbuf() const {
	return float_buf;
}
std::vector<uint8_t> RenderTarget::generate_depth_img() const {
	std::vector<uint8_t> depth_norm(width * height);
	//Determine the min/max range of depth values so we can scale
	//them into 0-255 range
	float zmin = std::numeric_limits<float>::infinity();
	float zmax = std::numeric_limits<float>::min();
	for (const auto &f : float_buf){
		if (f == std::numeric_limits<float>::infinity()){
			continue;
		}
		if (f < zmin){
			zmin = f;
		}
		if (f > zmax){
			zmax = f;
		}
	}
	for (size_t i = 0; i < float_buf.size(); ++i){
		if (float_buf[i] == std::numeric_limits<float>::infinity()){
			depth_norm[i] = 0;
		}
		else {
			depth_norm[i] = static_cast<uint8_t>((zmax - float_buf[i]) / (zmax - zmin) * 255);
			depth_norm[i] = clamp(depth_norm[i], uint8_t{0}, uint8_t{255});
		}
	}
	return depth_norm;
}
std::vector<Color24> RenderTarget::generate_heat_img() const {
	//We use HSV to generate the heat map taking H = 240 as our min value (coolest)
	//and H = 0 as our max (hottest)
	std::vector<Color24> heat_map(width * height);
	float min = std::numeric_limits<float>::infinity();
	float max = std::numeric_limits<float>::min();
	for (const auto &f : float_buf){
		if (f == std::numeric_limits<float>::infinity()){
			continue;
		}
		if (f < min){
			min = f;
		}
		if (f > max){
			max = f;
		}
	}
	for (size_t i = 0; i < float_buf.size(); ++i){
		float hue = 240;
		if (float_buf[i] != std::numeric_limits<float>::infinity()){
			hue = (float_buf[i] - max) / (max - min) * -240.f;
			hue = clamp(hue, 0.f, 240.f);
		}
		hue /= 60;
		float x = 1 - std::abs(static_cast<int>(hue) % 2 - 1);
		if (hue >= 0 && hue < 1){
			heat_map[i] = Colorf{1, x, 0};
		}
		else if (hue < 2){
			heat_map[i] = Colorf{x, 1, 0};
		}
		else if (hue < 3){
			heat_map[i] = Colorf{0, 1, x};
		}
		else if (hue < 4){
			heat_map[i] = Colorf{0, x, 1};
		}
		else if (hue < 5){
			heat_map[i] = Colorf{x, 0, 1};
		}
		else if (hue < 6){
			heat_map[i] = Colorf{1, 0, x};
		}
	}
	return heat_map;
}
bool RenderTarget::save_ppm(const std::string &file, const uint8_t *data) const {
	FILE *fp = fopen(file.c_str(), "wb");
	if (!fp){
		std::cerr << "RenderTarget::save_ppm Error: failed to open file " << file << std::endl;
		return false;
	}
	fprintf(fp, "P6\n%d %d\n255\n", static_cast<int>(width), static_cast<int>(height));
	fwrite(data, 1, 3 * width * height, fp);
	fclose(fp);
	return true;
}
bool RenderTarget::save_pgm(const std::string &file, const uint8_t * data) const {
	FILE *fp = fopen(file.c_str(), "wb");
	if (!fp){
		std::cerr << "RenderTarget::save_pgm Error: failed to open file " << file << std::endl;
		return false;
	}
	fprintf(fp, "P5\n%d %d\n255\n", static_cast<int>(width), static_cast<int>(height));
	fwrite(data, 1, width * height, fp);
	fclose(fp);
	return true;
}

<commit_msg>Just use get_colorbuf to compute the Color24 when writing image<commit_after>#include <array>
#include <atomic>
#include <string>
#include <iostream>
#include <vector>
#include <limits>
#include <memory>
#include <cstdio>
#include "linalg/util.h"
#include "render/render_target.h"

/*
 * Perform an atomic addition to the float via spin-locking
 * on compare_exchange_weak. Memory ordering is release on write
 * consume on read
 */
static float atomic_addf(std::atomic<float> &f, float d){
	float old = f.load(std::memory_order_consume);
	float desired = old + d;
	while (!f.compare_exchange_weak(old, desired,
		std::memory_order_release, std::memory_order_consume))
	{
		desired = old + d;
	}
	return desired;
}

Pixel::Pixel() : r(0), g(0), b(0), weight(0){}
Pixel::Pixel(const Pixel &p) : r(p.r.load(std::memory_order_consume)), g(p.g.load(std::memory_order_consume)),
	b(p.b.load(std::memory_order_consume)), weight(p.weight.load(std::memory_order_consume))
{}

RenderTarget::RenderTarget(size_t width, size_t height, std::unique_ptr<Filter> f)
	: width(width), height(height), filter(std::move(f)), pixels(width * height),
	float_buf(width * height, std::numeric_limits<float>::infinity())
{
	//Pre-compute the filter table values
	for (int y = 0; y < FILTER_TABLE_SIZE; ++y){
		float fy = (y + .5f) * filter->h / FILTER_TABLE_SIZE;
		for (int x = 0; x < FILTER_TABLE_SIZE; ++x){
			float fx = (x + .5f) * filter->w / FILTER_TABLE_SIZE;
			filter_table[y * FILTER_TABLE_SIZE + x] = filter->weight(fx, fy);
		}
	}
}
void RenderTarget::write_pixel(float x, float y, const Colorf &c){
	//Compute the discrete pixel coordinates which the sample hits
	float img_x = x - 0.5f;
	float img_y = y - 0.5f;
	std::array<int, 2> x_range = {static_cast<int>(std::ceil(img_x - filter->w)),
		static_cast<int>(std::floor(img_x + filter->w))};
	std::array<int, 2> y_range = {static_cast<int>(std::ceil(img_y - filter->h)),
		static_cast<int>(std::floor(img_y + filter->h))};
	//Keep pixel coordinates in range and ignore degenerate ranges
	x_range[0] = std::max(x_range[0], 0);
	x_range[1] = std::min(x_range[1], static_cast<int>(width) - 1);
	y_range[0] = std::max(y_range[0], 0);
	y_range[1] = std::min(y_range[1], static_cast<int>(height) - 1);
	if (x_range[1] - x_range[0] < 0 || y_range[1] - y_range[0] < 0){
		return;
	}
	//Filter this sample to apply it to the pixels in the image affected by it
	for (int iy = y_range[0]; iy <= y_range[1]; ++iy){
		float fy = std::abs(iy - img_y) * filter->inv_h * FILTER_TABLE_SIZE;
		int fy_idx = std::min(static_cast<int>(fy), FILTER_TABLE_SIZE - 1);
		for (int ix = x_range[0]; ix <= x_range[1]; ++ix){
			//Compute location of this sample in the pre-computed filter values
			float fx = std::abs(ix - img_x) * filter->inv_w * FILTER_TABLE_SIZE;
			int fx_idx = std::min(static_cast<int>(fx), FILTER_TABLE_SIZE - 1);
			float fweight = filter_table[fy_idx * FILTER_TABLE_SIZE + fx_idx];
			Pixel &p = pixels[iy * width + ix];
			atomic_addf(p.r, fweight * c.r);
			atomic_addf(p.g, fweight * c.g);
			atomic_addf(p.b, fweight * c.b);
			atomic_addf(p.weight, fweight);
		}
	}
}
void RenderTarget::write_float(size_t x, size_t y, float d){
	float_buf[y * width + x] = d;
}
bool RenderTarget::save_image(const std::string &file) const {
	//Compute the correct image from the saved pixel data
	std::vector<Color24> img(width * height);
	get_colorbuf(img);
	return save_ppm(file, &img[0].r);
}
bool RenderTarget::save_depth(const std::string &file) const {
	std::vector<uint8_t> depth_norm = generate_depth_img();
	return save_pgm(file, depth_norm.data());
}
bool RenderTarget::save_heat(const std::string &file) const {
	std::vector<Color24> heat_map = generate_heat_img();
	return save_ppm(file, &heat_map[0].r);
}
size_t RenderTarget::get_width() const {
	return width;
}
size_t RenderTarget::get_height() const {
	return height;
}
void RenderTarget::get_colorbuf(std::vector<Color24> &img) const {
	//Compute the correct image from the saved pixel data
	img.resize(width * height);
	for (size_t y = 0; y < height; ++y){
		for (size_t x = 0; x < width; ++x){
			const Pixel &p = pixels[y * width + x];
			float weight = p.weight.load(std::memory_order_consume);
			if (weight != 0){
				Colorf c{p.r.load(std::memory_order_consume),
					p.g.load(std::memory_order_consume),
					p.b.load(std::memory_order_consume)};
				c /= weight;
				c.normalize();
				img[y * width + x] = c;
			}
		}
	}
}
const std::vector<float>& RenderTarget::get_floatbuf() const {
	return float_buf;
}
std::vector<uint8_t> RenderTarget::generate_depth_img() const {
	std::vector<uint8_t> depth_norm(width * height);
	//Determine the min/max range of depth values so we can scale
	//them into 0-255 range
	float zmin = std::numeric_limits<float>::infinity();
	float zmax = std::numeric_limits<float>::min();
	for (const auto &f : float_buf){
		if (f == std::numeric_limits<float>::infinity()){
			continue;
		}
		if (f < zmin){
			zmin = f;
		}
		if (f > zmax){
			zmax = f;
		}
	}
	for (size_t i = 0; i < float_buf.size(); ++i){
		if (float_buf[i] == std::numeric_limits<float>::infinity()){
			depth_norm[i] = 0;
		}
		else {
			depth_norm[i] = static_cast<uint8_t>((zmax - float_buf[i]) / (zmax - zmin) * 255);
			depth_norm[i] = clamp(depth_norm[i], uint8_t{0}, uint8_t{255});
		}
	}
	return depth_norm;
}
std::vector<Color24> RenderTarget::generate_heat_img() const {
	//We use HSV to generate the heat map taking H = 240 as our min value (coolest)
	//and H = 0 as our max (hottest)
	std::vector<Color24> heat_map(width * height);
	float min = std::numeric_limits<float>::infinity();
	float max = std::numeric_limits<float>::min();
	for (const auto &f : float_buf){
		if (f == std::numeric_limits<float>::infinity()){
			continue;
		}
		if (f < min){
			min = f;
		}
		if (f > max){
			max = f;
		}
	}
	for (size_t i = 0; i < float_buf.size(); ++i){
		float hue = 240;
		if (float_buf[i] != std::numeric_limits<float>::infinity()){
			hue = (float_buf[i] - max) / (max - min) * -240.f;
			hue = clamp(hue, 0.f, 240.f);
		}
		hue /= 60;
		float x = 1 - std::abs(static_cast<int>(hue) % 2 - 1);
		if (hue >= 0 && hue < 1){
			heat_map[i] = Colorf{1, x, 0};
		}
		else if (hue < 2){
			heat_map[i] = Colorf{x, 1, 0};
		}
		else if (hue < 3){
			heat_map[i] = Colorf{0, 1, x};
		}
		else if (hue < 4){
			heat_map[i] = Colorf{0, x, 1};
		}
		else if (hue < 5){
			heat_map[i] = Colorf{x, 0, 1};
		}
		else if (hue < 6){
			heat_map[i] = Colorf{1, 0, x};
		}
	}
	return heat_map;
}
bool RenderTarget::save_ppm(const std::string &file, const uint8_t *data) const {
	FILE *fp = fopen(file.c_str(), "wb");
	if (!fp){
		std::cerr << "RenderTarget::save_ppm Error: failed to open file " << file << std::endl;
		return false;
	}
	fprintf(fp, "P6\n%d %d\n255\n", static_cast<int>(width), static_cast<int>(height));
	fwrite(data, 1, 3 * width * height, fp);
	fclose(fp);
	return true;
}
bool RenderTarget::save_pgm(const std::string &file, const uint8_t * data) const {
	FILE *fp = fopen(file.c_str(), "wb");
	if (!fp){
		std::cerr << "RenderTarget::save_pgm Error: failed to open file " << file << std::endl;
		return false;
	}
	fprintf(fp, "P5\n%d %d\n255\n", static_cast<int>(width), static_cast<int>(height));
	fwrite(data, 1, width * height, fp);
	fclose(fp);
	return true;
}

<|endoftext|>


<commit_before>/*****************************************************************************************
 *                                                                                *
 * OpenSpace                                                                             *
 *                                                                                *
 * Copyright (c) 2014-2020                                                               *
 *                                                                                *
 * 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.                                         *
 ****************************************************************************************/

#include <openspace/rendering/renderable.h>

#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/util/factorymanager.h>
#include <openspace/util/updatestructures.h>
#include <ghoul/misc/profiling.h>
#include <ghoul/opengl/programobject.h>

namespace {
    constexpr const char* KeyType = "Type";
    constexpr const char* KeyTag = "Tag";

    constexpr openspace::properties::Property::PropertyInfo EnabledInfo = {
        "Enabled",
        "Is Enabled",
        "This setting determines whether this object will be visible or not."
    };

    constexpr openspace::properties::Property::PropertyInfo OpacityInfo = {
        "Opacity",
        "Transparency",
        "This value determines the transparency of this object."
    };

    constexpr openspace::properties::Property::PropertyInfo RenderableTypeInfo = {
        "Type",
        "Renderable Type",
        "This tells the type of the renderable.",
        openspace::properties::Property::Visibility::Hidden
    };

    constexpr openspace::properties::Property::PropertyInfo BoundingSphereInfo = {
        "BoundingSphere",
        "Bounding Sphere",
        "The size of the bounding sphere radius."
    };

} // namespace

namespace openspace {

documentation::Documentation Renderable::Documentation() {
    using namespace openspace::documentation;

    return {
        "Renderable",
        "renderable",
        {
            {
                KeyType,
                new StringAnnotationVerifier("A valid Renderable created by a factory"),
                Optional::No,
                "This key specifies the type of Renderable that gets created. It has to "
                "be one of the valid Renderables that are available for creation (see "
                "the FactoryDocumentation for a list of possible Renderables), which "
                "depends on the configration of the application"
            },
            {
                EnabledInfo.identifier,
                new BoolVerifier,
                Optional::Yes,
                EnabledInfo.description
            },
            {
                OpacityInfo.identifier,
                new DoubleInRangeVerifier(0.0, 1.0),
                Optional::Yes,
                OpacityInfo.description
            }
        }
    };
}

std::unique_ptr<Renderable> Renderable::createFromDictionary(
                                                      const ghoul::Dictionary& dictionary)
{
    documentation::testSpecificationAndThrow(Documentation(), dictionary, "Renderable");

    std::string renderableType = dictionary.value<std::string>(KeyType);

    auto factory = FactoryManager::ref().factory<Renderable>();
    ghoul_assert(factory, "Renderable factory did not exist");
    std::unique_ptr<Renderable> result = factory->create(renderableType, dictionary);
    return result;
}

Renderable::Renderable(const ghoul::Dictionary& dictionary)
    : properties::PropertyOwner({ "Renderable" })
    , _enabled(EnabledInfo, true)
    , _opacity(OpacityInfo, 1.f, 0.f, 1.f)
    , _boundingSphere(BoundingSphereInfo, 0.f, 0.f, 3e10f)
    , _renderableType(RenderableTypeInfo, "Renderable")
{
    ZoneScoped

    // I can't come up with a good reason not to do this for all renderables
    registerUpdateRenderBinFromOpacity();

    if (dictionary.hasKeyAndValue<std::string>(KeyTag)) {
        std::string tagName = dictionary.value<std::string>(KeyTag);
        if (!tagName.empty()) {
            addTag(std::move(tagName));
        }
    }
    else if (dictionary.hasKeyAndValue<ghoul::Dictionary>(KeyTag)) {
        const ghoul::Dictionary& tagNames = dictionary.value<ghoul::Dictionary>(KeyTag);
        const std::vector<std::string>& keys = tagNames.keys();
        for (const std::string& key : keys) {
            std::string tagName = tagNames.value<std::string>(key);
            if (!tagName.empty()) {
                addTag(std::move(tagName));
            }
        }
    }

    if (dictionary.hasKey(EnabledInfo.identifier)) {
        _enabled = dictionary.value<bool>(EnabledInfo.identifier);
    }

    if (dictionary.hasKey(OpacityInfo.identifier)) {
        _opacity = static_cast<float>(dictionary.value<double>(
            OpacityInfo.identifier)
       );
    }

    addProperty(_enabled);

    //set type for UI
    if (dictionary.hasKey(RenderableTypeInfo.identifier)) {
        _renderableType = dictionary.value<std::string>(
            RenderableTypeInfo.identifier
       );
    }

    if (dictionary.hasKey(BoundingSphereInfo.identifier)) {
        _boundingSphere = static_cast<float>(
            dictionary.value<double>(BoundingSphereInfo.identifier)
       );
    }

    addProperty(_renderableType);
    addProperty(_boundingSphere);
}

void Renderable::initialize() {}

void Renderable::initializeGL() {}

void Renderable::deinitialize() {}

void Renderable::deinitializeGL() {}

void Renderable::update(const UpdateData&) {}

void Renderable::render(const RenderData&, RendererTasks&) {}

void Renderable::setBoundingSphere(float boundingSphere) {
    _boundingSphere = boundingSphere;
}

float Renderable::boundingSphere() const {
    return _boundingSphere;
}

SurfacePositionHandle Renderable::calculateSurfacePositionHandle(
                                                 const glm::dvec3& targetModelSpace) const
{
    const glm::dvec3 directionFromCenterToTarget = glm::normalize(targetModelSpace);
    return {
        directionFromCenterToTarget * static_cast<double>(boundingSphere()),
        directionFromCenterToTarget,
        0.0
    };
}

bool Renderable::renderedWithDesiredData() const {
    return true;
}

Renderable::RenderBin Renderable::renderBin() const {
    return _renderBin;
}

void Renderable::setRenderBin(RenderBin bin) {
    _renderBin = bin;
}

bool Renderable::matchesRenderBinMask(int binMask) {
    return binMask & static_cast<int>(renderBin());
}

bool Renderable::isVisible() const {
    return _enabled;
}

bool Renderable::isReady() const {
    return true;
}

bool Renderable::isEnabled() const {
    return _enabled;
}

void Renderable::onEnabledChange(std::function<void(bool)> callback) {
    _enabled.onChange([this, c = std::move(callback)]() {
        c(isEnabled());
    });
}

void Renderable::setRenderBinFromOpacity() {
    if (_renderBin != Renderable::RenderBin::PostDeferredTransparent) {
        if (_opacity >= 0.f && _opacity < 1.f) {
            setRenderBin(Renderable::RenderBin::PreDeferredTransparent);
        }
        else {
            setRenderBin(Renderable::RenderBin::Opaque);
        }
    }
}

void Renderable::registerUpdateRenderBinFromOpacity() {
    _opacity.onChange([this](){
        if (_renderBin != Renderable::RenderBin::PostDeferredTransparent) {
            if (_opacity >= 0.f && _opacity < 1.f) {
                setRenderBin(Renderable::RenderBin::PreDeferredTransparent);
            }
            else {
                setRenderBin(Renderable::RenderBin::Opaque);
            }
        }
    });
}

}  // namespace openspace
<commit_msg>Update opacity property description in renderable base class<commit_after>/*****************************************************************************************
 *                                                                                *
 * OpenSpace                                                                             *
 *                                                                                *
 * Copyright (c) 2014-2020                                                               *
 *                                                                                *
 * 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.                                         *
 ****************************************************************************************/

#include <openspace/rendering/renderable.h>

#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/util/factorymanager.h>
#include <openspace/util/updatestructures.h>
#include <ghoul/misc/profiling.h>
#include <ghoul/opengl/programobject.h>

namespace {
    constexpr const char* KeyType = "Type";
    constexpr const char* KeyTag = "Tag";

    constexpr openspace::properties::Property::PropertyInfo EnabledInfo = {
        "Enabled",
        "Is Enabled",
        "This setting determines whether this object will be visible or not."
    };

    constexpr openspace::properties::Property::PropertyInfo OpacityInfo = {
        "Opacity",
        "Opacity",
        "This value determines the opacity of this renderable. A value of 0 means "
        "completely transparent."
    };

    constexpr openspace::properties::Property::PropertyInfo RenderableTypeInfo = {
        "Type",
        "Renderable Type",
        "This tells the type of the renderable.",
        openspace::properties::Property::Visibility::Hidden
    };

    constexpr openspace::properties::Property::PropertyInfo BoundingSphereInfo = {
        "BoundingSphere",
        "Bounding Sphere",
        "The size of the bounding sphere radius."
    };

} // namespace

namespace openspace {

documentation::Documentation Renderable::Documentation() {
    using namespace openspace::documentation;

    return {
        "Renderable",
        "renderable",
        {
            {
                KeyType,
                new StringAnnotationVerifier("A valid Renderable created by a factory"),
                Optional::No,
                "This key specifies the type of Renderable that gets created. It has to "
                "be one of the valid Renderables that are available for creation (see "
                "the FactoryDocumentation for a list of possible Renderables), which "
                "depends on the configration of the application"
            },
            {
                EnabledInfo.identifier,
                new BoolVerifier,
                Optional::Yes,
                EnabledInfo.description
            },
            {
                OpacityInfo.identifier,
                new DoubleInRangeVerifier(0.0, 1.0),
                Optional::Yes,
                OpacityInfo.description
            }
        }
    };
}

std::unique_ptr<Renderable> Renderable::createFromDictionary(
                                                      const ghoul::Dictionary& dictionary)
{
    documentation::testSpecificationAndThrow(Documentation(), dictionary, "Renderable");

    std::string renderableType = dictionary.value<std::string>(KeyType);

    auto factory = FactoryManager::ref().factory<Renderable>();
    ghoul_assert(factory, "Renderable factory did not exist");
    std::unique_ptr<Renderable> result = factory->create(renderableType, dictionary);
    return result;
}

Renderable::Renderable(const ghoul::Dictionary& dictionary)
    : properties::PropertyOwner({ "Renderable" })
    , _enabled(EnabledInfo, true)
    , _opacity(OpacityInfo, 1.f, 0.f, 1.f)
    , _boundingSphere(BoundingSphereInfo, 0.f, 0.f, 3e10f)
    , _renderableType(RenderableTypeInfo, "Renderable")
{
    ZoneScoped

    // I can't come up with a good reason not to do this for all renderables
    registerUpdateRenderBinFromOpacity();

    if (dictionary.hasKeyAndValue<std::string>(KeyTag)) {
        std::string tagName = dictionary.value<std::string>(KeyTag);
        if (!tagName.empty()) {
            addTag(std::move(tagName));
        }
    }
    else if (dictionary.hasKeyAndValue<ghoul::Dictionary>(KeyTag)) {
        const ghoul::Dictionary& tagNames = dictionary.value<ghoul::Dictionary>(KeyTag);
        const std::vector<std::string>& keys = tagNames.keys();
        for (const std::string& key : keys) {
            std::string tagName = tagNames.value<std::string>(key);
            if (!tagName.empty()) {
                addTag(std::move(tagName));
            }
        }
    }

    if (dictionary.hasKey(EnabledInfo.identifier)) {
        _enabled = dictionary.value<bool>(EnabledInfo.identifier);
    }

    if (dictionary.hasKey(OpacityInfo.identifier)) {
        _opacity = static_cast<float>(dictionary.value<double>(
            OpacityInfo.identifier)
       );
    }

    addProperty(_enabled);

    //set type for UI
    if (dictionary.hasKey(RenderableTypeInfo.identifier)) {
        _renderableType = dictionary.value<std::string>(
            RenderableTypeInfo.identifier
       );
    }

    if (dictionary.hasKey(BoundingSphereInfo.identifier)) {
        _boundingSphere = static_cast<float>(
            dictionary.value<double>(BoundingSphereInfo.identifier)
       );
    }

    addProperty(_renderableType);
    addProperty(_boundingSphere);
}

void Renderable::initialize() {}

void Renderable::initializeGL() {}

void Renderable::deinitialize() {}

void Renderable::deinitializeGL() {}

void Renderable::update(const UpdateData&) {}

void Renderable::render(const RenderData&, RendererTasks&) {}

void Renderable::setBoundingSphere(float boundingSphere) {
    _boundingSphere = boundingSphere;
}

float Renderable::boundingSphere() const {
    return _boundingSphere;
}

SurfacePositionHandle Renderable::calculateSurfacePositionHandle(
                                                 const glm::dvec3& targetModelSpace) const
{
    const glm::dvec3 directionFromCenterToTarget = glm::normalize(targetModelSpace);
    return {
        directionFromCenterToTarget * static_cast<double>(boundingSphere()),
        directionFromCenterToTarget,
        0.0
    };
}

bool Renderable::renderedWithDesiredData() const {
    return true;
}

Renderable::RenderBin Renderable::renderBin() const {
    return _renderBin;
}

void Renderable::setRenderBin(RenderBin bin) {
    _renderBin = bin;
}

bool Renderable::matchesRenderBinMask(int binMask) {
    return binMask & static_cast<int>(renderBin());
}

bool Renderable::isVisible() const {
    return _enabled;
}

bool Renderable::isReady() const {
    return true;
}

bool Renderable::isEnabled() const {
    return _enabled;
}

void Renderable::onEnabledChange(std::function<void(bool)> callback) {
    _enabled.onChange([this, c = std::move(callback)]() {
        c(isEnabled());
    });
}

void Renderable::setRenderBinFromOpacity() {
    if (_renderBin != Renderable::RenderBin::PostDeferredTransparent) {
        if (_opacity >= 0.f && _opacity < 1.f) {
            setRenderBin(Renderable::RenderBin::PreDeferredTransparent);
        }
        else {
            setRenderBin(Renderable::RenderBin::Opaque);
        }
    }
}

void Renderable::registerUpdateRenderBinFromOpacity() {
    _opacity.onChange([this](){
        if (_renderBin != Renderable::RenderBin::PostDeferredTransparent) {
            if (_opacity >= 0.f && _opacity < 1.f) {
                setRenderBin(Renderable::RenderBin::PreDeferredTransparent);
            }
            else {
                setRenderBin(Renderable::RenderBin::Opaque);
            }
        }
    });
}

}  // namespace openspace
<|endoftext|>


<commit_before>#include "list.h"
#include "list.cpp"
#include "queue.h"
#include "queue.cpp"
#include <iostream>
#include <cassert>
#include <exception>
#include <cstdlib>
using namespace std;

//---------------------------------------------------------------------------
// driver to test list
//---------------------------------------------------------------------------
int main(void)
{
	using NP_ADT::CDLL; // not the same as std::list<class T>
	using NP_ADT::Queue;
	try
	{
		CDLL<char> mylist(3, 'X');
		CDLL<char> mylist2;
		CDLL<char> mylist3(mylist);
		CDLL<char> mylist4(mylist.begin(), mylist.end());
		cout << "mylist: " << mylist << endl;
		cout << "mylist2: " << mylist2 << endl;
		cout << "mylist3: " << mylist3 << endl;
		cout << "mylist4: " << mylist4 << endl;
		mylist.push_front('Y');
		mylist.push_front('Z');
		cout << mylist.pop_front() << endl;
		mylist2 = mylist; // a copy
		cout << "mylist: " << mylist << endl;
		// create a new iterator pointing to the beginning of mylist
		CDLL<char>::iterator listit(mylist.begin());
		cout << listit++->data << " ";
		cout << listit->data << endl;
		cout << "mylist: ";
		for (unsigned int i = 0; i < mylist.getSize(); i++)
			cout << mylist[i] << " ";
		cout << endl;
		cout << "mylist[1] = 'N';" << endl;
		mylist[1] = 'N';
		cout << "mylist: " << mylist << endl;
		mylist.release();
		cout << "mylist: " << mylist << endl;
		cout << "mylist2: " << mylist2 << endl;

		// Queue Pointer Tests

		myqueue = &Queue<char>(3, 'X');
		CDLL<char> mylist2;
		CDLL<char> mylist3(mylist);
		CDLL<char> mylist4(mylist.begin(), mylist.end());
		cout << "mylist: " << mylist << endl;
		cout << "mylist2: " << mylist2 << endl;
		cout << "mylist3: " << mylist3 << endl;
		cout << "mylist4: " << mylist4 << endl;
		mylist.push_front('Y');
		mylist.push_front('Z');
		cout << mylist.pop_front() << endl;
		mylist2 = mylist; // a copy
		cout << "mylist: " << mylist << endl;
		// create a new iterator pointing to the beginning of mylist
		CDLL<char>::iterator listit(mylist.begin());
		cout << listit++->data << " ";
		cout << listit->data << endl;
		cout << "mylist: ";
		for (unsigned int i = 0; i < mylist.getSize(); i++)
			cout << mylist[i] << " ";
		cout << endl;
		cout << "mylist[1] = 'N';" << endl;
		mylist[1] = 'N';
		cout << "mylist: " << mylist << endl;
		mylist.release();
		cout << "mylist: " << mylist << endl;
		cout << "mylist2: " << mylist2 << endl;
	}
	catch (exception e)
	{
		cerr << "program terminated: " << e.what() << endl;
		cin.get();
		return EXIT_FAILURE;
	}
	cin.get();  // keep window open
	return EXIT_SUCCESS;
}<commit_msg>comment out buggy code<commit_after>#include "list.h"
#include "list.cpp"
#include "queue.h"
#include "queue.cpp"
#include <iostream>
#include <cassert>
#include <exception>
#include <cstdlib>
using namespace std;

//---------------------------------------------------------------------------
// driver to test list
//---------------------------------------------------------------------------
int main(void)
{
	using NP_ADT::CDLL; // not the same as std::list<class T>
	using NP_ADT::Queue;
	try
	{
		CDLL<char> mylist(3, 'X');
		CDLL<char> mylist2;
		CDLL<char> mylist3(mylist);
		CDLL<char> mylist4(mylist.begin(), mylist.end());
		cout << "mylist: " << mylist << endl;
		cout << "mylist2: " << mylist2 << endl;
		cout << "mylist3: " << mylist3 << endl;
		cout << "mylist4: " << mylist4 << endl;
		mylist.push_front('Y');
		mylist.push_front('Z');
		cout << mylist.pop_front() << endl;
		mylist2 = mylist; // a copy
		cout << "mylist: " << mylist << endl;
		// create a new iterator pointing to the beginning of mylist
		CDLL<char>::iterator listit(mylist.begin());
		cout << listit++->data << " ";
		cout << listit->data << endl;
		cout << "mylist: ";
		for (unsigned int i = 0; i < mylist.getSize(); i++)
			cout << mylist[i] << " ";
		cout << endl;
		cout << "mylist[1] = 'N';" << endl;
		mylist[1] = 'N';
		cout << "mylist: " << mylist << endl;
		mylist.release();
		cout << "mylist: " << mylist << endl;
		cout << "mylist2: " << mylist2 << endl;

		// Queue Pointer Tests
		/*
		myqueue = &Queue<char>(3, 'X');
		CDLL<char> mylist2;
		CDLL<char> mylist3(mylist);
		CDLL<char> mylist4(mylist.begin(), mylist.end());
		cout << "mylist: " << mylist << endl;
		cout << "mylist2: " << mylist2 << endl;
		cout << "mylist3: " << mylist3 << endl;
		cout << "mylist4: " << mylist4 << endl;
		mylist.push_front('Y');
		mylist.push_front('Z');
		cout << mylist.pop_front() << endl;
		mylist2 = mylist; // a copy
		cout << "mylist: " << mylist << endl;
		// create a new iterator pointing to the beginning of mylist
		CDLL<char>::iterator listit(mylist.begin());
		cout << listit++->data << " ";
		cout << listit->data << endl;
		cout << "mylist: ";
		for (unsigned int i = 0; i < mylist.getSize(); i++)
			cout << mylist[i] << " ";
		cout << endl;
		cout << "mylist[1] = 'N';" << endl;
		mylist[1] = 'N';
		cout << "mylist: " << mylist << endl;
		mylist.release();
		cout << "mylist: " << mylist << endl;
		cout << "mylist2: " << mylist2 << endl;
		*/
	}
	catch (exception e)
	{
		cerr << "program terminated: " << e.what() << endl;
		cin.get();
		return EXIT_FAILURE;
	}
	cin.get();  // keep window open
	return EXIT_SUCCESS;
}<|endoftext|>


<commit_before>/*
TidyEngine
Copyright (C) 2016 Jakob Sinclair

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
Contact the author at: jakob.sinclair99@gmail.com
*/

#include "spriterenderer.hpp"
#include "shader.hpp"
#include "batch.hpp"
#include "camera.hpp"

SpriteRenderer::SpriteRenderer()
{
	;
}

SpriteRenderer::~SpriteRenderer()
{
	if (m_VAOID != 0)
		glDeleteVertexArrays(1, &m_VAOID);
	if (m_VBOID != 0)
		glDeleteBuffers(1, &m_VBOID);
}

void SpriteRenderer::Initialise(Shader *shader, Batch *batch)
{
	m_Shader = shader;
	m_Batch = batch;

	if (m_VAOID != 0)
		glDeleteVertexArrays(1, &m_VAOID);
	if (m_VBOID != 0)
		glDeleteBuffers(1, &m_VBOID);

	glGenVertexArrays(1, &m_VAOID);
	glBindVertexArray(m_VAOID);

	glGenBuffers(1, &m_VBOID);
	glBindBuffer(GL_ARRAY_BUFFER, m_VBOID);
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * 6000000, NULL, GL_DYNAMIC_DRAW);

	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);
	glEnableVertexAttribArray(2);

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
			(void*)offsetof(Vertex, Position));
	glVertexAttribPointer(1, 4, GL_FLOAT, GL_TRUE, sizeof(Vertex),
			(void*)offsetof(Vertex, Color));
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
			(void*)offsetof(Vertex, TexUV));

	glBindVertexArray(0);
}

void SpriteRenderer::Draw(Renderable *object)
{
	/* Updates the object to prepare for rendering */
	object->Render();
	m_Batch->Draw(object);
}

void SpriteRenderer::Present(const Camera *camera)
{
	if (camera != nullptr) {
		m_Shader->SetUniformMat4("projection", camera->GetProj());
		m_Shader->SetUniformMat4("view", camera->GetView());
		m_Shader->SetUniformMat4("model", camera->GetModel());
	}
	m_Batch->Present();
}<commit_msg>libTidyEngine: cleaned up optimasation test<commit_after>/*
TidyEngine
Copyright (C) 2016 Jakob Sinclair

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
Contact the author at: jakob.sinclair99@gmail.com
*/
#define SPRITE_COUNT 1000000
#include "spriterenderer.hpp"
#include "shader.hpp"
#include "batch.hpp"
#include "camera.hpp"

SpriteRenderer::SpriteRenderer()
{
	;
}

SpriteRenderer::~SpriteRenderer()
{
	if (m_VAOID != 0)
		glDeleteVertexArrays(1, &m_VAOID);
	if (m_VBOID != 0)
		glDeleteBuffers(1, &m_VBOID);
}

void SpriteRenderer::Initialise(Shader *shader, Batch *batch)
{
	m_Shader = shader;
	m_Batch = batch;

	if (m_VAOID != 0)
		glDeleteVertexArrays(1, &m_VAOID);
	if (m_VBOID != 0)
		glDeleteBuffers(1, &m_VBOID);

	glGenVertexArrays(1, &m_VAOID);
	glBindVertexArray(m_VAOID);

	glGenBuffers(1, &m_VBOID);
	glBindBuffer(GL_ARRAY_BUFFER, m_VBOID);
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * SPRITE_COUNT * 6, NULL, GL_STREAM_DRAW);

	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);
	glEnableVertexAttribArray(2);

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
			(void*)offsetof(Vertex, Position));
	glVertexAttribPointer(1, 4, GL_FLOAT, GL_TRUE, sizeof(Vertex),
			(void*)offsetof(Vertex, Color));
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
			(void*)offsetof(Vertex, TexUV));

	glBindVertexArray(0);
}

void SpriteRenderer::Draw(Renderable *object)
{
	/* Updates the object to prepare for rendering */
	object->Render();
	m_Batch->Draw(object);
}

void SpriteRenderer::Present(const Camera *camera)
{
	if (camera != nullptr) {
		m_Shader->SetUniformMat4("projection", camera->GetProj());
		m_Shader->SetUniformMat4("view", camera->GetView());
		m_Shader->SetUniformMat4("model", camera->GetModel());
	}
	m_Batch->Present();
}<|endoftext|>


<commit_before>/**
 * @file	src/core/ParameterizedWithSetters.cpp
 * @date	Aug. 2016
 * @author	PhRG - opticalp.fr
 */

/*
 Copyright (c) 2016 Ph. Renaud-Goud / Opticalp

 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.
 */

#include "ParameterizedWithSetters.h"

#include "ParameterizedEntityWithWorkers.h"
#include "ExecutionAbortedException.h"

using Poco::AutoPtr;

ParameterizedWithSetters::~ParameterizedWithSetters()
{
	while (setters.size())
	{
		const_cast<ParameterSetter*>(setters.begin()->get())->invalidate();
		setters.erase(setters.begin());
	}
}

AutoPtr<ParameterSetter> ParameterizedWithSetters::buildParameterSetter(
		size_t paramIndex, bool immediateApply)
{
	for (std::set< Poco::AutoPtr<ParameterSetter> >::iterator it = setters.begin(),
			ite = setters.end(); it != ite; it++)
	{
		if (it->get()->getParameterIndex() == paramIndex)
			const_cast<ParameterSetter*>(it->get())->invalidate();
	}

	AutoPtr<ParameterSetter> ptr(new ParameterSetter(self, paramIndex, this, immediateApply));
	setters.insert(ptr);
	return ptr;
}

Poco::AutoPtr<ParameterSetter> ParameterizedWithSetters::buildParameterSetter(
		std::string paramName)
{
	return buildParameterSetter(self->getParameterIndex(paramName));
}

Poco::AutoPtr<ParameterSetter> ParameterizedWithSetters::buildParameterSetter(
		std::string paramName, bool imm)
{
	return buildParameterSetter(self->getParameterIndex(paramName), imm);
}

bool ParameterizedWithSetters::trySetParameter(size_t paramIndex)
{
    alreadySetLock.lock();

    if (paramAlreadySet.count(paramIndex) == 0)
        return true;
    else
    {
        alreadySetLock.unlock();
        return false;
    }
}

void ParameterizedWithSetters::trigSetParameter(size_t paramIndex)
{

    if (paramAlreadySet.insert(paramIndex).second)
    {
        if (paramAlreadySet.size() == setters.size())
        {
            if (preApply)
                self->tryApplyParameters(true);

            allSet.set();
        }

        alreadySetLock.unlock();
    }
    else
    {
        poco_bugcheck_msg("trying to trig a parameter that was not previously locked");
    }
}

bool ParameterizedWithSetters::tryAllParametersSet()
{
	if (setters.size())
	{
		if (allSet.tryWait(0))
		    return true;
		else
		{
		    for (std::set< Poco::AutoPtr<ParameterSetter> >::iterator it = setters.begin(),
		            ite = setters.end(); it != ite; it++)
		    {
		        alreadySetLock.lock();
		        bool alreadySet = paramAlreadySet.count(const_cast<ParameterSetter*>(it->get())->getParameterIndex()) > 0 ;
		        alreadySetLock.unlock();

		        if ( !alreadySet &&  (it->get())->isTargetCancelling() )
		            throw ExecutionAbortedException("Apply parameters: "
		                    "Cancellation upon user request (setter)");
		    }

		    return false;
		}
	}
	else
		return true;
}

void ParameterizedWithSetters::parametersTreated()
{
	Poco::ScopedLock<Poco::FastMutex> lock(alreadySetLock);
	paramAlreadySet.clear();

	// allSet event should be already reset (auto-reset).
}
<commit_msg>Avoid possible deadlock<commit_after>/**
 * @file	src/core/ParameterizedWithSetters.cpp
 * @date	Aug. 2016
 * @author	PhRG - opticalp.fr
 */

/*
 Copyright (c) 2016 Ph. Renaud-Goud / Opticalp

 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.
 */

#include "ParameterizedWithSetters.h"

#include "ParameterizedEntityWithWorkers.h"
#include "ExecutionAbortedException.h"

using Poco::AutoPtr;

ParameterizedWithSetters::~ParameterizedWithSetters()
{
	while (setters.size())
	{
		const_cast<ParameterSetter*>(setters.begin()->get())->invalidate();
		setters.erase(setters.begin());
	}
}

AutoPtr<ParameterSetter> ParameterizedWithSetters::buildParameterSetter(
		size_t paramIndex, bool immediateApply)
{
	for (std::set< Poco::AutoPtr<ParameterSetter> >::iterator it = setters.begin(),
			ite = setters.end(); it != ite; it++)
	{
		if (it->get()->getParameterIndex() == paramIndex)
			const_cast<ParameterSetter*>(it->get())->invalidate();
	}

	AutoPtr<ParameterSetter> ptr(new ParameterSetter(self, paramIndex, this, immediateApply));
	setters.insert(ptr);
	return ptr;
}

Poco::AutoPtr<ParameterSetter> ParameterizedWithSetters::buildParameterSetter(
		std::string paramName)
{
	return buildParameterSetter(self->getParameterIndex(paramName));
}

Poco::AutoPtr<ParameterSetter> ParameterizedWithSetters::buildParameterSetter(
		std::string paramName, bool imm)
{
	return buildParameterSetter(self->getParameterIndex(paramName), imm);
}

bool ParameterizedWithSetters::trySetParameter(size_t paramIndex)
{
    alreadySetLock.lock();

    if (paramAlreadySet.count(paramIndex) == 0)
        return true;
    else
    {
        alreadySetLock.unlock();
        return false;
    }
}

void ParameterizedWithSetters::trigSetParameter(size_t paramIndex)
{

    if (paramAlreadySet.insert(paramIndex).second)
    {
        bool done = (paramAlreadySet.size() == setters.size());

        alreadySetLock.unlock();
        if (done)
        {
            if (preApply)
                self->tryApplyParameters(true);

            allSet.set();
        }
    }
    else
    {
        poco_bugcheck_msg("trying to trig a parameter that was not previously locked");
    }
}

bool ParameterizedWithSetters::tryAllParametersSet()
{
	if (setters.size())
	{
		if (allSet.tryWait(0))
		    return true;
		else
		{
		    for (std::set< Poco::AutoPtr<ParameterSetter> >::iterator it = setters.begin(),
		            ite = setters.end(); it != ite; it++)
		    {
		        alreadySetLock.lock();
		        bool alreadySet = paramAlreadySet.count(const_cast<ParameterSetter*>(it->get())->getParameterIndex()) > 0 ;
		        alreadySetLock.unlock();

		        if ( !alreadySet &&  (it->get())->isTargetCancelling() )
		            throw ExecutionAbortedException("Apply parameters: "
		                    "Cancellation upon user request (setter)");
		    }

		    return false;
		}
	}
	else
		return true;
}

void ParameterizedWithSetters::parametersTreated()
{
	Poco::ScopedLock<Poco::FastMutex> lock(alreadySetLock);
	paramAlreadySet.clear();

	// allSet event should be already reset (auto-reset).
}
<|endoftext|>


<commit_before>#include "i_core.h"

TargetPlayerController::TargetPlayerController(Actor* player):Controller()
	,mCounter(2)
	,mHeadingModifier(0)
	,mPlayer(player)
{

}

void TargetPlayerController::SetActor(Actor* Obj)
{
	Controller::SetActor(Obj);
	if(!mActor)return;
	mActor->SetHeading(0);
	mActor->SetSpeed(0.1);
	Action const* Act=ActionHolder::Get().GetAction("move");
	if(Act) Act->Activate(*mActor);
}

void TargetPlayerController::Update( double Seconds )
{
	if(!mActor)return;
	if(!mPlayer)return;
	mCounter+=Seconds;
	mCounter=0;
	double Rot=atan2(mPlayer->GetY()-mActor->GetY(),mPlayer->GetX()-mActor->GetX());
	double Radians=Rot-mActor->GetHeading();
	static const double pi=boost::math::constants::pi<double>();
    while (Radians < -pi)
    {
        Radians += pi*2;
    }
    while (Radians > pi)
    {
        Radians -= pi*2;
    }
	double RotSpd=(Radians>0?1:-1)*0.01;
	mActor->SetHeading(mActor->GetHeading()+RotSpd);
	mActor->SetOrientation(mActor->GetHeading());
}
<commit_msg>Whitespace fix<commit_after>#include "i_core.h"

TargetPlayerController::TargetPlayerController(Actor* player):Controller()
	,mCounter(2)
	,mHeadingModifier(0)
	,mPlayer(player)
{

}

void TargetPlayerController::SetActor(Actor* Obj)
{
	Controller::SetActor(Obj);
	if(!mActor)return;
	mActor->SetHeading(0);
	mActor->SetSpeed(0.1);
	Action const* Act=ActionHolder::Get().GetAction("move");
	if(Act) Act->Activate(*mActor);
}

void TargetPlayerController::Update( double Seconds )
{
	if(!mActor)return;
	if(!mPlayer)return;
	mCounter+=Seconds;
	mCounter=0;
	double Rot=atan2(mPlayer->GetY()-mActor->GetY(),mPlayer->GetX()-mActor->GetX());
	double Radians=Rot-mActor->GetHeading();
	static const double pi=boost::math::constants::pi<double>();
	while (Radians < -pi)
	{
		Radians += pi*2;
	}
	while (Radians > pi)
	{
		Radians -= pi*2;
	}
	double RotSpd=(Radians>0?1:-1)*0.01;
	mActor->SetHeading(mActor->GetHeading()+RotSpd);
	mActor->SetOrientation(mActor->GetHeading());
}
<|endoftext|>