<commit_before>//  (C) Copyright Gennadiy Rozental 2001-2005.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : simple facility that mimmic notion of read-only read-write
//  properties in C++ classes. Original idea by Henrik Ravn.
// ***************************************************************************

#ifndef BOOST_TEST_CLASS_PROPERTIES_HPP_071894GER
#define BOOST_TEST_CLASS_PROPERTIES_HPP_071894GER

// Boost.Test
#include <boost/test/detail/config.hpp>

// Boost
#if !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))
#include <boost/preprocessor/seq/for_each.hpp>
#endif
#include <boost/call_traits.hpp>
#include <boost/type_traits/add_pointer.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/utility/addressof.hpp>

// STL
#include <iosfwd>

#include <boost/test/detail/suppress_warnings.hpp>

//____________________________________________________________________________//

namespace boost {

namespace unit_test {

// ************************************************************************** //
// **************                 class_property               ************** //
// ************************************************************************** //

template<class PropertyType>
class class_property {
protected:
    typedef typename call_traits<PropertyType>::const_reference read_access_t;
    typedef typename call_traits<PropertyType>::param_type      write_param_t;
    typedef typename add_pointer<PropertyType const>::type      address_res_t;

public:
    // Constructor
                    class_property() : value( PropertyType() ) {}
    explicit        class_property( write_param_t init_value )
    : value( init_value ) {}

    // Access methods
    operator        read_access_t() const   { return value; }
    read_access_t   get() const             { return value; }
    bool            operator!() const       { return !value; }
    address_res_t   operator&() const       { return &value; }

    // Data members
#ifndef BOOST_TEST_NO_PROTECTED_USING
protected:
#endif
    PropertyType        value;
};

//____________________________________________________________________________//

#ifdef BOOST_CLASSIC_IOSTREAMS

template<class PropertyType>
inline std::ostream&
operator<<( std::ostream& os, class_property<PropertyType> const& p )

#else

template<typename CharT1, typename Tr,class PropertyType>
inline std::basic_ostream<CharT1,Tr>&
operator<<( std::basic_ostream<CharT1,Tr>& os, class_property<PropertyType> const& p )

#endif
{
    return os << p.get();
}

//____________________________________________________________________________//

#define DEFINE_PROPERTY_FREE_BINARY_OPERATOR( op )                              \
template<class PropertyType>                                                    \
inline bool                                                                     \
operator op( PropertyType const& lhs, class_property<PropertyType> const& rhs ) \
{                                                                               \
    return lhs op rhs.get();                                                    \
}                                                                               \
template<class PropertyType>                                                    \
inline bool                                                                     \
operator op( class_property<PropertyType> const& lhs, PropertyType const& rhs ) \
{                                                                               \
    return lhs.get() op rhs;                                                    \
}                                                                               \
template<class PropertyType>                                                    \
inline bool                                                                     \
operator op( class_property<PropertyType> const& lhs,                           \
             class_property<PropertyType> const& rhs )                          \
{                                                                               \
    return lhs.get() op rhs.get();                                              \
}                                                                               \
/**/

DEFINE_PROPERTY_FREE_BINARY_OPERATOR( == )
DEFINE_PROPERTY_FREE_BINARY_OPERATOR( != )

#undef DEFINE_PROPERTY_FREE_BINARY_OPERATOR

#if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)

#define DEFINE_PROPERTY_LOGICAL_OPERATOR( op )                                  \
template<class PropertyType>                                                    \
inline bool                                                                     \
operator op( bool b, class_property<PropertyType> const& p )                    \
{                                                                               \
    return b op p.get();                                                        \
}                                                                               \
template<class PropertyType>                                                    \
inline bool                                                                     \
operator op( class_property<PropertyType> const& p, bool b )                    \
{                                                                               \
    return b op p.get();                                                        \
}                                                                               \
/**/

DEFINE_PROPERTY_LOGICAL_OPERATOR( && )
DEFINE_PROPERTY_LOGICAL_OPERATOR( || )

#endif

// ************************************************************************** //
// **************               readonly_property              ************** //
// ************************************************************************** //

template<class PropertyType>
class readonly_property : public class_property<PropertyType> {
    typedef class_property<PropertyType>         base_prop;
    typedef typename base_prop::address_res_t    arrow_res_t;
protected:
    typedef typename base_prop::write_param_t    write_param_t;
public:
    // Constructor
                    readonly_property() {}
    explicit        readonly_property( write_param_t init_value ) : base_prop( init_value ) {}

    // access methods
    arrow_res_t     operator->() const      { return boost::addressof( base_prop::value ); }
};

//____________________________________________________________________________//

#if BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))

#define BOOST_READONLY_PROPERTY( property_type, friends ) boost::unit_test::readwrite_property<property_type >

#else

#define BOOST_READONLY_PROPERTY_DECLARE_FRIEND(r, data, elem) friend class elem;

#define BOOST_READONLY_PROPERTY( property_type, friends )                           \
class BOOST_JOIN( readonly_property, __LINE__ )                                     \
: public boost::unit_test::readonly_property<property_type > {                      \
    typedef boost::unit_test::readonly_property<property_type > base_prop;          \
    BOOST_PP_SEQ_FOR_EACH( BOOST_READONLY_PROPERTY_DECLARE_FRIEND, ' ', friends )   \
    typedef base_prop::write_param_t  write_param_t;                                \
public:                                                                             \
                BOOST_JOIN( readonly_property, __LINE__ )() {}                      \
    explicit    BOOST_JOIN( readonly_property, __LINE__ )( write_param_t init_v  )  \
    : base_prop( init_v ) {}                                                        \
}                                                                                \
/**/

#endif

// ************************************************************************** //
// **************              readwrite_property              ************** //
// ************************************************************************** //

template<class PropertyType>
class readwrite_property : public class_property<PropertyType> {
    typedef class_property<PropertyType>                base_prop;
    typedef typename add_pointer<PropertyType>::type    arrow_res_t;
    typedef typename base_prop::address_res_t           const_arrow_res_t;
    typedef typename base_prop::write_param_t           write_param_t;
public:
                    readwrite_property() : base_prop() {}
    explicit        readwrite_property( write_param_t init_value ) : base_prop( init_value ) {}

    // access methods
    void            set( write_param_t v )  { base_prop::value = v; }
    arrow_res_t     operator->()            { return boost::addressof( base_prop::value ); }
    const_arrow_res_t operator->() const    { return boost::addressof( base_prop::value ); }

#ifndef BOOST_TEST_NO_PROTECTED_USING
    using           base_prop::value;
#endif
};

//____________________________________________________________________________//

} // unit_test

} // namespace boost

//____________________________________________________________________________//

#include <boost/test/detail/enable_warnings.hpp>

#undef BOOST_TEST_NO_PROTECTED_USING

// ***************************************************************************
//  Revision History :
//
//  $Log$
//  Revision 1.5  2005/02/21 10:17:27  rogeeff
//  base reference renamed (borland bug fix)
//
//  Revision 1.4  2005/02/20 08:27:08  rogeeff
//  This a major update for Boost.Test framework. See release docs for complete list of fixes/updates
//
//  Revision 1.3  2005/02/01 06:40:07  rogeeff
//  copyright update
//  old log entries removed
//  minor stilistic changes
//  depricated tools removed
//
//  Revision 1.2  2005/01/22 19:22:13  rogeeff
//  implementation moved into headers section to eliminate dependency of included/minimal component on src directory
//
//  Revision 1.1  2005/01/22 18:21:39  rogeeff
//  moved sharable staff into utils
//
// ***************************************************************************

#endif // BOOST_TEST_CLASS_PROPERTIES_HPP_071894GER
<commit_msg>use add_const<commit_after>//  (C) Copyright Gennadiy Rozental 2001-2005.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : simple facility that mimmic notion of read-only read-write
//  properties in C++ classes. Original idea by Henrik Ravn.
// ***************************************************************************

#ifndef BOOST_TEST_CLASS_PROPERTIES_HPP_071894GER
#define BOOST_TEST_CLASS_PROPERTIES_HPP_071894GER

// Boost.Test
#include <boost/test/detail/config.hpp>

// Boost
#if !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))
#include <boost/preprocessor/seq/for_each.hpp>
#endif
#include <boost/call_traits.hpp>
#include <boost/type_traits/add_pointer.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/utility/addressof.hpp>

// STL
#include <iosfwd>

#include <boost/test/detail/suppress_warnings.hpp>

//____________________________________________________________________________//

namespace boost {

namespace unit_test {

// ************************************************************************** //
// **************                 class_property               ************** //
// ************************************************************************** //

template<class PropertyType>
class class_property {
protected:
    typedef typename call_traits<PropertyType>::const_reference     read_access_t;
    typedef typename call_traits<PropertyType>::param_type          write_param_t;
    typedef typename add_pointer<typename add_const<PropertyType>::type>::type address_res_t;

public:
    // Constructor
                    class_property() : value( PropertyType() ) {}
    explicit        class_property( write_param_t init_value )
    : value( init_value ) {}

