<commit_before>//==============================================================================

#include <game.hpp>
#include <engine.hpp>
#include <entity.hpp>
#include <entity_manager.hpp>
#include <clump_manager.hpp>
#include <viewport.hpp>
#include <fujin.hpp>
#include <cloud.hpp>
#include <girder.hpp>
#include <score.hpp>

#include <hgeresource.h>

#include <algorithm>

namespace
{
    const float ZOOM[5] = { 1.0f, 1.8f, 3.2f, 5.8f, 10.5f };

    bool
    lessThan( const Entity * left, const Entity * right )
    {
        if ( left->getScale() < right->getScale() * 0.99f )
        {
            return true;
        }
        if ( left->getScale() * 0.99f > right->getScale() )
        {
            return false;
        }
        if ( left->getType() < right->getType() )
        {
            return true;
        }
        return false;
    }
}

//==============================================================================
Game::Game()
    :
    Context(),
    m_last_zoom( 1.0f ),
    m_zoom( 0 ),
    m_fujin( 0 )
{
}

//------------------------------------------------------------------------------
Game::~Game()
{
}

//------------------------------------------------------------------------------
// public:
//------------------------------------------------------------------------------
void
Game::init()
{
    HGE * hge( Engine::hge() );
    b2World * b2d( Engine::b2d() );
    hgeResourceManager * rm( Engine::rm() );
    ViewPort * vp( Engine::vp() );

    notifyOnCollision( true );

    Fujin::registerEntity();
    Cloud::registerEntity();
    Girder::registerEntity();

    m_zoom = 0;

	m_timeRemaining = 300;
	m_score = 0;
    Engine::em()->init();
	Engine::cm()->init();

    vp->offset().x = 0.0f;
    vp->offset().y = 0.0f;
    vp->bounds().x = 800.0f;
    vp->bounds().y = 600.0f;
    vp->setAngle( 0.0f );
    vp->setScale( ZOOM[m_zoom] );

    m_fujin = static_cast< Fujin * >( Engine::em()->factory( Fujin::TYPE ) );
    b2Vec2 position( 0.0f, 0.0f );
    float angle( 0.0f );
    m_fujin->setSprite( "fujin" );
    m_fujin->setScale( 1.0f / ZOOM[m_zoom] );
    m_fujin->init();
    m_fujin->getBody()->SetXForm( position, angle );

    for ( int zoom = 0; zoom < 5; ++ zoom )
    {
	for (int i = 0; i < 8; ++i)
	{
		Entity* entity = Engine::em()->factory( Cloud::TYPE );
		b2Vec2 position( Engine::hge()->Random_Float( -400.0f, 400.0f),
                         Engine::hge()->Random_Float( -300.0f, 300.0f) );
		float angle( 0.f );
		entity->setSprite( "cloud" );
		entity->setScale( 1.0f / ZOOM[zoom] );
		entity->init();
		entity->getBody()->SetXForm( position, angle );
        static_cast< Cloud * >( entity )->setZoom( zoom );
	}
    }

    _initArena();
}

//------------------------------------------------------------------------------
void
Game::fini()
{
    notifyOnCollision( false );

    Engine::cm()->fini();
	Engine::em()->fini();
}

//------------------------------------------------------------------------------
bool
Game::update( float dt )
{
	m_timeRemaining -= dt;
    const Controller & pad( Engine::instance()->getController() );
    HGE * hge( Engine::hge() );
    ViewPort * vp( Engine::vp() );

    if ( pad.buttonDown( XPAD_BUTTON_BUTTON_Y ) )
    {
        Engine::instance()->switchContext( STATE_SCORE );
        Context * context( Engine::instance()->getContext() );
        static_cast< Score * >( context )->setValue( 13 );
        return false;
    }

	Engine::cm()->update( dt );
    Engine::em()->update( dt );

    if ( Engine::instance()->isPaused() )
    {
        return false;
    }

    if ( pad.isConnected() )
    {
        if ( pad.buttonDown( XPAD_BUTTON_LEFT_SHOULDER ) && m_zoom > 0 )
        {
            --m_zoom;
        }
        else if ( pad.buttonDown( XPAD_BUTTON_RIGHT_SHOULDER ) && m_zoom < 4 )
        {
            ++m_zoom;
        }
    }
    else
    {
        if ( ( Engine::hge()->Input_KeyDown( HGEK_Q ) ||
               hge->Input_GetMouseWheel() < 0 ) && m_zoom > 0 )
        {
            --m_zoom;
        }
        else if ( ( Engine::hge()->Input_KeyDown( HGEK_E ) ||
                    hge->Input_GetMouseWheel() > 0 ) && m_zoom < 4 )
        {
            ++m_zoom;
        }
    }

    if ( ZOOM[m_zoom] > m_last_zoom )
    {
        m_last_zoom += ( ZOOM[m_zoom] - m_last_zoom ) * dt * 10.0f;
        vp->setScale( m_last_zoom );
        m_fujin->setScale( 1.0f / m_last_zoom );
    }
    else if ( ZOOM[m_zoom] < m_last_zoom )
    {
        m_last_zoom += ( ZOOM[m_zoom] - m_last_zoom ) * dt * 10.0f;
        vp->setScale( m_last_zoom );
        m_fujin->setScale( 1.0f / m_last_zoom );
    }

    vp->offset() = m_fujin->getBody()->GetPosition();

    return false;
}

//------------------------------------------------------------------------------
void
Game::render()
{
	hgeResourceManager * rm( Engine::rm() );
	hgeFont* font = Engine::rm()->GetFont("menu");
	b2Vec2 timeTextLocation (700,10);
	b2Vec2 scoreTextLocation(0,10);
	char timeRemainingText[10];
	sprintf_s(timeRemainingText,"%d:%d",(int)m_timeRemaining/60,(int)(m_timeRemaining)%60);

	char scoreText[15];
	sprintf_s(scoreText,"Score: %5d",m_score);

    ViewPort * vp( Engine::vp() );

    vp->setTransform();

	// render time remaining
    rm->GetSprite( "polluted" )->RenderEx( 0.0f, 0.0f, 0.0f, 2.0f );

//	scoreTextLocation.x =m_zoom-1 * vp->offset().x;
	//scoreTextLocation.y=m_zoom-1 * vp->offset().y;

    std::vector< Entity * > entities;
    for ( b2Body * body( Engine::b2d()->GetBodyList() ); body != NULL;
          body = body->GetNext() )
    {
        Entity * entity( static_cast< Entity * >( body->GetUserData() ) );
        if ( entity )
        {
            entities.push_back( entity );
        }
    }

    std::sort( entities.begin(), entities.end(), lessThan );

    std::vector< Entity * >::iterator i;
    float scale( 1.0f / static_cast< float >( ZOOM[m_zoom] ) );
    for ( i = entities.begin(); i != entities.end(); ++i )
    {
        Entity * entity( * i );
        entity->render( scale );
    }

	Engine::hge()->Gfx_SetTransform();
	font->SetColor(0xFFFFFFFF);
	font->Render( timeTextLocation.x, timeTextLocation.y, HGETEXT_LEFT, timeRemainingText );
	font->Render( scoreTextLocation.x, scoreTextLocation.y, HGETEXT_LEFT, scoreText );

}

//------------------------------------------------------------------------------
bool
Game::shouldCollide( Entity * left, Entity * right )
{
    if ( left->getType() == Girder::TYPE ||
         right->getType() == Girder::TYPE )
    {
        return true;
    }

    if ( left->getScale() > right->getScale() * 0.99f &&
         left->getScale() * 0.99f < right->getScale() )
    {
        return left->getType() == right->getType();
    }

    return false;
}

//------------------------------------------------------------------------------
// private:
//------------------------------------------------------------------------------
void
Game::_initArena()
{
    b2Vec2 position( 0.0f, 0.0f );
    b2Vec2 dimensions( 0.0f, 0.0f );
    Entity * entity( 0 );

    for ( int i = 0; i < 4; ++i )
    {
        switch( i )
        {
            case 0:
            {
                dimensions.x = 800.0f;
                dimensions.y = 1.0f;
                position.x = 0.0f;
                position.y = -300.0f;
                break;
            }
            case 1:
            {
                dimensions.x = 1.0f;
                dimensions.y = 600.0f;
                position.x = 400.0f;
                position.y = 0.0f;
                break;
            }
            case 2:
            {
                dimensions.x = 800.0f;
                dimensions.y = 1.0f;
                position.x = 0.0f;
                position.y = 300.0f;
                break;
            }
            case 3:
            {
                dimensions.x = 1.0f;
                dimensions.y = 600.0f;
                position.x = -400.0f;
                position.y = 0.0f;
                break;
            }
        }
        Girder * girder( static_cast< Girder * >(
            Engine::em()->factory( Girder::TYPE ) ) );
        girder->setScale( 1.0f );
        girder->setDimensions( dimensions );
        girder->init();
        girder->getBody()->SetXForm( position, 0.0f );
    }
}
<commit_msg>set the timer so it will run out<commit_after>//==============================================================================

#include <game.hpp>
#include <engine.hpp>
#include <entity.hpp>
#include <entity_manager.hpp>
#include <clump_manager.hpp>
#include <viewport.hpp>
#include <fujin.hpp>
#include <cloud.hpp>
#include <girder.hpp>
#include <score.hpp>

#include <hgeresource.h>

#include <algorithm>

namespace
{
    const float ZOOM[5] = { 1.0f, 1.8f, 3.2f, 5.8f, 10.5f };

    bool
    lessThan( const Entity * left, const Entity * right )
    {
        if ( left->getScale() < right->getScale() * 0.99f )
        {
            return true;
        }
        if ( left->getScale() * 0.99f > right->getScale() )
        {
            return false;
        }
        if ( left->getType() < right->getType() )
        {
            return true;
        }
        return false;
    }
}

//==============================================================================
Game::Game()
    :
    Context(),
    m_last_zoom( 1.0f ),
    m_zoom( 0 ),
    m_fujin( 0 )
{
}

//------------------------------------------------------------------------------
Game::~Game()
{
}

//------------------------------------------------------------------------------
// public:
//------------------------------------------------------------------------------
void
Game::init()
{
    HGE * hge( Engine::hge() );
    b2World * b2d( Engine::b2d() );
    hgeResourceManager * rm( Engine::rm() );
    ViewPort * vp( Engine::vp() );

    notifyOnCollision( true );

    Fujin::registerEntity();
    Cloud::registerEntity();
    Girder::registerEntity();

    m_zoom = 0;

	m_timeRemaining = 300;
	m_score = 0;
    Engine::em()->init();
	Engine::cm()->init();

    vp->offset().x = 0.0f;
    vp->offset().y = 0.0f;
    vp->bounds().x = 800.0f;
    vp->bounds().y = 600.0f;
    vp->setAngle( 0.0f );
    vp->setScale( ZOOM[m_zoom] );

    m_fujin = static_cast< Fujin * >( Engine::em()->factory( Fujin::TYPE ) );
    b2Vec2 position( 0.0f, 0.0f );
    float angle( 0.0f );
    m_fujin->setSprite( "fujin" );
    m_fujin->setScale( 1.0f / ZOOM[m_zoom] );
    m_fujin->init();
    m_fujin->getBody()->SetXForm( position, angle );

    for ( int zoom = 0; zoom < 5; ++ zoom )
    {
	for (int i = 0; i < 8; ++i)
	{
		Entity* entity = Engine::em()->factory( Cloud::TYPE );
		b2Vec2 position( Engine::hge()->Random_Float( -400.0f, 400.0f),
                         Engine::hge()->Random_Float( -300.0f, 300.0f) );
		float angle( 0.f );
		entity->setSprite( "cloud" );
		entity->setScale( 1.0f / ZOOM[zoom] );
		entity->init();
		entity->getBody()->SetXForm( position, angle );
        static_cast< Cloud * >( entity )->setZoom( zoom );
	}
    }

    _initArena();
}

