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 13.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
29
30
31
32
33
34
35
36
#include "cgt/assert.h"
#include "cgt/exception.h"
#include "cgt/glcanvas.h"
#include "cgt/glcontextmanager.h"
#include "cgt/gpucapabilities.h"
#include "cgt/init.h"
#include "cgt/opengljobprocessor.h"
#include "cgt/shadermanager.h"
#include "cgt/texturereadertga.h"
#include "cgt/qt/qtthreadedcanvas.h"
37

schultezub's avatar
schultezub committed
38
#include "application/campvispainter.h"
39
#include "application/gui/properties/propertywidgetfactory.h"
40
#include "application/gui/mainwindow.h"
CAMP C++ Builder's avatar
CAMP C++ Builder committed
41
#include "application/gui/mdi/mdidockablewindow.h"
42

43
#include "core/tools/simplejobprocessor.h"
44
#include "core/tools/stringutils.h"
45
#include "core/tools/quadrenderer.h"
46
#include "core/pipeline/abstractpipeline.h"
47
#include "core/datastructures/imagerepresentationconverter.h"
48
#include "core/pipeline/visualizationprocessor.h"
49

50
#include "modules/pipelinefactory.h"
51
#include "qtjobprocessor.h"
52

53
54
#include <QApplication>

55
#ifdef CAMPVIS_HAS_SCRIPTING
56
#include "scripting/gen_pipelineregistration.h"
57
58
#endif

schultezub's avatar
schultezub committed
59
namespace campvis {
60

61
    const std::string CampVisApplication::loggerCat_ = "CAMPVis.application.CampVisApplication";
62

63
    CampVisApplication::CampVisApplication(int& argc, char** argv) 
64
65
        : QApplication(argc, argv)
        , _localContext(0)
66
        , _mainWindow(0)
67
        , _errorTexture(nullptr)
68
        , _luaVmState(nullptr)
69
70
71
72
        , _initialized(false)
        , _argc(argc)
        , _argv(argv)
    {
73
74
        // Make Xlib and GLX thread safe under X11
        QApplication::setAttribute(Qt::AA_X11InitThreads);
75

76
77
        sigslot::signal_manager::init();
        sigslot::signal_manager::getRef().start();
78
        cgt::GlContextManager::init();
79
        OpenGLJobProcessor::init();
80
        SimpleJobProcessor::init();
81
        QtJobProcessor::init();
82
83
    }

84
    CampVisApplication::~CampVisApplication() {
85
        cgtAssert(_initialized == false, "Destructing initialized CampVisApplication, deinitialize first!");
86
87

        // delete everything in the right order:
88
89
90
        for (std::vector<PipelineRecord>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
            delete it->_painter;
            delete it->_pipeline;
91
        }
92
93
94
        for (std::vector<DataContainer*>::iterator it = _dataContainers.begin(); it != _dataContainers.end(); ++it) {
            delete *it;
        }
95
96
97

        sigslot::signal_manager::getRef().stop();
        sigslot::signal_manager::deinit();
98
99
    }

100
    void CampVisApplication::init() {
101
        cgtAssert(_initialized == false, "Tried to initialize CampVisApplication twice.");
102

103
104
105
        // Init CGT
        cgt::InitFeature::Features featureset = cgt::InitFeature::ALL;
        cgt::init(featureset);
106
107
        LogMgr.getConsoleLog()->addCat("", true);

108
109
        _mainWindow = new MainWindow(this);

110
        // create a local OpenGL context and init GL
111
112
        _localContext = new QtThreadedCanvas("", cgt::ivec2(16, 16));
        cgt::GlContextManager::getRef().registerContextAndInitGlew(_localContext, "Local Context");
113

114
        cgt::initGL(featureset);
115
        ShdrMgr.setDefaultGlslVersion("330");
116
117
        LGL_ERROR;

118
        QuadRenderer::init();
119
        
120
121
        if (_argc > 0) {
            // ugly hack
schultezub's avatar
schultezub committed
122
            std::string basePath(_argv[0]);
123
            basePath = cgt::FileSystem::parentDir(basePath);
124
125
126
            ShdrMgr.addPath(basePath);
            ShdrMgr.addPath(basePath + "/core/glsl");

127
            basePath = cgt::FileSystem::parentDir(cgt::FileSystem::parentDir(basePath));
schultezub's avatar
schultezub committed
128
129
130
            ShdrMgr.addPath(basePath);
            ShdrMgr.addPath(basePath + "/core/glsl");

131
132
133
134
135
136
#ifdef CAMPVIS_SOURCE_DIR
            {
                std::string sourcePath = CAMPVIS_SOURCE_DIR;
                ShdrMgr.addPath(sourcePath);
                ShdrMgr.addPath(sourcePath + "/core/glsl");
            }
schultezub's avatar
schultezub committed
137
#endif
138
139
        }

140
141
        _mainWindow->init();

142
143
144
        // ensure matching OpenGL specs
        LINFO("Using Graphics Hardware " << GpuCaps.getVendorAsString() << " " << GpuCaps.getGlRendererString() << " on " << GpuCaps.getOSVersionString());
        LINFO("Supported OpenGL " << GpuCaps.getGlVersion() << ", GLSL " << GpuCaps.getShaderVersion());
145
        if (GpuCaps.getGlVersion() < cgt::GpuCapabilities::GlVersion::CGT_GL_VERSION_3_3) {
146
147
            LERROR("Your system does not support OpenGL 3.3, which is mandatory. CAMPVis will probably not work as intended.");
        }
148
        if (GpuCaps.getShaderVersion() < cgt::GpuCapabilities::GlVersion::SHADER_VERSION_330) {
149
150
151
            LERROR("Your system does not support GLSL Shader Version 3.30, which is mandatory. CAMPVis will probably not work as intended.");
        }

152

153
        // load textureData from file
154
155
        cgt::TextureReaderTga trt;
        _errorTexture = trt.loadTexture(ShdrMgr.completePath("application/data/no_input.tga"), cgt::Texture::LINEAR);
156

157
158
159
160

#ifdef CAMPVIS_HAS_SCRIPTING
        // create and store Lua VM for this very pipeline
        _luaVmState = new LuaVmState();
161
        _luaVmState->redirectLuaPrint();
162
163
164
165
166
167
168
169

        // 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.");
170
        if (! _luaVmState->execString("require(\"cgt\")"))
171
172
173
174
175
176
177
178
            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.");
#endif
179
        GLCtxtMgr.releaseContext(_localContext, false);
180

181
182
183
184
185
186
187
        // 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);
188
189
        }

190
191
192
        GLJobProc.setContext(_localContext);
        GLJobProc.start();

193
194
195
        _initialized = true;
    }