    // Access methods
    operator        read_access_t() const   { return value; }
    read_access_t   get() const             { return value; }
    bool            operator!() const       { return !value; }
    address_res_t   operator&() const       { return &value; }

    // Data members
#ifndef BOOST_TEST_NO_PROTECTED_USING
protected:
#endif
    PropertyType        value;
};

//____________________________________________________________________________//

#ifdef BOOST_CLASSIC_IOSTREAMS

template<class PropertyType>
inline std::ostream&
operator<<( std::ostream& os, class_property<PropertyType> const& p )

#else

template<typename CharT1, typename Tr,class PropertyType>
inline std::basic_ostream<CharT1,Tr>&
operator<<( std::basic_ostream<CharT1,Tr>& os, class_property<PropertyType> const& p )

#endif
{
    return os << p.get();
}

//____________________________________________________________________________//

#define DEFINE_PROPERTY_FREE_BINARY_OPERATOR( op )                              \
template<class PropertyType>                                                    \
inline bool                                                                     \
operator op( PropertyType const& lhs, class_property<PropertyType> const& rhs ) \
{                                                                               \
    return lhs op rhs.get();                                                    \
}                                                                               \
template<class PropertyType>                                                    \
inline bool                                                                     \
operator op( class_property<PropertyType> const& lhs, PropertyType const& rhs ) \
{                                                                               \
    return lhs.get() op rhs;                                                    \
}                                                                               \
template<class PropertyType>                                                    \
inline bool                                                                     \
operator op( class_property<PropertyType> const& lhs,                           \
             class_property<PropertyType> const& rhs )                          \
{                                                                               \
    return lhs.get() op rhs.get();                                              \
}                                                                               \
/**/

DEFINE_PROPERTY_FREE_BINARY_OPERATOR( == )
DEFINE_PROPERTY_FREE_BINARY_OPERATOR( != )

#undef DEFINE_PROPERTY_FREE_BINARY_OPERATOR

#if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)

#define DEFINE_PROPERTY_LOGICAL_OPERATOR( op )                                  \
template<class PropertyType>                                                    \
inline bool                                                                     \
operator op( bool b, class_property<PropertyType> const& p )                    \
{                                                                               \
    return b op p.get();                                                        \
}                                                                               \
template<class PropertyType>                                                    \
inline bool                                                                     \
operator op( class_property<PropertyType> const& p, bool b )                    \
{                                                                               \
    return b op p.get();                                                        \
}                                                                               \
/**/

DEFINE_PROPERTY_LOGICAL_OPERATOR( && )
DEFINE_PROPERTY_LOGICAL_OPERATOR( || )

#endif

// ************************************************************************** //
// **************               readonly_property              ************** //
// ************************************************************************** //

template<class PropertyType>
class readonly_property : public class_property<PropertyType> {
    typedef class_property<PropertyType>         base_prop;
    typedef typename base_prop::address_res_t    arrow_res_t;
protected:
    typedef typename base_prop::write_param_t    write_param_t;
public:
    // Constructor
                    readonly_property() {}
    explicit        readonly_property( write_param_t init_value ) : base_prop( init_value ) {}

    // access methods
    arrow_res_t     operator->() const      { return boost::addressof( base_prop::value ); }
};

//____________________________________________________________________________//

#if BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))

#define BOOST_READONLY_PROPERTY( property_type, friends ) boost::unit_test::readwrite_property<property_type >

#else

#define BOOST_READONLY_PROPERTY_DECLARE_FRIEND(r, data, elem) friend class elem;

#define BOOST_READONLY_PROPERTY( property_type, friends )                           \
class BOOST_JOIN( readonly_property, __LINE__ )                                     \
: public boost::unit_test::readonly_property<property_type > {                      \
    typedef boost::unit_test::readonly_property<property_type > base_prop;          \
    BOOST_PP_SEQ_FOR_EACH( BOOST_READONLY_PROPERTY_DECLARE_FRIEND, ' ', friends )   \
    typedef base_prop::write_param_t  write_param_t;                                \
public:                                                                             \
                BOOST_JOIN( readonly_property, __LINE__ )() {}                      \
    explicit    BOOST_JOIN( readonly_property, __LINE__ )( write_param_t init_v  )  \
    : base_prop( init_v ) {}                                                        \
}                                                                                \
/**/

#endif

// ************************************************************************** //
// **************              readwrite_property              ************** //
// ************************************************************************** //

template<class PropertyType>
class readwrite_property : public class_property<PropertyType> {
    typedef class_property<PropertyType>                base_prop;
    typedef typename add_pointer<PropertyType>::type    arrow_res_t;
    typedef typename base_prop::address_res_t           const_arrow_res_t;
    typedef typename base_prop::write_param_t           write_param_t;
public:
                    readwrite_property() : base_prop() {}
    explicit        readwrite_property( write_param_t init_value ) : base_prop( init_value ) {}

    // access methods
    void            set( write_param_t v )  { base_prop::value = v; }
    arrow_res_t     operator->()            { return boost::addressof( base_prop::value ); }
    const_arrow_res_t operator->() const    { return boost::addressof( base_prop::value ); }

#ifndef BOOST_TEST_NO_PROTECTED_USING
    using           base_prop::value;
#endif
};

//____________________________________________________________________________//

} // unit_test

} // namespace boost

//____________________________________________________________________________//

#include <boost/test/detail/enable_warnings.hpp>

#undef BOOST_TEST_NO_PROTECTED_USING

// ***************************************************************************
//  Revision History :
//
//  $Log$
//  Revision 1.6  2005/04/12 06:46:17  rogeeff
//  use add_const
//
//  Revision 1.5  2005/02/21 10:17:27  rogeeff
//  base reference renamed (borland bug fix)
//
//  Revision 1.4  2005/02/20 08:27:08  rogeeff
//  This a major update for Boost.Test framework. See release docs for complete list of fixes/updates
//
//  Revision 1.3  2005/02/01 06:40:07  rogeeff
//  copyright update
//  old log entries removed
//  minor stilistic changes
//  depricated tools removed
//
//  Revision 1.2  2005/01/22 19:22:13  rogeeff
//  implementation moved into headers section to eliminate dependency of included/minimal component on src directory
//
//  Revision 1.1  2005/01/22 18:21:39  rogeeff
//  moved sharable staff into utils
//
// ***************************************************************************

#endif // BOOST_TEST_CLASS_PROPERTIES_HPP_071894GER
<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2009-2017 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

// ospray
#include "lights/Light.h"
#include "common/Data.h"
#include "RaycastVolumeRenderer.h"
#include "RaycastVolumeMaterial.h"
// ospcommon
#include "ospcommon/tasking/parallel_for.h"

// ours
// ispc exports
#include "RaycastVolumeRenderer_ispc.h"

#include "mpiCommon/MPICommon.h"
#include "../../fb/DistributedFrameBuffer.h"
#include "../../volume/DataDistributedBlockedVolume.h"
#include "render/LoadBalancer.h"

#define TILE_CACHE_SAFE_MUTEX 0

namespace ospray {

  using namespace mpicommon;

  Material *RaycastVolumeRenderer::createMaterial(const char *type)
  {
    UNUSED(type);
    return new RaycastVolumeMaterial;
  }

  struct CacheForBlockTiles
  {
    CacheForBlockTiles(size_t numBlocks)
      : numBlocks(numBlocks), blockTile(new Tile *[numBlocks])
    {
      for (size_t i = 0; i < numBlocks; i++)
        blockTile[i] = nullptr;
    }

    ~CacheForBlockTiles()
    {
      for (size_t i = 0; i < numBlocks; i++) {
        if (blockTile[i])
          delete blockTile[i];
      }

      delete [] blockTile;
    }

    Tile *allocTile()
    {
      float infinity = std::numeric_limits<float>::infinity();
      Tile *tile = new Tile;
      for (int i = 0; i < TILE_SIZE*TILE_SIZE; i++) tile->r[i] = 0.f;
      for (int i = 0; i < TILE_SIZE*TILE_SIZE; i++) tile->g[i] = 0.f;
      for (int i = 0; i < TILE_SIZE*TILE_SIZE; i++) tile->b[i] = 0.f;
      for (int i = 0; i < TILE_SIZE*TILE_SIZE; i++) tile->a[i] = 0.f;
      for (int i = 0; i < TILE_SIZE*TILE_SIZE; i++) tile->z[i] = infinity;
      return tile;
    }

    Tile *getTileForBlock(size_t blockID)
    {
#if TILE_CACHE_SAFE_MUTEX
      mutex.lock();
      Tile *tile = blockTile[blockID];
      if (tile == nullptr) {
        blockTile[blockID] = tile = allocTile();
      }
      mutex.unlock();
      return tile;
#else
      Tile *tile = blockTile[blockID];
      if (tile != nullptr) return tile;
      mutex.lock();
      tile = blockTile[blockID];
      if (tile == nullptr) {
        blockTile[blockID] = tile = allocTile();
      }
      mutex.unlock();
      return tile;
#endif
    }

