<commit_before>/*
 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
 *
 * 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.
 */

#include "scene-graph-renderer-attachment.h"
#include <dali/internal/update/common/uniform-map.h>
#include <dali/internal/update/manager/prepare-render-instructions.h>
#include <dali/internal/update/rendering/scene-graph-geometry.h>
#include <dali/internal/update/rendering/scene-graph-material.h>
#include <dali/internal/update/rendering/scene-graph-sampler.h>
#include <dali/internal/update/resources/complete-status-manager.h>
#include <dali/internal/update/resources/resource-manager.h>
#include <dali/internal/render/data-providers/render-data-provider.h>
#include <dali/internal/render/queue/render-queue.h>
#include <dali/internal/render/renderers/render-renderer.h>
#include <dali/internal/render/shaders/scene-graph-shader.h>

#if defined(DEBUG_ENABLED)
Debug::Filter* gImageAttachmentLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_SCENE_GRAPH_IMAGE_ATTACHMENT");

#define ATTACHMENT_LOG(level)                                                 \
  DALI_LOG_INFO(gImageAttachmentLogFilter, level, "SceneGraph::ImageAttachment::%s: this:%p\n", __FUNCTION__, this)
#define ATTACHMENT_LOG_FMT(level, format, args...) \
  DALI_LOG_INFO(gImageAttachmentLogFilter, level, "SceneGraph::ImageAttachment::%s: this:%p " format, __FUNCTION__, this, ## args)

#else

#define ATTACHMENT_LOG(level)
#define ATTACHMENT_LOG_FMT(level, format, args...)

#endif

namespace // unnamed namespace
{
const int REGENERATE_UNIFORM_MAP = 2;
const int COPY_UNIFORM_MAP       = 1;
}

namespace Dali
{
namespace Internal
{
namespace SceneGraph
{

RendererAttachment* RendererAttachment::New()
{
  return new RendererAttachment();
}

RendererAttachment::RendererAttachment()
: RenderableAttachment( false ),
  mRenderer(NULL),
  mMaterial(NULL),
  mGeometry(NULL),
  mRegenerateUniformMap(REGENERATE_UNIFORM_MAP),
  mResendDataProviders(false),
  mDepthIndex(0)
{
  mUniformMapChanged[0]=false;
  mUniformMapChanged[1]=false;

  // Observe our own PropertyOwner's uniform map
  AddUniformMapObserver( *this );
}

RendererAttachment::~RendererAttachment()
{
  mMaterial->RemoveConnectionObserver(*this);
  mGeometry->RemoveConnectionObserver(*this);

  mMaterial=NULL;
  mGeometry=NULL;
}

void RendererAttachment::Initialize2( BufferIndex updateBufferIndex )
{
  DALI_ASSERT_DEBUG( mSceneController );
}

void RendererAttachment::OnDestroy2()
{
}

void RendererAttachment::ConnectedToSceneGraph()
{
  mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
  mParent->AddUniformMapObserver( *this ); // Watch actor's uniform maps

  DALI_ASSERT_DEBUG( mParent != NULL );

  RenderDataProvider* dataProvider = NewRenderDataProvider();

  mRenderer = NewRenderer::New( *mParent, dataProvider );
  mSceneController->GetRenderMessageDispatcher().AddRenderer( *mRenderer );
}

void RendererAttachment::DisconnectedFromSceneGraph()
{
  mRegenerateUniformMap = 0;
  mParent->RemoveUniformMapObserver( *this );

  DALI_ASSERT_DEBUG( mSceneController );
  mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mRenderer );
  mRenderer = NULL;
}

void RendererAttachment::SetMaterial( BufferIndex updateBufferIndex, Material* material)
{
  DALI_ASSERT_DEBUG( material != NULL && "Material pointer is NULL" );

  mMaterial = material;
  mMaterial->AddConnectionObserver( *this );
  mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;

  mResendDataProviders = true;
}

Material& RendererAttachment::GetMaterial()
{
  return *mMaterial;
}

void RendererAttachment::SetGeometry( BufferIndex updateBufferIndex, Geometry* geometry)
{
  DALI_ASSERT_DEBUG( geometry != NULL && "Geometry pointer is NULL");

  mGeometry = geometry;
  mGeometry->AddConnectionObserver( *this ); // Observe geometry connections / uniform mapping changes
  mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;

  mResendDataProviders = true;
}

Geometry& RendererAttachment::GetGeometry()
{
  return *mGeometry;
}

void RendererAttachment::SetSortAttributes( BufferIndex bufferIndex, RendererWithSortAttributes& sortAttributes )
{
  sortAttributes.shader = mMaterial->GetShader();
  sortAttributes.material = mMaterial;
  sortAttributes.geometry = mGeometry;
}

void RendererAttachment::SetDepthIndex( int depthIndex )
{
  mDepthIndex = depthIndex;

  if( mParent )
  {
    // only do this if we are on-stage. Ensures the render lists are re-sorted
    mParent->SetDirtyFlag( SortModifierFlag );
  }
}

Renderer& RendererAttachment::GetRenderer()
{
  return *mRenderer;
}

const Renderer& RendererAttachment::GetRenderer() const
{
  return *mRenderer;
}

// Called by ProcessRenderTasks after DoPrepareRender
bool RendererAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
{
  bool opaque = false;

  if( mMaterial != NULL )
  {
    Material::BlendPolicy blendPolicy = mMaterial->GetBlendPolicy();
    switch( blendPolicy )
    {
      case Material::OPAQUE:
      {
        opaque = true;
        break;
      }
      case Material::TRANSPARENT:
      {
        opaque = false;
        break;
      }
      case Material::USE_ACTOR_COLOR:
      {
        if( mParent )
        {
          opaque = mParent->GetWorldColor( updateBufferIndex ).a >= FULLY_OPAQUE;
        }
        break;
      }
    }
  }

  return opaque;
}

void RendererAttachment::SizeChanged( BufferIndex updateBufferIndex )
{
  // Do nothing.
}

bool RendererAttachment::DoPrepareResources(
  BufferIndex updateBufferIndex,
  ResourceManager& resourceManager )
{
  DALI_ASSERT_DEBUG( mSceneController );

  CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
  bool ready = false;
  mFinishedResourceAcquisition = false;

  // Can only be considered ready when all the scene graph objects are connected to the renderer
  if( ( mGeometry ) &&
      ( mGeometry->GetVertexBuffers().Count() > 0 ) &&
      ( mMaterial ) &&
      ( mMaterial->GetShader() != NULL ) )
  {
    unsigned int completeCount = 0;
    unsigned int neverCount = 0;
    unsigned int frameBufferCount = 0;

    Vector<Sampler*>& samplers = mMaterial->GetSamplers();
    for( Vector<Sampler*>::ConstIterator iter = samplers.Begin();
         iter != samplers.End(); ++iter )
    {
      Sampler* sampler = *iter;

      ResourceId textureId = sampler->GetTextureId( updateBufferIndex );
      BitmapMetadata metaData = resourceManager.GetBitmapMetadata( textureId );

      sampler->SetFullyOpaque( metaData.IsFullyOpaque() );

      switch( completeStatusManager.GetStatus( textureId ) )
      {
        case CompleteStatusManager::NOT_READY:
        {
          if( metaData.GetIsFramebuffer() )
          {
            frameBufferCount++;
          }
          FollowTracker( textureId ); // @todo MESH_REWORK Trackers per sampler rather than per actor?
        }
        break;

        case CompleteStatusManager::COMPLETE:
        {
          completeCount++;
        }
        break;

        case CompleteStatusManager::NEVER:
        {
          neverCount++;
        }
        break;
      }
    }

    // We are ready if all samplers are complete, or those that aren't are framebuffers
    // We are complete if all samplers are either complete or will never complete

    ready = ( completeCount + frameBufferCount >= samplers.Count() ) ;
    mFinishedResourceAcquisition = ( completeCount + neverCount >= samplers.Count() );
  }

  return ready;
}

// Uniform maps are checked in the following priority order:
//   Renderer (this object)
//   Actor
//   Material
//   Samplers
//   Shader
//   Geometry
//   VertexBuffers
void RendererAttachment::DoPrepareRender( BufferIndex updateBufferIndex )
{
  // @todo MESH_REWORK - call DoPrepareRender on all scene objects? in caller class?
  mMaterial->PrepareRender( updateBufferIndex );

  if( mRegenerateUniformMap > 0)
  {
    if( mRegenerateUniformMap == REGENERATE_UNIFORM_MAP)
    {
      DALI_ASSERT_DEBUG( mGeometry != NULL && "No geometry available in DoPrepareRender()" );
      DALI_ASSERT_DEBUG( mMaterial != NULL && "No geometry available in DoPrepareRender()" );

      CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
      localMap.Resize(0);

      const UniformMap& rendererUniformMap = PropertyOwner::GetUniformMap();
      AddMappings( localMap, rendererUniformMap );

      const UniformMap& actorUniformMap = mParent->GetUniformMap();
      AddMappings( localMap, actorUniformMap );

      AddMappings( localMap, mMaterial->GetUniformMap() );
      Vector<Sampler*>& samplers = mMaterial->GetSamplers();
      for( Vector<Sampler*>::ConstIterator iter = samplers.Begin(), end = samplers.End();
           iter != end ;
           ++iter )
      {
        const SceneGraph::Sampler* sampler = (*iter);
        AddMappings( localMap, sampler->GetUniformMap() );
      }

      AddMappings( localMap, mMaterial->GetShader()->GetUniformMap() );

      AddMappings( localMap, mGeometry->GetUniformMap() );

      Vector<PropertyBuffer*>& vertexBuffers = mGeometry->GetVertexBuffers();
      for( Vector<PropertyBuffer*>::ConstIterator iter = vertexBuffers.Begin(), end = vertexBuffers.End() ;
           iter != end ;
           ++iter )
      {
        const SceneGraph::PropertyBuffer* vertexBuffer = *iter;
        AddMappings( localMap, vertexBuffer->GetUniformMap() );
      }

      PropertyBuffer* indexBuffer = mGeometry->GetIndexBuffer();
      if( indexBuffer )
      {
        AddMappings( localMap, indexBuffer->GetUniformMap() );
      }

      mUniformMapChanged[updateBufferIndex] = true;
    }
    else if( mRegenerateUniformMap == COPY_UNIFORM_MAP )
    {
      // Copy old map into current map
      CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
      CollectedUniformMap& oldMap = mCollectedUniformMap[ 1-updateBufferIndex ];

      localMap.Resize( oldMap.Count() );

      unsigned int index=0;
      for( CollectedUniformMap::Iterator iter = oldMap.Begin(), end = oldMap.End() ; iter != end ; ++iter, ++index )
      {
        localMap[index] = *iter;
      }

      mUniformMapChanged[updateBufferIndex] = true;
    }

    mRegenerateUniformMap--;
  }

  bool geometryDataChanged = false;
  if( PropertyBuffer* indexBuffer = mGeometry->GetIndexBuffer() )
  {
    geometryDataChanged = indexBuffer->HasDataChanged(updateBufferIndex);
  }
  Vector<PropertyBuffer*>& vertexBuffers = mGeometry->GetVertexBuffers();
  Vector<PropertyBuffer*>::ConstIterator end = vertexBuffers.End();
  for( Vector<PropertyBuffer*>::Iterator it = vertexBuffers.Begin();
       it != end;
       ++it )
  {
    geometryDataChanged = geometryDataChanged || (*it)->HasDataChanged(updateBufferIndex);
  }
  if( geometryDataChanged )
  {
    //TODO: MESH_REWORK : use buffer data cache and remove all this
    typedef Message< NewRenderer > DerivedType;
    unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
    new (slot) DerivedType( mRenderer, &NewRenderer::SetGeometryUpdated );
  }

  if( mResendDataProviders )
  {
    RenderDataProvider* dataProvider = NewRenderDataProvider();

    // Tell renderer about a new provider
    // @todo MESH_REWORK Should we instead create a new renderer when these change?

    typedef MessageValue1< NewRenderer, OwnerPointer<RenderDataProvider> > DerivedType;
    unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
    new (slot) DerivedType( mRenderer, &NewRenderer::SetRenderDataProvider, dataProvider );
    mResendDataProviders = false;
  }
}

void RendererAttachment::ConnectionsChanged( PropertyOwner& object )
{
  // One of our child objects has changed it's connections. Ensure the uniform
  // map gets regenerated during PrepareRender
  mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;

  // Ensure the child object pointers get re-sent to the renderer
  mResendDataProviders = true;
}

void RendererAttachment::ConnectedUniformMapChanged()
{
  mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
}

void RendererAttachment::UniformMappingsChanged( const UniformMap& mappings )
{
  // The mappings are either from PropertyOwner base class, or the Actor
  mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
}

bool RendererAttachment::GetUniformMapChanged( BufferIndex bufferIndex ) const
{
  return mUniformMapChanged[bufferIndex];
}

const CollectedUniformMap& RendererAttachment::GetUniformMap( BufferIndex bufferIndex ) const
{
  return mCollectedUniformMap[ bufferIndex ];
}

void RendererAttachment::AddMappings( CollectedUniformMap& localMap, const UniformMap& uniformMap )
{
  // Iterate thru uniformMap.
  //   Any maps that aren't in localMap should be added in a single step
  CollectedUniformMap newUniformMappings;

  for( unsigned int i=0, count=uniformMap.Count(); i<count; ++i )
  {
    UniformPropertyMapping::Hash nameHash = uniformMap[i].uniformNameHash;
    bool found = false;

    for( CollectedUniformMap::Iterator iter = localMap.Begin() ; iter != localMap.End() ; ++iter )
    {
      const UniformPropertyMapping* map = (*iter);
      if( map->uniformNameHash == nameHash )
      {
        if( map->uniformName == uniformMap[i].uniformName )
        {
          found = true;
          break;
        }
      }
    }
    if( !found )
    {
      // it's a new mapping. Add raw ptr to temporary list
      newUniformMappings.PushBack( &uniformMap[i] );
    }
  }

  if( newUniformMappings.Count() > 0 )
  {
    localMap.Reserve( localMap.Count() + newUniformMappings.Count() );

    for( CollectedUniformMap::Iterator iter = newUniformMappings.Begin(),
           end = newUniformMappings.End() ;
         iter != end ;
         ++iter )
    {
      const UniformPropertyMapping* map = (*iter);
      localMap.PushBack( map );
    }
    //@todo MESH_REWORK Use memcpy to copy ptrs from one array to the other
  }
}

RenderDataProvider* RendererAttachment::NewRenderDataProvider()
{
  RenderDataProvider* dataProvider = new RenderDataProvider();

  dataProvider->mGeometryDataProvider = mGeometry;
  dataProvider->mMaterialDataProvider = mMaterial;
  dataProvider->mUniformMapDataProvider = this;
  dataProvider->mShader = mMaterial->GetShader();
  dataProvider->mIndexBuffer = mGeometry->GetIndexBuffer();

  Vector<PropertyBuffer*>& vertexBuffers = mGeometry->GetVertexBuffers();
  dataProvider->mVertexBuffers.Reserve( vertexBuffers.Count() );

  for( Vector<PropertyBuffer*>::Iterator iter = vertexBuffers.Begin() ;
       iter != vertexBuffers.End();
       ++iter )
  {
    dataProvider->mVertexBuffers.PushBack(*iter); // Convert from derived type to base type
  }

  Vector<Sampler*>& samplers = mMaterial->GetSamplers();
  dataProvider->mSamplers.Reserve( samplers.Count() );
  for( Vector<Sampler*>::Iterator iter = samplers.Begin() ;
       iter != samplers.End();
       ++iter )
  {
    dataProvider->mSamplers.PushBack(*iter); // Convert from derived type to base type
  }
  return dataProvider;
}

} // namespace SceneGraph
} // namespace Internal
} // namespace Dali
<commit_msg>Fix in RenderAttachment destructor<commit_after>/*
 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
 *
 * 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.
 */

#include "scene-graph-renderer-attachment.h"
#include <dali/internal/update/common/uniform-map.h>
#include <dali/internal/update/manager/prepare-render-instructions.h>
#include <dali/internal/update/rendering/scene-graph-geometry.h>
#include <dali/internal/update/rendering/scene-graph-material.h>
#include <dali/internal/update/rendering/scene-graph-sampler.h>
#include <dali/internal/update/resources/complete-status-manager.h>
#include <dali/internal/update/resources/resource-manager.h>
#include <dali/internal/render/data-providers/render-data-provider.h>
#include <dali/internal/render/queue/render-queue.h>
#include <dali/internal/render/renderers/render-renderer.h>
#include <dali/internal/render/shaders/scene-graph-shader.h>

#if defined(DEBUG_ENABLED)
Debug::Filter* gImageAttachmentLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_SCENE_GRAPH_IMAGE_ATTACHMENT");

#define ATTACHMENT_LOG(level)                                                 \
  DALI_LOG_INFO(gImageAttachmentLogFilter, level, "SceneGraph::ImageAttachment::%s: this:%p\n", __FUNCTION__, this)
#define ATTACHMENT_LOG_FMT(level, format, args...) \
  DALI_LOG_INFO(gImageAttachmentLogFilter, level, "SceneGraph::ImageAttachment::%s: this:%p " format, __FUNCTION__, this, ## args)

#else

#define ATTACHMENT_LOG(level)
#define ATTACHMENT_LOG_FMT(level, format, args...)

#endif

namespace // unnamed namespace
{
const int REGENERATE_UNIFORM_MAP = 2;
const int COPY_UNIFORM_MAP       = 1;
}

namespace Dali
{
namespace Internal
{
namespace SceneGraph
{

RendererAttachment* RendererAttachment::New()
{
  return new RendererAttachment();
}

RendererAttachment::RendererAttachment()
: RenderableAttachment( false ),
  mRenderer(NULL),
  mMaterial(NULL),
  mGeometry(NULL),
  mRegenerateUniformMap(REGENERATE_UNIFORM_MAP),
  mResendDataProviders(false),
  mDepthIndex(0)
{
  mUniformMapChanged[0]=false;
  mUniformMapChanged[1]=false;

  // Observe our own PropertyOwner's uniform map
  AddUniformMapObserver( *this );
}

RendererAttachment::~RendererAttachment()
{
  if (mMaterial)
  {
    mMaterial->RemoveConnectionObserver(*this);
    mMaterial=NULL;
  }
  if (mGeometry)
  {
    mGeometry->RemoveConnectionObserver(*this);
    mGeometry=NULL;
  }
}

void RendererAttachment::Initialize2( BufferIndex updateBufferIndex )
{
  DALI_ASSERT_DEBUG( mSceneController );
}

void RendererAttachment::OnDestroy2()
{
}

void RendererAttachment::ConnectedToSceneGraph()
{
  mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
  mParent->AddUniformMapObserver( *this ); // Watch actor's uniform maps

  DALI_ASSERT_DEBUG( mParent != NULL );

  RenderDataProvider* dataProvider = NewRenderDataProvider();

  mRenderer = NewRenderer::New( *mParent, dataProvider );
  mSceneController->GetRenderMessageDispatcher().AddRenderer( *mRenderer );
}

void RendererAttachment::DisconnectedFromSceneGraph()
{
  mRegenerateUniformMap = 0;
  mParent->RemoveUniformMapObserver( *this );

  DALI_ASSERT_DEBUG( mSceneController );
  mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mRenderer );
  mRenderer = NULL;
}

void RendererAttachment::SetMaterial( BufferIndex updateBufferIndex, Material* material)
{
  DALI_ASSERT_DEBUG( material != NULL && "Material pointer is NULL" );

  mMaterial = material;
  mMaterial->AddConnectionObserver( *this );
  mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;

  mResendDataProviders = true;
}

Material& RendererAttachment::GetMaterial()
{
  return *mMaterial;
}

void RendererAttachment::SetGeometry( BufferIndex updateBufferIndex, Geometry* geometry)
{
  DALI_ASSERT_DEBUG( geometry != NULL && "Geometry pointer is NULL");

  mGeometry = geometry;
  mGeometry->AddConnectionObserver( *this ); // Observe geometry connections / uniform mapping changes
  mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;

  mResendDataProviders = true;
}

Geometry& RendererAttachment::GetGeometry()
{
  return *mGeometry;
}

void RendererAttachment::SetSortAttributes( BufferIndex bufferIndex, RendererWithSortAttributes& sortAttributes )
{
  sortAttributes.shader = mMaterial->GetShader();
  sortAttributes.material = mMaterial;
  sortAttributes.geometry = mGeometry;
}

void RendererAttachment::SetDepthIndex( int depthIndex )
{
  mDepthIndex = depthIndex;

  if( mParent )
  {
    // only do this if we are on-stage. Ensures the render lists are re-sorted
    mParent->SetDirtyFlag( SortModifierFlag );
  }
}

Renderer& RendererAttachment::GetRenderer()
{
  return *mRenderer;
}

const Renderer& RendererAttachment::GetRenderer() const
{
  return *mRenderer;
}

// Called by ProcessRenderTasks after DoPrepareRender
bool RendererAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
{
  bool opaque = false;

  if( mMaterial != NULL )
  {
    Material::BlendPolicy blendPolicy = mMaterial->GetBlendPolicy();
    switch( blendPolicy )
    {
      case Material::OPAQUE:
      {
        opaque = true;
        break;
      }
      case Material::TRANSPARENT:
      {
        opaque = false;
        break;
      }
      case Material::USE_ACTOR_COLOR:
      {
        if( mParent )
        {
          opaque = mParent->GetWorldColor( updateBufferIndex ).a >= FULLY_OPAQUE;
        }
        break;
      }
    }
  }

  return opaque;
}

void RendererAttachment::SizeChanged( BufferIndex updateBufferIndex )
{
  // Do nothing.
}

bool RendererAttachment::DoPrepareResources(
  BufferIndex updateBufferIndex,
  ResourceManager& resourceManager )
{
  DALI_ASSERT_DEBUG( mSceneController );

  CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
  bool ready = false;
  mFinishedResourceAcquisition = false;

  // Can only be considered ready when all the scene graph objects are connected to the renderer
  if( ( mGeometry ) &&
      ( mGeometry->GetVertexBuffers().Count() > 0 ) &&
      ( mMaterial ) &&
      ( mMaterial->GetShader() != NULL ) )
  {
    unsigned int completeCount = 0;
    unsigned int neverCount = 0;
    unsigned int frameBufferCount = 0;

    Vector<Sampler*>& samplers = mMaterial->GetSamplers();
    for( Vector<Sampler*>::ConstIterator iter = samplers.Begin();
         iter != samplers.End(); ++iter )
    {
      Sampler* sampler = *iter;

      ResourceId textureId = sampler->GetTextureId( updateBufferIndex );
      BitmapMetadata metaData = resourceManager.GetBitmapMetadata( textureId );

      sampler->SetFullyOpaque( metaData.IsFullyOpaque() );

      switch( completeStatusManager.GetStatus( textureId ) )
      {
        case CompleteStatusManager::NOT_READY:
        {
          if( metaData.GetIsFramebuffer() )
          {
            frameBufferCount++;
          }
          FollowTracker( textureId ); // @todo MESH_REWORK Trackers per sampler rather than per actor?
        }
        break;

        case CompleteStatusManager::COMPLETE:
        {
          completeCount++;
        }
        break;

        case CompleteStatusManager::NEVER:
        {
          neverCount++;
        }
        break;
      }
    }

    // We are ready if all samplers are complete, or those that aren't are framebuffers
    // We are complete if all samplers are either complete or will never complete

    ready = ( completeCount + frameBufferCount >= samplers.Count() ) ;
    mFinishedResourceAcquisition = ( completeCount + neverCount >= samplers.Count() );
  }

  return ready;
}

// Uniform maps are checked in the following priority order:
//   Renderer (this object)
//   Actor
//   Material
//   Samplers
//   Shader
//   Geometry
//   VertexBuffers
void RendererAttachment::DoPrepareRender( BufferIndex updateBufferIndex )
{
  // @todo MESH_REWORK - call DoPrepareRender on all scene objects? in caller class?
  mMaterial->PrepareRender( updateBufferIndex );

  if( mRegenerateUniformMap > 0)
  {
    if( mRegenerateUniformMap == REGENERATE_UNIFORM_MAP)
    {
      DALI_ASSERT_DEBUG( mGeometry != NULL && "No geometry available in DoPrepareRender()" );
      DALI_ASSERT_DEBUG( mMaterial != NULL && "No geometry available in DoPrepareRender()" );

      CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
      localMap.Resize(0);

      const UniformMap& rendererUniformMap = PropertyOwner::GetUniformMap();
      AddMappings( localMap, rendererUniformMap );

      const UniformMap& actorUniformMap = mParent->GetUniformMap();
      AddMappings( localMap, actorUniformMap );

      AddMappings( localMap, mMaterial->GetUniformMap() );
      Vector<Sampler*>& samplers = mMaterial->GetSamplers();
      for( Vector<Sampler*>::ConstIterator iter = samplers.Begin(), end = samplers.End();
           iter != end ;
           ++iter )
      {
        const SceneGraph::Sampler* sampler = (*iter);
        AddMappings( localMap, sampler->GetUniformMap() );
      }

      AddMappings( localMap, mMaterial->GetShader()->GetUniformMap() );

      AddMappings( localMap, mGeometry->GetUniformMap() );

      Vector<PropertyBuffer*>& vertexBuffers = mGeometry->GetVertexBuffers();
      for( Vector<PropertyBuffer*>::ConstIterator iter = vertexBuffers.Begin(), end = vertexBuffers.End() ;
           iter != end ;
           ++iter )
      {
        const SceneGraph::PropertyBuffer* vertexBuffer = *iter;
        AddMappings( localMap, vertexBuffer->GetUniformMap() );
      }

      PropertyBuffer* indexBuffer = mGeometry->GetIndexBuffer();
      if( indexBuffer )
      {
        AddMappings( localMap, indexBuffer->GetUniformMap() );
      }

      mUniformMapChanged[updateBufferIndex] = true;
    }
    else if( mRegenerateUniformMap == COPY_UNIFORM_MAP )
    {
      // Copy old map into current map
      CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
      CollectedUniformMap& oldMap = mCollectedUniformMap[ 1-updateBufferIndex ];

      localMap.Resize( oldMap.Count() );

      unsigned int index=0;
      for( CollectedUniformMap::Iterator iter = oldMap.Begin(), end = oldMap.End() ; iter != end ; ++iter, ++index )
      {
        localMap[index] = *iter;
      }

      mUniformMapChanged[updateBufferIndex] = true;
    }

    mRegenerateUniformMap--;
  }

  bool geometryDataChanged = false;
  if( PropertyBuffer* indexBuffer = mGeometry->GetIndexBuffer() )
  {
    geometryDataChanged = indexBuffer->HasDataChanged(updateBufferIndex);
  }
  Vector<PropertyBuffer*>& vertexBuffers = mGeometry->GetVertexBuffers();
  Vector<PropertyBuffer*>::ConstIterator end = vertexBuffers.End();
  for( Vector<PropertyBuffer*>::Iterator it = vertexBuffers.Begin();
       it != end;
       ++it )
  {
    geometryDataChanged = geometryDataChanged || (*it)->HasDataChanged(updateBufferIndex);
  }
  if( geometryDataChanged )
  {
    //TODO: MESH_REWORK : use buffer data cache and remove all this
    typedef Message< NewRenderer > DerivedType;
    unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
    new (slot) DerivedType( mRenderer, &NewRenderer::SetGeometryUpdated );
  }

  if( mResendDataProviders )
  {
    RenderDataProvider* dataProvider = NewRenderDataProvider();

    // Tell renderer about a new provider
    // @todo MESH_REWORK Should we instead create a new renderer when these change?

    typedef MessageValue1< NewRenderer, OwnerPointer<RenderDataProvider> > DerivedType;
    unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
    new (slot) DerivedType( mRenderer, &NewRenderer::SetRenderDataProvider, dataProvider );
    mResendDataProviders = false;
  }
}

void RendererAttachment::ConnectionsChanged( PropertyOwner& object )
{
  // One of our child objects has changed it's connections. Ensure the uniform
  // map gets regenerated during PrepareRender
  mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;

  // Ensure the child object pointers get re-sent to the renderer
  mResendDataProviders = true;
}

void RendererAttachment::ConnectedUniformMapChanged()
{
  mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
}

void RendererAttachment::UniformMappingsChanged( const UniformMap& mappings )
{
  // The mappings are either from PropertyOwner base class, or the Actor
  mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
}

bool RendererAttachment::GetUniformMapChanged( BufferIndex bufferIndex ) const
{
  return mUniformMapChanged[bufferIndex];
}

const CollectedUniformMap& RendererAttachment::GetUniformMap( BufferIndex bufferIndex ) const
{
  return mCollectedUniformMap[ bufferIndex ];
}

void RendererAttachment::AddMappings( CollectedUniformMap& localMap, const UniformMap& uniformMap )
{
  // Iterate thru uniformMap.
  //   Any maps that aren't in localMap should be added in a single step
  CollectedUniformMap newUniformMappings;

  for( unsigned int i=0, count=uniformMap.Count(); i<count; ++i )
  {
    UniformPropertyMapping::Hash nameHash = uniformMap[i].uniformNameHash;
    bool found = false;

    for( CollectedUniformMap::Iterator iter = localMap.Begin() ; iter != localMap.End() ; ++iter )
    {
      const UniformPropertyMapping* map = (*iter);
      if( map->uniformNameHash == nameHash )
      {
        if( map->uniformName == uniformMap[i].uniformName )
        {
          found = true;
          break;
        }
      }
    }
    if( !found )
    {
      // it's a new mapping. Add raw ptr to temporary list
      newUniformMappings.PushBack( &uniformMap[i] );
    }
  }

  if( newUniformMappings.Count() > 0 )
  {
    localMap.Reserve( localMap.Count() + newUniformMappings.Count() );

    for( CollectedUniformMap::Iterator iter = newUniformMappings.Begin(),
           end = newUniformMappings.End() ;
         iter != end ;
         ++iter )
    {
      const UniformPropertyMapping* map = (*iter);
      localMap.PushBack( map );
    }
    //@todo MESH_REWORK Use memcpy to copy ptrs from one array to the other
  }
}

RenderDataProvider* RendererAttachment::NewRenderDataProvider()
{
  RenderDataProvider* dataProvider = new RenderDataProvider();

  dataProvider->mGeometryDataProvider = mGeometry;
  dataProvider->mMaterialDataProvider = mMaterial;
  dataProvider->mUniformMapDataProvider = this;
  dataProvider->mShader = mMaterial->GetShader();
  dataProvider->mIndexBuffer = mGeometry->GetIndexBuffer();

  Vector<PropertyBuffer*>& vertexBuffers = mGeometry->GetVertexBuffers();
  dataProvider->mVertexBuffers.Reserve( vertexBuffers.Count() );

  for( Vector<PropertyBuffer*>::Iterator iter = vertexBuffers.Begin() ;
       iter != vertexBuffers.End();
       ++iter )
  {
    dataProvider->mVertexBuffers.PushBack(*iter); // Convert from derived type to base type
  }

  Vector<Sampler*>& samplers = mMaterial->GetSamplers();
  dataProvider->mSamplers.Reserve( samplers.Count() );
  for( Vector<Sampler*>::Iterator iter = samplers.Begin() ;
       iter != samplers.End();
       ++iter )
  {
    dataProvider->mSamplers.PushBack(*iter); // Convert from derived type to base type
  }
  return dataProvider;
}

} // namespace SceneGraph
} // namespace Internal
} // namespace Dali
<|endoftext|>


<commit_before>/***********************************************************************
    created:    24/9/2004
    author:     Paul D Turner
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2008 Paul D Turner & The CEGUI Development Team
 *
 *   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 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 "Win32CEGuiRendererSelector.h"
#include <tchar.h>

/*************************************************************************
    Constructor
*************************************************************************/
Win32CEGuiRendererSelector::Win32CEGuiRendererSelector() :
        d_template(createDialogTemplate())
{}

/*************************************************************************
    Destructor
*************************************************************************/
Win32CEGuiRendererSelector::~Win32CEGuiRendererSelector()
{
    if (d_template)
    {
        LocalFree(d_template);
    }
}

/*************************************************************************
    Display the dialog and wait for user
*************************************************************************/
bool Win32CEGuiRendererSelector::invokeDialog()
{
    // dialog template was not created so abort.
    if (!d_template)
        return false;

    int renderer_count = 0;
    CEGuiRendererType first_available = InvalidGuiRendererType;

    // Check number of renderer modules available
    for (int i = 0; i < RendererTypeCount; ++i)
    {
        if (d_rendererAvailability[i])
        {
            ++renderer_count;

            if (first_available == InvalidGuiRendererType)
                first_available = static_cast<CEGuiRendererType>(i);
        }
    }

    // if there is only one renderer, select that one, but do not show dialog
    if (renderer_count == 1)
    {
        d_lastSelected = first_available;
        return true;
    }

    // multiple renderer modules available, so show dialog & return result
    return (1 == DialogBoxIndirectParam(GetModuleHandle(nullptr), d_template, nullptr, Win32CEGuiRendererSelector::dialogProcedure, reinterpret_cast<LPARAM>(this)));
}

