<commit_before>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Achim Brandt
////////////////////////////////////////////////////////////////////////////////

#ifdef _WIN32
#include "Basics/win-utils.h"
#endif

#include "Scheduler.h"

#include <velocypack/Builder.h>
#include <velocypack/velocypack-aliases.h>

#include "Basics/MutexLocker.h"
#include "Basics/StringUtils.h"
#include "Basics/Thread.h"
#include "Logger/Logger.h"
#include "Rest/GeneralResponse.h"
#include "Scheduler/JobQueue.h"
#include "Scheduler/Task.h"

using namespace arangodb;
using namespace arangodb::basics;
using namespace arangodb::rest;

// -----------------------------------------------------------------------------
// --SECTION--                                            SchedulerManagerThread
// -----------------------------------------------------------------------------

namespace {
class SchedulerManagerThread : public Thread {
 public:
  SchedulerManagerThread(Scheduler* scheduler, boost::asio::io_service* service)
      : Thread("SchedulerManager"), _scheduler(scheduler), _service(service) {}

  ~SchedulerManagerThread() { shutdown(); }

 public:
  void run() {
    while (!_scheduler->isStopping()) {
      try {
        _service->run_one();
        _scheduler->deleteOldThreads();
      } catch (...) {
        LOG_TOPIC(ERR, Logger::THREADS)
            << "manager loop caught an error, restarting";
      }
    }

    _scheduler->threadDone(this);
  }

 private:
  Scheduler* _scheduler;
  boost::asio::io_service* _service;
};
}

// -----------------------------------------------------------------------------
// --SECTION--                                                   SchedulerThread
// -----------------------------------------------------------------------------

namespace {
class SchedulerThread : public Thread {
 public:
  SchedulerThread(Scheduler* scheduler, boost::asio::io_service* service)
      : Thread("Scheduler"), _scheduler(scheduler), _service(service) {}

  ~SchedulerThread() { shutdown(); }

 public:
  void run() {
    _scheduler->incRunning();
    LOG_TOPIC(DEBUG, Logger::THREADS) << "running (" << _scheduler->infoStatus()
                                      << ")";

    auto start = std::chrono::steady_clock::now();

    try {
      static size_t EVERY_LOOP = 1000;
      static double MIN_SECONDS = 30;

      size_t counter = 0;
      while (!_scheduler->isStopping()) {
        _service->run_one();

        if (++counter > EVERY_LOOP) {
          auto now = std::chrono::steady_clock::now();
          std::chrono::duration<double> diff = now - start;

          if (diff.count() > MIN_SECONDS) {
            if (_scheduler->stopThread()) {
              auto n = _scheduler->decRunning();

              if (n <= 2) {
                _scheduler->incRunning();
              } else {
                break;
              }
            }

            start = std::chrono::steady_clock::now();
          }
        }
      }

      LOG_TOPIC(DEBUG, Logger::THREADS) << "stopped ("
                                        << _scheduler->infoStatus() << ")";
    } catch (...) {
      LOG_TOPIC(ERR, Logger::THREADS)
          << "scheduler loop caught an error, restarting";
      _scheduler->decRunning();
      _scheduler->startNewThread();
    }

    _scheduler->threadDone(this);
  }

 private:
  Scheduler* _scheduler;
  boost::asio::io_service* _service;
};
}

// -----------------------------------------------------------------------------
// --SECTION--                                                         Scheduler
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// --SECTION--                                      constructors and destructors
// -----------------------------------------------------------------------------

Scheduler::Scheduler(size_t nrThreads, size_t maxQueueSize)
    : _nrThreads(nrThreads),
      _maxQueueSize(maxQueueSize),
      _stopping(false),
      _nrBusy(0),
      _nrWorking(0),
      _nrBlocked(0),
      _nrRunning(0),
      _nrMinimal(0),
      _nrMaximal(0),
      _nrRealMaximum(0),
      _lastThreadWarning(0) {
  // setup signal handlers
  initializeSignalHandlers();
}

Scheduler::~Scheduler() { deleteOldThreads(); }

// -----------------------------------------------------------------------------
// --SECTION--                                      constructors and destructors
// -----------------------------------------------------------------------------

bool Scheduler::start(ConditionVariable* cv) {
  // start the I/O
  startIoService();

  // initialize thread handling
  if (_nrMaximal <= 0) {
    _nrMaximal = _nrThreads;
  }

  if (_nrRealMaximum <= 0) {
    _nrRealMaximum = 4 * _nrMaximal;
  }

  for (size_t i = 0; i < 2; ++i) {
    startNewThread();
  }

  startManagerThread();
  startRebalancer();

  // initialize the queue handling
  _jobQueue.reset(new JobQueue(_maxQueueSize, _ioService.get()));
  _jobQueue->start();

  // done
  LOG(TRACE) << "all scheduler threads are up and running";
  return true;
}

void Scheduler::startIoService() {
  _ioService.reset(new boost::asio::io_service());
  _serviceGuard.reset(new boost::asio::io_service::work(*_ioService));

  _managerService.reset(new boost::asio::io_service());
  _managerGuard.reset(new boost::asio::io_service::work(*_managerService));
}

void Scheduler::startRebalancer() {
  std::chrono::milliseconds interval(500);
  _threadManager.reset(new boost::asio::steady_timer(*_managerService));

  _threadHandler = [this, interval](const boost::system::error_code& error) {
    if (error || isStopping()) {
      return;
    }

    rebalanceThreads();

    _threadManager->expires_from_now(interval);
    _threadManager->async_wait(_threadHandler);
  };

  _threadManager->expires_from_now(interval);
  _threadManager->async_wait(_threadHandler);

  _lastThreadWarning.store(TRI_microtime());
}

void Scheduler::startManagerThread() {
  MUTEX_LOCKER(guard, _threadsLock);

  auto thread = new SchedulerManagerThread(this, _managerService.get());

  _threads.emplace(thread);
  thread->start();
}

void Scheduler::startNewThread() {
  MUTEX_LOCKER(guard, _threadsLock);

  auto thread = new SchedulerThread(this, _ioService.get());

  _threads.emplace(thread);
  thread->start();
}

bool Scheduler::stopThread() {
  if (_nrRunning <= _nrMinimal) {
    return false;
  }

  if (_nrRunning >= 3) {
    int64_t low = ((_nrRunning <= 4) ? 0 : (_nrRunning * 1 / 4)) - _nrBlocked;

    if (_nrBusy <= low && _nrWorking <= low) {
      return true;
    }
  }

  return false;
}

void Scheduler::threadDone(Thread* thread) {
  MUTEX_LOCKER(guard, _threadsLock);

  _threads.erase(thread);
  _deadThreads.insert(thread);
}

void Scheduler::deleteOldThreads() {
  // delete old thread objects
  std::unordered_set<Thread*> deadThreads;

  {
    MUTEX_LOCKER(guard, _threadsLock);

    if (_deadThreads.empty()) {
      return;
    }

    deadThreads.swap(_deadThreads);
  }

  for (auto thread : deadThreads) {
    try {
      delete thread;
    } catch (...) {
      LOG_TOPIC(ERR, Logger::THREADS) << "cannot delete thread";
    }
  }
}

void Scheduler::rebalanceThreads() {
  static double const MIN_WARN_INTERVAL = 10;
  static double const MIN_ERR_INTERVAL = 300;

  int64_t high = (_nrRunning <= 4) ? 1 : (_nrRunning * 11 / 16);
  int64_t working = (_nrBusy > _nrWorking) ? _nrBusy : _nrWorking;

  LOG_TOPIC(DEBUG, Logger::THREADS) << "rebalancing threads, high: " << high
                                    << ", working: " << working << " ("
                                    << infoStatus() << ")";

  if (working >= high) {
    if (_nrRunning < _nrMaximal + _nrBlocked &&
        _nrRunning < _nrRealMaximal) {   // added by Max 22.12.2016
      // otherwise we exceed the total maximum
      startNewThread();
      return;
    }
  }

  if (working >= _nrMaximal + _nrBlocked || _nrRunning < _nrMinimal) {
    double ltw = _lastThreadWarning.load();
    double now = TRI_microtime();

    if (_nrRunning >= _nrRealMaximum) {
      if (ltw - now > MIN_ERR_INTERVAL) {
        LOG_TOPIC(ERR, Logger::THREADS) << "too many threads (" << infoStatus()
                                        << ")";
        _lastThreadWarning.store(now);
      }
    } else {
      if (_nrRunning >= _nrRealMaximum * 3 / 4) {
        if (ltw - now > MIN_WARN_INTERVAL) {
          LOG_TOPIC(WARN, Logger::THREADS)
              << "number of threads is reaching a critical limit ("
              << infoStatus() << ")";
          _lastThreadWarning.store(now);
        }
      }

      LOG_TOPIC(DEBUG, Logger::THREADS) << "overloading threads ("
                                        << infoStatus() << ")";

      startNewThread();
    }
  }
}

void Scheduler::beginShutdown() {
  if (_stopping) {
    return;
  }

  _jobQueue->beginShutdown();

  _threadManager.reset();

  _managerGuard.reset();
  _managerService->stop();

  _serviceGuard.reset();
  _ioService->stop();

  // set the flag AFTER stopping the threads
  _stopping = true;
}

void Scheduler::shutdown() {
  bool done = false;

  while (!done) {
    MUTEX_LOCKER(guard, _threadsLock);
    done = _threads.empty();
  }

  deleteOldThreads();

  _managerService.reset();
  _ioService.reset();
}

void Scheduler::initializeSignalHandlers() {
#ifdef _WIN32
// Windows does not support POSIX signal handling
#else
  struct sigaction action;
  memset(&action, 0, sizeof(action));
  sigfillset(&action.sa_mask);

  // ignore broken pipes
  action.sa_handler = SIG_IGN;

  int res = sigaction(SIGPIPE, &action, 0);

  if (res < 0) {
    LOG(ERR) << "cannot initialize signal handlers for pipe";
  }
#endif
}
<commit_msg>Fix compilation.<commit_after>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Achim Brandt
////////////////////////////////////////////////////////////////////////////////

#ifdef _WIN32
#include "Basics/win-utils.h"
#endif

#include "Scheduler.h"

#include <velocypack/Builder.h>
#include <velocypack/velocypack-aliases.h>

#include "Basics/MutexLocker.h"
#include "Basics/StringUtils.h"
#include "Basics/Thread.h"
#include "Logger/Logger.h"
#include "Rest/GeneralResponse.h"
#include "Scheduler/JobQueue.h"
#include "Scheduler/Task.h"

using namespace arangodb;
using namespace arangodb::basics;
using namespace arangodb::rest;

// -----------------------------------------------------------------------------
// --SECTION--                                            SchedulerManagerThread
// -----------------------------------------------------------------------------