    std::mutex mutex;
    size_t numBlocks;
    Tile *volatile *blockTile;
  };

  /*! extern exported function so even ISPC code can access this cache */
  extern "C" Tile *
  CacheForBlockTiles_getTileForBlock(CacheForBlockTiles *cache,
                                     uint32 blockID)
  {
    return cache->getTileForBlock(blockID);
  }

  struct DPRenderTask
  {
    mutable Ref<Renderer>     renderer;
    mutable Ref<FrameBuffer>  fb;
    size_t                    numTiles_x;
    size_t                    numTiles_y;
    uint32                    channelFlags;
    const DataDistributedBlockedVolume *dpv;

    void operator()(int taskIndex) const;
  };

  void DPRenderTask::operator()(int taskIndex) const
  {
    const int &tileID = taskIndex;
    const int tile_y  = tileID / numTiles_x;
    const int tile_x  = tileID - tile_y*numTiles_x;
    const vec2i tileId(tile_x, tile_y);
    const int accumID = fb->accumID(tileId);
    Tile bgTile(tileId, fb->size, accumID);
    Tile fgTile(bgTile);

    int numBlocks = dpv->numDDBlocks;
    CacheForBlockTiles blockTileCache(numBlocks);
    bool *blockWasVisible = STACK_BUFFER(bool, numBlocks);

    for (int i = 0; i < numBlocks; i++)
      blockWasVisible[i] = false;

    bool renderForeAndBackground =
        (tileID % mpicommon::numWorkers()) == mpicommon::workerRank();

    const int numJobs = (TILE_SIZE*TILE_SIZE)/RENDERTILE_PIXELS_PER_JOB;

    tasking::parallel_for(numJobs, [&](int tid){
      ispc::DDDVRRenderer_renderTile(renderer->getIE(),
                                     (ispc::Tile&)fgTile,
                                     (ispc::Tile&)bgTile,
                                     &blockTileCache,
                                     numBlocks,
                                     dpv->ddBlock,
                                     blockWasVisible,
                                     tileID,
                                     mpicommon::workerRank(),
                                     renderForeAndBackground,
                                     tid);
    });

    if (renderForeAndBackground) {
      // this is a tile owned by me - i'm responsible for writing
      // generaition #0, and telling the fb how many more tiles will
      // be coming in generation #1

      size_t totalBlocksInTile = 0;
      for (size_t blockID = 0; blockID < numBlocks; blockID++) {
        if (blockWasVisible[blockID])
          totalBlocksInTile++;
      }

      size_t nextGenTiles
          = 1 /* expect one additional tile for background tile. */
          + totalBlocksInTile /* plus how many blocks map to this
                                     tile, IN TOTAL (ie, INCLUDING blocks
                                     on other nodes)*/;

      // set background tile
      bgTile.generation = 0;
      bgTile.children   = nextGenTiles;
      fb->setTile(bgTile);

      // set foreground tile
      fgTile.generation = 1;
      fgTile.children   = 0; //nextGenTiles-1;
      fb->setTile(fgTile);
      // all other tiles for gen #1 will be set below, no matter whether
      // it's mine or not
    }

    // now, send all block cache tiles that were generated on this
    // node back to master, too. for this, it doesn't matter if this
    // is our tile or not; it's the job of the owner of this tile to
    // tell the DFB how many tiles will arrive for the final thile
    // _across_all_clients_, but we only have to send ours (assuming
    // that all clients together send exactly as many as the owner
    // told the DFB to expect)
    for (int blockID = 0; blockID < numBlocks; blockID++) {
      Tile *tile = blockTileCache.blockTile[blockID];
      if (tile == nullptr)
        continue;

      tile->region = bgTile.region;
      tile->fbSize = bgTile.fbSize;
      tile->rcp_fbSize = bgTile.rcp_fbSize;
      tile->accumID = accumID;
      tile->generation = 1;
      tile->children   = 0;

      fb->setTile(*tile);
    }
  }

  /*! try if we are running in data-parallel mode, and if
    data-parallel is even required. if not (eg, if there's no
    data-parallel volumes in the scene) return nullptr and render only
    in regular mode; otherwise, compute some precomputations and
    return pointer to that (which'll switch the main renderframe fct
    to render data parallel) */
  float RaycastVolumeRenderer::renderFrame(FrameBuffer *fb,
                                           const uint32 channelFlags)
  {
    if (mpicommon::IamTheMaster()) {
      //NOTE: This function is for offload render worker ranks only, thus the
      //      master punts to default behavior
      return Renderer::renderFrame(fb, channelFlags);
    }

    using DDBV = DataDistributedBlockedVolume;
    std::vector<const DDBV*> ddVolumeVec;
    for (size_t volumeID = 0; volumeID < model->volume.size(); volumeID++) {
      const DDBV* ddv = dynamic_cast<const DDBV*>(model->volume[volumeID].ptr);
      if (!ddv) continue;
      ddVolumeVec.push_back(ddv);
    }

    if (ddVolumeVec.empty()) {
      static WarnOnce warning("no data parallel volumes, rendering in "
                              "traditional raycast_volume_render mode");
      return Renderer::renderFrame(fb, channelFlags);
    }

    // =======================================================
    // OK, we _need_ data-parallel rendering ....
    static WarnOnce dataParMsg("#dvr: at least one dp volume ->"
                               " needs data-parallel rendering ...");

    // check if we're even in mpi parallel mode (can't do
    // data-parallel otherwise)
    if (!mpicommon::isMpiParallel()) {
      throw std::runtime_error("#dvr: need data-parallel rendering, "
                               "but not running in mpi mode!?");
    }

    // switch (distributed) frame buffer into compositing mode
    DistributedFrameBuffer *dfb = dynamic_cast<DistributedFrameBuffer *>(fb);
    if (!dfb) {
      throw std::runtime_error("OSPRay data parallel rendering error. "
                               "this is a data-parallel scene, but we're "
                               "not using the distributed frame buffer!?");
    }

    dfb->setFrameMode(DistributedFrameBuffer::ALPHA_BLEND);

    Renderer::beginFrame(fb);

    dfb->startNewFrame(errorThreshold);

    if (ddVolumeVec.size() > 1) {
      /* note: our assumption below is that all blocks together are
         contiguous, and fill a convex region (ie, any point on a
         given ray is either entirely before any block, entirely
         behind any block, or inside one of the blocks) - if we have
         multiple data distributed volumes that is no longer the case,
         so we're not currently supporting this ... */
      throw std::runtime_error("currently supporting only ONE data parallel "
                               "volume in scene");
    }

    // create the render task
    DPRenderTask renderTask;
    renderTask.fb = fb;
    renderTask.renderer = this;
    renderTask.numTiles_x = divRoundUp(dfb->size.x, TILE_SIZE);
    renderTask.numTiles_y = divRoundUp(dfb->size.y, TILE_SIZE);
    renderTask.channelFlags = channelFlags;
    renderTask.dpv = ddVolumeVec[0];

    size_t NTASKS = renderTask.numTiles_x * renderTask.numTiles_y;
    tasking::parallel_for(NTASKS, renderTask);

    dfb->waitUntilFinished();
    Renderer::endFrame(nullptr, channelFlags);
    return fb->endFrame(0.f);
  }

  void RaycastVolumeRenderer::commit()
  {
    // Create the equivalent ISPC RaycastVolumeRenderer object.
    if (ispcEquivalent == nullptr) {
      ispcEquivalent = ispc::RaycastVolumeRenderer_createInstance();
    }

    // Set the lights if any.
    Data *lightsData = (Data *)getParamData("lights", nullptr);

    lights.clear();

    if (lightsData) {
      for (size_t i=0; i<lightsData->size(); i++)
        lights.push_back(((Light **)lightsData->data)[i]->getIE());
    }

    ispc::RaycastVolumeRenderer_setLights(ispcEquivalent,
                                          lights.empty() ? nullptr : &lights[0],
                                          lights.size());

    // Initialize state in the parent class, must be called after the ISPC
    // object is created.
    Renderer::commit();
  }

  // A renderer type for volumes with embedded surfaces.
  OSP_REGISTER_RENDERER(RaycastVolumeRenderer, raycast_volume_renderer);
  OSP_REGISTER_RENDERER(RaycastVolumeRenderer, dvr);

} // ::ospray

<commit_msg>Fix crash w/ old data-parallel vol. renderer and variance<commit_after>// ======================================================================== //
// Copyright 2009-2017 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

// ospray
#include "lights/Light.h"
#include "common/Data.h"
#include "RaycastVolumeRenderer.h"
#include "RaycastVolumeMaterial.h"
// ospcommon
#include "ospcommon/tasking/parallel_for.h"

// ours
// ispc exports
#include "RaycastVolumeRenderer_ispc.h"

#include "mpiCommon/MPICommon.h"
#include "../../fb/DistributedFrameBuffer.h"
#include "../../volume/DataDistributedBlockedVolume.h"
#include "render/LoadBalancer.h"

