<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

#include <osgViewer/View>
#include <osgViewer/GraphicsWindow>

#include <osgUtil/SceneView>
#include <osg/io_utils>

using namespace osgViewer;

View::View()
{
    // osg::notify(osg::NOTICE)<<"Constructing osgViewer::View"<<std::endl;
   setEventQueue(new osgGA::EventQueue);
}

View::~View()
{
    // osg::notify(osg::NOTICE)<<"Destructing osgViewer::View"<<std::endl;
}

void View::setSceneData(osg::Node* node)
{
    _scene = new osgViewer::Scene;
    _scene->setSceneData(node);

    assignSceneDataToCameras();
}

void View::setCameraManipulator(osgGA::MatrixManipulator* manipulator)
{
    _cameraManipulator = manipulator;
    if (_cameraManipulator.valid() && getSceneData())
    {
        _cameraManipulator->setNode(getSceneData());

        osg::ref_ptr<osgGA::GUIEventAdapter> dummyEvent = _eventQueue->createEvent();

        _cameraManipulator->home(*dummyEvent, *this);
    }
}

void View::addEventHandler(osgGA::GUIEventHandler* eventHandler)
{
    _eventHandlers.push_back(eventHandler);
}

void View::setUpViewAcrossAllScreens()
{
    osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
    if (!wsi)
    {
        osg::notify(osg::NOTICE)<<"View::setUpViewAcrossAllScreens() : Error, no WindowSystemInterface available, cannot create windows."<<std::endl;
        return;
    }

    double fovy, aspectRatio, zNear, zFar;
    _camera->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar);

    double fovx = atan(tan(osg::DegreesToRadians(fovy*0.5)) * aspectRatio) * 2.0;

    unsigned int numScreens = wsi->getNumScreens();
    if (numScreens==1)
    {
            unsigned int width, height;
            wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), width, height);

            osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
            traits->x = 0;
            traits->y = 0;
            traits->width = width;
            traits->height = height;
#if 1
            traits->windowDecoration = false;
#else
            traits->windowDecoration = true;
#endif
            traits->doubleBuffer = true;
            traits->sharedContext = 0;

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

            _camera->setGraphicsContext(gc.get());

            osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc.get());
            if (gw)
            {
                osg::notify(osg::INFO)<<"  GraphicsWindow has been created successfully."<<std::endl;
                gw->getEventQueue()->getCurrentEventState()->setWindowRectangle(0, 0, width, height );
            }
            else
            {
                osg::notify(osg::NOTICE)<<"  GraphicsWindow has not been created successfully."<<std::endl;
            }

            _camera->setViewport(new osg::Viewport(0, 0, width, height));

            GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;

            _camera->setDrawBuffer(buffer);
            _camera->setReadBuffer(buffer);

    }
    else
    {
        double rotate_x = - double(numScreens-1) * 0.5 * fovx;

        for(unsigned int i=0; i<numScreens; ++i, rotate_x += fovx)
        {
            unsigned int width, height;
            wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(i), width, height);

            osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
            traits->screenNum = i;
            traits->x = 0;
            traits->y = 0;
            traits->width = width;
            traits->height = height;
            traits->windowDecoration = false;
            traits->doubleBuffer = true;
            traits->sharedContext = 0;

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

            osg::ref_ptr<osg::Camera> camera = new osg::Camera;
            camera->setGraphicsContext(gc.get());

            osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc.get());
            if (gw)
            {
                osg::notify(osg::INFO)<<"  GraphicsWindow has been created successfully."<<gw<<std::endl;

                gw->getEventQueue()->getCurrentEventState()->setWindowRectangle(0, 0, width, height );
            }
            else
            {
                osg::notify(osg::NOTICE)<<"  GraphicsWindow has not been created successfully."<<std::endl;
            }

            camera->setViewport(new osg::Viewport(0, 0, width, height));

            GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
            camera->setDrawBuffer(buffer);
            camera->setReadBuffer(buffer);

            addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::rotate( rotate_x, 0.0, 1.0, 0.0));

        }
    }

    setUpRenderingSupport();
    assignSceneDataToCameras();
}

// Draw operation, that does a draw on the scene graph.
struct RenderingOperation : public osg::GraphicsOperation
{
    RenderingOperation(osgUtil::SceneView* sceneView, osgDB::DatabasePager* databasePager):
        osg::GraphicsOperation("Render",true),
        _sceneView(sceneView),
        _databasePager(databasePager)
    {
        _sceneView->getCullVisitor()->setDatabaseRequestHandler(_databasePager.get());
    }

    virtual void operator () (osg::GraphicsContext*)
    {
        if (!_sceneView) return;

        // osg::notify(osg::NOTICE)<<"RenderingOperation"<<std::endl;

        _sceneView->cull();
        _sceneView->draw();

        if (_databasePager.valid())
        {
            double availableTime = 0.004; // 4 ms
            _databasePager->compileGLObjects(*(_sceneView->getState()), availableTime);
            _sceneView->flushDeletedGLObjects(availableTime);
        }
    }

    osg::observer_ptr<osgUtil::SceneView>    _sceneView;
    osg::observer_ptr<osgDB::DatabasePager>  _databasePager;
};

void View::setUpRenderingSupport()
{
    osg::FrameStamp* frameStamp = _scene->getFrameStamp();

    // what should we do with the old sceneViews?
    _cameraSceneViewMap.clear();

    if (_camera.valid() && _camera->getGraphicsContext())
    {
        osgUtil::SceneView* sceneView = new osgUtil::SceneView;
        _cameraSceneViewMap[_camera] = sceneView;

        sceneView->setDefaults();
        sceneView->setCamera(_camera.get());
        sceneView->setState(_camera->getGraphicsContext()->getState());
        sceneView->setSceneData(getSceneData());
        sceneView->setFrameStamp(frameStamp);

        _camera->getGraphicsContext()->add(new RenderingOperation(sceneView, _scene->getDatabasePager()));
    }

    for(unsigned i=0; i<getNumSlaves(); ++i)
    {
        Slave& slave = getSlave(i);
        if (slave._camera.valid() && slave._camera->getGraphicsContext())
        {
            osgUtil::SceneView* sceneView = new osgUtil::SceneView;
            _cameraSceneViewMap[slave._camera] = sceneView;

            sceneView->setDefaults();
            sceneView->setCamera(slave._camera.get());
            sceneView->setState(slave._camera->getGraphicsContext()->getState());
            sceneView->setSceneData(getSceneData());
            sceneView->setFrameStamp(frameStamp);

            slave._camera->getGraphicsContext()->add(new RenderingOperation(sceneView, _scene->getDatabasePager()));
        }
    }
}

void View::assignSceneDataToCameras()
{
    osg::Node* sceneData = _scene.valid() ? _scene->getSceneData() : 0;

    if (_cameraManipulator.valid())
    {
        _cameraManipulator->setNode(sceneData);

        osg::ref_ptr<osgGA::GUIEventAdapter> dummyEvent = _eventQueue->createEvent();

        _cameraManipulator->home(*dummyEvent, *this);
    }

    if (_camera.valid())
    {
        _camera->removeChildren(0,_camera->getNumChildren());
        if (sceneData) _camera->addChild(sceneData);
    }

    for(unsigned i=0; i<getNumSlaves(); ++i)
    {
        Slave& slave = getSlave(i);
        if (slave._camera.valid())
        {
            slave._camera->removeChildren(0,slave._camera->getNumChildren());
            if (sceneData) slave._camera->addChild(sceneData);
        }
    }
}

void View::requestRedraw()
{
}

void View::requestContinuousUpdate(bool)
{
}

void View::requestWarpPointer(float x,float y)
{
    osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
    bool view_invert_y = eventState->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;

    getEventQueue()->mouseWarped(x,y);

    osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(_camera->getGraphicsContext());
    if (gw)
    {
        bool gw_invert_y = gw->getEventQueue()->getCurrentEventState()->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;

        x = x * float(gw->getTraits()->width) / (eventState->getXmax()-eventState->getXmin());
        y = y * float(gw->getTraits()->height) / (eventState->getYmax()-eventState->getYmin());

        if (view_invert_y != gw_invert_y) y = gw->getTraits()->height - y;

        gw->requestWarpPointer(x, y);

        return;
    }

    osg::Matrix masterCameraVPW = getCamera()->getViewMatrix() * getCamera()->getProjectionMatrix();

    x = (x - eventState->getXmin()) * 2.0 / (eventState->getXmax()-eventState->getXmin()) - 1.0;
    y = (y - eventState->getYmin())* 2.0 / (eventState->getYmax()-eventState->getYmin()) - 1.0;

    if (view_invert_y) y = - y;

    for(unsigned i=0; i<getNumSlaves(); ++i)
    {
        Slave& slave = getSlave(i);
        if (slave._camera.valid())
        {
            osg::Camera* camera = slave._camera.get();
            osg::Viewport* viewport = camera ? camera->getViewport() : 0;

            osg::Matrix localCameraVPW = camera->getViewMatrix() * camera->getProjectionMatrix();
            if (viewport) localCameraVPW *= viewport->computeWindowMatrix();

            osg::Matrix matrix( osg::Matrix::inverse(masterCameraVPW) * localCameraVPW );

            osg::Vec3d new_coord = osg::Vec3d(x,y,0.0) * matrix;

            if (viewport &&
                new_coord.x() >= viewport->x() && new_coord.y() >= viewport->y() &&
                new_coord.x() <= (viewport->x()+viewport->width()) && new_coord.y() <= (viewport->y()+viewport->height()) )
            {
                gw = dynamic_cast<osgViewer::GraphicsWindow*>(camera->getGraphicsContext());
                if (gw)
                {
                    x = new_coord.x();
                    y = new_coord.y();

                    bool gw_invert_y = gw->getEventQueue()->getCurrentEventState()->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;

                    if (gw_invert_y) y = gw->getTraits()->height - y;

                    gw->requestWarpPointer(x, y);

                    return;
                }
            }

        }
    }

}
<commit_msg>Changed default multi-screen setup to set up for a flat wall configuration<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

#include <osgViewer/View>
#include <osgViewer/GraphicsWindow>

#include <osgUtil/SceneView>
#include <osg/io_utils>

using namespace osgViewer;

View::View()
{
    // osg::notify(osg::NOTICE)<<"Constructing osgViewer::View"<<std::endl;
   setEventQueue(new osgGA::EventQueue);
}

View::~View()
{
    // osg::notify(osg::NOTICE)<<"Destructing osgViewer::View"<<std::endl;
}

void View::setSceneData(osg::Node* node)
{
    _scene = new osgViewer::Scene;
    _scene->setSceneData(node);

    assignSceneDataToCameras();
}

void View::setCameraManipulator(osgGA::MatrixManipulator* manipulator)
{
    _cameraManipulator = manipulator;
    if (_cameraManipulator.valid() && getSceneData())
    {
        _cameraManipulator->setNode(getSceneData());

        osg::ref_ptr<osgGA::GUIEventAdapter> dummyEvent = _eventQueue->createEvent();

        _cameraManipulator->home(*dummyEvent, *this);
    }
}

void View::addEventHandler(osgGA::GUIEventHandler* eventHandler)
{
    _eventHandlers.push_back(eventHandler);
}

