<commit_before>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#include <visionaray/cuda/array.h>

namespace visionaray
{

//-------------------------------------------------------------------------------------------------
// CUDA texture1d
//

template <typename T, tex_read_mode ReadMode>
class cuda_texture<T, ReadMode, 1>
{
public:

    using device_type   = typename cuda::map_texel_type<T, ReadMode>::device_type;
    using host_type     = typename cuda::map_texel_type<T, ReadMode>::host_type;

public:

    cuda_texture() = default;

    // Construct from host texture
    template <typename U>
    explicit cuda_texture(texture<U, ReadMode, 1> const& host_tex)
        : width_(host_tex.width())
    {
        if (width_ == 0)
        {
            return;
        }

        cudaChannelFormatDesc desc = cudaCreateChannelDesc<device_type>();

        if ( array_.allocate(desc, width_) != cudaSuccess )
        {
            return;
        }

        if ( upload_data(host_tex.data()) != cudaSuccess )
        {
            return;
        }

        cudaResourceDesc resource_desc;
        memset(&resource_desc, 0, sizeof(resource_desc));
        resource_desc.resType                   = cudaResourceTypeArray;
        resource_desc.res.array.array           = array_.get();

        cudaTextureDesc texture_desc;
        memset(&texture_desc, 0, sizeof(texture_desc));
        texture_desc.addressMode[0]             = detail::map_address_mode( host_tex.get_address_mode(0) );
        texture_desc.filterMode                 = detail::map_filter_mode( host_tex.get_filter_mode() );
        texture_desc.readMode                   = detail::map_read_mode( ReadMode );
        texture_desc.normalizedCoords           = true;

        cudaTextureObject_t obj = 0;
        cudaCreateTextureObject( &obj, &resource_desc, &texture_desc, 0 );
        texture_obj_.reset(obj);std::cerr << cudaGetErrorString(cudaGetLastError()) << std::endl;
    }

#if !VSNRAY_CXX_MSVC
    cuda_texture(cuda_texture&&) = default;
    cuda_texture& operator=(cuda_texture&&) = default;
#else
    cuda_texture(cuda_texture&& rhs)
        : buffer_(std::move(rhs.buffer_))
        , texture_obj_(std::move(rhs.texture_obj_))
        , width_(rhs.width_)
    {
    }

    cuda_texture& operator=(cuda_texture&& rhs)
    {
        buffer_ = std::move(rhs.buffer_);
        texture_obj_ = std::move(rhs.texture_obj_);
        width_ = rhs.width_;

        return *this;
    }
#endif

    // NOT copyable
    cuda_texture(cuda_texture const& rhs) = delete;
    cuda_texture& operator=(cuda_texture const& rhs) = delete;

    cudaTextureObject_t texture_object() const
    {
        return texture_obj_.get();
    }

    size_t width() const
    {
        return width_;
    }

private:

    cuda::array             array_;

    cuda::texture_object    texture_obj_;

    size_t width_;

    cudaError_t upload_data(host_type const* data)
    {
        // Cast from host type to device type
        return array_.upload( reinterpret_cast<device_type const*>(data), width_ * sizeof(device_type) );
    }

    template <typename U>
    cudaError_t upload_data(U const* data)
    {
        // First promote to host type
        aligned_vector<host_type> dst( width_ );

        for (size_t i = 0; i < width_; ++i)
        {
            dst[i] = host_type( data[i] );
        }

        return upload_data( dst.data() );
    }

};

//-------------------------------------------------------------------------------------------------
// CUDA texture1d reference
//

template <typename T, tex_read_mode ReadMode>
class cuda_texture_ref<T, ReadMode, 1>
{
public:

    using device_type = typename cuda::map_texel_type<T, ReadMode>::device_type;
    using host_type   = typename cuda::map_texel_type<T, ReadMode>::host_type;

public:

    VSNRAY_FUNC cuda_texture_ref() = default;

    VSNRAY_CPU_FUNC cuda_texture_ref(cuda_texture<T, ReadMode, 1> const& ref)
        : texture_obj_(ref.texture_object())
        , width_(ref.width())
    {
    }

    VSNRAY_FUNC ~cuda_texture_ref() = default;

    VSNRAY_FUNC cuda_texture_ref& operator=(cuda_texture<T, ReadMode, 1> const& rhs)
    {
        texture_obj_ = rhs.texture_object();
        width_ = rhs.width();
        return *this;
    }

    VSNRAY_FUNC cudaTextureObject_t texture_object() const
    {
        return texture_obj_;
    }

    VSNRAY_FUNC size_t width() const
    {
        return width_;
    }

private:

    cudaTextureObject_t texture_obj_;

    size_t width_;

};

} // visionaray
<commit_msg>Remove debug output<commit_after>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#include <visionaray/cuda/array.h>

namespace visionaray
{

//-------------------------------------------------------------------------------------------------
// CUDA texture1d
//

template <typename T, tex_read_mode ReadMode>
class cuda_texture<T, ReadMode, 1>
{
public:

    using device_type   = typename cuda::map_texel_type<T, ReadMode>::device_type;
    using host_type     = typename cuda::map_texel_type<T, ReadMode>::host_type;

public:

    cuda_texture() = default;

    // Construct from host texture
    template <typename U>
    explicit cuda_texture(texture<U, ReadMode, 1> const& host_tex)
        : width_(host_tex.width())
    {
        if (width_ == 0)
        {
            return;
        }

        cudaChannelFormatDesc desc = cudaCreateChannelDesc<device_type>();

        if ( array_.allocate(desc, width_) != cudaSuccess )
        {
            return;
        }

        if ( upload_data(host_tex.data()) != cudaSuccess )
        {
            return;
        }

        cudaResourceDesc resource_desc;
        memset(&resource_desc, 0, sizeof(resource_desc));
        resource_desc.resType                   = cudaResourceTypeArray;
        resource_desc.res.array.array           = array_.get();

        cudaTextureDesc texture_desc;
        memset(&texture_desc, 0, sizeof(texture_desc));
        texture_desc.addressMode[0]             = detail::map_address_mode( host_tex.get_address_mode(0) );
        texture_desc.filterMode                 = detail::map_filter_mode( host_tex.get_filter_mode() );
        texture_desc.readMode                   = detail::map_read_mode( ReadMode );
        texture_desc.normalizedCoords           = true;

        cudaTextureObject_t obj = 0;
        cudaCreateTextureObject( &obj, &resource_desc, &texture_desc, 0 );
        texture_obj_.reset(obj);
    }

#if !VSNRAY_CXX_MSVC
    cuda_texture(cuda_texture&&) = default;
    cuda_texture& operator=(cuda_texture&&) = default;
#else
    cuda_texture(cuda_texture&& rhs)
        : buffer_(std::move(rhs.buffer_))
        , texture_obj_(std::move(rhs.texture_obj_))
        , width_(rhs.width_)
    {
    }

    cuda_texture& operator=(cuda_texture&& rhs)
    {
        buffer_ = std::move(rhs.buffer_);
        texture_obj_ = std::move(rhs.texture_obj_);
        width_ = rhs.width_;

        return *this;
    }
#endif

    // NOT copyable
    cuda_texture(cuda_texture const& rhs) = delete;
    cuda_texture& operator=(cuda_texture const& rhs) = delete;

    cudaTextureObject_t texture_object() const
    {
        return texture_obj_.get();
    }

    size_t width() const
    {
        return width_;
    }

private:

    cuda::array             array_;

    cuda::texture_object    texture_obj_;

    size_t width_;

    cudaError_t upload_data(host_type const* data)
    {
        // Cast from host type to device type
        return array_.upload( reinterpret_cast<device_type const*>(data), width_ * sizeof(device_type) );
    }

    template <typename U>
    cudaError_t upload_data(U const* data)
    {
        // First promote to host type
        aligned_vector<host_type> dst( width_ );

        for (size_t i = 0; i < width_; ++i)
        {
            dst[i] = host_type( data[i] );
        }

        return upload_data( dst.data() );
    }

};

//-------------------------------------------------------------------------------------------------
// CUDA texture1d reference
//

template <typename T, tex_read_mode ReadMode>
class cuda_texture_ref<T, ReadMode, 1>
{
public:

    using device_type = typename cuda::map_texel_type<T, ReadMode>::device_type;
    using host_type   = typename cuda::map_texel_type<T, ReadMode>::host_type;

public:

    VSNRAY_FUNC cuda_texture_ref() = default;

    VSNRAY_CPU_FUNC cuda_texture_ref(cuda_texture<T, ReadMode, 1> const& ref)
        : texture_obj_(ref.texture_object())
        , width_(ref.width())
    {
    }

    VSNRAY_FUNC ~cuda_texture_ref() = default;

    VSNRAY_FUNC cuda_texture_ref& operator=(cuda_texture<T, ReadMode, 1> const& rhs)
    {
        texture_obj_ = rhs.texture_object();
        width_ = rhs.width();
        return *this;
    }

    VSNRAY_FUNC cudaTextureObject_t texture_object() const
    {
        return texture_obj_;
    }

    VSNRAY_FUNC size_t width() const
    {
        return width_;
    }

private:

    cudaTextureObject_t texture_obj_;

    size_t width_;

};

} // visionaray
<|endoftext|>


<commit_before>#pragma once

#include <algorithm> // copy, equal
#include <initializer_list>
#include <iosfwd>

#include <boost/container/flat_set.hpp>

#include "sdd/dd/context_fwd.hh"
#include "sdd/dd/definition.hh"
#include "sdd/mem/linear_alloc.hh"
#include "sdd/util/hash.hh"

namespace sdd { namespace dd {

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Base class for sum and intersection operations, used by the cache.
/// @tparam Operation The implementation of the sum or intersection algorithm.
///
/// It manages the allocation and deallocation of operands, as well as the dispatch on the
/// correct type (flat or hierarchical node).
template <typename C, typename Operation>
struct LIBSDD_ATTRIBUTE_PACKED nary_op
{
  // Can't copy a nary_op.
  nary_op(const nary_op&) = delete;
  nary_op& operator=(const nary_op&) = delete;

  /// @brief Used by the cache to know the type of the result.
  using result_type = SDD<C>;

  /// @brief Define an iterator on operands.
  using const_iterator = const SDD<C>*;

  /// @brief The dynamically allocated array of operands.
  ///
  /// The concrete type will always be an SDD<C>. We use a raw memory storage as we don't want to
  /// build useless default SDD (the |0| terminal). This storage will be filled by the constructor.
  /// Also, as an operation is moved by the cache, we stick to a pointer (contrary to SDD nodes or
  /// homomorphisms n-ary operations) to avoid to move all operands.
  char* operands;

  /// @brief The number of operands.
  const typename C::operands_size_type size;

  /// @brief Constructor from an nary_builder.
  template <typename Builder>
  nary_op(Builder& builder)
    : operands(new char[builder.size_to_allocate()])
    , size(static_cast<typename C::operands_size_type>(builder.size()))
  {
    // Will place (with a placement new combined with a move) operands in the raw storage.
    builder.consolidate(operands);
  }