namespace {
class SchedulerManagerThread : public Thread {
 public:
  SchedulerManagerThread(Scheduler* scheduler, boost::asio::io_service* service)
      : Thread("SchedulerManager"), _scheduler(scheduler), _service(service) {}

  ~SchedulerManagerThread() { shutdown(); }

 public:
  void run() {
    while (!_scheduler->isStopping()) {
      try {
        _service->run_one();
        _scheduler->deleteOldThreads();
      } catch (...) {
        LOG_TOPIC(ERR, Logger::THREADS)
            << "manager loop caught an error, restarting";
      }
    }

    _scheduler->threadDone(this);
  }

 private:
  Scheduler* _scheduler;
  boost::asio::io_service* _service;
};
}

// -----------------------------------------------------------------------------
// --SECTION--                                                   SchedulerThread
// -----------------------------------------------------------------------------

namespace {
class SchedulerThread : public Thread {
 public:
  SchedulerThread(Scheduler* scheduler, boost::asio::io_service* service)
      : Thread("Scheduler"), _scheduler(scheduler), _service(service) {}

  ~SchedulerThread() { shutdown(); }

 public:
  void run() {
    _scheduler->incRunning();
    LOG_TOPIC(DEBUG, Logger::THREADS) << "running (" << _scheduler->infoStatus()
                                      << ")";

    auto start = std::chrono::steady_clock::now();

    try {
      static size_t EVERY_LOOP = 1000;
      static double MIN_SECONDS = 30;

      size_t counter = 0;
      while (!_scheduler->isStopping()) {
        _service->run_one();

        if (++counter > EVERY_LOOP) {
          auto now = std::chrono::steady_clock::now();
          std::chrono::duration<double> diff = now - start;

          if (diff.count() > MIN_SECONDS) {
            if (_scheduler->stopThread()) {
              auto n = _scheduler->decRunning();

              if (n <= 2) {
                _scheduler->incRunning();
              } else {
                break;
              }
            }

            start = std::chrono::steady_clock::now();
          }
        }
      }

      LOG_TOPIC(DEBUG, Logger::THREADS) << "stopped ("
                                        << _scheduler->infoStatus() << ")";
    } catch (...) {
      LOG_TOPIC(ERR, Logger::THREADS)
          << "scheduler loop caught an error, restarting";
      _scheduler->decRunning();
      _scheduler->startNewThread();
    }

    _scheduler->threadDone(this);
  }

 private:
  Scheduler* _scheduler;
  boost::asio::io_service* _service;
};
}

// -----------------------------------------------------------------------------
// --SECTION--                                                         Scheduler
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// --SECTION--                                      constructors and destructors
// -----------------------------------------------------------------------------

Scheduler::Scheduler(size_t nrThreads, size_t maxQueueSize)
    : _nrThreads(nrThreads),
      _maxQueueSize(maxQueueSize),
      _stopping(false),
      _nrBusy(0),
      _nrWorking(0),
      _nrBlocked(0),
      _nrRunning(0),
      _nrMinimal(0),
      _nrMaximal(0),
      _nrRealMaximum(0),
      _lastThreadWarning(0) {
  // setup signal handlers
  initializeSignalHandlers();
}

Scheduler::~Scheduler() { deleteOldThreads(); }

// -----------------------------------------------------------------------------
// --SECTION--                                      constructors and destructors
// -----------------------------------------------------------------------------

bool Scheduler::start(ConditionVariable* cv) {
  // start the I/O
  startIoService();

  // initialize thread handling
  if (_nrMaximal <= 0) {
    _nrMaximal = _nrThreads;
  }

  if (_nrRealMaximum <= 0) {
    _nrRealMaximum = 4 * _nrMaximal;
  }

  for (size_t i = 0; i < 2; ++i) {
    startNewThread();
  }

  startManagerThread();
  startRebalancer();

  // initialize the queue handling
  _jobQueue.reset(new JobQueue(_maxQueueSize, _ioService.get()));
  _jobQueue->start();

  // done
  LOG(TRACE) << "all scheduler threads are up and running";
  return true;
}

void Scheduler::startIoService() {
  _ioService.reset(new boost::asio::io_service());
  _serviceGuard.reset(new boost::asio::io_service::work(*_ioService));

  _managerService.reset(new boost::asio::io_service());
  _managerGuard.reset(new boost::asio::io_service::work(*_managerService));
}

void Scheduler::startRebalancer() {
  std::chrono::milliseconds interval(500);
  _threadManager.reset(new boost::asio::steady_timer(*_managerService));

  _threadHandler = [this, interval](const boost::system::error_code& error) {
    if (error || isStopping()) {
      return;
    }

    rebalanceThreads();

    _threadManager->expires_from_now(interval);
    _threadManager->async_wait(_threadHandler);
  };

  _threadManager->expires_from_now(interval);
  _threadManager->async_wait(_threadHandler);

  _lastThreadWarning.store(TRI_microtime());
}

void Scheduler::startManagerThread() {
  MUTEX_LOCKER(guard, _threadsLock);

  auto thread = new SchedulerManagerThread(this, _managerService.get());

  _threads.emplace(thread);
  thread->start();
}

void Scheduler::startNewThread() {
  MUTEX_LOCKER(guard, _threadsLock);

  auto thread = new SchedulerThread(this, _ioService.get());

  _threads.emplace(thread);
  thread->start();
}

bool Scheduler::stopThread() {
  if (_nrRunning <= _nrMinimal) {
    return false;
  }

  if (_nrRunning >= 3) {
    int64_t low = ((_nrRunning <= 4) ? 0 : (_nrRunning * 1 / 4)) - _nrBlocked;

    if (_nrBusy <= low && _nrWorking <= low) {
      return true;
    }
  }

  return false;
}

void Scheduler::threadDone(Thread* thread) {
  MUTEX_LOCKER(guard, _threadsLock);

  _threads.erase(thread);
  _deadThreads.insert(thread);
}

void Scheduler::deleteOldThreads() {
  // delete old thread objects
  std::unordered_set<Thread*> deadThreads;

  {
    MUTEX_LOCKER(guard, _threadsLock);

    if (_deadThreads.empty()) {
      return;
    }

    deadThreads.swap(_deadThreads);
  }

  for (auto thread : deadThreads) {
    try {
      delete thread;
    } catch (...) {
      LOG_TOPIC(ERR, Logger::THREADS) << "cannot delete thread";
    }
  }
}

void Scheduler::rebalanceThreads() {
  static double const MIN_WARN_INTERVAL = 10;
  static double const MIN_ERR_INTERVAL = 300;

  int64_t high = (_nrRunning <= 4) ? 1 : (_nrRunning * 11 / 16);
  int64_t working = (_nrBusy > _nrWorking) ? _nrBusy : _nrWorking;

  LOG_TOPIC(DEBUG, Logger::THREADS) << "rebalancing threads, high: " << high
                                    << ", working: " << working << " ("
                                    << infoStatus() << ")";

  if (working >= high) {
    if (_nrRunning < _nrMaximal + _nrBlocked &&
        _nrRunning < _nrRealMaximum) {   // added by Max 22.12.2016
      // otherwise we exceed the total maximum
      startNewThread();
      return;
    }
  }

  if (working >= _nrMaximal + _nrBlocked || _nrRunning < _nrMinimal) {
    double ltw = _lastThreadWarning.load();
    double now = TRI_microtime();

    if (_nrRunning >= _nrRealMaximum) {
      if (ltw - now > MIN_ERR_INTERVAL) {
        LOG_TOPIC(ERR, Logger::THREADS) << "too many threads (" << infoStatus()
                                        << ")";
        _lastThreadWarning.store(now);
      }
    } else {
      if (_nrRunning >= _nrRealMaximum * 3 / 4) {
        if (ltw - now > MIN_WARN_INTERVAL) {
          LOG_TOPIC(WARN, Logger::THREADS)
              << "number of threads is reaching a critical limit ("
              << infoStatus() << ")";
          _lastThreadWarning.store(now);
        }
      }

      LOG_TOPIC(DEBUG, Logger::THREADS) << "overloading threads ("
                                        << infoStatus() << ")";

      startNewThread();
    }
  }
}

void Scheduler::beginShutdown() {
  if (_stopping) {
    return;
  }

  _jobQueue->beginShutdown();

  _threadManager.reset();

  _managerGuard.reset();
  _managerService->stop();

  _serviceGuard.reset();
  _ioService->stop();

  // set the flag AFTER stopping the threads
  _stopping = true;
}

void Scheduler::shutdown() {
  bool done = false;

  while (!done) {
    MUTEX_LOCKER(guard, _threadsLock);
    done = _threads.empty();
  }

  deleteOldThreads();

  _managerService.reset();
  _ioService.reset();
}