196
    void CampVisApplication::deinit() {
197
        cgtAssert(_initialized, "Tried to deinitialize uninitialized CampVisApplication.");
198

199
200
201
202
        // Stop all pipeline threads.
        for (std::vector<PipelineRecord>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
            it->_pipeline->stop();
        }
203

204
205
        {
            // Deinit everything OpenGL related using the local context.
206
            cgt::GLContextScopedLock lock(_localContext);
207

208
209
            delete _errorTexture;

210
211
212
213
            // Deinit pipeline and painter first
            for (std::vector<PipelineRecord>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
                it->_pipeline->deinit();
                it->_painter->deinit();
214
215
            }

216
            _mainWindow->deinit();
217
218
            QuadRenderer::deinit();

219
220
            // deinit OpenGL and cgt
            cgt::deinitGL();
221
222
        }

223
224
        // MainWindow dtor needs a valid CampVisApplication, so we need to call it here instead of during destruction.
        delete _mainWindow;
225

226
        GLJobProc.stop();
227
228
229
        OpenGLJobProcessor::deinit();
        SimpleJobProcessor::deinit();

230
231
        cgt::GlContextManager::deinit();
        cgt::deinit();
232

233
234
235
236
        PropertyWidgetFactory::deinit();
        ImageRepresentationConverter::deinit();
        PipelineFactory::deinit();

237
238
239
        _initialized = false;
    }

