<commit_before>// C++ source file - (C) 2003 Robert Osfield, released under the OSGPL.
//
// Simple example of use of Producer::RenderSurface to create an OpenGL
// graphics window, and OSG for rendering.

#include <osg/Timer>
#include <osg/GraphicsContext>
#include <osg/GraphicsThread>

#include <osgUtil/UpdateVisitor>
#include <osgUtil/CullVisitor>
#include <osgUtil/SceneView>
#include <osgUtil/GLObjectsVisitor>

#include <osgDB/ReadFile>

#include <map>
#include <list>
#include <iostream>

////////////////////////////////////////////////////////////////////////////////
//
//
//  **************** THIS IS AN EXPERIMENTAL IMPLEMENTATION ***************
//  ************************** PLEASE DO NOT COPY  ************************
//
//
///////////////////////////////////////////////////////////////////////////////

// Compile operation, that compile OpenGL objects.
struct CompileOperation : public osg::GraphicsThread::Operation
{
    CompileOperation(osg::Node* scene):
        osg::GraphicsThread::Operation("Compile",false),
        _scene(scene)
    {
    }

    virtual void operator () (osg::GraphicsContext* context)
    {
        std::cout<<"Compile"<<std::endl;

        osgUtil::GLObjectsVisitor compileVisitor;
        compileVisitor.setState(context->getState());

        // do the compile traversal
        _scene->accept(compileVisitor);
    }

    osg::ref_ptr<osg::Node> _scene;
};

// Cull operation, that does a cull on the scene graph.
struct CullOperation : public osg::GraphicsThread::Operation
{
    CullOperation(osg::CameraNode* camera, osgUtil::SceneView* sceneView):
        osg::GraphicsThread::Operation("Cull",true),
        _camera(camera),
        _sceneView(sceneView)
    {
    }

    virtual void operator () (osg::GraphicsContext* context)
    {
        _sceneView->setState(context->getState());
        _sceneView->setProjectionMatrix(_camera->getProjectionMatrix());
        _sceneView->setViewMatrix(_camera->getViewMatrix());
        _sceneView->setViewport(_camera->getViewport());

        _sceneView->cull();
    }

    osg::ref_ptr<osg::CameraNode>    _camera;
    osg::ref_ptr<osgUtil::SceneView> _sceneView;
};

// Draw operation, that does a draw on the scene graph.
struct DrawOperation : public osg::GraphicsThread::Operation
{
    DrawOperation(osgUtil::SceneView* sceneView):
        osg::GraphicsThread::Operation("Draw",true),
        _sceneView(sceneView)
    {
    }

    virtual void operator () (osg::GraphicsContext*)
    {
        _sceneView->draw();
    }

    osg::ref_ptr<osgUtil::SceneView> _sceneView;
};

// main does the following steps to create a multi-thread, multiple camera/graphics context view of a scene graph.
//
// 1) load the scene graph
//
// 2) create a list of camera, each with their own graphis context, with a graphics thread for each context.
//
// 3) set up the graphic threads so that the do an initial compile OpenGL objects operation, this is done once, and then this compile op is disgarded
//
// 4) set up the graphics thread so that it has all the graphics ops required for the main loop, these ops are:
// 4.a) frame begin barrair, syncronizes all the waiting graphic threads so they don't run while update is occuring
// 4.b) frame operation - the cull and draw for each camera
// 4.c) frame end barrier, releases the update thread once all graphic threads have dispatched all their OpenGL commands
// 4.d) pre swap barrier, barrier which ensures that all graphics threads have sent their data down to the gfx card.
// 4.e) swap buffers, do the swap buffers on all the graphics contexts.
//
// 5. The main loop:
// 5.a) update
// 5.b) join the frame begin barrrier, releasing all the graphics threads to do their stuff
// 5.c) block on the frame end barrier, waiting till all the graphics threads have done their cull/draws.
// 5.d) check to see if any of the windows has been closed.
//
int main( int argc, char **argv )
{
    if (argc<2)
    {
        std::cout << argv[0] <<": requires filename argument." << std::endl;
        return 1;
    }

    // load the scene.
    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFile(argv[1]);
    if (!loadedModel)
    {
        std::cout << argv[0] <<": No data loaded." << std::endl;
        return 1;
    }

    // set up the frame stamp for current frame to record the current time and frame number so that animtion code can advance correctly
    osg::ref_ptr<osg::FrameStamp> frameStamp = new osg::FrameStamp;

    unsigned int frameNum = 0;

    osgUtil::UpdateVisitor updateVisitor;
    updateVisitor.setFrameStamp(frameStamp.get());

    unsigned int numberCameras = 3;
    unsigned int xpos = 0;
    unsigned int ypos = 400;
    unsigned int width = 400;
    unsigned int height = 400;

    typedef std::list< osg::ref_ptr<osg::CameraNode> > CameraList;
    typedef std::set< osg::GraphicsContext* > GraphicsContextSet;

    CameraList cameraList;
    GraphicsContextSet graphicsContextSet;

    // create the cameras, graphic contexts and graphic threads.
    bool shareContexts = false;
    osg::GraphicsContext* previousContext = 0;
    for(unsigned int i=0; i< numberCameras; ++i)
    {
        osg::ref_ptr<osg::CameraNode> camera = new osg::CameraNode;
        camera->addChild(loadedModel.get());

        osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
        traits->_windowName = "osgcamera";
        traits->_x = xpos;
        traits->_y = ypos;
        traits->_width = width;
        traits->_height = height;
        traits->_windowDecoration = true;
        traits->_doubleBuffer = true;
        traits->_sharedContext = shareContexts ? previousContext : 0;

        xpos += width;

        osg::ref_ptr<osg::GraphicsContext> gfxc = osg::GraphicsContext::createGraphicsContext(traits.get());

        if (!gfxc)
        {
            std::cout<<"Unable to create window."<<std::endl;
            return 1;
        }

        camera->setGraphicsContext(gfxc.get());

        // initialize the view to look at the center of the scene graph
        const osg::BoundingSphere& bs = loadedModel->getBound();
        osg::Matrix viewMatrix;
        viewMatrix.makeLookAt(bs.center()-osg::Vec3(0.0,2.0f*bs.radius(),0.0),bs.center(),osg::Vec3(0.0f,0.0f,1.0f));

        camera->setViewport(0,0,traits->_width,traits->_height);
        camera->setProjectionMatrixAsPerspective(50.0f,1.4f,1.0f,10000.0f);
        camera->setViewMatrix(viewMatrix);

        // graphics thread will realize the window.
        gfxc->createGraphicsThread();

        cameraList.push_back(camera);

        previousContext = gfxc.get();
    }

    // build the list of unique graphics contexts.
    CameraList::iterator citr;
    for(citr = cameraList.begin();
        citr != cameraList.end();
        ++citr)
    {
        graphicsContextSet.insert(const_cast<osg::GraphicsContext*>((*citr)->getGraphicsContext()));
    }

    std::cout<<"Number of cameras = "<<cameraList.size()<<std::endl;
    std::cout<<"Number of graphics contexts = "<<graphicsContextSet.size()<<std::endl;

    // first the compile of the GL Objects, do it syncronously.
    GraphicsContextSet::iterator gitr;
    osg::ref_ptr<CompileOperation> compileOp = new CompileOperation(loadedModel.get());
    for(gitr = graphicsContextSet.begin();
        gitr != graphicsContextSet.end();
        ++gitr)
    {
        osg::GraphicsContext* context = *gitr;
        context->getGraphicsThread()->add(compileOp.get(), false);
    }

    // second the begin frame barrier to all graphics threads
    osg::ref_ptr<osg::BarrierOperation> frameBeginBarrierOp = new osg::BarrierOperation(graphicsContextSet.size()+1, osg::BarrierOperation::NO_OPERATION);
    for(gitr = graphicsContextSet.begin();
        gitr != graphicsContextSet.end();
        ++gitr)
    {
        osg::GraphicsContext* context = *gitr;
        context->getGraphicsThread()->add(frameBeginBarrierOp.get(), false);
    }

    osg::ref_ptr<osg::BarrierOperation> glFinishBarrierOp = new osg::BarrierOperation(graphicsContextSet.size(), osg::BarrierOperation::GL_FINISH);

    // we can put a finish in to gate rendering throughput, so that each new frame starts with a clean sheet.
    // you should only enable one of these, doFinishBeforeNewDraw will allow for the better parallism of the two finish approaches
    bool doFinishBeforeNewDraw = true;
    bool doFinishAfterSwap = false;

    // third add the frame for each camera.
    for(citr = cameraList.begin();
        citr != cameraList.end();
        ++citr)
    {
        osg::CameraNode* camera = citr->get();

        // create a scene view to do the cull and draw
        osgUtil::SceneView* sceneView = new osgUtil::SceneView;
        sceneView->setDefaults();
        sceneView->setFrameStamp(frameStamp.get());

        if (camera->getNumChildren()>=1)
        {
            sceneView->setSceneData(camera->getChild(0));
        }

        // cull traversal operation
        camera->getGraphicsContext()->getGraphicsThread()->add( new CullOperation(camera, sceneView), false);

        // optionally add glFinish barrier to ensure that all OpenGL commands are completed before we start dispatching a new frame
        if (doFinishBeforeNewDraw) camera->getGraphicsContext()->getGraphicsThread()->add( glFinishBarrierOp.get(), false);

        // draw traversal operation.
        camera->getGraphicsContext()->getGraphicsThread()->add( new DrawOperation(sceneView), false);
    }

    // fourth add the frame end barrier, the pre swap barrier and finally the swap buffers to each graphics thread.
    // The frame end barrier tells the main thead that the draw dispatch/read phase of the scene graph is complete.
    // The pre swap barrier is an optional extra, which does a flush before joining the barrier, using this all graphics threads
    // are held back until they have all dispatched their fifo to the graphics hardware.
    // The swapOp just issues a swap buffers for each of the graphics contexts.
    osg::ref_ptr<osg::BarrierOperation> frameEndBarrierOp = new osg::BarrierOperation(graphicsContextSet.size()+1, osg::BarrierOperation::NO_OPERATION);
    osg::ref_ptr<osg::BarrierOperation> preSwapBarrierOp = new osg::BarrierOperation(graphicsContextSet.size(), osg::BarrierOperation::GL_FLUSH);
    osg::ref_ptr<osg::SwapBuffersOperation> swapOp = new osg::SwapBuffersOperation();
    for(gitr = graphicsContextSet.begin();
        gitr != graphicsContextSet.end();
        ++gitr)
    {
        osg::GraphicsContext* context = *gitr;

        context->getGraphicsThread()->add(frameEndBarrierOp.get(), false);
        context->getGraphicsThread()->add(preSwapBarrierOp.get(), false);
        context->getGraphicsThread()->add(swapOp.get(), false);

        // optionally add finish barrier to ensure that we don't do any other graphics work till the current OpenGL commands are complete.
        if (doFinishAfterSwap) context->getGraphicsThread()->add(glFinishBarrierOp.get(), false);
    }

    // record the timer tick at the start of rendering.
    osg::Timer_t start_tick = osg::Timer::instance()->tick();
    osg::Timer_t previous_tick = start_tick;

    bool done = false;

    // main loop -  update scene graph, dispatch frame, wait for frame done.
    while( !done )
    {

        osg::Timer_t current_tick = osg::Timer::instance()->tick();

        frameStamp->setReferenceTime(osg::Timer::instance()->delta_s(start_tick,current_tick));
        frameStamp->setFrameNumber(frameNum++);

        std::cout<<"Frame rate "<<1.0/osg::Timer::instance()->delta_s(previous_tick,current_tick)<<std::endl;
        previous_tick = current_tick;

        // do the update traversal.
        loadedModel->accept(updateVisitor);

        // dispatch the frame.
        frameBeginBarrierOp->block();

        // wait till the frame is done.
        frameEndBarrierOp->block();

        // check if any of the windows are closed
        for(gitr = graphicsContextSet.begin();
            gitr != graphicsContextSet.end();
            ++gitr)
        {
            osg::GraphicsContext* context = *gitr;
            if (!context->isRealized()) done = true;
        }

    }
    return 0;
}
<commit_msg>Disable the glFinishBarrierOp usage as glFinish was spin locking the CPU :-|<commit_after>// C++ source file - (C) 2003 Robert Osfield, released under the OSGPL.
//
// Simple example of use of Producer::RenderSurface to create an OpenGL
// graphics window, and OSG for rendering.

#include <osg/Timer>
#include <osg/GraphicsContext>
#include <osg/GraphicsThread>

#include <osgUtil/UpdateVisitor>
#include <osgUtil/CullVisitor>
#include <osgUtil/SceneView>
#include <osgUtil/GLObjectsVisitor>

#include <osgDB/ReadFile>

#include <map>
#include <list>
#include <iostream>