void View::setUpViewAcrossAllScreens()
{
    osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
    if (!wsi)
    {
        osg::notify(osg::NOTICE)<<"View::setUpViewAcrossAllScreens() : Error, no WindowSystemInterface available, cannot create windows."<<std::endl;
        return;
    }

    double fovy, aspectRatio, zNear, zFar;
    _camera->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar);

    double fovx = atan(tan(osg::DegreesToRadians(fovy*0.5)) * aspectRatio) * 2.0;

    unsigned int numScreens = wsi->getNumScreens();
    if (numScreens==1)
    {
            unsigned int width, height;
            wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), width, height);

            osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
            traits->x = 0;
            traits->y = 0;
            traits->width = width;
            traits->height = height;
#if 1
            traits->windowDecoration = false;
#else
            traits->windowDecoration = true;
#endif
            traits->doubleBuffer = true;
            traits->sharedContext = 0;

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

            _camera->setGraphicsContext(gc.get());

            osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc.get());
            if (gw)
            {
                osg::notify(osg::INFO)<<"  GraphicsWindow has been created successfully."<<std::endl;
                gw->getEventQueue()->getCurrentEventState()->setWindowRectangle(0, 0, width, height );
            }
            else
            {
                osg::notify(osg::NOTICE)<<"  GraphicsWindow has not been created successfully."<<std::endl;
            }

            _camera->setViewport(new osg::Viewport(0, 0, width, height));

            GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;

            _camera->setDrawBuffer(buffer);
            _camera->setReadBuffer(buffer);

    }
    else
    {

        bool cylindericalScreen = false;

        if (cylindericalScreen)
        {
            double rotate_x = - double(numScreens-1) * 0.5 * fovx;

            for(unsigned int i=0; i<numScreens; ++i, rotate_x += fovx)
            {
                unsigned int width, height;
                wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(i), width, height);

                osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
                traits->screenNum = i;
                traits->x = 0;
                traits->y = 0;
                traits->width = width;
                traits->height = height;
                traits->windowDecoration = false;
                traits->doubleBuffer = true;
                traits->sharedContext = 0;

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

                osg::ref_ptr<osg::Camera> camera = new osg::Camera;
                camera->setGraphicsContext(gc.get());

                osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc.get());
                if (gw)
                {
                    osg::notify(osg::INFO)<<"  GraphicsWindow has been created successfully."<<gw<<std::endl;

                    gw->getEventQueue()->getCurrentEventState()->setWindowRectangle(0, 0, width, height );
                }
                else
                {
                    osg::notify(osg::NOTICE)<<"  GraphicsWindow has not been created successfully."<<std::endl;
                }

                camera->setViewport(new osg::Viewport(0, 0, width, height));

                GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
                camera->setDrawBuffer(buffer);
                camera->setReadBuffer(buffer);

                addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::rotate( rotate_x, 0.0, 1.0, 0.0));

            }
        }
        else
        {
            double translate_x = double(numScreens) - 1.0;

            for(unsigned int i=0; i<numScreens; ++i, translate_x -= 2.0)
            {
                unsigned int width, height;
                wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(i), width, height);

                osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
                traits->screenNum = i;
                traits->x = 0;
                traits->y = 0;
                traits->width = width;
                traits->height = height;
                traits->windowDecoration = false;
                traits->doubleBuffer = true;
                traits->sharedContext = 0;

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

                osg::ref_ptr<osg::Camera> camera = new osg::Camera;
                camera->setGraphicsContext(gc.get());

                osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc.get());
                if (gw)
                {
                    osg::notify(osg::INFO)<<"  GraphicsWindow has been created successfully."<<gw<<std::endl;

                    gw->getEventQueue()->getCurrentEventState()->setWindowRectangle(0, 0, width, height );
                }
                else
                {
                    osg::notify(osg::NOTICE)<<"  GraphicsWindow has not been created successfully."<<std::endl;
                }

                camera->setViewport(new osg::Viewport(0, 0, width, height));

                GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
                camera->setDrawBuffer(buffer);
                camera->setReadBuffer(buffer);

                addSlave(camera.get(), osg::Matrixd::translate( translate_x, 0.0, 0.0), osg::Matrixd() );

            }
        }
    }

    setUpRenderingSupport();
    assignSceneDataToCameras();
}

// Draw operation, that does a draw on the scene graph.
struct RenderingOperation : public osg::GraphicsOperation
{
    RenderingOperation(osgUtil::SceneView* sceneView, osgDB::DatabasePager* databasePager):
        osg::GraphicsOperation("Render",true),
        _sceneView(sceneView),
        _databasePager(databasePager)
    {
        _sceneView->getCullVisitor()->setDatabaseRequestHandler(_databasePager.get());
    }

    virtual void operator () (osg::GraphicsContext*)
    {
        if (!_sceneView) return;

        // osg::notify(osg::NOTICE)<<"RenderingOperation"<<std::endl;

        _sceneView->cull();
        _sceneView->draw();

        if (_databasePager.valid())
        {
            double availableTime = 0.004; // 4 ms
            _databasePager->compileGLObjects(*(_sceneView->getState()), availableTime);
            _sceneView->flushDeletedGLObjects(availableTime);
        }
    }

    osg::observer_ptr<osgUtil::SceneView>    _sceneView;
    osg::observer_ptr<osgDB::DatabasePager>  _databasePager;
};

void View::setUpRenderingSupport()
{
    osg::FrameStamp* frameStamp = _scene->getFrameStamp();

    // what should we do with the old sceneViews?
    _cameraSceneViewMap.clear();

    if (_camera.valid() && _camera->getGraphicsContext())
    {
        osgUtil::SceneView* sceneView = new osgUtil::SceneView;
        _cameraSceneViewMap[_camera] = sceneView;

        sceneView->setDefaults();
        sceneView->setCamera(_camera.get());
        sceneView->setState(_camera->getGraphicsContext()->getState());
        sceneView->setSceneData(getSceneData());
        sceneView->setFrameStamp(frameStamp);

        _camera->getGraphicsContext()->add(new RenderingOperation(sceneView, _scene->getDatabasePager()));
    }

    for(unsigned i=0; i<getNumSlaves(); ++i)
    {
        Slave& slave = getSlave(i);
        if (slave._camera.valid() && slave._camera->getGraphicsContext())
        {
            osgUtil::SceneView* sceneView = new osgUtil::SceneView;
            _cameraSceneViewMap[slave._camera] = sceneView;

            sceneView->setDefaults();
            sceneView->setCamera(slave._camera.get());
            sceneView->setState(slave._camera->getGraphicsContext()->getState());
            sceneView->setSceneData(getSceneData());
            sceneView->setFrameStamp(frameStamp);

            slave._camera->getGraphicsContext()->add(new RenderingOperation(sceneView, _scene->getDatabasePager()));
        }
    }
}

void View::assignSceneDataToCameras()
{
    osg::Node* sceneData = _scene.valid() ? _scene->getSceneData() : 0;

    if (_cameraManipulator.valid())
    {
        _cameraManipulator->setNode(sceneData);

        osg::ref_ptr<osgGA::GUIEventAdapter> dummyEvent = _eventQueue->createEvent();

        _cameraManipulator->home(*dummyEvent, *this);
    }

    if (_camera.valid())
    {
        _camera->removeChildren(0,_camera->getNumChildren());
        if (sceneData) _camera->addChild(sceneData);
    }

    for(unsigned i=0; i<getNumSlaves(); ++i)
    {
        Slave& slave = getSlave(i);
        if (slave._camera.valid())
        {
            slave._camera->removeChildren(0,slave._camera->getNumChildren());
            if (sceneData) slave._camera->addChild(sceneData);
        }
    }
}

void View::requestRedraw()
{
}

void View::requestContinuousUpdate(bool)
{
}

void View::requestWarpPointer(float x,float y)
{
    // osg::notify(osg::NOTICE)<<"View::requestWarpPointer("<<x<<","<<y<<")"<<std::endl;

    osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
    bool view_invert_y = eventState->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;

    getEventQueue()->mouseWarped(x,y);

    osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(_camera->getGraphicsContext());
    if (gw)
    {
        bool gw_invert_y = gw->getEventQueue()->getCurrentEventState()->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;

        x = x * float(gw->getTraits()->width) / (eventState->getXmax()-eventState->getXmin());
        y = y * float(gw->getTraits()->height) / (eventState->getYmax()-eventState->getYmin());

        if (view_invert_y != gw_invert_y) y = gw->getTraits()->height - y;

        gw->requestWarpPointer(x, y);

        return;
    }

    osg::Matrix masterCameraVPW = getCamera()->getViewMatrix() * getCamera()->getProjectionMatrix();

    x = (x - eventState->getXmin()) * 2.0 / (eventState->getXmax()-eventState->getXmin()) - 1.0;
    y = (y - eventState->getYmin())* 2.0 / (eventState->getYmax()-eventState->getYmin()) - 1.0;

    if (view_invert_y) y = - y;

    // osg::notify(osg::NOTICE)<<"  remapped ("<<x<<","<<y<<")"<<std::endl;;
    // osg::notify(osg::NOTICE)<<"  number of slaves = "<<getNumSlaves()<<std::endl;;

    double epsilon = 0.5;

    for(unsigned i=0; i<getNumSlaves(); ++i)
    {
        Slave& slave = getSlave(i);
        if (slave._camera.valid())
        {
            osg::Camera* camera = slave._camera.get();
            osg::Viewport* viewport = camera ? camera->getViewport() : 0;

            osg::Matrix localCameraVPW = camera->getViewMatrix() * camera->getProjectionMatrix();
            if (viewport) localCameraVPW *= viewport->computeWindowMatrix();

            osg::Matrix matrix( osg::Matrix::inverse(masterCameraVPW) * localCameraVPW );

            osg::Vec3d new_coord = osg::Vec3d(x,y,0.0) * matrix;

            // osg::notify(osg::NOTICE)<<"  new_coord "<<new_coord<<std::endl;;

            if (viewport &&
                new_coord.x() >= (viewport->x()-epsilon) && new_coord.y() >= (viewport->y()-epsilon) &&
                new_coord.x() < (viewport->x()+viewport->width()-1.0+epsilon) && new_coord.y() <= (viewport->y()+viewport->height()-1.0+epsilon) )
            {
                // osg::notify(osg::NOTICE)<<"  in viewport "<<std::endl;;

                gw = dynamic_cast<osgViewer::GraphicsWindow*>(camera->getGraphicsContext());
                if (gw)
                {
                    x = new_coord.x();
                    y = new_coord.y();

                    bool gw_invert_y = gw->getEventQueue()->getCurrentEventState()->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;

                    if (gw_invert_y) y = gw->getTraits()->height - y;

                    gw->requestWarpPointer(x, y);

                    return;
                }
            }
            else
            {
                // osg::notify(osg::NOTICE)<<"  not in viewport "<<viewport->x()<<" "<<(viewport->x()+viewport->width())<<std::endl;;
            }

        }
    }

    // osg::notify(osg::NOTICE)<<"  ** no warping applied. **"<<std::endl;

}
<|endoftext|>


<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "bitvector.h"
#include "allocatedbitvector.h"
#include "growablebitvector.h"
#include "partialbitvector.h"
#include <vespa/vespalib/hwaccelrated/iaccelrated.h>
#include <vespa/vespalib/util/exceptions.h>
#include <vespa/vespalib/util/size_literals.h>
#include <vespa/vespalib/objects/nbostream.h>
#include <vespa/fastos/file.h>
#include <cassert>

#include <vespa/log/log.h>
LOG_SETUP(".searchlib.common.bitvector");