#define TILE_CACHE_SAFE_MUTEX 0

namespace ospray {

  using namespace mpicommon;

  Material *RaycastVolumeRenderer::createMaterial(const char *type)
  {
    UNUSED(type);
    return new RaycastVolumeMaterial;
  }

  struct CacheForBlockTiles
  {
    CacheForBlockTiles(size_t numBlocks)
      : numBlocks(numBlocks), blockTile(new Tile *[numBlocks])
    {
      for (size_t i = 0; i < numBlocks; i++)
        blockTile[i] = nullptr;
    }

    ~CacheForBlockTiles()
    {
      for (size_t i = 0; i < numBlocks; i++) {
        if (blockTile[i])
          delete blockTile[i];
      }

      delete [] blockTile;
    }

    Tile *allocTile()
    {
      float infinity = std::numeric_limits<float>::infinity();
      Tile *tile = new Tile;
      for (int i = 0; i < TILE_SIZE*TILE_SIZE; i++) tile->r[i] = 0.f;
      for (int i = 0; i < TILE_SIZE*TILE_SIZE; i++) tile->g[i] = 0.f;
      for (int i = 0; i < TILE_SIZE*TILE_SIZE; i++) tile->b[i] = 0.f;
      for (int i = 0; i < TILE_SIZE*TILE_SIZE; i++) tile->a[i] = 0.f;
      for (int i = 0; i < TILE_SIZE*TILE_SIZE; i++) tile->z[i] = infinity;
      return tile;
    }

    Tile *getTileForBlock(size_t blockID)
    {
#if TILE_CACHE_SAFE_MUTEX
      mutex.lock();
      Tile *tile = blockTile[blockID];
      if (tile == nullptr) {
        blockTile[blockID] = tile = allocTile();
      }
      mutex.unlock();
      return tile;
#else
      Tile *tile = blockTile[blockID];
      if (tile != nullptr) return tile;
      mutex.lock();
      tile = blockTile[blockID];
      if (tile == nullptr) {
        blockTile[blockID] = tile = allocTile();
      }
      mutex.unlock();
      return tile;
#endif
    }

    std::mutex mutex;
    size_t numBlocks;
    Tile *volatile *blockTile;
  };

  /*! extern exported function so even ISPC code can access this cache */
  extern "C" Tile *
  CacheForBlockTiles_getTileForBlock(CacheForBlockTiles *cache,
                                     uint32 blockID)
  {
    return cache->getTileForBlock(blockID);
  }

  struct DPRenderTask
  {
    mutable Ref<Renderer>     renderer;
    mutable Ref<FrameBuffer>  fb;
    size_t                    numTiles_x;
    size_t                    numTiles_y;
    uint32                    channelFlags;
    const DataDistributedBlockedVolume *dpv;

    void operator()(int taskIndex) const;
  };

  void DPRenderTask::operator()(int taskIndex) const
  {
    const int &tileID = taskIndex;
    const int tile_y  = tileID / numTiles_x;
    const int tile_x  = tileID - tile_y*numTiles_x;
    const vec2i tileId(tile_x, tile_y);
    const int accumID = fb->accumID(tileId);
    Tile bgTile(tileId, fb->size, accumID);
    Tile fgTile(bgTile);

    int numBlocks = dpv->numDDBlocks;
    CacheForBlockTiles blockTileCache(numBlocks);
    bool *blockWasVisible = STACK_BUFFER(bool, numBlocks);

    for (int i = 0; i < numBlocks; i++)
      blockWasVisible[i] = false;

    bool renderForeAndBackground =
        (tileID % mpicommon::numWorkers()) == mpicommon::workerRank();

    const int numJobs = (TILE_SIZE*TILE_SIZE)/RENDERTILE_PIXELS_PER_JOB;

    tasking::parallel_for(numJobs, [&](int tid){
      ispc::DDDVRRenderer_renderTile(renderer->getIE(),
                                     (ispc::Tile&)fgTile,
                                     (ispc::Tile&)bgTile,
                                     &blockTileCache,
                                     numBlocks,
                                     dpv->ddBlock,
                                     blockWasVisible,
                                     tileID,
                                     mpicommon::workerRank(),
                                     renderForeAndBackground,
                                     tid);
    });

    if (renderForeAndBackground) {
      // this is a tile owned by me - i'm responsible for writing
      // generaition #0, and telling the fb how many more tiles will
      // be coming in generation #1

      size_t totalBlocksInTile = 0;
      for (size_t blockID = 0; blockID < numBlocks; blockID++) {
        if (blockWasVisible[blockID])
          totalBlocksInTile++;
      }

      size_t nextGenTiles
          = 1 /* expect one additional tile for background tile. */
          + totalBlocksInTile /* plus how many blocks map to this
                                     tile, IN TOTAL (ie, INCLUDING blocks
                                     on other nodes)*/;

      // set background tile
      bgTile.generation = 0;
      bgTile.children   = nextGenTiles;
      fb->setTile(bgTile);

      // set foreground tile
      fgTile.generation = 1;
      fgTile.children   = 0; //nextGenTiles-1;
      fb->setTile(fgTile);
      // all other tiles for gen #1 will be set below, no matter whether
      // it's mine or not
    }

    // now, send all block cache tiles that were generated on this
    // node back to master, too. for this, it doesn't matter if this
    // is our tile or not; it's the job of the owner of this tile to
    // tell the DFB how many tiles will arrive for the final thile
    // _across_all_clients_, but we only have to send ours (assuming
    // that all clients together send exactly as many as the owner
    // told the DFB to expect)
    for (int blockID = 0; blockID < numBlocks; blockID++) {
      Tile *tile = blockTileCache.blockTile[blockID];
      if (tile == nullptr)
        continue;

      tile->region = bgTile.region;
      tile->fbSize = bgTile.fbSize;
      tile->rcp_fbSize = bgTile.rcp_fbSize;
      tile->accumID = accumID;
      tile->generation = 1;
      tile->children   = 0;

      fb->setTile(*tile);
    }
  }

  /*! try if we are running in data-parallel mode, and if
    data-parallel is even required. if not (eg, if there's no
    data-parallel volumes in the scene) return nullptr and render only
    in regular mode; otherwise, compute some precomputations and
    return pointer to that (which'll switch the main renderframe fct
    to render data parallel) */
  float RaycastVolumeRenderer::renderFrame(FrameBuffer *fb,
                                           const uint32 channelFlags)
  {
    if (mpicommon::IamTheMaster()) {
      //NOTE: This function is for offload render worker ranks only, thus the
      //      master punts to default behavior
      return Renderer::renderFrame(fb, channelFlags);
    }

    using DDBV = DataDistributedBlockedVolume;
    std::vector<const DDBV*> ddVolumeVec;
    for (size_t volumeID = 0; volumeID < model->volume.size(); volumeID++) {
      const DDBV* ddv = dynamic_cast<const DDBV*>(model->volume[volumeID].ptr);
      if (!ddv) continue;
      ddVolumeVec.push_back(ddv);
    }

    if (ddVolumeVec.empty()) {
      static WarnOnce warning("no data parallel volumes, rendering in "
                              "traditional raycast_volume_render mode");
      return Renderer::renderFrame(fb, channelFlags);
    }

    // =======================================================
    // OK, we _need_ data-parallel rendering ....
    static WarnOnce dataParMsg("#dvr: at least one dp volume ->"
                               " needs data-parallel rendering ...");

    // check if we're even in mpi parallel mode (can't do
    // data-parallel otherwise)
    if (!mpicommon::isMpiParallel()) {
      throw std::runtime_error("#dvr: need data-parallel rendering, "
                               "but not running in mpi mode!?");
    }

    // switch (distributed) frame buffer into compositing mode
    DistributedFrameBuffer *dfb = dynamic_cast<DistributedFrameBuffer *>(fb);
    if (!dfb) {
      throw std::runtime_error("OSPRay data parallel rendering error. "
                               "this is a data-parallel scene, but we're "
                               "not using the distributed frame buffer!?");
    }

    dfb->setFrameMode(DistributedFrameBuffer::ALPHA_BLEND);
    dfb->startNewFrame(errorThreshold);
    Renderer::beginFrame(fb);

    if (ddVolumeVec.size() > 1) {
      /* note: our assumption below is that all blocks together are
         contiguous, and fill a convex region (ie, any point on a
         given ray is either entirely before any block, entirely
         behind any block, or inside one of the blocks) - if we have
         multiple data distributed volumes that is no longer the case,
         so we're not currently supporting this ... */
      throw std::runtime_error("currently supporting only ONE data parallel "
                               "volume in scene");
    }

    // create the render task
    DPRenderTask renderTask;
    renderTask.fb = fb;
    renderTask.renderer = this;
    renderTask.numTiles_x = divRoundUp(dfb->size.x, TILE_SIZE);
    renderTask.numTiles_y = divRoundUp(dfb->size.y, TILE_SIZE);
    renderTask.channelFlags = channelFlags;
    renderTask.dpv = ddVolumeVec[0];

    size_t NTASKS = renderTask.numTiles_x * renderTask.numTiles_y;
    tasking::parallel_for(NTASKS, renderTask);

    dfb->waitUntilFinished();
    Renderer::endFrame(nullptr, channelFlags);
    return fb->endFrame(0.f);
  }