////////////////////////////////////////////////////////////////////////////////
//
//
//  **************** THIS IS AN EXPERIMENTAL IMPLEMENTATION ***************
//  ************************** PLEASE DO NOT COPY  ************************
//
//
///////////////////////////////////////////////////////////////////////////////

// Compile operation, that compile OpenGL objects.
struct CompileOperation : public osg::GraphicsThread::Operation
{
    CompileOperation(osg::Node* scene):
        osg::GraphicsThread::Operation("Compile",false),
        _scene(scene)
    {
    }

    virtual void operator () (osg::GraphicsContext* context)
    {
        std::cout<<"Compile"<<std::endl;

        osgUtil::GLObjectsVisitor compileVisitor;
        compileVisitor.setState(context->getState());

        // do the compile traversal
        _scene->accept(compileVisitor);
    }

    osg::ref_ptr<osg::Node> _scene;
};

// Cull operation, that does a cull on the scene graph.
struct CullOperation : public osg::GraphicsThread::Operation
{
    CullOperation(osg::CameraNode* camera, osgUtil::SceneView* sceneView):
        osg::GraphicsThread::Operation("Cull",true),
        _camera(camera),
        _sceneView(sceneView)
    {
    }

    virtual void operator () (osg::GraphicsContext* context)
    {
        _sceneView->setState(context->getState());
        _sceneView->setProjectionMatrix(_camera->getProjectionMatrix());
        _sceneView->setViewMatrix(_camera->getViewMatrix());
        _sceneView->setViewport(_camera->getViewport());

        _sceneView->cull();
    }

    osg::ref_ptr<osg::CameraNode>    _camera;
    osg::ref_ptr<osgUtil::SceneView> _sceneView;
};

// Draw operation, that does a draw on the scene graph.
struct DrawOperation : public osg::GraphicsThread::Operation
{
    DrawOperation(osgUtil::SceneView* sceneView):
        osg::GraphicsThread::Operation("Draw",true),
        _sceneView(sceneView)
    {
    }

    virtual void operator () (osg::GraphicsContext*)
    {
        _sceneView->draw();
    }

    osg::ref_ptr<osgUtil::SceneView> _sceneView;
};

// main does the following steps to create a multi-thread, multiple camera/graphics context view of a scene graph.
//
// 1) load the scene graph
//
// 2) create a list of camera, each with their own graphis context, with a graphics thread for each context.
//
// 3) set up the graphic threads so that the do an initial compile OpenGL objects operation, this is done once, and then this compile op is disgarded
//
// 4) set up the graphics thread so that it has all the graphics ops required for the main loop, these ops are:
// 4.a) frame begin barrair, syncronizes all the waiting graphic threads so they don't run while update is occuring
// 4.b) frame operation - the cull and draw for each camera
// 4.c) frame end barrier, releases the update thread once all graphic threads have dispatched all their OpenGL commands
// 4.d) pre swap barrier, barrier which ensures that all graphics threads have sent their data down to the gfx card.
// 4.e) swap buffers, do the swap buffers on all the graphics contexts.
//
// 5. The main loop:
// 5.a) update
// 5.b) join the frame begin barrrier, releasing all the graphics threads to do their stuff
// 5.c) block on the frame end barrier, waiting till all the graphics threads have done their cull/draws.
// 5.d) check to see if any of the windows has been closed.
//
int main( int argc, char **argv )
{
    if (argc<2)
    {
        std::cout << argv[0] <<": requires filename argument." << std::endl;
        return 1;
    }

    // load the scene.
    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFile(argv[1]);
    if (!loadedModel)
    {
        std::cout << argv[0] <<": No data loaded." << std::endl;
        return 1;
    }

    // set up the frame stamp for current frame to record the current time and frame number so that animtion code can advance correctly
    osg::ref_ptr<osg::FrameStamp> frameStamp = new osg::FrameStamp;

    unsigned int frameNum = 0;

    osgUtil::UpdateVisitor updateVisitor;
    updateVisitor.setFrameStamp(frameStamp.get());

    unsigned int numberCameras = 1;
    unsigned int xpos = 0;
    unsigned int ypos = 400;
    unsigned int width = 400;
    unsigned int height = 400;

    typedef std::list< osg::ref_ptr<osg::CameraNode> > CameraList;
    typedef std::set< osg::GraphicsContext* > GraphicsContextSet;

    CameraList cameraList;
    GraphicsContextSet graphicsContextSet;

    // create the cameras, graphic contexts and graphic threads.
    bool shareContexts = false;
    osg::GraphicsContext* previousContext = 0;
    for(unsigned int i=0; i< numberCameras; ++i)
    {
        osg::ref_ptr<osg::CameraNode> camera = new osg::CameraNode;
        camera->addChild(loadedModel.get());

        osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
        traits->_windowName = "osgcamera";
        traits->_x = xpos;
        traits->_y = ypos;
        traits->_width = width;
        traits->_height = height;
        traits->_windowDecoration = true;
        traits->_doubleBuffer = true;
        traits->_sharedContext = shareContexts ? previousContext : 0;

        xpos += width;

        osg::ref_ptr<osg::GraphicsContext> gfxc = osg::GraphicsContext::createGraphicsContext(traits.get());

        if (!gfxc)
        {
            std::cout<<"Unable to create window."<<std::endl;
            return 1;
        }

        camera->setGraphicsContext(gfxc.get());

        // initialize the view to look at the center of the scene graph
        const osg::BoundingSphere& bs = loadedModel->getBound();
        osg::Matrix viewMatrix;
        viewMatrix.makeLookAt(bs.center()-osg::Vec3(0.0,2.0f*bs.radius(),0.0),bs.center(),osg::Vec3(0.0f,0.0f,1.0f));

        camera->setViewport(0,0,traits->_width,traits->_height);
        camera->setProjectionMatrixAsPerspective(50.0f,1.4f,1.0f,10000.0f);
        camera->setViewMatrix(viewMatrix);

        // graphics thread will realize the window.
        gfxc->createGraphicsThread();

        cameraList.push_back(camera);

        previousContext = gfxc.get();
    }

    // build the list of unique graphics contexts.
    CameraList::iterator citr;
    for(citr = cameraList.begin();
        citr != cameraList.end();
        ++citr)
    {
        graphicsContextSet.insert(const_cast<osg::GraphicsContext*>((*citr)->getGraphicsContext()));
    }

    std::cout<<"Number of cameras = "<<cameraList.size()<<std::endl;
    std::cout<<"Number of graphics contexts = "<<graphicsContextSet.size()<<std::endl;

    // first the compile of the GL Objects, do it syncronously.
    GraphicsContextSet::iterator gitr;
    osg::ref_ptr<CompileOperation> compileOp = new CompileOperation(loadedModel.get());
    for(gitr = graphicsContextSet.begin();
        gitr != graphicsContextSet.end();
        ++gitr)
    {
        osg::GraphicsContext* context = *gitr;
        context->getGraphicsThread()->add(compileOp.get(), false);
    }

    // second the begin frame barrier to all graphics threads
    osg::ref_ptr<osg::BarrierOperation> frameBeginBarrierOp = new osg::BarrierOperation(graphicsContextSet.size()+1, osg::BarrierOperation::NO_OPERATION);
    for(gitr = graphicsContextSet.begin();
        gitr != graphicsContextSet.end();
        ++gitr)
    {
        osg::GraphicsContext* context = *gitr;
        context->getGraphicsThread()->add(frameBeginBarrierOp.get(), false);
    }

    osg::ref_ptr<osg::BarrierOperation> glFinishBarrierOp = new osg::BarrierOperation(graphicsContextSet.size(), osg::BarrierOperation::GL_FINISH);

    // we can put a finish in to gate rendering throughput, so that each new frame starts with a clean sheet.
    // you should only enable one of these, doFinishBeforeNewDraw will allow for the better parallism of the two finish approaches
    // note, both are disabled right now, as glFinish is spin locking the CPU, not something that we want...
    bool doFinishBeforeNewDraw = false;
    bool doFinishAfterSwap = false;

    // third add the frame for each camera.
    for(citr = cameraList.begin();
        citr != cameraList.end();
        ++citr)
    {
        osg::CameraNode* camera = citr->get();

        // create a scene view to do the cull and draw
        osgUtil::SceneView* sceneView = new osgUtil::SceneView;
        sceneView->setDefaults();
        sceneView->setFrameStamp(frameStamp.get());

        if (camera->getNumChildren()>=1)
        {
            sceneView->setSceneData(camera->getChild(0));
        }

        // cull traversal operation
        camera->getGraphicsContext()->getGraphicsThread()->add( new CullOperation(camera, sceneView), false);

        // optionally add glFinish barrier to ensure that all OpenGL commands are completed before we start dispatching a new frame
        if (doFinishBeforeNewDraw) camera->getGraphicsContext()->getGraphicsThread()->add( glFinishBarrierOp.get(), false);

        // draw traversal operation.
        camera->getGraphicsContext()->getGraphicsThread()->add( new DrawOperation(sceneView), false);
    }

    // fourth add the frame end barrier, the pre swap barrier and finally the swap buffers to each graphics thread.
    // The frame end barrier tells the main thead that the draw dispatch/read phase of the scene graph is complete.
    // The pre swap barrier is an optional extra, which does a flush before joining the barrier, using this all graphics threads
    // are held back until they have all dispatched their fifo to the graphics hardware.
    // The swapOp just issues a swap buffers for each of the graphics contexts.
    osg::ref_ptr<osg::BarrierOperation> frameEndBarrierOp = new osg::BarrierOperation(graphicsContextSet.size()+1, osg::BarrierOperation::NO_OPERATION);
    osg::ref_ptr<osg::BarrierOperation> preSwapBarrierOp = new osg::BarrierOperation(graphicsContextSet.size(), osg::BarrierOperation::GL_FLUSH);
    osg::ref_ptr<osg::SwapBuffersOperation> swapOp = new osg::SwapBuffersOperation();
    for(gitr = graphicsContextSet.begin();
        gitr != graphicsContextSet.end();
        ++gitr)
    {
        osg::GraphicsContext* context = *gitr;

        context->getGraphicsThread()->add(frameEndBarrierOp.get(), false);
        // context->getGraphicsThread()->add(preSwapBarrierOp.get(), false);
        context->getGraphicsThread()->add(swapOp.get(), false);

        // optionally add finish barrier to ensure that we don't do any other graphics work till the current OpenGL commands are complete.
        if (doFinishAfterSwap) context->getGraphicsThread()->add(glFinishBarrierOp.get(), false);
    }

    // record the timer tick at the start of rendering.
    osg::Timer_t start_tick = osg::Timer::instance()->tick();
    osg::Timer_t previous_tick = start_tick;

    bool done = false;

    // main loop -  update scene graph, dispatch frame, wait for frame done.
    while( !done )
    {

        osg::Timer_t current_tick = osg::Timer::instance()->tick();

        frameStamp->setReferenceTime(osg::Timer::instance()->delta_s(start_tick,current_tick));
        frameStamp->setFrameNumber(frameNum++);

        //std::cout<<"Frame rate "<<1.0/osg::Timer::instance()->delta_s(previous_tick,current_tick)<<std::endl;
        previous_tick = current_tick;

        // do the update traversal.
        loadedModel->accept(updateVisitor);

        // dispatch the frame.
        frameBeginBarrierOp->block();

        // wait till the frame is done.
        frameEndBarrierOp->block();

        // check if any of the windows are closed
        for(gitr = graphicsContextSet.begin();
            gitr != graphicsContextSet.end();
            ++gitr)
        {
            osg::GraphicsContext* context = *gitr;
            if (!context->isRealized()) done = true;
        }

    }
    return 0;
}
<|endoftext|>


<commit_before>//===-- GlobalDCE.cpp - DCE unreachable internal functions ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This transform is designed to eliminate unreachable internal globals from the
// program.  It uses an aggressive algorithm, searching out globals that are
// known to be alive.  After it finds all of the globals which are needed, it
// deletes whatever is left over.  This allows it to delete recursive chunks of
// the program which are unreachable.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "globaldce"
#include "llvm/Transforms/IPO.h"
#include "llvm/Constants.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
#include <set>
using namespace llvm;

STATISTIC(NumAliases  , "Number of global aliases removed");
STATISTIC(NumFunctions, "Number of functions removed");
STATISTIC(NumVariables, "Number of global variables removed");

namespace {
  struct VISIBILITY_HIDDEN GlobalDCE : public ModulePass {
    static char ID; // Pass identification, replacement for typeid
    GlobalDCE() : ModulePass(&ID) {}

    // run - Do the GlobalDCE pass on the specified module, optionally updating
    // the specified callgraph to reflect the changes.
    //
    bool runOnModule(Module &M);

  private:
    std::set<GlobalValue*> AliveGlobals;