using vespalib::make_string;
using vespalib::IllegalArgumentException;
using vespalib::hwaccelrated::IAccelrated;
using vespalib::Optimized;
using vespalib::alloc::Alloc;

namespace {

void verifyInclusiveStart(const search::BitVector & a, const search::BitVector & b) __attribute__((noinline));

void verifyInclusiveStart(const search::BitVector & a, const search::BitVector & b)
{
    if (a.getStartIndex() < b.getStartIndex()) {
        throw IllegalArgumentException(make_string("[%d, %d] starts before which is not allowed currently [%d, %d]",
                                                   a.getStartIndex(), a.size(), b.getStartIndex(), b.size()),
                                       VESPA_STRLOC);
    }
}

constexpr size_t MMAP_LIMIT = 16_Mi;
constexpr size_t DIRECTIO_ALIGNMENT = 4_Ki;

}

/////////////////////////////////
namespace search {

using vespalib::nbostream;
using vespalib::GenerationHeldBase;
using vespalib::GenerationHeldAlloc;
using vespalib::GenerationHolder;

Alloc
BitVector::allocatePaddedAndAligned(Index start, Index end, Index capacity)
{
    assert(capacity >= end);
    uint32_t words = numActiveWords(start, capacity);
    words += (-words & 15); // Pad to 64 byte alignment
    const size_t sz(words * sizeof(Word));
    Alloc alloc = Alloc::alloc(sz, MMAP_LIMIT);
    assert(alloc.size()/sizeof(Word) >= words);
    // Clear padding
    size_t usedBytes = numBytes(end - start);
    memset(static_cast<char *>(alloc.get()) + usedBytes, 0, alloc.size() - usedBytes);
    return alloc;
}

BitVector::BitVector(void * buf, Index start, Index end) :
    _words(static_cast<Word *>(buf) - wordNum(start)),
    _startOffset(start),
    _sz(end),
    _numTrueBits(invalidCount())
{
    assert((reinterpret_cast<size_t>(_words) & (sizeof(Word) - 1ul)) == 0);
}

void
BitVector::init(void * buf,  Index start, Index end)
{
    _words = static_cast<Word *>(buf) - wordNum(start);
    _startOffset = start;
    _sz = end;
    _numTrueBits = invalidCount();
}

void
BitVector::clear()
{
    memset(getActiveStart(), '\0', getActiveBytes());
    setBit(size()); // Guard bit
    setTrueBits(0);
}

void
BitVector::clearInterval(Index start, Index end)
{
    clearIntervalNoInvalidation(Range(start, end));

    invalidateCachedCount();
}

void
BitVector::clearIntervalNoInvalidation(Range range_in)
{
    Range range = sanitize(range_in);
    if ( ! range.validNonZero()) { return; }

    Index last = range.end() - 1;
    Index startw = wordNum(range.start());
    Index endw = wordNum(last);

    if (endw > startw) {
        _words[startw++] &= startBits(range.start());
        memset(_words+startw, 0, sizeof(*_words)*(endw-startw));
        _words[endw] &= endBits(last);
    } else {
        _words[startw] &= (startBits(range.start()) | endBits(last));
    }
}

void
BitVector::setInterval(Index start_in, Index end_in)
{
    Range range = sanitize(Range(start_in, end_in));
    if ( ! range.validNonZero()) { return; }

    Index last = range.end() - 1;
    Index startw = wordNum(range.start());
    Index endw = wordNum(last);

    if (endw > startw) {
        _words[startw++] |= checkTab(range.start());
        memset(_words + startw, 0xff, sizeof(*_words)*(endw-startw));
        _words[endw] |= ~endBits(last);
    } else {
        _words[startw] |= ~(startBits(range.start()) | endBits(last));
    }

    invalidateCachedCount();
}

BitVector::Index
BitVector::count() const
{
    return countInterval(Range(getStartIndex(), size()));
}

BitVector::Index
BitVector::countInterval(Range range_in) const
{
    Range range = sanitize(range_in);
    if ( ! range.validNonZero()) { return 0; }

    Index last = range.end() - 1;
    // Count bits in range [start..end>
    Index startw = wordNum(range.start());
    Index endw = wordNum(last);
    Word *bitValues = _words;

    if (startw == endw) {
        return Optimized::popCount(bitValues[startw] & ~(startBits(range.start()) | endBits(last)));
    }
    Index res = 0;
    // Limit to full words
    if ((range.start() & (WordLen - 1)) != 0) {
        res += Optimized::popCount(bitValues[startw] & ~startBits(range.start()));
        ++startw;
    }
    // Align start to 16 bytes
    while (startw < endw && (startw & 3) != 0) {
        res += Optimized::popCount(bitValues[startw]);
        ++startw;
    }
    bool partialEnd = (last & (WordLen - 1)) != (WordLen - 1);
    if (!partialEnd) {
        ++endw;
    }
    if (startw < endw) {
        res += IAccelrated::getAccelerator().populationCount(bitValues + startw, endw - startw);
    }
    if (partialEnd) {
        res += Optimized::popCount(bitValues[endw] & ~endBits(last));
    }

    return res;
}

void
BitVector::orWith(const BitVector & right)
{
    verifyInclusiveStart(*this, right);

    if (right.size() < size()) {
        if (right.size() > 0) {
            ssize_t commonBytes = numActiveBytes(getStartIndex(), right.size()) - sizeof(Word);
            if (commonBytes > 0) {
                IAccelrated::getAccelerator().orBit(getActiveStart(), right.getWordIndex(getStartIndex()), commonBytes);
            }
            Index last(right.size() - 1);
            getWordIndex(last)[0] |= (right.getWordIndex(last)[0] & ~endBits(last));
        }
    } else {
        IAccelrated::getAccelerator().orBit(getActiveStart(), right.getWordIndex(getStartIndex()), getActiveBytes());
    }
    repairEnds();
    invalidateCachedCount();
}

void
BitVector::repairEnds()
{
    if (size() != 0) {
        Index start(getStartIndex());
        Index last(size() - 1);
        getWordIndex(start)[0] &= ~startBits(start);
        getWordIndex(last)[0] &= ~endBits(last);
    }
    setGuardBit();
}

void
BitVector::andWith(const BitVector & right)
{
    verifyInclusiveStart(*this, right);

    uint32_t commonBytes = std::min(getActiveBytes(), numActiveBytes(getStartIndex(), right.size()));
    IAccelrated::getAccelerator().andBit(getActiveStart(), right.getWordIndex(getStartIndex()), commonBytes);
    if (right.size() < size()) {
        clearInterval(right.size(), size());
    }

    repairEnds();
    invalidateCachedCount();
}

void
BitVector::andNotWith(const BitVector& right)
{
    verifyInclusiveStart(*this, right);

    if (right.size() < size()) {
        if (right.size() > 0) {
            ssize_t commonBytes = numActiveBytes(getStartIndex(), right.size()) - sizeof(Word);
            if (commonBytes > 0) {
                IAccelrated::getAccelerator().andNotBit(getActiveStart(), right.getWordIndex(getStartIndex()), commonBytes);
            }
            Index last(right.size() - 1);
            getWordIndex(last)[0] &= ~(right.getWordIndex(last)[0] & ~endBits(last));
        }
    } else {
        IAccelrated::getAccelerator().andNotBit(getActiveStart(), right.getWordIndex(getStartIndex()), getActiveBytes());
    }

    repairEnds();
    invalidateCachedCount();
}

void
BitVector::notSelf() {
    IAccelrated::getAccelerator().notBit(getActiveStart(), getActiveBytes());
    setGuardBit();
    invalidateCachedCount();
}

bool
BitVector::operator==(const BitVector &rhs) const
{
    if ((size() != rhs.size()) || (getStartIndex() != rhs.getStartIndex())) {
        return false;
    }

    Index bitVectorSize = numActiveWords();
    const Word *words = getActiveStart();
    const Word *oWords = rhs.getActiveStart();
    for (Index i = 0; i < bitVectorSize; i++) {
        if (words[i] != oWords[i]) {
            return false;
        }
    }
    return true;
}

bool
BitVector::hasTrueBitsInternal() const
{
    Index bitVectorSizeL1(numActiveWords() - 1);
    const Word *words(getActiveStart());
    for (Index i = 0; i < bitVectorSizeL1; i++) {
        if (words[i] != 0) {
            return true;
        }
    }

    // Ignore guard bit.
    if ((words[bitVectorSizeL1] & ~mask(size())) != 0)
        return true;

    return false;
}

//////////////////////////////////////////////////////////////////////
// Set new length. Destruction of content
//////////////////////////////////////////////////////////////////////
void
BitVector::resize(Index)
{
    LOG_ABORT("should not be reached");
}
GenerationHeldBase::UP
BitVector::grow(Index, Index )
{
    LOG_ABORT("should not be reached");
}

size_t
BitVector::getFileBytes(Index bits)
{
    Index bytes = numBytes(bits);
    bytes += (-bytes & (getAlignment() - 1));
    return bytes;
}

class MMappedBitVector : public BitVector
{
public:
    MMappedBitVector(Index numberOfElements, FastOS_FileInterface &file,
                     int64_t offset, Index doccount);

private:
    void read(Index numberOfElements, FastOS_FileInterface &file,
              int64_t offset, Index doccount);
};

BitVector::UP
BitVector::create(Index numberOfElements, FastOS_FileInterface &file,
                  int64_t offset, Index doccount)
{
    UP bv;
    if (file.IsMemoryMapped()) {
        bv = std::make_unique<MMappedBitVector>(numberOfElements, file, offset, doccount);
    } else {
        size_t padbefore, padafter;
        size_t vectorsize = getFileBytes(numberOfElements);
        file.DirectIOPadding(offset, vectorsize, padbefore, padafter);
        assert((padbefore & (getAlignment() - 1)) == 0);
        AllocatedBitVector::Alloc alloc = Alloc::alloc(padbefore + vectorsize + padafter, MMAP_LIMIT, DIRECTIO_ALIGNMENT);
        void * alignedBuffer = alloc.get();
        file.ReadBuf(alignedBuffer, alloc.size(), offset - padbefore);
        bv = std::make_unique<AllocatedBitVector>(numberOfElements, std::move(alloc), padbefore);
        bv->setTrueBits(doccount);
        // Check guard bit for getNextTrueBit()
        assert(bv->testBit(bv->size()));
    }
    return bv;
}

BitVector::UP
BitVector::create(Index start, Index end)
{
    return (start == 0)
           ? create(end)
           : std::make_unique<PartialBitVector>(start, end);
}

BitVector::UP
BitVector::create(const BitVector & org, Index start, Index end)
{
    return ((start == 0) && (end == org.size()) && (org.getStartIndex() == 0))
           ? create(org)
           : std::make_unique<PartialBitVector>(org, start, end);
}

BitVector::UP
BitVector::create(Index numberOfElements)
{
    return std::make_unique<AllocatedBitVector>(numberOfElements);
}

BitVector::UP
BitVector::create(const BitVector & rhs)
{
    return std::make_unique<AllocatedBitVector>(rhs);
}

BitVector::UP
BitVector::create(Index numberOfElements, Index newCapacity, GenerationHolder &generationHolder)
{
    return std::make_unique<GrowableBitVector>(numberOfElements, newCapacity, generationHolder);
}

MMappedBitVector::MMappedBitVector(Index numberOfElements, FastOS_FileInterface &file,
                                   int64_t offset, Index doccount) :
    BitVector()
{
    read(numberOfElements, file, offset, doccount);
}

void
MMappedBitVector::read(Index numberOfElements, FastOS_FileInterface &file,
                       int64_t offset, Index doccount)
{
    assert((offset & (getAlignment() - 1)) == 0);
    void *mapptr = file.MemoryMapPtr(offset);
    assert(mapptr != nullptr);
    if (mapptr != nullptr) {
        init(mapptr, 0, numberOfElements);
    }
    setTrueBits(doccount);
}

nbostream &
operator<<(nbostream &out, const BitVector &bv)
{
    uint64_t size = bv.size();
    uint64_t cachedHits = bv.countTrueBits();
    uint64_t fileBytes = bv.getFileBytes();
    assert(size <= std::numeric_limits<BitVector::Index>::max());
    assert(cachedHits <= size || ! bv.isValidCount(cachedHits));
    assert(bv.testBit(size));
    out << size << cachedHits << fileBytes;
    out.write(bv.getStart(), bv.getFileBytes());
    return out;
}

nbostream &
operator>>(nbostream &in, BitVector &bv)
{
    uint64_t size;
    uint64_t cachedHits;
    uint64_t fileBytes;
    in >> size >> cachedHits >> fileBytes;
    assert(size <= std::numeric_limits<BitVector::Index>::max());
    assert(cachedHits <= size || ! bv.isValidCount(cachedHits));
    if (bv.size() != size)
        bv.resize(size);
    assert(bv.getFileBytes() == fileBytes);
    in.read(bv.getStart(), bv.getFileBytes());
    assert(bv.testBit(size));
    bv.setTrueBits(cachedHits);
    return in;
}

} // namespace search
<commit_msg>Use 32M which is the same limit used in some other query related places.<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "bitvector.h"
#include "allocatedbitvector.h"
#include "growablebitvector.h"
#include "partialbitvector.h"
#include <vespa/vespalib/hwaccelrated/iaccelrated.h>
#include <vespa/vespalib/util/exceptions.h>
#include <vespa/vespalib/util/size_literals.h>
#include <vespa/vespalib/objects/nbostream.h>
#include <vespa/fastos/file.h>
#include <cassert>