  /// @brief Move constructor.
  nary_op(nary_op&& other)
  noexcept
    : operands(other.operands)
    , size(other.size)
  {
    other.operands = nullptr;
  }

  /// @brief Destructor.
  ~nary_op()
  {
    if (operands != nullptr)
    {
      for (auto& operand : *this)
      {
        operand.~SDD<C>();
      }
      delete[] operands;
    }
  }

  /// @brief Get an iterator to the first operand.
  const_iterator
  begin()
  const noexcept
  {
    return reinterpret_cast<const SDD<C>*>(operands);
  }

  /// @brief Get an iterator to the end.
  const_iterator
  end()
  const noexcept
  {
    return reinterpret_cast<const SDD<C>*>(operands) + size;
  }

  /// @brief Apply the operation.
  ///
  /// Called by the cache.
  SDD<C>
  operator()(context<C>& cxt)
  const
  {
    // Compatibility of nodes is checked on the fly by operations.
    // It avoids to perform an iteration only for this task.
    if (mem::is<flat_node<C>>(*begin()))
    {
      return Operation::template work<const_iterator, flat_node<C>>(begin(), end(), cxt);
    }
    else
    {
      return Operation::template work<const_iterator, hierarchical_node<C>>(begin(), end(), cxt);
    }
  }

  friend
  bool
  operator==(const nary_op& lhs, const nary_op& rhs)
  noexcept
  {
    return lhs.size == rhs.size and std::equal(lhs.begin(), lhs.end(), rhs.begin());
  }

  friend
  std::ostream&
  operator<<(std::ostream& os, const nary_op& x)
  {
    os << Operation::symbol << " (";
    std::copy(x.begin(), std::prev(x.end()), std::ostream_iterator<SDD<C>>(os, ", "));
    return os << *std::prev(x.end()) << ")";
  }
};

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Base type for builders of sum and intersection operations.
///
/// The goal of a this builder is ensure that operands are always stored in the same order
/// (to improve cache hits); and to know the exact number of operands in order to allocate the
/// smallest possible memory to store all of them (this allocation is performed in the
/// construction of operations in nary_op).
template <typename C, typename Valuation, typename Builder>
struct LIBSDD_ATTRIBUTE_PACKED nary_builder
  : private Builder
{
  using builder_type = Builder;
  using set_type = boost::container::flat_set< Valuation, std::less<Valuation>
                                             , mem::linear_alloc<Valuation>>;
  using const_iterator = typename set_type::const_iterator;

  /// @brief Sorted container of operands.
  set_type set_;

  /// @brief Default constructor.
  nary_builder(context<C>& cxt)
    : builder_type()
    , set_(std::less<Valuation>(), mem::linear_alloc<Valuation>(cxt.arena()))
  {}

  /// @brief Construction from a list of operands.
  nary_builder(context<C>& cxt, std::initializer_list<Valuation> operands)
    : builder_type()
    , set_(std::less<Valuation>(), mem::linear_alloc<Valuation>(cxt.arena()))
  {
    set_.reserve(operands.size());
    for (const auto& op : operands)
    {
      add(op);
    }
  }

  /// @brief Request for allocation of additional memory.
  void
  reserve(std::size_t size)
  {
    set_.reserve(size);
  }

  /// @brief Add a new operand.
  void
  add(Valuation&& operand)
  {
    builder_type::add(set_, std::move(operand));
  }

  /// @brief Add a new operand.
  void
  add(const Valuation& operand)
  {
    builder_type::add(set_, operand);
  }

  /// @brief Get an iterator to the first operand.
  const_iterator
  begin()
  const noexcept
  {
    return set_.begin();
  }

  /// @brief Get an iterator to the end.
  const_iterator
  end()
  const noexcept
  {
    return set_.end();
  }

  /// @brief Tell if this build doesn't contain any node.
  bool
  empty()
  const noexcept
  {
    return set_.empty();
  }

  /// @brief Get the number of contained elements.
  std::size_t
  size()
  const noexcept
  {
    return set_.size();
  }

  /// @brief Compute the size needed to store all the operands contained by this builder.
  std::size_t
  size_to_allocate()
  const noexcept
  {
    return set_.size() * sizeof(Valuation);
  }

  /// @brief Move operands of this builder to a given memory location.
  /// @param addr shall point to an allocated memory location of the size returned by
  /// size_to_allocate().
  ///
  /// Once performed, all subsequent calls to this instance are invalid.
  void
  consolidate(char* addr)
  noexcept
  {
    Valuation* base = reinterpret_cast<Valuation*>(addr);
    for (auto it = set_.begin(); it != set_.end(); ++it)
    {
      new (base++) Valuation(std::move(*it));
    }
  }
};

/*------------------------------------------------------------------------------------------------*/

}} // namespace sdd::dd

namespace std {

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Hash specialization for sdd::dd::nary_op
template <typename C, typename Operation>
struct hash<sdd::dd::nary_op<C, Operation>>
{
  std::size_t
  operator()(const sdd::dd::nary_op<C, Operation>& op)
  const
  {
    using namespace sdd::hash;
    return seed() (range(op));
  }
};

/*------------------------------------------------------------------------------------------------*/

} // namespace std
<commit_msg>Assert that a nary operation has always more than 1 operand<commit_after>#pragma once

#include <algorithm> // copy, equal
#include <initializer_list>
#include <iosfwd>

#include <boost/container/flat_set.hpp>

#include "sdd/dd/context_fwd.hh"
#include "sdd/dd/definition.hh"
#include "sdd/mem/linear_alloc.hh"
#include "sdd/util/hash.hh"

namespace sdd { namespace dd {

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Base class for sum and intersection operations, used by the cache.
/// @tparam Operation The implementation of the sum or intersection algorithm.
///
/// It manages the allocation and deallocation of operands, as well as the dispatch on the
/// correct type (flat or hierarchical node).
template <typename C, typename Operation>
struct LIBSDD_ATTRIBUTE_PACKED nary_op
{
  // Can't copy a nary_op.
  nary_op(const nary_op&) = delete;
  nary_op& operator=(const nary_op&) = delete;

  /// @brief Used by the cache to know the type of the result.
  using result_type = SDD<C>;

  /// @brief Define an iterator on operands.
  using const_iterator = const SDD<C>*;

  /// @brief The dynamically allocated array of operands.
  ///
  /// The concrete type will always be an SDD<C>. We use a raw memory storage as we don't want to
  /// build useless default SDD (the |0| terminal). This storage will be filled by the constructor.
  /// Also, as an operation is moved by the cache, we stick to a pointer (contrary to SDD nodes or
  /// homomorphisms n-ary operations) to avoid to move all operands.
  char* operands;

  /// @brief The number of operands.
  const typename C::operands_size_type size;

  /// @brief Constructor from an nary_builder.
  template <typename Builder>
  nary_op(Builder& builder)
    : operands(new char[builder.size_to_allocate()])
    , size(static_cast<typename C::operands_size_type>(builder.size()))
  {
    assert(size > 1);
    // Will place (with a placement new combined with a move) operands in the raw storage.
    builder.consolidate(operands);
  }

  /// @brief Move constructor.
  nary_op(nary_op&& other)
  noexcept
    : operands(other.operands)
    , size(other.size)
  {
    other.operands = nullptr;
  }

  /// @brief Destructor.
  ~nary_op()
  {
    if (operands != nullptr)
    {
      for (auto& operand : *this)
      {
        operand.~SDD<C>();
      }
      delete[] operands;
    }
  }

  /// @brief Get an iterator to the first operand.
  const_iterator
  begin()
  const noexcept
  {
    return reinterpret_cast<const SDD<C>*>(operands);
  }

  /// @brief Get an iterator to the end.
  const_iterator
  end()
  const noexcept
  {
    return reinterpret_cast<const SDD<C>*>(operands) + size;
  }

  /// @brief Apply the operation.
  ///
  /// Called by the cache.
  SDD<C>
  operator()(context<C>& cxt)
  const
  {
    // Compatibility of nodes is checked on the fly by operations.
    // It avoids to perform an iteration only for this task.
    if (mem::is<flat_node<C>>(*begin()))
    {
      return Operation::template work<const_iterator, flat_node<C>>(begin(), end(), cxt);
    }
    else
    {
      return Operation::template work<const_iterator, hierarchical_node<C>>(begin(), end(), cxt);
    }
  }

  friend
  bool
  operator==(const nary_op& lhs, const nary_op& rhs)
  noexcept
  {
    return lhs.size == rhs.size and std::equal(lhs.begin(), lhs.end(), rhs.begin());
  }

  friend
  std::ostream&
  operator<<(std::ostream& os, const nary_op& x)
  {
    os << Operation::symbol << " (";
    std::copy(x.begin(), std::prev(x.end()), std::ostream_iterator<SDD<C>>(os, ", "));
    return os << *std::prev(x.end()) << ")";
  }
};

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Base type for builders of sum and intersection operations.
///
/// The goal of a this builder is ensure that operands are always stored in the same order
/// (to improve cache hits); and to know the exact number of operands in order to allocate the
/// smallest possible memory to store all of them (this allocation is performed in the
/// construction of operations in nary_op).
template <typename C, typename Valuation, typename Builder>
struct LIBSDD_ATTRIBUTE_PACKED nary_builder
  : private Builder
{
  using builder_type = Builder;
  using set_type = boost::container::flat_set< Valuation, std::less<Valuation>
                                             , mem::linear_alloc<Valuation>>;
  using const_iterator = typename set_type::const_iterator;

  /// @brief Sorted container of operands.
  set_type set_;

  /// @brief Default constructor.
  nary_builder(context<C>& cxt)
    : builder_type()
    , set_(std::less<Valuation>(), mem::linear_alloc<Valuation>(cxt.arena()))
  {}

  /// @brief Construction from a list of operands.
  nary_builder(context<C>& cxt, std::initializer_list<Valuation> operands)
    : builder_type()
    , set_(std::less<Valuation>(), mem::linear_alloc<Valuation>(cxt.arena()))
  {
    set_.reserve(operands.size());
    for (const auto& op : operands)
    {
      add(op);
    }
  }

  /// @brief Request for allocation of additional memory.
  void
  reserve(std::size_t size)
  {
    set_.reserve(size);
  }

  /// @brief Add a new operand.
  void
  add(Valuation&& operand)
  {
    builder_type::add(set_, std::move(operand));
  }

  /// @brief Add a new operand.
  void
  add(const Valuation& operand)
  {
    builder_type::add(set_, operand);
  }

  /// @brief Get an iterator to the first operand.
  const_iterator
  begin()
  const noexcept
  {
    return set_.begin();
  }

  /// @brief Get an iterator to the end.
  const_iterator
  end()
  const noexcept
  {
    return set_.end();
  }

  /// @brief Tell if this build doesn't contain any node.
  bool
  empty()
  const noexcept
  {
    return set_.empty();
  }

  /// @brief Get the number of contained elements.
  std::size_t
  size()
  const noexcept
  {
    return set_.size();
  }

  /// @brief Compute the size needed to store all the operands contained by this builder.
  std::size_t
  size_to_allocate()
  const noexcept
  {
    return set_.size() * sizeof(Valuation);
  }

  /// @brief Move operands of this builder to a given memory location.
  /// @param addr shall point to an allocated memory location of the size returned by
  /// size_to_allocate().
  ///
  /// Once performed, all subsequent calls to this instance are invalid.
  void
  consolidate(char* addr)
  noexcept
  {
    Valuation* base = reinterpret_cast<Valuation*>(addr);
    for (auto it = set_.begin(); it != set_.end(); ++it)
    {
      new (base++) Valuation(std::move(*it));
    }
  }
};

/*------------------------------------------------------------------------------------------------*/

}} // namespace sdd::dd

