Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

campvisapplication.cpp 11.4 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
// 
// ================================================================================================

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
#include "tgt/shadermanager.h"
33
#include "tgt/texturereadertga.h"
34
35
#include "tgt/qt/qtapplication.h"
#include "tgt/qt/qtthreadedcanvas.h"
schultezub's avatar
schultezub committed
36
#include "tbb/compat/thread"
37

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

49
50
51
52
#ifdef CAMPVIS_HAS_SCRIPTING
#include "scripting/scriptedpipelineregistrar.h"
#endif

schultezub's avatar
schultezub committed
53
namespace campvis {
54

55
    const std::string CampVisApplication::loggerCat_ = "CAMPVis.application.CampVisApplication";
56

57
    CampVisApplication::CampVisApplication(int& argc, char** argv) 
58
59
        : QApplication(argc, argv)
        , _localContext(0)
60
        , _mainWindow(0)
61
        , _errorTexture(nullptr)
62
63
64
65
        , _initialized(false)
        , _argc(argc)
        , _argv(argv)
    {
66
67
        // Make Xlib and GLX thread safe under X11
        QApplication::setAttribute(Qt::AA_X11InitThreads);
68

69
        _mainWindow = new MainWindow(this);
70
        tgt::GlContextManager::init();
71
72

        OpenGLJobProcessor::init();
73
        SimpleJobProcessor::init();
74
75
    }

76
77
    CampVisApplication::~CampVisApplication() {
        tgtAssert(_initialized == false, "Destructing initialized CampVisApplication, deinitialize first!");
78
79

        // delete everything in the right order:
80
        for (std::vector< std::pair<AbstractPipeline*, CampVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
81
82
83
84
85
            delete it->second;
        }
        for (std::vector<AbstractPipeline*>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
            delete *it;
        }
86
87
88
        for (std::vector<DataContainer*>::iterator it = _dataContainers.begin(); it != _dataContainers.end(); ++it) {
            delete *it;
        }
89
90
    }

91
92
    void CampVisApplication::init() {
        tgtAssert(_initialized == false, "Tried to initialize CampVisApplication twice.");
93
94
95
96
97
98
99

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

        // create a local OpenGL context and init GL
100
        _localContext = new QtThreadedCanvas("", tgt::ivec2(16, 16));
101

102
        tgt::GLContextScopedLock lock(_localContext);
103
        tgt::GlContextManager::getRef().registerContextAndInitGlew(_localContext);
104

105
        tgt::initGL(featureset);
106
        ShdrMgr.setDefaultGlslVersion("330");
107
108
        LGL_ERROR;

109
        QuadRenderer::init();
110
        
111
112
        if (_argc > 0) {
            // ugly hack
schultezub's avatar
schultezub committed
113
            std::string basePath(_argv[0]);
114
115
116
117
118
            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
119
120
121
            ShdrMgr.addPath(basePath);
            ShdrMgr.addPath(basePath + "/core/glsl");

122
123
124
125
126
127
#ifdef CAMPVIS_SOURCE_DIR
            {
                std::string sourcePath = CAMPVIS_SOURCE_DIR;
                ShdrMgr.addPath(sourcePath);
                ShdrMgr.addPath(sourcePath + "/core/glsl");
            }
schultezub's avatar
schultezub committed
128
#endif
129
130
        }

131
132
        _mainWindow->init();

133
134
135
136
137
138
139
140
141
142
        // 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.");
        }

143
144
        GLJobProc.start();
        GLJobProc.registerContext(_localContext);
145

146
147
148
149
        // load textureData from file
        tgt::TextureReaderTga trt;
        _errorTexture = trt.loadTexture(CAMPVIS_SOURCE_DIR "/application/data/no_input.tga", tgt::Texture::LINEAR);

150
151
152
153
154
155
156
        // 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);
157
158
159
160
161
        }

        _initialized = true;
    }

162
163
    void CampVisApplication::deinit() {
        tgtAssert(_initialized, "Tried to deinitialize uninitialized CampVisApplication.");
164

165
166
        GLJobProc.stop();

167
168
        {
            // Deinit everything OpenGL related using the local context.
169
            tgt::GLContextScopedLock lock(_localContext);
170

171
172
            delete _errorTexture;

173
174
175
176
177
178
            // Deinit pipeline first
            for (std::vector<AbstractPipeline*>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
                (*it)->deinit();
            }

            // Now deinit painters:
179
            for (std::vector< std::pair<AbstractPipeline*, CampVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
180
181
182
                it->second->deinit();
            }

183
            _mainWindow->deinit();
184
185
            QuadRenderer::deinit();

186
187
            // deinit OpenGL and tgt
            tgt::deinitGL();
188
189
        }

190
        SimpleJobProcessor::deinit();
191
        OpenGLJobProcessor::deinit();
192
        PipelineFactory::deinit();
193

194
        tgt::GlContextManager::deinit();
195
196
        tgt::deinit();

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

200
201
202
        _initialized = false;
    }

203
204
    int CampVisApplication::run() {
        tgtAssert(_initialized, "Tried to run uninitialized CampVisApplication.");
205
206

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

209
210
        _mainWindow->show();

211
212
213
214
215
216
        // Start QApplication
        int toReturn = QApplication::exec();

        return toReturn;
    }

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

220
        // create canvas and painter for the pipeline and connect all together
221
        tgt::QtThreadedCanvas* canvas = new tgt::QtThreadedCanvas("CAMPVis", tgt::ivec2(512, 512));
222
        GLJobProc.registerContext(canvas);
223
224
        canvas->init();

225
        CampVisPainter* painter = new CampVisPainter(canvas, pipeline);
226
        canvas->setPainter(painter, false);
227
        pipeline->setCanvas(canvas);
228
        painter->setErrorTexture(_errorTexture);
229

230
231
232
        _visualizations.push_back(std::make_pair(pipeline, painter));
        _pipelines.push_back(pipeline);

233
234
        _mainWindow->addVisualizationPipelineWidget(name, canvas);

235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
        // 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;

252
253
254
255
256
        // 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);
        }
257
258
    }

259
260
261
262
263
264
    void CampVisApplication::registerDockWidget(Qt::DockWidgetArea area, QDockWidget* dock) {
        tgtAssert(dock != 0, "Dock widget must not be 0.");

        _mainWindow->addDockWidget(area, dock);
    }

265
266
267
268
269
    DataContainer* CampVisApplication::createAndAddDataContainer(const std::string& name) {
        DataContainer* dc = new DataContainer(name);
        _dataContainers.push_back(dc);
        s_DataContainersChanged();
        return dc;
270
271
    }

272
273
274
275
276
277
278
279
280
281
282
    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;
        }
283
284
285
        else {
            LINFO("Rebuilding shaders from file successful.");
        }
286
287
288
289
290
291
292
293
294
295

        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);
                }
            }
        }
    }

296

297
}