campvisapplication.cpp 11 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-2013, 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 Universität München
//      Boltzmannstr. 3, 85748 Garching b. München, 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
// 
// ================================================================================================

schultezub's avatar
schultezub committed
25
#include "campvisapplication.h"
26
27
28

#include "tgt/assert.h"
#include "tgt/exception.h"
29
#include "tgt/glcanvas.h"
30
#include "tgt/glcontextmanager.h"
31
#include "tgt/gpucapabilities.h"
32
33
34
#include "tgt/shadermanager.h"
#include "tgt/qt/qtapplication.h"
#include "tgt/qt/qtthreadedcanvas.h"
schultezub's avatar
schultezub committed
35
#include "tbb/compat/thread"
36

schultezub's avatar
schultezub committed
37
#include "application/campvispainter.h"
38
#include "application/gui/mainwindow.h"
39
#include "core/tools/job.h"
40
#include "core/tools/opengljobprocessor.h"
41
#include "core/tools/simplejobprocessor.h"
42
#include "core/tools/stringutils.h"
43
#include "core/tools/quadrenderer.h"
44
#include "core/pipeline/abstractpipeline.h"
45
#include "core/pipeline/visualizationprocessor.h"
46
#include "modules/pipelinefactory.h"
47

schultezub's avatar
schultezub committed
48
namespace campvis {
49

50
    const std::string CampVisApplication::loggerCat_ = "CAMPVis.application.CampVisApplication";
51

52
    CampVisApplication::CampVisApplication(int& argc, char** argv) 
53
54
        : QApplication(argc, argv)
        , _localContext(0)
55
        , _mainWindow(0)
56
57
58
59
        , _initialized(false)
        , _argc(argc)
        , _argv(argv)
    {
60
61
        // Make Xlib and GLX thread safe under X11
        QApplication::setAttribute(Qt::AA_X11InitThreads);
62

63
        _mainWindow = new MainWindow(this);
64
        tgt::GlContextManager::init();
65
66

        OpenGLJobProcessor::init();
67
        SimpleJobProcessor::init();
68
69
    }

70
71
    CampVisApplication::~CampVisApplication() {
        tgtAssert(_initialized == false, "Destructing initialized CampVisApplication, deinitialize first!");
72
73

        // delete everything in the right order:
74
        for (std::vector< std::pair<AbstractPipeline*, CampVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
75
76
77
78
79
            delete it->second;
        }
        for (std::vector<AbstractPipeline*>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
            delete *it;
        }
80
81
82
        for (std::vector<DataContainer*>::iterator it = _dataContainers.begin(); it != _dataContainers.end(); ++it) {
            delete *it;
        }
83
84
    }

85
86
    void CampVisApplication::init() {
        tgtAssert(_initialized == false, "Tried to initialize CampVisApplication twice.");
87
88
89
90
91
92
93

        // Init TGT
        tgt::InitFeature::Features featureset = tgt::InitFeature::ALL;
        tgt::init(featureset);
        LogMgr.getConsoleLog()->addCat("", true);

        // create a local OpenGL context and init GL
94
95
        _localContext = new QtThreadedCanvas("", tgt::ivec2(16, 16));
        tgt::GlContextManager::getRef().registerContextAndInitGlew(_localContext);
96

97
        tgt::GLContextScopedLock lock(_localContext);
98

99
        tgt::initGL(featureset);
100
        ShdrMgr.setDefaultGlslVersion("330");
101
102
        LGL_ERROR;

103
        QuadRenderer::init();
104
        
105
106
        if (_argc > 0) {
            // ugly hack
schultezub's avatar
schultezub committed
107
            std::string basePath(_argv[0]);
108
109
110
111
112
            basePath = tgt::FileSystem::parentDir(basePath);
            ShdrMgr.addPath(basePath);
            ShdrMgr.addPath(basePath + "/core/glsl");

            basePath = tgt::FileSystem::parentDir(tgt::FileSystem::parentDir(basePath));
schultezub's avatar
schultezub committed
113
114
115
            ShdrMgr.addPath(basePath);
            ShdrMgr.addPath(basePath + "/core/glsl");

116
117
118
119
120
121
#ifdef CAMPVIS_SOURCE_DIR
            {
                std::string sourcePath = CAMPVIS_SOURCE_DIR;
                ShdrMgr.addPath(sourcePath);
                ShdrMgr.addPath(sourcePath + "/core/glsl");
            }
schultezub's avatar
schultezub committed
122
#endif
123
124
        }

125
126
        _mainWindow->init();

127
128
129
130
131
132
133
134
135
136
        // ensure matching OpenGL specs
        LINFO("Using Graphics Hardware " << GpuCaps.getVendorAsString() << " " << GpuCaps.getGlRendererString() << " on " << GpuCaps.getOSVersionString());
        LINFO("Supported OpenGL " << GpuCaps.getGlVersion() << ", GLSL " << GpuCaps.getShaderVersion());
        if (GpuCaps.getGlVersion() < tgt::GpuCapabilities::GlVersion::TGT_GL_VERSION_3_3) {
            LERROR("Your system does not support OpenGL 3.3, which is mandatory. CAMPVis will probably not work as intended.");
        }
        if (GpuCaps.getShaderVersion() < tgt::GpuCapabilities::GlVersion::SHADER_VERSION_330) {
            LERROR("Your system does not support GLSL Shader Version 3.30, which is mandatory. CAMPVis will probably not work as intended.");
        }

137
138
        GLJobProc.start();
        GLJobProc.registerContext(_localContext);
139

140
141
142
143
144
145
146
        // parse argument list and create pipelines
        QStringList pipelinesToAdd = this->arguments();
        for (int i = 1; i < pipelinesToAdd.size(); ++i) {
            DataContainer* dc = createAndAddDataContainer("DataContainer #" + StringUtils::toString(_dataContainers.size() + 1));
            AbstractPipeline* p = PipelineFactory::getRef().createPipeline(pipelinesToAdd[i].toStdString(), dc);
            if (p != 0)
                addPipeline(pipelinesToAdd[i].toStdString(), p);
147
148
149
150
151
        }

        _initialized = true;
    }

152
153
    void CampVisApplication::deinit() {
        tgtAssert(_initialized, "Tried to deinitialize uninitialized CampVisApplication.");
154

155
156
        GLJobProc.stop();

157
158
        {
            // Deinit everything OpenGL related using the local context.
159
            tgt::GLContextScopedLock lock(_localContext);
160

161
162
163
164
165
166
            // Deinit pipeline first
            for (std::vector<AbstractPipeline*>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
                (*it)->deinit();
            }

            // Now deinit painters:
167
            for (std::vector< std::pair<AbstractPipeline*, CampVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
168
169
170
                it->second->deinit();
            }

171
            _mainWindow->deinit();
172
173
            QuadRenderer::deinit();

174
175
            // deinit OpenGL and tgt
            tgt::deinitGL();
176
177
        }

178
        SimpleJobProcessor::deinit();
179
        OpenGLJobProcessor::deinit();
180
        PipelineFactory::deinit();
181

182
        tgt::GlContextManager::deinit();
183
184
        tgt::deinit();

185
        // MainWindow dtor needs a valid CampVisApplication, so we need to call it here instead of during destruction.
schultezub's avatar
schultezub committed
186
187
        delete _mainWindow;

188
189
190
        _initialized = false;
    }

191
192
    int CampVisApplication::run() {
        tgtAssert(_initialized, "Tried to run uninitialized CampVisApplication.");
193
194

        // disconnect OpenGL context from this thread so that the other threads can acquire an OpenGL context.
195
        tgt::GlContextManager::getRef().releaseCurrentContext();
196

197
198
        _mainWindow->show();

199
200
201
202
203
204
        // Start QApplication
        int toReturn = QApplication::exec();

        return toReturn;
    }

205
    void CampVisApplication::addPipeline(const std::string& name, AbstractPipeline* pipeline) {
206
207
        tgtAssert(pipeline != 0, "Pipeline must not be 0.");

208
        // create canvas and painter for the pipeline and connect all together
209
        tgt::QtThreadedCanvas* canvas = new tgt::QtThreadedCanvas("CAMPVis", tgt::ivec2(512, 512));
210
        GLJobProc.registerContext(canvas);
211
212
        canvas->init();

213
        CampVisPainter* painter = new CampVisPainter(canvas, pipeline);
214
        canvas->setPainter(painter, false);
215
        pipeline->setCanvas(canvas);
216

217
218
219
        _visualizations.push_back(std::make_pair(pipeline, painter));
        _pipelines.push_back(pipeline);

220
221
        _mainWindow->addVisualizationPipelineWidget(name, canvas);

222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
        // initialize context (GLEW) and pipeline in OpenGL thread)
        GLJobProc.enqueueJob(
            canvas, 
            makeJobOnHeap<CampVisApplication, tgt::GLCanvas*, AbstractPipeline*>(this, &CampVisApplication::initGlContextAndPipeline, canvas, pipeline), 
            OpenGLJobProcessor::SerialJob);

        s_PipelinesChanged();
    }