  void RaycastVolumeRenderer::commit()
  {
    // Create the equivalent ISPC RaycastVolumeRenderer object.
    if (ispcEquivalent == nullptr) {
      ispcEquivalent = ispc::RaycastVolumeRenderer_createInstance();
    }

    // Set the lights if any.
    Data *lightsData = (Data *)getParamData("lights", nullptr);

    lights.clear();

    if (lightsData) {
      for (size_t i=0; i<lightsData->size(); i++)
        lights.push_back(((Light **)lightsData->data)[i]->getIE());
    }

    ispc::RaycastVolumeRenderer_setLights(ispcEquivalent,
                                          lights.empty() ? nullptr : &lights[0],
                                          lights.size());

    // Initialize state in the parent class, must be called after the ISPC
    // object is created.
    Renderer::commit();
  }

  // A renderer type for volumes with embedded surfaces.
  OSP_REGISTER_RENDERER(RaycastVolumeRenderer, raycast_volume_renderer);
  OSP_REGISTER_RENDERER(RaycastVolumeRenderer, dvr);

} // ::ospray

<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2012-2014 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 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.
 *
 ****************************************************************************/

/**
 * @file device.cpp
 *
 * Fundamental driver base class for the virtual device framework.
 */

#include "device.h"

#include <px4_defines.h>
#include <px4_posix.h>
#include <drivers/drv_device.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>

namespace device
{

Device::Device(const char *name) :
	// public
	// protected
	_name(name),
	_debug_enabled(false)
{
	#ifndef __PX4_DARWIN
		_lock = new sem_t;
		int ret = sem_init(_lock, 0, 1);

		if (ret != 0) {
			PX4_WARN("SEM INIT FAIL: ret %d, %s", ret, strerror(errno));
		}
	#else
		_lock_name = new char[strlen(_name) + 2];
		_lock_name[0] = '/';
		strcpy(&_lock_name[1], _name);
		/* not using O_EXCL as the device handles are unique */
		_lock = sem_open(_lock_name, O_CREAT, 0777, 1);

		if (_lock == SEM_FAILED) {
			PX4_WARN("SEM INIT FAIL: %s", strerror(errno));
		}
	#endif

	/* setup a default device ID. When bus_type is UNKNOWN the
	   other fields are invalid */
	_device_id.devid = 0;
	_device_id.devid_s.bus_type = DeviceBusType_UNKNOWN;
	_device_id.devid_s.bus = 0;
	_device_id.devid_s.address = 0;
	_device_id.devid_s.devtype = 0;
}

Device::~Device()
{
	#ifdef __PX4_DARWIN
	sem_unlink(_name);
	#else
	sem_destroy(&_lock);
	#endif
}

int
Device::init()
{
	int ret = OK;

	return ret;
}

int
Device::dev_read(unsigned offset, void *data, unsigned count)
{
        return -ENODEV;
}

int
Device::dev_write(unsigned offset, void *data, unsigned count)
{
        return -ENODEV;
}

int
Device::dev_ioctl(unsigned operation, unsigned &arg)
{
        switch (operation) {
        case DEVIOCGDEVICEID:
                return (int)_device_id.devid;
        }
        return -ENODEV;
}

} // namespace device
<commit_msg>Linux device build fix<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2012-2014 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 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.
 *
 ****************************************************************************/

/**
 * @file device.cpp
 *
 * Fundamental driver base class for the virtual device framework.
 */

#include "device.h"

#include <px4_defines.h>
#include <px4_posix.h>
#include <drivers/drv_device.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>

namespace device
{

Device::Device(const char *name) :
	// public
	// protected
	_name(name),
	_debug_enabled(false)
{
	#ifndef __PX4_DARWIN
		_lock = new sem_t;
		int ret = sem_init(_lock, 0, 1);

		if (ret != 0) {
			PX4_WARN("SEM INIT FAIL: ret %d, %s", ret, strerror(errno));
		}
	#else
		_lock_name = new char[strlen(_name) + 2];
		_lock_name[0] = '/';
		strcpy(&_lock_name[1], _name);
		/* not using O_EXCL as the device handles are unique */
		_lock = sem_open(_lock_name, O_CREAT, 0777, 1);

		if (_lock == SEM_FAILED) {
			PX4_WARN("SEM INIT FAIL: %s", strerror(errno));
		}
	#endif

	/* setup a default device ID. When bus_type is UNKNOWN the
	   other fields are invalid */
	_device_id.devid = 0;
	_device_id.devid_s.bus_type = DeviceBusType_UNKNOWN;
	_device_id.devid_s.bus = 0;
	_device_id.devid_s.address = 0;
	_device_id.devid_s.devtype = 0;
}

Device::~Device()
{
	#ifdef __PX4_DARWIN
	sem_unlink(_name);
	#else
	sem_destroy(_lock);
	#endif
}

int
Device::init()
{
	int ret = OK;

	return ret;
}

int
Device::dev_read(unsigned offset, void *data, unsigned count)
{
        return -ENODEV;
}

int
Device::dev_write(unsigned offset, void *data, unsigned count)
{
        return -ENODEV;
}

int
Device::dev_ioctl(unsigned operation, unsigned &arg)
{
        switch (operation) {
        case DEVIOCGDEVICEID:
                return (int)_device_id.devid;
        }
        return -ENODEV;
}

} // namespace device
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <gtest/gtest.h>

#include <stout/os.hpp>
#include <stout/path.hpp>
#include <stout/try.hpp>

#include <process/owned.hpp>

#include "tests/mesos.hpp"

#include "tests/containerizer/docker_archive.hpp"

using std::string;

using process::Future;
using process::Owned;

namespace mesos {
namespace internal {
namespace tests {

#ifdef __linux__
class DockerArchiveTest : public TemporaryDirectoryTest {};

// This test verifies that a testing docker image is created as
// a local archive under a given directory. This is a ROOT test
// because permission is need to create linux root filesystem.
TEST_F(DockerArchiveTest, ROOT_CreateDockerLocalTar)
{
  const string directory = path::join(os::getcwd(), "archives");

  Future<Nothing> testImage = DockerArchive::create(directory, "alpine");
  AWAIT_READY(testImage);

  EXPECT_TRUE(os::exists(path::join(directory, "alpine.tar")));
  EXPECT_FALSE(os::exists(path::join(directory, "alpine")));
}

#endif // __linux__

} // namespace tests {
} // namespace internal {
} // namespace mesos {
<commit_msg>Implemented runtime isolator default cmd test.<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <gtest/gtest.h>

#include <stout/os.hpp>
#include <stout/path.hpp>
#include <stout/try.hpp>
#include <stout/uuid.hpp>

#include <process/owned.hpp>

#include "tests/environment.hpp"
#include "tests/mesos.hpp"

#include "tests/containerizer/docker_archive.hpp"

namespace master = mesos::internal::master;
namespace slave = mesos::internal::slave;

using std::string;
using std::vector;

using process::Future;
using process::Owned;
using process::PID;

using master::Master;

using slave::Slave;

