opengljobprocessor.cpp 4.87 KB
Newer Older
1 2
// ================================================================================================
// 
schultezub's avatar
schultezub committed
3
// This file is part of the CAMPVis Software Framework.
4
// 
5
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
schultezub's avatar
schultezub committed
6
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
7
//      Chair for Computer Aided Medical Procedures
8 9
//      Technische Universitaet Muenchen
//      Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
10
// 
schultezub's avatar
schultezub committed
11
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
12
// 
13 14 15 16
// 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
17
// 
18 19 20 21
// 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.
22 23 24 25 26
// 
// ================================================================================================

#include "opengljobprocessor.h"

27 28
#include <tbb/tick_count.h>

29
#include "tgt/assert.h"
30 31
#include "tgt/logmanager.h"
#include "tgt/openglgarbagecollector.h"
32
#include "tgt/glcontextmanager.h"
33 34
#include "core/tools/job.h"

schultezub's avatar
schultezub committed
35
namespace campvis {
36

37 38 39
    OpenGLJobProcessor::ScopedSynchronousGlJobExecution::ScopedSynchronousGlJobExecution()
        : _lock(nullptr)
    {
40
        if (! GLCtxtMgr.checkWhetherThisThreadHasAcquiredOpenGlContext()) {
41 42 43 44 45 46 47 48 49 50 51 52 53 54
            GLJobProc.pause();
            _lock = new tgt::GLContextScopedLock(GLJobProc.iKnowWhatImDoingGetArbitraryContext());
        }
    }

    OpenGLJobProcessor::ScopedSynchronousGlJobExecution::~ScopedSynchronousGlJobExecution() {
        if (_lock != nullptr) {
            delete _lock;
            GLJobProc.resume();
        }
    }

// ================================================================================================
    
55 56
    OpenGLJobProcessor::OpenGLJobProcessor()
    {
57
        _pause = 0;
58
        _context= nullptr;
59 60 61
    }

    OpenGLJobProcessor::~OpenGLJobProcessor() {
62 63 64 65
        // delete all unfinished jobs
        AbstractJob* jobToDo = nullptr;
        while (_jobQueue.try_pop(jobToDo)) {
            delete jobToDo;
schultezub's avatar
schultezub committed
66
        }
67

68
        _jobQueue.clear();
69
        _jobPool.recycle();
70 71 72 73 74
    }

    void OpenGLJobProcessor::stop() {
        _stopExecution = true;
        _evaluationCondition.notify_all();
75 76

        Runnable::stop();
77 78 79
    }

    void OpenGLJobProcessor::run() {
80 81 82
        tgtAssert(_context != nullptr, "You have to set the context first before calling OpenGLJobProcessor::run()!");
        std::unique_lock<std::mutex> lock(*tgt::GlContextManager::getRef().getGlMutexForContext(_context));
        tgt::GlContextManager::getRef().acquireContext(_context, false);
83 84

        while (! _stopExecution) {
85 86
            bool hadWork = false;

87 88
            AbstractJob* jobToDo = nullptr;
            while (_pause == 0 && !_stopExecution && _jobQueue.try_pop(jobToDo)) {
89 90
                hadWork = true;

91 92 93
                // execute and delete the job
                jobToDo->execute();
                delete jobToDo;
94
            }
95

96
            while (_pause > 0) {
97
                tgt::GlContextManager::getRef().releaseContext(_context, false);
98
                _evaluationCondition.wait(lock);
99
                tgt::GlContextManager::getRef().acquireContext(_context, false);
100 101
                hadWork = true;
            }
102

103
            if (! hadWork) {
104
                tgt::GlContextManager::getRef().releaseContext(_context, false);
105
                _evaluationCondition.wait(lock);
106
                tgt::GlContextManager::getRef().acquireContext(_context, false);
107
            }
108 109 110
        }

        // release OpenGL context, so that other threads can access it
111
        tgt::GlContextManager::getRef().releaseContext(_context, false);
112 113
    }

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
    void OpenGLJobProcessor::pause() {
        ++_pause;
    }

    void OpenGLJobProcessor::resume() {
        if (_pause == 0) {
            tgtAssert(false, "Called resume on non-paused job processor!");
            return;
        }

        --_pause;
        if (_pause == 0)
            _evaluationCondition.notify_all();
    }

129 130
    void OpenGLJobProcessor::enqueueJob(AbstractJob* job) {
        _jobQueue.push(job);
131 132
        _evaluationCondition.notify_all();
    }
133

134 135 136
    void OpenGLJobProcessor::setContext(tgt::GLCanvas* context) {
        tgtAssert(_context == nullptr, "You are trying to change an already set context, thou shalt not do that!");
        _context = context;
137 138
    }

139

140
    tgt::GLCanvas* OpenGLJobProcessor::iKnowWhatImDoingGetArbitraryContext() {
141
        return _context;
142 143
    }

144

145 146
}