namespace std {

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Hash specialization for sdd::dd::nary_op
template <typename C, typename Operation>
struct hash<sdd::dd::nary_op<C, Operation>>
{
  std::size_t
  operator()(const sdd::dd::nary_op<C, Operation>& op)
  const
  {
    using namespace sdd::hash;
    return seed() (range(op));
  }
};

/*------------------------------------------------------------------------------------------------*/

} // namespace std
<|endoftext|>


<commit_before>
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkGLWidget.h"

SkGLWidget::SkGLWidget(SkDebugger* debugger) : QGLWidget() {
    this->setStyleSheet("QWidget {background-color: white; border: 1px solid #cccccc;}");
    fDebugger = debugger;
    fCurIntf = NULL;
    fCurContext = NULL;
    fGpuDevice = NULL;
    fCanvas = NULL;
}

SkGLWidget::~SkGLWidget() {
    SkSafeUnref(fCurIntf);
    SkSafeUnref(fCurContext);
    SkSafeUnref(fGpuDevice);
    SkSafeUnref(fCanvas);
}

void SkGLWidget::initializeGL() {
    fCurIntf = GrGLCreateNativeInterface();
    fCurContext = GrContext::Create(kOpenGL_Shaders_GrEngine, (GrPlatform3DContext) fCurIntf);
    GrRenderTarget* curRenderTarget = fCurContext->createPlatformRenderTarget(getDesc(this->width(), this->height()));
    fGpuDevice = new SkGpuDevice(fCurContext, curRenderTarget);
    fCanvas = new SkCanvas(fGpuDevice);
    curRenderTarget->unref();

    glClearColor(1, 1, 1, 0);
    glClearStencil(0);
    glClear(GL_STENCIL_BUFFER_BIT);
}

void SkGLWidget::resizeGL(int w, int h) {
    GrRenderTarget* curRenderTarget = fCurContext->createPlatformRenderTarget(getDesc(w,h));
    SkSafeUnref(fGpuDevice);
    SkSafeUnref(fCanvas);
    fGpuDevice = new SkGpuDevice(fCurContext, curRenderTarget);
    fCanvas = new SkCanvas(fGpuDevice);
    fDebugger->resize(w, h);
    draw();
}

void SkGLWidget::paintGL() {
    if (!this->isHidden()) {
        glClearColor(1, 1, 1, 0);
        fDebugger->draw(fCanvas);
        // TODO(chudy): Implement an optional flush button in Gui.
        fCanvas->flush();
        emit drawComplete();
    }
}

GrPlatformRenderTargetDesc SkGLWidget::getDesc(int w, int h) {
    GrPlatformRenderTargetDesc desc;
    desc.fWidth = SkScalarRound(this->width());
    desc.fHeight = SkScalarRound(this->height());
    desc.fConfig = kSkia8888_PM_GrPixelConfig;
    GR_GL_GetIntegerv(fCurIntf, GR_GL_SAMPLES, &desc.fSampleCnt);
    GR_GL_GetIntegerv(fCurIntf, GR_GL_STENCIL_BITS, &desc.fStencilBits);
    GrGLint buffer;
    GR_GL_GetIntegerv(fCurIntf, GR_GL_FRAMEBUFFER_BINDING, &buffer);
    desc.fRenderTargetHandle = buffer;

    return desc;
}
<commit_msg>Bug Fix: Fixes incremental drawing in conjunction with the highlighting filter for the OpenGL widget.<commit_after>
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkGLWidget.h"

SkGLWidget::SkGLWidget(SkDebugger* debugger) : QGLWidget() {
    this->setStyleSheet("QWidget {background-color: white; border: 1px solid #cccccc;}");
    fDebugger = debugger;
    fCurIntf = NULL;
    fCurContext = NULL;
    fGpuDevice = NULL;
    fCanvas = NULL;
}

SkGLWidget::~SkGLWidget() {
    SkSafeUnref(fCurIntf);
    SkSafeUnref(fCurContext);
    SkSafeUnref(fGpuDevice);
    SkSafeUnref(fCanvas);
}

void SkGLWidget::initializeGL() {
    fCurIntf = GrGLCreateNativeInterface();
    fCurContext = GrContext::Create(kOpenGL_Shaders_GrEngine, (GrPlatform3DContext) fCurIntf);
    GrRenderTarget* curRenderTarget = fCurContext->createPlatformRenderTarget(getDesc(this->width(), this->height()));
    fGpuDevice = new SkGpuDevice(fCurContext, curRenderTarget);
    fCanvas = new SkCanvas(fGpuDevice);
    curRenderTarget->unref();

    glClearColor(1, 1, 1, 0);
    glClearStencil(0);
    glClear(GL_STENCIL_BUFFER_BIT);
}

void SkGLWidget::resizeGL(int w, int h) {
    GrRenderTarget* curRenderTarget = fCurContext->createPlatformRenderTarget(getDesc(w,h));
    SkSafeUnref(fGpuDevice);
    SkSafeUnref(fCanvas);
    fGpuDevice = new SkGpuDevice(fCurContext, curRenderTarget);
    fCanvas = new SkCanvas(fGpuDevice);
    fDebugger->resize(w, h);
    draw();
}

void SkGLWidget::paintGL() {
    if (!this->isHidden()) {
        fDebugger->draw(fCanvas);
        // TODO(chudy): Implement an optional flush button in Gui.
        fCanvas->flush();
        emit drawComplete();
    }
}

GrPlatformRenderTargetDesc SkGLWidget::getDesc(int w, int h) {
    GrPlatformRenderTargetDesc desc;
    desc.fWidth = SkScalarRound(this->width());
    desc.fHeight = SkScalarRound(this->height());
    desc.fConfig = kSkia8888_PM_GrPixelConfig;
    GR_GL_GetIntegerv(fCurIntf, GR_GL_SAMPLES, &desc.fSampleCnt);
    GR_GL_GetIntegerv(fCurIntf, GR_GL_STENCIL_BITS, &desc.fStencilBits);
    GrGLint buffer;
    GR_GL_GetIntegerv(fCurIntf, GR_GL_FRAMEBUFFER_BINDING, &buffer);
    desc.fRenderTargetHandle = buffer;

    return desc;
}
<|endoftext|>


<commit_before>/*
 * This file is part of the UnTech Editor Suite.
 * Copyright (c) 2016 - 2018, Marcus Rowe <undisbeliever@gmail.com>.
 * Distributed under The MIT License: https://opensource.org/licenses/MIT
 */

#include "mtgraphicsscenes.h"
#include "mttilesetrenderer.h"
#include "mttilesetresourceitem.h"
#include "stampgraphicsitem.h"
#include "gui-qt/metatiles/style.h"
#include "models/metatiles/metatile-tileset.h"

#include <QGraphicsSceneMouseEvent>

using namespace UnTech;
using namespace UnTech::GuiQt;
using namespace UnTech::GuiQt::MetaTiles;

AbstractCursorGraphicsItem::AbstractCursorGraphicsItem()
    : QGraphicsObject()
    , _enableClickDrag(false)
{
    setFlag(ItemSendsGeometryChanges);
    setAcceptHoverEvents(true);
}

void AbstractCursorGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
{
    bool moved = processMouseScenePosition(event->scenePos());

    if (moved && _enableClickDrag && event->button() == Qt::LeftButton) {
        processClick();
    }
}

void AbstractCursorGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
    processMouseScenePosition(event->scenePos());

    if (event->button() == Qt::LeftButton) {
        processClick();
    }
}
<commit_msg>Fix click-drag placing tiles in MT editable scene<commit_after>/*
 * This file is part of the UnTech Editor Suite.
 * Copyright (c) 2016 - 2018, Marcus Rowe <undisbeliever@gmail.com>.
 * Distributed under The MIT License: https://opensource.org/licenses/MIT
 */

#include "mtgraphicsscenes.h"
#include "mttilesetrenderer.h"
#include "mttilesetresourceitem.h"
#include "stampgraphicsitem.h"
#include "gui-qt/metatiles/style.h"
#include "models/metatiles/metatile-tileset.h"

#include <QGraphicsSceneMouseEvent>

using namespace UnTech;
using namespace UnTech::GuiQt;
using namespace UnTech::GuiQt::MetaTiles;

AbstractCursorGraphicsItem::AbstractCursorGraphicsItem()
    : QGraphicsObject()
    , _enableClickDrag(false)
{
    setFlag(ItemSendsGeometryChanges);
    setAcceptHoverEvents(true);
}

void AbstractCursorGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
{
    bool moved = processMouseScenePosition(event->scenePos());

    if (moved && _enableClickDrag && event->buttons() == Qt::LeftButton) {
        processClick();
    }
}

void AbstractCursorGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
    processMouseScenePosition(event->scenePos());

    if (event->button() == Qt::LeftButton) {
        processClick();
    }
}
<|endoftext|>


<commit_before>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "IncrementalJIT.h"

#include "IncrementalExecutor.h"

#include "llvm/Support/DynamicLibrary.h"

using namespace llvm;

namespace {
// Forward cxa_atexit for global d'tors.
static void local_cxa_atexit(void (*func) (void*), void* arg, void* dso) {
  cling::IncrementalExecutor* exe = (cling::IncrementalExecutor*)dso;
  exe->AddAtExitFunc(func, arg);
}

///\brief Memory manager providing the lop-level link to the
/// IncrementalExecutor, handles missing or special / replaced symbols.
class ClingMemoryManager: public SectionMemoryManager {
  cling::IncrementalExecutor& m_exe;

public:
  ClingMemoryManager(cling::IncrementalExecutor& Exe):
    m_exe(Exe) {}

  /// This method returns the address of the specified function or variable
  /// that could not be resolved by getSymbolAddress() or by resolving
  /// possible weak symbols by the ExecutionEngine.
  /// It is used to resolve symbols during module linking.
  uint64_t getMissingSymbolAddress(const std::string &Name) override {
    return (uint64_t) m_exe.NotifyLazyFunctionCreators(Name);
  }

  ///\brief Simply wraps the base class's function setting AbortOnFailure
  /// to false and instead using the error handling mechanism to report it.
  void* getPointerToNamedFunction(const std::string &Name,
                                  bool /*AbortOnFailure*/ =true) override {
    return SectionMemoryManager::getPointerToNamedFunction(Name, false);
  }
};
} // unnamed namespace