namespace mesos {
namespace internal {
namespace tests {

#ifdef __linux__
class DockerArchiveTest : public TemporaryDirectoryTest {};

// This test verifies that a testing docker image is created as
// a local archive under a given directory. This is a ROOT test
// because permission is need to create linux root filesystem.
TEST_F(DockerArchiveTest, ROOT_CreateDockerLocalTar)
{
  const string directory = path::join(os::getcwd(), "archives");

  Future<Nothing> testImage = DockerArchive::create(directory, "alpine");
  AWAIT_READY(testImage);

  EXPECT_TRUE(os::exists(path::join(directory, "alpine.tar")));
  EXPECT_FALSE(os::exists(path::join(directory, "alpine")));
}

class DockerRuntimeIsolatorTest : public MesosTest {};

// This test verifies that docker image default cmd is executed correctly.
// This corresponds to the case in runtime isolator logic table: sh=0,
// value=0, argv=1, entrypoint=0, cmd=1.
TEST_F(DockerRuntimeIsolatorTest, ROOT_DockerDefaultCmdLocalPuller)
{
  Try<PID<Master>> master = StartMaster();
  ASSERT_SOME(master);

  Try<string> mkdtemp = environment->mkdtemp();
  ASSERT_SOME(mkdtemp);

  const string directory = path::join(mkdtemp.get(), "archives");

  Future<Nothing> testImage =
    DockerArchive::create(directory, "alpine", "null", "[\"sh\"]");

  AWAIT_READY(testImage);

  ASSERT_TRUE(os::exists(path::join(directory, "alpine.tar")));

  slave::Flags flags = CreateSlaveFlags();
  flags.isolation = "docker/runtime,filesystem/linux";
  flags.image_providers = "docker";
  flags.docker_registry = directory;

  // Make docker store directory as a temparary directory. Because the
  // manifest of the test image is changeable, the image cached on
  // previous tests should never be used.
  flags.docker_store_dir = path::join(flags.work_dir, "docker");

  Try<PID<Slave>> slave = StartSlave(flags);
  ASSERT_SOME(slave);

  MockScheduler sched;
  MesosSchedulerDriver driver(
      &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);

  EXPECT_CALL(sched, registered(&driver, _, _));

  Future<vector<Offer>> offers;
  EXPECT_CALL(sched, resourceOffers(&driver, _))
    .WillOnce(FutureArg<1>(&offers))
    .WillRepeatedly(Return()); // Ignore subsequent offers.

  driver.start();

  AWAIT_READY(offers);
  ASSERT_EQ(1u, offers->size());

  const Offer& offer = offers.get()[0];

  TaskInfo task;
  task.set_name("test-task");
  task.mutable_task_id()->set_value(UUID::random().toString());
  task.mutable_slave_id()->CopyFrom(offer.slave_id());
  task.mutable_resources()->CopyFrom(Resources::parse("cpus:1;mem:128").get());
  task.mutable_command()->set_shell(false);
  task.mutable_command()->add_arguments("-c");
  task.mutable_command()->add_arguments("echo 'hello world'");

  Image image;
  image.set_type(Image::DOCKER);
  image.mutable_docker()->set_name("alpine");

  ContainerInfo* container = task.mutable_container();
  container->set_type(ContainerInfo::MESOS);
  container->mutable_mesos()->mutable_image()->CopyFrom(image);

  Future<TaskStatus> statusRunning;
  Future<TaskStatus> statusFinished;
  EXPECT_CALL(sched, statusUpdate(&driver, _))
    .WillOnce(FutureArg<1>(&statusRunning))
    .WillOnce(FutureArg<1>(&statusFinished));

  driver.launchTasks(offer.id(), {task});

  AWAIT_READY_FOR(statusRunning, Seconds(60));
  EXPECT_EQ(task.task_id(), statusRunning->task_id());
  EXPECT_EQ(TASK_RUNNING, statusRunning->state());

  AWAIT_READY(statusFinished);
  EXPECT_EQ(task.task_id(), statusFinished->task_id());
  EXPECT_EQ(TASK_FINISHED, statusFinished->state());

  driver.stop();
  driver.join();

  Shutdown();
}

#endif // __linux__

} // namespace tests {
} // namespace internal {
} // namespace mesos {
<|endoftext|>


<commit_before>/************************************************************************
	filename: 	CEGUIDragContainer.cpp
	created:	14/2/2005
	author:		Paul D Turner
*************************************************************************/
/*************************************************************************
    Crazy Eddie's GUI System (http://www.cegui.org.uk)
    Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)

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

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

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*************************************************************************/
#include "elements/CEGUIDragContainer.h"
#include "CEGUIImageset.h"
#include <cmath>

// Start of CEGUI namespace section
namespace CEGUI
{
    //////////////////////////////////////////////////////////////////////////
    // Window type string
    const String DragContainer::WidgetTypeName("DragContainer");
    // Event Strings
    const String DragContainer::EventNamespace("DragContainer");
    const String DragContainer::EventDragStarted("DragStarted");
    const String DragContainer::EventDragEnded("DragEnded");
    const String DragContainer::EventDragPositionChanged("DragPositionChanged");
    const String DragContainer::EventDragEnabledChanged("DragEnabledChanged");
    const String DragContainer::EventDragAlphaChanged("DragAlphaChanged");
    const String DragContainer::EventDragMouseCursorChanged("DragMouseCursorChanged");
    const String DragContainer::EventDragThresholdChanged("DragThresholdChanged");
    const String DragContainer::EventDragDropTargetChanged("DragDropTargetChanged");
    // Properties
    DragContainerProperties::DragAlpha       DragContainer::d_dragAlphaProperty;
    DragContainerProperties::DragCursorImage DragContainer::d_dragCursorImageProperty;
    DragContainerProperties::DraggingEnabled DragContainer::d_dragEnabledProperty;
    DragContainerProperties::DragThreshold   DragContainer::d_dragThresholdProperty;

    //////////////////////////////////////////////////////////////////////////

    DragContainer::DragContainer(const String& type, const String& name) :
        Window(type, name),
        d_draggingEnabled(true),
        d_leftMouseDown(false),
        d_dragging(false),
        d_dragThreshold(8.0f),
        d_dragAlpha(0.5f),
        d_dropTarget(0),
        d_dragCursorImage((const Image*)DefaultMouseCursor)
    {
        addDragContainerEvents();
        addDragContainerProperties();
    }

    DragContainer::~DragContainer(void)
    {
    }

    bool DragContainer::isDraggingEnabled(void) const
    {
        return d_draggingEnabled;
    }

    void DragContainer::setDraggingEnabled(bool setting)
    {
        if (d_draggingEnabled != setting)
        {
            d_draggingEnabled = setting;
            WindowEventArgs args(this);
            onDragEnabledChanged(args);
        }
    }

    bool DragContainer::isBeingDragged(void) const
    {
        return d_dragging;
    }

    float DragContainer::getPixelDragThreshold(void) const
    {
        return d_dragThreshold;
    }

    void DragContainer::setPixelDragThreshold(float pixels)
    {
        if (d_dragThreshold != pixels)
        {
            d_dragThreshold = pixels;
            WindowEventArgs args(this);
            onDragThresholdChanged(args);
        }
    }

    float DragContainer::getDragAlpha(void) const
    {
        return d_dragAlpha;
    }

    void DragContainer::setDragAlpha(float alpha)
    {
        if (d_dragAlpha != alpha)
        {
            d_dragAlpha = alpha;
            WindowEventArgs args(this);
            onDragAlphaChanged(args);
        }
    }

    const Image* DragContainer::getDragCursorImage(void) const
    {
        if (d_dragCursorImage == (const Image*)DefaultMouseCursor)
        {
            return System::getSingleton().getDefaultMouseCursor();
        }
        else
        {
            return d_dragCursorImage;
        }
    }

    void DragContainer::setDragCursorImage(const Image* image)
    {
        if (d_dragCursorImage != image)
        {
            d_dragCursorImage = image;
            WindowEventArgs args(this);
            onDragMouseCursorChanged(args);
        }
    }

    void DragContainer::setDragCursorImage(MouseCursorImage image)
    {
        setDragCursorImage((const Image*)image);
    }

    void DragContainer::setDragCursorImage(const String& imageset, const String& image)
    {
        setDragCursorImage(&ImagesetManager::getSingleton().getImageset(imageset)->getImage(image));
    }

    Window* DragContainer::getCurrentDropTarget(void) const
    {
        return d_dropTarget;
    }

    void DragContainer::addDragContainerEvents(void)
    {
        addEvent(EventDragStarted);
        addEvent(EventDragEnded);
        addEvent(EventDragPositionChanged);
        addEvent(EventDragEnabledChanged);
        addEvent(EventDragAlphaChanged);
        addEvent(EventDragMouseCursorChanged);
        addEvent(EventDragThresholdChanged);
        addEvent(EventDragDropTargetChanged);
    }

    void DragContainer::addDragContainerProperties(void)
    {
        addProperty(&d_dragEnabledProperty);
        addProperty(&d_dragAlphaProperty);
        addProperty(&d_dragThresholdProperty);
        addProperty(&d_dragCursorImageProperty);
    }

    bool DragContainer::isDraggingThresholdExceeded(const Point& local_mouse)
    {
        // calculate amount mouse has moved.
        float	deltaX = std::fabs(local_mouse.d_x - d_dragPoint.d_x);
        float	deltaY = std::fabs(local_mouse.d_y - d_dragPoint.d_y);

        // see if mouse has moved far enough to start dragging operation
        return (deltaX > d_dragThreshold || deltaY > d_dragThreshold) ? true : false;
    }

    void DragContainer::initialiseDragging(void)
    {
        // only proceed if dragging is actually enabled
        if (d_draggingEnabled)
        {
            // initialise drag moving state
            d_storedClipState = d_clippedByParent;
            setClippedByParent(false);
            d_storedAlpha = d_alpha;
            setAlpha(d_dragAlpha);
            d_startPosition = getPosition(Absolute);

            d_dragging = true;

            // Now drag mode is set, change cursor as required
            updateActiveMouseCursor();
        }
    }

    void DragContainer::doDragging(const Point& local_mouse)
    {
        setPosition(Absolute, getPosition(Absolute) + (local_mouse - d_dragPoint));

        WindowEventArgs args(this);
        onDragPositionChanged(args);
    }

    void DragContainer::updateActiveMouseCursor(void) const
    {
        MouseCursor::getSingleton().setImage(d_dragging ? getDragCursorImage() : getMouseCursor());
    }

    void DragContainer::drawSelf(float z)
    {
        // No rendering for this window
    }