#include <vespa/log/log.h>
LOG_SETUP(".searchlib.common.bitvector");

using vespalib::make_string;
using vespalib::IllegalArgumentException;
using vespalib::hwaccelrated::IAccelrated;
using vespalib::Optimized;
using vespalib::alloc::Alloc;

namespace {

void verifyInclusiveStart(const search::BitVector & a, const search::BitVector & b) __attribute__((noinline));

void verifyInclusiveStart(const search::BitVector & a, const search::BitVector & b)
{
    if (a.getStartIndex() < b.getStartIndex()) {
        throw IllegalArgumentException(make_string("[%d, %d] starts before which is not allowed currently [%d, %d]",
                                                   a.getStartIndex(), a.size(), b.getStartIndex(), b.size()),
                                       VESPA_STRLOC);
    }
}

constexpr size_t MMAP_LIMIT = 32_Mi;
constexpr size_t DIRECTIO_ALIGNMENT = 4_Ki;

}

/////////////////////////////////
namespace search {

using vespalib::nbostream;
using vespalib::GenerationHeldBase;
using vespalib::GenerationHeldAlloc;
using vespalib::GenerationHolder;

Alloc
BitVector::allocatePaddedAndAligned(Index start, Index end, Index capacity)
{
    assert(capacity >= end);
    uint32_t words = numActiveWords(start, capacity);
    words += (-words & 15); // Pad to 64 byte alignment
    const size_t sz(words * sizeof(Word));
    Alloc alloc = Alloc::alloc(sz, MMAP_LIMIT);
    assert(alloc.size()/sizeof(Word) >= words);
    // Clear padding
    size_t usedBytes = numBytes(end - start);
    memset(static_cast<char *>(alloc.get()) + usedBytes, 0, alloc.size() - usedBytes);
    return alloc;
}

BitVector::BitVector(void * buf, Index start, Index end) :
    _words(static_cast<Word *>(buf) - wordNum(start)),
    _startOffset(start),
    _sz(end),
    _numTrueBits(invalidCount())
{
    assert((reinterpret_cast<size_t>(_words) & (sizeof(Word) - 1ul)) == 0);
}

void
BitVector::init(void * buf,  Index start, Index end)
{
    _words = static_cast<Word *>(buf) - wordNum(start);
    _startOffset = start;
    _sz = end;
    _numTrueBits = invalidCount();
}

void
BitVector::clear()
{
    memset(getActiveStart(), '\0', getActiveBytes());
    setBit(size()); // Guard bit
    setTrueBits(0);
}

void
BitVector::clearInterval(Index start, Index end)
{
    clearIntervalNoInvalidation(Range(start, end));

    invalidateCachedCount();
}

void
BitVector::clearIntervalNoInvalidation(Range range_in)
{
    Range range = sanitize(range_in);
    if ( ! range.validNonZero()) { return; }

    Index last = range.end() - 1;
    Index startw = wordNum(range.start());
    Index endw = wordNum(last);

    if (endw > startw) {
        _words[startw++] &= startBits(range.start());
        memset(_words+startw, 0, sizeof(*_words)*(endw-startw));
        _words[endw] &= endBits(last);
    } else {
        _words[startw] &= (startBits(range.start()) | endBits(last));
    }
}

void
BitVector::setInterval(Index start_in, Index end_in)
{
    Range range = sanitize(Range(start_in, end_in));
    if ( ! range.validNonZero()) { return; }

    Index last = range.end() - 1;
    Index startw = wordNum(range.start());
    Index endw = wordNum(last);

    if (endw > startw) {
        _words[startw++] |= checkTab(range.start());
        memset(_words + startw, 0xff, sizeof(*_words)*(endw-startw));
        _words[endw] |= ~endBits(last);
    } else {
        _words[startw] |= ~(startBits(range.start()) | endBits(last));
    }

    invalidateCachedCount();
}

BitVector::Index
BitVector::count() const
{
    return countInterval(Range(getStartIndex(), size()));
}

BitVector::Index
BitVector::countInterval(Range range_in) const
{
    Range range = sanitize(range_in);
    if ( ! range.validNonZero()) { return 0; }

    Index last = range.end() - 1;
    // Count bits in range [start..end>
    Index startw = wordNum(range.start());
    Index endw = wordNum(last);
    Word *bitValues = _words;

    if (startw == endw) {
        return Optimized::popCount(bitValues[startw] & ~(startBits(range.start()) | endBits(last)));
    }
    Index res = 0;
    // Limit to full words
    if ((range.start() & (WordLen - 1)) != 0) {
        res += Optimized::popCount(bitValues[startw] & ~startBits(range.start()));
        ++startw;
    }
    // Align start to 16 bytes
    while (startw < endw && (startw & 3) != 0) {
        res += Optimized::popCount(bitValues[startw]);
        ++startw;
    }
    bool partialEnd = (last & (WordLen - 1)) != (WordLen - 1);
    if (!partialEnd) {
        ++endw;
    }
    if (startw < endw) {
        res += IAccelrated::getAccelerator().populationCount(bitValues + startw, endw - startw);
    }
    if (partialEnd) {
        res += Optimized::popCount(bitValues[endw] & ~endBits(last));
    }

    return res;
}

void
BitVector::orWith(const BitVector & right)
{
    verifyInclusiveStart(*this, right);

    if (right.size() < size()) {
        if (right.size() > 0) {
            ssize_t commonBytes = numActiveBytes(getStartIndex(), right.size()) - sizeof(Word);
            if (commonBytes > 0) {
                IAccelrated::getAccelerator().orBit(getActiveStart(), right.getWordIndex(getStartIndex()), commonBytes);
            }
            Index last(right.size() - 1);
            getWordIndex(last)[0] |= (right.getWordIndex(last)[0] & ~endBits(last));
        }
    } else {
        IAccelrated::getAccelerator().orBit(getActiveStart(), right.getWordIndex(getStartIndex()), getActiveBytes());
    }
    repairEnds();
    invalidateCachedCount();
}

void
BitVector::repairEnds()
{
    if (size() != 0) {
        Index start(getStartIndex());
        Index last(size() - 1);
        getWordIndex(start)[0] &= ~startBits(start);
        getWordIndex(last)[0] &= ~endBits(last);
    }
    setGuardBit();
}

void
BitVector::andWith(const BitVector & right)
{
    verifyInclusiveStart(*this, right);

    uint32_t commonBytes = std::min(getActiveBytes(), numActiveBytes(getStartIndex(), right.size()));
    IAccelrated::getAccelerator().andBit(getActiveStart(), right.getWordIndex(getStartIndex()), commonBytes);
    if (right.size() < size()) {
        clearInterval(right.size(), size());
    }

    repairEnds();
    invalidateCachedCount();
}

void
BitVector::andNotWith(const BitVector& right)
{
    verifyInclusiveStart(*this, right);

    if (right.size() < size()) {
        if (right.size() > 0) {
            ssize_t commonBytes = numActiveBytes(getStartIndex(), right.size()) - sizeof(Word);
            if (commonBytes > 0) {
                IAccelrated::getAccelerator().andNotBit(getActiveStart(), right.getWordIndex(getStartIndex()), commonBytes);
            }
            Index last(right.size() - 1);
            getWordIndex(last)[0] &= ~(right.getWordIndex(last)[0] & ~endBits(last));
        }
    } else {
        IAccelrated::getAccelerator().andNotBit(getActiveStart(), right.getWordIndex(getStartIndex()), getActiveBytes());
    }

    repairEnds();
    invalidateCachedCount();
}

void
BitVector::notSelf() {
    IAccelrated::getAccelerator().notBit(getActiveStart(), getActiveBytes());
    setGuardBit();
    invalidateCachedCount();
}

bool
BitVector::operator==(const BitVector &rhs) const
{
    if ((size() != rhs.size()) || (getStartIndex() != rhs.getStartIndex())) {
        return false;
    }

    Index bitVectorSize = numActiveWords();
    const Word *words = getActiveStart();
    const Word *oWords = rhs.getActiveStart();
    for (Index i = 0; i < bitVectorSize; i++) {
        if (words[i] != oWords[i]) {
            return false;
        }
    }
    return true;
}

bool
BitVector::hasTrueBitsInternal() const
{
    Index bitVectorSizeL1(numActiveWords() - 1);
    const Word *words(getActiveStart());
    for (Index i = 0; i < bitVectorSizeL1; i++) {
        if (words[i] != 0) {
            return true;
        }
    }

    // Ignore guard bit.
    if ((words[bitVectorSizeL1] & ~mask(size())) != 0)
        return true;

    return false;
}

//////////////////////////////////////////////////////////////////////
// Set new length. Destruction of content
//////////////////////////////////////////////////////////////////////
void
BitVector::resize(Index)
{
    LOG_ABORT("should not be reached");
}
GenerationHeldBase::UP
BitVector::grow(Index, Index )
{
    LOG_ABORT("should not be reached");
}

size_t
BitVector::getFileBytes(Index bits)
{
    Index bytes = numBytes(bits);
    bytes += (-bytes & (getAlignment() - 1));
    return bytes;
}

class MMappedBitVector : public BitVector
{
public:
    MMappedBitVector(Index numberOfElements, FastOS_FileInterface &file,
                     int64_t offset, Index doccount);

private:
    void read(Index numberOfElements, FastOS_FileInterface &file,
              int64_t offset, Index doccount);
};

BitVector::UP
BitVector::create(Index numberOfElements, FastOS_FileInterface &file,
                  int64_t offset, Index doccount)
{
    UP bv;
    if (file.IsMemoryMapped()) {
        bv = std::make_unique<MMappedBitVector>(numberOfElements, file, offset, doccount);
    } else {
        size_t padbefore, padafter;
        size_t vectorsize = getFileBytes(numberOfElements);
        file.DirectIOPadding(offset, vectorsize, padbefore, padafter);
        assert((padbefore & (getAlignment() - 1)) == 0);
        AllocatedBitVector::Alloc alloc = Alloc::alloc(padbefore + vectorsize + padafter, MMAP_LIMIT, DIRECTIO_ALIGNMENT);
        void * alignedBuffer = alloc.get();
        file.ReadBuf(alignedBuffer, alloc.size(), offset - padbefore);
        bv = std::make_unique<AllocatedBitVector>(numberOfElements, std::move(alloc), padbefore);
        bv->setTrueBits(doccount);
        // Check guard bit for getNextTrueBit()
        assert(bv->testBit(bv->size()));
    }
    return bv;
}

BitVector::UP
BitVector::create(Index start, Index end)
{
    return (start == 0)
           ? create(end)
           : std::make_unique<PartialBitVector>(start, end);
}

BitVector::UP
BitVector::create(const BitVector & org, Index start, Index end)
{
    return ((start == 0) && (end == org.size()) && (org.getStartIndex() == 0))
           ? create(org)
           : std::make_unique<PartialBitVector>(org, start, end);
}

BitVector::UP
BitVector::create(Index numberOfElements)
{
    return std::make_unique<AllocatedBitVector>(numberOfElements);
}

BitVector::UP
BitVector::create(const BitVector & rhs)
{
    return std::make_unique<AllocatedBitVector>(rhs);
}

BitVector::UP
BitVector::create(Index numberOfElements, Index newCapacity, GenerationHolder &generationHolder)
{
    return std::make_unique<GrowableBitVector>(numberOfElements, newCapacity, generationHolder);
}

MMappedBitVector::MMappedBitVector(Index numberOfElements, FastOS_FileInterface &file,
                                   int64_t offset, Index doccount) :
    BitVector()
{
    read(numberOfElements, file, offset, doccount);
}

void
MMappedBitVector::read(Index numberOfElements, FastOS_FileInterface &file,
                       int64_t offset, Index doccount)
{
    assert((offset & (getAlignment() - 1)) == 0);
    void *mapptr = file.MemoryMapPtr(offset);
    assert(mapptr != nullptr);
    if (mapptr != nullptr) {
        init(mapptr, 0, numberOfElements);
    }
    setTrueBits(doccount);
}

nbostream &
operator<<(nbostream &out, const BitVector &bv)
{
    uint64_t size = bv.size();
    uint64_t cachedHits = bv.countTrueBits();
    uint64_t fileBytes = bv.getFileBytes();
    assert(size <= std::numeric_limits<BitVector::Index>::max());
    assert(cachedHits <= size || ! bv.isValidCount(cachedHits));
    assert(bv.testBit(size));
    out << size << cachedHits << fileBytes;
    out.write(bv.getStart(), bv.getFileBytes());
    return out;
}

nbostream &
operator>>(nbostream &in, BitVector &bv)
{
    uint64_t size;
    uint64_t cachedHits;
    uint64_t fileBytes;
    in >> size >> cachedHits >> fileBytes;
    assert(size <= std::numeric_limits<BitVector::Index>::max());
    assert(cachedHits <= size || ! bv.isValidCount(cachedHits));
    if (bv.size() != size)
        bv.resize(size);
    assert(bv.getFileBytes() == fileBytes);
    in.read(bv.getStart(), bv.getFileBytes());
    assert(bv.testBit(size));
    bv.setTrueBits(cachedHits);
    return in;
}

} // namespace search
<|endoftext|>


