glcontextmanager.h 4.28 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#ifndef GLCONTEXTMANAGER_H__
#define GLCONTEXTMANAGER_H__

#include "tgt/singleton.h"
#include "tgt/glcanvas.h"
#include <tbb/mutex.h>  // TODO: TBB dependency in TGT is not that beautiful...
#include <map>
#include <string>

class QWidget;

namespace tgt {
    class GLCanvas;

    /**
     * Manages multiple shared OpenGL contexts and offers methods to ensure that only one context is active at a time.
     */
    class GlContextManager : public Singleton<GlContextManager> {
    public:
        /**
         * Creates a new QtGLContext for the OpenGL context of \a canvas.
         * \param   canvas  QtCanvas with the OpenGL context to manage
         */
        GlContextManager();

        /**
         * Destructor
         */
        virtual ~GlContextManager();

        /**
         * Get Pointer of the actual class
         * @return Pointer of the actual class
         */
        static GlContextManager* getPtr();

        /**
         * Get reference of the actual class
         * @return reference of the actual class
        */
        static GlContextManager& getRef();

        /**
         * Has the actual class been inited?
         */
        static bool isInited();

        /**
         * Creates a new OpenGL context in a QtThreadedCanvas with the given arguments.
         * Parameters are the same as in QtThreadedCanvas() but context sharing is enables per default.
         * 
         * \note    Must be called with the OpenGL mutex acquired!
         * 
         * \note    The created canvas/context is owned by this ContextManager. Hence, you may not
         *          delete it yourself!
         * 
         * \param   key     Key of the context to create, must be unique.
         * \param   title   Window title
         * \param   size    Window size
         * \return  The newly created QtThreadedCanvas.
         */
        virtual GLCanvas* createContext(
            const std::string& key,
            const std::string& title = "",
            const ivec2& size = ivec2(GLCanvas::DEFAULT_WINDOW_WIDTH, GLCanvas::DEFAULT_WINDOW_HEIGHT),
            const GLCanvas::Buffers buffers = GLCanvas::RGBADD,
            bool shared = true) = 0;
        
        /**
         * Returns the OpenGL context with the given key \a key, 0 if no such context exists.
         * \param   key     Key of the context to return.
         * \return  The OpenGL context with the given key \a key, 0 if no such context exists.
         */
        GLCanvas* getContextByKey(const std::string& key);

        GLCanvas* getCurrentContext() const;

        tbb::mutex& getGlMutex();

        void acquireContext(GLCanvas* context);

        void releaseCurrentContext();


        void lockAndAcquire(GLCanvas* context);

        void releaseAndUnlock();
        
    protected:
        /**
         * Sets the given context \a context as the current context for the OpenGL device.
         * If \a context is already the current context, nothing will happen.
         * \param   context     Context to set as current.
         */
        virtual void setCurrent(GLCanvas* context) = 0;

        /**
         * Locks the OpenGL device for other threads acessing the ContextManager.
         * \see GlContextManager::release
         */
        void lock();

        /**
         * Releases the lock on the OpenGL device
         * \see GlContextManager::lock
         */
        void unlock();


        std::map<std::string, GLCanvas*> _contexts;  ///< Map of all OpenGL contexts
        GLCanvas* _currentContext;                   ///< Current active OpenGL context
        tbb::mutex _glMutex;                                ///< Mutex protecting OpenGL for multi-threaded access

        static GlContextManager* singletonClass_;
    };

    
    /**
     * Scoped lockAndAcquire for a GLContext, that automatically unlocks the context on destruction.
     */
    class TGT_API GLContextScopedLock {
    public:
        GLContextScopedLock(GLCanvas* context)
            : _context(context)
        {
            if (_context) {
                GlContextManager::getRef().lockAndAcquire(context);
            }
        };
        ~GLContextScopedLock() {
            if (_context)
                GlContextManager::getRef().releaseAndUnlock();
        }
    private:
        GLCanvas* _context;
    };

} // namespace tgt


#endif // GLCONTEXTMANAGER_H__