void Scheduler::initializeSignalHandlers() {
#ifdef _WIN32
// Windows does not support POSIX signal handling
#else
  struct sigaction action;
  memset(&action, 0, sizeof(action));
  sigfillset(&action.sa_mask);

  // ignore broken pipes
  action.sa_handler = SIG_IGN;

  int res = sigaction(SIGPIPE, &action, 0);

  if (res < 0) {
    LOG(ERR) << "cannot initialize signal handlers for pipe";
  }
#endif
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <utility>
#include <stdexcept>
#include <string.h>
#include <algorithm>

#include <xf86drm.h>
#include <xf86drmMode.h>

#include "kms++.h"

#ifndef DRM_CLIENT_CAP_ATOMIC
#define DRM_CLIENT_CAP_ATOMIC 3
#endif

using namespace std;

namespace kms
{

Card::Card()
{
	const char *card = "/dev/dri/card0";

	int fd = open(card, O_RDWR | O_CLOEXEC);
	if (fd < 0)
		throw invalid_argument(string(strerror(errno)) + " opening " +
				       card);
	m_fd = fd;

	int r;

	r = drmSetMaster(fd);
	m_master = r == 0;

	r = drmSetClientCap(m_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
	m_has_universal_planes = r == 0;

	if (getenv("LIBKMSXX_DISABLE_ATOMIC") == 0) {
		r = drmSetClientCap(m_fd, DRM_CLIENT_CAP_ATOMIC, 1);
		m_has_atomic = r == 0;
	} else {
		m_has_atomic = false;
	}

	uint64_t has_dumb;
	r = drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb);
	if (r || !has_dumb)
		throw invalid_argument("Dumb buffers not available");

	auto res = drmModeGetResources(m_fd);
	if (!res)
		throw invalid_argument("Can't get card resources");

	for (int i = 0; i < res->count_connectors; ++i) {
		uint32_t id = res->connectors[i];
		m_obmap[id] = new Connector(*this, id, i);
	}

	for (int i = 0; i < res->count_crtcs; ++i) {
		uint32_t id = res->crtcs[i];
		m_obmap[id] = new Crtc(*this, id, i);
	}

	for (int i = 0; i < res->count_encoders; ++i) {
		uint32_t id = res->encoders[i];
		m_obmap[id] = new Encoder(*this, id);
	}

	drmModeFreeResources(res);

	auto planeRes = drmModeGetPlaneResources(m_fd);

	for (uint i = 0; i < planeRes->count_planes; ++i) {
		uint32_t id = planeRes->planes[i];
		m_obmap[id] = new Plane(*this, id);
	}

	drmModeFreePlaneResources(planeRes);

	// collect all possible props
	for (auto ob : get_objects()) {
		auto props = drmModeObjectGetProperties(m_fd, ob->id(), ob->object_type());

		if (props == nullptr)
			continue;

		for (unsigned i = 0; i < props->count_props; ++i) {
			uint32_t prop_id = props->props[i];

			if (m_obmap.find(prop_id) == m_obmap.end())
				m_obmap[prop_id] = new Property(*this, prop_id);
		}

		drmModeFreeObjectProperties(props);
	}

	for (auto pair : m_obmap)
		pair.second->setup();
}

Card::~Card()
{
	for (auto pair : m_obmap)
		delete pair.second;

	close(m_fd);
}

template <class T> static void print_obs(const map<uint32_t, DrmObject*>& obmap)
{
	for (auto pair : obmap) {
		auto ob = pair.second;
		if (dynamic_cast<T*>(ob)) {
			ob->print_short();
			//ob->print_props();
		}
	}
}

void Card::print_short() const
{
	print_obs<Connector>(m_obmap);
	print_obs<Encoder>(m_obmap);
	print_obs<Crtc>(m_obmap);
	print_obs<Plane>(m_obmap);
}

Property* Card::get_prop(const char *name) const
{
	for (auto pair : m_obmap) {
		auto prop = dynamic_cast<Property*>(pair.second);
		if (!prop)
			continue;

		if (strcmp(name, prop->name()) == 0)
			return prop;
	}

	throw invalid_argument(string("Card property ") + name + " not found");
}

Connector* Card::get_first_connected_connector() const
{
	for(auto pair : m_obmap) {
		auto c = dynamic_cast<Connector*>(pair.second);

		if (c && c->connected())
			return c;
	}

	throw invalid_argument("no connected connectors");
}

DrmObject* Card::get_object(uint32_t id) const
{
	return m_obmap.at(id);
}

vector<Connector*> Card::get_connectors() const
{
	vector<Connector*> v;
	for(auto pair : m_obmap) {
		auto p = dynamic_cast<Connector*>(pair.second);
		if (p)
			v.push_back(p);
	}
	return v;
}

vector<Plane*> Card::get_planes() const
{
	vector<Plane*> v;
	for(auto pair : m_obmap) {
		auto p = dynamic_cast<Plane*>(pair.second);
		if (p)
			v.push_back(p);
	}
	return v;
}

vector<DrmObject*> Card::get_objects() const
{
	vector<DrmObject*> v;
	for(auto pair : m_obmap)
		v.push_back(pair.second);
	return v;
}

Crtc* Card::get_crtc_by_index(uint32_t idx) const
{
	for(auto pair : m_obmap) {
		auto crtc = dynamic_cast<Crtc*>(pair.second);
		if (crtc && crtc->idx() == idx)
			return crtc;
	}
	throw invalid_argument(string("Crtc #") + to_string(idx) + "not found");
}

Crtc* Card::get_crtc(uint32_t id) const { return dynamic_cast<Crtc*>(get_object(id)); }
Encoder* Card::get_encoder(uint32_t id) const { return dynamic_cast<Encoder*>(get_object(id)); }
Property* Card::get_prop(uint32_t id) const { return dynamic_cast<Property*>(get_object(id)); }

std::vector<kms::Pipeline> Card::get_connected_pipelines()
{
	vector<Pipeline> outputs;

	for (auto conn : get_connectors())
	{
		if (conn->connected() == false)
			continue;

		Crtc* crtc = conn->get_current_crtc();

		if (!crtc) {
			for (auto possible : conn->get_possible_crtcs()) {
				if (find_if(outputs.begin(), outputs.end(), [possible](Pipeline out) { return out.crtc == possible; }) == outputs.end()) {
					crtc = possible;
					break;
				}
			}
		}

		if (!crtc)
			throw invalid_argument(string("Connector #") +
					       to_string(conn->idx()) +
					       " has no possible crtcs");

		outputs.push_back(Pipeline { crtc, conn });
	}

	return outputs;
}

}
<commit_msg>Allow disabling universal planes with LIBKMSXX_DISABLE_UNIVERSAL_PLANES<commit_after>#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <utility>
#include <stdexcept>
#include <string.h>
#include <algorithm>

#include <xf86drm.h>
#include <xf86drmMode.h>

#include "kms++.h"

#ifndef DRM_CLIENT_CAP_ATOMIC
#define DRM_CLIENT_CAP_ATOMIC 3
#endif

using namespace std;

namespace kms
{

Card::Card()
{
	const char *card = "/dev/dri/card0";

	int fd = open(card, O_RDWR | O_CLOEXEC);
	if (fd < 0)
		throw invalid_argument(string(strerror(errno)) + " opening " +
				       card);
	m_fd = fd;

	int r;

	r = drmSetMaster(fd);
	m_master = r == 0;

	if (getenv("LIBKMSXX_DISABLE_UNIVERSAL_PLANES") == 0) {
		r = drmSetClientCap(m_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
		m_has_universal_planes = r == 0;
	} else {
		m_has_universal_planes = false;
	}

	if (getenv("LIBKMSXX_DISABLE_ATOMIC") == 0) {
		r = drmSetClientCap(m_fd, DRM_CLIENT_CAP_ATOMIC, 1);
		m_has_atomic = r == 0;
	} else {
		m_has_atomic = false;
	}

	uint64_t has_dumb;
	r = drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb);
	if (r || !has_dumb)
		throw invalid_argument("Dumb buffers not available");

	auto res = drmModeGetResources(m_fd);
	if (!res)
		throw invalid_argument("Can't get card resources");

	for (int i = 0; i < res->count_connectors; ++i) {
		uint32_t id = res->connectors[i];
		m_obmap[id] = new Connector(*this, id, i);
	}

	for (int i = 0; i < res->count_crtcs; ++i) {
		uint32_t id = res->crtcs[i];
		m_obmap[id] = new Crtc(*this, id, i);
	}

	for (int i = 0; i < res->count_encoders; ++i) {
		uint32_t id = res->encoders[i];
		m_obmap[id] = new Encoder(*this, id);
	}

	drmModeFreeResources(res);

	auto planeRes = drmModeGetPlaneResources(m_fd);

	for (uint i = 0; i < planeRes->count_planes; ++i) {
		uint32_t id = planeRes->planes[i];
		m_obmap[id] = new Plane(*this, id);
	}

	drmModeFreePlaneResources(planeRes);

	// collect all possible props
	for (auto ob : get_objects()) {
		auto props = drmModeObjectGetProperties(m_fd, ob->id(), ob->object_type());

		if (props == nullptr)
			continue;

		for (unsigned i = 0; i < props->count_props; ++i) {
			uint32_t prop_id = props->props[i];

			if (m_obmap.find(prop_id) == m_obmap.end())
				m_obmap[prop_id] = new Property(*this, prop_id);
		}

		drmModeFreeObjectProperties(props);
	}

	for (auto pair : m_obmap)
		pair.second->setup();
}

Card::~Card()
{
	for (auto pair : m_obmap)
		delete pair.second;

	close(m_fd);
}

template <class T> static void print_obs(const map<uint32_t, DrmObject*>& obmap)
{
	for (auto pair : obmap) {
		auto ob = pair.second;
		if (dynamic_cast<T*>(ob)) {
			ob->print_short();
			//ob->print_props();
		}
	}
}

void Card::print_short() const
{
	print_obs<Connector>(m_obmap);
	print_obs<Encoder>(m_obmap);
	print_obs<Crtc>(m_obmap);
	print_obs<Plane>(m_obmap);
}

Property* Card::get_prop(const char *name) const
{
	for (auto pair : m_obmap) {
		auto prop = dynamic_cast<Property*>(pair.second);
		if (!prop)
			continue;

		if (strcmp(name, prop->name()) == 0)
			return prop;
	}

	throw invalid_argument(string("Card property ") + name + " not found");
}

Connector* Card::get_first_connected_connector() const
{
	for(auto pair : m_obmap) {
		auto c = dynamic_cast<Connector*>(pair.second);

		if (c && c->connected())
			return c;
	}

	throw invalid_argument("no connected connectors");
}

DrmObject* Card::get_object(uint32_t id) const
{
	return m_obmap.at(id);
}

vector<Connector*> Card::get_connectors() const
{
	vector<Connector*> v;
	for(auto pair : m_obmap) {
		auto p = dynamic_cast<Connector*>(pair.second);
		if (p)
			v.push_back(p);
	}
	return v;
}

vector<Plane*> Card::get_planes() const
{
	vector<Plane*> v;
	for(auto pair : m_obmap) {
		auto p = dynamic_cast<Plane*>(pair.second);
		if (p)
			v.push_back(p);
	}
	return v;
}

vector<DrmObject*> Card::get_objects() const
{
	vector<DrmObject*> v;
	for(auto pair : m_obmap)
		v.push_back(pair.second);
	return v;
}

Crtc* Card::get_crtc_by_index(uint32_t idx) const
{
	for(auto pair : m_obmap) {
		auto crtc = dynamic_cast<Crtc*>(pair.second);
		if (crtc && crtc->idx() == idx)
			return crtc;
	}
	throw invalid_argument(string("Crtc #") + to_string(idx) + "not found");
}

Crtc* Card::get_crtc(uint32_t id) const { return dynamic_cast<Crtc*>(get_object(id)); }
Encoder* Card::get_encoder(uint32_t id) const { return dynamic_cast<Encoder*>(get_object(id)); }
Property* Card::get_prop(uint32_t id) const { return dynamic_cast<Property*>(get_object(id)); }

std::vector<kms::Pipeline> Card::get_connected_pipelines()
{
	vector<Pipeline> outputs;

	for (auto conn : get_connectors())
	{
		if (conn->connected() == false)
			continue;

		Crtc* crtc = conn->get_current_crtc();

		if (!crtc) {
			for (auto possible : conn->get_possible_crtcs()) {
				if (find_if(outputs.begin(), outputs.end(), [possible](Pipeline out) { return out.crtc == possible; }) == outputs.end()) {
					crtc = possible;
					break;
				}
			}
		}

		if (!crtc)
			throw invalid_argument(string("Connector #") +
					       to_string(conn->idx()) +
					       " has no possible crtcs");

		outputs.push_back(Pipeline { crtc, conn });
	}

	return outputs;
}

}
<|endoftext|>


<commit_before>/*  LibMary - C++ library for high-performance network servers
    Copyright (C) 2011 Dmitry Shatrov

    This library 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 2.1 of the License, or (at your option) any later version.

    This library 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 library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <libmary/types.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>

#include <libmary/exception.h>
#include <libmary/posix.h>
#include <libmary/io.h>
#include <libmary/native_file.h>
#include <libmary/buffered_output_stream.h>
#include <libmary/log.h>
#include <libmary/util_str.h>

namespace M {

#if 0
void posix_throw_errno ()
{
//    switch (errno) {
//    }
    exc_throw (PosixException (errno));
    exc_push ();

#if 0
    // TODO Convert posix errors to libmary.
    exc_throw (InternalException (InternalException::UnknownError));
#endif
}
#endif

void libMary_posixInit ()
{
    // Calling tzset() for localtime_r() to behave correctly.
    tzset ();

    outs = new NativeFile (STDOUT_FILENO);
    errs = new NativeFile (STDERR_FILENO);

    static BufferedOutputStream logs_buffered (errs, 4096);
    logs = &logs_buffered;

    if (!updateTime ())
	logE_ (_func, exc->toString());

    // Blocking SIGPIPE for write()/writev().
    {
//	logD_ (_func, "blocking SIGPIPE");

	struct sigaction act;
	memset (&act, 0, sizeof (act));
	act.sa_handler = SIG_IGN;
	// TODO -1 on error
	sigemptyset (&act.sa_mask);
	// TODO -1 on error
	sigaddset (&act.sa_mask, SIGPIPE);
	if (sigaction (SIGPIPE, &act, NULL) == -1)
	    logE_ (_func, "sigaction() failed: ", errnoString (errno));
    }
#if 0
    {
	struct sigaction sa;
	zeroMemory (&sa, sizeof sa);
	sa.sa_handler = sigchld_handler;
	sigemptyset (&sa.sa_mask);
/* I'd like to have a non-restarting signal
 * to test MyNC libraries for correct handling of EINTR.
	sa.sa_flags = SA_RESTART;
 */
	// TODO sigaddset?
	sa.sa_flags = 0;
	if (sigaction (SIGCHLD, &sa, NULL) == -1) {
	    printError ("sigthread_func: (fatal) sigaction");
	    _exit (-1);
	}
    }