/*************************************************************************
    Create Win32 dialog template
*************************************************************************/
LPDLGTEMPLATE Win32CEGuiRendererSelector::createDialogTemplate()
{
    SIZE_T  templateBufferSize = 1024;

    // allocate memory to hold the template we're going to construct
    LPDLGTEMPLATE dialogTemplate = static_cast<LPDLGTEMPLATE>(LocalAlloc(LPTR, templateBufferSize));

    // if allocation was successful
    if (dialogTemplate)
    {
        LPDLGITEMTEMPLATE item;
        LPBYTE buffer = reinterpret_cast<LPBYTE>(dialogTemplate);

        //
        // build template header
        //
        LPDLGTEMPLATE header    = reinterpret_cast<LPDLGTEMPLATE>(buffer);
        header->style           = DS_MODALFRAME|WS_CAPTION|WS_VISIBLE;
        header->dwExtendedStyle = 0;
        header->cdit            = 6;
        header->x               = static_cast<short>(0x8000);
        header->y               = static_cast<short>(0x8000);
        header->cx              = 150;
        header->cy              = 75;

        // advance buffer pointer
        buffer += sizeof(DLGTEMPLATE);

        //
        // Write null menu and class names
        //
        *reinterpret_cast<LPWORD>(buffer) = 0;
        buffer += sizeof(WORD);

        *reinterpret_cast<LPWORD>(buffer) = 0;
        buffer += sizeof(WORD);

        //
        // Write dialog title
        //
        int charCount = copyAnsiToWideChar(buffer, TEXT("CEGui - Renderer Selection"));
        buffer += charCount * sizeof(WORD);

        // align pointer for first item
        buffer = alignPointer(buffer);

        //
        // Buttons area static frame
        //
        item = reinterpret_cast<LPDLGITEMTEMPLATE>(buffer);
        item->style             = BS_GROUPBOX|WS_VISIBLE|WS_CHILD;
        item->dwExtendedStyle   = 0;
        item->x                 = 5;
        item->y                 = 48;
        item->cx                = 140;
        item->cy                = 22;
        item->id                = 0;

        // advance buffer pointer
        buffer += sizeof(DLGITEMTEMPLATE);

        // write class information
        *reinterpret_cast<LPWORD>(buffer) = 0xFFFF;
        buffer += sizeof(WORD);

        *reinterpret_cast<LPWORD>(buffer) = 0x0080;
        buffer += sizeof(WORD);

        // write caption
        charCount = copyAnsiToWideChar(buffer, TEXT(""));
        buffer += charCount * sizeof(WORD);

        // no creation data
        *reinterpret_cast<LPWORD>(buffer) = 0x0000;
        buffer += sizeof(WORD);

        // align pointer for next item
        buffer = alignPointer(buffer);

        //
        // Selection area static frame
        //
        item = reinterpret_cast<LPDLGITEMTEMPLATE>(buffer);
        item->style             = BS_GROUPBOX|WS_VISIBLE|WS_CHILD;
        item->dwExtendedStyle   = 0;
        item->x                 = 5;
        item->y                 = 0;
        item->cx                = 140;
        item->cy                = 50;
        item->id                = 0;

        // advance buffer pointer
        buffer += sizeof(DLGITEMTEMPLATE);

        // write class information
        *reinterpret_cast<LPWORD>(buffer) = 0xFFFF;
        buffer += sizeof(WORD);

        *reinterpret_cast<LPWORD>(buffer) = 0x0080;
        buffer += sizeof(WORD);

        // write caption
        charCount = copyAnsiToWideChar(buffer, TEXT(""));
        buffer += charCount * sizeof(WORD);

        // no creation data
        *reinterpret_cast<LPWORD>(buffer) = 0x0000;
        buffer += sizeof(WORD);

        // align pointer for next item
        buffer = alignPointer(buffer);

        //
        // Okay button
        //
        item = reinterpret_cast<LPDLGITEMTEMPLATE>(buffer);
        item->style             = BS_DEFPUSHBUTTON|WS_VISIBLE|WS_CHILD|WS_TABSTOP;
        item->dwExtendedStyle   = 0;
        item->x                 = 9;
        item->y                 = 55;
        item->cx                = 40;
        item->cy                = 12;
        item->id                = IDOK;

        // advance buffer pointer
        buffer += sizeof(DLGITEMTEMPLATE);

        // write class information
        *reinterpret_cast<LPWORD>(buffer) = 0xFFFF;
        buffer += sizeof(WORD);

        *reinterpret_cast<LPWORD>(buffer) = 0x0080;
        buffer += sizeof(WORD);

        // write caption
        charCount = copyAnsiToWideChar(buffer, TEXT("Go!"));
        buffer += charCount * sizeof(WORD);

        // no creation data
        *reinterpret_cast<LPWORD>(buffer) = 0x0000;
        buffer += sizeof(WORD);

        // align pointer for next item
        buffer = alignPointer(buffer);

        //
        // Cancel button
        //
        item = reinterpret_cast<LPDLGITEMTEMPLATE>(buffer);
        item->style             = BS_PUSHBUTTON|WS_VISIBLE|WS_CHILD|WS_TABSTOP;
        item->dwExtendedStyle   = 0;
        item->x                 = 101;
        item->y                 = 55;
        item->cx                = 40;
        item->cy                = 12;
        item->id                = IDCANCEL;

        // advance buffer pointer
        buffer += sizeof(DLGITEMTEMPLATE);

        // write class information
        *reinterpret_cast<LPWORD>(buffer) = 0xFFFF;
        buffer += sizeof(WORD);

        *reinterpret_cast<LPWORD>(buffer) = 0x0080;
        buffer += sizeof(WORD);

        // write caption
        charCount = copyAnsiToWideChar(buffer, TEXT("Cancel"));
        buffer += charCount * sizeof(WORD);

        // no creation data
        *reinterpret_cast<LPWORD>(buffer) = 0x0000;
        buffer += sizeof(WORD);

        // align pointer for next item
        buffer = alignPointer(buffer);

        //
        // Combo label
        //
        item = reinterpret_cast<LPDLGITEMTEMPLATE>(buffer);
        item->style             = SS_LEFT|WS_VISIBLE|WS_CHILD|WS_TABSTOP;
        item->dwExtendedStyle   = 0;
        item->x                 = 8;
        item->y                 = 7;
        item->cx                = 130;
        item->cy                = 12;
        item->id                = 0;

        // advance buffer pointer
        buffer += sizeof(DLGITEMTEMPLATE);

        // write class information
        *reinterpret_cast<LPWORD>(buffer) = 0xFFFF;
        buffer += sizeof(WORD);

        *reinterpret_cast<LPWORD>(buffer) = 0x0082;
        buffer += sizeof(WORD);

        // write caption
        charCount = copyAnsiToWideChar(buffer, TEXT("Select Renderer to Use:"));
        buffer += charCount * sizeof(WORD);

        // no creation data
        *reinterpret_cast<LPWORD>(buffer) = 0x0000;
        buffer += sizeof(WORD);

        // align pointer for next item
        buffer = alignPointer(buffer);

        //
        // Combobox
        //
        item = reinterpret_cast<LPDLGITEMTEMPLATE>(buffer);
        item->style             = CBS_DROPDOWNLIST|WS_VISIBLE|WS_CHILD;
        item->dwExtendedStyle   = 0;
        item->x                 = 8;
        item->y                 = 19;
        item->cx                = 130;
        item->cy                = 100;
        item->id                = 1000;

        // advance buffer pointer
        buffer += sizeof(DLGITEMTEMPLATE);

        // write class information
        *reinterpret_cast<LPWORD>(buffer) = 0xFFFF;
        buffer += sizeof(WORD);

        *reinterpret_cast<LPWORD>(buffer) = 0x0085;
        buffer += sizeof(WORD);

        // write caption
        charCount = copyAnsiToWideChar(buffer, TEXT(""));
        buffer += charCount * sizeof(WORD);

        // no creation data
        *reinterpret_cast<LPWORD>(buffer) = 0x0000;
        buffer += sizeof(WORD);

        // align pointer for next item
        buffer = alignPointer(buffer);

        return dialogTemplate;
    }

    return nullptr;
}

/*************************************************************************
    Checks availability of a renderer type and adds an entry to the
    combo box if it's available.  Returns true if the item was added.
*************************************************************************/
bool Win32CEGuiRendererSelector::addComboboxOption(HWND combo, const char* name, CEGuiRendererType rendererType)
{
    if (d_rendererAvailability[rendererType])
    {
        int idx = static_cast<int>(SendMessage(combo, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(name)));
        SendMessage(combo, CB_SETITEMDATA, idx, rendererType);

        // pre-select this item if it's the first one added.
        if (idx == 0)
        {
            SendMessage(combo, CB_SETCURSEL, 0, 0);
            d_lastSelected = rendererType;
        }
    }

    return d_rendererAvailability[rendererType];
}