    /// GlobalIsNeeded - mark the specific global value as needed, and
    /// recursively mark anything that it uses as also needed.
    void GlobalIsNeeded(GlobalValue *GV);
    void MarkUsedGlobalsAsNeeded(Constant *C);

    bool RemoveUnusedGlobalValue(GlobalValue &GV);
  };
}

char GlobalDCE::ID = 0;
static RegisterPass<GlobalDCE> X("globaldce", "Dead Global Elimination");

ModulePass *llvm::createGlobalDCEPass() { return new GlobalDCE(); }

bool GlobalDCE::runOnModule(Module &M) {
  bool Changed = false;

  // Loop over the module, adding globals which are obviously necessary.
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
    Changed |= RemoveUnusedGlobalValue(*I);
    // Functions with external linkage are needed if they have a body
    if (!I->hasLocalLinkage() && !I->hasLinkOnceLinkage() &&
        !I->isDeclaration() && !I->hasAvailableExternallyLinkage())
      GlobalIsNeeded(I);
  }

  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
       I != E; ++I) {
    Changed |= RemoveUnusedGlobalValue(*I);
    // Externally visible & appending globals are needed, if they have an
    // initializer.
    if (!I->hasLocalLinkage() && !I->hasLinkOnceLinkage() &&
        !I->isDeclaration() && !I->hasAvailableExternallyLinkage())
      GlobalIsNeeded(I);
  }

  for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end();
       I != E; ++I) {
    Changed |= RemoveUnusedGlobalValue(*I);
    // Externally visible aliases are needed.
    if (!I->hasLocalLinkage() && !I->hasLinkOnceLinkage())
      GlobalIsNeeded(I);
  }

  // Now that all globals which are needed are in the AliveGlobals set, we loop
  // through the program, deleting those which are not alive.
  //

  // The first pass is to drop initializers of global variables which are dead.
  std::vector<GlobalVariable*> DeadGlobalVars;   // Keep track of dead globals
  for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
    if (!AliveGlobals.count(I)) {
      DeadGlobalVars.push_back(I);         // Keep track of dead globals
      I->setInitializer(0);
    }

  // The second pass drops the bodies of functions which are dead...
  std::vector<Function*> DeadFunctions;
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!AliveGlobals.count(I)) {
      DeadFunctions.push_back(I);         // Keep track of dead globals
      if (!I->isDeclaration())
        I->deleteBody();
    }

  // The third pass drops targets of aliases which are dead...
  std::vector<GlobalAlias*> DeadAliases;
  for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E;
       ++I)
    if (!AliveGlobals.count(I)) {
      DeadAliases.push_back(I);
      I->setAliasee(0);
    }

  if (!DeadFunctions.empty()) {
    // Now that all interferences have been dropped, delete the actual objects
    // themselves.
    for (unsigned i = 0, e = DeadFunctions.size(); i != e; ++i) {
      RemoveUnusedGlobalValue(*DeadFunctions[i]);
      M.getFunctionList().erase(DeadFunctions[i]);
    }
    NumFunctions += DeadFunctions.size();
    Changed = true;
  }

  if (!DeadGlobalVars.empty()) {
    for (unsigned i = 0, e = DeadGlobalVars.size(); i != e; ++i) {
      RemoveUnusedGlobalValue(*DeadGlobalVars[i]);
      M.getGlobalList().erase(DeadGlobalVars[i]);
    }
    NumVariables += DeadGlobalVars.size();
    Changed = true;
  }

  // Now delete any dead aliases.
  if (!DeadAliases.empty()) {
    for (unsigned i = 0, e = DeadAliases.size(); i != e; ++i) {
      RemoveUnusedGlobalValue(*DeadAliases[i]);
      M.getAliasList().erase(DeadAliases[i]);
    }
    NumAliases += DeadAliases.size();
    Changed = true;
  }

  // Make sure that all memory is released
  AliveGlobals.clear();

  // Remove dead metadata.
  Changed |= M.getContext().RemoveDeadMetadata();
  return Changed;
}

/// GlobalIsNeeded - the specific global value as needed, and
/// recursively mark anything that it uses as also needed.
void GlobalDCE::GlobalIsNeeded(GlobalValue *G) {
  std::set<GlobalValue*>::iterator I = AliveGlobals.find(G);

  // If the global is already in the set, no need to reprocess it.
  if (I != AliveGlobals.end()) return;

  // Otherwise insert it now, so we do not infinitely recurse
  AliveGlobals.insert(I, G);

  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(G)) {
    // If this is a global variable, we must make sure to add any global values
    // referenced by the initializer to the alive set.
    if (GV->hasInitializer())
      MarkUsedGlobalsAsNeeded(GV->getInitializer());
  } else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(G)) {
    // The target of a global alias is needed.
    MarkUsedGlobalsAsNeeded(GA->getAliasee());
  } else {
    // Otherwise this must be a function object.  We have to scan the body of
    // the function looking for constants and global values which are used as
    // operands.  Any operands of these types must be processed to ensure that
    // any globals used will be marked as needed.
    Function *F = cast<Function>(G);
    // For all basic blocks...
    for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
      // For all instructions...
      for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
        // For all operands...
        for (User::op_iterator U = I->op_begin(), E = I->op_end(); U != E; ++U)
          if (GlobalValue *GV = dyn_cast<GlobalValue>(*U))
            GlobalIsNeeded(GV);
          else if (Constant *C = dyn_cast<Constant>(*U))
            MarkUsedGlobalsAsNeeded(C);
  }
}

void GlobalDCE::MarkUsedGlobalsAsNeeded(Constant *C) {
  if (GlobalValue *GV = dyn_cast<GlobalValue>(C))
    GlobalIsNeeded(GV);
  else {
    // Loop over all of the operands of the constant, adding any globals they
    // use to the list of needed globals.
    for (User::op_iterator I = C->op_begin(), E = C->op_end(); I != E; ++I)
      MarkUsedGlobalsAsNeeded(cast<Constant>(*I));
  }
}

// RemoveUnusedGlobalValue - Loop over all of the uses of the specified
// GlobalValue, looking for the constant pointer ref that may be pointing to it.
// If found, check to see if the constant pointer ref is safe to destroy, and if
// so, nuke it.  This will reduce the reference count on the global value, which
// might make it deader.
//
bool GlobalDCE::RemoveUnusedGlobalValue(GlobalValue &GV) {
  if (GV.use_empty()) return false;
  GV.removeDeadConstantUsers();
  return GV.use_empty();
}
<commit_msg>Do not remove dead metadata for now.<commit_after>//===-- GlobalDCE.cpp - DCE unreachable internal functions ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This transform is designed to eliminate unreachable internal globals from the
// program.  It uses an aggressive algorithm, searching out globals that are
// known to be alive.  After it finds all of the globals which are needed, it
// deletes whatever is left over.  This allows it to delete recursive chunks of
// the program which are unreachable.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "globaldce"
#include "llvm/Transforms/IPO.h"
#include "llvm/Constants.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
#include <set>
using namespace llvm;

STATISTIC(NumAliases  , "Number of global aliases removed");
STATISTIC(NumFunctions, "Number of functions removed");
STATISTIC(NumVariables, "Number of global variables removed");

namespace {
  struct VISIBILITY_HIDDEN GlobalDCE : public ModulePass {
    static char ID; // Pass identification, replacement for typeid
    GlobalDCE() : ModulePass(&ID) {}

    // run - Do the GlobalDCE pass on the specified module, optionally updating
    // the specified callgraph to reflect the changes.
    //
    bool runOnModule(Module &M);

  private:
    std::set<GlobalValue*> AliveGlobals;

    /// GlobalIsNeeded - mark the specific global value as needed, and
    /// recursively mark anything that it uses as also needed.
    void GlobalIsNeeded(GlobalValue *GV);
    void MarkUsedGlobalsAsNeeded(Constant *C);

    bool RemoveUnusedGlobalValue(GlobalValue &GV);
  };
}

char GlobalDCE::ID = 0;
static RegisterPass<GlobalDCE> X("globaldce", "Dead Global Elimination");

ModulePass *llvm::createGlobalDCEPass() { return new GlobalDCE(); }

bool GlobalDCE::runOnModule(Module &M) {
  bool Changed = false;

  // Loop over the module, adding globals which are obviously necessary.
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
    Changed |= RemoveUnusedGlobalValue(*I);
    // Functions with external linkage are needed if they have a body
    if (!I->hasLocalLinkage() && !I->hasLinkOnceLinkage() &&
        !I->isDeclaration() && !I->hasAvailableExternallyLinkage())
      GlobalIsNeeded(I);
  }

  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
       I != E; ++I) {
    Changed |= RemoveUnusedGlobalValue(*I);
    // Externally visible & appending globals are needed, if they have an
    // initializer.
    if (!I->hasLocalLinkage() && !I->hasLinkOnceLinkage() &&
        !I->isDeclaration() && !I->hasAvailableExternallyLinkage())
      GlobalIsNeeded(I);
  }

  for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end();
       I != E; ++I) {
    Changed |= RemoveUnusedGlobalValue(*I);
    // Externally visible aliases are needed.
    if (!I->hasLocalLinkage() && !I->hasLinkOnceLinkage())
      GlobalIsNeeded(I);
  }

  // Now that all globals which are needed are in the AliveGlobals set, we loop
  // through the program, deleting those which are not alive.
  //

  // The first pass is to drop initializers of global variables which are dead.
  std::vector<GlobalVariable*> DeadGlobalVars;   // Keep track of dead globals
  for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
    if (!AliveGlobals.count(I)) {
      DeadGlobalVars.push_back(I);         // Keep track of dead globals
      I->setInitializer(0);
    }

  // The second pass drops the bodies of functions which are dead...
  std::vector<Function*> DeadFunctions;
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!AliveGlobals.count(I)) {
      DeadFunctions.push_back(I);         // Keep track of dead globals
      if (!I->isDeclaration())
        I->deleteBody();
    }

  // The third pass drops targets of aliases which are dead...
  std::vector<GlobalAlias*> DeadAliases;
  for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E;
       ++I)
    if (!AliveGlobals.count(I)) {
      DeadAliases.push_back(I);
      I->setAliasee(0);
    }

  if (!DeadFunctions.empty()) {
    // Now that all interferences have been dropped, delete the actual objects
    // themselves.
    for (unsigned i = 0, e = DeadFunctions.size(); i != e; ++i) {
      RemoveUnusedGlobalValue(*DeadFunctions[i]);
      M.getFunctionList().erase(DeadFunctions[i]);
    }
    NumFunctions += DeadFunctions.size();
    Changed = true;
  }

  if (!DeadGlobalVars.empty()) {
    for (unsigned i = 0, e = DeadGlobalVars.size(); i != e; ++i) {
      RemoveUnusedGlobalValue(*DeadGlobalVars[i]);
      M.getGlobalList().erase(DeadGlobalVars[i]);
    }
    NumVariables += DeadGlobalVars.size();
    Changed = true;
  }

  // Now delete any dead aliases.
  if (!DeadAliases.empty()) {
    for (unsigned i = 0, e = DeadAliases.size(); i != e; ++i) {
      RemoveUnusedGlobalValue(*DeadAliases[i]);
      M.getAliasList().erase(DeadAliases[i]);
    }
    NumAliases += DeadAliases.size();
    Changed = true;
  }

  // Make sure that all memory is released
  AliveGlobals.clear();

  // Remove dead metadata.
  // FIXME - Enable this.
  // Changed |= M.getContext().RemoveDeadMetadata();
  return Changed;
}

/// GlobalIsNeeded - the specific global value as needed, and
/// recursively mark anything that it uses as also needed.
void GlobalDCE::GlobalIsNeeded(GlobalValue *G) {
  std::set<GlobalValue*>::iterator I = AliveGlobals.find(G);

  // If the global is already in the set, no need to reprocess it.
  if (I != AliveGlobals.end()) return;

  // Otherwise insert it now, so we do not infinitely recurse
  AliveGlobals.insert(I, G);

  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(G)) {
    // If this is a global variable, we must make sure to add any global values
    // referenced by the initializer to the alive set.
    if (GV->hasInitializer())
      MarkUsedGlobalsAsNeeded(GV->getInitializer());
  } else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(G)) {
    // The target of a global alias is needed.
    MarkUsedGlobalsAsNeeded(GA->getAliasee());
  } else {
    // Otherwise this must be a function object.  We have to scan the body of
    // the function looking for constants and global values which are used as
    // operands.  Any operands of these types must be processed to ensure that
    // any globals used will be marked as needed.
    Function *F = cast<Function>(G);
    // For all basic blocks...
    for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
      // For all instructions...
      for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
        // For all operands...
        for (User::op_iterator U = I->op_begin(), E = I->op_end(); U != E; ++U)
          if (GlobalValue *GV = dyn_cast<GlobalValue>(*U))
            GlobalIsNeeded(GV);
          else if (Constant *C = dyn_cast<Constant>(*U))
            MarkUsedGlobalsAsNeeded(C);
  }
}