#endif
}

}

<commit_msg>prevent 'logs' from being destroyed when the server exits<commit_after>/*  LibMary - C++ library for high-performance network servers
    Copyright (C) 2011 Dmitry Shatrov

    This library 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 2.1 of the License, or (at your option) any later version.

    This library 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 library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <libmary/types.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>

#include <libmary/exception.h>
#include <libmary/posix.h>
#include <libmary/io.h>
#include <libmary/native_file.h>
#include <libmary/buffered_output_stream.h>
#include <libmary/log.h>
#include <libmary/util_str.h>

namespace M {

#if 0
void posix_throw_errno ()
{
//    switch (errno) {
//    }
    exc_throw (PosixException (errno));
    exc_push ();

#if 0
    // TODO Convert posix errors to libmary.
    exc_throw (InternalException (InternalException::UnknownError));
#endif
}
#endif

void libMary_posixInit ()
{
    // Calling tzset() for localtime_r() to behave correctly.
    tzset ();

    outs = new NativeFile (STDOUT_FILENO);
    errs = new NativeFile (STDERR_FILENO);

#if 0
    static BufferedOutputStream logs_buffered (errs, 4096);
    logs = &logs_buffered;
#endif
    // Allocating on heap to avoid problems with deinitialization order
    // of static data.
    logs = new BufferedOutputStream (errs, 4096);

    if (!updateTime ())
	logE_ (_func, exc->toString());

    // Blocking SIGPIPE for write()/writev().
    {
//	logD_ (_func, "blocking SIGPIPE");

	struct sigaction act;
	memset (&act, 0, sizeof (act));
	act.sa_handler = SIG_IGN;
	// TODO -1 on error
	sigemptyset (&act.sa_mask);
	// TODO -1 on error
	sigaddset (&act.sa_mask, SIGPIPE);
	if (sigaction (SIGPIPE, &act, NULL) == -1)
	    logE_ (_func, "sigaction() failed: ", errnoString (errno));
    }
#if 0
    {
	struct sigaction sa;
	zeroMemory (&sa, sizeof sa);
	sa.sa_handler = sigchld_handler;
	sigemptyset (&sa.sa_mask);
/* I'd like to have a non-restarting signal
 * to test MyNC libraries for correct handling of EINTR.
	sa.sa_flags = SA_RESTART;
 */
	// TODO sigaddset?
	sa.sa_flags = 0;
	if (sigaction (SIGCHLD, &sa, NULL) == -1) {
	    printError ("sigthread_func: (fatal) sigaction");
	    _exit (-1);
	}
    }
#endif
}

}

<|endoftext|>


<commit_before>/*
 *  Copyright 2019-2020 Diligent Graphics LLC
 *  Copyright 2015-2019 Egor Yusov
 *
 *  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.
 *
 *  In no event and under no legal theory, whether in tort (including negligence),
 *  contract, or otherwise, unless required by applicable law (such as deliberate
 *  and grossly negligent acts) or agreed to in writing, shall any Contributor be
 *  liable for any damages, including any direct, indirect, special, incidental,
 *  or consequential damages of any character arising as a result of this License or
 *  out of the use or inability to use the software (including but not limited to damages
 *  for loss of goodwill, work stoppage, computer failure or malfunction, or any and
 *  all other commercial damages or losses), even if such Contributor has been advised
 *  of the possibility of such damages.
 */

#include "TestingEnvironment.hpp"

#include <GL/glx.h>

typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, int, const int*);

namespace Diligent
{

namespace Testing
{

NativeWindow TestingEnvironment::CreateNativeWindow()
{
    auto* display = XOpenDisplay(0);

    // clang-format off
    static int visual_attribs[] =
    {
        GLX_RENDER_TYPE,    GLX_RGBA_BIT,
        GLX_DRAWABLE_TYPE,  GLX_WINDOW_BIT,
        GLX_DOUBLEBUFFER,   true,

        // The largest available total RGBA color buffer size (sum of GLX_RED_SIZE,
        // GLX_GREEN_SIZE, GLX_BLUE_SIZE, and GLX_ALPHA_SIZE) of at least the minimum
        // size specified for each color component is preferred.
        GLX_RED_SIZE,       8,
        GLX_GREEN_SIZE,     8,
        GLX_BLUE_SIZE,      8,
        GLX_ALPHA_SIZE,     8,

        // The largest available depth buffer of at least GLX_DEPTH_SIZE size is preferred
        GLX_DEPTH_SIZE,     24,

        //GLX_SAMPLE_BUFFERS, 1,
        GLX_SAMPLES, 1,
        None
    };
    // clang-format on

    int          fbcount = 0;
    GLXFBConfig* fbc     = glXChooseFBConfig(display, DefaultScreen(display), visual_attribs, &fbcount);
    if (!fbc)
    {
        LOG_ERROR_AND_THROW("Failed to retrieve a framebuffer config");
    }

    XVisualInfo* vi = glXGetVisualFromFBConfig(display, fbc[0]);

    XSetWindowAttributes swa;
    swa.colormap     = XCreateColormap(display, RootWindow(display, vi->screen), vi->visual, AllocNone);
    swa.border_pixel = 0;
    swa.event_mask =
        StructureNotifyMask |
        ExposureMask |
        KeyPressMask |
        KeyReleaseMask |
        ButtonPressMask |
        ButtonReleaseMask |
        PointerMotionMask;

    auto win = XCreateWindow(display, RootWindow(display, vi->screen), 0, 0, 1024, 768, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask, &swa);
    if (!win)
    {
        LOG_ERROR_AND_THROW("Failed to create window.");
    }

    {
        auto SizeHints        = XAllocSizeHints();
        SizeHints->flags      = PMinSize;
        SizeHints->min_width  = 320;
        SizeHints->min_height = 240;
        XSetWMNormalHints(display, win, SizeHints);
        XFree(SizeHints);
    }

    XMapWindow(display, win);

    glXCreateContextAttribsARBProc glXCreateContextAttribsARB = nullptr;
    {
        // Create an oldstyle context first, to get the correct function pointer for glXCreateContextAttribsARB
        GLXContext ctx_old         = glXCreateContext(display, vi, 0, GL_TRUE);
        glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");
        glXMakeCurrent(display, None, NULL);
        glXDestroyContext(display, ctx_old);
    }

    if (glXCreateContextAttribsARB == nullptr)
    {
        LOG_ERROR_AND_THROW("glXCreateContextAttribsARB entry point not found. Aborting.");
    }

    int Flags = GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
#ifdef _DEBUG
    Flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
#endif

    int major_version = 4;
    int minor_version = 3;
    // clang-format off
    static int context_attribs[] =
    {
        GLX_CONTEXT_MAJOR_VERSION_ARB, major_version,
        GLX_CONTEXT_MINOR_VERSION_ARB, minor_version,
        GLX_CONTEXT_FLAGS_ARB, Flags,
        None
    };
    // clang-format on

    GLXContext ctx = glXCreateContextAttribsARB(display, fbc[0], NULL, 1, context_attribs);
    if (!ctx)
    {
        LOG_ERROR_AND_THROW("Failed to create GL context.");
    }
    XFree(fbc);

    glXMakeCurrent(display, win, ctx);

    struct TestingEnvironmentLinuxData : PlatformData
    {
        TestingEnvironmentLinuxData(NativeWindow _LinuxWnd) :
            LinuxWnd{_LinuxWnd}
        {
        }

        virtual ~TestingEnvironmentLinuxData()
        {
            auto  ctx     = glXGetCurrentContext();
            auto* display = reinterpret_cast<Display*>(LinuxWnd.pDisplay);
            glXMakeCurrent(display, None, NULL);
            glXDestroyContext(display, ctx);
            XDestroyWindow(display, LinuxWnd.WindowId);
            XCloseDisplay(display);
        }

        NativeWindow LinuxWnd;
    };

    NativeWindow LinuxWnd;
    LinuxWnd.pDisplay = display;
    LinuxWnd.WindowId = win;

    m_pPlatformData.reset(new TestingEnvironmentLinuxData{LinuxWnd});

    return LinuxWnd;
}

} // namespace Testing

} // namespace Diligent
<commit_msg>Fixed minor issue with non-explicit ctor<commit_after>/*
 *  Copyright 2019-2020 Diligent Graphics LLC
 *  Copyright 2015-2019 Egor Yusov
 *
 *  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.
 *
 *  In no event and under no legal theory, whether in tort (including negligence),
 *  contract, or otherwise, unless required by applicable law (such as deliberate
 *  and grossly negligent acts) or agreed to in writing, shall any Contributor be
 *  liable for any damages, including any direct, indirect, special, incidental,
 *  or consequential damages of any character arising as a result of this License or
 *  out of the use or inability to use the software (including but not limited to damages
 *  for loss of goodwill, work stoppage, computer failure or malfunction, or any and
 *  all other commercial damages or losses), even if such Contributor has been advised
 *  of the possibility of such damages.
 */