//------------------------------------------------------------------------------
void
Game::fini()
{
    notifyOnCollision( false );

    Engine::cm()->fini();
	Engine::em()->fini();
}

//------------------------------------------------------------------------------
bool
Game::update( float dt )
{
	m_timeRemaining -= dt;
    const Controller & pad( Engine::instance()->getController() );
    HGE * hge( Engine::hge() );
    ViewPort * vp( Engine::vp() );

    if ( m_timeRemaining <= 0)
    {
        Engine::instance()->switchContext( STATE_SCORE );
        Context * context( Engine::instance()->getContext() );
        static_cast< Score * >( context )->setValue( 13 );
        return false;
    }

	Engine::cm()->update( dt );
    Engine::em()->update( dt );

    if ( Engine::instance()->isPaused() )
    {
        return false;
    }

    if ( pad.isConnected() )
    {
        if ( pad.buttonDown( XPAD_BUTTON_LEFT_SHOULDER ) && m_zoom > 0 )
        {
            --m_zoom;
        }
        else if ( pad.buttonDown( XPAD_BUTTON_RIGHT_SHOULDER ) && m_zoom < 4 )
        {
            ++m_zoom;
        }
    }
    else
    {
        if ( ( Engine::hge()->Input_KeyDown( HGEK_Q ) ||
               hge->Input_GetMouseWheel() < 0 ) && m_zoom > 0 )
        {
            --m_zoom;
        }
        else if ( ( Engine::hge()->Input_KeyDown( HGEK_E ) ||
                    hge->Input_GetMouseWheel() > 0 ) && m_zoom < 4 )
        {
            ++m_zoom;
        }
    }

    if ( ZOOM[m_zoom] > m_last_zoom )
    {
        m_last_zoom += ( ZOOM[m_zoom] - m_last_zoom ) * dt * 10.0f;
        vp->setScale( m_last_zoom );
        m_fujin->setScale( 1.0f / m_last_zoom );
    }
    else if ( ZOOM[m_zoom] < m_last_zoom )
    {
        m_last_zoom += ( ZOOM[m_zoom] - m_last_zoom ) * dt * 10.0f;
        vp->setScale( m_last_zoom );
        m_fujin->setScale( 1.0f / m_last_zoom );
    }

    vp->offset() = m_fujin->getBody()->GetPosition();

    return false;
}

//------------------------------------------------------------------------------
void
Game::render()
{
	hgeResourceManager * rm( Engine::rm() );
	hgeFont* font = Engine::rm()->GetFont("menu");
	b2Vec2 timeTextLocation (700,10);
	b2Vec2 scoreTextLocation(0,10);
	char timeRemainingText[10];
	sprintf_s(timeRemainingText,"%d:%d",(int)m_timeRemaining/60,(int)(m_timeRemaining)%60);

	char scoreText[15];
	sprintf_s(scoreText,"Score: %5d",m_score);

    ViewPort * vp( Engine::vp() );

    vp->setTransform();

    rm->GetSprite( "polluted" )->RenderEx( 0.0f, 0.0f, 0.0f, 2.0f );

    std::vector< Entity * > entities;
    for ( b2Body * body( Engine::b2d()->GetBodyList() ); body != NULL;
          body = body->GetNext() )
    {
        Entity * entity( static_cast< Entity * >( body->GetUserData() ) );
        if ( entity )
        {
            entities.push_back( entity );
        }
    }

    std::sort( entities.begin(), entities.end(), lessThan );

    std::vector< Entity * >::iterator i;
    float scale( 1.0f / static_cast< float >( ZOOM[m_zoom] ) );
    for ( i = entities.begin(); i != entities.end(); ++i )
    {
        Entity * entity( * i );
        entity->render( scale );
    }
	// render time remaining
	Engine::hge()->Gfx_SetTransform();
	font->SetColor(0xFFFFFFFF);
	font->Render( timeTextLocation.x, timeTextLocation.y, HGETEXT_LEFT, timeRemainingText );
	font->Render( scoreTextLocation.x, scoreTextLocation.y, HGETEXT_LEFT, scoreText );

}

//------------------------------------------------------------------------------
bool
Game::shouldCollide( Entity * left, Entity * right )
{
    if ( left->getType() == Girder::TYPE ||
         right->getType() == Girder::TYPE )
    {
        return true;
    }

    if ( left->getScale() > right->getScale() * 0.99f &&
         left->getScale() * 0.99f < right->getScale() )
    {
        return left->getType() == right->getType();
    }

    return false;
}

//------------------------------------------------------------------------------
// private:
//------------------------------------------------------------------------------
void
Game::_initArena()
{
    b2Vec2 position( 0.0f, 0.0f );
    b2Vec2 dimensions( 0.0f, 0.0f );
    Entity * entity( 0 );

    for ( int i = 0; i < 4; ++i )
    {
        switch( i )
        {
            case 0:
            {
                dimensions.x = 800.0f;
                dimensions.y = 1.0f;
                position.x = 0.0f;
                position.y = -300.0f;
                break;
            }
            case 1:
            {
                dimensions.x = 1.0f;
                dimensions.y = 600.0f;
                position.x = 400.0f;
                position.y = 0.0f;
                break;
            }
            case 2:
            {
                dimensions.x = 800.0f;
                dimensions.y = 1.0f;
                position.x = 0.0f;
                position.y = 300.0f;
                break;
            }
            case 3:
            {
                dimensions.x = 1.0f;
                dimensions.y = 600.0f;
                position.x = -400.0f;
                position.y = 0.0f;
                break;
            }
        }
        Girder * girder( static_cast< Girder * >(
            Engine::em()->factory( Girder::TYPE ) ) );
        girder->setScale( 1.0f );
        girder->setDimensions( dimensions );
        girder->init();
        girder->getBody()->SetXForm( position, 0.0f );
    }
}
<|endoftext|>


<commit_before><commit_msg>second attempt to blind fix MSVC werror C4701,C4703<commit_after><|endoftext|>


<commit_before>#include <limits.h>
#include <stdlib.h>
#include <process.h>

#include "PwsPlatform.h"
#include "PWSrand.h"

// See the MSDN documentation for RtlGenRandom. We will try to load it
// and if that fails, use our own random number generator. The function
// call is indirected through a function pointer

static BOOLEAN (APIENTRY *pfnGetRandomData)(void*, ULONG) = NULL;

static bool __stdcall LoadRandomDataFunction();

PWSrand *PWSrand::self = NULL;

PWSrand *PWSrand::GetInstance()
{
  if (self == NULL) {
    self = new PWSrand;
  }
  return self;
}

void PWSrand::DeleteInstance()
{
  delete self;
  self = NULL;
}

PWSrand::PWSrand()
  : ibRandomData(SHA256::HASHLEN)
{
  m_IsInternalPRNG = !LoadRandomDataFunction();

  SHA256 s;
  time_t t = time(NULL);
  int pid = _getpid();
  DWORD ticks = GetTickCount();

  s.Update((const unsigned char *)&t, sizeof(t));
  s.Update((const unsigned char *)&pid, sizeof(pid));
  s.Update((const unsigned char *)&ticks, sizeof(ticks));

  s.Final(K);
}

PWSrand::~PWSrand()
{
}

void PWSrand::AddEntropy(unsigned char *bytes, unsigned int numBytes)
{
  ASSERT(bytes != NULL);

  SHA256 s;

  s.Update(K, sizeof(K));
  s.Update(bytes, numBytes);
  s.Final(K);
  //  TRACE1(_T("PWSrand::AddEntropy! %x\n"), bytes[0]);
}

void PWSrand::NextRandBlock()
{
  SHA256 s;
  s.Update(K, sizeof(K));
  s.Final(R);
  unsigned int *Kp = (unsigned int *)K;
  unsigned int *Rp = (unsigned int *)R;
  const int N = SHA256::HASHLEN/sizeof(unsigned int);

  Kp[0]++;

  for (int i = 0; i < N; i++)
    Kp[i] += Rp[i];
}

void PWSrand::GetRandomData( void * const buffer, unsigned long length )
{
  if (!m_IsInternalPRNG) {
    ASSERT(pfnGetRandomData != NULL);
    (void)(*pfnGetRandomData)(buffer, length);
  } else {
    unsigned char *pb = (unsigned char *)buffer;
    while (length > SHA256::HASHLEN) {
      NextRandBlock();
      for (int j = 0; j < SHA256::HASHLEN; j++)
        pb[j] = R[j];
      length -= SHA256::HASHLEN;
      pb += SHA256::HASHLEN;
    }
    ASSERT(length <= SHA256::HASHLEN);
    if (length > 0) {
      unsigned long i = 0;
      NextRandBlock();
      while (i < length) {
        pb[i] = R[i];
        i++;
      }
    }
  }
}

// generate random numbers from a buffer filled in by GetRandomData()
unsigned int PWSrand::RandUInt()
{
  // we don't want to keep filling the random buffer for each number we
  // want, so fill the buffer with random data and use it up

  if( ibRandomData > ( SHA256::HASHLEN - sizeof( unsigned int ) ) ) {
    // no data left, refill the buffer
    GetRandomData(rgbRandomData, SHA256::HASHLEN);
    ibRandomData = 0;
  }

  const unsigned int u =
    *(reinterpret_cast<unsigned int *>(rgbRandomData + ibRandomData));
  ibRandomData += sizeof(unsigned int);
  return u;
}

/*
 *  RangeRand(len)
 *
 *  Returns a random number in the range 0 to (len-1).
 *  For example, RangeRand(256) returns a value from 0 to 255.
 */
unsigned int PWSrand::RangeRand(size_t len)
{
  unsigned int      r;
  const unsigned int ceil = UINT_MAX - (UINT_MAX % len) - 1;
  while ((r = RandUInt()) > ceil)
    ;
  return(r%len);
}

static bool __stdcall LoadRandomDataFunction()
{
  HMODULE hLib = LoadLibrary(_T("ADVAPI32.DLL"));
  if (hLib != NULL) {
    BOOLEAN (APIENTRY *pfnGetRandomDataT)(void*, ULONG);
    pfnGetRandomDataT = (BOOLEAN (APIENTRY *)(void*,ULONG))GetProcAddress(hLib,"SystemFunction036");
    if (pfnGetRandomDataT) {
      pfnGetRandomData = pfnGetRandomDataT;
    }
  }
  return (hLib != NULL);
}

<commit_msg>Fixed assert under win2k (thanks to DK!)<commit_after>#include <limits.h>
#include <stdlib.h>
#include <process.h>

#include "PwsPlatform.h"
#include "PWSrand.h"

// See the MSDN documentation for RtlGenRandom. We will try to load it
// and if that fails, use our own random number generator. The function
// call is indirected through a function pointer

static BOOLEAN (APIENTRY *pfnGetRandomData)(void*, ULONG) = NULL;

static bool __stdcall LoadRandomDataFunction();

PWSrand *PWSrand::self = NULL;

PWSrand *PWSrand::GetInstance()
{
  if (self == NULL) {
    self = new PWSrand;
  }
  return self;
}

void PWSrand::DeleteInstance()
{
  delete self;
  self = NULL;
}

PWSrand::PWSrand()
  : ibRandomData(SHA256::HASHLEN)
{
  m_IsInternalPRNG = !LoadRandomDataFunction();

  SHA256 s;
  time_t t = time(NULL);
  int pid = _getpid();
  DWORD ticks = GetTickCount();

  s.Update((const unsigned char *)&t, sizeof(t));
  s.Update((const unsigned char *)&pid, sizeof(pid));
  s.Update((const unsigned char *)&ticks, sizeof(ticks));

  s.Final(K);
}