void GlobalDCE::MarkUsedGlobalsAsNeeded(Constant *C) {
  if (GlobalValue *GV = dyn_cast<GlobalValue>(C))
    GlobalIsNeeded(GV);
  else {
    // Loop over all of the operands of the constant, adding any globals they
    // use to the list of needed globals.
    for (User::op_iterator I = C->op_begin(), E = C->op_end(); I != E; ++I)
      MarkUsedGlobalsAsNeeded(cast<Constant>(*I));
  }
}

// RemoveUnusedGlobalValue - Loop over all of the uses of the specified
// GlobalValue, looking for the constant pointer ref that may be pointing to it.
// If found, check to see if the constant pointer ref is safe to destroy, and if
// so, nuke it.  This will reduce the reference count on the global value, which
// might make it deader.
//
bool GlobalDCE::RemoveUnusedGlobalValue(GlobalValue &GV) {
  if (GV.use_empty()) return false;
  GV.removeDeadConstantUsers();
  return GV.use_empty();
}
<|endoftext|>


<commit_before>#include <stan/io/mcmc_writer.hpp>
#include <test/test-models/no-main/io_example.cpp>

#include <vector>
#include <boost/random/additive_combine.hpp>

#include <stan/mcmc/sample.hpp>
#include <stan/mcmc/hmc/nuts/diag_e_nuts.hpp>

#include <sstream>
#include <string>

#include <gtest/gtest.h>

TEST(StanIoMcmcWriter, write_sample_names) {

  // Model
  std::fstream data_stream("", std::fstream::in);
  stan::io::dump data_var_context(data_stream);
  data_stream.close();

  io_example_model_namespace::io_example_model model(data_var_context, &std::cout);

  // Sample
  Eigen::VectorXd real(2);
  real(0) = 1.43;
  real(1) = 2.71;

  double log_prob = 3.14;
  double accept_stat = 0.84;

  stan::mcmc::sample sample(real, log_prob, accept_stat);

  // Sampler
  typedef boost::ecuyer1988 rng_t;
  rng_t base_rng(0);

  stan::mcmc::adapt_diag_e_nuts<io_example_model_namespace::io_example_model, rng_t> sampler(model, base_rng, 0);
  sampler.seed(real);

  // Writer
  std::stringstream sample_stream;
  std::stringstream diagnostic_stream;

  stan::common::recorder::csv sample_recorder(&sample_stream, "# ");
  stan::common::recorder::csv diagnostic_recorder(&diagnostic_stream, "# ");

  stan::io::mcmc_writer<io_example_model_namespace::io_example_model,
                        stan::common::recorder::csv,
                        stan::common::recorder::csv>
    writer(sample_recorder, diagnostic_recorder);

  writer.write_sample_names(sample, &sampler, model);

  std::string line;
  std::getline(sample_stream, line);

  EXPECT_EQ("lp__,accept_stat__,stepsize__,treedepth__,n_leapfrog__,n_divergent__,mu1,mu2", line);

}

TEST(StanIoMcmcWriter, write_sample_params) {

  // Model
  std::fstream data_stream("", std::fstream::in);
  stan::io::dump data_var_context(data_stream);
  data_stream.close();

  io_example_model_namespace::io_example_model model(data_var_context, &std::cout);

  // Sample
  Eigen::VectorXd real(2);
  real(0) = 1.43;
  real(1) = 2.71;

  double log_prob = 3.14;
  double accept_stat = 0.84;

  stan::mcmc::sample sample(real, log_prob, accept_stat);

  // Sampler
  typedef boost::ecuyer1988 rng_t;
  rng_t base_rng(0);

  stan::mcmc::adapt_diag_e_nuts<io_example_model_namespace::io_example_model, rng_t> sampler(model, base_rng, 0);
  sampler.seed(real);

  // Writer
  std::stringstream sample_stream;
  std::stringstream diagnostic_stream;

  stan::common::recorder::csv sample_recorder(&sample_stream, "# ");
  stan::common::recorder::csv diagnostic_recorder(&diagnostic_stream, "# ");

  stan::io::mcmc_writer<io_example_model_namespace::io_example_model,
                        stan::common::recorder::csv,
                        stan::common::recorder::csv> writer(sample_recorder, diagnostic_recorder);

  writer.write_sample_params<rng_t>(base_rng, sample, sampler, model);

  std::string line;
  std::getline(sample_stream, line);

  std::stringstream expected_stream;
  expected_stream << log_prob << ",";
  expected_stream << accept_stat << ",";
  expected_stream << sampler.get_current_stepsize() << ",";
  expected_stream << 0 << ",";
  expected_stream << 0 << ",";
  expected_stream << 0 << ",";
  expected_stream << real(0) << ",";
  expected_stream << real(1);

  std::string expected_line;
  std::getline(expected_stream, expected_line);

  EXPECT_EQ(expected_line, line);

}

TEST(StanIoMcmcWriter, write_adapt_finish) {

  // Model
  std::fstream data_stream("", std::fstream::in);
  stan::io::dump data_var_context(data_stream);
  data_stream.close();

  io_example_model_namespace::io_example_model model(data_var_context, &std::cout);

  // Sample
  Eigen::VectorXd real(2);
  real(0) = 1.43;
  real(1) = 2.71;

  double log_prob = 3.14;
  double accept_stat = 0.84;

  stan::mcmc::sample sample(real, log_prob, accept_stat);

  // Sampler
  typedef boost::ecuyer1988 rng_t;
  rng_t base_rng(0);

  stan::mcmc::adapt_diag_e_nuts<io_example_model_namespace::io_example_model, rng_t> sampler(model, base_rng, 0);
  sampler.seed(real);

  // Writer
  std::stringstream sample_stream;
  std::stringstream diagnostic_stream;

  stan::common::recorder::csv sample_recorder(&sample_stream, "# ");
  stan::common::recorder::csv diagnostic_recorder(&diagnostic_stream, "# ");

  stan::io::mcmc_writer<io_example_model_namespace::io_example_model,
                        stan::common::recorder::csv,
                        stan::common::recorder::csv>
    writer(sample_recorder, diagnostic_recorder);

  writer.write_adapt_finish(&sampler);

  std::stringstream expected_stream;
  expected_stream << "# Adaptation terminated" << std::endl;
  expected_stream << "# Step size = " << sampler.get_current_stepsize() << std::endl;
  expected_stream << "# Diagonal elements of inverse mass matrix:" << std::endl;
  expected_stream << "# " << sampler.z().mInv(0) << ", " << sampler.z().mInv(1) << std::endl;

  std::string line;
  std::string expected_line;

  // Line 1
  std::getline(expected_stream, expected_line);

  std::getline(sample_stream, line);
  EXPECT_EQ(expected_line, line);

  std::getline(diagnostic_stream, line);
  EXPECT_EQ(expected_line, line);

  // Line 2
  std::getline(expected_stream, expected_line);

  std::getline(sample_stream, line);
  EXPECT_EQ(expected_line, line);

  std::getline(diagnostic_stream, line);
  EXPECT_EQ(expected_line, line);

  // Line 3
  std::getline(expected_stream, expected_line);

  std::getline(sample_stream, line);
  EXPECT_EQ(expected_line, line);

  std::getline(diagnostic_stream, line);
  EXPECT_EQ(expected_line, line);

  // Line 4
  std::getline(expected_stream, expected_line);

  std::getline(sample_stream, line);
  EXPECT_EQ(expected_line, line);

  std::getline(diagnostic_stream, line);
  EXPECT_EQ(expected_line, line);

}

TEST(StanIoMcmcWriter, write_diagnostic_names) {

  // Model
  std::fstream data_stream("", std::fstream::in);
  stan::io::dump data_var_context(data_stream);
  data_stream.close();

  io_example_model_namespace::io_example_model model(data_var_context, &std::cout);

  // Sample
  Eigen::VectorXd real(2);
  real(0) = 1.43;
  real(1) = 2.71;

  double log_prob = 3.14;
  double accept_stat = 0.84;

  stan::mcmc::sample sample(real, log_prob, accept_stat);

  // Sampler
  typedef boost::ecuyer1988 rng_t;
  rng_t base_rng(0);

  stan::mcmc::adapt_diag_e_nuts<io_example_model_namespace::io_example_model, rng_t> sampler(model, base_rng, 0);
  sampler.seed(real);

  // Writer
  std::stringstream sample_stream;
  std::stringstream diagnostic_stream;

  stan::common::recorder::csv sample_recorder(&sample_stream, "# ");
  stan::common::recorder::csv diagnostic_recorder(&diagnostic_stream, "# ");

  stan::io::mcmc_writer<io_example_model_namespace::io_example_model,
                        stan::common::recorder::csv,
                        stan::common::recorder::csv>
    writer(sample_recorder, diagnostic_recorder);

  writer.write_diagnostic_names(sample, &sampler, model);

  std::string line;
  std::getline(diagnostic_stream, line);

  // FIXME: make this work, too
  EXPECT_EQ("lp__,accept_stat__,stepsize__,treedepth__,n_leapfrog__,n_divergent__,mu1,mu2,p_mu1,p_mu2,g_mu1,g_mu2", line);

}

TEST(StanIoMcmcWriter, write_diagnostic_params) {

  // Model
  std::fstream data_stream("", std::fstream::in);
  stan::io::dump data_var_context(data_stream);
  data_stream.close();

  io_example_model_namespace::io_example_model model(data_var_context, &std::cout);

  // Sample
  Eigen::VectorXd real(2);
  real(0) = 1.43;
  real(1) = 2.71;

  double log_prob = 3.14;
  double accept_stat = 0.84;

  stan::mcmc::sample sample(real, log_prob, accept_stat);

  // Sampler
  typedef boost::ecuyer1988 rng_t;
  rng_t base_rng(0);

  stan::mcmc::adapt_diag_e_nuts<io_example_model_namespace::io_example_model, rng_t> sampler(model, base_rng, 0);
  sampler.seed(real);
  sampler.z().p(0) = 0;
  sampler.z().p(1) = 0;
  sampler.z().g(0) = 0;
  sampler.z().g(1) = 0;

  // Writer
  std::stringstream sample_stream;
  std::stringstream diagnostic_stream;

  stan::common::recorder::csv sample_recorder(&sample_stream, "# ");
  stan::common::recorder::csv diagnostic_recorder(&diagnostic_stream, "# ");

  stan::io::mcmc_writer<io_example_model_namespace::io_example_model,
                        stan::common::recorder::csv,
                        stan::common::recorder::csv>
    writer(sample_recorder, diagnostic_recorder);

  writer.write_diagnostic_params(sample, &sampler);

  std::string line;
  std::getline(diagnostic_stream, line);

  std::stringstream expected_stream;
  expected_stream << log_prob << ",";
  expected_stream << accept_stat << ",";
  expected_stream << sampler.get_current_stepsize() << ",";
  expected_stream << 0 << ",";
  expected_stream << 0 << ",";
  expected_stream << 0 << ",";
  expected_stream << real(0) << ",";
  expected_stream << real(1) << ",";
  expected_stream << 0 << ",";
  expected_stream << 0 << ",";
  expected_stream << 0 << ",";
  expected_stream << 0;

  std::string expected_line;
  std::getline(expected_stream, expected_line);

  EXPECT_EQ(expected_line, line);

}