/*************************************************************************
    Win32 dialog procedure function
*************************************************************************/
INT_PTR CALLBACK Win32CEGuiRendererSelector::dialogProcedure(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
    case WM_INITDIALOG:
        {
            // get the 'this' ptr we were passed
            Win32CEGuiRendererSelector* obj = reinterpret_cast<Win32CEGuiRendererSelector*>(lParam);

            // set as window long for future use
            SetWindowLongPtr(hDlg, DWLP_USER, static_cast<LONG_PTR>(lParam));

            //
            // Set-up combo box list
            //
            // get combo control
            HWND combo = GetDlgItem(hDlg, 1000);

            if (combo)
            {
                // clear old data
                SendMessage(combo, CB_RESETCONTENT, 0, 0);

                // add new stings according to if item is enabled or not
                obj->addComboboxOption(combo, "OpenGL 3.2 Core Renderer", OpenGL3GuiRendererType);
                obj->addComboboxOption(combo, "OpenGL ES 2.0 Renderer", OpenglEs2GuiRendererType);
                obj->addComboboxOption(combo, "OpenGL ES 2.0 Alternate Renderer", OpenglEs2AlternateGuiRendererType);
                obj->addComboboxOption(combo, "OpenGL Renderer", OpenGLGuiRendererType);
                obj->addComboboxOption(combo, "Ogre Engine Renderer", OgreGuiRendererType);
                obj->addComboboxOption(combo, "Microsoft Direct3D 11 Renderer", Direct3D11GuiRendererType);
                obj->addComboboxOption(combo, "Irrlicht Engine Renderer", IrrlichtGuiRendererType);
            }

            return FALSE;
        }

    case WM_COMMAND:
        switch(LOWORD(wParam))
        {
        case IDOK:
            EndDialog(hDlg, 1);
            return TRUE;

        case IDCANCEL:
            EndDialog(hDlg, 0);
            return TRUE;

            // Combo-box
        case 1000:
            switch(HIWORD(wParam))
            {
            case CBN_SELENDOK:
                {
                    HWND combo = reinterpret_cast<HWND>(lParam);

                    // get the 'this' ptr for the object we were created by
                    Win32CEGuiRendererSelector* obj = reinterpret_cast<Win32CEGuiRendererSelector*>(GetWindowLongPtr(hDlg, DWLP_USER));

                    int idx = static_cast<int>(SendMessage(combo, CB_GETCURSEL, 0, 0));

                    if (idx != CB_ERR)
                    {
                        // set last selected renderer type
                        obj->d_lastSelected = static_cast<CEGuiRendererType>(SendMessage(combo, CB_GETITEMDATA, idx, 0));
                    }

                    return TRUE;
                }
            }
        }

        break;
    }

    return FALSE;
}

/*************************************************************************
    Take an input pointer, return closest pointer that is aligned on a
    DWORD (4 byte) boundary.
*************************************************************************/
LPBYTE Win32CEGuiRendererSelector::alignPointer(LPBYTE buff)
{
    DWORD_PTR ul = reinterpret_cast<DWORD_PTR>(buff);
    ul +=3;
    ul >>=2;
    ul <<=2;
    return reinterpret_cast<LPBYTE>(ul);
}

/*************************************************************************
    Converts the Ansi string in 'pAnsiIn' into wide characters and
    copies the result into the WORD array at 'pWCStr'.
*************************************************************************/
int Win32CEGuiRendererSelector::copyAnsiToWideChar(LPBYTE outBuff, PCTSTR ansiString)
{
    LPWSTR pWCStr = reinterpret_cast<LPWSTR>(outBuff);

#   ifdef UNICODE
    return lstrlen(lstrcpy(pWCStr, ansiString)) + 1;
#   else
    int cchAnsi = lstrlen(ansiString);
    return MultiByteToWideChar(GetACP(), MB_PRECOMPOSED, ansiString, cchAnsi, pWCStr, cchAnsi) + 1;
#   endif
}
<commit_msg>Minor warning fix<commit_after>/***********************************************************************
    created:    24/9/2004
    author:     Paul D Turner
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2008 Paul D Turner & The CEGUI Development Team
 *
 *   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 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 "Win32CEGuiRendererSelector.h"
#include <tchar.h>

/*************************************************************************
    Constructor
*************************************************************************/
Win32CEGuiRendererSelector::Win32CEGuiRendererSelector() :
        d_template(createDialogTemplate())
{}

/*************************************************************************
    Destructor
*************************************************************************/
Win32CEGuiRendererSelector::~Win32CEGuiRendererSelector()
{
    if (d_template)
    {
        LocalFree(d_template);
    }
}

/*************************************************************************
    Display the dialog and wait for user
*************************************************************************/
bool Win32CEGuiRendererSelector::invokeDialog()
{
    // dialog template was not created so abort.
    if (!d_template)
        return false;

    int renderer_count = 0;
    CEGuiRendererType first_available = InvalidGuiRendererType;

    // Check number of renderer modules available
    for (int i = 0; i < RendererTypeCount; ++i)
    {
        if (d_rendererAvailability[i])
        {
            ++renderer_count;

            if (first_available == InvalidGuiRendererType)
                first_available = static_cast<CEGuiRendererType>(i);
        }
    }

    // if there is only one renderer, select that one, but do not show dialog
    if (renderer_count == 1)
    {
        d_lastSelected = first_available;
        return true;
    }

    // multiple renderer modules available, so show dialog & return result
    return (1 == DialogBoxIndirectParam(GetModuleHandle(nullptr), d_template, nullptr, Win32CEGuiRendererSelector::dialogProcedure, reinterpret_cast<LPARAM>(this)));
}

/*************************************************************************
    Create Win32 dialog template
*************************************************************************/
LPDLGTEMPLATE Win32CEGuiRendererSelector::createDialogTemplate()
{
    SIZE_T  templateBufferSize = 1024;

    // allocate memory to hold the template we're going to construct
    LPDLGTEMPLATE dialogTemplate = static_cast<LPDLGTEMPLATE>(LocalAlloc(LPTR, templateBufferSize));

    // if allocation was successful
    if (dialogTemplate)
    {
        LPDLGITEMTEMPLATE item;
        LPBYTE buffer = reinterpret_cast<LPBYTE>(dialogTemplate);

        //
        // build template header
        //
        LPDLGTEMPLATE header    = reinterpret_cast<LPDLGTEMPLATE>(buffer);
        header->style           = DS_MODALFRAME|WS_CAPTION|WS_VISIBLE;
        header->dwExtendedStyle = 0;
        header->cdit            = 6;
        header->x               = 20;
        header->y               = 20;
        header->cx              = 150;
        header->cy              = 75;

        // advance buffer pointer
        buffer += sizeof(DLGTEMPLATE);

        //
        // Write null menu and class names
        //
        *reinterpret_cast<LPWORD>(buffer) = 0;
        buffer += sizeof(WORD);

        *reinterpret_cast<LPWORD>(buffer) = 0;
        buffer += sizeof(WORD);

        //
        // Write dialog title
        //
        int charCount = copyAnsiToWideChar(buffer, TEXT("CEGui - Renderer Selection"));
        buffer += charCount * sizeof(WORD);

        // align pointer for first item
        buffer = alignPointer(buffer);

        //
        // Buttons area static frame
        //
        item = reinterpret_cast<LPDLGITEMTEMPLATE>(buffer);
        item->style             = BS_GROUPBOX|WS_VISIBLE|WS_CHILD;
        item->dwExtendedStyle   = 0;
        item->x                 = 5;
        item->y                 = 48;
        item->cx                = 140;
        item->cy                = 22;
        item->id                = 0;

        // advance buffer pointer
        buffer += sizeof(DLGITEMTEMPLATE);

        // write class information
        *reinterpret_cast<LPWORD>(buffer) = 0xFFFF;
        buffer += sizeof(WORD);

        *reinterpret_cast<LPWORD>(buffer) = 0x0080;
        buffer += sizeof(WORD);

        // write caption
        charCount = copyAnsiToWideChar(buffer, TEXT(""));
        buffer += charCount * sizeof(WORD);

        // no creation data
        *reinterpret_cast<LPWORD>(buffer) = 0x0000;
        buffer += sizeof(WORD);

        // align pointer for next item
        buffer = alignPointer(buffer);

        //
        // Selection area static frame
        //
        item = reinterpret_cast<LPDLGITEMTEMPLATE>(buffer);
        item->style             = BS_GROUPBOX|WS_VISIBLE|WS_CHILD;
        item->dwExtendedStyle   = 0;
        item->x                 = 5;
        item->y                 = 0;
        item->cx                = 140;
        item->cy                = 50;
        item->id                = 0;

        // advance buffer pointer
        buffer += sizeof(DLGITEMTEMPLATE);

        // write class information
        *reinterpret_cast<LPWORD>(buffer) = 0xFFFF;
        buffer += sizeof(WORD);

        *reinterpret_cast<LPWORD>(buffer) = 0x0080;
        buffer += sizeof(WORD);

        // write caption
        charCount = copyAnsiToWideChar(buffer, TEXT(""));
        buffer += charCount * sizeof(WORD);

        // no creation data
        *reinterpret_cast<LPWORD>(buffer) = 0x0000;
        buffer += sizeof(WORD);

        // align pointer for next item
        buffer = alignPointer(buffer);

        //
        // Okay button
        //
        item = reinterpret_cast<LPDLGITEMTEMPLATE>(buffer);
        item->style             = BS_DEFPUSHBUTTON|WS_VISIBLE|WS_CHILD|WS_TABSTOP;
        item->dwExtendedStyle   = 0;
        item->x                 = 9;
        item->y                 = 55;
        item->cx                = 40;
        item->cy                = 12;
        item->id                = IDOK;

        // advance buffer pointer
        buffer += sizeof(DLGITEMTEMPLATE);

        // write class information
        *reinterpret_cast<LPWORD>(buffer) = 0xFFFF;
        buffer += sizeof(WORD);

        *reinterpret_cast<LPWORD>(buffer) = 0x0080;
        buffer += sizeof(WORD);

        // write caption
        charCount = copyAnsiToWideChar(buffer, TEXT("Go!"));
        buffer += charCount * sizeof(WORD);

        // no creation data
        *reinterpret_cast<LPWORD>(buffer) = 0x0000;
        buffer += sizeof(WORD);

        // align pointer for next item
        buffer = alignPointer(buffer);

        //
        // Cancel button
        //
        item = reinterpret_cast<LPDLGITEMTEMPLATE>(buffer);
        item->style             = BS_PUSHBUTTON|WS_VISIBLE|WS_CHILD|WS_TABSTOP;
        item->dwExtendedStyle   = 0;
        item->x                 = 101;
        item->y                 = 55;
        item->cx                = 40;
        item->cy                = 12;
        item->id                = IDCANCEL;

        // advance buffer pointer
        buffer += sizeof(DLGITEMTEMPLATE);

        // write class information
        *reinterpret_cast<LPWORD>(buffer) = 0xFFFF;
        buffer += sizeof(WORD);

        *reinterpret_cast<LPWORD>(buffer) = 0x0080;
        buffer += sizeof(WORD);

        // write caption
        charCount = copyAnsiToWideChar(buffer, TEXT("Cancel"));
        buffer += charCount * sizeof(WORD);

        // no creation data
        *reinterpret_cast<LPWORD>(buffer) = 0x0000;
        buffer += sizeof(WORD);

        // align pointer for next item
        buffer = alignPointer(buffer);

        //
        // Combo label
        //
        item = reinterpret_cast<LPDLGITEMTEMPLATE>(buffer);
        item->style             = SS_LEFT|WS_VISIBLE|WS_CHILD|WS_TABSTOP;
        item->dwExtendedStyle   = 0;
        item->x                 = 8;
        item->y                 = 7;
        item->cx                = 130;
        item->cy                = 12;
        item->id                = 0;

        // advance buffer pointer
        buffer += sizeof(DLGITEMTEMPLATE);

        // write class information
        *reinterpret_cast<LPWORD>(buffer) = 0xFFFF;
        buffer += sizeof(WORD);

        *reinterpret_cast<LPWORD>(buffer) = 0x0082;
        buffer += sizeof(WORD);

        // write caption
        charCount = copyAnsiToWideChar(buffer, TEXT("Select Renderer to Use:"));
        buffer += charCount * sizeof(WORD);

        // no creation data
        *reinterpret_cast<LPWORD>(buffer) = 0x0000;
        buffer += sizeof(WORD);

        // align pointer for next item
        buffer = alignPointer(buffer);

        //
        // Combobox
        //
        item = reinterpret_cast<LPDLGITEMTEMPLATE>(buffer);
        item->style             = CBS_DROPDOWNLIST|WS_VISIBLE|WS_CHILD;
        item->dwExtendedStyle   = 0;
        item->x                 = 8;
        item->y                 = 19;
        item->cx                = 130;
        item->cy                = 100;
        item->id                = 1000;

        // advance buffer pointer
        buffer += sizeof(DLGITEMTEMPLATE);

        // write class information
        *reinterpret_cast<LPWORD>(buffer) = 0xFFFF;
        buffer += sizeof(WORD);

        *reinterpret_cast<LPWORD>(buffer) = 0x0085;
        buffer += sizeof(WORD);

        // write caption
        charCount = copyAnsiToWideChar(buffer, TEXT(""));
        buffer += charCount * sizeof(WORD);

        // no creation data
        *reinterpret_cast<LPWORD>(buffer) = 0x0000;
        buffer += sizeof(WORD);

        // align pointer for next item
        buffer = alignPointer(buffer);

        return dialogTemplate;
    }

    return nullptr;
}

/*************************************************************************
    Checks availability of a renderer type and adds an entry to the
    combo box if it's available.  Returns true if the item was added.
*************************************************************************/
bool Win32CEGuiRendererSelector::addComboboxOption(HWND combo, const char* name, CEGuiRendererType rendererType)
{
    if (d_rendererAvailability[rendererType])
    {
        int idx = static_cast<int>(SendMessage(combo, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(name)));
        SendMessage(combo, CB_SETITEMDATA, idx, rendererType);

        // pre-select this item if it's the first one added.
        if (idx == 0)
        {
            SendMessage(combo, CB_SETCURSEL, 0, 0);
            d_lastSelected = rendererType;
        }
    }

    return d_rendererAvailability[rendererType];
}

/*************************************************************************
    Win32 dialog procedure function
*************************************************************************/
INT_PTR CALLBACK Win32CEGuiRendererSelector::dialogProcedure(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
    case WM_INITDIALOG:
        {
            // get the 'this' ptr we were passed
            Win32CEGuiRendererSelector* obj = reinterpret_cast<Win32CEGuiRendererSelector*>(lParam);

            // set as window long for future use
            SetWindowLongPtr(hDlg, DWLP_USER, static_cast<LONG_PTR>(lParam));

            //
            // Set-up combo box list
            //
            // get combo control
            HWND combo = GetDlgItem(hDlg, 1000);

            if (combo)
            {
                // clear old data
                SendMessage(combo, CB_RESETCONTENT, 0, 0);

                // add new stings according to if item is enabled or not
                obj->addComboboxOption(combo, "OpenGL 3.2 Core Renderer", OpenGL3GuiRendererType);
                obj->addComboboxOption(combo, "OpenGL ES 2.0 Renderer", OpenglEs2GuiRendererType);
                obj->addComboboxOption(combo, "OpenGL ES 2.0 Alternate Renderer", OpenglEs2AlternateGuiRendererType);
                obj->addComboboxOption(combo, "OpenGL Renderer", OpenGLGuiRendererType);
                obj->addComboboxOption(combo, "Ogre Engine Renderer", OgreGuiRendererType);
                obj->addComboboxOption(combo, "Microsoft Direct3D 11 Renderer", Direct3D11GuiRendererType);
                obj->addComboboxOption(combo, "Irrlicht Engine Renderer", IrrlichtGuiRendererType);
            }

            return FALSE;
        }

    case WM_COMMAND:
        switch(LOWORD(wParam))
        {
        case IDOK:
            EndDialog(hDlg, 1);
            return TRUE;

        case IDCANCEL:
            EndDialog(hDlg, 0);
            return TRUE;

            // Combo-box
        case 1000:
            switch(HIWORD(wParam))
            {
            case CBN_SELENDOK:
                {
                    HWND combo = reinterpret_cast<HWND>(lParam);

                    // get the 'this' ptr for the object we were created by
                    Win32CEGuiRendererSelector* obj = reinterpret_cast<Win32CEGuiRendererSelector*>(GetWindowLongPtr(hDlg, DWLP_USER));

                    int idx = static_cast<int>(SendMessage(combo, CB_GETCURSEL, 0, 0));

                    if (idx != CB_ERR)
                    {
                        // set last selected renderer type
                        obj->d_lastSelected = static_cast<CEGuiRendererType>(SendMessage(combo, CB_GETITEMDATA, idx, 0));
                    }

                    return TRUE;
                }
            }
        }

        break;
    }

    return FALSE;
}

/*************************************************************************
    Take an input pointer, return closest pointer that is aligned on a
    DWORD (4 byte) boundary.
*************************************************************************/
LPBYTE Win32CEGuiRendererSelector::alignPointer(LPBYTE buff)
{
    DWORD_PTR ul = reinterpret_cast<DWORD_PTR>(buff);
    ul +=3;
    ul >>=2;
    ul <<=2;
    return reinterpret_cast<LPBYTE>(ul);
}

/*************************************************************************
    Converts the Ansi string in 'pAnsiIn' into wide characters and
    copies the result into the WORD array at 'pWCStr'.
*************************************************************************/
int Win32CEGuiRendererSelector::copyAnsiToWideChar(LPBYTE outBuff, PCTSTR ansiString)
{
    LPWSTR pWCStr = reinterpret_cast<LPWSTR>(outBuff);

#   ifdef UNICODE
    return lstrlen(lstrcpy(pWCStr, ansiString)) + 1;
#   else
    int cchAnsi = lstrlen(ansiString);
    return MultiByteToWideChar(GetACP(), MB_PRECOMPOSED, ansiString, cchAnsi, pWCStr, cchAnsi) + 1;
#   endif
}
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <algorithm>

#include "cnn/cnn.h"
#include "cnn/cuda.h"

using namespace std;

namespace cnn {

cublasHandle_t cublas_handle;

static void RemoveArgs(int& argc, char**& argv, int& argi, int n) {
  for (int i = argi + n; i < argc; ++i)
    argv[i - n] = argv[i];
  argc -= n;
  assert(argc >= 0);
}

#define MAX_GPUS 256

vector<Device*> Initialize_GPU(int& argc, char**& argv) {
  int nDevices;
  CUDA_CHECK(cudaGetDeviceCount(&nDevices));
  if (nDevices < 1) {
    cerr << "[cnn] No GPUs found, recompile without DENABLE_CUDA=1\n";
    throw std::runtime_error("No GPUs found but CNN compiled with CUDA support.");
  }
  // logic: no flags, you get 1 GPU
  // or you request a certain number of GPUs explicitly
  // or you request the device ids
  int requested_gpus = -1;
  vector<int> gpu_mask(MAX_GPUS,0);
  int argi = 1;
  bool ngpus_requested = false;
  bool ids_requested = false;
  for( ;argi < argc; ++argi) {
    string arg = argv[argi];
    if (arg == "--cnn_gpus" || arg == "--cnn-gpus") {
      if ((argi + 1) > argc) {
        cerr << "[cnn] --cnn-gpus expects an argument (number of GPUs to use)\n";
        abort();
      } else {
        if (ngpus_requested) {
          cerr << "Multiple instances of --cnn-gpus" << endl; abort();
        }
        ngpus_requested = true;
        string a2 = argv[argi+1];
        istringstream c(a2); c >> requested_gpus;
        RemoveArgs(argc, argv, argi, 2);
      }
    } else if (arg == "--cnn_gpu_ids" || arg == "--cnn-gpu-ids") {
      if ((argi + 1) > argc) {
        cerr << "[cnn] --cnn-gpu-ids expects an argument (comma separated list of physical GPU ids to use)\n";
        abort();
      } else {
        string a2 = argv[argi+1];
        if (ids_requested) {
          cerr << "Multiple instances of --cnn-gpu-ids" << endl; abort();
        }
        ids_requested = true;
        if (a2.size() % 2 != 1) {
          cerr << "Bad argument to --cnn-gpu-ids: " << a2 << endl; abort();
        }
        for (unsigned i = 0; i < a2.size(); ++i) {
          if ((i % 2 == 0 && (a2[i] < '0' || a2[i] > '9')) ||
              (i % 2 == 1 && a2[i] != ',')) {
            cerr << "Bad argument to --cnn-gpu-ids: " << a2 << endl; abort();
          }
          if (i % 2 == 0) {
            int gpu_id = a2[i] - '0';
            if (gpu_id >= nDevices) {
              cerr << "You requested GPU id " << gpu_id << " but system only reports up to " << nDevices << endl;
              abort();
            }
            if (gpu_id >= MAX_GPUS) { cerr << "Raise MAX_GPUS\n"; abort(); }
            gpu_mask[gpu_id]++;
            requested_gpus++;
            if (gpu_mask[gpu_id] != 1) {
              cerr << "Bad argument to --cnn-gpu-ids: " << a2 << endl; abort();
            }
          }
        }
        RemoveArgs(argc, argv, argi, 2);
      }
    }
  }
  if (ids_requested && ngpus_requested) {
    cerr << "Use only --cnn_gpus or --cnn_gpu_ids, not both\n";
    abort();
  }
  if (ngpus_requested || requested_gpus == -1) {
    if (requested_gpus == -1) requested_gpus = 1;
    cerr << "Request for " << requested_gpus << " GPU" << (requested_gpus == 1 ? "" : "s") << " ...\n";
    for (int i = 0; i < MAX_GPUS; ++i) gpu_mask[i] = 1;
  } else if (ids_requested) {
    requested_gpus++;
    cerr << "[cnn] Request for " << requested_gpus << " specific GPU" << (requested_gpus == 1 ? "" : "s") << " ...\n";
  }

  vector<Device*> gpudevices;
  if (requested_gpus == 0) return gpudevices;
  if (requested_gpus > nDevices) {
    cerr << "You requested " << requested_gpus << " GPUs but system only reports " << nDevices << endl;
    abort();
  }

  // after all that, requested_gpus is the number of GPUs to reserve
  // we now pick the ones that are both requested by the user or have
  // the most memory free

  vector<size_t> gpu_free_mem(MAX_GPUS, 0);
  vector<int> gpus(MAX_GPUS, 0);
  for (int i = 0; i < MAX_GPUS; ++i) gpus[i] = i;
  size_t free_bytes, total_bytes, max_free = 0;
  int selected = 0;
  for (int i = 0; i < nDevices; i++) {
    if (!gpu_mask[i]) continue;
    cudaDeviceProp prop;
    CUDA_CHECK(cudaGetDeviceProperties(&prop, i));
    cerr << "[cnn] Device Number: " << i << endl;
    cerr << "[cnn]   Device name: " << prop.name << endl;
    cerr << "[cnn]   Memory Clock Rate (KHz): " << prop.memoryClockRate << endl;
    cerr << "[cnn]   Memory Bus Width (bits): " << prop.memoryBusWidth << endl;
    cerr << "[cnn]   Peak Memory Bandwidth (GB/s): " << (2.0*prop.memoryClockRate*(prop.memoryBusWidth/8)/1.0e6) << endl;
    if (!prop.unifiedAddressing) {
      cerr << "[cnn] GPU does not support unified addressing.\n";
      abort();
    }
    CUDA_CHECK(cudaSetDevice(i));
    CUDA_CHECK(cudaMemGetInfo( &free_bytes, &total_bytes ));
    CUDA_CHECK(cudaDeviceReset());
    cerr << "[cnn]   Memory Free (GB): " << free_bytes/1.0e9 << "/" << total_bytes/1.0e9 << endl;
    cerr << "[cnn]" << endl;
    gpu_free_mem[i] = free_bytes;
  }
  stable_sort(gpus.begin(), gpus.end(), [&](int a, int b) -> bool { return gpu_free_mem[a] > gpu_free_mem[b]; });
  gpus.resize(requested_gpus);
  cerr << "[cnn] Device(s) selected:";
  for (int i = 0; i < requested_gpus; ++i) {
    cerr << ' ' << gpus[i];
    int mb = 512;
    Device* d = new Device_GPU(mb, gpus[i]);
    gpudevices.push_back(d);
  }
  cerr << endl;

  // eventually kill the global handle
  CUDA_CHECK(cudaSetDevice(gpus[0]));
  CUBLAS_CHECK(cublasCreate(&cublas_handle));
  CUBLAS_CHECK(cublasSetPointerMode(cublas_handle, CUBLAS_POINTER_MODE_DEVICE));
  return gpudevices;
}

} // namespace cnn
<commit_msg>Made it possible to specify memory on GPU<commit_after>#include <iostream>
#include <vector>
#include <algorithm>

#include "cnn/cnn.h"
#include "cnn/cuda.h"

using namespace std;

namespace cnn {

cublasHandle_t cublas_handle;

static void RemoveArgs(int& argc, char**& argv, int& argi, int n) {
  for (int i = argi + n; i < argc; ++i)
    argv[i - n] = argv[i];
  argc -= n;
  assert(argc >= 0);
}

#define MAX_GPUS 256

vector<Device*> Initialize_GPU(int& argc, char**& argv) {
  int nDevices;
  CUDA_CHECK(cudaGetDeviceCount(&nDevices));
  if (nDevices < 1) {
    cerr << "[cnn] No GPUs found, recompile without DENABLE_CUDA=1\n";
    throw std::runtime_error("No GPUs found but CNN compiled with CUDA support.");
  }
  // logic: no flags, you get 1 GPU
  // or you request a certain number of GPUs explicitly
  // or you request the device ids
  int requested_gpus = -1;
  vector<int> gpu_mask(MAX_GPUS,0);
  int argi = 1;
  int num_mb = 512;
  bool ngpus_requested = false;
  bool ids_requested = false;
  for( ;argi < argc; ++argi) {
    string arg = argv[argi];
    if (arg == "--cnn-mem" || arg == "--cnn_mem") {
      if ((argi + 1) > argc) {
        cerr << "[cnn] --cnn-mem expects an argument (the memory, in megabytes, to reserve)\n";
        abort();
      } else {
        string a2 = argv[argi+1];
        istringstream c(a2); c >> num_mb;
        RemoveArgs(argc, argv, argi, 2);
      }
    } else if (arg == "--cnn_gpus" || arg == "--cnn-gpus") {
      if ((argi + 1) > argc) {
        cerr << "[cnn] --cnn-gpus expects an argument (number of GPUs to use)\n";
        abort();
      } else {
        if (ngpus_requested) {
          cerr << "Multiple instances of --cnn-gpus" << endl; abort();
        }
        ngpus_requested = true;
        string a2 = argv[argi+1];
        istringstream c(a2); c >> requested_gpus;
        RemoveArgs(argc, argv, argi, 2);
      }
    } else if (arg == "--cnn_gpu_ids" || arg == "--cnn-gpu-ids") {
      if ((argi + 1) > argc) {
        cerr << "[cnn] --cnn-gpu-ids expects an argument (comma separated list of physical GPU ids to use)\n";
        abort();
      } else {
        string a2 = argv[argi+1];
        if (ids_requested) {
          cerr << "Multiple instances of --cnn-gpu-ids" << endl; abort();
        }
        ids_requested = true;
        if (a2.size() % 2 != 1) {
          cerr << "Bad argument to --cnn-gpu-ids: " << a2 << endl; abort();
        }
        for (unsigned i = 0; i < a2.size(); ++i) {
          if ((i % 2 == 0 && (a2[i] < '0' || a2[i] > '9')) ||
              (i % 2 == 1 && a2[i] != ',')) {
            cerr << "Bad argument to --cnn-gpu-ids: " << a2 << endl; abort();
          }
          if (i % 2 == 0) {
            int gpu_id = a2[i] - '0';
            if (gpu_id >= nDevices) {
              cerr << "You requested GPU id " << gpu_id << " but system only reports up to " << nDevices << endl;
              abort();
            }
            if (gpu_id >= MAX_GPUS) { cerr << "Raise MAX_GPUS\n"; abort(); }
            gpu_mask[gpu_id]++;
            requested_gpus++;
            if (gpu_mask[gpu_id] != 1) {
              cerr << "Bad argument to --cnn-gpu-ids: " << a2 << endl; abort();
            }
          }
        }
        RemoveArgs(argc, argv, argi, 2);
      }
    }
  }
  if (ids_requested && ngpus_requested) {
    cerr << "Use only --cnn_gpus or --cnn_gpu_ids, not both\n";
    abort();
  }
  if (ngpus_requested || requested_gpus == -1) {
    if (requested_gpus == -1) requested_gpus = 1;
    cerr << "Request for " << requested_gpus << " GPU" << (requested_gpus == 1 ? "" : "s") << " ...\n";
    for (int i = 0; i < MAX_GPUS; ++i) gpu_mask[i] = 1;
  } else if (ids_requested) {
    requested_gpus++;
    cerr << "[cnn] Request for " << requested_gpus << " specific GPU" << (requested_gpus == 1 ? "" : "s") << " ...\n";
  }

  vector<Device*> gpudevices;
  if (requested_gpus == 0) return gpudevices;
  if (requested_gpus > nDevices) {
    cerr << "You requested " << requested_gpus << " GPUs but system only reports " << nDevices << endl;
    abort();
  }

  // after all that, requested_gpus is the number of GPUs to reserve
  // we now pick the ones that are both requested by the user or have
  // the most memory free

  vector<size_t> gpu_free_mem(MAX_GPUS, 0);
  vector<int> gpus(MAX_GPUS, 0);
  for (int i = 0; i < MAX_GPUS; ++i) gpus[i] = i;
  size_t free_bytes, total_bytes, max_free = 0;
  int selected = 0;
  for (int i = 0; i < nDevices; i++) {
    if (!gpu_mask[i]) continue;
    cudaDeviceProp prop;
    CUDA_CHECK(cudaGetDeviceProperties(&prop, i));
    cerr << "[cnn] Device Number: " << i << endl;
    cerr << "[cnn]   Device name: " << prop.name << endl;
    cerr << "[cnn]   Memory Clock Rate (KHz): " << prop.memoryClockRate << endl;
    cerr << "[cnn]   Memory Bus Width (bits): " << prop.memoryBusWidth << endl;
    cerr << "[cnn]   Peak Memory Bandwidth (GB/s): " << (2.0*prop.memoryClockRate*(prop.memoryBusWidth/8)/1.0e6) << endl;
    if (!prop.unifiedAddressing) {
      cerr << "[cnn] GPU does not support unified addressing.\n";
      abort();
    }
    CUDA_CHECK(cudaSetDevice(i));
    CUDA_CHECK(cudaMemGetInfo( &free_bytes, &total_bytes ));
    CUDA_CHECK(cudaDeviceReset());
    cerr << "[cnn]   Memory Free (GB): " << free_bytes/1.0e9 << "/" << total_bytes/1.0e9 << endl;
    cerr << "[cnn]" << endl;
    gpu_free_mem[i] = free_bytes;
  }
  stable_sort(gpus.begin(), gpus.end(), [&](int a, int b) -> bool { return gpu_free_mem[a] > gpu_free_mem[b]; });
  gpus.resize(requested_gpus);
  cerr << "[cnn] Device(s) selected:";
  for (int i = 0; i < requested_gpus; ++i) {
    cerr << ' ' << gpus[i];
    Device* d = new Device_GPU(num_mb, gpus[i]);
    gpudevices.push_back(d);
  }
  cerr << endl;

  // eventually kill the global handle
  CUDA_CHECK(cudaSetDevice(gpus[0]));
  CUBLAS_CHECK(cublasCreate(&cublas_handle));
  CUBLAS_CHECK(cublasSetPointerMode(cublas_handle, CUBLAS_POINTER_MODE_DEVICE));
  return gpudevices;
}

} // namespace cnn
<|endoftext|>


<commit_before>/*
 * Chemharp, an efficient IO library for chemistry file formats
 * Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
*/

#ifndef HARP_ATOM_HPP
#define HARP_ATOM_HPP

#include <string>
#include <vector>
#include <map>

namespace harp {

/*!
 * @class Atom Atom.hpp Atom.cpp
 * @brief Atom representation class
 */
class Atom {
public:
    enum AtomType {
        //! Element from the periodic table of elements
        ELEMENT,
        //! Corse-grained atom: CH4, …
        CORSE_GRAIN,
        //! Dummy site, with no physical reality
        DUMMY,
        //! Undefined atom-type
        UNDEFINED
    };

    Atom(const std::string& name);
    Atom(AtomType type, const std::string& name = "");
    Atom();
    Atom(const Atom &) = default;
    Atom& operator=(const Atom &) = default;

    bool operator==(const Atom& other) const{
        return (_name == other._name && _mass == other._mass &&
                _charge == other._charge && _type == other._type);
    }

    ~Atom(){};

    //! Get a const (non-modifiable) reference to the atom name
    const std::string& name(void) const {return _name;}
    //! Get a const (non-modifiable) reference to the atom mass
    const float& mass(void) const {return _mass;}
    //! Get a const (non-modifiable) reference to the atom charge
    const float& charge(void) const {return _charge;}
    //! Get a const (non-modifiable) reference to the atom type
    const AtomType& type(void) const {return _type;}

    //! Set the atom name
    void name(const std::string& n) {_name = n;}
    //! Set the atom mass
    void mass(float m) {_mass = m;}
    //! Set the atom charge
    void charge(float c) {_charge = c;}
    //! Set the atom type
    void type(AtomType t) {_type = t;}

    //! Try to get the full element name, return and empty string if this is
    //! impossible
    std::string full_name() const;
    //! Try to get the Van der Waals or the covalent radius of the atom. Returns
    //! -1 if they can not be found.
    float vdw_radius() const;
    float covalent_radius() const;
    //! Try to get the atomic number, if defined. Return -1 if it can not be found.
    int atomic_number() const;
private:
    std::string _name;
    float _mass;
    float _charge;
    AtomType _type;
};

//! All the elements in the periodic table
const std::vector<std::string> ALL_ELEMENTS = std::vector<std::string>{
"H" ,                                                                                "He",
"Li", "Be",                                                             "B" , "C" , "N" , "O" , "F" , "Ne",
"Na", "Mg",                                                             "Al", "Si", "P" , "S" , "Cl", "Ar",
"K" , "Ca", "Sc", "Ti", "V" , "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", "As", "Se", "Br", "Kr",
"Rb", "Sr", "Y" , "Zr", "Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ar", "Cd", "In", "Sn", "Sb", "Te", "I" , "Xe",
"Cs", "Ba", "La", "Hf", "Ta", "W" , "Re", "Os", "Ir", "Pt", "Au", "Hg", "Ti", "Pb", "Bi", "Po", "At", "Rn",
"Fr", "Ra", "Ac", "Rf", "Db", "Sg", "Bh", "Hs", "Mt", "Ds", "Rg", "Cn",

"Ce", "Pr", "Nd", "Pm", "Sm", "Eu", "Gd", "Tb", "Dy", "Ho", "Er", "Tm", "Yb", "Lu",
"Th", "Pa", "U" , "Np", "Pu", "Am", "Cm", "Bk", "Cf", "Es", "Fm", "Md", "No", "Lr"
};

} // namespace harp

#endif
<commit_msg>Add atom output, usefull for debugging<commit_after>/*
 * Chemharp, an efficient IO library for chemistry file formats
 * Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
*/

#ifndef HARP_ATOM_HPP
#define HARP_ATOM_HPP

#include <iostream>
#include <string>
#include <vector>
#include <map>

namespace harp {

/*!
 * @class Atom Atom.hpp Atom.cpp
 * @brief Atom representation class
 */
class Atom {
public:
    enum AtomType {
        //! Element from the periodic table of elements
        ELEMENT,
        //! Corse-grained atom: CH4, …
        CORSE_GRAIN,
        //! Dummy site, with no physical reality
        DUMMY,
        //! Undefined atom-type
        UNDEFINED
    };

    Atom(const std::string& name);
    Atom(AtomType type, const std::string& name = "");
    Atom();
    Atom(const Atom &) = default;
    Atom& operator=(const Atom &) = default;

    bool operator==(const Atom& other) const{
        return (_name == other._name && _mass == other._mass &&
                _charge == other._charge && _type == other._type);
    }

    ~Atom(){};

    //! Get a const (non-modifiable) reference to the atom name
    const std::string& name(void) const {return _name;}
    //! Get a const (non-modifiable) reference to the atom mass
    const float& mass(void) const {return _mass;}
    //! Get a const (non-modifiable) reference to the atom charge
    const float& charge(void) const {return _charge;}
    //! Get a const (non-modifiable) reference to the atom type
    const AtomType& type(void) const {return _type;}

    //! Set the atom name
    void name(const std::string& n) {_name = n;}
    //! Set the atom mass
    void mass(float m) {_mass = m;}
    //! Set the atom charge
    void charge(float c) {_charge = c;}
    //! Set the atom type
    void type(AtomType t) {_type = t;}

    //! Try to get the full element name, return and empty string if this is
    //! impossible
    std::string full_name() const;
    //! Try to get the Van der Waals or the covalent radius of the atom. Returns
    //! -1 if they can not be found.
    float vdw_radius() const;
    float covalent_radius() const;
    //! Try to get the atomic number, if defined. Return -1 if it can not be found.
    int atomic_number() const;
private:
    std::string _name;
    float _mass;
    float _charge;
    AtomType _type;
};

inline std::ostream& operator<<(std::ostream& out, const Atom& atom){
    out << "Atom \"" << atom.name() << "\"";
    return out;
}

//! All the elements in the periodic table
const std::vector<std::string> ALL_ELEMENTS = std::vector<std::string>{
"H" ,                                                                                "He",
"Li", "Be",                                                             "B" , "C" , "N" , "O" , "F" , "Ne",
"Na", "Mg",                                                             "Al", "Si", "P" , "S" , "Cl", "Ar",
"K" , "Ca", "Sc", "Ti", "V" , "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", "As", "Se", "Br", "Kr",
"Rb", "Sr", "Y" , "Zr", "Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ar", "Cd", "In", "Sn", "Sb", "Te", "I" , "Xe",
"Cs", "Ba", "La", "Hf", "Ta", "W" , "Re", "Os", "Ir", "Pt", "Au", "Hg", "Ti", "Pb", "Bi", "Po", "At", "Rn",
"Fr", "Ra", "Ac", "Rf", "Db", "Sg", "Bh", "Hs", "Mt", "Ds", "Rg", "Cn",

"Ce", "Pr", "Nd", "Pm", "Sm", "Eu", "Gd", "Tb", "Dy", "Ho", "Er", "Tm", "Yb", "Lu",
"Th", "Pa", "U" , "Np", "Pu", "Am", "Cm", "Bk", "Cf", "Es", "Fm", "Md", "No", "Lr"
};

} // namespace harp

#endif
<|endoftext|>


<commit_before>/*
 * Copyright 2013-2014 gtalent2@gmail.com
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
#include "personclass.hpp"

namespace wombat {
namespace world {

using models::SpriteDirection;
using models::SpriteMotion;

core::Flyweight<models::PersonClass> PersonClass::c_personClasses(
	[](models::PersonClass model) {
		if (model.Import != "") {
			core::read(model, model.Import);
		}
		return new PersonClass(model);
	}
);

PersonClass::PersonClass(models::PersonClass model) {
	m_title = model.Title[core::getLanguage()];

	m_animations.resize(model.Overhead.size());
	for (uint i = 0; i < model.Overhead.size(); i++) {
		m_animations[i].resize(model.Overhead[i].size());
		for (uint ii = 0; ii < model.Overhead[i].size(); ii++) {
			m_animations[i][ii].load(model.Overhead[i][ii]);
		}
	}
}

void PersonClass::draw(core::Graphics &gfx, common::Point pt, SpriteDirection facing, SpriteMotion motion) {
	auto anim = this->anim(facing, motion);
	if (anim.animation) {
		gfx.draw(anim.animation->getImage(), pt + anim.point);
	}
}

AnimLayer PersonClass::anim(models::SpriteDirection facing, models::SpriteMotion motion) {
	if ((uint) facing < m_animations.size() && (uint) motion < m_animations[(uint) facing].size()) {
		return m_animations[(uint) facing][(uint) motion];
	}
	return AnimLayer();
}

PersonClass *PersonClass::checkout(models::PersonClass model) {
	return dynamic_cast<PersonClass*>(c_personClasses.checkout(model));
}

PersonClass *PersonClass::checkout(std::string path) {
	return dynamic_cast<PersonClass*>(c_personClasses.checkout(path));
}

void PersonClass::checkin(PersonClass *pc) {
	c_personClasses.checkin(pc);
}

}
}
<commit_msg>Added code to make PersonClass use the North Still AnimLayer if the appropriate on isn't available.<commit_after>/*
 * Copyright 2013-2014 gtalent2@gmail.com
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
#include "personclass.hpp"

namespace wombat {
namespace world {

using models::SpriteDirection;
using models::SpriteMotion;

core::Flyweight<models::PersonClass> PersonClass::c_personClasses(
	[](models::PersonClass model) {
		if (model.Import != "") {
			core::read(model, model.Import);
		}
		return new PersonClass(model);
	}
);

PersonClass::PersonClass(models::PersonClass model) {
	m_title = model.Title[core::getLanguage()];

	m_animations.resize(model.Overhead.size());
	for (uint i = 0; i < model.Overhead.size(); i++) {
		m_animations[i].resize(model.Overhead[i].size());
		for (uint ii = 0; ii < model.Overhead[i].size(); ii++) {
			m_animations[i][ii].load(model.Overhead[i][ii]);
		}
	}
}

void PersonClass::draw(core::Graphics &gfx, common::Point pt, SpriteDirection facing, SpriteMotion motion) {
	auto anim = this->anim(facing, motion);
	if (anim.animation) {
		gfx.draw(anim.animation->getImage(), pt + anim.point);
	}
}

AnimLayer PersonClass::anim(SpriteDirection facing, SpriteMotion motion) {
	for (int i = 0; i < 2; i++) {
		if ((uint) facing < m_animations.size() && (uint) motion < m_animations[(uint) facing].size()) {
			return m_animations[(uint) facing][(uint) motion];
		}
		facing = (SpriteDirection) 0;
		motion = (SpriteMotion) 0;
	}
	return AnimLayer();
}

PersonClass *PersonClass::checkout(models::PersonClass model) {
	return dynamic_cast<PersonClass*>(c_personClasses.checkout(model));
}

PersonClass *PersonClass::checkout(std::string path) {
	return dynamic_cast<PersonClass*>(c_personClasses.checkout(path));
}

void PersonClass::checkin(PersonClass *pc) {
	c_personClasses.checkin(pc);
}

}
}
<|endoftext|>