PWSrand::~PWSrand()
{
}

void PWSrand::AddEntropy(unsigned char *bytes, unsigned int numBytes)
{
  ASSERT(bytes != NULL);

  SHA256 s;

  s.Update(K, sizeof(K));
  s.Update(bytes, numBytes);
  s.Final(K);
  //  TRACE1(_T("PWSrand::AddEntropy! %x\n"), bytes[0]);
}

void PWSrand::NextRandBlock()
{
  SHA256 s;
  s.Update(K, sizeof(K));
  s.Final(R);
  unsigned int *Kp = (unsigned int *)K;
  unsigned int *Rp = (unsigned int *)R;
  const int N = SHA256::HASHLEN/sizeof(unsigned int);

  Kp[0]++;

  for (int i = 0; i < N; i++)
    Kp[i] += Rp[i];
}

void PWSrand::GetRandomData( void * const buffer, unsigned long length )
{
  if (!m_IsInternalPRNG) {
    ASSERT(pfnGetRandomData != NULL);
    (void)(*pfnGetRandomData)(buffer, length);
  } else {
    unsigned char *pb = (unsigned char *)buffer;
    while (length > SHA256::HASHLEN) {
      NextRandBlock();
      for (int j = 0; j < SHA256::HASHLEN; j++)
        pb[j] = R[j];
      length -= SHA256::HASHLEN;
      pb += SHA256::HASHLEN;
    }
    ASSERT(length <= SHA256::HASHLEN);
    if (length > 0) {
      unsigned long i = 0;
      NextRandBlock();
      while (i < length) {
        pb[i] = R[i];
        i++;
      }
    }
  }
}

// generate random numbers from a buffer filled in by GetRandomData()
unsigned int PWSrand::RandUInt()
{
  // we don't want to keep filling the random buffer for each number we
  // want, so fill the buffer with random data and use it up

  if( ibRandomData > ( SHA256::HASHLEN - sizeof( unsigned int ) ) ) {
    // no data left, refill the buffer
    GetRandomData(rgbRandomData, SHA256::HASHLEN);
    ibRandomData = 0;
  }

  const unsigned int u =
    *(reinterpret_cast<unsigned int *>(rgbRandomData + ibRandomData));
  ibRandomData += sizeof(unsigned int);
  return u;
}

/*
 *  RangeRand(len)
 *
 *  Returns a random number in the range 0 to (len-1).
 *  For example, RangeRand(256) returns a value from 0 to 255.
 */
unsigned int PWSrand::RangeRand(size_t len)
{
  unsigned int      r;
  const unsigned int ceil = UINT_MAX - (UINT_MAX % len) - 1;
  while ((r = RandUInt()) > ceil)
    ;
  return(r%len);
}

static bool __stdcall LoadRandomDataFunction()
{
  HMODULE hLib = LoadLibrary(_T("ADVAPI32.DLL"));
  BOOLEAN (APIENTRY *pfnGetRandomDataT)(void*, ULONG) = NULL;
  if (hLib != NULL) {
    pfnGetRandomDataT = (BOOLEAN (APIENTRY *)(void*,ULONG))GetProcAddress(hLib,"SystemFunction036");
    if (pfnGetRandomDataT) {
      pfnGetRandomData = pfnGetRandomDataT;
    }
  }
  return (hLib != NULL && pfnGetRandomDataT != NULL);
}

<|endoftext|>


<commit_before><commit_msg>fdo#75970: Let's do it in a straightforward fashion.<commit_after><|endoftext|>


<commit_before>#include "RDom.h"
#include "Util.h"
#include "IROperator.h"
#include "Scope.h"

namespace Halide {

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

RVar::operator Expr() const {
    return new Internal::Variable(Int(32), name(), domain);
}

Internal::ReductionDomain build_domain(string name0, Expr min0, Expr extent0,
                                       string name1, Expr min1, Expr extent1,
                                       string name2, Expr min2, Expr extent2,
                                       string name3, Expr min3, Expr extent3) {
    vector<Internal::ReductionVariable> d;
    if (min0.defined()) {
        Internal::ReductionVariable v = {name0, min0, extent0};
        d.push_back(v);
    }
    if (min1.defined()) {
        Internal::ReductionVariable v = {name1, min1, extent1};
        d.push_back(v);
    }
    if (min2.defined()) {
        Internal::ReductionVariable v = {name2, min2, extent2};
        d.push_back(v);
    }
    if (min3.defined()) {
        Internal::ReductionVariable v = {name3, min3, extent3};
        d.push_back(v);
    }

    Internal::ReductionDomain dom(d);

    return dom;
}

// We suffix all RVars with $r to prevent unintentional name matches with pure vars called x, y, z, w.
RDom::RDom(Expr min, Expr extent, string name) {
    min = cast<int>(min);
    extent = cast<int>(extent);
    if (name == "") name = Internal::unique_name('r');
    domain = build_domain(name + ".x$r", min, extent,
                          "", Expr(), Expr(),
                          "", Expr(), Expr(),
                          "", Expr(), Expr());
    x = RVar(name + ".x$r", min, extent, domain);
}

RDom::RDom(Expr min0, Expr extent0, Expr min1, Expr extent1, string name) {
    min0 = cast<int>(min0);
    extent0 = cast<int>(extent0);
    min1 = cast<int>(min1);
    extent1 = cast<int>(extent1);
    if (name == "") name = Internal::unique_name('r');
    domain = build_domain(name + ".x$r", min0, extent0,
                          name + ".y$r", min1, extent1,
                          "", Expr(), Expr(),
                          "", Expr(), Expr());
    x = RVar(name + ".x$r", min0, extent0, domain);
    y = RVar(name + ".y$r", min1, extent1, domain);
}

RDom::RDom(Expr min0, Expr extent0, Expr min1, Expr extent1, Expr min2, Expr extent2, string name) {
    min0 = cast<int>(min0);
    extent0 = cast<int>(extent0);
    min1 = cast<int>(min1);
    extent1 = cast<int>(extent1);
    min2 = cast<int>(min2);
    extent2 = cast<int>(extent2);
    if (name == "") name = Internal::unique_name('r');
    domain = build_domain(name + ".x$r", min0, extent0,
                          name + ".y$r", min1, extent1,
                          name + ".z$r", min2, extent2,
                          "", Expr(), Expr());
    x = RVar(name + ".x$r", min0, extent1, domain);
    y = RVar(name + ".y$r", min1, extent1, domain);
    z = RVar(name + ".z$r", min2, extent2, domain);
}

RDom::RDom(Expr min0, Expr extent0, Expr min1, Expr extent1, Expr min2, Expr extent2, Expr min3, Expr extent3, string name) {
    min0 = cast<int>(min0);
    extent0 = cast<int>(extent0);
    min1 = cast<int>(min1);
    extent1 = cast<int>(extent1);
    min2 = cast<int>(min2);
    extent2 = cast<int>(extent2);
    min3 = cast<int>(min3);
    extent3 = cast<int>(extent3);
    if (name == "") name = Internal::unique_name('r');
    domain = build_domain(name + ".x$r", min0, extent0,
                          name + ".y$r", min1, extent1,
                          name + ".z$r", min2, extent2,
                          name + ".w$r", min3, extent3);
    x = RVar(name + ".x$r", min0, extent1, domain);
    y = RVar(name + ".y$r", min1, extent1, domain);
    z = RVar(name + ".z$r", min2, extent2, domain);
    w = RVar(name + ".w$r", min3, extent3, domain);
}

RDom::RDom(Buffer b) {
    Expr min[4], extent[4];
    for (int i = 0; i < 4; i++) {
        if (b.dimensions() > i) {
            min[i] = b.min(i);
            extent[i] = b.extent(i);
        }
    }
    string names[] = {b.name() + ".x$r", b.name() + ".y$r", b.name() + ".z$r", b.name() + ".w$r"};
    domain = build_domain(names[0], min[0], extent[0],
                          names[1], min[1], extent[1],
                          names[2], min[2], extent[2],
                          names[3], min[3], extent[3]);
    RVar *vars[] = {&x, &y, &z, &w};
    for (int i = 0; i < 4; i++) {
        if (b.dimensions() > i) {
            *(vars[i]) = RVar(names[i], min[i], extent[i], domain);
        }
    }
}

RDom::RDom(ImageParam p) {
    Expr min[4], extent[4];
    for (int i = 0; i < 4; i++) {
        if (p.dimensions() > i) {
            min[i] = 0;
            extent[i] = p.extent(i);
        }
    }
    string names[] = {p.name() + ".x$r", p.name() + ".y$r", p.name() + ".z$r", p.name() + ".w$r"};
    domain = build_domain(names[0], min[0], extent[0],
                          names[1], min[1], extent[1],
                          names[2], min[2], extent[2],
                          names[3], min[3], extent[3]);
    RVar *vars[] = {&x, &y, &z, &w};
    for (int i = 0; i < 4; i++) {
        if (p.dimensions() > i) {
            *(vars[i]) = RVar(names[i], min[i], extent[i], domain);
        }
    }
}

int RDom::dimensions() const {
    return (int)domain.domain().size();
}

RVar RDom::operator[](int i) {
    if (i == 0) return x;
    if (i == 1) return y;
    if (i == 2) return z;
    if (i == 3) return w;
    assert(false && "Reduction domain index out of bounds");
	return x; // Keep the compiler happy
}

RDom::operator Expr() const {
    assert(dimensions() == 1 && "Can only treat single-dimensional RDoms as expressions");
    return Expr(x);
}

RDom::operator RVar() const {
    assert(dimensions() == 1 && "Can only treat single-dimensional RDoms as RVars");
    return x;
}

}
<commit_msg>Correct copy-paste error affecting RDom of 3 and 4 dimensions.<commit_after>#include "RDom.h"
#include "Util.h"
#include "IROperator.h"
#include "Scope.h"