<commit_before>/**
* Benchmark Boost `expm1`.
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real_distribution.hpp>
#include <boost/math/special_functions/gamma.hpp>

using boost::random::uniform_real_distribution;
using boost::random::mt19937;

#define NAME "expm1"
#define ITERATIONS 1000000
#define REPEATS 3

/**
* Prints the TAP version.
*/
void print_version() {
	printf( "TAP version 13\n" );
}

/**
* Prints the TAP summary.
*
* @param total     total number of tests
* @param passing   total number of passing tests
*/
void print_summary( int total, int passing ) {
	printf( "#\n" );
	printf( "1..%d\n", total ); // TAP plan
	printf( "# total %d\n", total );
	printf( "# pass  %d\n", passing );
	printf( "#\n" );
	printf( "# ok\n" );
}

/**
* Prints benchmarks results.
*
* @param elapsed   elapsed time in seconds
*/
void print_results( double elapsed ) {
	double rate = (double)ITERATIONS / elapsed;
	printf( "  ---\n" );
	printf( "  iterations: %d\n", ITERATIONS );
	printf( "  elapsed: %0.9f\n", elapsed );
	printf( "  rate: %0.9f\n", rate );
	printf( "  ...\n" );
}

/**
* Returns a clock time.
*
* @return clock time
*/
double tic() {
	struct timeval now;
	gettimeofday( &now, NULL );
	return (double)now.tv_sec + (double)now.tv_usec/1.0e6;
}

/**
* Runs a benchmark.
*
* @return elapsed time in seconds
*/
double benchmark() {
	double elapsed;
	double x;
	double y;
	double t;
	int i;

	// Define a new pseudorandom number generator:
	mt19937 rng;

	// Define a uniform distribution for generating pseudorandom numbers as "doubles" between a minimum value (inclusive) and a maximum value (exclusive):
	uniform_real_distribution<> randu( -5.0, 5.0 );

	t = tic();
	for ( i = 0; i < ITERATIONS; i++ ) {
		x = randu( rng ) + 2.0 - 4.0;
		y = boost::math::gamma1pm1( x );
		if ( y != y ) {
			printf( "should not return NaN\n" );
			break;
		}
	}
	elapsed = tic() - t;
	if ( y != y ) {
		printf( "should not return NaN\n" );
	}
	return elapsed;
}

/**
* Main execution sequence.
*/
int main( void ) {
	double elapsed;
	int i;

	print_version();
	for ( i = 0; i < REPEATS; i++ ) {
		printf( "# cpp::boost::%s\n", NAME );
		elapsed = benchmark();
		print_results( elapsed );
		printf( "ok %d benchmark finished\n", i+1 );
	}
	print_summary( REPEATS, REPEATS );
	return 0;
}
<commit_msg>Fix copy-paste error and generated values<commit_after>/**
* Benchmark Boost `gamma1pm1`.
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real_distribution.hpp>
#include <boost/math/special_functions/gamma.hpp>

using boost::random::uniform_real_distribution;
using boost::random::mt19937;

#define NAME "gamma1pm1"
#define ITERATIONS 1000000
#define REPEATS 3

/**
* Prints the TAP version.
*/
void print_version() {
	printf( "TAP version 13\n" );
}

/**
* Prints the TAP summary.
*
* @param total     total number of tests
* @param passing   total number of passing tests
*/
void print_summary( int total, int passing ) {
	printf( "#\n" );
	printf( "1..%d\n", total ); // TAP plan
	printf( "# total %d\n", total );
	printf( "# pass  %d\n", passing );
	printf( "#\n" );
	printf( "# ok\n" );
}

/**
* Prints benchmarks results.
*
* @param elapsed   elapsed time in seconds
*/
void print_results( double elapsed ) {
	double rate = (double)ITERATIONS / elapsed;
	printf( "  ---\n" );
	printf( "  iterations: %d\n", ITERATIONS );
	printf( "  elapsed: %0.9f\n", elapsed );
	printf( "  rate: %0.9f\n", rate );
	printf( "  ...\n" );
}

/**
* Returns a clock time.
*
* @return clock time
*/
double tic() {
	struct timeval now;
	gettimeofday( &now, NULL );
	return (double)now.tv_sec + (double)now.tv_usec/1.0e6;
}

/**
* Runs a benchmark.
*
* @return elapsed time in seconds
*/
double benchmark() {
	double elapsed;
	double x;
	double y;
	double t;
	int i;

	// Define a new pseudorandom number generator:
	mt19937 rng;

	// Define a uniform distribution for generating pseudorandom numbers as "doubles" between a minimum value (inclusive) and a maximum value (exclusive):
	uniform_real_distribution<> randu( -5.0, 5.0 );

	t = tic();
	for ( i = 0; i < ITERATIONS; i++ ) {
		x = randu( rng );
		y = boost::math::gamma1pm1( x );
		if ( y != y ) {
			printf( "should not return NaN\n" );
			break;
		}
	}
	elapsed = tic() - t;
	if ( y != y ) {
		printf( "should not return NaN\n" );
	}
	return elapsed;
}

/**
* Main execution sequence.
*/
int main( void ) {
	double elapsed;
	int i;

	print_version();
	for ( i = 0; i < REPEATS; i++ ) {
		printf( "# cpp::boost::%s\n", NAME );
		elapsed = benchmark();
		print_results( elapsed );
		printf( "ok %d benchmark finished\n", i+1 );
	}
	print_summary( REPEATS, REPEATS );
	return 0;
}
<|endoftext|>


<commit_before>class Solution {
public:
    int minDistance(string word1, string word2) {
        int m = word1.length(), n = word2.length();
        vector<vector<int> > dp(m+1, vector<int>(n+1));
        for (int i = 0; i <= m; ++i) {
            for (int j = 0; j <= n; ++j) {
                if(i == 0){
                    dp[i][j] = j;
                }else if(j == 0){
                    dp[i][j] = i;
                }else{
                    dp[i][j] = min(dp[i-1][j-1] + ((word1[i-1] == word2[j-1])?0:1), min(dp[i][j-1]+1, dp[i-1][j]+1));
                }
            }
        }
        return dp[m][n];
    }
};<commit_msg>reduce space for problem 72<commit_after>class Solution {
public:
    int minDistance(string word1, string word2) {
        int m = word1.length(), n = word2.length();
        vector<int> dp(n+1);
        for (int i = 0; i <= m; ++i) {
            int last;
            for (int j = 0; j <= n; ++j) {
                if(i == 0){
                    dp[j] = j;
                }else if(j == 0){
                    last = dp[j];
                    dp[j] = i;
                }else{
                    int temp = dp[j];
                    dp[j] = min(last + ((word1[i-1] == word2[j-1])?0:1), min(dp[j-1]+1, dp[j]+1));
                    last = temp;
                }
            }
        }
        return dp[n];
    }
};<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (C) 2006 by FThauer FHammer   *
 *   f.thauer@web.de   *
 *                                                                         *
 *   This program 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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "joinnetworkgamedialogimpl.h"
#include "session.h"
#include "configfile.h"
#include "tinyxml.h"

using namespace std;

joinNetworkGameDialogImpl::joinNetworkGameDialogImpl(QWidget *parent)
      : QDialog(parent)
{

    setupUi(this);

	//Profile Name darf nicht mit einer Zahl beginnen --> XML konform
	QRegExp rx("[A-Z|a-z]+[A-Z|a-z|\\d]*");
 	QValidator *validator = new QRegExpValidator(rx, this);
 	lineEdit_profileName->setValidator(validator);

	pushButton_delete->setDisabled(TRUE);

	lineEdit_ipAddress->setFocus();

	myServerProfilesFile = myConfig.readConfigString("DataDir")+"serverprofiles.xml";

	//Anlegen wenn noch nicht existiert!
	QFile serverProfilesfile(QString::fromUtf8(myServerProfilesFile.c_str()));

	if(!serverProfilesfile.exists()) {

		TiXmlDocument doc;
		TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "UTF-8", "");
		doc.LinkEndChild( decl );

		TiXmlElement * root = new TiXmlElement( "PokerTH" );
		doc.LinkEndChild( root );

		TiXmlElement * profiles = new TiXmlElement( "ServerProfiles" );
		root->LinkEndChild( profiles );

		doc.SaveFile( myServerProfilesFile );
	}

	//Liste Füllen
	fillServerProfileList();

// 	QShortcut *connectKey = new QShortcut(QKeySequence(Qt::Key_Enter), this);
// 	connect( connectKey, SIGNAL(activated() ), pushButton_connect, SLOT( click() ) );

	connect( pushButton_connect, SIGNAL( clicked() ), this, SLOT( startClient() ) );
	connect( pushButton_save, SIGNAL( clicked() ), this, SLOT( saveServerProfile() ) );
	connect( pushButton_delete, SIGNAL( clicked() ), this, SLOT( deleteServerProfile() ) );

	connect( treeWidget, SIGNAL( itemClicked ( QTreeWidgetItem*, int) ), this, SLOT( itemFillForm (QTreeWidgetItem*, int) ) );

}

void joinNetworkGameDialogImpl::startClient() {

	// TODO: Check input values!
}

void joinNetworkGameDialogImpl::fillServerProfileList() {

	treeWidget->clear();

	TiXmlDocument doc(myServerProfilesFile);
	if(!doc.LoadFile()) {
		QMessageBox::warning(this, tr("Load Server-Profile-File Error"),
			tr("Could not load server-profiles-file:\n"+QString::fromUtf8(myServerProfilesFile.c_str()).toAscii()),
			QMessageBox::Close);
	}
	TiXmlHandle docHandle( &doc );

	TiXmlElement* profile = docHandle.FirstChild( "PokerTH" ).FirstChild( "ServerProfiles" ).FirstChild().ToElement();
	if ( profile ) {

                for( profile; profile; profile = profile->NextSiblingElement()) {

		   	QTreeWidgetItem *item = new QTreeWidgetItem(treeWidget,0);
			item->setData(0, 0, profile->Attribute("Name"));
			item->setData(1, 0, profile->Attribute("Address"));
			item->setData(2, 0, profile->Attribute("Port"));

			string isIpv6 = "no";
			int tempInt = 0;
			profile->QueryIntAttribute("IsIpv6", &tempInt );
			if( tempInt == 1 ) { isIpv6 = "yes"; }
			item->setData(3, 0, QString::fromUtf8(isIpv6.c_str()));

			treeWidget->addTopLevelItem(item);
		}
	}
	else { cout << "No Profiles Found \n";  }

	treeWidget->resizeColumnToContents ( 0 );
	treeWidget->resizeColumnToContents ( 1 );
	treeWidget->resizeColumnToContents ( 2 );
	treeWidget->resizeColumnToContents ( 3 );
}

void joinNetworkGameDialogImpl::itemFillForm (QTreeWidgetItem* item, int column) {

	bool toIntTrue;

	TiXmlDocument doc(myServerProfilesFile);
	if(!doc.LoadFile()) {
		QMessageBox::warning(this, tr("Load Server-Profile-File Error"),
			tr("Could not load server-profiles-file:\n"+QString::fromUtf8(myServerProfilesFile.c_str()).toAscii()),
			QMessageBox::Close);
	}
	TiXmlHandle docHandle( &doc );

	TiXmlElement* profile = docHandle.FirstChild( "PokerTH" ).FirstChild( "ServerProfiles" ).FirstChild( item->data(0,0).toString().toStdString() ).ToElement();
	if ( profile ) {

        	lineEdit_profileName->setText(QString::fromUtf8(profile->Attribute("Name")));
		lineEdit_ipAddress->setText(QString::fromUtf8(profile->Attribute("Address")));
		lineEdit_password->setText(QString::fromUtf8(profile->Attribute("Password")));
		spinBox_port->setValue(QString::fromUtf8(profile->Attribute("Port")).toInt(&toIntTrue, 10));
		checkBox_ipv6->setChecked(QString::fromUtf8(profile->Attribute("IsIpv6")).toInt(&toIntTrue, 10));

	}

	pushButton_delete->setEnabled(TRUE);
}

void joinNetworkGameDialogImpl::saveServerProfile() {

// 	bool toIntTrue;

	TiXmlDocument doc(myServerProfilesFile);
	if(!doc.LoadFile()) {
		QMessageBox::warning(this, tr("Load Server-Profile-File Error"),
			tr("Could not load server-profiles-file:\n"+QString::fromUtf8(myServerProfilesFile.c_str()).toAscii()),
			QMessageBox::Close);
	}
	TiXmlHandle docHandle( &doc );

	TiXmlElement* profiles = docHandle.FirstChild( "PokerTH" ).FirstChild( "ServerProfiles" ).ToElement();
	if ( profiles ) {

		TiXmlElement * testProfile = docHandle.FirstChild( "PokerTH" ).FirstChild( "ServerProfiles" ).FirstChild( lineEdit_profileName->text().toStdString() ).ToElement();

		if( testProfile ) {
			// Wenn der Name schon existiert --> Überschreiben?
			QMessageBox msgBox(QMessageBox::Warning, tr("Save Server Profile Error"),
				tr("A profile with the name: \""+lineEdit_profileName->text().toAscii()+"\" already exists.\nWould you like to overwrite ?"), QMessageBox::Yes | QMessageBox::No, this);
			switch (msgBox.exec()) {

				case QMessageBox::Yes: {
					// yes was clicked
					// remove the old
					testProfile->Parent()->RemoveChild(testProfile);
					// write the new
					TiXmlElement * profile1 = new TiXmlElement( lineEdit_profileName->text().toStdString() );
					profiles->LinkEndChild( profile1 );
					profile1->SetAttribute("Name", lineEdit_profileName->text().toStdString());
					profile1->SetAttribute("Address", lineEdit_ipAddress->text().toStdString());
					profile1->SetAttribute("Password", lineEdit_password->text().toStdString());
					profile1->SetAttribute("Port", spinBox_port->value());
					profile1->SetAttribute("IsIpv6", checkBox_ipv6->isChecked());
				}
				break;
				case QMessageBox::No:
				// no was clicked
				break;
				default:
				// should never be reached
				break;
			}

		}
		else {
			// Wenn der Name nicht existiert --> speichern
			TiXmlElement * profile2 = new TiXmlElement( lineEdit_profileName->text().toStdString() );
			profiles->LinkEndChild( profile2 );
			profile2->SetAttribute("Name", lineEdit_profileName->text().toStdString());
			profile2->SetAttribute("Address", lineEdit_ipAddress->text().toStdString());
			profile2->SetAttribute("Password", lineEdit_password->text().toStdString());
			profile2->SetAttribute("Port", spinBox_port->value());
			profile2->SetAttribute("IsIpv6", checkBox_ipv6->isChecked());

		}
        }
	else { QMessageBox::warning(this, tr("Read Server-Profile List Error"),
			tr("Could not read server-profiles list"),
			QMessageBox::Close);	 }

	if(!doc.SaveFile()) {	QMessageBox::warning(this, tr("Save Server-Profile-File Error"),
			tr("Could not save server-profiles-file:\n"+QString::fromUtf8(myServerProfilesFile.c_str()).toAscii()),
			QMessageBox::Close);	 }

	fillServerProfileList();
}

void joinNetworkGameDialogImpl::deleteServerProfile() {

	TiXmlDocument doc(myServerProfilesFile);
	if(!doc.LoadFile()) {
		QMessageBox::warning(this, tr("Load Server-Profile-File Error"),
			tr("Could not load server-profiles-file:\n"+QString::fromUtf8(myServerProfilesFile.c_str()).toAscii()),
			QMessageBox::Close);
	}
	else {
		TiXmlHandle docHandle( &doc );

		TiXmlElement* profile = docHandle.FirstChild( "PokerTH" ).FirstChild( "ServerProfiles" ).FirstChild( treeWidget->currentItem()->data(0,0).toString().toStdString() ).ToElement();

		if ( profile ) { profile->Parent()->RemoveChild(profile); }

		if(!doc.SaveFile()) {	QMessageBox::warning(this, tr("Save Server-Profile-File Error"),
			tr("Could not save server-profiles-file:\n"+QString::fromUtf8(myServerProfilesFile.c_str()).toAscii()),
			QMessageBox::Close);	 }

		//Liste Füllen
		fillServerProfileList();
	}

	pushButton_delete->setDisabled(TRUE);
}

void joinNetworkGameDialogImpl::keyPressEvent ( QKeyEvent * event ) {

// 	std::cout << "key" << event->key();
	if (event->key() == 16777220) { pushButton_connect->click(); } //ENTER
}
<commit_msg>Fixed server profile file names for utf-8 support.<commit_after>/***************************************************************************
 *   Copyright (C) 2006 by FThauer FHammer   *
 *   f.thauer@web.de   *
 *                                                                         *
 *   This program 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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "joinnetworkgamedialogimpl.h"
#include "session.h"
#include "configfile.h"
#include "tinyxml.h"

using namespace std;

joinNetworkGameDialogImpl::joinNetworkGameDialogImpl(QWidget *parent)
      : QDialog(parent)
{

    setupUi(this);

	//Profile Name darf nicht mit einer Zahl beginnen --> XML konform
	QRegExp rx("[A-Z|a-z]+[A-Z|a-z|\\d]*");
 	QValidator *validator = new QRegExpValidator(rx, this);
 	lineEdit_profileName->setValidator(validator);

	pushButton_delete->setDisabled(TRUE);

	lineEdit_ipAddress->setFocus();

	myServerProfilesFile = myConfig.readConfigString("DataDir")+"serverprofiles.xml";

	//Anlegen wenn noch nicht existiert!
	QFile serverProfilesfile(QString::fromUtf8(myServerProfilesFile.c_str()));

	if(!serverProfilesfile.exists()) {

		TiXmlDocument doc;
		TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "UTF-8", "");
		doc.LinkEndChild( decl );

		TiXmlElement * root = new TiXmlElement( "PokerTH" );
		doc.LinkEndChild( root );

		TiXmlElement * profiles = new TiXmlElement( "ServerProfiles" );
		root->LinkEndChild( profiles );

		doc.SaveFile( QString::fromUtf8(myServerProfilesFile.c_str()).toStdString() );
	}

	//Liste Füllen
	fillServerProfileList();

// 	QShortcut *connectKey = new QShortcut(QKeySequence(Qt::Key_Enter), this);
// 	connect( connectKey, SIGNAL(activated() ), pushButton_connect, SLOT( click() ) );

	connect( pushButton_connect, SIGNAL( clicked() ), this, SLOT( startClient() ) );
	connect( pushButton_save, SIGNAL( clicked() ), this, SLOT( saveServerProfile() ) );
	connect( pushButton_delete, SIGNAL( clicked() ), this, SLOT( deleteServerProfile() ) );

	connect( treeWidget, SIGNAL( itemClicked ( QTreeWidgetItem*, int) ), this, SLOT( itemFillForm (QTreeWidgetItem*, int) ) );

}

void joinNetworkGameDialogImpl::startClient() {

	// TODO: Check input values!
}

void joinNetworkGameDialogImpl::fillServerProfileList() {

	treeWidget->clear();

	TiXmlDocument doc(QString::fromUtf8(myServerProfilesFile.c_str()).toStdString());
	if(!doc.LoadFile()) {
		QMessageBox::warning(this, tr("Load Server-Profile-File Error"),
			tr("Could not load server-profiles-file:\n"+QString::fromUtf8(myServerProfilesFile.c_str()).toAscii()),
			QMessageBox::Close);
	}
	TiXmlHandle docHandle( &doc );

	TiXmlElement* profile = docHandle.FirstChild( "PokerTH" ).FirstChild( "ServerProfiles" ).FirstChild().ToElement();
	if ( profile ) {

                for( profile; profile; profile = profile->NextSiblingElement()) {

		   	QTreeWidgetItem *item = new QTreeWidgetItem(treeWidget,0);
			item->setData(0, 0, profile->Attribute("Name"));
			item->setData(1, 0, profile->Attribute("Address"));
			item->setData(2, 0, profile->Attribute("Port"));

			string isIpv6 = "no";
			int tempInt = 0;
			profile->QueryIntAttribute("IsIpv6", &tempInt );
			if( tempInt == 1 ) { isIpv6 = "yes"; }
			item->setData(3, 0, QString::fromUtf8(isIpv6.c_str()));

			treeWidget->addTopLevelItem(item);
		}
	}
	else { cout << "No Profiles Found \n";  }

	treeWidget->resizeColumnToContents ( 0 );
	treeWidget->resizeColumnToContents ( 1 );
	treeWidget->resizeColumnToContents ( 2 );
	treeWidget->resizeColumnToContents ( 3 );
}

void joinNetworkGameDialogImpl::itemFillForm (QTreeWidgetItem* item, int column) {

	bool toIntTrue;

	TiXmlDocument doc(myServerProfilesFile);
	if(!doc.LoadFile()) {
		QMessageBox::warning(this, tr("Load Server-Profile-File Error"),
			tr("Could not load server-profiles-file:\n"+QString::fromUtf8(myServerProfilesFile.c_str()).toAscii()),
			QMessageBox::Close);
	}
	TiXmlHandle docHandle( &doc );

	TiXmlElement* profile = docHandle.FirstChild( "PokerTH" ).FirstChild( "ServerProfiles" ).FirstChild( item->data(0,0).toString().toStdString() ).ToElement();
	if ( profile ) {

        	lineEdit_profileName->setText(QString::fromUtf8(profile->Attribute("Name")));
		lineEdit_ipAddress->setText(QString::fromUtf8(profile->Attribute("Address")));
		lineEdit_password->setText(QString::fromUtf8(profile->Attribute("Password")));
		spinBox_port->setValue(QString::fromUtf8(profile->Attribute("Port")).toInt(&toIntTrue, 10));
		checkBox_ipv6->setChecked(QString::fromUtf8(profile->Attribute("IsIpv6")).toInt(&toIntTrue, 10));

	}

	pushButton_delete->setEnabled(TRUE);
}

void joinNetworkGameDialogImpl::saveServerProfile() {

// 	bool toIntTrue;

	TiXmlDocument doc(myServerProfilesFile);
	if(!doc.LoadFile()) {
		QMessageBox::warning(this, tr("Load Server-Profile-File Error"),
			tr("Could not load server-profiles-file:\n"+QString::fromUtf8(myServerProfilesFile.c_str()).toAscii()),
			QMessageBox::Close);
	}
	TiXmlHandle docHandle( &doc );

	TiXmlElement* profiles = docHandle.FirstChild( "PokerTH" ).FirstChild( "ServerProfiles" ).ToElement();
	if ( profiles ) {

		TiXmlElement * testProfile = docHandle.FirstChild( "PokerTH" ).FirstChild( "ServerProfiles" ).FirstChild( lineEdit_profileName->text().toStdString() ).ToElement();

		if( testProfile ) {
			// Wenn der Name schon existiert --> Überschreiben?
			QMessageBox msgBox(QMessageBox::Warning, tr("Save Server Profile Error"),
				tr("A profile with the name: \""+lineEdit_profileName->text().toAscii()+"\" already exists.\nWould you like to overwrite ?"), QMessageBox::Yes | QMessageBox::No, this);
			switch (msgBox.exec()) {

				case QMessageBox::Yes: {
					// yes was clicked
					// remove the old
					testProfile->Parent()->RemoveChild(testProfile);
					// write the new
					TiXmlElement * profile1 = new TiXmlElement( lineEdit_profileName->text().toStdString() );
					profiles->LinkEndChild( profile1 );
					profile1->SetAttribute("Name", lineEdit_profileName->text().toStdString());
					profile1->SetAttribute("Address", lineEdit_ipAddress->text().toStdString());
					profile1->SetAttribute("Password", lineEdit_password->text().toStdString());
					profile1->SetAttribute("Port", spinBox_port->value());
					profile1->SetAttribute("IsIpv6", checkBox_ipv6->isChecked());
				}
				break;
				case QMessageBox::No:
				// no was clicked
				break;
				default:
				// should never be reached
				break;
			}

		}
		else {
			// Wenn der Name nicht existiert --> speichern
			TiXmlElement * profile2 = new TiXmlElement( lineEdit_profileName->text().toStdString() );
			profiles->LinkEndChild( profile2 );
			profile2->SetAttribute("Name", lineEdit_profileName->text().toStdString());
			profile2->SetAttribute("Address", lineEdit_ipAddress->text().toStdString());
			profile2->SetAttribute("Password", lineEdit_password->text().toStdString());
			profile2->SetAttribute("Port", spinBox_port->value());
			profile2->SetAttribute("IsIpv6", checkBox_ipv6->isChecked());

		}
        }
	else { QMessageBox::warning(this, tr("Read Server-Profile List Error"),
			tr("Could not read server-profiles list"),
			QMessageBox::Close);	 }

	if(!doc.SaveFile()) {	QMessageBox::warning(this, tr("Save Server-Profile-File Error"),
			tr("Could not save server-profiles-file:\n"+QString::fromUtf8(myServerProfilesFile.c_str()).toAscii()),
			QMessageBox::Close);	 }

	fillServerProfileList();
}

void joinNetworkGameDialogImpl::deleteServerProfile() {

	TiXmlDocument doc(myServerProfilesFile);
	if(!doc.LoadFile()) {
		QMessageBox::warning(this, tr("Load Server-Profile-File Error"),
			tr("Could not load server-profiles-file:\n"+QString::fromUtf8(myServerProfilesFile.c_str()).toAscii()),
			QMessageBox::Close);
	}
	else {
		TiXmlHandle docHandle( &doc );

		TiXmlElement* profile = docHandle.FirstChild( "PokerTH" ).FirstChild( "ServerProfiles" ).FirstChild( treeWidget->currentItem()->data(0,0).toString().toStdString() ).ToElement();

		if ( profile ) { profile->Parent()->RemoveChild(profile); }

		if(!doc.SaveFile()) {	QMessageBox::warning(this, tr("Save Server-Profile-File Error"),
			tr("Could not save server-profiles-file:\n"+QString::fromUtf8(myServerProfilesFile.c_str()).toAscii()),
			QMessageBox::Close);	 }

		//Liste Füllen
		fillServerProfileList();
	}

	pushButton_delete->setDisabled(TRUE);
}

void joinNetworkGameDialogImpl::keyPressEvent ( QKeyEvent * event ) {

// 	std::cout << "key" << event->key();
	if (event->key() == 16777220) { pushButton_connect->click(); } //ENTER
}
<|endoftext|>


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

/*!
 * \file format_encrypted.hpp
 * \brief %FormatEncrypted class header file
 */

#ifndef VMF_FORMAT_ENCRYPTED_HPP
#define VMF_FORMAT_ENCRYPTED_HPP

#include "vmf/format.hpp"

namespace vmf
{

/*!
 * \class FormatEncrypted
 * \brief FormatEncrypted class is a %Format interface extension for %Encryptor use.
 * The class performs (de)serialization of the stream with encryption
 * based on provided instance of %Format and %Encryptor interfaces.
 */
class VMF_EXPORT FormatEncrypted : public Format
{
public:

    /*!
     * \brief Constructor taking encryptor and format to be used at data reading and writing
     * \note To use both compression and encryption pass the FormatCompressed as format
     * \param format Shared pointer to instance of Format
     * \param _encryptor Shared pointer to instance of Encryptor class
     * \param encryptAll Specifies whether all data should be encrypted
     * or just selected items
     * \param _ignoreUnknownEncryptor Flag specifying what to do with unknown encryptor:
     * throw an exception (false) or pass encrypted data as VMF metadata
     */
    FormatEncrypted(std::shared_ptr<Format> format,
                    std::shared_ptr<Encryptor> _encryptor,
                    bool encryptAll = false,
                    bool _ignoreUnknownEncryptor = false);

    /*!
     * \brief Default destructor
     */
    virtual ~FormatEncrypted();

    /*!
     * \brief Serialize input metadata and related stuff to string
     */
    virtual std::string store(
            const MetadataSet &set,
            const std::vector<std::shared_ptr<MetadataSchema> > &schemas = {},
            const std::vector<std::shared_ptr<MetadataStream::VideoSegment> > &segments = {},
            //const std::vector<Stat>& stats = {},
            const AttribMap &attribs = AttribMap() // nextId, checksum, etc.
            );

    /*!
     * \brief Deserialize input string to metadata and related stuff
     * \param text input string
     * \param metadata Metadata records
     * \param schemas Schemas of the metadata
     * \param segments Video segments
     * \param attribs Attributes like nextId, checksum, etc.
     * \return Numbers of items read by categories
     */
    virtual ParseCounters parse(
            const std::string &text,
            std::vector<std::shared_ptr<MetadataInternal> > &metadata,
            std::vector<std::shared_ptr<MetadataSchema> > &schemas,
            std::vector<std::shared_ptr<MetadataStream::VideoSegment> > &segments,
            //std::vector<Stat>& stats,
            AttribMap &attribs
            );

protected:
    /*!
     * \brief Performs encryption of text data
     * \param input Input string
     * \return Encrypted string
     */
    virtual std::string encrypt(const std::string& input);

    /*!
     * \brief Performs decryption of previously encrypted data
     * \param input Input string
     * \return Decrypted string
     */
    virtual std::string decrypt(const std::string& input);

    std::shared_ptr<Format> format;
    std::shared_ptr<Encryptor> encryptor;
    std::shared_ptr<vmf::MetadataSchema> eSchema;
    bool useEncryption;
    bool ignoreUnknownEncryptor;
};

}

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

/*!
 * \file format_encrypted.hpp
 * \brief %FormatEncrypted class header file
 */

#ifndef VMF_FORMAT_ENCRYPTED_HPP
#define VMF_FORMAT_ENCRYPTED_HPP

#include "vmf/format.hpp"

namespace vmf
{

/*!
 * \class FormatEncrypted
 * \brief FormatEncrypted class is a %Format interface extension for %Encryptor use.
 * The class performs (de)serialization of the stream with encryption
 * based on provided instance of %Format and %Encryptor interfaces.
 */
class VMF_EXPORT FormatEncrypted : public Format
{
public:

