2.12.2021, 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

glcontextmanager.cpp 4.43 KB
Newer Older
1
2
3
#include "glcontextmanager.h"

#include "tgt/assert.h"
4
#include "tgt/logmanager.h"
5
6

namespace tgt {
7
8

    std::string GlContextManager::loggerCat_ = "tgt.GlContextManager";
9
    
10
    GlContextManager::GlContextManager() {
11
12
    }

13
14
15
    GlContextManager::~GlContextManager() {
        for (auto it = _contextMap.begin(); it != _contextMap.end(); ++it) {
            delete it->second._glMutex;
16
        }
17
        _contextMap.clear();
18
19
    }

20
21
    void GlContextManager::registerContextAndInitGlew(GLCanvas* context, const std::string& title) {
        tbb::concurrent_hash_map<GLCanvas*, ContextInfo>::accessor a;
22
        tgtAssert(context != 0, "Given context must not be 0.");
23
24
25
26
        tgtAssert(! _contextMap.find(a, context), "Tried to double register the same context.");

        ContextInfo ci = { context, new std::mutex(), std::this_thread::get_id(), true, title };
        _contextMap.insert(std::make_pair(context, ci));
27
28

        // Init GLEW for this context
29
        context->acquireAsCurrentContext();
30
31
32
33
34
35
36
37
38
39
40
41
        GLenum err = glewInit();
        if (err != GLEW_OK) {
            // Problem: glewInit failed, something is seriously wrong.
            tgtAssert(false, "glewInit failed");
            std::cerr << "glewInit failed, error: " << glewGetErrorString(err) << std::endl;
            exit(EXIT_FAILURE);
        }

        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glPixelStorei(GL_PACK_ALIGNMENT, 1);
    }

42
    void GlContextManager::removeContext(GLCanvas* context) {
43
44
45
46
47
48
49
50
51
52
        tbb::concurrent_hash_map<GLCanvas*, ContextInfo>::accessor a;
        if (_contextMap.find(a, context)) {
            delete a->second._glMutex;
        }
        else {
            tgtAssert(false, "Could not find the context in map, this should not happen!");
        }

        _contextMap.erase(a);
    }
53

54
55
56
57
58
59
60
61
    std::mutex* GlContextManager::getGlMutexForContext(GLCanvas* context) {
        tbb::concurrent_hash_map<GLCanvas*, ContextInfo>::const_accessor a;
        if (_contextMap.find(a, context)) {
            return a->second._glMutex;
        }
        else {
            tgtAssert(false, "Could not find the context in map, this should not happen!");
            return nullptr;
62
63
64
        }
    }

65
66
67
68
69
70
71
72
73
74
75
76
77
    void GlContextManager::acquireContext(GLCanvas* context, bool lockGlMutex) {
        {
            tbb::concurrent_hash_map<GLCanvas*, ContextInfo>::const_accessor a;
            if (_contextMap.find(a, context)) {
                ContextInfo& ci = const_cast<ContextInfo&>(a->second);
                if (lockGlMutex)
                    ci._glMutex->lock();

                tgtAssert(a->second._acquired == false || a->second._threadId == std::this_thread::get_id(), "Tried to acquire an OpenGL thread that is already acquired by another thread!");

                ci._acquired = true;
                ci._threadId = std::this_thread::get_id();
                context->acquireAsCurrentContext();
78
79
            }
            else {
80
                tgtAssert(false, "Could not find the context in map, this should not happen!");
81
82
            }
        }
83

84
85
        tbb::spin_rw_mutex::scoped_lock lock(_threadSetMutex, true);
        _threadsWithAcquiredOpenGlContext.insert(std::this_thread::get_id());
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
    void GlContextManager::releaseContext(GLCanvas* context, bool unlockGlMutex) {
        {
            tbb::concurrent_hash_map<GLCanvas*, ContextInfo>::const_accessor a;
            if (_contextMap.find(a, context)) {
                tgtAssert(a->second._acquired == true, "Tried to release an unbound OpenGL context!");
                tgtAssert(a->second._threadId == std::this_thread::get_id(), "Tried to release an OpenGL thread that was acquired by another thread!");
    
                ContextInfo& ci = const_cast<ContextInfo&>(a->second);
                ci._acquired = false;
                context->releaseAsCurrentContext();
    
                if (unlockGlMutex)
                    ci._glMutex->unlock();
            }
            else {
                tgtAssert(false, "Could not find the context in map, this should not happen!");
            }
        }

        tbb::spin_rw_mutex::scoped_lock lock(_threadSetMutex, true);
        _threadsWithAcquiredOpenGlContext.erase(std::this_thread::get_id());
    }

    bool GlContextManager::checkWhetherThisThreadHasAcquiredOpenGlContext() const {
        tbb::spin_rw_mutex::scoped_lock lock(_threadSetMutex, false);
        return (_threadsWithAcquiredOpenGlContext.find(std::this_thread::get_id()) != _threadsWithAcquiredOpenGlContext.end());
    }
115
}