namespace Halide {

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

RVar::operator Expr() const {
    return new Internal::Variable(Int(32), name(), domain);
}

Internal::ReductionDomain build_domain(string name0, Expr min0, Expr extent0,
                                       string name1, Expr min1, Expr extent1,
                                       string name2, Expr min2, Expr extent2,
                                       string name3, Expr min3, Expr extent3) {
    vector<Internal::ReductionVariable> d;
    if (min0.defined()) {
        Internal::ReductionVariable v = {name0, min0, extent0};
        d.push_back(v);
    }
    if (min1.defined()) {
        Internal::ReductionVariable v = {name1, min1, extent1};
        d.push_back(v);
    }
    if (min2.defined()) {
        Internal::ReductionVariable v = {name2, min2, extent2};
        d.push_back(v);
    }
    if (min3.defined()) {
        Internal::ReductionVariable v = {name3, min3, extent3};
        d.push_back(v);
    }

    Internal::ReductionDomain dom(d);

    return dom;
}

// We suffix all RVars with $r to prevent unintentional name matches with pure vars called x, y, z, w.
RDom::RDom(Expr min, Expr extent, string name) {
    min = cast<int>(min);
    extent = cast<int>(extent);
    if (name == "") name = Internal::unique_name('r');
    domain = build_domain(name + ".x$r", min, extent,
                          "", Expr(), Expr(),
                          "", Expr(), Expr(),
                          "", Expr(), Expr());
    x = RVar(name + ".x$r", min, extent, domain);
}

RDom::RDom(Expr min0, Expr extent0, Expr min1, Expr extent1, string name) {
    min0 = cast<int>(min0);
    extent0 = cast<int>(extent0);
    min1 = cast<int>(min1);
    extent1 = cast<int>(extent1);
    if (name == "") name = Internal::unique_name('r');
    domain = build_domain(name + ".x$r", min0, extent0,
                          name + ".y$r", min1, extent1,
                          "", Expr(), Expr(),
                          "", Expr(), Expr());
    x = RVar(name + ".x$r", min0, extent0, domain);
    y = RVar(name + ".y$r", min1, extent1, domain);
}

RDom::RDom(Expr min0, Expr extent0, Expr min1, Expr extent1, Expr min2, Expr extent2, string name) {
    min0 = cast<int>(min0);
    extent0 = cast<int>(extent0);
    min1 = cast<int>(min1);
    extent1 = cast<int>(extent1);
    min2 = cast<int>(min2);
    extent2 = cast<int>(extent2);
    if (name == "") name = Internal::unique_name('r');
    domain = build_domain(name + ".x$r", min0, extent0,
                          name + ".y$r", min1, extent1,
                          name + ".z$r", min2, extent2,
                          "", Expr(), Expr());
    x = RVar(name + ".x$r", min0, extent0, domain);
    y = RVar(name + ".y$r", min1, extent1, domain);
    z = RVar(name + ".z$r", min2, extent2, domain);
}

RDom::RDom(Expr min0, Expr extent0, Expr min1, Expr extent1, Expr min2, Expr extent2, Expr min3, Expr extent3, string name) {
    min0 = cast<int>(min0);
    extent0 = cast<int>(extent0);
    min1 = cast<int>(min1);
    extent1 = cast<int>(extent1);
    min2 = cast<int>(min2);
    extent2 = cast<int>(extent2);
    min3 = cast<int>(min3);
    extent3 = cast<int>(extent3);
    if (name == "") name = Internal::unique_name('r');
    domain = build_domain(name + ".x$r", min0, extent0,
                          name + ".y$r", min1, extent1,
                          name + ".z$r", min2, extent2,
                          name + ".w$r", min3, extent3);
    x = RVar(name + ".x$r", min0, extent0, domain);
    y = RVar(name + ".y$r", min1, extent1, domain);
    z = RVar(name + ".z$r", min2, extent2, domain);
    w = RVar(name + ".w$r", min3, extent3, domain);
}

RDom::RDom(Buffer b) {
    Expr min[4], extent[4];
    for (int i = 0; i < 4; i++) {
        if (b.dimensions() > i) {
            min[i] = b.min(i);
            extent[i] = b.extent(i);
        }
    }
    string names[] = {b.name() + ".x$r", b.name() + ".y$r", b.name() + ".z$r", b.name() + ".w$r"};
    domain = build_domain(names[0], min[0], extent[0],
                          names[1], min[1], extent[1],
                          names[2], min[2], extent[2],
                          names[3], min[3], extent[3]);
    RVar *vars[] = {&x, &y, &z, &w};
    for (int i = 0; i < 4; i++) {
        if (b.dimensions() > i) {
            *(vars[i]) = RVar(names[i], min[i], extent[i], domain);
        }
    }
}

RDom::RDom(ImageParam p) {
    Expr min[4], extent[4];
    for (int i = 0; i < 4; i++) {
        if (p.dimensions() > i) {
            min[i] = 0;
            extent[i] = p.extent(i);
        }
    }
    string names[] = {p.name() + ".x$r", p.name() + ".y$r", p.name() + ".z$r", p.name() + ".w$r"};
    domain = build_domain(names[0], min[0], extent[0],
                          names[1], min[1], extent[1],
                          names[2], min[2], extent[2],
                          names[3], min[3], extent[3]);
    RVar *vars[] = {&x, &y, &z, &w};
    for (int i = 0; i < 4; i++) {
        if (p.dimensions() > i) {
            *(vars[i]) = RVar(names[i], min[i], extent[i], domain);
        }
    }
}

int RDom::dimensions() const {
    return (int)domain.domain().size();
}

RVar RDom::operator[](int i) {
    if (i == 0) return x;
    if (i == 1) return y;
    if (i == 2) return z;
    if (i == 3) return w;
    assert(false && "Reduction domain index out of bounds");
	return x; // Keep the compiler happy
}

RDom::operator Expr() const {
    assert(dimensions() == 1 && "Can only treat single-dimensional RDoms as expressions");
    return Expr(x);
}

RDom::operator RVar() const {
    assert(dimensions() == 1 && "Can only treat single-dimensional RDoms as RVars");
    return x;
}

}
<|endoftext|>


<commit_before><commit_msg>fdo#39468 translated german comments<commit_after><|endoftext|>


<commit_before>#include "tangram.h"

#include "platform.h"
#include "scene/scene.h"
#include "scene/sceneLoader.h"
#include "scene/skybox.h"
#include "style/material.h"
#include "style/style.h"
#include "labels/labels.h"
#include "tile/tileManager.h"
#include "tile/tile.h"
#include "gl/error.h"
#include "gl/shaderProgram.h"
#include "gl/renderState.h"
#include "gl/primitives.h"
#include "util/inputHandler.h"
#include "view/view.h"
#include "data/clientGeoJsonSource.h"
#include "text/fontContext.h"
#include "gl.h"
#include "gl/extension.h"
#include "util/ease.h"
#include <memory>
#include <cmath>
#include <bitset>
#include <mutex>

