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 12.1 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
#ifdef CAMPVIS_HAS_SCRIPTING
50
#include "scripting/gen_pipelineregistration.h"
51
52
#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
81
82
        for (std::vector<PipelineRecord>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
            delete it->_painter;
            delete it->_pipeline;
83
        }
84
85
86
        for (std::vector<DataContainer*>::iterator it = _dataContainers.begin(); it != _dataContainers.end(); ++it) {
            delete *it;
        }
87
88
    }

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

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

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

100
        tgt::GLContextScopedLock lock(_localContext);
101
        tgt::GlContextManager::getRef().registerContextAndInitGlew(_localContext);
102

103
        tgt::initGL(featureset);
104
        ShdrMgr.setDefaultGlslVersion("330");
105
106
        LGL_ERROR;

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

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

129
130
        _mainWindow->init();

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

141
142
        GLJobProc.start();
        GLJobProc.registerContext(_localContext);
143

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

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

        _initialized = true;
    }

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

163
164
        GLJobProc.stop();

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

169
170
            delete _errorTexture;

171
172
173
174
            // Deinit pipeline and painter first
            for (std::vector<PipelineRecord>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
                it->_pipeline->deinit();
                it->_painter->deinit();
175
176
            }

177
            _mainWindow->deinit();
178
179
            QuadRenderer::deinit();

180
181
            // deinit OpenGL and tgt
            tgt::deinitGL();
182
183
        }

184
        SimpleJobProcessor::deinit();
185
        OpenGLJobProcessor::deinit();
186
        PipelineFactory::deinit();
187

188
        tgt::GlContextManager::deinit();
189
190
        tgt::deinit();

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

194
195
196
        _initialized = false;
    }

197
198
    int CampVisApplication::run() {
        tgtAssert(_initialized, "Tried to run uninitialized CampVisApplication.");
199
200

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

203
204
        _mainWindow->show();

205
206
207
208
209
210
        // Start QApplication
        int toReturn = QApplication::exec();

        return toReturn;
    }

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

214
        // create canvas and painter for the pipeline and connect all together
215
        tgt::QtThreadedCanvas* canvas = new tgt::QtThreadedCanvas("CAMPVis", tgt::ivec2(512, 512));
216
        GLJobProc.registerContext(canvas);
217
218
        canvas->init();

219
        CampVisPainter* painter = new CampVisPainter(canvas, pipeline);
220
        canvas->setPainter(painter, false);
221
        pipeline->setCanvas(canvas);
222
        painter->setErrorTexture(_errorTexture);
223

224
225
        PipelineRecord pr = { pipeline, painter, nullptr };
        _pipelines.push_back(pr);
226

227
228
        _mainWindow->addVisualizationPipelineWidget(name, canvas);

229
230
231
232
233
234
        // initialize context (GLEW) and pipeline in OpenGL thread)
        GLJobProc.enqueueJob(
            canvas, 
            makeJobOnHeap<CampVisApplication, tgt::GLCanvas*, AbstractPipeline*>(this, &CampVisApplication::initGlContextAndPipeline, canvas, pipeline), 
            OpenGLJobProcessor::SerialJob);

235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
        // create and store Lua VM for this very pipeline
#ifdef CAMPVIS_HAS_SCRIPTING
        LuaVmState* lvs = new LuaVmState();

        // Let Lua know where CAMPVis modules are located
        if (!lvs->execString("package.cpath = '" CAMPVIS_LUA_MODS_PATH "'"))
            LERROR("Error setting up Lua VM.");

        // Load CAMPVis' core Lua module to have SWIG glue for AutoEvaluationPipeline available
        if (!lvs->execString("require(\"campvis\")"))
            LERROR("Error setting up Lua VM.");
        if (!lvs->execString("require(\"tgt\")"))
            LERROR("Error setting up Lua VM.");

//         if (!lvs->execFile(CAMPVIS_SOURCE_DIR "/application/scripting/inspect.lua"))
//             LERROR("Error setting up Lua VM.");

        if (!lvs->injectObjectPointer(pipeline, "campvis::AutoEvaluationPipeline *", "pipeline")) {
            LERROR("Could not inject the pipeline into the Lua VM.");
        }

        _pipelines.back()._luaVmState = std::shared_ptr<LuaVmState>(lvs);
#endif

259
260
261
262
263
264
265
266
267
268
269
        s_PipelinesChanged();
    }

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

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

270
271
272
273
274
        // 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);
        }
275
276
    }

277
278
279
280
281
282
    void CampVisApplication::registerDockWidget(Qt::DockWidgetArea area, QDockWidget* dock) {
        tgtAssert(dock != 0, "Dock widget must not be 0.");

        _mainWindow->addDockWidget(area, dock);
    }

283
284
285
286
287
    DataContainer* CampVisApplication::createAndAddDataContainer(const std::string& name) {
        DataContainer* dc = new DataContainer(name);
        _dataContainers.push_back(dc);
        s_DataContainersChanged();
        return dc;
288
289
    }

290
291
292
293
294
295
296
297
298
299
300
    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;
        }
301
302
303
        else {
            LINFO("Rebuilding shaders from file successful.");
        }
304

305
306
        for (std::vector<PipelineRecord>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
            for (std::vector<AbstractProcessor*>::const_iterator pit = it->_pipeline->getProcessors().begin(); pit != it->_pipeline->getProcessors().end(); ++pit) {
307
308
309
310
311
312
313
                if (VisualizationProcessor* tester = dynamic_cast<VisualizationProcessor*>(*pit)) {
                	tester->invalidate(AbstractProcessor::INVALID_RESULT);
                }
            }
        }
    }

314

315
}