    void DragContainer::onMouseButtonDown(MouseEventArgs& e)
    {
        Window::onMouseButtonDown(e);

        if (e.button == LeftButton)
        {
            // ensure all inputs come to us for now
            if (captureInput())
            {
                // get position of mouse as co-ordinates local to this window.
                Point localPos = (getMetricsMode() == Relative) ?
                    relativeToAbsolute(screenToWindow(e.position)) :
                    screenToWindow(e.position);

                // store drag point for possible sizing or moving operation.
                d_dragPoint = localPos;
                d_leftMouseDown = true;
            }

            e.handled = true;
        }

    }

    void DragContainer::onMouseButtonUp(MouseEventArgs& e)
    {
        Window::onMouseButtonUp(e);

        if (e.button == LeftButton)
        {
            if (d_dragging)
            {
                // fire off event
                WindowEventArgs args(this);
                onDragEnded(args);
            }

            // release our capture on the input data
            releaseInput();
            e.handled = true;
        }
    }

    void DragContainer::onMouseMove(MouseEventArgs& e)
    {
        Window::onMouseMove(e);

        // get position of mouse as co-ordinates local to this window.
        Point localMousePos = (getMetricsMode() == Relative) ?
            relativeToAbsolute(screenToWindow(e.position)) :
            screenToWindow(e.position);

        // handle dragging
        if (d_dragging)
        {
            doDragging(localMousePos);
       }
        // not dragging
        else
        {
            // if mouse button is down (but we're not yet being dragged)
            if (d_leftMouseDown)
            {
                if (isDraggingThresholdExceeded(localMousePos))
                {
                    // Trigger the event
                    WindowEventArgs args(this);
                    onDragStarted(args);
                }
            }
        }
    }

    void DragContainer::onCaptureLost(WindowEventArgs& e)
    {
        Window::onCaptureLost(e);

        // reset state
        if (d_dragging)
        {
            // restore windows 'normal' state.
            d_dragging = false;
            setPosition(Absolute, d_startPosition);
            setClippedByParent(d_storedClipState);
            setAlpha(d_storedAlpha);

            // restore normal mouse cursor
            updateActiveMouseCursor();
        }

        d_leftMouseDown = false;
        d_dropTarget = 0;

        e.handled = true;
    }

    void DragContainer::onAlphaChanged(WindowEventArgs& e)
    {
        // store new value and re-set dragging alpha as required.
        if (d_dragging)
        {
            d_storedAlpha = d_alpha;
            d_alpha = d_dragAlpha;
        }

        Window::onAlphaChanged(e);
    }

    void DragContainer::onClippingChanged(WindowEventArgs& e)
    {
        // store new value and re-set clipping for drag as required.
        if (d_dragging)
        {
            d_storedClipState = d_clippedByParent;
            d_clippedByParent = false;
        }

        Window::onClippingChanged(e);
    }

    void DragContainer::onDragStarted(WindowEventArgs& e)
    {
        initialiseDragging();

        fireEvent(EventDragStarted, e, EventNamespace);
    }

    void DragContainer::onDragEnded(WindowEventArgs& e)
    {
        fireEvent(EventDragEnded, e, EventNamespace);

        // did we drop over a window?
        if (d_dropTarget)
        {
            // Notify that item was dropped in the target window
            d_dropTarget->notifyDragDropItemDropped(this);
        }
    }

    void DragContainer::onDragPositionChanged(WindowEventArgs& e)
    {
        fireEvent(EventDragPositionChanged, e, EventNamespace);

        Window* root;

        if (0 != (root = System::getSingleton().getGUISheet()))
        {
            // this hack with the 'enabled' state is so that getChildAtPosition
            // returns something useful instead of a pointer back to 'this'.
            // This hack is only acceptable because I am CrazyEddie!
            bool wasEnabled = d_enabled;
            d_enabled = false;
            // find out which child of root window has the mouse in it
            Window* eventWindow = root->getChildAtPosition(MouseCursor::getSingleton().getPosition());
            d_enabled = wasEnabled;

            // use root itself if no child was hit
            if (!eventWindow)
            {
                eventWindow = root;
            }

            // if the window with the mouse is different to current drop target
            if (eventWindow != d_dropTarget)
            {
                DragDropEventArgs args(eventWindow);
                args.dragDropItem = this;
                onDragDropTargetChanged(args);
            }
        }
    }

    void DragContainer::onDragEnabledChanged(WindowEventArgs& e)
    {
        fireEvent(EventDragEnabledChanged, e, EventNamespace);

        // abort current drag operation if dragging gets disabled part way through
        if (!d_draggingEnabled && d_dragging)
        {
            releaseInput();
        }
    }

    void DragContainer::onDragAlphaChanged(WindowEventArgs& e)
    {
        fireEvent(EventDragAlphaChanged, e, EventNamespace);

        if (d_dragging)
        {
            d_alpha = d_storedAlpha;
            onAlphaChanged(e);
        }
    }

    void DragContainer::onDragMouseCursorChanged(WindowEventArgs& e)
    {
        fireEvent(EventDragMouseCursorChanged, e, EventNamespace);

        updateActiveMouseCursor();
    }

    void DragContainer::onDragThresholdChanged(WindowEventArgs& e)
    {
        fireEvent(EventDragThresholdChanged, e, EventNamespace);
    }

    void DragContainer::onDragDropTargetChanged(DragDropEventArgs& e)
    {
        fireEvent(EventDragDropTargetChanged, e, EventNamespace);

        // Notify old target that drop item has left
        if (d_dropTarget)
        {
            d_dropTarget->notifyDragDropItemLeaves(this);
        }

        // update to new target
        d_dropTarget = e.window;

        // Notify new target window that someone has dragged a DragContainer over it
        d_dropTarget->notifyDragDropItemEnters(this);
    }

} // End of  CEGUI namespace section
<commit_msg>Fixes to work around possible STLport issues where it does not put some C funcs into std (_STL) namespace.<commit_after>/************************************************************************
	filename: 	CEGUIDragContainer.cpp
	created:	14/2/2005
	author:		Paul D Turner
*************************************************************************/
/*************************************************************************
    Crazy Eddie's GUI System (http://www.cegui.org.uk)
    Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)

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

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

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*************************************************************************/
#include "elements/CEGUIDragContainer.h"
#include "CEGUIImageset.h"
#include <math.h>

// Start of CEGUI namespace section
namespace CEGUI
{
    //////////////////////////////////////////////////////////////////////////
    // Window type string
    const String DragContainer::WidgetTypeName("DragContainer");
    // Event Strings
    const String DragContainer::EventNamespace("DragContainer");
    const String DragContainer::EventDragStarted("DragStarted");
    const String DragContainer::EventDragEnded("DragEnded");
    const String DragContainer::EventDragPositionChanged("DragPositionChanged");
    const String DragContainer::EventDragEnabledChanged("DragEnabledChanged");
    const String DragContainer::EventDragAlphaChanged("DragAlphaChanged");
    const String DragContainer::EventDragMouseCursorChanged("DragMouseCursorChanged");
    const String DragContainer::EventDragThresholdChanged("DragThresholdChanged");
    const String DragContainer::EventDragDropTargetChanged("DragDropTargetChanged");
    // Properties
    DragContainerProperties::DragAlpha       DragContainer::d_dragAlphaProperty;
    DragContainerProperties::DragCursorImage DragContainer::d_dragCursorImageProperty;
    DragContainerProperties::DraggingEnabled DragContainer::d_dragEnabledProperty;
    DragContainerProperties::DragThreshold   DragContainer::d_dragThresholdProperty;

    //////////////////////////////////////////////////////////////////////////

    DragContainer::DragContainer(const String& type, const String& name) :
        Window(type, name),
        d_draggingEnabled(true),
        d_leftMouseDown(false),
        d_dragging(false),
        d_dragThreshold(8.0f),
        d_dragAlpha(0.5f),
        d_dropTarget(0),
        d_dragCursorImage((const Image*)DefaultMouseCursor)
    {
        addDragContainerEvents();
        addDragContainerProperties();
    }

    DragContainer::~DragContainer(void)
    {
    }

    bool DragContainer::isDraggingEnabled(void) const
    {
        return d_draggingEnabled;
    }

    void DragContainer::setDraggingEnabled(bool setting)
    {
        if (d_draggingEnabled != setting)
        {
            d_draggingEnabled = setting;
            WindowEventArgs args(this);
            onDragEnabledChanged(args);
        }
    }

    bool DragContainer::isBeingDragged(void) const
    {
        return d_dragging;
    }

    float DragContainer::getPixelDragThreshold(void) const
    {
        return d_dragThreshold;
    }

    void DragContainer::setPixelDragThreshold(float pixels)
    {
        if (d_dragThreshold != pixels)
        {
            d_dragThreshold = pixels;
            WindowEventArgs args(this);
            onDragThresholdChanged(args);
        }
    }

    float DragContainer::getDragAlpha(void) const
    {
        return d_dragAlpha;
    }

    void DragContainer::setDragAlpha(float alpha)
    {
        if (d_dragAlpha != alpha)
        {
            d_dragAlpha = alpha;
            WindowEventArgs args(this);
            onDragAlphaChanged(args);
        }
    }