namespace Tangram {

std::unique_ptr<TileManager> m_tileManager;
std::shared_ptr<Scene> m_scene;
std::shared_ptr<View> m_view;
std::unique_ptr<Labels> m_labels;
std::unique_ptr<Skybox> m_skybox;
std::unique_ptr<InputHandler> m_inputHandler;
std::mutex m_tilesMutex;
std::vector<Ease> m_eases;

static float g_time = 0.0;
static std::bitset<8> g_flags = 0;
int log_level = 2;

void initialize(const char* _scenePath) {

    if (m_tileManager) {
        LOG("Notice: Already initialized");
        return;
    }

    LOG("initialize");

    // Create view
    m_view = std::make_shared<View>();

    // Create a scene object
    m_scene = std::make_shared<Scene>();

    // Input handler
    m_inputHandler = std::unique_ptr<InputHandler>(new InputHandler(m_view));

    // Create a tileManager
    m_tileManager = TileManager::GetInstance();

    // Pass references to the view and scene into the tile manager
    m_tileManager->setView(m_view);

    // label setup
    m_labels = std::unique_ptr<Labels>(new Labels());

    loadScene(_scenePath, true);

    glm::dvec2 projPos = m_view->getMapProjection().LonLatToMeters(m_scene->startPosition);
    m_view->setPosition(projPos.x, projPos.y);
    m_view->setZoom(m_scene->startZoom);

    LOG("finish initialize");

}

void loadScene(const char* _scenePath, bool _setPositionFromScene) {
    LOG("Loading scene file: %s", _scenePath);

    auto sceneString = stringFromFile(setResourceRoot(_scenePath).c_str(), PathType::resource);

    bool setPositionFromCurrentView = bool(m_scene);

    auto scene = std::make_shared<Scene>();
    if (SceneLoader::loadScene(sceneString, *scene)) {
        m_scene = scene;
        m_scene->fontContext()->addFont("FiraSans", "Medium", "");
        if (setPositionFromCurrentView && !_setPositionFromScene) {
            m_scene->view()->setPosition(m_view->getPosition());
            m_scene->view()->setZoom(m_view->getZoom());
        }
        m_view = m_scene->view();
        m_inputHandler->setView(m_view);
        m_tileManager->setView(m_view);
        m_tileManager->setScene(scene);

    }
}

void resize(int _newWidth, int _newHeight) {

    LOG("resize: %d x %d", _newWidth, _newHeight);

    glViewport(0, 0, _newWidth, _newHeight);

    if (m_view) {
        m_view->setSize(_newWidth, _newHeight);
    }

    for (auto& style : m_scene->styles()) {
        style->viewportHasChanged();
    }

    Primitives::setResolution(_newWidth, _newHeight);

    while (Error::hadGlError("Tangram::resize()")) {}

}

void update(float _dt) {

    g_time += _dt;

    for (auto& ease : m_eases) {
        ease.update(_dt);
    }
    std::remove_if(m_eases.begin(), m_eases.end(), [](Ease& e) { return e.finished(); });

    m_inputHandler->update(_dt);

    m_view->update();

    {
        std::lock_guard<std::mutex> lock(m_tilesMutex);

        m_tileManager->updateTileSets();

        if (m_view->changedOnLastUpdate() || m_tileManager->hasTileSetChanged() || m_labels->needUpdate()) {

            auto& tiles = m_tileManager->getVisibleTiles();

            for (const auto& tile : tiles) {
                tile->update(_dt, *m_view);
            }

            m_labels->update(*m_view, _dt, m_scene->styles(), tiles);
        }

        bool animated = false;
        for (const auto& style : m_scene->styles()) {
            if (style->isAnimated()) {
                animated = true;
                break;
            }
        }
        if (animated != isContinuousRendering()) {
            setContinuousRendering(animated);
        }
    }
}

void render() {

    // Set up openGL for new frame
    RenderState::depthWrite(GL_TRUE);
    auto& color = m_scene->background();
    RenderState::clearColor(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    {
        std::lock_guard<std::mutex> lock(m_tilesMutex);

        // Loop over all styles
        for (const auto& style : m_scene->styles()) {

            // Set time uniforms style's shader programs
            style->getShaderProgram()->setUniformf("u_time", g_time);

            style->onBeginDrawFrame(*m_view, *m_scene);

            // Loop over all tiles in m_tileSet
            for (const auto& tile : m_tileManager->getVisibleTiles()) {
                tile->draw(*style, *m_view);
            }

            style->onEndDrawFrame();
        }
    }

    m_labels->drawDebug(*m_view);

    while (Error::hadGlError("Tangram::render()")) {}
}

void setPosition(double _lon, double _lat) {

    glm::dvec2 meters = m_view->getMapProjection().LonLatToMeters({ _lon, _lat});
    m_view->setPosition(meters.x, meters.y);
    requestRender();

}

void setPosition(double _lon, double _lat, float _duration) {

    double lon_start, lat_start;
    getPosition(lon_start, lat_start);
    auto cb = [=](float t) { setPosition(ease(lon_start, _lon, t), ease(lat_start, _lat, t)); };
    m_eases.push_back({ _duration, cb });

}

void getPosition(double& _lon, double& _lat) {

    glm::dvec2 meters(m_view->getPosition().x, m_view->getPosition().y);
    glm::dvec2 degrees = m_view->getMapProjection().MetersToLonLat(meters);
    _lon = degrees.x;
    _lat = degrees.y;

}

void setZoom(float _z) {

    m_view->setZoom(_z);
    requestRender();

}

void setZoom(float _z, float _duration) {

    float z_start = getZoom();
    auto cb = [=](float t) { setZoom(ease(z_start, _z, t)); };
    m_eases.push_back({ _duration, cb });

}

float getZoom() {

    return m_view->getZoom();

}

void setRotation(float _radians) {

    m_view->setRoll(_radians);
    requestRender();

}

void setRotation(float _radians, float _duration) {

    float radians_start = getRotation();
    auto cb = [=](float t) { setRotation(ease(radians_start, _radians, t)); };
    m_eases.push_back({ _duration, cb });

}

float getRotation() {

    return m_view->getRoll();

}

void setTilt(float _radians) {

    m_view->setPitch(_radians);
    requestRender();

}

void setTilt(float _radians, float _duration) {

    float tilt_start = getTilt();
    auto cb = [=](float t) { setTilt(ease(tilt_start, _radians, t)); };
    m_eases.push_back({ _duration, cb });

}

float getTilt() {

    return m_view->getPitch();

}

void screenToWorldCoordinates(double& _x, double& _y) {

    m_view->screenToGroundPlane(_x, _y);
    glm::dvec2 meters(_x + m_view->getPosition().x, _y + m_view->getPosition().y);
    glm::dvec2 lonLat = m_view->getMapProjection().MetersToLonLat(meters);
    _x = lonLat.x;
    _y = lonLat.y;

}

void setPixelScale(float _pixelsPerPoint) {

    if (m_view) {
        m_view->setPixelScale(_pixelsPerPoint);
    }

    for (auto& style : m_scene->styles()) {
        style->setPixelScale(_pixelsPerPoint);
    }
}

void addDataSource(std::shared_ptr<DataSource> _source) {
    if (!m_tileManager) { return; }
    std::lock_guard<std::mutex> lock(m_tilesMutex);

    m_tileManager->addDataSource(_source);
}

void clearDataSource(DataSource& _source, bool _data, bool _tiles) {
    if (!m_tileManager) { return; }
    std::lock_guard<std::mutex> lock(m_tilesMutex);

    if (_tiles) { m_tileManager->clearTileSet(_source.id()); }
    if (_data) { _source.clearData(); }

    requestRender();
}

void handleTapGesture(float _posX, float _posY) {

    m_inputHandler->handleTapGesture(_posX, _posY);

}

void handleDoubleTapGesture(float _posX, float _posY) {

    m_inputHandler->handleDoubleTapGesture(_posX, _posY);

}

void handlePanGesture(float _startX, float _startY, float _endX, float _endY) {

    m_inputHandler->handlePanGesture(_startX, _startY, _endX, _endY);

}

void handlePinchGesture(float _posX, float _posY, float _scale, float _velocity) {

    m_inputHandler->handlePinchGesture(_posX, _posY, _scale, _velocity);

}

void handleRotateGesture(float _posX, float _posY, float _radians) {

    m_inputHandler->handleRotateGesture(_posX, _posY, _radians);

}

void handleShoveGesture(float _distance) {

    m_inputHandler->handleShoveGesture(_distance);

}

void setDebugFlag(DebugFlags _flag, bool _on) {

    g_flags.set(_flag, _on);
    m_view->setZoom(m_view->getZoom()); // Force the view to refresh

}

bool getDebugFlag(DebugFlags _flag) {

    return g_flags.test(_flag);

}

void toggleDebugFlag(DebugFlags _flag) {

    g_flags.flip(_flag);
    m_view->setZoom(m_view->getZoom()); // Force the view to refresh

}

const std::vector<TouchItem>& pickFeaturesAt(float _x, float _y) {
    return m_labels->getFeaturesAtPoint(*m_view, 0, m_scene->styles(),
                                        m_tileManager->getVisibleTiles(),
                                        _x, _y);
}

void setupGL() {

    LOG("setup GL");

    if (m_tileManager) {
        m_tileManager->clearTileSets();

        for (auto& style : m_scene->styles()) {
           style->notifyGLContextLost();
        }
    }

    // The OpenGL context has been destroyed since the last time resources were created,
    // so we invalidate all data that depends on OpenGL object handles.

    // ShaderPrograms are invalidated and immediately rebuilt
    ShaderProgram::invalidateAllPrograms();

    // Buffer objects are invalidated and re-uploaded the next time they are used
    VboMesh::invalidateAllVBOs();

    // Texture objects are invalidated and re-uploaded the next time they are updated
    Texture::invalidateAllTextures();

    // Reconfigure the render states
    RenderState::configure();

    // Set default primitive render color
    Primitives::setColor(0xffffff);

    // Load GL extensions
    GLExtensions::load();

    GLExtensions::printAvailableExtensions();

    while (Error::hadGlError("Tangram::setupGL()")) {}
}

}
<commit_msg>Fix removal of completed eases<commit_after>#include "tangram.h"

#include "platform.h"
#include "scene/scene.h"
#include "scene/sceneLoader.h"
#include "scene/skybox.h"
#include "style/material.h"
#include "style/style.h"
#include "labels/labels.h"
#include "tile/tileManager.h"
#include "tile/tile.h"
#include "gl/error.h"
#include "gl/shaderProgram.h"
#include "gl/renderState.h"
#include "gl/primitives.h"
#include "util/inputHandler.h"
#include "view/view.h"
#include "data/clientGeoJsonSource.h"
#include "text/fontContext.h"
#include "gl.h"
#include "gl/extension.h"
#include "util/ease.h"
#include <memory>
#include <cmath>
#include <bitset>
#include <mutex>

namespace Tangram {

std::unique_ptr<TileManager> m_tileManager;
std::shared_ptr<Scene> m_scene;
std::shared_ptr<View> m_view;
std::unique_ptr<Labels> m_labels;
std::unique_ptr<Skybox> m_skybox;
std::unique_ptr<InputHandler> m_inputHandler;
std::mutex m_tilesMutex;
std::vector<Ease> m_eases;

static float g_time = 0.0;
static std::bitset<8> g_flags = 0;
int log_level = 2;

void initialize(const char* _scenePath) {

    if (m_tileManager) {
        LOG("Notice: Already initialized");
        return;
    }

    LOG("initialize");

    // Create view
    m_view = std::make_shared<View>();

    // Create a scene object
    m_scene = std::make_shared<Scene>();

    // Input handler
    m_inputHandler = std::unique_ptr<InputHandler>(new InputHandler(m_view));

    // Create a tileManager
    m_tileManager = TileManager::GetInstance();

    // Pass references to the view and scene into the tile manager
    m_tileManager->setView(m_view);

    // label setup
    m_labels = std::unique_ptr<Labels>(new Labels());

    loadScene(_scenePath, true);

    glm::dvec2 projPos = m_view->getMapProjection().LonLatToMeters(m_scene->startPosition);
    m_view->setPosition(projPos.x, projPos.y);
    m_view->setZoom(m_scene->startZoom);

    LOG("finish initialize");

}

void loadScene(const char* _scenePath, bool _setPositionFromScene) {
    LOG("Loading scene file: %s", _scenePath);

    auto sceneString = stringFromFile(setResourceRoot(_scenePath).c_str(), PathType::resource);

    bool setPositionFromCurrentView = bool(m_scene);

    auto scene = std::make_shared<Scene>();
    if (SceneLoader::loadScene(sceneString, *scene)) {
        m_scene = scene;
        m_scene->fontContext()->addFont("FiraSans", "Medium", "");
        if (setPositionFromCurrentView && !_setPositionFromScene) {
            m_scene->view()->setPosition(m_view->getPosition());
            m_scene->view()->setZoom(m_view->getZoom());
        }
        m_view = m_scene->view();
        m_inputHandler->setView(m_view);
        m_tileManager->setView(m_view);
        m_tileManager->setScene(scene);

    }
}

void resize(int _newWidth, int _newHeight) {

    LOG("resize: %d x %d", _newWidth, _newHeight);

    glViewport(0, 0, _newWidth, _newHeight);

    if (m_view) {
        m_view->setSize(_newWidth, _newHeight);
    }

    for (auto& style : m_scene->styles()) {
        style->viewportHasChanged();
    }

    Primitives::setResolution(_newWidth, _newHeight);

    while (Error::hadGlError("Tangram::resize()")) {}

}

void update(float _dt) {

    g_time += _dt;

    for (auto it = m_eases.begin(); it < m_eases.end(); it++) {
        it->update(_dt);
        if (it->finished()) { m_eases.erase(it); }
    }

    m_inputHandler->update(_dt);

    m_view->update();

    {
        std::lock_guard<std::mutex> lock(m_tilesMutex);

        m_tileManager->updateTileSets();

        if (m_view->changedOnLastUpdate() || m_tileManager->hasTileSetChanged() || m_labels->needUpdate()) {

            auto& tiles = m_tileManager->getVisibleTiles();

            for (const auto& tile : tiles) {
                tile->update(_dt, *m_view);
            }

            m_labels->update(*m_view, _dt, m_scene->styles(), tiles);
        }

        bool animated = false;
        for (const auto& style : m_scene->styles()) {
            if (style->isAnimated()) {
                animated = true;
                break;
            }
        }
        if (animated != isContinuousRendering()) {
            setContinuousRendering(animated);
        }
    }
}

void render() {

    // Set up openGL for new frame
    RenderState::depthWrite(GL_TRUE);
    auto& color = m_scene->background();
    RenderState::clearColor(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    {
        std::lock_guard<std::mutex> lock(m_tilesMutex);

        // Loop over all styles
        for (const auto& style : m_scene->styles()) {

            // Set time uniforms style's shader programs
            style->getShaderProgram()->setUniformf("u_time", g_time);

            style->onBeginDrawFrame(*m_view, *m_scene);

            // Loop over all tiles in m_tileSet
            for (const auto& tile : m_tileManager->getVisibleTiles()) {
                tile->draw(*style, *m_view);
            }

            style->onEndDrawFrame();
        }
    }

    m_labels->drawDebug(*m_view);

    while (Error::hadGlError("Tangram::render()")) {}
}

void setPosition(double _lon, double _lat) {

    glm::dvec2 meters = m_view->getMapProjection().LonLatToMeters({ _lon, _lat});
    m_view->setPosition(meters.x, meters.y);
    requestRender();

}

void setPosition(double _lon, double _lat, float _duration) {

    double lon_start, lat_start;
    getPosition(lon_start, lat_start);
    auto cb = [=](float t) { setPosition(ease(lon_start, _lon, t), ease(lat_start, _lat, t)); };
    m_eases.push_back({ _duration, cb });

}

void getPosition(double& _lon, double& _lat) {

    glm::dvec2 meters(m_view->getPosition().x, m_view->getPosition().y);
    glm::dvec2 degrees = m_view->getMapProjection().MetersToLonLat(meters);
    _lon = degrees.x;
    _lat = degrees.y;

}

void setZoom(float _z) {

    m_view->setZoom(_z);
    requestRender();

}

void setZoom(float _z, float _duration) {

    float z_start = getZoom();
    auto cb = [=](float t) { setZoom(ease(z_start, _z, t)); };
    m_eases.push_back({ _duration, cb });

}

float getZoom() {

    return m_view->getZoom();

}

void setRotation(float _radians) {

    m_view->setRoll(_radians);
    requestRender();

}

void setRotation(float _radians, float _duration) {

    float radians_start = getRotation();
    auto cb = [=](float t) { setRotation(ease(radians_start, _radians, t)); };
    m_eases.push_back({ _duration, cb });

}

float getRotation() {

    return m_view->getRoll();

}

void setTilt(float _radians) {

    m_view->setPitch(_radians);
    requestRender();

}

void setTilt(float _radians, float _duration) {

    float tilt_start = getTilt();
    auto cb = [=](float t) { setTilt(ease(tilt_start, _radians, t)); };
    m_eases.push_back({ _duration, cb });

}

float getTilt() {

    return m_view->getPitch();

}

void screenToWorldCoordinates(double& _x, double& _y) {

    m_view->screenToGroundPlane(_x, _y);
    glm::dvec2 meters(_x + m_view->getPosition().x, _y + m_view->getPosition().y);
    glm::dvec2 lonLat = m_view->getMapProjection().MetersToLonLat(meters);
    _x = lonLat.x;
    _y = lonLat.y;

}

void setPixelScale(float _pixelsPerPoint) {

    if (m_view) {
        m_view->setPixelScale(_pixelsPerPoint);
    }

    for (auto& style : m_scene->styles()) {
        style->setPixelScale(_pixelsPerPoint);
    }
}

void addDataSource(std::shared_ptr<DataSource> _source) {
    if (!m_tileManager) { return; }
    std::lock_guard<std::mutex> lock(m_tilesMutex);

    m_tileManager->addDataSource(_source);
}

void clearDataSource(DataSource& _source, bool _data, bool _tiles) {
    if (!m_tileManager) { return; }
    std::lock_guard<std::mutex> lock(m_tilesMutex);

    if (_tiles) { m_tileManager->clearTileSet(_source.id()); }
    if (_data) { _source.clearData(); }

    requestRender();
}

void handleTapGesture(float _posX, float _posY) {

    m_inputHandler->handleTapGesture(_posX, _posY);

}

void handleDoubleTapGesture(float _posX, float _posY) {

    m_inputHandler->handleDoubleTapGesture(_posX, _posY);

}

void handlePanGesture(float _startX, float _startY, float _endX, float _endY) {

    m_inputHandler->handlePanGesture(_startX, _startY, _endX, _endY);

}

void handlePinchGesture(float _posX, float _posY, float _scale, float _velocity) {

    m_inputHandler->handlePinchGesture(_posX, _posY, _scale, _velocity);

}

void handleRotateGesture(float _posX, float _posY, float _radians) {

    m_inputHandler->handleRotateGesture(_posX, _posY, _radians);

}

void handleShoveGesture(float _distance) {

    m_inputHandler->handleShoveGesture(_distance);

}

void setDebugFlag(DebugFlags _flag, bool _on) {

    g_flags.set(_flag, _on);
    m_view->setZoom(m_view->getZoom()); // Force the view to refresh

}

bool getDebugFlag(DebugFlags _flag) {

    return g_flags.test(_flag);

}

void toggleDebugFlag(DebugFlags _flag) {

    g_flags.flip(_flag);
    m_view->setZoom(m_view->getZoom()); // Force the view to refresh

}

const std::vector<TouchItem>& pickFeaturesAt(float _x, float _y) {
    return m_labels->getFeaturesAtPoint(*m_view, 0, m_scene->styles(),
                                        m_tileManager->getVisibleTiles(),
                                        _x, _y);
}

void setupGL() {

    LOG("setup GL");

    if (m_tileManager) {
        m_tileManager->clearTileSets();

        for (auto& style : m_scene->styles()) {
           style->notifyGLContextLost();
        }
    }

    // The OpenGL context has been destroyed since the last time resources were created,
    // so we invalidate all data that depends on OpenGL object handles.

    // ShaderPrograms are invalidated and immediately rebuilt
    ShaderProgram::invalidateAllPrograms();

    // Buffer objects are invalidated and re-uploaded the next time they are used
    VboMesh::invalidateAllVBOs();

    // Texture objects are invalidated and re-uploaded the next time they are updated
    Texture::invalidateAllTextures();

    // Reconfigure the render states
    RenderState::configure();

    // Set default primitive render color
    Primitives::setColor(0xffffff);

    // Load GL extensions
    GLExtensions::load();

    GLExtensions::printAvailableExtensions();

    while (Error::hadGlError("Tangram::setupGL()")) {}
}

}
<|endoftext|>


<commit_before>/*
Copyright (c) 2014 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include "kernel/expr_eq_fn.h"

#ifndef LEAN_EQ_CACHE_THRESHOLD
#define LEAN_EQ_CACHE_THRESHOLD 4
#endif

namespace lean {
bool expr_eq_fn::apply(expr const & a, expr const & b) {
    if (is_eqp(a, b))          return true;
    if (a.hash() != b.hash())  return false;
    if (a.kind() != b.kind())  return false;
    if (is_var(a))             return var_idx(a) == var_idx(b);
    if (m_counter >= LEAN_EQ_CACHE_THRESHOLD && is_shared(a) && is_shared(b)) {
        auto p = std::make_pair(a.raw(), b.raw());
        if (!m_eq_visited)
            m_eq_visited.reset(new expr_cell_pair_set);
        if (m_eq_visited->find(p) != m_eq_visited->end())
            return true;
        m_eq_visited->insert(p);
    }
    check_system("expression equality test");
    switch (a.kind()) {
    case expr_kind::Var:
        lean_unreachable(); // LCOV_EXCL_LINE
    case expr_kind::Constant:
        return
            const_name(a) == const_name(b) &&
            compare(const_levels(a), const_levels(b), [](level const & l1, level const & l2) { return l1 == l2; });
    case expr_kind::Meta:
        return
            mlocal_name(a) == mlocal_name(b) &&
            apply(mlocal_type(a), mlocal_type(b));
    case expr_kind::Local:
        return
            mlocal_name(a) == mlocal_name(b) &&
            apply(mlocal_type(a), mlocal_type(b)) &&
            (!m_compare_binder_info || local_info(a) == local_info(b));
    case expr_kind::App:
        m_counter++;
        return
            apply(app_fn(a), app_fn(b)) &&
            apply(app_arg(a), app_arg(b));
    case expr_kind::Lambda: case expr_kind::Pi:
        m_counter++;
        return
            apply(binding_domain(a), binding_domain(b)) &&
            apply(binding_body(a), binding_body(b)) &&
            (!m_compare_binder_info || binding_info(a) == binding_info(b));
    case expr_kind::Sort:
        return sort_level(a) == sort_level(b);
    case expr_kind::Macro:
        m_counter++;
        if (macro_def(a) != macro_def(b) || macro_num_args(a) != macro_num_args(b))
            return false;
        for (unsigned i = 0; i < macro_num_args(a); i++) {
            if (!apply(macro_arg(a, i), macro_arg(b, i)))
                return false;
        }
        return true;
    }
    lean_unreachable(); // LCOV_EXCL_LINE
}
}
<commit_msg>fix(kernel/expr_eq_fn): take local pp name into account when annotations are considered in the equality test<commit_after>/*
Copyright (c) 2014 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include "kernel/expr_eq_fn.h"

#ifndef LEAN_EQ_CACHE_THRESHOLD
#define LEAN_EQ_CACHE_THRESHOLD 4
#endif

namespace lean {
bool expr_eq_fn::apply(expr const & a, expr const & b) {
    if (is_eqp(a, b))          return true;
    if (a.hash() != b.hash())  return false;
    if (a.kind() != b.kind())  return false;
    if (is_var(a))             return var_idx(a) == var_idx(b);
    if (m_counter >= LEAN_EQ_CACHE_THRESHOLD && is_shared(a) && is_shared(b)) {
        auto p = std::make_pair(a.raw(), b.raw());
        if (!m_eq_visited)
            m_eq_visited.reset(new expr_cell_pair_set);
        if (m_eq_visited->find(p) != m_eq_visited->end())
            return true;
        m_eq_visited->insert(p);
    }
    check_system("expression equality test");
    switch (a.kind()) {
    case expr_kind::Var:
        lean_unreachable(); // LCOV_EXCL_LINE
    case expr_kind::Constant:
        return
            const_name(a) == const_name(b) &&
            compare(const_levels(a), const_levels(b), [](level const & l1, level const & l2) { return l1 == l2; });
    case expr_kind::Meta:
        return
            mlocal_name(a) == mlocal_name(b) &&
            apply(mlocal_type(a), mlocal_type(b));
    case expr_kind::Local:
        return
            mlocal_name(a) == mlocal_name(b) &&
            apply(mlocal_type(a), mlocal_type(b)) &&
            (!m_compare_binder_info || local_pp_name(a) == local_pp_name(b));
            (!m_compare_binder_info || local_info(a) == local_info(b));
    case expr_kind::App:
        m_counter++;
        return
            apply(app_fn(a), app_fn(b)) &&
            apply(app_arg(a), app_arg(b));
    case expr_kind::Lambda: case expr_kind::Pi:
        m_counter++;
        return
            apply(binding_domain(a), binding_domain(b)) &&
            apply(binding_body(a), binding_body(b)) &&
            (!m_compare_binder_info || binding_info(a) == binding_info(b));
    case expr_kind::Sort:
        return sort_level(a) == sort_level(b);
    case expr_kind::Macro:
        m_counter++;
        if (macro_def(a) != macro_def(b) || macro_num_args(a) != macro_num_args(b))
            return false;
        for (unsigned i = 0; i < macro_num_args(a); i++) {
            if (!apply(macro_arg(a, i), macro_arg(b, i)))
                return false;
        }
        return true;
    }
    lean_unreachable(); // LCOV_EXCL_LINE
}
}
<|endoftext|>


<commit_before>#/** \ingroup kernel
* \{
*
* \file kernel/memory_map.hpp
* \brief This file defines the memory map used by the
*        kernel as well as some auxilliary types.
*/

#ifndef H_kernel_memory
#define H_kernel_memory

#include <common/types.hpp>

#include "dynarray.hpp"
#include "debug.hpp"
#include "constants.hpp"

#include <memory_resource>
#include <algorithm>
#include <limits>

namespace UtopiaOS
{
    namespace kernel
    {
        /** \enum memory_type
         * \brief Analogous to the UEFI memory type
         *        but contains only types the kernel
         *        actually knows about.
         */
        enum class memory_type : common::uint32
        {
            general_purpose,
            unusable,
            invalid
        };