#include "TestingEnvironment.hpp"

#include <GL/glx.h>

typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, int, const int*);

namespace Diligent
{

namespace Testing
{

NativeWindow TestingEnvironment::CreateNativeWindow()
{
    auto* display = XOpenDisplay(0);

    // clang-format off
    static int visual_attribs[] =
    {
        GLX_RENDER_TYPE,    GLX_RGBA_BIT,
        GLX_DRAWABLE_TYPE,  GLX_WINDOW_BIT,
        GLX_DOUBLEBUFFER,   true,

        // The largest available total RGBA color buffer size (sum of GLX_RED_SIZE,
        // GLX_GREEN_SIZE, GLX_BLUE_SIZE, and GLX_ALPHA_SIZE) of at least the minimum
        // size specified for each color component is preferred.
        GLX_RED_SIZE,       8,
        GLX_GREEN_SIZE,     8,
        GLX_BLUE_SIZE,      8,
        GLX_ALPHA_SIZE,     8,

        // The largest available depth buffer of at least GLX_DEPTH_SIZE size is preferred
        GLX_DEPTH_SIZE,     24,

        //GLX_SAMPLE_BUFFERS, 1,
        GLX_SAMPLES, 1,
        None
    };
    // clang-format on

    int          fbcount = 0;
    GLXFBConfig* fbc     = glXChooseFBConfig(display, DefaultScreen(display), visual_attribs, &fbcount);
    if (!fbc)
    {
        LOG_ERROR_AND_THROW("Failed to retrieve a framebuffer config");
    }

    XVisualInfo* vi = glXGetVisualFromFBConfig(display, fbc[0]);

    XSetWindowAttributes swa;
    swa.colormap     = XCreateColormap(display, RootWindow(display, vi->screen), vi->visual, AllocNone);
    swa.border_pixel = 0;
    swa.event_mask =
        StructureNotifyMask |
        ExposureMask |
        KeyPressMask |
        KeyReleaseMask |
        ButtonPressMask |
        ButtonReleaseMask |
        PointerMotionMask;

    auto win = XCreateWindow(display, RootWindow(display, vi->screen), 0, 0, 1024, 768, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask, &swa);
    if (!win)
    {
        LOG_ERROR_AND_THROW("Failed to create window.");
    }

    {
        auto SizeHints        = XAllocSizeHints();
        SizeHints->flags      = PMinSize;
        SizeHints->min_width  = 320;
        SizeHints->min_height = 240;
        XSetWMNormalHints(display, win, SizeHints);
        XFree(SizeHints);
    }

    XMapWindow(display, win);

    glXCreateContextAttribsARBProc glXCreateContextAttribsARB = nullptr;
    {
        // Create an oldstyle context first, to get the correct function pointer for glXCreateContextAttribsARB
        GLXContext ctx_old         = glXCreateContext(display, vi, 0, GL_TRUE);
        glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");
        glXMakeCurrent(display, None, NULL);
        glXDestroyContext(display, ctx_old);
    }

    if (glXCreateContextAttribsARB == nullptr)
    {
        LOG_ERROR_AND_THROW("glXCreateContextAttribsARB entry point not found. Aborting.");
    }

    int Flags = GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
#ifdef _DEBUG
    Flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
#endif

    int major_version = 4;
    int minor_version = 3;
    // clang-format off
    static int context_attribs[] =
    {
        GLX_CONTEXT_MAJOR_VERSION_ARB, major_version,
        GLX_CONTEXT_MINOR_VERSION_ARB, minor_version,
        GLX_CONTEXT_FLAGS_ARB, Flags,
        None
    };
    // clang-format on

    GLXContext ctx = glXCreateContextAttribsARB(display, fbc[0], NULL, 1, context_attribs);
    if (!ctx)
    {
        LOG_ERROR_AND_THROW("Failed to create GL context.");
    }
    XFree(fbc);

    glXMakeCurrent(display, win, ctx);

    struct TestingEnvironmentLinuxData : PlatformData
    {
        explicit TestingEnvironmentLinuxData(NativeWindow _LinuxWnd) :
            LinuxWnd{_LinuxWnd}
        {
        }

        virtual ~TestingEnvironmentLinuxData()
        {
            auto  ctx     = glXGetCurrentContext();
            auto* display = reinterpret_cast<Display*>(LinuxWnd.pDisplay);
            glXMakeCurrent(display, None, NULL);
            glXDestroyContext(display, ctx);
            XDestroyWindow(display, LinuxWnd.WindowId);
            XCloseDisplay(display);
        }

        NativeWindow LinuxWnd;
    };

    NativeWindow LinuxWnd;
    LinuxWnd.pDisplay = display;
    LinuxWnd.WindowId = win;

    m_pPlatformData.reset(new TestingEnvironmentLinuxData{LinuxWnd});

    return LinuxWnd;
}

} // namespace Testing

} // namespace Diligent
<|endoftext|>


<commit_before>#include "ui_lua.h"

#include <lua\lua.hpp>
#include <util\lua_table.h>

#include "image_mgr.h"
#include "script_mgr.h"
#include "soundbuf_mgr.h"
#include "string_mgr.h"
#include "ui_button.h"
#include "ui_label.h"
#include "ui_line.h"
#include "ui_panel.h"
#include "ui_progressbar.h"
#include "ui_window.h"
#include "util_lua.h"
#include "util_sprite.h"

void RegisterUICreators()
{
  ScriptManager& scriptMgr = ScriptManager::GetInstance();

  scriptMgr.RegisterFunc("Button", Button);
  scriptMgr.RegisterFunc("Label", Label);
  scriptMgr.RegisterFunc("Line", Line);
  scriptMgr.RegisterFunc("Panel", Panel);
  scriptMgr.RegisterFunc("Progressbar", Progressbar);
  scriptMgr.RegisterFunc("Widget", Widget);
  scriptMgr.RegisterFunc("Window", Window_);
}

namespace
{
  void SetName(lua_State* L, UIWidget* widget)
  {
    if (util::HasField(L, "name"))
    {
      std::string name = util::GetField_String(L, "name");
      widget->SetName(name);
    }
  }

  void SetTopLeftWidthHeight(lua_State* L, UIWidget* widget)
  {
    if (util::HasField(L, "top") && util::HasField(L, "left"))
    {
      float left = util::GetField_Number(L, "left");
      float top = util::GetField_Number(L, "top");
      widget->SetTopLeft(Vector2f(left, top));
    }

    if (util::HasField(L, "width") && util::HasField(L, "height"))
    {
      float width = util::GetField_Number(L, "width");
      float height = util::GetField_Number(L, "height");
      widget->SetWidthHeight(Vector2f(width, height));
    }
  }

  void SetAnim(lua_State* L, UIWidget* widget, std::string widgetAnimKey, std::string luaAnimFieldKey)
  {
    if (util::HasField(L, luaAnimFieldKey.c_str()))
    {
      std::string imgKey = util::GetField_String(L, luaAnimFieldKey);
      if (!imgKey.empty())
      {
        Animation anim;
        Image& img = ImageManager::GetInstance().GetImage(imgKey);
        SetImage(anim, img);
        widget->SetAnim(widgetAnimKey, anim);
      }
    }
  }

  void SetTooltip(lua_State* L, UIWidget* widget)
  {
    if (util::HasField(L, "tooltipStringKey"))
    {
      std::string tooltipStringKey = util::GetField_String(L, "tooltipStringKey");
      if (!tooltipStringKey.empty())
      {
        String& str = StringManager::GetInstance().GetString(tooltipStringKey);
        widget->SetTooltip(str);
      }
    }

    if (util::HasField(L, "tooltipTopleft"))
    {
      lua_getfield(L, -1, "tooltipTopleft");
      Vector2f topleft;
      SetVector2f(L, topleft);
      lua_pop(L, 1);
      widget->SetTooltipTopLeft(topleft);
    }

    if (util::HasField(L, "useRelativeTooltipTopleft"))
    {
      bool useRelativeTooltipTopleft = util::GetField_Boolean(L, "useRelativeTooltipTopleft");
      widget->SetUseRelativeTooltipTopLeft(useRelativeTooltipTopleft);
    }
  }

  void SetTextUserData(lua_State* L, UIWidget* widget)
  {
    if (util::HasField(L, "textUserData"))
    {
      std::string textUserData = util::GetField_String(L, "textUserData");
      if (!textUserData.empty())
        widget->SetTextUserData(textUserData);
    }
  }

  void SetPressedSoundKey(lua_State* L, UIWidget* widget)
  {
    if (util::HasField(L, "pressedSoundKey"))
      widget->SetPressedSoundKey(util::GetField_String(L, "pressedSoundKey"));
  }

  void AddWidget(lua_State* L, UIWidget* widget)
  {
    lua_pushnil(L);
    while (lua_next(L, -2) != 0)
    {
      if (lua_islightuserdata(L, -1))
      {
        UIWidget* subWidget = static_cast<UIWidget*>(lua_touserdata(L, -1));
        widget->AddWidget(subWidget, subWidget->GetName());
      }

      lua_pop(L, 1);
    }
  }

  void SetButton(lua_State* L, UIButton* btn)
  {
    SetName(L, btn);
    SetTopLeftWidthHeight(L, btn);
    SetAnim(L, btn, UIButton::NORMAL_ANIM_, "normalAnim");
    SetAnim(L, btn, UIButton::HOVERED_ANIM_, "hoveredAnim");
    SetAnim(L, btn, UIButton::PRESSED_ANIM_, "pressedAnim");
    SetAnim(L, btn, UIButton::DISABLED_ANIM_, "disabledAnim");

    AddWidget(L, btn);
  }

}

int Button(lua_State* L)
{
  UIButton* btn = new UIButton;

  SetName(L, btn);
  SetTopLeftWidthHeight(L, btn);
  SetTooltip(L, btn);
  SetAnim(L, btn, UIButton::NORMAL_ANIM_, "normalAnim");
  SetAnim(L, btn, UIButton::HOVERED_ANIM_, "hoveredAnim");
  SetAnim(L, btn, UIButton::PRESSED_ANIM_, "pressedAnim");
  SetAnim(L, btn, UIButton::DISABLED_ANIM_, "disabledAnim");
  SetTextUserData(L, btn);
  SetPressedSoundKey(L, btn);

  AddWidget(L, btn);

  lua_pushlightuserdata(L, btn);

  return 1;
}

int Label(lua_State* L)
{
  UILabel* label = new UILabel;

  SetName(L, label);
  SetTopLeftWidthHeight(L, label);
  SetTooltip(L, label);
  SetTextUserData(L, label);
  SetPressedSoundKey(L, label);

  if (util::HasField(L, "hoveredStyle"))
  {
    int style = util::GetField_Number(L, "hoveredStyle");
    label->SetHoveredStyle(style);
  }

  if (util::HasField(L, "stringKey"))
  {
    std::string stringKey = util::GetField_String(L, "stringKey");
    if (!stringKey.empty())
      label->SetString(StringManager::GetInstance().GetString(stringKey));
  }

  if (util::HasField(L, "color"))
  {
    String& str = label->GetString();
    Color& color = const_cast<Color&>(str.GetColor());
    lua_getfield(L, -1, "color");
    SetColor(L, color);
    lua_pop(L, 1);
  }

  lua_pushlightuserdata(L, label);

  return 1;
}

int Line(lua_State* L)
{
  UILine* line = new UILine;
  SetName(L, line);
  SetTopLeftWidthHeight(L, line);
  SetTooltip(L, line);
  SetTextUserData(L, line);
  lua_pushlightuserdata(L, line);
  return 1;
}

int Panel(lua_State* L)
{
  UIPanel* panel = new UIPanel;

  SetName(L, panel);
  SetTopLeftWidthHeight(L, panel);
  SetTooltip(L, panel);
  SetAnim(L, panel, UIPanel::NORMAL_ANIM_, "normalAnim");
  SetAnim(L, panel, UIPanel::DISABLED_ANIM_, "disabledAnim");
  SetTextUserData(L, panel);

  AddWidget(L, panel);

  lua_pushlightuserdata(L, panel);

  return 1;
}

int Progressbar(lua_State* L)
{
  UIProgressbar* progressbar = new UIProgressbar;

  SetName(L, progressbar);
  SetTopLeftWidthHeight(L, progressbar);
  SetTooltip(L, progressbar);
  SetAnim(L, progressbar, UIProgressbar::BOTTOM_ANIM_, "bottomAnim");
  SetAnim(L, progressbar, UIProgressbar::MID_ANIM_, "midAnim");
  SetAnim(L, progressbar, UIProgressbar::TOP_ANIM_, "topAnim");
  SetTextUserData(L, progressbar);

  AddWidget(L, progressbar);

  lua_pushlightuserdata(L, progressbar);

  return 1;
}

int Window_( lua_State* L )
{
  UIWindow* window = new UIWindow;

  SetName(L, window);
  SetTopLeftWidthHeight(L, window);
  SetTooltip(L, window);
  SetAnim(L, window, UIPanel::NORMAL_ANIM_, "normalAnim");
  SetAnim(L, window, UIPanel::DISABLED_ANIM_, "disabledAnim");
  SetTextUserData(L, window);

  AddWidget(L, window);

  // ùرհť

  if (util::HasField(L, "closeBtn"))
  {
    lua_pushstring(L, "closeBtn");
    lua_gettable(L, -2);
    if (lua_istable(L, -1))
      SetButton(L, window->GetCloseButton());
    lua_pop(L, 1);
  }

  lua_pushlightuserdata(L, window);

  return 1;
}

int Widget(lua_State* L)
{
  UIWindow* widget = new UIWindow;

  SetName(L, widget);
  SetTextUserData(L, widget);

  AddWidget(L, widget);

  lua_pushlightuserdata(L, widget);

  return 1;
}
<commit_msg>Fixed bug in int Widget(lua_State* L).<commit_after>#include "ui_lua.h"

#include <lua\lua.hpp>
#include <util\lua_table.h>

#include "image_mgr.h"
#include "script_mgr.h"
#include "soundbuf_mgr.h"
#include "string_mgr.h"
#include "ui_button.h"
#include "ui_label.h"
#include "ui_line.h"
#include "ui_panel.h"
#include "ui_progressbar.h"
#include "ui_window.h"
#include "util_lua.h"
#include "util_sprite.h"

void RegisterUICreators()
{
  ScriptManager& scriptMgr = ScriptManager::GetInstance();

  scriptMgr.RegisterFunc("Button", Button);
  scriptMgr.RegisterFunc("Label", Label);
  scriptMgr.RegisterFunc("Line", Line);
  scriptMgr.RegisterFunc("Panel", Panel);
  scriptMgr.RegisterFunc("Progressbar", Progressbar);
  scriptMgr.RegisterFunc("Widget", Widget);
  scriptMgr.RegisterFunc("Window", Window_);
}

namespace
{
  void SetName(lua_State* L, UIWidget* widget)
  {
    if (util::HasField(L, "name"))
    {
      std::string name = util::GetField_String(L, "name");
      widget->SetName(name);
    }
  }

  void SetTopLeftWidthHeight(lua_State* L, UIWidget* widget)
  {
    if (util::HasField(L, "top") && util::HasField(L, "left"))
    {
      float left = util::GetField_Number(L, "left");
      float top = util::GetField_Number(L, "top");
      widget->SetTopLeft(Vector2f(left, top));
    }

    if (util::HasField(L, "width") && util::HasField(L, "height"))
    {
      float width = util::GetField_Number(L, "width");
      float height = util::GetField_Number(L, "height");
      widget->SetWidthHeight(Vector2f(width, height));
    }
  }

  void SetAnim(lua_State* L, UIWidget* widget, std::string widgetAnimKey, std::string luaAnimFieldKey)
  {
    if (util::HasField(L, luaAnimFieldKey.c_str()))
    {
      std::string imgKey = util::GetField_String(L, luaAnimFieldKey);
      if (!imgKey.empty())
      {
        Animation anim;
        Image& img = ImageManager::GetInstance().GetImage(imgKey);
        SetImage(anim, img);
        widget->SetAnim(widgetAnimKey, anim);
      }
    }
  }

  void SetTooltip(lua_State* L, UIWidget* widget)
  {
    if (util::HasField(L, "tooltipStringKey"))
    {
      std::string tooltipStringKey = util::GetField_String(L, "tooltipStringKey");
      if (!tooltipStringKey.empty())
      {
        String& str = StringManager::GetInstance().GetString(tooltipStringKey);
        widget->SetTooltip(str);
      }
    }

    if (util::HasField(L, "tooltipTopleft"))
    {
      lua_getfield(L, -1, "tooltipTopleft");
      Vector2f topleft;
      SetVector2f(L, topleft);
      lua_pop(L, 1);
      widget->SetTooltipTopLeft(topleft);
    }

    if (util::HasField(L, "useRelativeTooltipTopleft"))
    {
      bool useRelativeTooltipTopleft = util::GetField_Boolean(L, "useRelativeTooltipTopleft");
      widget->SetUseRelativeTooltipTopLeft(useRelativeTooltipTopleft);
    }
  }

  void SetTextUserData(lua_State* L, UIWidget* widget)
  {
    if (util::HasField(L, "textUserData"))
    {
      std::string textUserData = util::GetField_String(L, "textUserData");
      if (!textUserData.empty())
        widget->SetTextUserData(textUserData);
    }
  }

  void SetPressedSoundKey(lua_State* L, UIWidget* widget)
  {
    if (util::HasField(L, "pressedSoundKey"))
      widget->SetPressedSoundKey(util::GetField_String(L, "pressedSoundKey"));
  }

  void AddWidget(lua_State* L, UIWidget* widget)
  {
    lua_pushnil(L);
    while (lua_next(L, -2) != 0)
    {
      if (lua_islightuserdata(L, -1))
      {
        UIWidget* subWidget = static_cast<UIWidget*>(lua_touserdata(L, -1));
        widget->AddWidget(subWidget, subWidget->GetName());
      }

      lua_pop(L, 1);
    }
  }

  void SetButton(lua_State* L, UIButton* btn)
  {
    SetName(L, btn);
    SetTopLeftWidthHeight(L, btn);
    SetAnim(L, btn, UIButton::NORMAL_ANIM_, "normalAnim");
    SetAnim(L, btn, UIButton::HOVERED_ANIM_, "hoveredAnim");
    SetAnim(L, btn, UIButton::PRESSED_ANIM_, "pressedAnim");
    SetAnim(L, btn, UIButton::DISABLED_ANIM_, "disabledAnim");

    AddWidget(L, btn);
  }

}

int Button(lua_State* L)
{
  UIButton* btn = new UIButton;

  SetName(L, btn);
  SetTopLeftWidthHeight(L, btn);
  SetTooltip(L, btn);
  SetAnim(L, btn, UIButton::NORMAL_ANIM_, "normalAnim");
  SetAnim(L, btn, UIButton::HOVERED_ANIM_, "hoveredAnim");
  SetAnim(L, btn, UIButton::PRESSED_ANIM_, "pressedAnim");
  SetAnim(L, btn, UIButton::DISABLED_ANIM_, "disabledAnim");
  SetTextUserData(L, btn);
  SetPressedSoundKey(L, btn);

  AddWidget(L, btn);

  lua_pushlightuserdata(L, btn);

  return 1;
}

int Label(lua_State* L)
{
  UILabel* label = new UILabel;

  SetName(L, label);
  SetTopLeftWidthHeight(L, label);
  SetTooltip(L, label);
  SetTextUserData(L, label);
  SetPressedSoundKey(L, label);

  if (util::HasField(L, "hoveredStyle"))
  {
    int style = util::GetField_Number(L, "hoveredStyle");
    label->SetHoveredStyle(style);
  }

  if (util::HasField(L, "stringKey"))
  {
    std::string stringKey = util::GetField_String(L, "stringKey");
    if (!stringKey.empty())
      label->SetString(StringManager::GetInstance().GetString(stringKey));
  }

  if (util::HasField(L, "color"))
  {
    String& str = label->GetString();
    Color& color = const_cast<Color&>(str.GetColor());
    lua_getfield(L, -1, "color");
    SetColor(L, color);
    lua_pop(L, 1);
  }

  lua_pushlightuserdata(L, label);

  return 1;
}

int Line(lua_State* L)
{
  UILine* line = new UILine;
  SetName(L, line);
  SetTopLeftWidthHeight(L, line);
  SetTooltip(L, line);
  SetTextUserData(L, line);
  lua_pushlightuserdata(L, line);
  return 1;
}