240
    int CampVisApplication::run() {
241
        cgtAssert(_initialized, "Tried to run uninitialized CampVisApplication.");
242
243

        // disconnect OpenGL context from this thread so that the other threads can acquire an OpenGL context.
244
        //cgt::GlContextManager::getRef().releaseCurrentContext();
245

246
247
        _mainWindow->show();

248
249
250
251
252
253
        // Start QApplication
        int toReturn = QApplication::exec();

        return toReturn;
    }

254
    void CampVisApplication::addPipeline(const std::string& name, AbstractPipeline* pipeline) {
255
        cgtAssert(pipeline != 0, "Pipeline must not be 0.");
256

257
        // create canvas and painter for the pipeline and connect all together
258
        cgt::QtThreadedCanvas* canvas = new cgt::QtThreadedCanvas("CAMPVis", cgt::ivec2(512, 512));
259
260
        canvas->init();

261
        CampVisPainter* painter = new CampVisPainter(canvas, pipeline);
262
        canvas->setPainter(painter, false);
263
        pipeline->setCanvas(canvas);
264
        painter->setErrorTexture(_errorTexture);
265

266
        PipelineRecord pr = { pipeline, painter };
267
        _pipelines.push_back(pr);
268

CAMP C++ Builder's avatar
CAMP C++ Builder committed
269
        _pipelineWindows[pipeline] = _mainWindow->addVisualizationPipelineWidget(name, canvas);
270

271
        // initialize context (GLEW) and pipeline in OpenGL thread)
272
        initGlContextAndPipeline(canvas, pipeline);
273

274
#ifdef CAMPVIS_HAS_SCRIPTING
275
276
        if (! _luaVmState->injectObjectPointerToTable(pipeline, "campvis::AutoEvaluationPipeline *", "pipelines", static_cast<int>(_pipelines.size())))
        //if (! _luaVmState->injectObjectPointerToTableField(pipeline, "campvis::AutoEvaluationPipeline *", "pipelines", name))
277
278
            LERROR("Could not inject the pipeline into the Lua VM.");

279
        _luaVmState->execString("inspect(pipelines)");
280
281
#endif

282
        GLCtxtMgr.releaseContext(canvas, false);
283
        s_PipelinesChanged.emitSignal();
284
        pipeline->start();
285
286
    }

287
288
    void CampVisApplication::initGlContextAndPipeline(cgt::GLCanvas* canvas, AbstractPipeline* pipeline) {
        cgt::GlContextManager::getRef().registerContextAndInitGlew(canvas, pipeline->getName());
289
290
291
292
293
294

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

295
296
297
298
299
        // 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);
        }
300
301
    }

302
    void CampVisApplication::registerDockWidget(Qt::DockWidgetArea area, QDockWidget* dock) {
303
        cgtAssert(dock != 0, "Dock widget must not be 0.");
304
305
306
307

        _mainWindow->addDockWidget(area, dock);
    }

308
309
310
    DataContainer* CampVisApplication::createAndAddDataContainer(const std::string& name) {
        DataContainer* dc = new DataContainer(name);
        _dataContainers.push_back(dc);
311
        s_DataContainersChanged.emitSignal();
312
        return dc;
313
314
    }

315
316
    void CampVisApplication::rebuildAllShadersFromFiles() {
        // rebuilding all shaders has to be done from OpenGL context, use the local one.
317
        GLJobProc.enqueueJob(makeJobOnHeap(this, &CampVisApplication::triggerShaderRebuild));
318
319
320
321
322
323
324
    }

    void CampVisApplication::triggerShaderRebuild() {
        if (! ShdrMgr.rebuildAllShadersFromFile()) {
            LERROR("Could not rebuild all shaders from file.");
            return;
        }
325
326
327
        else {
            LINFO("Rebuilding shaders from file successful.");
        }
328

329
330
        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) {
331
332
333
334
335
336
337
                if (VisualizationProcessor* tester = dynamic_cast<VisualizationProcessor*>(*pit)) {
                	tester->invalidate(AbstractProcessor::INVALID_RESULT);
                }
            }
        }
    }

338
339
340
341
#ifdef CAMPVIS_HAS_SCRIPTING
    LuaVmState* CampVisApplication::getLuaVmState() {
        return _luaVmState;
    }
342

343
#endif
344

345
}