    void CampVisApplication::initGlContextAndPipeline(tgt::GLCanvas* canvas, AbstractPipeline* pipeline) {
        tgt::GlContextManager::getRef().registerContextAndInitGlew(canvas);

        pipeline->init();
        LGL_ERROR;
        canvas->getPainter()->init();
        LGL_ERROR;

239
240
241
242
243
        // enable pipeline and invalidate all processors
        pipeline->setEnabled(true);
        for (std::vector<AbstractProcessor*>::const_iterator it = pipeline->getProcessors().begin(); it != pipeline->getProcessors().end(); ++it) {
            (*it)->invalidate(AbstractProcessor::INVALID_RESULT);
        }
244
245
    }

246
247
248
249
250
251
    void CampVisApplication::registerDockWidget(Qt::DockWidgetArea area, QDockWidget* dock) {
        tgtAssert(dock != 0, "Dock widget must not be 0.");

        _mainWindow->addDockWidget(area, dock);
    }

252
253
254
255
256
    DataContainer* CampVisApplication::createAndAddDataContainer(const std::string& name) {
        DataContainer* dc = new DataContainer(name);
        _dataContainers.push_back(dc);
        s_DataContainersChanged();
        return dc;
257
258
    }

259
260
261
262
263
264
265
266
267
268
269
    void CampVisApplication::rebuildAllShadersFromFiles() {
        // rebuilding all shaders has to be done from OpenGL context, use the local one.
        GLJobProc.enqueueJob(_localContext, makeJobOnHeap(this, &CampVisApplication::triggerShaderRebuild), OpenGLJobProcessor::SerialJob);
    }

    void CampVisApplication::triggerShaderRebuild() {

        if (! ShdrMgr.rebuildAllShadersFromFile()) {
            LERROR("Could not rebuild all shaders from file.");
            return;
        }
270
271
272
        else {
            LINFO("Rebuilding shaders from file successful.");
        }
273
274
275
276
277
278
279
280
281
282

        for (std::vector<AbstractPipeline*>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
            for (std::vector<AbstractProcessor*>::const_iterator pit = (*it)->getProcessors().begin(); pit != (*it)->getProcessors().end(); ++pit) {
                if (VisualizationProcessor* tester = dynamic_cast<VisualizationProcessor*>(*pit)) {
                	tester->invalidate(AbstractProcessor::INVALID_RESULT);
                }
            }
        }
    }

283

284
}