TEST(StanIoMcmcWriter, write_timing) {

  // Model
  std::fstream data_stream("", std::fstream::in);
  stan::io::dump data_var_context(data_stream);
  data_stream.close();

  io_example_model_namespace::io_example_model model(data_var_context, &std::cout);

  // Sample
  Eigen::VectorXd real(2);
  real(0) = 1.43;
  real(1) = 2.71;

  double log_prob = 3.14;
  double accept_stat = 0.84;

  stan::mcmc::sample sample(real, log_prob, accept_stat);

  // Sampler
  typedef boost::ecuyer1988 rng_t;
  rng_t base_rng(0);

  stan::mcmc::adapt_diag_e_nuts<io_example_model_namespace::io_example_model, rng_t> sampler(model, base_rng, 0);
  sampler.seed(real);

  // Writer
  std::stringstream sample_stream;
  std::stringstream diagnostic_stream;

  stan::common::recorder::csv sample_recorder(&sample_stream, "# ");
  stan::common::recorder::csv diagnostic_recorder(&diagnostic_stream, "# ");

  stan::io::mcmc_writer<io_example_model_namespace::io_example_model,
                        stan::common::recorder::csv,
                        stan::common::recorder::csv>
    writer(sample_recorder, diagnostic_recorder);

  double warm = 0.193933;
  double sampling = 0.483830;

  writer.write_timing(warm, sampling, sample_recorder);

  std::stringstream expected_stream;
  expected_stream << std::endl;
  expected_stream << "#  Elapsed Time: " << warm << " seconds (Warm-up)" << std::endl;
  expected_stream << "#                " << sampling << " seconds (Sampling)" << std::endl;
  expected_stream << "#                " << warm + sampling << " seconds (Total)" << std::endl;
  expected_stream << std::endl;

  std::string line;
  std::string expected_line;

  // Line 1
  std::getline(expected_stream, expected_line);

  std::getline(sample_stream, line);
  EXPECT_EQ(expected_line, line);

  std::getline(diagnostic_stream, line);
  EXPECT_EQ(expected_line, line);

  // Line 2
  std::getline(expected_stream, expected_line);

  std::getline(sample_stream, line);
  EXPECT_EQ(expected_line, line);

  std::getline(diagnostic_stream, line);
  EXPECT_EQ(expected_line, line);

  // Line 3
  std::getline(expected_stream, expected_line);

  std::getline(sample_stream, line);
  EXPECT_EQ(expected_line, line);

  std::getline(diagnostic_stream, line);
  EXPECT_EQ(expected_line, line);

  // Line 4
  std::getline(expected_stream, expected_line);

  std::getline(sample_stream, line);
  EXPECT_EQ(expected_line, line);

  std::getline(diagnostic_stream, line);
  EXPECT_EQ(expected_line, line);

  // Line 5
  std::getline(expected_stream, expected_line);

  std::getline(sample_stream, line);
  EXPECT_EQ(expected_line, line);

  std::getline(diagnostic_stream, line);
  EXPECT_EQ(expected_line, line);

}
<commit_msg>fixed src/test/unit<commit_after>#include <stan/io/mcmc_writer.hpp>
#include <test/test-models/no-main/io_example.cpp>

#include <vector>
#include <boost/random/additive_combine.hpp>

#include <stan/mcmc/sample.hpp>
#include <stan/mcmc/hmc/nuts/diag_e_nuts.hpp>

#include <sstream>
#include <string>

#include <gtest/gtest.h>

TEST(StanIoMcmcWriter, write_sample_names) {

  // Model
  std::fstream data_stream("", std::fstream::in);
  stan::io::dump data_var_context(data_stream);
  data_stream.close();

  io_example_model_namespace::io_example_model model(data_var_context, &std::cout);

  // Sample
  Eigen::VectorXd real(2);
  real(0) = 1.43;
  real(1) = 2.71;

  double log_prob = 3.14;
  double accept_stat = 0.84;

  stan::mcmc::sample sample(real, log_prob, accept_stat);

  // Sampler
  typedef boost::ecuyer1988 rng_t;
  rng_t base_rng(0);

  stan::mcmc::adapt_diag_e_nuts<io_example_model_namespace::io_example_model, rng_t> sampler(model, base_rng, 0);
  sampler.seed(real);

  // Writer
  std::stringstream sample_stream;
  std::stringstream diagnostic_stream;
  std::stringstream message_stream;

  stan::common::recorder::csv sample_recorder(&sample_stream, "# ");
  stan::common::recorder::csv diagnostic_recorder(&diagnostic_stream, "# ");
  stan::common::recorder::messages message_recorder(&message_stream, "# ");

  stan::io::mcmc_writer<io_example_model_namespace::io_example_model,
                        stan::common::recorder::csv,
                        stan::common::recorder::csv,
                        stan::common::recorder::messages>
    writer(sample_recorder, diagnostic_recorder, message_recorder);

  writer.write_sample_names(sample, &sampler, model);

  std::string line;
  std::getline(sample_stream, line);

  EXPECT_EQ("lp__,accept_stat__,stepsize__,treedepth__,n_leapfrog__,n_divergent__,mu1,mu2", line);
  EXPECT_EQ("", message_stream.str());
}

TEST(StanIoMcmcWriter, write_sample_params) {

  // Model
  std::fstream data_stream("", std::fstream::in);
  stan::io::dump data_var_context(data_stream);
  data_stream.close();

  io_example_model_namespace::io_example_model model(data_var_context, &std::cout);

  // Sample
  Eigen::VectorXd real(2);
  real(0) = 1.43;
  real(1) = 2.71;

  double log_prob = 3.14;
  double accept_stat = 0.84;

  stan::mcmc::sample sample(real, log_prob, accept_stat);

  // Sampler
  typedef boost::ecuyer1988 rng_t;
  rng_t base_rng(0);

  stan::mcmc::adapt_diag_e_nuts<io_example_model_namespace::io_example_model, rng_t> sampler(model, base_rng, 0);
  sampler.seed(real);

  // Writer
  std::stringstream sample_stream;
  std::stringstream diagnostic_stream;
  std::stringstream message_stream;

  stan::common::recorder::csv sample_recorder(&sample_stream, "# ");
  stan::common::recorder::csv diagnostic_recorder(&diagnostic_stream, "# ");
  stan::common::recorder::messages message_recorder(&message_stream, "# ");

  stan::io::mcmc_writer<io_example_model_namespace::io_example_model,
                        stan::common::recorder::csv,
                        stan::common::recorder::csv,
                        stan::common::recorder::messages>
    writer(sample_recorder, diagnostic_recorder, message_recorder);

  writer.write_sample_params<rng_t>(base_rng, sample, sampler, model);

  std::string line;
  std::getline(sample_stream, line);

  std::stringstream expected_stream;
  expected_stream << log_prob << ",";
  expected_stream << accept_stat << ",";
  expected_stream << sampler.get_current_stepsize() << ",";
  expected_stream << 0 << ",";
  expected_stream << 0 << ",";
  expected_stream << 0 << ",";
  expected_stream << real(0) << ",";
  expected_stream << real(1);

  std::string expected_line;
  std::getline(expected_stream, expected_line);

  EXPECT_EQ(expected_line, line);
  EXPECT_EQ("", message_stream.str());
}

TEST(StanIoMcmcWriter, write_adapt_finish) {

  // Model
  std::fstream data_stream("", std::fstream::in);
  stan::io::dump data_var_context(data_stream);
  data_stream.close();

  io_example_model_namespace::io_example_model model(data_var_context, &std::cout);

  // Sample
  Eigen::VectorXd real(2);
  real(0) = 1.43;
  real(1) = 2.71;

  double log_prob = 3.14;
  double accept_stat = 0.84;

  stan::mcmc::sample sample(real, log_prob, accept_stat);

  // Sampler
  typedef boost::ecuyer1988 rng_t;
  rng_t base_rng(0);

  stan::mcmc::adapt_diag_e_nuts<io_example_model_namespace::io_example_model, rng_t> sampler(model, base_rng, 0);
  sampler.seed(real);

  // Writer
  std::stringstream sample_stream;
  std::stringstream diagnostic_stream;
  std::stringstream message_stream;

  stan::common::recorder::csv sample_recorder(&sample_stream, "# ");
  stan::common::recorder::csv diagnostic_recorder(&diagnostic_stream, "# ");
  stan::common::recorder::messages message_recorder(&message_stream, "# ");

  stan::io::mcmc_writer<io_example_model_namespace::io_example_model,
                        stan::common::recorder::csv,
                        stan::common::recorder::csv,
                        stan::common::recorder::messages>
    writer(sample_recorder, diagnostic_recorder, message_recorder);

  writer.write_adapt_finish(&sampler);

  std::stringstream expected_stream;
  expected_stream << "# Adaptation terminated" << std::endl;
  expected_stream << "# Step size = " << sampler.get_current_stepsize() << std::endl;
  expected_stream << "# Diagonal elements of inverse mass matrix:" << std::endl;
  expected_stream << "# " << sampler.z().mInv(0) << ", " << sampler.z().mInv(1) << std::endl;

  std::string line;
  std::string expected_line;

  // Line 1
  std::getline(expected_stream, expected_line);

  std::getline(sample_stream, line);
  EXPECT_EQ(expected_line, line);

  std::getline(diagnostic_stream, line);
  EXPECT_EQ(expected_line, line);

  // Line 2
  std::getline(expected_stream, expected_line);

  std::getline(sample_stream, line);
  EXPECT_EQ(expected_line, line);

  std::getline(diagnostic_stream, line);
  EXPECT_EQ(expected_line, line);

  // Line 3
  std::getline(expected_stream, expected_line);

  std::getline(sample_stream, line);
  EXPECT_EQ(expected_line, line);

  std::getline(diagnostic_stream, line);
  EXPECT_EQ(expected_line, line);

  // Line 4
  std::getline(expected_stream, expected_line);

  std::getline(sample_stream, line);
  EXPECT_EQ(expected_line, line);

  std::getline(diagnostic_stream, line);
  EXPECT_EQ(expected_line, line);

  EXPECT_EQ("", message_stream.str());
}

TEST(StanIoMcmcWriter, write_diagnostic_names) {

  // Model
  std::fstream data_stream("", std::fstream::in);
  stan::io::dump data_var_context(data_stream);
  data_stream.close();

  io_example_model_namespace::io_example_model model(data_var_context, &std::cout);

  // Sample
  Eigen::VectorXd real(2);
  real(0) = 1.43;
  real(1) = 2.71;

  double log_prob = 3.14;
  double accept_stat = 0.84;

  stan::mcmc::sample sample(real, log_prob, accept_stat);

  // Sampler
  typedef boost::ecuyer1988 rng_t;
  rng_t base_rng(0);

  stan::mcmc::adapt_diag_e_nuts<io_example_model_namespace::io_example_model, rng_t> sampler(model, base_rng, 0);
  sampler.seed(real);

  // Writer
  std::stringstream sample_stream;
  std::stringstream diagnostic_stream;
  std::stringstream message_stream;

  stan::common::recorder::csv sample_recorder(&sample_stream, "# ");
  stan::common::recorder::csv diagnostic_recorder(&diagnostic_stream, "# ");
  stan::common::recorder::messages message_recorder(&message_stream, "# ");

  stan::io::mcmc_writer<io_example_model_namespace::io_example_model,
                        stan::common::recorder::csv,
                        stan::common::recorder::csv,
                        stan::common::recorder::messages>
    writer(sample_recorder, diagnostic_recorder, message_recorder);

  writer.write_diagnostic_names(sample, &sampler, model);

  std::string line;
  std::getline(diagnostic_stream, line);

  // FIXME: make this work, too
  EXPECT_EQ("lp__,accept_stat__,stepsize__,treedepth__,n_leapfrog__,n_divergent__,mu1,mu2,p_mu1,p_mu2,g_mu1,g_mu2", line);

  EXPECT_EQ("", message_stream.str());
}

TEST(StanIoMcmcWriter, write_diagnostic_params) {

  // Model
  std::fstream data_stream("", std::fstream::in);
  stan::io::dump data_var_context(data_stream);
  data_stream.close();

  io_example_model_namespace::io_example_model model(data_var_context, &std::cout);

  // Sample
  Eigen::VectorXd real(2);
  real(0) = 1.43;
  real(1) = 2.71;

  double log_prob = 3.14;
  double accept_stat = 0.84;

  stan::mcmc::sample sample(real, log_prob, accept_stat);

  // Sampler
  typedef boost::ecuyer1988 rng_t;
  rng_t base_rng(0);

  stan::mcmc::adapt_diag_e_nuts<io_example_model_namespace::io_example_model, rng_t> sampler(model, base_rng, 0);
  sampler.seed(real);
  sampler.z().p(0) = 0;
  sampler.z().p(1) = 0;
  sampler.z().g(0) = 0;
  sampler.z().g(1) = 0;

  // Writer
  std::stringstream sample_stream;
  std::stringstream diagnostic_stream;
  std::stringstream message_stream;

  stan::common::recorder::csv sample_recorder(&sample_stream, "# ");
  stan::common::recorder::csv diagnostic_recorder(&diagnostic_stream, "# ");
  stan::common::recorder::messages message_recorder(&message_stream, "# ");

  stan::io::mcmc_writer<io_example_model_namespace::io_example_model,
                        stan::common::recorder::csv,
                        stan::common::recorder::csv,
                        stan::common::recorder::messages>
    writer(sample_recorder, diagnostic_recorder, message_recorder);

  writer.write_diagnostic_params(sample, &sampler);

  std::string line;
  std::getline(diagnostic_stream, line);

  std::stringstream expected_stream;
  expected_stream << log_prob << ",";
  expected_stream << accept_stat << ",";
  expected_stream << sampler.get_current_stepsize() << ",";
  expected_stream << 0 << ",";
  expected_stream << 0 << ",";
  expected_stream << 0 << ",";
  expected_stream << real(0) << ",";
  expected_stream << real(1) << ",";
  expected_stream << 0 << ",";
  expected_stream << 0 << ",";
  expected_stream << 0 << ",";
  expected_stream << 0;

  std::string expected_line;
  std::getline(expected_stream, expected_line);

  EXPECT_EQ(expected_line, line);

}