int Panel(lua_State* L)
{
  UIPanel* panel = new UIPanel;

  SetName(L, panel);
  SetTopLeftWidthHeight(L, panel);
  SetTooltip(L, panel);
  SetAnim(L, panel, UIPanel::NORMAL_ANIM_, "normalAnim");
  SetAnim(L, panel, UIPanel::DISABLED_ANIM_, "disabledAnim");
  SetTextUserData(L, panel);

  AddWidget(L, panel);

  lua_pushlightuserdata(L, panel);

  return 1;
}

int Progressbar(lua_State* L)
{
  UIProgressbar* progressbar = new UIProgressbar;

  SetName(L, progressbar);
  SetTopLeftWidthHeight(L, progressbar);
  SetTooltip(L, progressbar);
  SetAnim(L, progressbar, UIProgressbar::BOTTOM_ANIM_, "bottomAnim");
  SetAnim(L, progressbar, UIProgressbar::MID_ANIM_, "midAnim");
  SetAnim(L, progressbar, UIProgressbar::TOP_ANIM_, "topAnim");
  SetTextUserData(L, progressbar);

  AddWidget(L, progressbar);

  lua_pushlightuserdata(L, progressbar);

  return 1;
}

int Window_( lua_State* L )
{
  UIWindow* window = new UIWindow;

  SetName(L, window);
  SetTopLeftWidthHeight(L, window);
  SetTooltip(L, window);
  SetAnim(L, window, UIPanel::NORMAL_ANIM_, "normalAnim");
  SetAnim(L, window, UIPanel::DISABLED_ANIM_, "disabledAnim");
  SetTextUserData(L, window);

  AddWidget(L, window);

  // ùرհť

  if (util::HasField(L, "closeBtn"))
  {
    lua_pushstring(L, "closeBtn");
    lua_gettable(L, -2);
    if (lua_istable(L, -1))
      SetButton(L, window->GetCloseButton());
    lua_pop(L, 1);
  }

  lua_pushlightuserdata(L, window);

  return 1;
}

int Widget(lua_State* L)
{
  UIWidget* widget = new UIWidget;

  SetName(L, widget);
  SetTextUserData(L, widget);

  AddWidget(L, widget);

  lua_pushlightuserdata(L, widget);

  return 1;
}
<|endoftext|>


<commit_before>#ifndef INCLUDE_ACKWARD_CORE_PROPERTY_HPP
#define INCLUDE_ACKWARD_CORE_PROPERTY_HPP

#include <string>

#include <boost/call_traits.hpp>

#include <ackward/core/ExceptionTranslator.hpp>
#include <ackward/core/Object.hpp>

namespace ackward {
namespace core {

/** Property<T> is a value-like C++ interface to an underlying Python
    property. It provides a C++ API for properties which is similar to
    what you get in Python.

    \rst
    General use is like this::

      class MyClass {
      public:
        Property<int> myProperty;
      };
      ...
      MyClass c;
      c.myProperty = 3;
      int x = c.myProperty;

    \endrst
 */
template <typename T>
class Property : private Object
{
public:
    typedef T value_type;

    /** Construct a new property.

        @param obj The underlying Python object.
        @param pythonName The name of the property on `obj`.
     */
    Property(boost::python::object obj,
             const std::string& pythonName) :
        Object (obj),
        pythonName_ (pythonName)
        {}

    /** Get the underlying property value.
     */
    operator value_type ()
        {
            try {
                return boost::python::extract<value_type>(
                    obj().attr(pythonName_));
            } TRANSLATE_PYTHON_EXCEPTION();
        }

    /** Assign to the underlying property.

        @param v The value to assign.
        @returns This object.
     */
    Property<value_type>& operator=(typename boost::call_traits<value_type>::const_reference v)
        {
            try {
                obj().attr(pythonName_) = v;
            } TRANSLATE_PYTHON_EXCEPTION();

            return *this;
        }

    using Object::obj;

private:
    std::string pythonName_;

};

}
}

#endif
<commit_msg>Added ostream operator support to Property.<commit_after>#ifndef INCLUDE_ACKWARD_CORE_PROPERTY_HPP
#define INCLUDE_ACKWARD_CORE_PROPERTY_HPP

#include <iostream>
#include <string>

#include <boost/call_traits.hpp>

#include <ackward/core/ExceptionTranslator.hpp>
#include <ackward/core/Object.hpp>

namespace ackward {
namespace core {

/** Property<T> is a value-like C++ interface to an underlying Python
    property. It provides a C++ API for properties which is similar to
    what you get in Python.

    \rst
    General use is like this::

      class MyClass {
      public:
        Property<int> myProperty;
      };
      ...
      MyClass c;
      c.myProperty = 3;
      int x = c.myProperty;

    \endrst
 */
template <typename T>
class Property : private Object
{
public:
    typedef T value_type;

    /** Construct a new property.

        @param obj The underlying Python object.
        @param pythonName The name of the property on `obj`.
     */
    Property(boost::python::object obj,
             const std::string& pythonName) :
        Object (obj),
        pythonName_ (pythonName)
        {}

    /** Get the underlying property value.
     */
    operator value_type () const
        {
            try {
                return boost::python::extract<value_type>(
                    obj().attr(pythonName_.c_str()));
            } TRANSLATE_PYTHON_EXCEPTION();
        }

    /** Assign to the underlying property.

        @param v The value to assign.
        @returns This object.
     */
    Property<value_type>& operator=(typename boost::call_traits<value_type>::const_reference v)
        {
            try {
                obj().attr(pythonName_.c_str()) = v;
            } TRANSLATE_PYTHON_EXCEPTION();

            return *this;
        }

    using Object::obj;

private:
    std::string pythonName_;

};

template <typename T>
std::ostream& operator<<(std::ostream& os, const Property<T>& p)
{
    os << static_cast<T>(p);
    return os;
}

}
}

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: dx_winstuff.hxx,v $
 * $Revision: 1.3 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _DXCANVAS_WINSTUFF_HXX
#define _DXCANVAS_WINSTUFF_HXX

#include <algorithm>

#include <boost/shared_ptr.hpp>

#include <basegfx/numeric/ftools.hxx>

#ifdef _WINDOWS_
#error someone else included <windows.h>
#endif

// Enabling Direct3D Debug Information Further more, with registry key
// \\HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Direct3D\D3D9Debugging\\EnableCreationStack
// set to 1, sets a backtrace each time an object is created to the
// following global variable: LPCWSTR CreationCallStack
#if OSL_DEBUG_LEVEL > 0
# define D3D_DEBUG_INFO
#endif

#ifndef DIRECTX_VERSION
#error please define for which directx version we should compile
#endif

#if defined _MSC_VER
#pragma warning(push,1)
#endif

#define BOOL win32BOOL
#define INT32 win32INT32
#define UINT32 win32UINT32
#define GradientStyle_RECT win32GradientStyle_RECT
#define Polygon win32Polygon
#define PolyPolygon win32PolyPolygon
#undef WB_LEFT
#undef WB_RIGHT

#define WIN32_LEAN_AND_MEAN
#include <windows.h> // TODO(Q1): extract minimal set of required headers for gdiplus

#if DIRECTX_VERSION < 0x0900

    #include <multimon.h>

    // Be compatible with directdraw 3.0. Lets see how far this takes us
    #define DIRECTDRAW_VERSION 0x0300
    #include <ddraw.h>

    // Be compatible with direct3d 5.0. Lets see how far this takes us
    #define DIRECT3D_VERSION 0x0500
    #define D3D_OVERLOADS
    #include <d3d.h>

    typedef IDirectDrawSurface surface_type;

#else

    #include <d3d9.h>
    #include <d3dx9.h>
    #include <dxerr9.h>

    typedef IDirect3DSurface9 surface_type;

#endif

#undef DrawText

#ifdef __MINGW32__
using ::std::max;
using ::std::min;
#endif

#include <gdiplus.h>

#ifdef min
#   undef min
#endif
#ifdef max
#   undef max
#endif

namespace dxcanvas
{
    // some shared pointer typedefs to Gdiplus objects
    typedef ::boost::shared_ptr< Gdiplus::Graphics >        GraphicsSharedPtr;
    typedef ::boost::shared_ptr< Gdiplus::GraphicsPath >    GraphicsPathSharedPtr;
    typedef ::boost::shared_ptr< Gdiplus::Bitmap >          BitmapSharedPtr;
    typedef ::boost::shared_ptr< Gdiplus::CachedBitmap >    CachedBitmapSharedPtr;
    typedef ::boost::shared_ptr< Gdiplus::Font >            FontSharedPtr;
    typedef ::boost::shared_ptr< Gdiplus::Brush >           BrushSharedPtr;
    typedef ::boost::shared_ptr< Gdiplus::TextureBrush >    TextureBrushSharedPtr;

    /** COM object RAII wrapper

        This template wraps a Windows COM object, transparently
        handling lifetime issues the C++ way (i.e. releasing the
        reference when the object is destroyed)
     */
    template< typename T > class COMReference
    {
    public:
        typedef T Wrappee;

        COMReference() :
            mp( NULL )
        {
        }

        /** Create from raw pointer

            @attention This constructor assumes the interface is
            already acquired (unless p is NULL), no additional AddRef
            is called here.

            This caters e.g. for all DirectX factory methods, which
            return the created interfaces pre-acquired, into a raw
            pointer. Simply pass the pointer to this class, but don't
            call Release manually on it!

            @example IDirectDrawSurface* pSurface;
            pDD->CreateSurface(&aSurfaceDesc, &pSurface, NULL);
            mpSurface = COMReference< IDirectDrawSurface >(pSurface);

         */
        explicit COMReference( T* p ) :
            mp( p )
        {
        }

        COMReference( const COMReference& rNew ) :
            mp( NULL )
        {
            if( rNew.mp == NULL )
                return;

            rNew.mp->AddRef(); // do that _before_ assigning the
                               // pointer. Just in case...
            mp = rNew.mp;
        }

        COMReference& operator=( const COMReference& rRHS )
        {
            COMReference aTmp(rRHS);
            ::std::swap( mp, aTmp.mp );

            return *this;
        }

        ~COMReference()
        {
            reset();
        }

        int reset()
        {
            int refcount = 0;
            if( mp )
                refcount = mp->Release();

            mp = NULL;
            return refcount;
        }

        bool        is() const { return mp != NULL; }
        T*          get() const { return mp; }
        T*          operator->() const { return mp; }
        T&          operator*() const { return *mp; }

    private:
        T*  mp;
    };

    // get_pointer() enables boost::mem_fn to recognize COMReference
    template<class T> inline T * get_pointer(COMReference<T> const& p)
    {
        return p.get();
    }
}

#if defined _MSC_VER
#pragma warning(pop)
#endif

#undef DELETE
#undef BOOL
#undef INT32
#undef UINT32
#undef PolyPolygon