        /** \struct memory_request
         * \brief Encapsulates a memory requirement
         * \tparam ALIGN Specifies the alignment
         */
        template<std::size_t ALIGN>
        struct memory_request
        {
            std::size_t size;
            static constexpr std::size_t alignment = ALIGN;
        };

        /** \brief Aligns a pointer to a given alignment.
         * \param[in] ptr The pointer to align
         * \param[in] alignment The alignment to meet
         * \returns An aligned pointer or 0 if the pointer
         *          could not be aligned.
         *
         * The aligned pointer is guaranteed to point to
         * an address not smaller than the original pointer.
         * It is guaranteed that there is no other aligned
         * address in the range [\a ptr, \a return-value].
         * If the pointer cannot be aligned, i.e it points
         * to an address so large that the next aligned
         * address would not fit into the data type,
         * 0 is returned.
         *
         * \warning If \a alignment is not a power of two,
         *          the behaviour is undefined!
         */
        static inline common::uintptr align( common::uintptr ptr, std::size_t alignment )
        {
            static_assert( std::numeric_limits<common::uintptr>::max() >=
                          std::numeric_limits<std::size_t>::max(),
                          "This implementation cannot guarantee to work." );
            debug_assert( (alignment % 2) == 0, "alignment has to be a power of two" );

            common::un mask = alignment - 1; // ...0000011111...
            common::un diff = (ptr & mask);

            if( diff == 0 )
                return ptr;

            return (ptr + alignment - diff);
        }

        /** \struct memory_descriptor
         * \brief Analogous to a UEFI memory descriptor,
         *        but usable by the kernel. It also has
         *        a well-defined size.
         *
         * It is guaranteed that
         * (\a start + \a number_of_pages * \a pagesize)
         * does not overflow, where \a start is either
         * \a physical_start or \a virtual_start.
         * For memory_descriptor with its type set to
         * \a memory_type::invalid the contents of the
         * other fields are undefined.
         */
        struct memory_descriptor
        {
            memory_type type;
            common::uint64 physical_start;
            common::uint64 virtual_start;
            common::uint64 number_of_pages;

            /** \brief Construct a kernel-usable memory
             *         descriptor from a UEFI one.
             *
             * \warning If there is an overflow in
             *          (\a start + \a number_of_pages * \a UEFI::pagesize)
             *          where \a start is either
             *          \a physical_start or \a virtual_start
             *          the memory_type will be set to unusable.
             * \warning If the total memory block is smaller than
             *          the kernel pagesize the type will be set
             *          to invalid and the other fields are undefined.
             * \warning If the kernel pagesize cannot be used to fully
             *          cover the memory region, the memory region
             *          will be truncated accordingly.
             */
            memory_descriptor( const UEFI::memory_descriptor_v1 &uefi_desc )
            : type( uefi_desc.type == UEFI::memory_type::EfiConventionalMemory ?
                   memory_type::general_purpose : memory_type::unusable ),
            physical_start( uefi_desc.physical_start ),
            virtual_start( uefi_desc.virtual_start ),
            number_of_pages( (uefi_desc.number_of_pages * UEFI::pagesize) / pagesize )
            {
                if( number_of_pages == 0 )
                    type = memory_type::invalid;
            }