TEST(StanIoMcmcWriter, write_timing) {

  // Model
  std::fstream data_stream("", std::fstream::in);
  stan::io::dump data_var_context(data_stream);
  data_stream.close();

  io_example_model_namespace::io_example_model model(data_var_context, &std::cout);

  // Sample
  Eigen::VectorXd real(2);
  real(0) = 1.43;
  real(1) = 2.71;

  double log_prob = 3.14;
  double accept_stat = 0.84;

  stan::mcmc::sample sample(real, log_prob, accept_stat);

  // Sampler
  typedef boost::ecuyer1988 rng_t;
  rng_t base_rng(0);

  stan::mcmc::adapt_diag_e_nuts<io_example_model_namespace::io_example_model, rng_t> sampler(model, base_rng, 0);
  sampler.seed(real);

  // Writer
  std::stringstream sample_stream;
  std::stringstream diagnostic_stream;
  std::stringstream message_stream;

  stan::common::recorder::csv sample_recorder(&sample_stream, "# ");
  stan::common::recorder::csv diagnostic_recorder(&diagnostic_stream, "# ");
  stan::common::recorder::messages message_recorder(&message_stream, "# ");

  stan::io::mcmc_writer<io_example_model_namespace::io_example_model,
                        stan::common::recorder::csv,
                        stan::common::recorder::csv,
                        stan::common::recorder::messages>
    writer(sample_recorder, diagnostic_recorder, message_recorder);

  double warm = 0.193933;
  double sampling = 0.483830;

  writer.write_timing(warm, sampling, sample_recorder);

  std::stringstream expected_stream;
  expected_stream << std::endl;
  expected_stream << "#  Elapsed Time: " << warm << " seconds (Warm-up)" << std::endl;
  expected_stream << "#                " << sampling << " seconds (Sampling)" << std::endl;
  expected_stream << "#                " << warm + sampling << " seconds (Total)" << std::endl;
  expected_stream << std::endl;

  std::string line;
  std::string expected_line;

  // Line 1
  std::getline(expected_stream, expected_line);

  std::getline(sample_stream, line);
  EXPECT_EQ(expected_line, line);

  std::getline(diagnostic_stream, line);
  EXPECT_EQ(expected_line, line);

  // Line 2
  std::getline(expected_stream, expected_line);

  std::getline(sample_stream, line);
  EXPECT_EQ(expected_line, line);

  std::getline(diagnostic_stream, line);
  EXPECT_EQ(expected_line, line);

  // Line 3
  std::getline(expected_stream, expected_line);

  std::getline(sample_stream, line);
  EXPECT_EQ(expected_line, line);

  std::getline(diagnostic_stream, line);
  EXPECT_EQ(expected_line, line);

  // Line 4
  std::getline(expected_stream, expected_line);

  std::getline(sample_stream, line);
  EXPECT_EQ(expected_line, line);

  std::getline(diagnostic_stream, line);
  EXPECT_EQ(expected_line, line);

  // Line 5
  std::getline(expected_stream, expected_line);

  std::getline(sample_stream, line);
  EXPECT_EQ(expected_line, line);

  std::getline(diagnostic_stream, line);
  EXPECT_EQ(expected_line, line);

  EXPECT_EQ("", message_stream.str());
}
<|endoftext|>


<commit_before>#include <pwn/engine/loop.h>
#include <pwn/engine/game.h>
#include <pwn/engine/startup.h>

#include <pwn/render/world3.h>
#include <pwn/render/world3widget.h>
#include <pwn/math/operations.h>
#include <pwn/render/actordef.h>
#include <pwn/render/actor.h>
#include <pwn/mesh/mesh.h>
#include <pwn/mesh/builder.h>
#include <pwn/mesh/predefinedmaterials.h>
#include <pwn/engine/democamera.h>
#include <pwn/engine/vfstexturepool2.h>
#include <pwn/io/io.h>
#include <pwn/render/worldwithcameraboundobject3.h>
#include <pwn/render/fse/Pipeline.h>
#include <pwn/render/light.h>
#include <pwn/engine/democontrols.h>

#include <pwn/render/shaderpool.h>

using namespace pwn;
using namespace pwn::engine;
using namespace pwn::render;
using namespace pwn::math;
using namespace pwn::mesh;

boost::shared_ptr<ActorDef> CreateCube(real size, const string& texture, TexturePool2* tpool, real alpha, bool out)
{
	const real halfsize = size/2;

	Builder b = CreateBox(materials::White(), halfsize*2, halfsize*2, halfsize*2, out);;
	b.materials[0].setTexture_Diffuse(texture);
	b.materials[0].diffuse.alpha(alpha);
	Move(&b, vec3(-halfsize, -halfsize, -halfsize));
	return Compile(b.asMesh(), tpool);
}

boost::shared_ptr<ActorDef> LoadMesh(const string& file, TexturePool2* tpool)
{
	Mesh mesh;
	pwn::io::Read(&mesh, file);
	return Compile(mesh, tpool);
}

class EasyLoop : public Loop
{
private:
	boost::shared_ptr<Actor> object;
	real pos;

	Camera cam;
	VfsTexturePool2 tpool;
	fse::PipelinePtr pipe;
	pwn::render::ShaderPool tempShaderPool;

	bool followcam;
	boost::shared_ptr<World3Widget > wid;
	DemoControls ctrl;
public:

	EasyLoop(Game* game)
		: Loop(game)
		, pos(0)
		, cam(point3(4,4,4), qIdentity(), 45, 0.1f, 1000)
		, followcam(false)
	{
		World3::Ptr world( new WorldWithCameraBoundObject3(Actor::Create(Origo3(), qIdentity(), CreateCube(10, "_stars-texture.jpg", &tpool, 1, false) ),
			World3::Create()) );
		world->light_setAmbient( math::Rgba(1.0f) );

		object = Actor::Create(point3(0,0,15), qIdentity(), CreateCube(1, "crate01a.jpg", &tpool, 1, true));
		object->debug = true;
		world->actor_add(object);

		wid.reset(new World3Widget( Dock::Fill(), world ) );
		cam.pipeline = fse::Pipeline::Create("fse/normal.xml", &tempShaderPool);
		display.widget_add( wid );
	}

	void onKey(Key::Code key, bool isDown)
	{
		if( key == Key::Escape && isDown )
		{
			stop();
		}
		if( key == Key::Return && isDown )
		{
			followcam = !followcam;
		}
		else
		{
			ctrl.onKey(key, isDown);
		}
	}

	void onUpdate(real delta)
	{
		ctrl.update(&object->position, &object->rotation, delta, 10.0f, 10.0f);
		if( followcam )
		{
			cam.lookAt(object->position);
		}
	}

	void onRender()
	{
		wid->updateCamera(cam);
		defaultRender();
	}

	void onMouse(const math::vec2 movement)
	{
		ctrl.onMouse(movement);
	}
};

int main(int, char** argv)
{
	{
		Game game;
		InstallDefaultSystems(&game,
			Startup(argv[0], "entsoft", "pwn-demo-basic-camera", "pwn demo: basic camera")
			);
		EasyLoop(&game).loop();
	}
}
<commit_msg>added lookat for object, but something still isnt right<commit_after>#include <pwn/engine/loop.h>
#include <pwn/engine/game.h>
#include <pwn/engine/startup.h>

#include <pwn/render/world3.h>
#include <pwn/render/world3widget.h>
#include <pwn/math/operations.h>
#include <pwn/render/actordef.h>
#include <pwn/render/actor.h>
#include <pwn/mesh/mesh.h>
#include <pwn/mesh/builder.h>
#include <pwn/mesh/predefinedmaterials.h>
#include <pwn/engine/democamera.h>
#include <pwn/engine/vfstexturepool2.h>
#include <pwn/io/io.h>
#include <pwn/render/worldwithcameraboundobject3.h>
#include <pwn/render/fse/Pipeline.h>
#include <pwn/render/light.h>
#include <pwn/engine/demomovement.h>

#include <pwn/render/shaderpool.h>

using namespace pwn;
using namespace pwn::engine;
using namespace pwn::render;
using namespace pwn::math;
using namespace pwn::mesh;

boost::shared_ptr<ActorDef> CreateCube(real size, const string& texture, TexturePool2* tpool, real alpha, bool out)
{
	const real halfsize = size/2;

	Builder b = CreateBox(materials::White(), halfsize*2, halfsize*2, halfsize*2, out);;
	b.materials[0].setTexture_Diffuse(texture);
	b.materials[0].diffuse.alpha(alpha);
	Move(&b, vec3(-halfsize, -halfsize, -halfsize));
	return Compile(b.asMesh(), tpool);
}

boost::shared_ptr<ActorDef> LoadMesh(const string& file, TexturePool2* tpool)
{
	Mesh mesh;
	pwn::io::Read(&mesh, file);
	return Compile(mesh, tpool);
}

class EasyLoop : public Loop
{
private:
	boost::shared_ptr<Actor> object;
	real pos;

	Camera cam;
	VfsTexturePool2 tpool;
	fse::PipelinePtr pipe;
	pwn::render::ShaderPool tempShaderPool;

	boost::shared_ptr<World3Widget > wid;
	DemoMovement ctrl;
public:

	EasyLoop(Game* game)
		: Loop(game)
		, pos(0)
		, cam(point3(0,0,0), qIdentity(), 45, 0.1f, 1000)
	{
		World3::Ptr world( new WorldWithCameraBoundObject3(Actor::Create(Origo3(), qIdentity(), CreateCube(10, "_stars-texture.jpg", &tpool, 1, false) ),
			World3::Create()) );
		world->light_setAmbient( math::Rgba(1.0f) );

		object = Actor::Create(point3(0,0,15), qIdentity(), CreateCube(1, "crate01a.jpg", &tpool, 1, true));
		object->debug = true;
		world->actor_add(object);

		wid.reset(new World3Widget( Dock::Fill(), world ) );
		cam.pipeline = fse::Pipeline::Create("fse/normal.xml", &tempShaderPool);
		display.widget_add( wid );

		ctrl.localUp = true;
	}

	void onKey(Key::Code key, bool isDown)
	{
		if( key == Key::Escape && isDown )
		{
			stop();
		}
		else
		{
			ctrl.onKey(key, isDown);
		}
	}

	void onUpdate(real delta)
	{
		ctrl.update(&object->position, object->rotation, delta, 10.0f);
		object->rotation = qLookAt(object->position.vec, cam.position.vec, Up());
		cam.lookAt(object->position);
	}

	void onRender()
	{
		wid->updateCamera(cam);
		defaultRender();
	}

	void onMouse(const math::vec2 movement)
	{
	}
};