    const Image* DragContainer::getDragCursorImage(void) const
    {
        if (d_dragCursorImage == (const Image*)DefaultMouseCursor)
        {
            return System::getSingleton().getDefaultMouseCursor();
        }
        else
        {
            return d_dragCursorImage;
        }
    }

    void DragContainer::setDragCursorImage(const Image* image)
    {
        if (d_dragCursorImage != image)
        {
            d_dragCursorImage = image;
            WindowEventArgs args(this);
            onDragMouseCursorChanged(args);
        }
    }

    void DragContainer::setDragCursorImage(MouseCursorImage image)
    {
        setDragCursorImage((const Image*)image);
    }

    void DragContainer::setDragCursorImage(const String& imageset, const String& image)
    {
        setDragCursorImage(&ImagesetManager::getSingleton().getImageset(imageset)->getImage(image));
    }

    Window* DragContainer::getCurrentDropTarget(void) const
    {
        return d_dropTarget;
    }

    void DragContainer::addDragContainerEvents(void)
    {
        addEvent(EventDragStarted);
        addEvent(EventDragEnded);
        addEvent(EventDragPositionChanged);
        addEvent(EventDragEnabledChanged);
        addEvent(EventDragAlphaChanged);
        addEvent(EventDragMouseCursorChanged);
        addEvent(EventDragThresholdChanged);
        addEvent(EventDragDropTargetChanged);
    }

    void DragContainer::addDragContainerProperties(void)
    {
        addProperty(&d_dragEnabledProperty);
        addProperty(&d_dragAlphaProperty);
        addProperty(&d_dragThresholdProperty);
        addProperty(&d_dragCursorImageProperty);
    }

    bool DragContainer::isDraggingThresholdExceeded(const Point& local_mouse)
    {
        // calculate amount mouse has moved.
        float	deltaX = fabs(local_mouse.d_x - d_dragPoint.d_x);
        float	deltaY = fabs(local_mouse.d_y - d_dragPoint.d_y);

        // see if mouse has moved far enough to start dragging operation
        return (deltaX > d_dragThreshold || deltaY > d_dragThreshold) ? true : false;
    }

    void DragContainer::initialiseDragging(void)
    {
        // only proceed if dragging is actually enabled
        if (d_draggingEnabled)
        {
            // initialise drag moving state
            d_storedClipState = d_clippedByParent;
            setClippedByParent(false);
            d_storedAlpha = d_alpha;
            setAlpha(d_dragAlpha);
            d_startPosition = getPosition(Absolute);

            d_dragging = true;

            // Now drag mode is set, change cursor as required
            updateActiveMouseCursor();
        }
    }

    void DragContainer::doDragging(const Point& local_mouse)
    {
        setPosition(Absolute, getPosition(Absolute) + (local_mouse - d_dragPoint));

        WindowEventArgs args(this);
        onDragPositionChanged(args);
    }

    void DragContainer::updateActiveMouseCursor(void) const
    {
        MouseCursor::getSingleton().setImage(d_dragging ? getDragCursorImage() : getMouseCursor());
    }

    void DragContainer::drawSelf(float z)
    {
        // No rendering for this window
    }

    void DragContainer::onMouseButtonDown(MouseEventArgs& e)
    {
        Window::onMouseButtonDown(e);

        if (e.button == LeftButton)
        {
            // ensure all inputs come to us for now
            if (captureInput())
            {
                // get position of mouse as co-ordinates local to this window.
                Point localPos = (getMetricsMode() == Relative) ?
                    relativeToAbsolute(screenToWindow(e.position)) :
                    screenToWindow(e.position);

                // store drag point for possible sizing or moving operation.
                d_dragPoint = localPos;
                d_leftMouseDown = true;
            }

            e.handled = true;
        }

    }

    void DragContainer::onMouseButtonUp(MouseEventArgs& e)
    {
        Window::onMouseButtonUp(e);

        if (e.button == LeftButton)
        {
            if (d_dragging)
            {
                // fire off event
                WindowEventArgs args(this);
                onDragEnded(args);
            }

            // release our capture on the input data
            releaseInput();
            e.handled = true;
        }
    }

    void DragContainer::onMouseMove(MouseEventArgs& e)
    {
        Window::onMouseMove(e);

        // get position of mouse as co-ordinates local to this window.
        Point localMousePos = (getMetricsMode() == Relative) ?
            relativeToAbsolute(screenToWindow(e.position)) :
            screenToWindow(e.position);

        // handle dragging
        if (d_dragging)
        {
            doDragging(localMousePos);
       }
        // not dragging
        else
        {
            // if mouse button is down (but we're not yet being dragged)
            if (d_leftMouseDown)
            {
                if (isDraggingThresholdExceeded(localMousePos))
                {
                    // Trigger the event
                    WindowEventArgs args(this);
                    onDragStarted(args);
                }
            }
        }
    }

    void DragContainer::onCaptureLost(WindowEventArgs& e)
    {
        Window::onCaptureLost(e);

        // reset state
        if (d_dragging)
        {
            // restore windows 'normal' state.
            d_dragging = false;
            setPosition(Absolute, d_startPosition);
            setClippedByParent(d_storedClipState);
            setAlpha(d_storedAlpha);

            // restore normal mouse cursor
            updateActiveMouseCursor();
        }

        d_leftMouseDown = false;
        d_dropTarget = 0;

        e.handled = true;
    }

    void DragContainer::onAlphaChanged(WindowEventArgs& e)
    {
        // store new value and re-set dragging alpha as required.
        if (d_dragging)
        {
            d_storedAlpha = d_alpha;
            d_alpha = d_dragAlpha;
        }

        Window::onAlphaChanged(e);
    }

    void DragContainer::onClippingChanged(WindowEventArgs& e)
    {
        // store new value and re-set clipping for drag as required.
        if (d_dragging)
        {
            d_storedClipState = d_clippedByParent;
            d_clippedByParent = false;
        }

        Window::onClippingChanged(e);
    }

    void DragContainer::onDragStarted(WindowEventArgs& e)
    {
        initialiseDragging();

        fireEvent(EventDragStarted, e, EventNamespace);
    }

    void DragContainer::onDragEnded(WindowEventArgs& e)
    {
        fireEvent(EventDragEnded, e, EventNamespace);

        // did we drop over a window?
        if (d_dropTarget)
        {
            // Notify that item was dropped in the target window
            d_dropTarget->notifyDragDropItemDropped(this);
        }
    }

    void DragContainer::onDragPositionChanged(WindowEventArgs& e)
    {
        fireEvent(EventDragPositionChanged, e, EventNamespace);

        Window* root;

        if (0 != (root = System::getSingleton().getGUISheet()))
        {
            // this hack with the 'enabled' state is so that getChildAtPosition
            // returns something useful instead of a pointer back to 'this'.
            // This hack is only acceptable because I am CrazyEddie!
            bool wasEnabled = d_enabled;
            d_enabled = false;
            // find out which child of root window has the mouse in it
            Window* eventWindow = root->getChildAtPosition(MouseCursor::getSingleton().getPosition());
            d_enabled = wasEnabled;

            // use root itself if no child was hit
            if (!eventWindow)
            {
                eventWindow = root;
            }

            // if the window with the mouse is different to current drop target
            if (eventWindow != d_dropTarget)
            {
                DragDropEventArgs args(eventWindow);
                args.dragDropItem = this;
                onDragDropTargetChanged(args);
            }
        }
    }

    void DragContainer::onDragEnabledChanged(WindowEventArgs& e)
    {
        fireEvent(EventDragEnabledChanged, e, EventNamespace);

        // abort current drag operation if dragging gets disabled part way through
        if (!d_draggingEnabled && d_dragging)
        {
            releaseInput();
        }
    }

    void DragContainer::onDragAlphaChanged(WindowEventArgs& e)
    {
        fireEvent(EventDragAlphaChanged, e, EventNamespace);

        if (d_dragging)
        {
            d_alpha = d_storedAlpha;
            onAlphaChanged(e);
        }
    }

    void DragContainer::onDragMouseCursorChanged(WindowEventArgs& e)
    {
        fireEvent(EventDragMouseCursorChanged, e, EventNamespace);

        updateActiveMouseCursor();
    }

    void DragContainer::onDragThresholdChanged(WindowEventArgs& e)
    {
        fireEvent(EventDragThresholdChanged, e, EventNamespace);
    }

    void DragContainer::onDragDropTargetChanged(DragDropEventArgs& e)
    {
        fireEvent(EventDragDropTargetChanged, e, EventNamespace);

        // Notify old target that drop item has left
        if (d_dropTarget)
        {
            d_dropTarget->notifyDragDropItemLeaves(this);
        }

        // update to new target
        d_dropTarget = e.window;

        // Notify new target window that someone has dragged a DragContainer over it
        d_dropTarget->notifyDragDropItemEnters(this);
    }

} // End of  CEGUI namespace section
<|endoftext|>