    /*!
     * \brief Constructor taking encryptor and format to be used at data reading and writing
     * \note To use both compression and encryption pass the FormatCompressed as format
     * \param format Shared pointer to instance of Format
     * \param _encryptor Shared pointer to instance of Encryptor class
     * \param encryptAll Specifies whether all data should be encrypted
     * or just selected items
     * \param _ignoreUnknownEncryptor Flag specifying what to do with unknown encryptor:
     * throw an exception (false) or pass encrypted data as VMF metadata
     */
    FormatEncrypted(std::shared_ptr<Format> format,
                    std::shared_ptr<Encryptor> _encryptor,
                    bool encryptAll = false,
                    bool _ignoreUnknownEncryptor = false);

    /*!
     * \brief Default destructor
     */
    virtual ~FormatEncrypted();

    /*!
     * \brief Serialize input metadata and related stuff to string
     */
    virtual std::string store(
            const MetadataSet &set,
            const std::vector<std::shared_ptr<MetadataSchema> > &schemas = {},
            const std::vector<std::shared_ptr<MetadataStream::VideoSegment> > &segments = {},
            //const std::vector<Stat>& stats = {},
            const AttribMap &attribs = AttribMap() // nextId, checksum, etc.
            );

    /*!
     * \brief Deserialize input string to metadata and related stuff
     * \param text input string
     * \param metadata Metadata records
     * \param schemas Schemas of the metadata
     * \param segments Video segments
     * \param attribs Attributes like nextId, checksum, etc.
     * \return Numbers of items read by categories
     */
    virtual ParseCounters parse(
            const std::string &text,
            std::vector<std::shared_ptr<MetadataInternal> > &metadata,
            std::vector<std::shared_ptr<MetadataSchema> > &schemas,
            std::vector<std::shared_ptr<MetadataStream::VideoSegment> > &segments,
            //std::vector<Stat>& stats,
            AttribMap &attribs
            );

    virtual std::shared_ptr<Format> getBackendFormat()
    {
        return format ? format->getBackendFormat() : nullptr;
    }

protected:
    /*!
     * \brief Performs encryption of text data
     * \param input Input string
     * \return Encrypted string
     */
    virtual std::string encrypt(const std::string& input);

    /*!
     * \brief Performs decryption of previously encrypted data
     * \param input Input string
     * \return Decrypted string
     */
    virtual std::string decrypt(const std::string& input);

    std::shared_ptr<Format> format;
    std::shared_ptr<Encryptor> encryptor;
    std::shared_ptr<vmf::MetadataSchema> eSchema;
    bool useEncryption;
    bool ignoreUnknownEncryptor;
};

}

#endif // VMF_FORMAT_ENCRYPTED_HPP
<|endoftext|>


<commit_before>/***********************************************************************
    created:    21/7/2015
    author:     Yaron Cohen-Tal
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2015 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "CEGUI/RendererModules/OpenGL/GL.h"
#include "CEGUI/String.h"
#include "CEGUI/Exceptions.h"

#include <list>
#include <iostream>

#if defined CEGUI_USE_GLEW
#include <sstream>
#include <cstring>
#endif

namespace CEGUI
{

OpenGLInfo OpenGLInfo::s_instance;

//----------------------------------------------------------------------------//
OpenGLInfo::OpenGLInfo() :
    d_type(TYPE_NONE),
    d_verMajor(-1),
    d_verMinor(-1),
    d_verMajorForce(-1),
    d_verMinorForce(-1),
    d_isS3tcSupported(false),
    d_isNpotTextureSupported(false),
    d_isReadBufferSupported(false),
    d_isPolygonModeSupported(false),
    d_isSeperateReadAndDrawFramebufferSupported(false),
    d_isVaoSupported(false)
{
}

//----------------------------------------------------------------------------//
void OpenGLInfo::init()
{
    initTypeAndVer();
    initSupportedFeatures();
}

void OpenGLInfo::verForce(GLint verMajor_, GLint verMinor_)
{
    d_verMajorForce = verMajor_;
    d_verMinorForce = verMinor_;
}

//----------------------------------------------------------------------------//
void OpenGLInfo::initTypeAndVer()
{
#if defined CEGUI_USE_EPOXY
    d_type = epoxy_is_desktop_gl() ? TYPE_DESKTOP : TYPE_ES;
    if (d_verMajorForce >= 0)
    {
        d_verMajor = d_verMajorForce;
        d_verMinor = d_verMinorForce;
    }
    else
    {
        int ver(epoxy_gl_version());
        if (!ver)
        {
            if (isUsingDesktopOpengl())
                CEGUI_THROW(RendererException
                  ("Failed to obtain desktop OpenGL version."));
            else
                CEGUI_THROW(RendererException
                  ("Failed to obtain OpenGL ES version."));
        }
        d_verMajor = ver / 10;
        d_verMinor = ver % 10;
    }
#elif defined CEGUI_USE_GLEW
    d_type = TYPE_DESKTOP;
    glGetError ();
    d_verMajor = d_verMinor = -1;
#endif
}

//----------------------------------------------------------------------------//
void OpenGLInfo::initSupportedFeatures()
{

#if defined CEGUI_USE_EPOXY

    d_isS3tcSupported = epoxy_has_gl_extension("GL_EXT_texture_compression_s3tc");
    d_isNpotTextureSupported =
          (isUsingDesktopOpengl()  &&  verMajor() >= 2)
      ||  (isUsingOpenglEs() && verMajor() >= 3)
      ||  epoxy_has_gl_extension("GL_ARB_texture_non_power_of_two");
    d_isReadBufferSupported =
          (isUsingDesktopOpengl() && verAtLeast(1, 3))
      ||  (isUsingOpenglEs() && verMajor() >= 3);
    d_isPolygonModeSupported = isUsingDesktopOpengl() && verAtLeast(1, 3);
    d_isSeperateReadAndDrawFramebufferSupported =
          (isUsingDesktopOpengl() && verAtLeast(3, 1))
      ||  (isUsingOpenglEs() && verMajor() >= 3);
    d_isVaoSupported =     (isUsingDesktopOpengl() && verAtLeast(3, 2))
                       ||  (isUsingOpenglEs() && verMajor() >= 3);

#elif defined CEGUI_USE_GLEW

    d_isS3tcSupported = false;

    // Why do we do this and not use GLEW_EXT_texture_compression_s3tc?
    // Because of glewExperimental, of course!
    int ext_count;
    glGetIntegerv(GL_NUM_EXTENSIONS, &ext_count);
    for(int i = 0; i < ext_count; ++i)
    {
        if (!std::strcmp(
                reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i)),
                                              "GL_EXT_texture_compression_s3tc"))
        {
            d_isS3tcSupported = true;
            break;
        }
    }

    d_isNpotTextureSupported =
          (GLEW_VERSION_2_0 == GL_TRUE)
      ||  (GLEW_ARB_texture_non_power_of_two == GL_TRUE);
    d_isPolygonModeSupported
      = (GLEW_VERSION_1_3 == GL_TRUE);
    d_isSeperateReadAndDrawFramebufferSupported = (GLEW_VERSION_3_1 == GL_TRUE);
    d_isVaoSupported = (GLEW_VERSION_3_2 == GL_TRUE);

#endif

}

} // namespace CEGUI
<commit_msg>Remove redundant "#include"-s.<commit_after>/***********************************************************************
    created:    21/7/2015
    author:     Yaron Cohen-Tal
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2015 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "CEGUI/RendererModules/OpenGL/GL.h"
#include "CEGUI/String.h"
#include "CEGUI/Exceptions.h"

#if defined CEGUI_USE_GLEW
#include <sstream>
#include <cstring>
#endif

namespace CEGUI
{

OpenGLInfo OpenGLInfo::s_instance;

//----------------------------------------------------------------------------//
OpenGLInfo::OpenGLInfo() :
    d_type(TYPE_NONE),
    d_verMajor(-1),
    d_verMinor(-1),
    d_verMajorForce(-1),
    d_verMinorForce(-1),
    d_isS3tcSupported(false),
    d_isNpotTextureSupported(false),
    d_isReadBufferSupported(false),
    d_isPolygonModeSupported(false),
    d_isSeperateReadAndDrawFramebufferSupported(false),
    d_isVaoSupported(false)
{
}

//----------------------------------------------------------------------------//
void OpenGLInfo::init()
{
    initTypeAndVer();
    initSupportedFeatures();
}

void OpenGLInfo::verForce(GLint verMajor_, GLint verMinor_)
{
    d_verMajorForce = verMajor_;
    d_verMinorForce = verMinor_;
}

//----------------------------------------------------------------------------//
void OpenGLInfo::initTypeAndVer()
{
#if defined CEGUI_USE_EPOXY
    d_type = epoxy_is_desktop_gl() ? TYPE_DESKTOP : TYPE_ES;
    if (d_verMajorForce >= 0)
    {
        d_verMajor = d_verMajorForce;
        d_verMinor = d_verMinorForce;
    }
    else
    {
        int ver(epoxy_gl_version());
        if (!ver)
        {
            if (isUsingDesktopOpengl())
                CEGUI_THROW(RendererException
                  ("Failed to obtain desktop OpenGL version."));
            else
                CEGUI_THROW(RendererException
                  ("Failed to obtain OpenGL ES version."));
        }
        d_verMajor = ver / 10;
        d_verMinor = ver % 10;
    }
#elif defined CEGUI_USE_GLEW
    d_type = TYPE_DESKTOP;
    glGetError ();
    d_verMajor = d_verMinor = -1;
#endif
}

//----------------------------------------------------------------------------//
void OpenGLInfo::initSupportedFeatures()
{

#if defined CEGUI_USE_EPOXY

    d_isS3tcSupported = epoxy_has_gl_extension("GL_EXT_texture_compression_s3tc");
    d_isNpotTextureSupported =
          (isUsingDesktopOpengl()  &&  verMajor() >= 2)
      ||  (isUsingOpenglEs() && verMajor() >= 3)
      ||  epoxy_has_gl_extension("GL_ARB_texture_non_power_of_two");
    d_isReadBufferSupported =
          (isUsingDesktopOpengl() && verAtLeast(1, 3))
      ||  (isUsingOpenglEs() && verMajor() >= 3);
    d_isPolygonModeSupported = isUsingDesktopOpengl() && verAtLeast(1, 3);
    d_isSeperateReadAndDrawFramebufferSupported =
          (isUsingDesktopOpengl() && verAtLeast(3, 1))
      ||  (isUsingOpenglEs() && verMajor() >= 3);
    d_isVaoSupported =     (isUsingDesktopOpengl() && verAtLeast(3, 2))
                       ||  (isUsingOpenglEs() && verMajor() >= 3);

#elif defined CEGUI_USE_GLEW

    d_isS3tcSupported = false;

    // Why do we do this and not use GLEW_EXT_texture_compression_s3tc?
    // Because of glewExperimental, of course!
    int ext_count;
    glGetIntegerv(GL_NUM_EXTENSIONS, &ext_count);
    for(int i = 0; i < ext_count; ++i)
    {
        if (!std::strcmp(
                reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i)),
                                              "GL_EXT_texture_compression_s3tc"))
        {
            d_isS3tcSupported = true;
            break;
        }
    }

    d_isNpotTextureSupported =
          (GLEW_VERSION_2_0 == GL_TRUE)
      ||  (GLEW_ARB_texture_non_power_of_two == GL_TRUE);
    d_isPolygonModeSupported
      = (GLEW_VERSION_1_3 == GL_TRUE);
    d_isSeperateReadAndDrawFramebufferSupported = (GLEW_VERSION_3_1 == GL_TRUE);
    d_isVaoSupported = (GLEW_VERSION_3_2 == GL_TRUE);

#endif

}

} // namespace CEGUI
<|endoftext|>