            /** \brief Checks whether the memory described by
             *         the memory descriptor can be used to
             *         fulfil a memory request.
             * \tparam ALIGN Specifies the alignment
             * \returns \a true if the request can be fulfilled
             *          and \a false otherwise.
             */
            template<std::size_t ALIGN>
            bool can_meet_request( const memory_request<ALIGN> &request ) const
            {
                static_assert( std::numeric_limits<common::uintptr>::max() >=
                              std::numeric_limits<std::size_t>::max(),
                              "This implementation cannot guarantee to work." );
                if( type != memory_type::general_purpose )
                    return false;

                auto aligned_address = align( virtual_start, request.alignment );
                common::uintptr request_end = aligned_address + request.size;

                if( (request_end - virtual_start) / pagesize <= number_of_pages )
                    return true;

                return false;
            }
        };

        /** \class memory_map
         * \brief The memory map used by the kernel
         * \tparam Allocator The type of allocator to use
         *
         * It has some sanity guarantees that UEFI lacks, like:
         * - fixed size of descriptors that is known compile-time
         * - no overlaps
         * - The memory descriptors always describe regions that
         *   are as large as possible, with lower ones always being
         *   full in a case of ambiguity.
         */
        template<class Allocator>
        class memory_map
        {
        public:
            using allocator_type = Allocator;
        private:
            using desc_array = dynarray<memory_descriptor, allocator_type>;
            desc_array descriptors;

            /** \brief Convert a uefi memory map to a
             *         kernel-usable one.
             * \param[in] uefi_map The UEFI memory map
             * \param[in] The allocator to use
             * \returns An array of descriptors with the guarantee
             *          that they do not overlap.
             */
            static desc_array
            convert_from_uefi( const UEFI::memory_map &uefi_map, allocator_type &&alloc )
            {
                desc_array stage1_descriptors( uefi_map.cbegin_v1(),
                                              uefi_map.cend_v1(),
                                              std::forward<allocator_type>( alloc ) );

                /** \todo Now remedy all possible overlaps and
                 *        any unnecessary fragmentation
                 */
            }
        public:
            /** \brief Returns a memory_request that when fulfilled
             *         will suffice to convert a UEFI memory map
             *         to a kernel-usable one.
             * \param[in] uefi_map The UEFI memory map
             * \returns The memory_request
             */
            static memory_request<alignof(memory_descriptor)>
            maximum_conversion_requirement( const UEFI::memory_map &uefi_map )
            {
                return { uefi_map.number_of_descriptors * sizeof(memory_descriptor) };
            }

            /** \brief Returns a memory_request that when fulfilled
             *         will suffice to copy the memory map.
             * \returns The memory_request
             */
            memory_request<alignof(memory_descriptor)> copy_requirement( void ) const
            {
                return { descriptors.size() * sizeof(memory_descriptor) };
            }

            /** \brief Constructs a kernel-usable memory map
             *         from a UEFI memory map.
             * \param[in] uefi_map The UEFI memory map
             * \param[in] alloc The allocator used to copy the
             *                  memory map. It has to be able to
             *                  allocate at least what is returned
             *                  by \a maximum_conversion_requirement.
             */
            memory_map( const UEFI::memory_map &uefi_map, allocator_type &&alloc )
            : descriptors( convert_from_uefi( uefi_map,
                                             std::forward<allocator_type>( alloc ) ) )
            {}

            /** \brief Returns a const iterator to the begin of
             *         the memory descriptor range.
             * \returns A const iterator to the begin of
             *          the memory descriptor range
             */
            typename desc_array::const_iterator cbegin( void ) const
            { return descriptors.cbegin(); }

            /** \brief Returns a const iterator to the end of
             *         the memory descriptor range.
             * \returns A const iterator to the end of
             *          the memory descriptor range
             */
            typename desc_array::const_iterator cend( void ) const
            { return descriptors.cend(); }
        };
    }
}

#endif

/** \} */
<commit_msg>Implemented UEFI memory map to kernel memory map conversion.<commit_after>#/** \ingroup kernel
* \{
*
* \file kernel/memory_map.hpp
* \brief This file defines the memory map used by the
*        kernel as well as some auxilliary types.
*/

#ifndef H_kernel_memory
#define H_kernel_memory

#include <common/types.hpp>

#include "dynarray.hpp"
#include "debug.hpp"
#include "constants.hpp"

#include <memory_resource>
#include <algorithm>
#include <limits>
#include <functional>

namespace UtopiaOS
{
    namespace kernel
    {
        /** \enum memory_type
         * \brief Analogous to the UEFI memory type
         *        but contains only types the kernel
         *        actually knows about.
         */
        enum class memory_type : common::uint32
        {
            general_purpose,
            unusable,
            invalid
        };

        /** \struct memory_request
         * \brief Encapsulates a memory requirement
         * \tparam ALIGN Specifies the alignment
         */
        template<std::size_t ALIGN>
        struct memory_request
        {
            std::size_t size;
            static constexpr std::size_t alignment = ALIGN;
        };

        /** \brief Aligns a pointer to a given alignment.
         * \param[in] ptr The pointer to align
         * \param[in] alignment The alignment to meet
         * \returns An aligned pointer or 0 if the pointer
         *          could not be aligned.
         *
         * The aligned pointer is guaranteed to point to
         * an address not smaller than the original pointer.
         * It is guaranteed that there is no other aligned
         * address in the range [\a ptr, \a return-value].
         * If the pointer cannot be aligned, i.e it points
         * to an address so large that the next aligned
         * address would not fit into the data type,
         * 0 is returned.
         *
         * \warning If \a alignment is not a power of two,
         *          the behaviour is undefined!
         */
        static inline common::uintptr align( common::uintptr ptr, std::size_t alignment )
        {
            static_assert( std::numeric_limits<common::uintptr>::max() >=
                          std::numeric_limits<std::size_t>::max(),
                          "This implementation cannot guarantee to work." );
            debug_assert( (alignment % 2) == 0, "alignment has to be a power of two" );

            common::un mask = alignment - 1; // ...0000011111...
            common::un diff = (ptr & mask);

            if( diff == 0 )
                return ptr;

            return (ptr + alignment - diff);
        }

        /** \struct memory_descriptor
         * \brief Analogous to a UEFI memory descriptor,
         *        but usable by the kernel. It also has
         *        a well-defined size.
         *
         * It is guaranteed that for a valid memory descriptor:
         * - (\a start + \a number_of_pages * \a pagesize)
         *   does not overflow, where \a start is either
         *   \a physical_start or \a virtual_start.
         * - \a number_of_pages is non-zero
         * For a memory_descriptor with its type set to
         * \a memory_type::invalid the contents of the
         * other fields are undefined.
         */
        struct memory_descriptor
        {
            memory_type type;
            common::uint64 physical_start;
            common::uint64 virtual_start;
            common::uint64 number_of_pages;

            /** \brief Returns an invalid memory descriptor.
             * \returns An invalid memory descriptor
             */
            static memory_descriptor invalid_memory_descriptor( void )
            {
                return memory_descriptor{ memory_type::invalid,
                    0, 0, 0 };
            }

            /** \brief Constructs a memory descriptor from
             *         properties describing a memory region.
             * \param[in] t The type of the memory region
             * \param[in] ps The physical start of the memory region
             * \param[in] vs The virtual start of the memory region
             * \param[in] np The number of pages of the memory region
             *
             * If the parameters do not fulfil the guarantees
             * required of a memory_descriptor object, a
             * std::invalid_argument exception is thrown.
             */
            memory_descriptor( memory_type t, common::uint64 ps,
                              common::uint64 vs, common::uint64 np )
            : type( t ), physical_start( ps ), virtual_start( vs ),
            number_of_pages( np )
            {
                if( validate( *this ) == false )
                {
                    type = memory_type::invalid;
                    throw std::invalid_argument( "Cannot construct a \
valid memory descriptor with the specified arguments" );
                }
            }

            /** \brief Construct a kernel-usable memory
             *         descriptor from a UEFI one.
             *
             * \warning If there is an overflow in
             *          (\a start + \a number_of_pages * \a UEFI::pagesize)
             *          where \a start is either
             *          \a physical_start or \a virtual_start
             *          the memory_type will be set to unusable.
             * \warning If the total memory block is smaller than
             *          the kernel pagesize the type will be set
             *          to invalid and the other fields are undefined.
             * \warning If the kernel pagesize cannot be used to fully
             *          cover the memory region, the memory region
             *          will be truncated accordingly.
             */
            memory_descriptor( const UEFI::memory_descriptor_v1 &uefi_desc )
            : type( uefi_desc.type == UEFI::memory_type::EfiConventionalMemory ?
                   memory_type::general_purpose : memory_type::unusable ),
            physical_start( uefi_desc.physical_start ),
            virtual_start( uefi_desc.virtual_start )
            {
                // Check if memory block size already overflows
                if( (std::numeric_limits<common::uint64>::max() /
                     UEFI::pagesize ) > uefi_desc.number_of_pages )
                    type = memory_type::invalid;
                // Check if the block starting at physical_address
                // overflows
                else if( (std::numeric_limits<common::uint64>::max() -
                          UEFI::pagesize * uefi_desc.number_of_pages) <
                        physical_start )
                    type = memory_type::invalid;
                // Check if the block starting at virtual_address
                // overflows
                else if( (std::numeric_limits<common::uint64>::max() -
                          UEFI::pagesize * uefi_desc.number_of_pages) <
                        virtual_start )
                    type = memory_type::invalid;
                else
                {
                    // Truncate the memory block as needed by pagesize
                    // limitations.
                    number_of_pages = ((uefi_desc.number_of_pages * UEFI::pagesize) /
                                       pagesize );

                    // Don't retain zero-sized memory blocks
                    if( number_of_pages == 0 )
                        type = memory_type::invalid;
                }
            }

            /** \brief Checks whether the memory described by
             *         the memory descriptor can be used to
             *         fulfil a memory request.
             * \tparam ALIGN Specifies the alignment
             * \returns \a true if the request can be fulfilled
             *          and \a false otherwise.
             */
            template<std::size_t ALIGN>
            bool can_meet_request( const memory_request<ALIGN> &request ) const
            {
                static_assert( std::numeric_limits<common::uintptr>::max() >=
                              std::numeric_limits<std::size_t>::max(),
                              "This implementation cannot guarantee to work." );
                if( type != memory_type::general_purpose )
                    return false;

                auto aligned_address = align( virtual_start, request.alignment );
                common::uintptr request_end = aligned_address + request.size;

                if( (request_end - virtual_start) / pagesize <= number_of_pages )
                    return true;

                return false;
            }

            /** \brief Checks whether the memory descriptor
             *         is valid.
             * \returns \a false if type is memory_type::invalid,
             *          true otherwise.
             */
            bool is_valid( void ) const { return (type != memory_type::invalid); }
        private:
            /** \brief Checks whether a memory descriptor does
             *         not fulfil the required guarantees.
             * \param[in] md The memory descriptor to validate
             * \returns \a true if the memory descriptor fulfils
             *          the guarantees and \a false otherwise.
             */
            static bool validate( const memory_descriptor &md )
            {
                // Check if memory block size already overflows
                if( (std::numeric_limits<common::uint64>::max() /
                     pagesize ) > md.number_of_pages )
                    return false;
                // Check if the block starting at physical_address
                // overflows
                if( (std::numeric_limits<common::uint64>::max() -
                    pagesize * md.number_of_pages) < md.physical_start )
                    return false;
                // Check if the block starting at virtual_address
                // overflows
                if( (std::numeric_limits<common::uint64>::max() -
                    pagesize * md.number_of_pages) < md.virtual_start )
                    return false;
                // Do not retain zero sized memory regions
                if( md.number_of_pages == 0 )
                    return false;
            }
        };

        /** \class memory_map
         * \brief The memory map used by the kernel
         * \tparam Allocator The type of allocator to use
         *
         * It has some sanity guarantees that UEFI lacks, like:
         * - fixed size of descriptors that is known compile-time
         * - overlapping ranges are merged if possible
         *   and removed otherwise
         */
        template<class Allocator>
        class memory_map
        {
        public:
            using allocator_type = Allocator;
        private:
            using desc_array = dynarray<memory_descriptor, allocator_type>;
            desc_array descriptors;

            /** \brief Checks whether the memory regions
             *         described by two memory descriptors
             *         overlap.
             * \param[in] md1 The first memory descriptor
             * \param[in] md2 The second memory descriptor
             * \returns \a true if there is an overlap
             * \warning The virtual start of \a md1 has to
             *          preceede that of \a md2, otherwise
             *          the behaviour is undefined.
             */
            static bool have_overlap( const memory_descriptor &md1,
                        const memory_descriptor &md2 )
            {
                debug_assert( md1.virtual_start <= md2.virtual_start,
                             "md1 does not preceede md2!" );

                auto end1 = md1.virtual_start + pagesize * md1.number_of_pages;
                return (end1 > md2.virtual_start);
            };

            /** \brief Merges the memory regions described
             *         by two overlapping memory descriptors.
             * \param[in] md1 The first memory descriptor
             * \param[in] md2 The second memory descriptor
             * \returns The merged memory descriptor describing
             *          both memory regions. If the regions
             *          are incompatible or either is invalid
             *          the returned descriptor will also be invalid.
             * \warning The virtual start of \a md1 has to
             *          preceede that of \a md2, otherwise
             *          the behaviour is undefined.
             * \warning The memory regions described by \a md1
             *          and \a md2 have to overlap, otherwise
             *          the behaviour is undefined.
             */
            static memory_descriptor merge_with_overlap( const memory_descriptor &md1,
                                                       const memory_descriptor &md2 )
            {
                debug_assert( md1.virtual_start <= md2.virtual_start,
                             "md1 does not preceede md2!" );
                debug_assert( have_overlap( md1, md2 ),
                             "md1 and md2 do not overlap" );

                if( md1.type != md2.type )
                {
                    // Different memory descriptor types
                    // for overlapping ranges... Corrupt!
                    return memory_descriptor::invalid_memory_descriptor();
                }

                auto size_before_overlap = md2.virtual_start - md1.virtual_start;
                auto physical_start2 = md1.physical_start + size_before_overlap;

                if( md2.physical_start != physical_start2 )
                {
                    // Same virtual address is mapped to multiple
                    // physical addresses... corrupt!
                    return memory_descriptor::invalid_memory_descriptor();
                }

                // Legal overlap
                auto end1 = (md1.virtual_start +
                             pagesize * md1.number_of_pages);
                auto end2 = (md2.virtual_start +
                             pagesize * md2.number_of_pages);
                auto end = std::max( end1, end2 );

                return memory_descriptor{ md1.type, md1.physical_start,
                    md1.virtual_start, (end - md1.virtual_start) / pagesize };
            }

            /** \brief Checks whether the memory regions described
             *         by two memory descriptors are adjacent
             *         and if they are mergable.
             * \param[in] md1 The first memory descriptor
             * \param[in] md2 The second memory descriptor
             * \returns \a true if the ranges are adjacent
             * \warning The virtual start of \a md1 has to
             *          preceede that of \a md2, otherwise
             *          the behaviour is undefined.
             *
             * Two memory ranges are mergable if they share the
             * same type and their physical addresses line up.
             */
            static bool are_adjacent_and_mergable( const memory_descriptor &md1,
                                                  const memory_descriptor &md2 )
            {
                debug_assert( md1.virtual_start <= md2.virtual_start,
                             "md1 does not preceede md2!" );

                if( md1.type != md2.type )
                    return false;

                auto end1 = md1.virtual_start + pagesize * md1.number_of_pages;

                if( md1.physical_start + (end1 - md1.virtual_start) != md2.physical_start )
                    return false;

                return (end1 == md2.virtual_start);
            };

            /** \brief Merges the memory regions described
             *         by two adjacent memory descriptors.
             * \param[in] md1 The first memory descriptor
             * \param[in] md2 The second memory descriptor
             * \returns The merged memory descriptor describing
             *          both memory regions.
             * \warning The virtual start of \a md1 has to
             *          preceede that of \a md2, otherwise
             *          the behaviour is undefined.
             * \warning The memory regions described by \a md1
             *          and \a md2 have to be adjacent and mergable,
             *          otherwise the behaviour is undefined.
             */
            static memory_descriptor merge_adjacent( const memory_descriptor &md1,
                                                    const memory_descriptor &md2 )
            {
                debug_assert( md1.virtual_start <= md2.virtual_start,
                             "md1 does not preceede md2!" );
                debug_assert( are_adjacent_and_mergable( md1, md2 ),
                             "md1 and md2 are not adjacent!" );

                auto end = (md2.virtual_start +
                            pagesize * md2.number_of_pages);

                return memory_descriptor{ md1.type, md1.physical_start,
                    md1.virtual_start, (end - md1.virtual_start) / pagesize };
            }

            /** \brief Convert a uefi memory map to a
             *         kernel-usable one.
             * \param[in] uefi_map The UEFI memory map
             * \param[in] The allocator to use
             * \returns An array of descriptors with the guarantee
             *          that they do not overlap.
             */
            static desc_array
            convert_from_uefi( const UEFI::memory_map &uefi_map,
                              allocator_type &&alloc )
            {
                desc_array stage1_descriptors( uefi_map.cbegin_v1(),
                                              uefi_map.cend_v1(),
                                              std::forward<allocator_type>( alloc ) );

                auto endValid = std::partition( stage1_descriptors.begin(),
                                               stage1_descriptors.end(),
                                               std::mem_fn( &memory_descriptor::is_valid ) );

                std::sort( stage1_descriptors.begin(), stage1_descriptors.end(),
                          [] ( const memory_descriptor &md1, const memory_descriptor &md2 ) {
                              return (md1.virtual_start < md2.virtual_start);
                          } );

                for( auto lower = stage1_descriptors.begin();
                    lower != endValid; ++lower )
                {
                    auto &md1 = *lower;
                    auto upper = lower + 1;

                    if( upper == endValid )
                        break;
                    auto &md2 = *upper;

                    if( have_overlap( md1, md2 ) )
                    {
                        md2 = merge_with_overlap( md1, md2 );
                        if( md2.type == memory_type::invalid )
                            md1.type = memory_type::invalid;
                        ++lower;
                    } else if( are_adjacent_and_mergable( md1, md2 ) )
                    {
                        md2 = merge_adjacent( md1, md2 );
                        ++lower;
                    }
                }

                endValid = std::partition( stage1_descriptors.begin(),
                                          stage1_descriptors.end(),
                                          std::mem_fn( &memory_descriptor::is_valid ) );

                return desc_array( std::move( stage1_descriptors ),
                                  endValid - stage1_descriptors.begin() );
            }
        public:
            /** \brief Returns a memory_request that when fulfilled
             *         will suffice to convert a UEFI memory map
             *         to a kernel-usable one.
             * \param[in] uefi_map The UEFI memory map
             * \returns The memory_request
             */
            static memory_request<alignof(memory_descriptor)>
            maximum_conversion_requirement( const UEFI::memory_map &uefi_map )
            {
                return { uefi_map.number_of_descriptors * sizeof(memory_descriptor) };
            }

            /** \brief Returns a memory_request that when fulfilled
             *         will suffice to copy the memory map.
             * \returns The memory_request
             */
            memory_request<alignof(memory_descriptor)> copy_requirement( void ) const
            {
                return { descriptors.size() * sizeof(memory_descriptor) };
            }

            /** \brief Constructs a kernel-usable memory map
             *         from a UEFI memory map.
             * \param[in] uefi_map The UEFI memory map
             * \param[in] alloc The allocator used to copy the
             *                  memory map. It has to be able to
             *                  allocate at least what is returned
             *                  by \a maximum_conversion_requirement.
             */
            memory_map( const UEFI::memory_map &uefi_map, allocator_type &&alloc )
            : descriptors( convert_from_uefi( uefi_map,
                                             std::forward<allocator_type>( alloc ) ) )
            {}

            /** \brief Returns a const iterator to the begin of
             *         the memory descriptor range.
             * \returns A const iterator to the begin of
             *          the memory descriptor range
             */
            typename desc_array::const_iterator cbegin( void ) const
            { return descriptors.cbegin(); }

            /** \brief Returns a const iterator to the end of
             *         the memory descriptor range.
             * \returns A const iterator to the end of
             *          the memory descriptor range
             */
            typename desc_array::const_iterator cend( void ) const
            { return descriptors.cend(); }
        };
    }
}

#endif

/** \} */
<|endoftext|>


<commit_before>#ifndef __MAPNIK_COMPARE_IMAGES_HPP__
#define __MAPNIK_COMPARE_IMAGES_HPP__

#include <mapnik/image.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/image_reader.hpp>

using namespace mapnik;

namespace benchmark {

    bool compare_images(std::string const& src_fn,std::string const& dest_fn)
    {
        std::unique_ptr<mapnik::image_reader> reader1(mapnik::get_image_reader(dest_fn,"png"));
        if (!reader1.get())
        {
            throw mapnik::image_reader_exception("Failed to load: " + dest_fn);
        }

        std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(src_fn,"png"));
        if (!reader2.get())
        {
            throw mapnik::image_reader_exception("Failed to load: " + src_fn);
        }

        image_rgba8 const& dest = util::get<image_rgba8>(reader1->read(0,0,reader1->width(), reader1->height()));
        image_rgba8 const& src = util::get<image_rgba8>(reader1->read(0,0,reader1->width(), reader1->height()));

        unsigned int width = src.width();
        unsigned int height = src.height();
        if ((width != dest.width()) || height != dest.height()) return false;
        for (unsigned int y = 0; y < height; ++y)
        {
            const unsigned int* row_from = src.getRow(y);
            const unsigned int* row_to = dest.getRow(y);
            for (unsigned int x = 0; x < width; ++x)
            {
               if (row_from[x] != row_to[x]) return false;
            }
        }
        return true;
    }

}

#endif // __MAPNIK_COMPARE_IMAGES_HPP__
<commit_msg>benchmark: fix image loading<commit_after>#ifndef __MAPNIK_COMPARE_IMAGES_HPP__
#define __MAPNIK_COMPARE_IMAGES_HPP__

#include <mapnik/image.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/image_reader.hpp>

using namespace mapnik;

namespace benchmark {

    bool compare_images(std::string const& src_fn,std::string const& dest_fn)
    {
        std::unique_ptr<mapnik::image_reader> reader1(mapnik::get_image_reader(dest_fn,"png"));
        if (!reader1.get())
        {
            throw mapnik::image_reader_exception("Failed to load: " + dest_fn);
        }

        std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(src_fn,"png"));
        if (!reader2.get())
        {
            throw mapnik::image_reader_exception("Failed to load: " + src_fn);
        }

        image_rgba8 const& dest = util::get<image_rgba8>(reader1->read(0,0,reader1->width(), reader1->height()));
        image_rgba8 const& src = util::get<image_rgba8>(reader2->read(0,0,reader2->width(), reader2->height()));

        unsigned int width = src.width();
        unsigned int height = src.height();
        if ((width != dest.width()) || height != dest.height()) return false;
        for (unsigned int y = 0; y < height; ++y)
        {
            const unsigned int* row_from = src.getRow(y);
            const unsigned int* row_to = dest.getRow(y);
            for (unsigned int x = 0; x < width; ++x)
            {
               if (row_from[x] != row_to[x]) return false;
            }
        }
        return true;
    }

}

#endif // __MAPNIK_COMPARE_IMAGES_HPP__
<|endoftext|>