int main(int, char** argv)
{
	{
		Game game;
		InstallDefaultSystems(&game,
			Startup(argv[0], "entsoft", "pwn-demo-basic-camera", "pwn demo: basic camera")
			);
		EasyLoop(&game).loop();
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 Plenluno All rights reserved.

#include "Libj/js_array.h"
#include "libj/detail/js_array.h"

namespace libj {

JsArray::Ptr JsArray::create() {
    return Ptr(new detail::JsArray<JsArray>());
}

JsArray::Ptr JsArray::create(ArrayList::CPtr list) {
    if (!list) return null();

    JsArray::Ptr ary(JsArray::create());
    ary->addAll(list);
    return ary;
}

}  // namespace libj
<commit_msg>fix typo<commit_after>// Copyright (c) 2012 Plenluno All rights reserved.

#include "libj/js_array.h"
#include "libj/detail/js_array.h"

namespace libj {

JsArray::Ptr JsArray::create() {
    return Ptr(new detail::JsArray<JsArray>());
}

JsArray::Ptr JsArray::create(ArrayList::CPtr list) {
    if (!list) return null();

    JsArray::Ptr ary(JsArray::create());
    ary->addAll(list);
    return ary;
}

}  // namespace libj
<|endoftext|>


<commit_before><commit_msg>remove log<commit_after><|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtTest/QtTest>

#include <QtCore/QCoreApplication>
#include <QtCore/QSocketNotifier>
#include <QtNetwork/QTcpServer>
#include <QtNetwork/QTcpSocket>
#include <private/qnativesocketengine_p.h>

class tst_QSocketNotifier : public QObject
{
    Q_OBJECT
public:
    tst_QSocketNotifier();
    ~tst_QSocketNotifier();

private slots:
    void unexpectedDisconnection();
    void mixingWithTimers();
};

tst_QSocketNotifier::tst_QSocketNotifier()
{ }

tst_QSocketNotifier::~tst_QSocketNotifier()
{
}

class UnexpectedDisconnectTester : public QObject
{
    Q_OBJECT
    int sequence;

public:
    QNativeSocketEngine *readEnd1, *readEnd2;

    UnexpectedDisconnectTester(QNativeSocketEngine *s1, QNativeSocketEngine *s2)
        : readEnd1(s1), readEnd2(s2), sequence(0)
    {
        QSocketNotifier *notifier1 =
            new QSocketNotifier(readEnd1->socketDescriptor(), QSocketNotifier::Read, this);
        connect(notifier1, SIGNAL(activated(int)), SLOT(handleActivated()));
        QSocketNotifier *notifier2 =
            new QSocketNotifier(readEnd2->socketDescriptor(), QSocketNotifier::Read, this);
        connect(notifier2, SIGNAL(activated(int)), SLOT(handleActivated()));
    }

    const int getSequence() {
        return sequence;
    }

    void incSequence() {
        ++sequence;
    }

public slots:
    void handleActivated()
    {
        char data1[1], data2[1];
        incSequence();
        if (getSequence() == 1) {
            // read from both ends
            (void) readEnd1->read(data1, sizeof(data1));
            (void) readEnd2->read(data2, sizeof(data2));
            emit finished();
        } else if (getSequence() == 2) {
            QCOMPARE(readEnd2->read(data2, sizeof(data2)), qint64(-2));
            QVERIFY(readEnd2->isValid());
        }
    }

signals:
    void finished();
};

void tst_QSocketNotifier::unexpectedDisconnection()
{
    /*
      Given two sockets and two QSocketNotifiers registered on each
      their socket. If both sockets receive data, and the first slot
      invoked by one of the socket notifiers empties both sockets, the
      other notifier will also emit activated(). This results in
      unexpected disconnection in QAbstractSocket.

      The use case is that somebody calls one of the
      waitFor... functions in a QSocketNotifier activated slot, and
      the waitFor... functions do local selects that can empty both
      stdin and stderr while waiting for fex bytes to be written.
    */

    QTcpServer server;
    QVERIFY(server.listen(QHostAddress::LocalHost, 0));

    QNativeSocketEngine readEnd1;
    readEnd1.initialize(QAbstractSocket::TcpSocket);
    bool b = readEnd1.connectToHost(server.serverAddress(), server.serverPort());
    QVERIFY(readEnd1.waitForWrite());
//    while (!b && readEnd1.state() != QAbstractSocket::ConnectedState)
//        b = readEnd1.connectToHost(server.serverAddress(), server.serverPort());
    QVERIFY(readEnd1.state() == QAbstractSocket::ConnectedState);
    QVERIFY(server.waitForNewConnection());
    QTcpSocket *writeEnd1 = server.nextPendingConnection();
    QVERIFY(writeEnd1 != 0);

    QNativeSocketEngine readEnd2;
    readEnd2.initialize(QAbstractSocket::TcpSocket);
    b = readEnd2.connectToHost(server.serverAddress(), server.serverPort());
    QVERIFY(readEnd2.waitForWrite());
//    while (!b)
//        b = readEnd2.connectToHost(server.serverAddress(), server.serverPort());
    QVERIFY(readEnd2.state() == QAbstractSocket::ConnectedState);
    QVERIFY(server.waitForNewConnection());
    QTcpSocket *writeEnd2 = server.nextPendingConnection();
    QVERIFY(writeEnd2 != 0);

    writeEnd1->write("1", 1);
    writeEnd2->write("2", 1);

    writeEnd1->waitForBytesWritten();
    writeEnd2->waitForBytesWritten();

    writeEnd1->flush();
    writeEnd2->flush();

    UnexpectedDisconnectTester tester(&readEnd1, &readEnd2);

    do {
        // we have to wait until sequence value changes
        // as any event can make us jump out processing
        QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
    }  while(tester.getSequence() <= 0);

    QVERIFY(readEnd1.state() == QAbstractSocket::ConnectedState);
    QVERIFY(readEnd2.state() == QAbstractSocket::ConnectedState);
#if defined(Q_OS_WIN)
    qWarning("### Windows returns 1 activation, Unix returns 2.");
    QCOMPARE(tester.getSequence(), 1);
#else
    QCOMPARE(tester.getSequence(), 2);
#endif

    readEnd1.close();
    readEnd2.close();
    writeEnd1->close();
    writeEnd2->close();
    server.close();
}

class MixingWithTimersHelper : public QObject
{
    Q_OBJECT

public:
    MixingWithTimersHelper(QTimer *timer, QTcpServer *server);

    bool timerActivated;
    bool socketActivated;

private slots:
    void timerFired();
    void socketFired();
};

MixingWithTimersHelper::MixingWithTimersHelper(QTimer *timer, QTcpServer *server)
{
    timerActivated = false;
    socketActivated = false;

    connect(timer, SIGNAL(timeout()), SLOT(timerFired()));
    connect(server, SIGNAL(newConnection()), SLOT(socketFired()));
}

void MixingWithTimersHelper::timerFired()
{
    timerActivated = true;
}

void MixingWithTimersHelper::socketFired()
{
    socketActivated = true;
}

void tst_QSocketNotifier::mixingWithTimers()
{
    QTimer timer;
    timer.setInterval(0);
    timer.start();

    QTcpServer server;
    QVERIFY(server.listen(QHostAddress::LocalHost, 0));

    MixingWithTimersHelper helper(&timer, &server);

    QCoreApplication::processEvents();

    QCOMPARE(helper.timerActivated, true);
    QCOMPARE(helper.socketActivated, false);

    helper.timerActivated = false;
    helper.socketActivated = false;

    QTcpSocket socket;
    socket.connectToHost(server.serverAddress(), server.serverPort());

    QCoreApplication::processEvents();

    QCOMPARE(helper.timerActivated, true);
    QCOMPARE(helper.socketActivated, true);
}

QTEST_MAIN(tst_QSocketNotifier)
#include <tst_qsocketnotifier.moc>
<commit_msg>We feel that test case should be changed, as we cant expect that order of the event hansling will be same on all platforms.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtTest/QtTest>

#include <QtCore/QCoreApplication>
#include <QtCore/QSocketNotifier>
#include <QtNetwork/QTcpServer>
#include <QtNetwork/QTcpSocket>
#include <private/qnativesocketengine_p.h>

class tst_QSocketNotifier : public QObject
{
    Q_OBJECT
public:
    tst_QSocketNotifier();
    ~tst_QSocketNotifier();

private slots:
    void unexpectedDisconnection();
    void mixingWithTimers();
};

tst_QSocketNotifier::tst_QSocketNotifier()
{ }

tst_QSocketNotifier::~tst_QSocketNotifier()
{
}

class UnexpectedDisconnectTester : public QObject
{
    Q_OBJECT
public:
    QNativeSocketEngine *readEnd1, *readEnd2;
    int sequence;

    UnexpectedDisconnectTester(QNativeSocketEngine *s1, QNativeSocketEngine *s2)
        : readEnd1(s1), readEnd2(s2), sequence(0)
    {
        QSocketNotifier *notifier1 =
            new QSocketNotifier(readEnd1->socketDescriptor(), QSocketNotifier::Read, this);
        connect(notifier1, SIGNAL(activated(int)), SLOT(handleActivated()));
        QSocketNotifier *notifier2 =
            new QSocketNotifier(readEnd2->socketDescriptor(), QSocketNotifier::Read, this);
        connect(notifier2, SIGNAL(activated(int)), SLOT(handleActivated()));
    }

public slots:
    void handleActivated()
    {
        char data1[1], data2[1];
        ++sequence;
        if (sequence == 1) {
            // read from both ends
            (void) readEnd1->read(data1, sizeof(data1));
            (void) readEnd2->read(data2, sizeof(data2));
            emit finished();
        } else if (sequence == 2) {
            // we should never get here
            QCOMPARE(readEnd2->read(data2, sizeof(data2)), qint64(-2));
            QVERIFY(readEnd2->isValid());
        }
    }

signals:
    void finished();
};

void tst_QSocketNotifier::unexpectedDisconnection()
{
    /*
      Given two sockets and two QSocketNotifiers registered on each
      their socket. If both sockets receive data, and the first slot
      invoked by one of the socket notifiers empties both sockets, the
      other notifier will also emit activated(). This results in
      unexpected disconnection in QAbstractSocket.

      The use case is that somebody calls one of the
      waitFor... functions in a QSocketNotifier activated slot, and
      the waitFor... functions do local selects that can empty both
      stdin and stderr while waiting for fex bytes to be written.
    */

    QTcpServer server;
    QVERIFY(server.listen(QHostAddress::LocalHost, 0));

    QNativeSocketEngine readEnd1;
    readEnd1.initialize(QAbstractSocket::TcpSocket);
    bool b = readEnd1.connectToHost(server.serverAddress(), server.serverPort());
    QVERIFY(readEnd1.waitForWrite());
//    while (!b && readEnd1.state() != QAbstractSocket::ConnectedState)
//        b = readEnd1.connectToHost(server.serverAddress(), server.serverPort());
    QVERIFY(readEnd1.state() == QAbstractSocket::ConnectedState);
    QVERIFY(server.waitForNewConnection());
    QTcpSocket *writeEnd1 = server.nextPendingConnection();
    QVERIFY(writeEnd1 != 0);

    QNativeSocketEngine readEnd2;
    readEnd2.initialize(QAbstractSocket::TcpSocket);
    b = readEnd2.connectToHost(server.serverAddress(), server.serverPort());
    QVERIFY(readEnd2.waitForWrite());
//    while (!b)
//        b = readEnd2.connectToHost(server.serverAddress(), server.serverPort());
    QVERIFY(readEnd2.state() == QAbstractSocket::ConnectedState);
    QVERIFY(server.waitForNewConnection());
    QTcpSocket *writeEnd2 = server.nextPendingConnection();
    QVERIFY(writeEnd2 != 0);

    writeEnd1->write("1", 1);
    writeEnd2->write("2", 1);

    writeEnd1->waitForBytesWritten();
    writeEnd2->waitForBytesWritten();

    writeEnd1->flush();
    writeEnd2->flush();

    UnexpectedDisconnectTester tester(&readEnd1, &readEnd2);

    do {
        // we have to wait until sequence value changes
        // as any event can make us jump out processing
        QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
    }  while(tester.sequence <= 0);

    QVERIFY(readEnd1.state() == QAbstractSocket::ConnectedState);
    QVERIFY(readEnd2.state() == QAbstractSocket::ConnectedState);

    QCOMPARE(tester.sequence, 2);

    readEnd1.close();
    readEnd2.close();
    writeEnd1->close();
    writeEnd2->close();
    server.close();
}

class MixingWithTimersHelper : public QObject
{
    Q_OBJECT

public:
    MixingWithTimersHelper(QTimer *timer, QTcpServer *server);

    bool timerActivated;
    bool socketActivated;

private slots:
    void timerFired();
    void socketFired();
};

MixingWithTimersHelper::MixingWithTimersHelper(QTimer *timer, QTcpServer *server)
{
    timerActivated = false;
    socketActivated = false;

    connect(timer, SIGNAL(timeout()), SLOT(timerFired()));
    connect(server, SIGNAL(newConnection()), SLOT(socketFired()));
}

void MixingWithTimersHelper::timerFired()
{
    timerActivated = true;
}

void MixingWithTimersHelper::socketFired()
{
    socketActivated = true;
}

void tst_QSocketNotifier::mixingWithTimers()
{
    QTimer timer;
    timer.setInterval(0);
    timer.start();

    QTcpServer server;
    QVERIFY(server.listen(QHostAddress::LocalHost, 0));

    MixingWithTimersHelper helper(&timer, &server);

    QCoreApplication::processEvents();

    QCOMPARE(helper.timerActivated, true);
    QCOMPARE(helper.socketActivated, false);

    helper.timerActivated = false;
    helper.socketActivated = false;

    QTcpSocket socket;
    socket.connectToHost(server.serverAddress(), server.serverPort());

    QCoreApplication::processEvents();

    QCOMPARE(helper.timerActivated, true);
    QCOMPARE(helper.socketActivated, true);
}

QTEST_MAIN(tst_QSocketNotifier)
#include <tst_qsocketnotifier.moc>
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2010-2011 Dmitry Marakasov
 *
 * This file is part of glosm.
 *
 * glosm is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * glosm is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with glosm.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "GlosmViewer.hh"

#include <glosm/util/gl.h>

#include <SDL/SDL.h>
#include <SDL/SDL_keysym.h>
#if defined(WITH_GLES)
#	include <SDL_gles.h>
#else
#	include <SDL/SDL_opengl.h>
#endif

#include <cstdio>

class GlosmViewerImpl : public GlosmViewer {
protected:
	bool ignoremouse_;

public:
	GlosmViewerImpl() : ignoremouse_(true) {
	}

	virtual void MouseMove(int x, int y) {
		if (!ignoremouse_)
			GlosmViewer::MouseMove(x, y);
	}

protected:
	virtual void WarpCursor(int x, int y) {
		ignoremouse_ = true;
		SDL_WarpMouse(x, y);
		ignoremouse_ = false;
	}

	virtual void Flip() {
#if defined(WITH_GLES)
		SDL_GLES_SwapBuffers();
#else
		SDL_GL_SwapBuffers();
#endif
	}

	virtual void ShowCursor(bool show) {
#if defined(WITH_TOUCHPAD)
		SDL_ShowCursor(SDL_DISABLE);
#else
		SDL_ShowCursor(show ? SDL_ENABLE : SDL_DISABLE);
#endif
	}
};

#if defined(WITH_GLES)
SDL_GLES_Context* gles_context = 0;
#endif

GlosmViewerImpl app;

void Reshape(int w, int h) {
#if !defined(WITH_GLES)
	if (SDL_SetVideoMode(w, h, 0, SDL_OPENGL | SDL_RESIZABLE | SDL_HWSURFACE) == NULL)
		throw Exception() << "SDL_SetVideoMode failed: " << (const char*)SDL_GetError();
#endif

	app.Resize(w, h);
}

void KeyDown(SDLKey key) {
	if (key < 0x100)
		app.KeyDown(key);
	else
		switch(key) {
		case SDLK_UP: app.KeyDown(GlosmViewer::KEY_UP); break;
		case SDLK_DOWN: app.KeyDown(GlosmViewer::KEY_DOWN); break;
		case SDLK_LEFT: app.KeyDown(GlosmViewer::KEY_LEFT); break;
		case SDLK_RIGHT: app.KeyDown(GlosmViewer::KEY_RIGHT); break;
		case SDLK_KP_PLUS: app.KeyDown('+'); break;
		case SDLK_KP_MINUS: app.KeyDown('-'); break;
		case SDLK_LSHIFT: case SDLK_RSHIFT: app.KeyDown(GlosmViewer::KEY_SHIFT); break;
		case SDLK_LCTRL: case SDLK_RCTRL: app.KeyDown(GlosmViewer::KEY_CTRL); break;
		default: break;
		}
}

void KeyUp(SDLKey key) {
	if (key < 0x100)
		app.KeyUp(key);
	else
		switch(key) {
		case SDLK_UP: app.KeyUp(GlosmViewer::KEY_UP); break;
		case SDLK_DOWN: app.KeyUp(GlosmViewer::KEY_DOWN); break;
		case SDLK_LEFT: app.KeyUp(GlosmViewer::KEY_LEFT); break;
		case SDLK_RIGHT: app.KeyUp(GlosmViewer::KEY_RIGHT); break;
		case SDLK_KP_PLUS: app.KeyUp('+'); break;
		case SDLK_KP_MINUS: app.KeyUp('-'); break;
		case SDLK_LSHIFT: case SDLK_RSHIFT: app.KeyUp(GlosmViewer::KEY_SHIFT); break;
		case SDLK_LCTRL: case SDLK_RCTRL: app.KeyUp(GlosmViewer::KEY_CTRL); break;
		default: break;
		}
}

void Cleanup() {
#if defined(WITH_GLES)
	if (gles_context)
		SDL_GLES_DeleteContext(gles_context);
#endif
	SDL_Quit();
}

int GetEvents() {
	SDL_Event event;

	while (SDL_PollEvent(&event)) {
		int ret = 1;
		switch(event.type) {
		case SDL_QUIT:
			return 0;
		case SDL_KEYDOWN:
			KeyDown(event.key.keysym.sym);
			break;
		case SDL_KEYUP:
			KeyUp(event.key.keysym.sym);
			break;
		case SDL_MOUSEMOTION:
			app.MouseMove(event.motion.x, event.motion.y);
			break;
		case SDL_MOUSEBUTTONDOWN:
		case SDL_MOUSEBUTTONUP:
			{
				int b = GlosmViewer::BUTTON_LEFT;
				switch (event.button.button) {
				case SDL_BUTTON_LEFT: b = GlosmViewer::BUTTON_LEFT; break;
				case SDL_BUTTON_RIGHT: b = GlosmViewer::BUTTON_RIGHT; break;
				case SDL_BUTTON_MIDDLE: b = GlosmViewer::BUTTON_MIDDLE; break;
				}
				app.MouseButton(b, event.button.state == SDL_PRESSED, event.button.x, event.button.y);
			}
			break;
		case SDL_VIDEORESIZE:
			Reshape(event.resize.w, event.resize.h);
			break;
		default:
			break;
		}

		if (ret == 0)
			return 0;
	}

	return 1;
}

int real_main(int argc, char** argv) {
	app.Init(argc, argv);

	/* glut init */
	if (SDL_Init(SDL_INIT_VIDEO) != 0)
		throw Exception() << "Couldn't initialize SDL: " << (const char*)SDL_GetError();

	atexit(Cleanup);

#if !defined(WITH_GLES)
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

	try {
		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
		Reshape(800, 600);
	} catch (Exception& e) {
		fprintf(stderr, "warning: %s, retrying without multisampling\n", e.what());
		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
		Reshape(800, 600);
	}
#else
	/* Using fixed resolution for N900
	 * it should be detected on the fly instead */
	SDL_SetVideoMode(800, 480, 0, SDL_SWSURFACE | SDL_FULLSCREEN);

	SDL_GLES_Init(SDL_GLES_VERSION_1_1);

	SDL_GLES_SetAttribute(SDL_GLES_DEPTH_SIZE, 24);

	gles_context = SDL_GLES_CreateContext();

	SDL_GLES_MakeCurrent(gles_context);

	Reshape(800, 480);
#endif

	SDL_EnableKeyRepeat(0, 0);

	app.InitGL();

	/* main loop */
	while (GetEvents())
		app.Render();

	return 0;
}

int main(int argc, char** argv) {
	try {
		return real_main(argc, argv);
	} catch (std::exception &e) {
		fprintf(stderr, "Exception: %s\n", e.what());
	} catch (...) {
		fprintf(stderr, "Unknown exception\n");
	}

	return 1;
}
<commit_msg>Keep SDL's glext out of way<commit_after>/*
 * Copyright (C) 2010-2011 Dmitry Marakasov
 *
 * This file is part of glosm.
 *
 * glosm is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * glosm is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with glosm.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "GlosmViewer.hh"

#include <glosm/util/gl.h>

#include <SDL/SDL.h>
#include <SDL/SDL_keysym.h>
#if defined(WITH_GLES)
#	include <SDL_gles.h>
#else
#	define NO_SDL_GLEXT
#	include <SDL/SDL_opengl.h>
#endif

#include <cstdio>

class GlosmViewerImpl : public GlosmViewer {
protected:
	bool ignoremouse_;

public:
	GlosmViewerImpl() : ignoremouse_(true) {
	}

	virtual void MouseMove(int x, int y) {
		if (!ignoremouse_)
			GlosmViewer::MouseMove(x, y);
	}

protected:
	virtual void WarpCursor(int x, int y) {
		ignoremouse_ = true;
		SDL_WarpMouse(x, y);
		ignoremouse_ = false;
	}

	virtual void Flip() {
#if defined(WITH_GLES)
		SDL_GLES_SwapBuffers();
#else
		SDL_GL_SwapBuffers();
#endif
	}

	virtual void ShowCursor(bool show) {
#if defined(WITH_TOUCHPAD)
		SDL_ShowCursor(SDL_DISABLE);
#else
		SDL_ShowCursor(show ? SDL_ENABLE : SDL_DISABLE);
#endif
	}
};

#if defined(WITH_GLES)
SDL_GLES_Context* gles_context = 0;
#endif

GlosmViewerImpl app;

void Reshape(int w, int h) {
#if !defined(WITH_GLES)
	if (SDL_SetVideoMode(w, h, 0, SDL_OPENGL | SDL_RESIZABLE | SDL_HWSURFACE) == NULL)
		throw Exception() << "SDL_SetVideoMode failed: " << (const char*)SDL_GetError();
#endif

	app.Resize(w, h);
}

void KeyDown(SDLKey key) {
	if (key < 0x100)
		app.KeyDown(key);
	else
		switch(key) {
		case SDLK_UP: app.KeyDown(GlosmViewer::KEY_UP); break;
		case SDLK_DOWN: app.KeyDown(GlosmViewer::KEY_DOWN); break;
		case SDLK_LEFT: app.KeyDown(GlosmViewer::KEY_LEFT); break;
		case SDLK_RIGHT: app.KeyDown(GlosmViewer::KEY_RIGHT); break;
		case SDLK_KP_PLUS: app.KeyDown('+'); break;
		case SDLK_KP_MINUS: app.KeyDown('-'); break;
		case SDLK_LSHIFT: case SDLK_RSHIFT: app.KeyDown(GlosmViewer::KEY_SHIFT); break;
		case SDLK_LCTRL: case SDLK_RCTRL: app.KeyDown(GlosmViewer::KEY_CTRL); break;
		default: break;
		}
}

void KeyUp(SDLKey key) {
	if (key < 0x100)
		app.KeyUp(key);
	else
		switch(key) {
		case SDLK_UP: app.KeyUp(GlosmViewer::KEY_UP); break;
		case SDLK_DOWN: app.KeyUp(GlosmViewer::KEY_DOWN); break;
		case SDLK_LEFT: app.KeyUp(GlosmViewer::KEY_LEFT); break;
		case SDLK_RIGHT: app.KeyUp(GlosmViewer::KEY_RIGHT); break;
		case SDLK_KP_PLUS: app.KeyUp('+'); break;
		case SDLK_KP_MINUS: app.KeyUp('-'); break;
		case SDLK_LSHIFT: case SDLK_RSHIFT: app.KeyUp(GlosmViewer::KEY_SHIFT); break;
		case SDLK_LCTRL: case SDLK_RCTRL: app.KeyUp(GlosmViewer::KEY_CTRL); break;
		default: break;
		}
}

void Cleanup() {
#if defined(WITH_GLES)
	if (gles_context)
		SDL_GLES_DeleteContext(gles_context);
#endif
	SDL_Quit();
}

int GetEvents() {
	SDL_Event event;

	while (SDL_PollEvent(&event)) {
		int ret = 1;
		switch(event.type) {
		case SDL_QUIT:
			return 0;
		case SDL_KEYDOWN:
			KeyDown(event.key.keysym.sym);
			break;
		case SDL_KEYUP:
			KeyUp(event.key.keysym.sym);
			break;
		case SDL_MOUSEMOTION:
			app.MouseMove(event.motion.x, event.motion.y);
			break;
		case SDL_MOUSEBUTTONDOWN:
		case SDL_MOUSEBUTTONUP:
			{
				int b = GlosmViewer::BUTTON_LEFT;
				switch (event.button.button) {
				case SDL_BUTTON_LEFT: b = GlosmViewer::BUTTON_LEFT; break;
				case SDL_BUTTON_RIGHT: b = GlosmViewer::BUTTON_RIGHT; break;
				case SDL_BUTTON_MIDDLE: b = GlosmViewer::BUTTON_MIDDLE; break;
				}
				app.MouseButton(b, event.button.state == SDL_PRESSED, event.button.x, event.button.y);
			}
			break;
		case SDL_VIDEORESIZE:
			Reshape(event.resize.w, event.resize.h);
			break;
		default:
			break;
		}

		if (ret == 0)
			return 0;
	}

	return 1;
}

int real_main(int argc, char** argv) {
	app.Init(argc, argv);

	/* glut init */
	if (SDL_Init(SDL_INIT_VIDEO) != 0)
		throw Exception() << "Couldn't initialize SDL: " << (const char*)SDL_GetError();

	atexit(Cleanup);

#if !defined(WITH_GLES)
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

	try {
		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
		Reshape(800, 600);
	} catch (Exception& e) {
		fprintf(stderr, "warning: %s, retrying without multisampling\n", e.what());
		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
		Reshape(800, 600);
	}
#else
	/* Using fixed resolution for N900
	 * it should be detected on the fly instead */
	SDL_SetVideoMode(800, 480, 0, SDL_SWSURFACE | SDL_FULLSCREEN);

	SDL_GLES_Init(SDL_GLES_VERSION_1_1);

	SDL_GLES_SetAttribute(SDL_GLES_DEPTH_SIZE, 24);

	gles_context = SDL_GLES_CreateContext();

	SDL_GLES_MakeCurrent(gles_context);

	Reshape(800, 480);
#endif

	SDL_EnableKeyRepeat(0, 0);

	app.InitGL();

	/* main loop */
	while (GetEvents())
		app.Render();

	return 0;
}

int main(int argc, char** argv) {
	try {
		return real_main(argc, argv);
	} catch (std::exception &e) {
		fprintf(stderr, "Exception: %s\n", e.what());
	} catch (...) {
		fprintf(stderr, "Unknown exception\n");
	}

	return 1;
}
<|endoftext|>