Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 2 of 2

Thread: GLUT - Non-shared Idle Function?

  1. #1
    Newbie Newbie
    Join Date
    Feb 2014
    Posts
    2

    GLUT - Non-shared Idle Function?

    Hello all, I'm looking into making an object oriented toolkit and have ran into a bit of a snag with glut's idle function callback. The problem is that I can't seem to attach a dedicated idle function callback on a per-window basis. Is there any way to make glut accept idle functions on a per-window basis? Thanks for any help.

    Below is what I have mocked together so far (It's a bit long, but cannot be further compressed for a SSCCE, sorry):
    (Note: The code is in C++11, only Clang is supported, though GCC *might* work)

    Code :
    #ifndef BOOTSTRAP_HPP
    #define BOOTSTRAP_HPP
     
    #include <iostream>
    #include <map>
     
    #include "Platform.hpp"
     
    namespace detail
    {
        struct VirtualBootstrap
        {
          protected:
            static thread_local bool glew_initialized;
          public:
            virtual void idle() = 0;
            virtual void tick() = 0;
            virtual void render() = 0;
            virtual ~VirtualBootstrap() = default;
        };
     
        thread_local bool VirtualBootstrap::glew_initialized = false;
     
        thread_local std::map<int, VirtualBootstrap*> bootstraps;
     
        template<int N>
        void register_this(VirtualBootstrap* bootstrap) noexcept
        {
            bootstraps.insert(std::make_pair(N, bootstrap));
        }
     
        template<int N>
        void unregister_this() noexcept
        {
            bootstraps.erase(N);
        }
     
        template<int N>
        void glutDisplayFuncDelegate()
        {
            std::cout << N << " rendering" << std::endl;
            bootstraps[N]->render();
        }
     
        template<int N>
        void glutIdleFuncDelegate()
        {
            std::cout << N << " idling" << std::endl;
            bootstraps[N]->idle();
        }
    }
     
    template<int N>
    class Bootstrap : public detail::VirtualBootstrap
    {
      public:
     
        Bootstrap(int windowWidth, int windowHeight)
        {
            glutInitWindowSize(windowWidth, windowHeight);
            glutInitWindowPosition(100, 100);
            glutCreateWindow((std::string("Bootstrap Test (") + std::to_string(N) + ")").c_str());
            if(!glew_initialized)
            {
                glewInit();
                glew_initialized = true;
            }
            glutDisplayFunc(detail::glutDisplayFuncDelegate<N>);
            glutIdleFunc(detail::glutIdleFuncDelegate<N>);
            detail::register_this<N>(this);
        }
     
        virtual ~Bootstrap()
        {
            detail::unregister_this<N>();
        }
    };
     
    template<int N>
    class TestBootstrap : public Bootstrap<N>
    {
      public:
        TestBootstrap(int w, int h) : Bootstrap<N>(w, h) {}
        virtual void idle() { /** update some uniforms... */ glutPostRedisplay();}
        virtual void tick() {}
        virtual void render() { /** Render something impressive */}
    };
     
    int main(int argc, char** argv)
    {
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA);
        TestBootstrap<0> bootstrap0(300, 300);
        TestBootstrap<1> bootstrap1(300, 300);
        glutMainLoop();
    }
     
    #endif

  2. #2
    Newbie Newbie
    Join Date
    Feb 2014
    Posts
    2
    Do'H!

    I think I just found a quick and dirty work-around...but would appreciate any peer reviews that might be offered!

    Code :
    #ifndef BOOTSTRAP_HPP
    #define BOOTSTRAP_HPP
     
    #include <map>
     
    #include "Platform.hpp"
     
    namespace detail
    {
        struct VirtualBootstrap
        {
          protected:
            static thread_local bool glew_initialized;
          public:
            virtual void idle() = 0;
            virtual void tick() = 0;
            virtual void render() = 0;
            virtual ~VirtualBootstrap() = default;
        };
     
        thread_local bool VirtualBootstrap::glew_initialized = false;
     
        thread_local VirtualBootstrap* current = nullptr;
     
        thread_local std::map<int, VirtualBootstrap*> bootstraps;
     
        template<int N>
        void register_this(VirtualBootstrap* bootstrap) noexcept
        {
            bootstraps.insert(std::make_pair(N, bootstrap));
        }
     
        template<int N>
        void unregister_this() noexcept
        {
            bootstraps.erase(N);
        }
     
        template<int N>
        void glutIdleFuncDelegate()
        {
            bootstraps[N]->idle();
        }
     
        template<int N>
        void glutDisplayFuncDelegate()
        {
            if(bootstraps[N] != current)
            {
                current = bootstraps[N];
     
                /// Invoke idle function one time
                glutIdleFuncDelegate<N>();
     
                /// Set subsequent idle function invocations
                glutIdleFunc(glutIdleFuncDelegate<N>);
            }
            bootstraps[N]->render();
        }
    }
     
    template<int N>
    class Bootstrap : public detail::VirtualBootstrap
    {
      public:
     
        Bootstrap(int windowWidth, int windowHeight)
        {
            glutInitWindowSize(windowWidth, windowHeight);
            glutInitWindowPosition(100, 100);
            glutCreateWindow((std::string("Bootstrap Test (") + std::to_string(N) + ")").c_str());
            if(!glew_initialized)
            {
                glewInit();
                glew_initialized = true;
            }
            glutDisplayFunc(detail::glutDisplayFuncDelegate<N>);
            glutIdleFunc(detail::glutIdleFuncDelegate<N>);
            detail::register_this<N>(this);
        }
     
        virtual ~Bootstrap()
        {
            detail::unregister_this<N>();
        }
    };
     
    #endif

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •