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.6 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
        , _luaVmState(nullptr)
63
64
65
66
        , _initialized(false)
        , _argc(argc)
        , _argv(argv)
    {
67
68
        // Make Xlib and GLX thread safe under X11
        QApplication::setAttribute(Qt::AA_X11InitThreads);
69

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

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

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

        // delete everything in the right order:
81
82
83
        for (std::vector<PipelineRecord>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
            delete it->_painter;
            delete it->_pipeline;
84
        }
85
86
87
        for (std::vector<DataContainer*>::iterator it = _dataContainers.begin(); it != _dataContainers.end(); ++it) {
            delete *it;
        }
88
89
    }

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

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

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

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

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

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

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

130
131
        _mainWindow->init();

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

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

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

149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172

#ifdef CAMPVIS_HAS_SCRIPTING
        // create and store Lua VM for this very pipeline
        _luaVmState = new LuaVmState();

        // Let Lua know where CAMPVis modules are located
        if (! _luaVmState->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 (! _luaVmState->execString("require(\"campvis\")"))
            LERROR("Error setting up Lua VM.");
        if (! _luaVmState->execString("require(\"tgt\")"))
            LERROR("Error setting up Lua VM.");

        if (! _luaVmState->execString("pipelines = {}"))
            LERROR("Error setting up Lua VM.");

        if (! _luaVmState->execString("inspect = require 'inspect'"))
            LERROR("Error setting up Lua VM.");

        _luaVmState->redirectLuaPrint();
#endif

173
174
175
176
177
178
179
        // 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);
180
181
182
183
184
        }

        _initialized = true;
    }

185
186
    void CampVisApplication::deinit() {
        tgtAssert(_initialized, "Tried to deinitialize uninitialized CampVisApplication.");
187

188
189
        GLJobProc.stop();

190
191
        {
            // Deinit everything OpenGL related using the local context.
192
            tgt::GLContextScopedLock lock(_localContext);
193

194
195
            delete _errorTexture;

196
197
198
199
            // Deinit pipeline and painter first
            for (std::vector<PipelineRecord>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
                it->_pipeline->deinit();
                it->_painter->deinit();
200
201
            }

202
            _mainWindow->deinit();
203
204
            QuadRenderer::deinit();

205
206
            // deinit OpenGL and tgt
            tgt::deinitGL();
207
208
        }

209
        SimpleJobProcessor::deinit();
210
        OpenGLJobProcessor::deinit();
211
        PipelineFactory::deinit();
212

213
        tgt::GlContextManager::deinit();
214
215
        tgt::deinit();

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

219
220
221
        _initialized = false;
    }

222
223
    int CampVisApplication::run() {
        tgtAssert(_initialized, "Tried to run uninitialized CampVisApplication.");
224
225

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

228
229
        _mainWindow->show();

230
231
232
233
234
235
        // Start QApplication
        int toReturn = QApplication::exec();

        return toReturn;
    }

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

239
        // create canvas and painter for the pipeline and connect all together
240
        tgt::QtThreadedCanvas* canvas = new tgt::QtThreadedCanvas("CAMPVis", tgt::ivec2(512, 512));
241
        GLJobProc.registerContext(canvas);
242
243
        canvas->init();

244
        CampVisPainter* painter = new CampVisPainter(canvas, pipeline);
245
        canvas->setPainter(painter, false);
246
        pipeline->setCanvas(canvas);
247
        painter->setErrorTexture(_errorTexture);
248

249
        PipelineRecord pr = { pipeline, painter };
250
        _pipelines.push_back(pr);
251

252
253
        _mainWindow->addVisualizationPipelineWidget(name, canvas);

254
255
256
257
258
259
        // initialize context (GLEW) and pipeline in OpenGL thread)
        GLJobProc.enqueueJob(
            canvas, 
            makeJobOnHeap<CampVisApplication, tgt::GLCanvas*, AbstractPipeline*>(this, &CampVisApplication::initGlContextAndPipeline, canvas, pipeline), 
            OpenGLJobProcessor::SerialJob);

260
#ifdef CAMPVIS_HAS_SCRIPTING
261
262
        if (! _luaVmState->injectObjectPointerToTable(pipeline, "campvis::AutoEvaluationPipeline *", "pipelines", static_cast<int>(_pipelines.size())))
        //if (! _luaVmState->injectObjectPointerToTableField(pipeline, "campvis::AutoEvaluationPipeline *", "pipelines", name))
263
264
            LERROR("Could not inject the pipeline into the Lua VM.");

265
        _luaVmState->execString("inspect(pipelines)");
266
267
#endif

268
269
270
271
272
273
274
275
276
277
278
        s_PipelinesChanged();
    }

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

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

279
280
281
282
283
        // 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);
        }
284
285
    }

286
287
288
289
290
291
    void CampVisApplication::registerDockWidget(Qt::DockWidgetArea area, QDockWidget* dock) {
        tgtAssert(dock != 0, "Dock widget must not be 0.");

        _mainWindow->addDockWidget(area, dock);
    }

292
293
294
295
296
    DataContainer* CampVisApplication::createAndAddDataContainer(const std::string& name) {
        DataContainer* dc = new DataContainer(name);
        _dataContainers.push_back(dc);
        s_DataContainersChanged();
        return dc;
297
298
    }

299
300
301
302
303
304
305
306
307
308
309
    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;
        }
310
311
312
        else {
            LINFO("Rebuilding shaders from file successful.");
        }
313

314
315
        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) {
316
317
318
319
320
321
322
                if (VisualizationProcessor* tester = dynamic_cast<VisualizationProcessor*>(*pit)) {
                	tester->invalidate(AbstractProcessor::INVALID_RESULT);
                }
            }
        }
    }

323
324
325
326
327
#ifdef CAMPVIS_HAS_SCRIPTING
    LuaVmState* CampVisApplication::getLuaVmState() {
        return _luaVmState;
    }
#endif
328

329
}