namespace cling {

///\brief Memory manager for the OrcJIT layers to resolve symbols from the
/// common IncrementalJIT. I.e. the master of the Orcs.
/// Each ObjectLayer instance has one Azog object.
class Azog: public RTDyldMemoryManager {
  cling::IncrementalJIT& m_jit;

public:
  Azog(cling::IncrementalJIT& Jit): m_jit(Jit) {}

  RTDyldMemoryManager* getExeMM() const { return m_jit.m_ExeMM.get(); }

  uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
                               unsigned SectionID,
                               StringRef SectionName) override {
    uint8_t *Addr =
      getExeMM()->allocateCodeSection(Size, Alignment, SectionID, SectionName);
    m_jit.m_SectionsAllocatedSinceLastLoad.insert(Addr);
    return Addr;
  }

  uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
                               unsigned SectionID, StringRef SectionName,
                               bool IsReadOnly) override {
    uint8_t *Addr = getExeMM()->allocateDataSection(Size, Alignment, SectionID,
                                                    SectionName, IsReadOnly);
    m_jit.m_SectionsAllocatedSinceLastLoad.insert(Addr);
    return Addr;
  }

  void reserveAllocationSpace(uintptr_t CodeSize, uintptr_t DataSizeRO,
                              uintptr_t DataSizeRW) override {
    return getExeMM()->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW);
  }

  bool needsToReserveAllocationSpace() override {
    return getExeMM()->needsToReserveAllocationSpace();
  }

  void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
                        size_t Size) override {
    return getExeMM()->registerEHFrames(Addr, LoadAddr, Size);
  }

  void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr,
                          size_t Size) override {
    return getExeMM()->deregisterEHFrames(Addr, LoadAddr, Size);
  }

  uint64_t getSymbolAddress(const std::string &Name) override {
    return m_jit.getSymbolAddressWithoutMangling(Name);
  }

  void *getPointerToNamedFunction(const std::string &Name,
                                  bool AbortOnFailure = true) override {
    return getExeMM()->getPointerToNamedFunction(Name, AbortOnFailure);
  }

  void notifyObjectLoaded(ExecutionEngine *EE,
                          const object::ObjectFile &O) override {
    return getExeMM()->notifyObjectLoaded(EE, O);
  }

  bool finalizeMemory(std::string *ErrMsg = nullptr) override {
    // Each set of objects loaded will be finalized exactly once, but since
    // symbol lookup during relocation may recursively trigger the
    // loading/relocation of other modules, and since we're forwarding all
    // finalizeMemory calls to a single underlying memory manager, we need to
    // defer forwarding the call on until all necessary objects have been
    // loaded. Otherwise, during the relocation of a leaf object, we will end
    // up finalizing memory, causing a crash further up the stack when we
    // attempt to apply relocations to finalized memory.
    // To avoid finalizing too early, look at how many objects have been
    // loaded but not yet finalized. This is a bit of a hack that relies on
    // the fact that we're lazily emitting object files: The only way you can
    // get more than one set of objects loaded but not yet finalized is if
    // they were loaded during relocation of another set.
    if (m_jit.m_UnfinalizedSections.size() == 1)
      return getExeMM()->finalizeMemory(ErrMsg);
    return false;
  };

  /// This method returns the address of the specified function or variable
  /// that could not be resolved by getSymbolAddress() or by resolving
  /// possible weak symbols by the ExecutionEngine.
  /// It is used to resolve symbols during module linking.
  uint64_t getMissingSymbolAddress(const std::string &Name) override {
    return (uint64_t) m_jit.getParent().NotifyLazyFunctionCreators(Name);
  }

}; // class Azog

IncrementalJIT::IncrementalJIT(IncrementalExecutor& exe,
                               std::unique_ptr<TargetMachine> TM):
  m_Parent(exe),
  m_TM(std::move(TM)),
  m_ExeMM(std::move(llvm::make_unique<ClingMemoryManager>(m_Parent))),
  m_Mang(m_TM->getDataLayout()),
  m_NotifyObjectLoaded(*this), m_NotifyFinalized(*this),
  m_ObjectLayer(ObjectLayerT::CreateRTDyldMMFtor(), m_NotifyObjectLoaded,
                m_NotifyFinalized),
  m_CompileLayer(m_ObjectLayer, SimpleCompiler(*m_TM)),
  m_LazyEmitLayer(m_CompileLayer) {

  // Enable JIT symbol resolution from the binary.
  llvm::sys::DynamicLibrary::LoadLibraryPermanently(0, 0);

// #if MCJIT
//   llvm::EngineBuilder builder(std::move(m));

//   std::string errMsg;
//   builder.setErrorStr(&errMsg);
//   builder.setOptLevel(llvm::CodeGenOpt::Less);
//   builder.setEngineKind(llvm::EngineKind::JIT);
//   std::unique_ptr<llvm::RTDyldMemoryManager>
//     MemMan(new ClingMemoryManager(*this));
//   builder.setMCJITMemoryManager(std::move(MemMan));

//   // EngineBuilder uses default c'ted TargetOptions, too:
//   llvm::TargetOptions TargetOpts;
//   TargetOpts.NoFramePointerElim = 1;
//   TargetOpts.JITEmitDebugInfo = 1;

//   builder.setTargetOptions(TargetOpts);

//   m_engine.reset(builder.create());
//   assert(m_engine && "Cannot create module!");
// #endif
}

uint64_t IncrementalJIT::getSymbolAddressWithoutMangling(llvm::StringRef Name) {
#ifdef __APPLE__
  // Apple adds an extra '_'
# define MANGLE_PREFIX "_"
#else
# define MANGLE_PREFIX ""
#endif
  if (Name == MANGLE_PREFIX "__cxa_atexit") {
    // Rewire __cxa_atexit to ~Interpreter(), thus also global destruction
    // coming from the JIT.
    return (uint64_t)&local_cxa_atexit;
  } else if (Name == MANGLE_PREFIX "__dso_handle") {
    // Provide IncrementalExecutor as the third argument to __cxa_atexit.
    return (uint64_t)&m_Parent;
  }
#undef MANGLE_PREFIX
  if (uint64_t Addr = m_ExeMM->getSymbolAddress(Name))
    return Addr;
  if (uint64_t Addr = m_LazyEmitLayer.getSymbolAddress(Name, false))
    return Addr;

  return 0;
}

size_t IncrementalJIT::addModules(std::vector<llvm::Module*>&& modules) {
  // If this module doesn't have a DataLayout attached then attach the
  // default.
  for (auto&& mod: modules) {
    if (!mod->getDataLayout())
      mod->setDataLayout(m_TM->getDataLayout());
  }

  ModuleSetHandleT MSHandle
    = m_LazyEmitLayer.addModuleSet(std::move(modules),
                                   llvm::make_unique<Azog>(*this));
  m_UnloadPoints.push_back(MSHandle);
  return m_UnloadPoints.size() - 1;
}

// void* IncrementalJIT::finalizeMemory() {
//   for (auto &P : UnfinalizedSections)
//     if (P.second.count(LocalAddress))
//       ObjectLayer.mapSectionAddress(P.first, LocalAddress, TargetAddress);
// }

void IncrementalJIT::removeModules(size_t handle) {
  m_LazyEmitLayer.removeModuleSet(m_UnloadPoints[handle]);
}

}// end namespace cling
<commit_msg>Also symbol lookup needs to remove the leading "_" on MacOS.<commit_after>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "IncrementalJIT.h"

#include "IncrementalExecutor.h"

#include "llvm/Support/DynamicLibrary.h"

#ifdef __APPLE__
// Apple adds an extra '_'
# define MANGLE_PREFIX "_"
#else
# define MANGLE_PREFIX ""
#endif

using namespace llvm;

namespace {
// Forward cxa_atexit for global d'tors.
static void local_cxa_atexit(void (*func) (void*), void* arg, void* dso) {
  cling::IncrementalExecutor* exe = (cling::IncrementalExecutor*)dso;
  exe->AddAtExitFunc(func, arg);
}

///\brief Memory manager providing the lop-level link to the
/// IncrementalExecutor, handles missing or special / replaced symbols.
class ClingMemoryManager: public SectionMemoryManager {
  cling::IncrementalExecutor& m_exe;

public:
  ClingMemoryManager(cling::IncrementalExecutor& Exe):
    m_exe(Exe) {}

  /// This method returns the address of the specified function or variable
  /// that could not be resolved by getSymbolAddress() or by resolving
  /// possible weak symbols by the ExecutionEngine.
  /// It is used to resolve symbols during module linking.
  uint64_t getMissingSymbolAddress(const std::string &Name) override {
    return (uint64_t) m_exe.NotifyLazyFunctionCreators(Name);
  }

  ///\brief Simply wraps the base class's function setting AbortOnFailure
  /// to false and instead using the error handling mechanism to report it.
  void* getPointerToNamedFunction(const std::string &Name,
                                  bool /*AbortOnFailure*/ =true) override {
    return SectionMemoryManager::getPointerToNamedFunction(Name, false);
  }
};
} // unnamed namespace

namespace cling {

///\brief Memory manager for the OrcJIT layers to resolve symbols from the
/// common IncrementalJIT. I.e. the master of the Orcs.
/// Each ObjectLayer instance has one Azog object.
class Azog: public RTDyldMemoryManager {
  cling::IncrementalJIT& m_jit;

public:
  Azog(cling::IncrementalJIT& Jit): m_jit(Jit) {}

  RTDyldMemoryManager* getExeMM() const { return m_jit.m_ExeMM.get(); }

  uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
                               unsigned SectionID,
                               StringRef SectionName) override {
    uint8_t *Addr =
      getExeMM()->allocateCodeSection(Size, Alignment, SectionID, SectionName);
    m_jit.m_SectionsAllocatedSinceLastLoad.insert(Addr);
    return Addr;
  }

  uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
                               unsigned SectionID, StringRef SectionName,
                               bool IsReadOnly) override {
    uint8_t *Addr = getExeMM()->allocateDataSection(Size, Alignment, SectionID,
                                                    SectionName, IsReadOnly);
    m_jit.m_SectionsAllocatedSinceLastLoad.insert(Addr);
    return Addr;
  }

  void reserveAllocationSpace(uintptr_t CodeSize, uintptr_t DataSizeRO,
                              uintptr_t DataSizeRW) override {
    return getExeMM()->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW);
  }

  bool needsToReserveAllocationSpace() override {
    return getExeMM()->needsToReserveAllocationSpace();
  }

  void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
                        size_t Size) override {
    return getExeMM()->registerEHFrames(Addr, LoadAddr, Size);
  }

  void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr,
                          size_t Size) override {
    return getExeMM()->deregisterEHFrames(Addr, LoadAddr, Size);
  }

  uint64_t getSymbolAddress(const std::string &Name) override {
    return m_jit.getSymbolAddressWithoutMangling(Name);
  }

  void *getPointerToNamedFunction(const std::string &Name,
                                  bool AbortOnFailure = true) override {
    return getExeMM()->getPointerToNamedFunction(Name, AbortOnFailure);
  }

  void notifyObjectLoaded(ExecutionEngine *EE,
                          const object::ObjectFile &O) override {
    return getExeMM()->notifyObjectLoaded(EE, O);
  }

  bool finalizeMemory(std::string *ErrMsg = nullptr) override {
    // Each set of objects loaded will be finalized exactly once, but since
    // symbol lookup during relocation may recursively trigger the
    // loading/relocation of other modules, and since we're forwarding all
    // finalizeMemory calls to a single underlying memory manager, we need to
    // defer forwarding the call on until all necessary objects have been
    // loaded. Otherwise, during the relocation of a leaf object, we will end
    // up finalizing memory, causing a crash further up the stack when we
    // attempt to apply relocations to finalized memory.
    // To avoid finalizing too early, look at how many objects have been
    // loaded but not yet finalized. This is a bit of a hack that relies on
    // the fact that we're lazily emitting object files: The only way you can
    // get more than one set of objects loaded but not yet finalized is if
    // they were loaded during relocation of another set.
    if (m_jit.m_UnfinalizedSections.size() == 1)
      return getExeMM()->finalizeMemory(ErrMsg);
    return false;
  };

  /// This method returns the address of the specified function or variable
  /// that could not be resolved by getSymbolAddress() or by resolving
  /// possible weak symbols by the ExecutionEngine.
  /// It is used to resolve symbols during module linking.
  uint64_t getMissingSymbolAddress(const std::string &Name) override {
    std::string NameNoPrefix;
    if (MANGLE_PREFIX[0]
        && !Name.compare(0, strlen(MANGLE_PREFIX), MANGLE_PREFIX))
      NameNoPrefix = Name.substr(strlen(MANGLE_PREFIX), -1);
    else
      NameNoPrefix = std::move(Name);
    return (uint64_t) m_jit.getParent().NotifyLazyFunctionCreators(NameNoPrefix);
  }

}; // class Azog

IncrementalJIT::IncrementalJIT(IncrementalExecutor& exe,
                               std::unique_ptr<TargetMachine> TM):
  m_Parent(exe),
  m_TM(std::move(TM)),
  m_ExeMM(std::move(llvm::make_unique<ClingMemoryManager>(m_Parent))),
  m_Mang(m_TM->getDataLayout()),
  m_NotifyObjectLoaded(*this), m_NotifyFinalized(*this),
  m_ObjectLayer(ObjectLayerT::CreateRTDyldMMFtor(), m_NotifyObjectLoaded,
                m_NotifyFinalized),
  m_CompileLayer(m_ObjectLayer, SimpleCompiler(*m_TM)),
  m_LazyEmitLayer(m_CompileLayer) {

  // Enable JIT symbol resolution from the binary.
  llvm::sys::DynamicLibrary::LoadLibraryPermanently(0, 0);

// #if MCJIT
//   llvm::EngineBuilder builder(std::move(m));

//   std::string errMsg;
//   builder.setErrorStr(&errMsg);
//   builder.setOptLevel(llvm::CodeGenOpt::Less);
//   builder.setEngineKind(llvm::EngineKind::JIT);
//   std::unique_ptr<llvm::RTDyldMemoryManager>
//     MemMan(new ClingMemoryManager(*this));
//   builder.setMCJITMemoryManager(std::move(MemMan));

//   // EngineBuilder uses default c'ted TargetOptions, too:
//   llvm::TargetOptions TargetOpts;
//   TargetOpts.NoFramePointerElim = 1;
//   TargetOpts.JITEmitDebugInfo = 1;

//   builder.setTargetOptions(TargetOpts);

//   m_engine.reset(builder.create());
//   assert(m_engine && "Cannot create module!");
// #endif
}

uint64_t IncrementalJIT::getSymbolAddressWithoutMangling(llvm::StringRef Name) {
  if (Name == MANGLE_PREFIX "__cxa_atexit") {
    // Rewire __cxa_atexit to ~Interpreter(), thus also global destruction
    // coming from the JIT.
    return (uint64_t)&local_cxa_atexit;
  } else if (Name == MANGLE_PREFIX "__dso_handle") {
    // Provide IncrementalExecutor as the third argument to __cxa_atexit.
    return (uint64_t)&m_Parent;
  }
  if (uint64_t Addr = m_ExeMM->getSymbolAddress(Name))
    return Addr;
  if (uint64_t Addr = m_LazyEmitLayer.getSymbolAddress(Name, false))
    return Addr;

  return 0;
}

size_t IncrementalJIT::addModules(std::vector<llvm::Module*>&& modules) {
  // If this module doesn't have a DataLayout attached then attach the
  // default.
  for (auto&& mod: modules) {
    if (!mod->getDataLayout())
      mod->setDataLayout(m_TM->getDataLayout());
  }

  ModuleSetHandleT MSHandle
    = m_LazyEmitLayer.addModuleSet(std::move(modules),
                                   llvm::make_unique<Azog>(*this));
  m_UnloadPoints.push_back(MSHandle);
  return m_UnloadPoints.size() - 1;
}

// void* IncrementalJIT::finalizeMemory() {
//   for (auto &P : UnfinalizedSections)
//     if (P.second.count(LocalAddress))
//       ObjectLayer.mapSectionAddress(P.first, LocalAddress, TargetAddress);
// }

void IncrementalJIT::removeModules(size_t handle) {
  m_LazyEmitLayer.removeModuleSet(m_UnloadPoints[handle]);
}

}// end namespace cling
<|endoftext|>


<commit_before>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium 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.

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

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/
#include <sstream>
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <bh.h>

using namespace std;

void range_filter(bh_ir* bhir)
{
    bh_intp nodes[] = {0};
    cout << "### Range-filter searching through. ndag="<< bhir->ndag  << "." << endl;
    bh_dag_split(bhir, 1, nodes, 0, -1);
    cout << "###" << endl;
}

<commit_msg>filter-range: nothing really...<commit_after>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium 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.

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

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/
#include <sstream>
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <bh.h>

using namespace std;

typedef enum { NONE, RANGE, FUSABLE, STREAMABLE } tag_t;

bh_error void ref_count(bh_ir* bhir, dag)
{
    for(bh_intp i=0; i< bhir->dag_list[dag].nnode; ++i) {
        bh_intp id = bhir->dag_list[dag].node_map[i];
        if (id < 0) {
            id = -1*id-1;
            bh_error err = ref_count(bhir, );
            if (err != BH_SUCCESS)
                return err;
        } else {
            bh_error err = func(&bhir->instr_list[id]);
            if (err != BH_SUCCESS)
                return err;
        }
    }
    return BH_SUCCESS;
}

void range_filter(bh_ir* bhir)
{
    cout << "### range-filter on bhir->ninstr = " << bhir->ninstr << endl;
    for(bh_intp dag=0; dag<bhir->ndag; ++dag) {

        cout << "Looking at dag[" << dag << "] " << dag+1 << " of "<< bhir->ndag << \
                ", containing " << bhir->dag_list[dag].nnode << " node(s)" << endl;

        if (bhir->dag_list[dag].tag != NONE) {      // Already tagged, skipping it.
            cout << "Skipping it..." << endl;
            continue;
        }

        for(bh_intp max_nodes=bhir->dag_list[dag].nnode; max_nodes>0; max_nodes--) {

            bh_intp nodes[] = {0};
            bh_dag_split(bhir, 1, nodes, dag, -1);  // Sub-graphing
            bh_intp dag_idx = bhir->ndag-1;         // Index of sub-graph
            bhir->dag_list[dag_idx].tag = RANGE;    // Tagging

        }
    }
    cout << "###" << endl;
}

<|endoftext|>


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

#include "RangeFilter.hpp"

#include <pdal/util/Utils.hpp>

#include <cctype>
#include <limits>
#include <map>
#include <string>
#include <vector>

