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.3 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

schultezub's avatar
schultezub committed
49
namespace campvis {
50

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

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

65
        _mainWindow = new MainWindow(this);
66
        tgt::GlContextManager::init();
67
68

        OpenGLJobProcessor::init();
69
        SimpleJobProcessor::init();
70
71
    }

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

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

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

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

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

98
        tgt::GLContextScopedLock lock(_localContext);
99
        tgt::GlContextManager::getRef().registerContextAndInitGlew(_localContext);
100

101
        tgt::initGL(featureset);
102
        ShdrMgr.setDefaultGlslVersion("330");
103
104
        LGL_ERROR;

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

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

127
128
        _mainWindow->init();

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

139
140
        GLJobProc.start();
        GLJobProc.registerContext(_localContext);
141

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

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

        _initialized = true;
    }

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

161
162
        GLJobProc.stop();

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

167
168
            delete _errorTexture;

169
170
171
172
173
174
            // Deinit pipeline first
            for (std::vector<AbstractPipeline*>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
                (*it)->deinit();
            }

            // Now deinit painters:
175
            for (std::vector< std::pair<AbstractPipeline*, CampVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
176
177
178
                it->second->deinit();
            }

179
            _mainWindow->deinit();
180
181
            QuadRenderer::deinit();

182
183
            // deinit OpenGL and tgt
            tgt::deinitGL();
184
185
        }

186
        SimpleJobProcessor::deinit();
187
        OpenGLJobProcessor::deinit();
188
        PipelineFactory::deinit();
189

190
        tgt::GlContextManager::deinit();
191
192
        tgt::deinit();

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

196
197
198
        _initialized = false;
    }

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

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

205
206
        _mainWindow->show();

207
208
209
210
211
212
        // Start QApplication
        int toReturn = QApplication::exec();

        return toReturn;
    }

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

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

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

226
227
228
        _visualizations.push_back(std::make_pair(pipeline, painter));
        _pipelines.push_back(pipeline);

229
230
        _mainWindow->addVisualizationPipelineWidget(name, canvas);

231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
        // 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;

248
249
250
251
252
        // 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);
        }
253
254
    }

255
256
257
258
259
260
    void CampVisApplication::registerDockWidget(Qt::DockWidgetArea area, QDockWidget* dock) {
        tgtAssert(dock != 0, "Dock widget must not be 0.");

        _mainWindow->addDockWidget(area, dock);
    }

261
262
263
264
265
    DataContainer* CampVisApplication::createAndAddDataContainer(const std::string& name) {
        DataContainer* dc = new DataContainer(name);
        _dataContainers.push_back(dc);
        s_DataContainersChanged();
        return dc;
266
267
    }

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

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

292

293
}