#endif /* _DXCANVAS_WINSTUFF_HXX */
<commit_msg>impress181: #i107614#: fixed build error, dxerr9.h has been renamed to dxerr.h in the latest DirectX SDK from August 2009<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: dx_winstuff.hxx,v $
 * $Revision: 1.3 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _DXCANVAS_WINSTUFF_HXX
#define _DXCANVAS_WINSTUFF_HXX

#include <algorithm>

#include <boost/shared_ptr.hpp>

#include <basegfx/numeric/ftools.hxx>

#ifdef _WINDOWS_
#error someone else included <windows.h>
#endif

// Enabling Direct3D Debug Information Further more, with registry key
// \\HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Direct3D\D3D9Debugging\\EnableCreationStack
// set to 1, sets a backtrace each time an object is created to the
// following global variable: LPCWSTR CreationCallStack
#if OSL_DEBUG_LEVEL > 0
# define D3D_DEBUG_INFO
#endif

#ifndef DIRECTX_VERSION
#error please define for which directx version we should compile
#endif

#if defined _MSC_VER
#pragma warning(push,1)
#endif

#define BOOL win32BOOL
#define INT32 win32INT32
#define UINT32 win32UINT32
#define GradientStyle_RECT win32GradientStyle_RECT
#define Polygon win32Polygon
#define PolyPolygon win32PolyPolygon
#undef WB_LEFT
#undef WB_RIGHT

#define WIN32_LEAN_AND_MEAN
#include <windows.h> // TODO(Q1): extract minimal set of required headers for gdiplus

#if DIRECTX_VERSION < 0x0900

    #include <multimon.h>

    // Be compatible with directdraw 3.0. Lets see how far this takes us
    #define DIRECTDRAW_VERSION 0x0300
    #include <ddraw.h>

    // Be compatible with direct3d 5.0. Lets see how far this takes us
    #define DIRECT3D_VERSION 0x0500
    #define D3D_OVERLOADS
    #include <d3d.h>

    typedef IDirectDrawSurface surface_type;

#else

    #include <d3d9.h>
    #include <d3dx9.h>
//  #include <dxerr9.h>     #i107614# removing include, it has been changed in the latest sdk fron August2009 from dxerr9.h into dxerr.h

    typedef IDirect3DSurface9 surface_type;

#endif

#undef DrawText

#ifdef __MINGW32__
using ::std::max;
using ::std::min;
#endif

#include <gdiplus.h>

#ifdef min
#   undef min
#endif
#ifdef max
#   undef max
#endif

namespace dxcanvas
{
    // some shared pointer typedefs to Gdiplus objects
    typedef ::boost::shared_ptr< Gdiplus::Graphics >        GraphicsSharedPtr;
    typedef ::boost::shared_ptr< Gdiplus::GraphicsPath >    GraphicsPathSharedPtr;
    typedef ::boost::shared_ptr< Gdiplus::Bitmap >          BitmapSharedPtr;
    typedef ::boost::shared_ptr< Gdiplus::CachedBitmap >    CachedBitmapSharedPtr;
    typedef ::boost::shared_ptr< Gdiplus::Font >            FontSharedPtr;
    typedef ::boost::shared_ptr< Gdiplus::Brush >           BrushSharedPtr;
    typedef ::boost::shared_ptr< Gdiplus::TextureBrush >    TextureBrushSharedPtr;

    /** COM object RAII wrapper

        This template wraps a Windows COM object, transparently
        handling lifetime issues the C++ way (i.e. releasing the
        reference when the object is destroyed)
     */
    template< typename T > class COMReference
    {
    public:
        typedef T Wrappee;

        COMReference() :
            mp( NULL )
        {
        }

        /** Create from raw pointer

            @attention This constructor assumes the interface is
            already acquired (unless p is NULL), no additional AddRef
            is called here.

            This caters e.g. for all DirectX factory methods, which
            return the created interfaces pre-acquired, into a raw
            pointer. Simply pass the pointer to this class, but don't
            call Release manually on it!

            @example IDirectDrawSurface* pSurface;
            pDD->CreateSurface(&aSurfaceDesc, &pSurface, NULL);
            mpSurface = COMReference< IDirectDrawSurface >(pSurface);

         */
        explicit COMReference( T* p ) :
            mp( p )
        {
        }

        COMReference( const COMReference& rNew ) :
            mp( NULL )
        {
            if( rNew.mp == NULL )
                return;

            rNew.mp->AddRef(); // do that _before_ assigning the
                               // pointer. Just in case...
            mp = rNew.mp;
        }

        COMReference& operator=( const COMReference& rRHS )
        {
            COMReference aTmp(rRHS);
            ::std::swap( mp, aTmp.mp );

            return *this;
        }

        ~COMReference()
        {
            reset();
        }

        int reset()
        {
            int refcount = 0;
            if( mp )
                refcount = mp->Release();

            mp = NULL;
            return refcount;
        }

        bool        is() const { return mp != NULL; }
        T*          get() const { return mp; }
        T*          operator->() const { return mp; }
        T&          operator*() const { return *mp; }

    private:
        T*  mp;
    };

    // get_pointer() enables boost::mem_fn to recognize COMReference
    template<class T> inline T * get_pointer(COMReference<T> const& p)
    {
        return p.get();
    }
}

#if defined _MSC_VER
#pragma warning(pop)
#endif

#undef DELETE
#undef BOOL
#undef INT32
#undef UINT32
#undef PolyPolygon

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


<commit_before>#ifdef CHANNEL_MKL

#include "Tools/Exception/exception.hpp"

#include "Noise_MKL.hpp"

using namespace aff3ct::tools;

template <typename R>
Noise_MKL<R>
::Noise_MKL(const int seed)
: Noise<R>(), stream_state(nullptr), is_stream_alloc(false)
{
	this->set_seed(seed);
}

template <typename R>
Noise_MKL<R>
::~Noise_MKL()
{
	if (is_stream_alloc)
		vslDeleteStream(&stream_state);
}

template <typename R>
void Noise_MKL<R>
::set_seed(const int seed)
{
	if (is_stream_alloc) vslDeleteStream(&stream_state);

	//vslNewStream(&stream_state, VSL_BRNG_MT2203, seed);
	vslNewStream(&stream_state, VSL_BRNG_SFMT19937, seed);

	is_stream_alloc = true;
}

template <typename R>
void Noise_MKL<R>
::generate(R *noise, const unsigned length, const R sigma, const R mu)
{
	throw runtime_error(__FILE__, __LINE__, __func__, "Adding white Gaussian noise is impossible on this data type.");
}

namespace aff3ct
{
namespace tools
{
template <>
void Noise_MKL<float>
::generate(float *noise, const unsigned length, const float sigma, const R mu)
{
	vsRngGaussian(VSL_RNG_METHOD_GAUSSIAN_BOXMULLER2,
	              stream_state,
	              length,
	              noise,
	              mu,
	              sigma);
	/*
	vsRngGaussian(VSL_RNG_METHOD_GAUSSIAN_ICDF,
	              stream_state,
	              length,
	              noise,
	              mu,
	              sigma);
	*/
}
}
}

namespace aff3ct
{
namespace tools
{
template <>
void Noise_MKL<double>
::generate(double *noise, const unsigned length, const double sigma, const R mu)
{
	vdRngGaussian(VSL_RNG_METHOD_GAUSSIAN_BOXMULLER2,
	              stream_state,
	              length,
	              noise,
	              mu,
	              sigma);
	/*
	vdRngGaussian(VSL_RNG_METHOD_GAUSSIAN_ICDF,
	              stream_state,
	              length,
	              noise,
	              mu,
	              sigma);
	*/
}
}
}

// ==================================================================================== explicit template instantiation
#include "Tools/types.h"
#ifdef MULTI_PREC
template class aff3ct::tools::Noise_MKL<R_32>;
template class aff3ct::tools::Noise_MKL<R_64>;
#else
template class aff3ct::tools::Noise_MKL<R>;
#endif
// ==================================================================================== explicit template instantiation

#endif
<commit_msg>Fix Noise MKL algo specialized generate functions<commit_after>#ifdef CHANNEL_MKL

#include "Tools/Exception/exception.hpp"

#include "Noise_MKL.hpp"

using namespace aff3ct::tools;

template <typename R>
Noise_MKL<R>
::Noise_MKL(const int seed)
: Noise<R>(), stream_state(nullptr), is_stream_alloc(false)
{
	this->set_seed(seed);
}

template <typename R>
Noise_MKL<R>
::~Noise_MKL()
{
	if (is_stream_alloc)
		vslDeleteStream(&stream_state);
}

template <typename R>
void Noise_MKL<R>
::set_seed(const int seed)
{
	if (is_stream_alloc) vslDeleteStream(&stream_state);

	//vslNewStream(&stream_state, VSL_BRNG_MT2203, seed);
	vslNewStream(&stream_state, VSL_BRNG_SFMT19937, seed);

	is_stream_alloc = true;
}

template <typename R>
void Noise_MKL<R>
::generate(R *noise, const unsigned length, const R sigma, const R mu)
{
	throw runtime_error(__FILE__, __LINE__, __func__, "Adding white Gaussian noise is impossible on this data type.");
}

namespace aff3ct
{
namespace tools
{
template <>
void Noise_MKL<float>
::generate(float *noise, const unsigned length, const float sigma, const float mu)
{
	vsRngGaussian(VSL_RNG_METHOD_GAUSSIAN_BOXMULLER2,
	              stream_state,
	              length,
	              noise,
	              mu,
	              sigma);
	/*
	vsRngGaussian(VSL_RNG_METHOD_GAUSSIAN_ICDF,
	              stream_state,
	              length,
	              noise,
	              mu,
	              sigma);
	*/
}
}
}

namespace aff3ct
{
namespace tools
{
template <>
void Noise_MKL<double>
::generate(double *noise, const unsigned length, const double sigma, const double mu)
{
	vdRngGaussian(VSL_RNG_METHOD_GAUSSIAN_BOXMULLER2,
	              stream_state,
	              length,
	              noise,
	              mu,
	              sigma);
	/*
	vdRngGaussian(VSL_RNG_METHOD_GAUSSIAN_ICDF,
	              stream_state,
	              length,
	              noise,
	              mu,
	              sigma);
	*/
}
}
}

// ==================================================================================== explicit template instantiation
#include "Tools/types.h"
#ifdef MULTI_PREC
template class aff3ct::tools::Noise_MKL<R_32>;
template class aff3ct::tools::Noise_MKL<R_64>;
#else
template class aff3ct::tools::Noise_MKL<R>;
#endif
// ==================================================================================== explicit template instantiation

#endif
<|endoftext|>


<commit_before><commit_msg>move log_entry_v4 out of unnamed namespace to make validate-reflection test happy<commit_after><|endoftext|>


<commit_before><commit_msg>[linalg] allow matrix rows to come in non-sorted order.<commit_after><|endoftext|>