namespace pdal
{

static PluginInfo const s_info =
    PluginInfo("filters.range", "Pass only points given a dimension/range.",
               "http://pdal.io/stages/filters.range.html");

CREATE_STATIC_PLUGIN(1, 0, RangeFilter, Filter, s_info)

std::string RangeFilter::getName() const
{
    return s_info.name;
}

namespace
{

RangeFilter::Range parseRange(const std::string& r)
{
    std::string::size_type pos, count;
    bool ilb = true;
    bool iub = true;
    const char *start;
    char *end;
    std::string name;
    double ub, lb;

    try
    {
        pos = 0;
        // Skip leading whitespace.
        count = Utils::extract(r, pos, (int(*)(int))std::isspace);
        pos += count;

        count = Utils::extract(r, pos, (int(*)(int))std::isalpha);
        if (count == 0)
           throw std::string("No dimension name.");
        name = r.substr(pos, count);
        pos += count;

        if (r[pos] == '(')
            ilb = false;
        else if (r[pos] != '[')
            throw std::string("Missing '(' or '['.");
        pos++;

        // Extract lower bound.
        start = r.data() + pos;
        lb = std::strtod(start, &end);
        if (start == end)
            lb = std::numeric_limits<double>::min();
        pos += (end - start);

        if (r[pos] != ':')
            throw std::string("Missing ':' limit separator.");
        pos++;

        start = r.data() + pos;
        ub = std::strtod(start, &end);
        if (start == end)
            ub = std::numeric_limits<double>::max();
        pos += (end - start);

        if (r[pos] == ')')
            iub = false;
        else if (r[pos] != ']')
            throw std::string("Missing ')' or ']'.");
        pos++;

        count = Utils::extract(r, pos, (int(*)(int))std::isspace);
        pos += count;

        if (pos != r.size())
            throw std::string("Invalid characters following valid range.");
    }
    catch (std::string s)
    {
        std::ostringstream oss;
        oss << "filters.range: invalid --limits option: '" << r << "': " << s;
        throw pdal_error(oss.str());
    }
    return RangeFilter::Range(name, lb, ub, ilb, iub);
}

}

void RangeFilter::processOptions(const Options& options)
{
    StringList rangeString = options.getValueOrDefault<StringList>("limits");

    if (rangeString.empty())
        throw pdal_error("filters.range missing required --limits option.");

    for (auto const& r : rangeString)
        m_range_list.push_back(parseRange(r));
}

void RangeFilter::prepared(PointTableRef table)
{
    const PointLayoutPtr layout(table.layout());

    for (auto const& d : m_range_list)
    {
        Dimension::Id::Enum id = layout->findDim(d.m_name);
        if (id == Dimension::Id::Unknown)
        {
            std::ostringstream oss;
            oss << "Invalid dimension name in filters.range --limits "
                "option: '" << d.m_name << "'.";
            throw pdal_error(oss.str());
        }
        m_dimensions_map[id] = d;
    }
}

PointViewSet RangeFilter::run(PointViewPtr inView)
{
    PointViewSet viewSet;
    if (!inView->size())
        return viewSet;

    PointViewPtr outView = inView->makeNew();

    for (PointId i = 0; i < inView->size(); ++i)
    {
        bool keep_point = true;
        for (auto const& d : m_dimensions_map)
        {
            double v = inView->getFieldAs<double>(d.first, i);
            if (d.second.m_inclusive_lower_bound)
            {
                if (v < d.second.m_lower_bound)
                    keep_point = false;
            }
            else
            {
                if (v <= d.second.m_lower_bound)
                    keep_point = false;
            }
            if (d.second.m_inclusive_upper_bound)
            {
                if (v > d.second.m_upper_bound)
                    keep_point = false;
            }
            else
            {
                if (v >= d.second.m_upper_bound)
                    keep_point = false;
            }

            if (keep_point)
                break;
        }
        if (keep_point)
            outView->appendPoint(*inView, i);
    }

    viewSet.insert(outView);

    return viewSet;
}

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

#include "RangeFilter.hpp"

#include <pdal/util/Utils.hpp>

#include <cctype>
#include <limits>
#include <map>
#include <string>
#include <vector>

namespace pdal
{

static PluginInfo const s_info =
    PluginInfo("filters.range", "Pass only points given a dimension/range.",
               "http://pdal.io/stages/filters.range.html");

CREATE_STATIC_PLUGIN(1, 0, RangeFilter, Filter, s_info)

std::string RangeFilter::getName() const
{
    return s_info.name;
}

namespace
{

RangeFilter::Range parseRange(const std::string& r)
{
    std::string::size_type pos, count;
    bool ilb = true;
    bool iub = true;
    const char *start;
    char *end;
    std::string name;
    double ub, lb;

    try
    {
        pos = 0;
        // Skip leading whitespace.
        count = Utils::extract(r, pos, (int(*)(int))std::isspace);
        pos += count;

        count = Utils::extract(r, pos, (int(*)(int))std::isalpha);
        if (count == 0)
           throw std::string("No dimension name.");
        name = r.substr(pos, count);
        pos += count;

        if (r[pos] == '(')
            ilb = false;
        else if (r[pos] != '[')
            throw std::string("Missing '(' or '['.");
        pos++;

        // Extract lower bound.
        start = r.data() + pos;
        lb = std::strtod(start, &end);
        if (start == end)
            lb = std::numeric_limits<double>::min();
        pos += (end - start);

        count = Utils::extract(r, pos, (int(*)(int))std::isspace);
        pos += count;

        if (r[pos] != ':')
            throw std::string("Missing ':' limit separator.");
        pos++;

        start = r.data() + pos;
        ub = std::strtod(start, &end);
        if (start == end)
            ub = std::numeric_limits<double>::max();
        pos += (end - start);

        count = Utils::extract(r, pos, (int(*)(int))std::isspace);
        pos += count;

        if (r[pos] == ')')
            iub = false;
        else if (r[pos] != ']')
            throw std::string("Missing ')' or ']'.");
        pos++;

        count = Utils::extract(r, pos, (int(*)(int))std::isspace);
        pos += count;

        if (pos != r.size())
            throw std::string("Invalid characters following valid range.");
    }
    catch (std::string s)
    {
        std::ostringstream oss;
        oss << "filters.range: invalid --limits option: '" << r << "': " << s;
        throw pdal_error(oss.str());
    }
    return RangeFilter::Range(name, lb, ub, ilb, iub);
}

}

void RangeFilter::processOptions(const Options& options)
{
    StringList rangeString = options.getValueOrDefault<StringList>("limits");

    if (rangeString.empty())
        throw pdal_error("filters.range missing required --limits option.");

    for (auto const& r : rangeString)
        m_range_list.push_back(parseRange(r));
}

void RangeFilter::prepared(PointTableRef table)
{
    const PointLayoutPtr layout(table.layout());

    for (auto const& d : m_range_list)
    {
        Dimension::Id::Enum id = layout->findDim(d.m_name);
        if (id == Dimension::Id::Unknown)
        {
            std::ostringstream oss;
            oss << "Invalid dimension name in filters.range --limits "
                "option: '" << d.m_name << "'.";
            throw pdal_error(oss.str());
        }
        m_dimensions_map[id] = d;
    }
}

PointViewSet RangeFilter::run(PointViewPtr inView)
{
    PointViewSet viewSet;
    if (!inView->size())
        return viewSet;

    PointViewPtr outView = inView->makeNew();

    for (PointId i = 0; i < inView->size(); ++i)
    {
        bool keep_point = true;
        for (auto const& d : m_dimensions_map)
        {
            double v = inView->getFieldAs<double>(d.first, i);
            if (d.second.m_inclusive_lower_bound)
            {
                if (v < d.second.m_lower_bound)
                    keep_point = false;
            }
            else
            {
                if (v <= d.second.m_lower_bound)
                    keep_point = false;
            }
            if (d.second.m_inclusive_upper_bound)
            {
                if (v > d.second.m_upper_bound)
                    keep_point = false;
            }
            else
            {
                if (v >= d.second.m_upper_bound)
                    keep_point = false;
            }

            if (keep_point)
                break;
        }
        if (keep_point)
            outView->appendPoint(*inView, i);
    }

    viewSet.insert(outView);

    return viewSet;
}

} // pdal
<|endoftext|>


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

#include "DecoderStateData.h"
#include "AudioDecoder.h"
//#include "AudioEngineDefines.h"

DecoderStateData::DecoderStateData()
	: mDecoder(NULL), mBufferList(NULL), mTimeStamp(0), mTotalFrames(0), mFramesRendered(0), mFrameToSeek(-1), mKeepDecoding(true), mReadyForCollection(false)
{}

DecoderStateData::DecoderStateData(AudioDecoder *decoder)
	: mDecoder(decoder), mBufferList(NULL), mTimeStamp(0), mFramesRendered(0), mFrameToSeek(-1), mKeepDecoding(true), mReadyForCollection(false)
{
	assert(NULL != decoder);

	// NB: The decoder may return an estimate of the total frames
	mTotalFrames = mDecoder->GetTotalFrames();
}

DecoderStateData::~DecoderStateData()
{
	// Delete the decoder
	if(NULL != mDecoder)
		delete mDecoder, mDecoder = NULL;

	DeallocateBufferList();
}

void DecoderStateData::AllocateBufferList(UInt32 capacityFrames)
{
	DeallocateBufferList();

	AudioStreamBasicDescription formatDescription = mDecoder->GetFormat();

	UInt32 numBuffers = (kAudioFormatFlagIsNonInterleaved & formatDescription.mFormatFlags) ? formatDescription.mChannelsPerFrame : 1;
	UInt32 channelsPerBuffer = numBuffers;

	mBufferList = static_cast<AudioBufferList *>(calloc(1, offsetof(AudioBufferList, mBuffers) + (sizeof(AudioBuffer) * numBuffers)));

	mBufferList->mNumberBuffers = numBuffers;

	for(UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i) {
		mBufferList->mBuffers[i].mData = static_cast<void *>(calloc(capacityFrames, formatDescription.mBytesPerFrame));
		mBufferList->mBuffers[i].mDataByteSize = capacityFrames * formatDescription.mBytesPerFrame;
		mBufferList->mBuffers[i].mNumberChannels = channelsPerBuffer;
	}
}

void DecoderStateData::DeallocateBufferList()
{
	if(NULL != mBufferList) {
		for(UInt32 bufferIndex = 0; bufferIndex < mBufferList->mNumberBuffers; ++bufferIndex)
			free(mBufferList->mBuffers[bufferIndex].mData), mBufferList->mBuffers[bufferIndex].mData = NULL;

		free(mBufferList), mBufferList = NULL;
	}
}
<commit_msg>Fix to correctly set the number of channels per buffer<commit_after>/*
 *  Copyright (C) 2009, 2010 Stephen F. Booth <me@sbooth.org>
 *  All Rights Reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *
 *    - Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    - Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    - Neither the name of Stephen F. Booth nor the names of its
 *      contributors may be used to endorse or promote products derived
 *      from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "DecoderStateData.h"
#include "AudioDecoder.h"
//#include "AudioEngineDefines.h"

DecoderStateData::DecoderStateData()
	: mDecoder(NULL), mBufferList(NULL), mTimeStamp(0), mTotalFrames(0), mFramesRendered(0), mFrameToSeek(-1), mKeepDecoding(true), mReadyForCollection(false)
{}

DecoderStateData::DecoderStateData(AudioDecoder *decoder)
	: mDecoder(decoder), mBufferList(NULL), mTimeStamp(0), mFramesRendered(0), mFrameToSeek(-1), mKeepDecoding(true), mReadyForCollection(false)
{
	assert(NULL != decoder);

	// NB: The decoder may return an estimate of the total frames
	mTotalFrames = mDecoder->GetTotalFrames();
}

DecoderStateData::~DecoderStateData()
{
	// Delete the decoder
	if(NULL != mDecoder)
		delete mDecoder, mDecoder = NULL;

	DeallocateBufferList();
}

void DecoderStateData::AllocateBufferList(UInt32 capacityFrames)
{
	DeallocateBufferList();

	AudioStreamBasicDescription formatDescription = mDecoder->GetFormat();

	UInt32 numBuffers = (kAudioFormatFlagIsNonInterleaved & formatDescription.mFormatFlags) ? formatDescription.mChannelsPerFrame : 1;
	UInt32 channelsPerBuffer = (kAudioFormatFlagIsNonInterleaved & formatDescription.mFormatFlags) ? 1 : formatDescription.mChannelsPerFrame;

	mBufferList = static_cast<AudioBufferList *>(calloc(1, offsetof(AudioBufferList, mBuffers) + (sizeof(AudioBuffer) * numBuffers)));

	mBufferList->mNumberBuffers = numBuffers;

	for(UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i) {
		mBufferList->mBuffers[i].mData = static_cast<void *>(calloc(capacityFrames, formatDescription.mBytesPerFrame));
		mBufferList->mBuffers[i].mDataByteSize = capacityFrames * formatDescription.mBytesPerFrame;
		mBufferList->mBuffers[i].mNumberChannels = channelsPerBuffer;
	}
}

void DecoderStateData::DeallocateBufferList()
{
	if(NULL != mBufferList) {
		for(UInt32 bufferIndex = 0; bufferIndex < mBufferList->mNumberBuffers; ++bufferIndex)
			free(mBufferList->mBuffers[bufferIndex].mData), mBufferList->mBuffers[bufferIndex].mData = NULL;

		free(mBufferList), mBufferList = NULL;
	}
}
<|endoftext|>


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

 The MIT License (MIT)

 Copyright (c) 2015 Dmitry Sovetov

 https://github.com/dmsovetov

 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 <Dreemchest.h>

DC_USE_DREEMCHEST

using namespace Platform;
using namespace Renderer;

static String s_vertexShader =
    "cbuffer Pass     pass     : 0;                                             \n"
    "cbuffer Instance instance : 1;                                             \n"
    "                                                                           \n"
    "varying vec3 v_wsVertex;                                                   \n"
    "varying vec3 v_wsNormal;                                                   \n"
    "                                                                           \n"
    "void main()                                                                \n"
    "{                                                                          \n"
    "   v_wsNormal  = normalize(instance.normal * vec4(gl_Normal, 1.0)).xyz;    \n"
    "   v_wsVertex  = (instance.transform * gl_Vertex).xyz;                     \n"
    "                                                                           \n"
    "   gl_Position = pass.projection * pass.view * vec4(v_wsVertex, 1.0);      \n"
    "}                                                                          \n"
;

static String s_fragmentShader =
    "cbuffer Pass     pass     : 0;                                             \n"
    "cbuffer Instance instance : 1;                                             \n"
    "cbuffer Light    light    : 2;                                             \n"
    "                                                                           \n"
    "uniform samplerCube Texture0;                                              \n"
    "varying vec3 v_wsVertex;                                                   \n"
    "varying vec3 v_wsNormal;                                                   \n"
    "                                                                           \n"
    "vec2 blinn(vec3 light, vec3 normal, vec3 view)                             \n"
    "{                                                                          \n"
    "    float ndotl     = dot(normal, light);                                  \n"
    "    vec3  reflected = light - 2.0 * ndotl * normal;                        \n"
    "    float rdotv     = dot(reflected, view);                                \n"
    "    return vec2(ndotl, rdotv);                                             \n"
    "}                                                                          \n"
    "                                                                           \n"
    "vec2 lit(float ndotl, float rdotv, float m)                                \n"
    "{                                                                          \n"
    "    float diff = max(0.0, ndotl);                                          \n"
    "    float spec = step(0.0, ndotl) * max(0.0, rdotv);                       \n"
    "    return vec2(diff, spec);                                               \n"
    "}                                                                          \n"
    "                                                                           \n"
    "float fresnel(float ndotl, float bias, float pow)                          \n"
    "{                                                                          \n"
    "    float facing = (1.0 - ndotl);                                          \n"
    "    return max(bias + (1.0 - bias) * pow(facing, pow), 0.0);               \n"
    "}                                                                          \n"
    "                                                                           \n"
    "void main()                                                                \n"
    "{                                                                          \n"
    "   vec3  norm  = normalize(v_wsNormal);                                    \n"
    "   vec3  ldir  = normalize(light.position - v_wsVertex);                   \n"
    "   vec3  cdir  = normalize(v_wsVertex - pass.camera);                      \n"
    "   vec3  env   = textureCube(Texture0, reflect(cdir, norm)).rgb;           \n"
    "   vec2  bln   = blinn(ldir, norm, cdir);                                  \n"
    "   vec2  lc    = lit(bln.x, bln.y, 0.95);                                  \n"
    "   float fs    = fresnel(bln.x, 0.2, 5.0);                                 \n"
    "   float fe    = fresnel(dot(-cdir, norm), 0.2, 5.0);                       \n"
    "   float spec  = fs * pow(lc.y, 64.0);                                     \n"
    "   vec3  final = light.color * light.intensity * (lc.x + pow(lc.y, 64.0)); \n"
    "   gl_FragColor = vec4(mix(final, env, fe), 1.0);                          \n"
    "}                                                                          \n"
    ;

struct Pass
{
    Matrix4 projection;
    Matrix4 view;
    Vec3    camera;
    static UniformElement s_layout[];
} s_pass;

UniformElement Pass::s_layout[] =
{
      { "projection", UniformElement::Matrix4, offsetof(Pass, projection) }
    , { "view",       UniformElement::Matrix4, offsetof(Pass, view)       }
    , { "camera",     UniformElement::Vec3,    offsetof(Pass, camera)     }
    , { NULL }
};

struct Instance
{
    Matrix4 transform;
    Matrix4 normal;
    static UniformElement s_layout[];
} s_instance;

UniformElement Instance::s_layout[] =
{
      { "transform", UniformElement::Matrix4, offsetof(Instance, transform) }
    , { "normal",    UniformElement::Matrix4, offsetof(Instance, normal)    }
    , { NULL }
};

struct Light
{
    Vec3    position;
    f32     range;
    Rgb     color;
    f32     intensity;
    static UniformElement s_layout[];
} s_light;

UniformElement Light::s_layout[] =
{
      { "position",  UniformElement::Vec3,  offsetof(Light, position)  }
    , { "range",     UniformElement::Float, offsetof(Light, range)     }
    , { "color",     UniformElement::Vec3,  offsetof(Light, color)     }
    , { "intensity", UniformElement::Float, offsetof(Light, intensity) }
    , { NULL }
};

class PointLights : public RenderingApplicationDelegate
{
    struct Object
    {
        MeshLoader::Descriptor  mesh;
        StateBlock              states;
    };

    StateBlock  m_renderStates;
    RenderFrame m_renderFrame;
    Object      m_platform;
    Object      m_bunny;
    ConstantBuffer_ m_instanceConstantBuffer;
    ConstantBuffer_ m_passConstantBuffer;
    ConstantBuffer_ m_lightConstantBuffer;

    virtual void handleLaunched(Application* application) NIMBLE_OVERRIDE
    {
        Logger::setStandardLogger();

        if (!initialize(800 / 3, 600 / 3))
        {
            application->quit(-1);
        }

        // First initialize objects that will be rendered
        initializeObjectFromMesh("Assets/Meshes/platform.obj", m_platform);
        initializeObjectFromMesh("Assets/Meshes/bunny_decimated.obj", m_bunny);

        static const Vec3 s_cameraPos    = Vec3(0.0f, 2.0f, -2.0f);
        static const Vec3 s_cameraTarget = Vec3(0.0f, 0.6f,  0.0f);

        // Configure pass constant buffer
        {
            s_pass.projection = Matrix4::perspective(60.0f, m_window->aspectRatio(), 0.1f, 100.0f);
            s_pass.view       = Matrix4::lookAt(s_cameraPos, s_cameraTarget, Vec3(0.0f, 1.0f, 0.0f));
            s_pass.camera     = s_cameraPos;
            UniformLayout uniformLayout = m_renderingContext->requestUniformLayout("Pass", Pass::s_layout);
            m_passConstantBuffer = m_renderingContext->requestConstantBuffer(&s_pass, sizeof(s_pass), uniformLayout);
            m_renderStates.bindConstantBuffer(m_passConstantBuffer, 0);
        }

        // Configure instance constant buffer
        {
            UniformLayout uniformLayout = m_renderingContext->requestUniformLayout("Instance", Instance::s_layout);
            m_instanceConstantBuffer = m_renderingContext->requestConstantBuffer(&s_instance, sizeof(s_instance), uniformLayout);
            m_renderStates.bindConstantBuffer(m_instanceConstantBuffer, 1);
        }

        // Configure a light constant buffer
        {
            s_light.position  = Vec3(-1.0f, 1.0f, -1.0f);
            s_light.color     = Rgb(1.0f, 1.0f, 1.0f);
            s_light.intensity = 1.0f;
            s_light.range     = 1.0f;
            UniformLayout uniformLayout = m_renderingContext->requestUniformLayout("Light", Light::s_layout);
            m_lightConstantBuffer = m_renderingContext->requestConstantBuffer(&s_light, sizeof(s_light), uniformLayout);
        }

        {
            static ImageLoader::CubeMap cubeMap = ImageLoader::cubeFromDds("Assets/Textures/coast2.dds");
            Texture_ envmap = m_renderingContext->requestTextureCube(&cubeMap.pixels[0], cubeMap.size, cubeMap.mipLevels, cubeMap.format);
            m_bunny.states.bindTexture(envmap, 0);
        }

        // Create a simple shader program
        Program program = m_renderingContext->requestProgram(s_vertexShader, s_fragmentShader);
        m_renderStates.bindProgram(program);
        m_renderStates.setColorMask(ColorMaskAll);
        m_renderStates.setDepthState(LessEqual, true);
        m_renderStates.disableStencilTest();
        m_renderStates.disableBlending();
        m_renderStates.setCullFace(TriangleFaceBack);
    }

    virtual void handleRenderFrame(const Window::Update& e) NIMBLE_OVERRIDE
    {
        m_renderFrame.clear();

        CommandBuffer& commands = m_renderFrame.entryPoint();

        // In this sample we will use a state stack
        StateStack& states = m_renderFrame.stateStack();

        // Push the default state
        StateScope defaultScope = states.push(&m_renderStates);

        // Light pass scope
        StateScope lightScope = states.newScope();
        lightScope->bindConstantBuffer(m_lightConstantBuffer, 2);

        f32 time = currentTime() * 0.001f;

        // Update light parameters
        {
            f32 st           = sinf(time);
            f32 ct           = cosf(time);
            s_light.color    = Rgb(st, 1.0f, ct);
            commands.uploadConstantBuffer(m_lightConstantBuffer, &s_light, sizeof(s_light));
        }

        // Update pass parameters
        {
            commands.uploadConstantBuffer(m_passConstantBuffer, &s_pass, sizeof(s_pass));
        }

        // Clear the viewport
        commands.clear(Rgba(0.3f, 0.3f, 0.3f), ClearAll);

        // Render the platform
        renderObject(states, commands, m_platform, Matrix4());

        const Vec3 position = Vec3(0.0f, 0.0f, 0.0f);
        const Vec3 scale    = Vec3(0.9f, 0.9f, 0.9f);

        // Finally render the stanford bunny
        renderObject(states, commands, m_bunny, Matrix4::rotateXY(0.0f, time * 0.5f) * Matrix4::translation(position) * Matrix4::scale(scale));

        m_renderingContext->display(m_renderFrame);
    }

    void initializeObjectFromMesh(const String& fileName, Object& object)
    {
        object.mesh = MeshLoader::objFromFile(fileName);

        VertexFormat vertexFormat  = object.mesh.vertexFormat;
        InputLayout inputLayout    = m_renderingContext->requestInputLayout(vertexFormat);
        VertexBuffer_ vertexBuffer = m_renderingContext->requestVertexBuffer(&object.mesh.vertices[0], object.mesh.vertices.size());

        object.states.bindInputLayout(inputLayout);
        object.states.bindVertexBuffer(vertexBuffer);

        if (object.mesh.indices.size())
        {
            IndexBuffer_ indexBuffer = m_renderingContext->requestIndexBuffer(&object.mesh.indices[0], sizeof(u16) * object.mesh.indices.size());
            object.states.bindIndexBuffer(indexBuffer);
        }
    }

    void renderObject(StateStack& states, CommandBuffer& commands, const Object& object, const Matrix4& transform)
    {
        StateScope instanceState = states.push(&object.states);
        s_instance.transform = transform;
        s_instance.normal = transform.inversed().transposed();
        commands.uploadConstantBuffer(m_instanceConstantBuffer, m_renderFrame.internBuffer(&s_instance, sizeof(s_instance)), sizeof(s_instance));
        commands.drawPrimitives(0, object.mesh.primitives, 0, object.mesh.vertices.size(), states);
    }
};

dcDeclareApplication(new PointLights)
<commit_msg>Modified: IBL example<commit_after>/**************************************************************************

 The MIT License (MIT)

 Copyright (c) 2015 Dmitry Sovetov

 https://github.com/dmsovetov

 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 <Dreemchest.h>

DC_USE_DREEMCHEST

using namespace Platform;
using namespace Renderer;

static String s_vertexShader =
    "cbuffer Pass     pass     : 0;                                             \n"
    "cbuffer Instance instance : 1;                                             \n"
    "                                                                           \n"
    "varying vec3 v_wsVertex;                                                   \n"
    "varying vec3 v_wsNormal;                                                   \n"
    "                                                                           \n"
    "void main()                                                                \n"
    "{                                                                          \n"
    "   v_wsNormal  = normalize(instance.normal * vec4(gl_Normal, 1.0)).xyz;    \n"
    "   v_wsVertex  = (instance.transform * gl_Vertex).xyz;                     \n"
    "                                                                           \n"
    "   gl_Position = pass.projection * pass.view * vec4(v_wsVertex, 1.0);      \n"
    "}                                                                          \n"
;

static String s_fragmentShader =
    "cbuffer Pass     pass     : 0;                                             \n"
    "cbuffer Instance instance : 1;                                             \n"
    "cbuffer Light    light    : 2;                                             \n"
    "                                                                           \n"
    "uniform samplerCube Texture0;                                              \n"
    "varying vec3 v_wsVertex;                                                   \n"
    "varying vec3 v_wsNormal;                                                   \n"
    "                                                                           \n"
    "vec2 blinn(vec3 light, vec3 normal, vec3 view)                             \n"
    "{                                                                          \n"
    "    float ndotl     = dot(normal, light);                                  \n"
    "    vec3  reflected = light - 2.0 * ndotl * normal;                        \n"
    "    float rdotv     = dot(reflected, view);                                \n"
    "    return vec2(ndotl, rdotv);                                             \n"
    "}                                                                          \n"
    "                                                                           \n"
    "vec2 lit(float ndotl, float rdotv, float m)                                \n"
    "{                                                                          \n"
    "    float diff = max(0.0, ndotl);                                          \n"
    "    float spec = step(0.0, ndotl) * max(0.0, rdotv);                       \n"
    "    return vec2(diff, spec);                                               \n"
    "}                                                                          \n"
    "                                                                           \n"
    "float fresnel(float ndotl, float reflectance, float pow)                   \n"
    "{                                                                          \n"
    "    float facing = (1.0 - ndotl);                                          \n"
    "    return max(reflectance + (1.0 - reflectance) * pow(facing, pow), 0.0); \n"
    "}                                                                          \n"
    "                                                                           \n"
    "const float Eta = 0.66; // Ratio of indices of refraction                  \n"
    "const float F = ((1.0-Eta) * (1.0-Eta)) / ((1.0+Eta) * (1.0+Eta));         \n"
    "                                                                           \n"
    "void main()                                                                \n"
    "{                                                                          \n"
    "   vec3  norm  = normalize(v_wsNormal);                                    \n"
    "   vec3  ldir  = normalize(light.position - v_wsVertex);                   \n"
    "   vec3  cdir  = normalize(v_wsVertex - pass.camera);                      \n"
    "   vec3  env   = textureCube(Texture0, reflect(cdir, norm)).rgb;           \n"
    "   vec2  bln   = blinn(ldir, norm, cdir);                                  \n"
    "   vec2  lc    = lit(bln.x, bln.y, 0.95);                                  \n"
    "   float fs    = fresnel(bln.x, 0.2, 5.0);                                 \n"
    "   float fe    = fresnel(dot(-cdir, norm), F, 2.0);                        \n"
    "   float spec  = fs * pow(lc.y, 64.0);                                     \n"
    "   vec3  final = light.color * light.intensity * (lc.x + pow(lc.y, 64.0)); \n"
    "   gl_FragColor = vec4(mix(final, env, fe), 1.0);                          \n"
    "}                                                                          \n"
    ;

struct Pass
{
    Matrix4 projection;
    Matrix4 view;
    Vec3    camera;
    static UniformElement s_layout[];
} s_pass;

UniformElement Pass::s_layout[] =
{
      { "projection", UniformElement::Matrix4, offsetof(Pass, projection) }
    , { "view",       UniformElement::Matrix4, offsetof(Pass, view)       }
    , { "camera",     UniformElement::Vec3,    offsetof(Pass, camera)     }
    , { NULL }
};

struct Instance
{
    Matrix4 transform;
    Matrix4 normal;
    static UniformElement s_layout[];
} s_instance;

UniformElement Instance::s_layout[] =
{
      { "transform", UniformElement::Matrix4, offsetof(Instance, transform) }
    , { "normal",    UniformElement::Matrix4, offsetof(Instance, normal)    }
    , { NULL }
};

struct Light
{
    Vec3    position;
    f32     range;
    Rgb     color;
    f32     intensity;
    static UniformElement s_layout[];
} s_light;

UniformElement Light::s_layout[] =
{
      { "position",  UniformElement::Vec3,  offsetof(Light, position)  }
    , { "range",     UniformElement::Float, offsetof(Light, range)     }
    , { "color",     UniformElement::Vec3,  offsetof(Light, color)     }
    , { "intensity", UniformElement::Float, offsetof(Light, intensity) }
    , { NULL }
};

class PointLights : public RenderingApplicationDelegate
{
    struct Object
    {
        MeshLoader::Descriptor  mesh;
        StateBlock              states;
    };

    StateBlock  m_renderStates;
    RenderFrame m_renderFrame;
    Object      m_platform;
    Object      m_bunny;
    ConstantBuffer_ m_instanceConstantBuffer;
    ConstantBuffer_ m_passConstantBuffer;
    ConstantBuffer_ m_lightConstantBuffer;

    virtual void handleLaunched(Application* application) NIMBLE_OVERRIDE
    {
        Logger::setStandardLogger();

        if (!initialize(800, 600))
        {
            application->quit(-1);
        }

        // First initialize objects that will be rendered
        initializeObjectFromMesh("Assets/Meshes/platform.obj", m_platform);
        initializeObjectFromMesh("Assets/Meshes/bunny_decimated.obj", m_bunny);

        static const Vec3 s_cameraPos    = Vec3(0.0f, 2.0f, -2.0f);
        static const Vec3 s_cameraTarget = Vec3(0.0f, 0.6f,  0.0f);

        // Configure pass constant buffer
        {
            s_pass.projection = Matrix4::perspective(60.0f, m_window->aspectRatio(), 0.1f, 100.0f);
            s_pass.view       = Matrix4::lookAt(s_cameraPos, s_cameraTarget, Vec3(0.0f, 1.0f, 0.0f));
            s_pass.camera     = s_cameraPos;
            UniformLayout uniformLayout = m_renderingContext->requestUniformLayout("Pass", Pass::s_layout);
            m_passConstantBuffer = m_renderingContext->requestConstantBuffer(&s_pass, sizeof(s_pass), uniformLayout);
            m_renderStates.bindConstantBuffer(m_passConstantBuffer, 0);
        }

        // Configure instance constant buffer
        {
            UniformLayout uniformLayout = m_renderingContext->requestUniformLayout("Instance", Instance::s_layout);
            m_instanceConstantBuffer = m_renderingContext->requestConstantBuffer(&s_instance, sizeof(s_instance), uniformLayout);
            m_renderStates.bindConstantBuffer(m_instanceConstantBuffer, 1);
        }

        // Configure a light constant buffer
        {
            s_light.position  = Vec3(-1.0f, 1.0f, -1.0f);
            s_light.color     = Rgb(1.0f, 1.0f, 1.0f);
            s_light.intensity = 1.0f;
            s_light.range     = 1.0f;
            UniformLayout uniformLayout = m_renderingContext->requestUniformLayout("Light", Light::s_layout);
            m_lightConstantBuffer = m_renderingContext->requestConstantBuffer(&s_light, sizeof(s_light), uniformLayout);
        }

        {
            static ImageLoader::CubeMap cubeMap = ImageLoader::cubeFromDds("Assets/Textures/coast2.dds");
            Texture_ envmap = m_renderingContext->requestTextureCube(&cubeMap.pixels[0], cubeMap.size, cubeMap.mipLevels, cubeMap.format);
            m_bunny.states.bindTexture(envmap, 0);
        }

        // Create a simple shader program
        Program program = m_renderingContext->requestProgram(s_vertexShader, s_fragmentShader);
        m_renderStates.bindProgram(program);
        m_renderStates.setColorMask(ColorMaskAll);
        m_renderStates.setDepthState(LessEqual, true);
        m_renderStates.disableStencilTest();
        m_renderStates.disableBlending();
        m_renderStates.setCullFace(TriangleFaceBack);
    }

    virtual void handleRenderFrame(const Window::Update& e) NIMBLE_OVERRIDE
    {
        m_renderFrame.clear();

        CommandBuffer& commands = m_renderFrame.entryPoint();

        // In this sample we will use a state stack
        StateStack& states = m_renderFrame.stateStack();

        // Push the default state
        StateScope defaultScope = states.push(&m_renderStates);

        // Light pass scope
        StateScope lightScope = states.newScope();
        lightScope->bindConstantBuffer(m_lightConstantBuffer, 2);

        f32 time = currentTime() * 0.001f;

        // Update light parameters
        {
            f32 st           = sinf(time);
            f32 ct           = cosf(time);
            s_light.color    = Rgb(st, 1.0f, ct);
            commands.uploadConstantBuffer(m_lightConstantBuffer, &s_light, sizeof(s_light));
        }

        // Update pass parameters
        {
            commands.uploadConstantBuffer(m_passConstantBuffer, &s_pass, sizeof(s_pass));
        }

        // Clear the viewport
        commands.clear(Rgba(0.3f, 0.3f, 0.3f), ClearAll);

        // Render the platform
        renderObject(states, commands, m_platform, Matrix4());

        const Vec3 position = Vec3(0.0f, 0.0f, 0.0f);
        const Vec3 scale    = Vec3(0.9f, 0.9f, 0.9f);

        // Finally render the stanford bunny
        renderObject(states, commands, m_bunny, Matrix4::rotateXY(0.0f, time * 0.5f) * Matrix4::translation(position) * Matrix4::scale(scale));

        m_renderingContext->display(m_renderFrame);
    }

    void initializeObjectFromMesh(const String& fileName, Object& object)
    {
        object.mesh = MeshLoader::objFromFile(fileName);

        VertexFormat vertexFormat  = object.mesh.vertexFormat;
        InputLayout inputLayout    = m_renderingContext->requestInputLayout(vertexFormat);
        VertexBuffer_ vertexBuffer = m_renderingContext->requestVertexBuffer(&object.mesh.vertices[0], object.mesh.vertices.size());

        object.states.bindInputLayout(inputLayout);
        object.states.bindVertexBuffer(vertexBuffer);

        if (object.mesh.indices.size())
        {
            IndexBuffer_ indexBuffer = m_renderingContext->requestIndexBuffer(&object.mesh.indices[0], sizeof(u16) * object.mesh.indices.size());
            object.states.bindIndexBuffer(indexBuffer);
        }
    }

    void renderObject(StateStack& states, CommandBuffer& commands, const Object& object, const Matrix4& transform)
    {
        StateScope instanceState = states.push(&object.states);
        s_instance.transform = transform;
        s_instance.normal = transform.inversed().transposed();
        commands.uploadConstantBuffer(m_instanceConstantBuffer, m_renderFrame.internBuffer(&s_instance, sizeof(s_instance)), sizeof(s_instance));
        commands.drawPrimitives(0, object.mesh.primitives, 0, object.mesh.vertices.size(), states);
    }
};

dcDeclareApplication(new PointLights)
<|endoftext|>