10.12., 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

Started refactoring the CAMPVis OpenGL Wrapping API:

The new OpenGL wrapping API allows for full multi-threaded access to OpenGL contexts. Instead of one single thread scheduling all OpenGL jobs for all contexts, the new GlContextManager allows for OpenGL access from multiple threads while ensuring that each OpenGL context is acquired by only one thread at a time.

Detailed list of changes:
* tgt::GlContextManager keeping track of which threads acquire which OpenGL contexts and which threads currently have a context acquired.
* OpenGLJobProcessor does no longer schedules and execute the OpenGL calls for all existing contexts, but only for one single context that can be used for background tasks or other jobs that explicitly need a valid OpenGL context.
* AbstractPipeline now implements the Runnable interface and thus runs in it's own thread. This thread also owns the pipeline's OpenGL context.
* AbstractPipeline has a new pure virtual method executePipeline() that has to perform all computations done by the pipeline.
* AbstractPipeline now takes directly care of calling Painter::paint() of the pipeline's canvas (instead of signalling the Painter). However, the Painter interface needs further cleanup.
* AutoEvaluationPipeline was adapted to the new AbstractPipeline API, hence executing processors is no longer delegated to the OpenGLJobProcessor or the SimpleJobProcessor but entirely done in AutoEvaluationPipeline::executePipeline() and thus in the pipeline's thread.
* Adjusted CampVisApplication, DataContainerInspectorWidget, and GeometryTransferFunctionEditor to the new API.
parent 2e1956c9
...@@ -74,9 +74,7 @@ namespace campvis { ...@@ -74,9 +74,7 @@ namespace campvis {
sigslot::signal_manager::init(); sigslot::signal_manager::init();
sigslot::signal_manager::getRef().start(); sigslot::signal_manager::getRef().start();
_mainWindow = new MainWindow(this);
tgt::GlContextManager::init(); tgt::GlContextManager::init();
OpenGLJobProcessor::init(); OpenGLJobProcessor::init();
SimpleJobProcessor::init(); SimpleJobProcessor::init();
QtJobProcessor::init(); QtJobProcessor::init();
...@@ -106,11 +104,11 @@ namespace campvis { ...@@ -106,11 +104,11 @@ namespace campvis {
tgt::init(featureset); tgt::init(featureset);
LogMgr.getConsoleLog()->addCat("", true); LogMgr.getConsoleLog()->addCat("", true);
_mainWindow = new MainWindow(this);
// create a local OpenGL context and init GL // create a local OpenGL context and init GL
_localContext = new QtThreadedCanvas("", tgt::ivec2(16, 16)); _localContext = new QtThreadedCanvas("", tgt::ivec2(16, 16));
tgt::GlContextManager::getRef().registerContextAndInitGlew(_localContext, "Local Context");
tgt::GLContextScopedLock lock(_localContext);
tgt::GlContextManager::getRef().registerContextAndInitGlew(_localContext);
tgt::initGL(featureset); tgt::initGL(featureset);
ShdrMgr.setDefaultGlslVersion("330"); ShdrMgr.setDefaultGlslVersion("330");
...@@ -150,8 +148,6 @@ namespace campvis { ...@@ -150,8 +148,6 @@ namespace campvis {
LERROR("Your system does not support GLSL Shader Version 3.30, which is mandatory. CAMPVis will probably not work as intended."); LERROR("Your system does not support GLSL Shader Version 3.30, which is mandatory. CAMPVis will probably not work as intended.");
} }
GLJobProc.start();
GLJobProc.registerContext(_localContext);
// load textureData from file // load textureData from file
tgt::TextureReaderTga trt; tgt::TextureReaderTga trt;
...@@ -179,6 +175,7 @@ namespace campvis { ...@@ -179,6 +175,7 @@ namespace campvis {
if (! _luaVmState->execString("inspect = require 'inspect'")) if (! _luaVmState->execString("inspect = require 'inspect'"))
LERROR("Error setting up Lua VM."); LERROR("Error setting up Lua VM.");
#endif #endif
GLCtxtMgr.releaseContext(_localContext, false);
// parse argument list and create pipelines // parse argument list and create pipelines
QStringList pipelinesToAdd = this->arguments(); QStringList pipelinesToAdd = this->arguments();
...@@ -189,6 +186,9 @@ namespace campvis { ...@@ -189,6 +186,9 @@ namespace campvis {
addPipeline(pipelinesToAdd[i].toStdString(), p); addPipeline(pipelinesToAdd[i].toStdString(), p);
} }
GLJobProc.setContext(_localContext);
GLJobProc.start();
_initialized = true; _initialized = true;
} }
...@@ -236,7 +236,7 @@ namespace campvis { ...@@ -236,7 +236,7 @@ namespace campvis {
tgtAssert(_initialized, "Tried to run uninitialized CampVisApplication."); tgtAssert(_initialized, "Tried to run uninitialized CampVisApplication.");
// disconnect OpenGL context from this thread so that the other threads can acquire an OpenGL context. // disconnect OpenGL context from this thread so that the other threads can acquire an OpenGL context.
tgt::GlContextManager::getRef().releaseCurrentContext(); //tgt::GlContextManager::getRef().releaseCurrentContext();
_mainWindow->show(); _mainWindow->show();
...@@ -251,7 +251,6 @@ namespace campvis { ...@@ -251,7 +251,6 @@ namespace campvis {
// create canvas and painter for the pipeline and connect all together // create canvas and painter for the pipeline and connect all together
tgt::QtThreadedCanvas* canvas = new tgt::QtThreadedCanvas("CAMPVis", tgt::ivec2(512, 512)); tgt::QtThreadedCanvas* canvas = new tgt::QtThreadedCanvas("CAMPVis", tgt::ivec2(512, 512));
GLJobProc.registerContext(canvas);
canvas->init(); canvas->init();
CampVisPainter* painter = new CampVisPainter(canvas, pipeline); CampVisPainter* painter = new CampVisPainter(canvas, pipeline);
...@@ -265,10 +264,7 @@ namespace campvis { ...@@ -265,10 +264,7 @@ namespace campvis {
_pipelineWindows[pipeline] = _mainWindow->addVisualizationPipelineWidget(name, canvas); _pipelineWindows[pipeline] = _mainWindow->addVisualizationPipelineWidget(name, canvas);
// initialize context (GLEW) and pipeline in OpenGL thread) // initialize context (GLEW) and pipeline in OpenGL thread)
GLJobProc.enqueueJob( initGlContextAndPipeline(canvas, pipeline);
canvas,
makeJobOnHeap<CampVisApplication, tgt::GLCanvas*, AbstractPipeline*>(this, &CampVisApplication::initGlContextAndPipeline, canvas, pipeline),
OpenGLJobProcessor::SerialJob);
#ifdef CAMPVIS_HAS_SCRIPTING #ifdef CAMPVIS_HAS_SCRIPTING
if (! _luaVmState->injectObjectPointerToTable(pipeline, "campvis::AutoEvaluationPipeline *", "pipelines", static_cast<int>(_pipelines.size()))) if (! _luaVmState->injectObjectPointerToTable(pipeline, "campvis::AutoEvaluationPipeline *", "pipelines", static_cast<int>(_pipelines.size())))
...@@ -278,11 +274,13 @@ namespace campvis { ...@@ -278,11 +274,13 @@ namespace campvis {
_luaVmState->execString("inspect(pipelines)"); _luaVmState->execString("inspect(pipelines)");
#endif #endif
GLCtxtMgr.releaseContext(canvas, false);
s_PipelinesChanged.emitSignal(); s_PipelinesChanged.emitSignal();
pipeline->start();
} }
void CampVisApplication::initGlContextAndPipeline(tgt::GLCanvas* canvas, AbstractPipeline* pipeline) { void CampVisApplication::initGlContextAndPipeline(tgt::GLCanvas* canvas, AbstractPipeline* pipeline) {
tgt::GlContextManager::getRef().registerContextAndInitGlew(canvas); tgt::GlContextManager::getRef().registerContextAndInitGlew(canvas, pipeline->getName());
pipeline->init(); pipeline->init();
LGL_ERROR; LGL_ERROR;
...@@ -311,11 +309,10 @@ namespace campvis { ...@@ -311,11 +309,10 @@ namespace campvis {
void CampVisApplication::rebuildAllShadersFromFiles() { void CampVisApplication::rebuildAllShadersFromFiles() {
// rebuilding all shaders has to be done from OpenGL context, use the local one. // rebuilding all shaders has to be done from OpenGL context, use the local one.
GLJobProc.enqueueJob(_localContext, makeJobOnHeap(this, &CampVisApplication::triggerShaderRebuild), OpenGLJobProcessor::SerialJob); GLJobProc.enqueueJob(makeJobOnHeap(this, &CampVisApplication::triggerShaderRebuild));
} }
void CampVisApplication::triggerShaderRebuild() { void CampVisApplication::triggerShaderRebuild() {
if (! ShdrMgr.rebuildAllShadersFromFile()) { if (! ShdrMgr.rebuildAllShadersFromFile()) {
LERROR("Could not rebuild all shaders from file."); LERROR("Could not rebuild all shaders from file.");
return; return;
......
...@@ -161,7 +161,7 @@ namespace campvis { ...@@ -161,7 +161,7 @@ namespace campvis {
} }
void CampVisPainter::repaint() { void CampVisPainter::repaint() {
GLJobProc.enqueueJob(getCanvas(), makeJobOnHeap(this, &CampVisPainter::paint), OpenGLJobProcessor::PaintJob); //GLJobProc.enqueueJob(getCanvas(), makeJobOnHeap(this, &CampVisPainter::paint), OpenGLJobProcessor::PaintJob);
} }
void CampVisPainter::onRenderTargetChanged() { void CampVisPainter::onRenderTargetChanged() {
......
...@@ -67,15 +67,8 @@ namespace campvis { ...@@ -67,15 +67,8 @@ namespace campvis {
{ {
static_cast<Geometry1DTransferFunction*>(p_transferFunction.getTF())->addGeometry(TFGeometry1D::createQuad(tgt::vec2(0.f, 1.f), tgt::col4(0, 0, 0, 255), tgt::col4(255, 255, 255, 255))); static_cast<Geometry1DTransferFunction*>(p_transferFunction.getTF())->addGeometry(TFGeometry1D::createQuad(tgt::vec2(0.f, 1.f), tgt::col4(0, 0, 0, 255), tgt::col4(255, 255, 255, 255)));
makeCurrent(); GLCtxtMgr.registerContextAndInitGlew(this, "DataContainerInspector");
// Init GLEW for this context GLCtxtMgr.releaseContext(this, false);
GLenum err = glewInit();
if (err != GLEW_OK) {
// Problem: glewInit failed, something is seriously wrong.
tgtAssert(false, "glewInit failed");
std::cerr << "glewInit failed, error: " << glewGetErrorString(err) << std::endl;
exit(EXIT_FAILURE);
}
addProperty(p_currentSlice); addProperty(p_currentSlice);
addProperty(p_transferFunction); addProperty(p_transferFunction);
...@@ -117,7 +110,6 @@ namespace campvis { ...@@ -117,7 +110,6 @@ namespace campvis {
void DataContainerInspectorCanvas::init() { void DataContainerInspectorCanvas::init() {
initAllProperties(); initAllProperties();
GLJobProc.registerContext(this);
_paintShader = ShdrMgr.load("core/glsl/passthrough.vert", "application/glsl/datacontainerinspector.frag", ""); _paintShader = ShdrMgr.load("core/glsl/passthrough.vert", "application/glsl/datacontainerinspector.frag", "");
_paintShader->setAttributeLocation(0, "in_Position"); _paintShader->setAttributeLocation(0, "in_Position");
_paintShader->setAttributeLocation(1, "in_TexCoords"); _paintShader->setAttributeLocation(1, "in_TexCoords");
...@@ -147,7 +139,8 @@ namespace campvis { ...@@ -147,7 +139,8 @@ namespace campvis {
_textures.clear(); _textures.clear();
ShdrMgr.dispose(_paintShader); ShdrMgr.dispose(_paintShader);
delete _quad; delete _quad;
GLJobProc.deregisterContext(this);
GLCtxtMgr.removeContext(this);
} }
QSize DataContainerInspectorCanvas::sizeHint() const { QSize DataContainerInspectorCanvas::sizeHint() const {
...@@ -261,8 +254,11 @@ namespace campvis { ...@@ -261,8 +254,11 @@ namespace campvis {
void DataContainerInspectorCanvas::invalidate() { void DataContainerInspectorCanvas::invalidate() {
// only if inited // only if inited
if (_quad != 0 && _paintShader != 0) if (_quad != 0 && _paintShader != 0) {
GLJobProc.enqueueJob(this, makeJobOnHeap(this, &DataContainerInspectorCanvas::paint), OpenGLJobProcessor::PaintJob); // TODO: check, whether this should be done in an extra thread
tgt::GLContextScopedLock lock(this);
paint();
}
} }
void DataContainerInspectorCanvas::createQuad() { void DataContainerInspectorCanvas::createQuad() {
......
...@@ -467,10 +467,8 @@ namespace campvis { ...@@ -467,10 +467,8 @@ namespace campvis {
if (! filename.isEmpty()) { if (! filename.isEmpty()) {
// Texture access needs OpenGL context - dispatch method call: // Texture access needs OpenGL context - dispatch method call:
GLJobProc.enqueueJob( tgt::GLContextScopedLock lock(_canvas);
_canvas, saveToFile(handle, filename.toStdString());
makeJobOnHeap(&DataContainerInspectorWidget::saveToFile, handle, filename.toStdString()),
OpenGLJobProcessor::SerialJob);
} }
} }
} }
......
...@@ -70,8 +70,6 @@ namespace campvis { ...@@ -70,8 +70,6 @@ namespace campvis {
Geometry1DTransferFunctionEditor::~Geometry1DTransferFunctionEditor() { Geometry1DTransferFunctionEditor::~Geometry1DTransferFunctionEditor() {
disconnectFromTf(); disconnectFromTf();
if (OpenGLJobProcessor::isInited())
GLJobProc.deregisterContext(_canvas);
if (tgt::GlContextManager::isInited()) if (tgt::GlContextManager::isInited())
tgt::GlContextManager::getRef().removeContext(_canvas); tgt::GlContextManager::getRef().removeContext(_canvas);
} }
...@@ -177,9 +175,11 @@ namespace campvis { ...@@ -177,9 +175,11 @@ namespace campvis {
} }
void Geometry1DTransferFunctionEditor::sizeChanged(const tgt::ivec2& size) { void Geometry1DTransferFunctionEditor::sizeChanged(const tgt::ivec2& size) {
tbb::mutex::scoped_lock lock(_localMutex); {
for (std::vector<AbstractTFGeometryManipulator*>::iterator it = _manipulators.begin(); it != _manipulators.end(); ++it) { tbb::mutex::scoped_lock lock(_localMutex);
(*it)->setViewportSize(size); for (std::vector<AbstractTFGeometryManipulator*>::iterator it = _manipulators.begin(); it != _manipulators.end(); ++it) {
(*it)->setViewportSize(size);
}
} }
invalidate(); invalidate();
} }
...@@ -220,7 +220,9 @@ namespace campvis { ...@@ -220,7 +220,9 @@ namespace campvis {
} }
void Geometry1DTransferFunctionEditor::invalidate() { void Geometry1DTransferFunctionEditor::invalidate() {
GLJobProc.enqueueJob(_canvas, makeJobOnHeap(this, &Geometry1DTransferFunctionEditor::paint), OpenGLJobProcessor::PaintJob); // TODO: check, whether this should be done in an extra thread
tgt::GLContextScopedLock lock(_canvas);
paint();
} }
void Geometry1DTransferFunctionEditor::setupGUI() { void Geometry1DTransferFunctionEditor::setupGUI() {
...@@ -237,8 +239,8 @@ namespace campvis { ...@@ -237,8 +239,8 @@ namespace campvis {
_layout->addWidget(lblOpacityBottom, 3, 0, 1, 1, Qt::AlignRight); _layout->addWidget(lblOpacityBottom, 3, 0, 1, 1, Qt::AlignRight);
_canvas = new tgt::QtThreadedCanvas("", tgt::ivec2(256, 128), tgt::GLCanvas::RGBA_BUFFER, 0, false); _canvas = new tgt::QtThreadedCanvas("", tgt::ivec2(256, 128), tgt::GLCanvas::RGBA_BUFFER, 0, false);
GLJobProc.registerContext(_canvas); GLCtxtMgr.registerContextAndInitGlew(_canvas, "Geometry1DTransferFunctionEditor");
GLJobProc.enqueueJob(_canvas, makeJobOnHeap<tgt::GlContextManager, tgt::GLCanvas*>(tgt::GlContextManager::getPtr(), &tgt::GlContextManager::registerContextAndInitGlew, _canvas), OpenGLJobProcessor::SerialJob); GLCtxtMgr.releaseContext(_canvas, false);
_canvas->setPainter(this, false); _canvas->setPainter(this, false);
_layout->addWidget(_canvas, 1, 1, 3, 3); _layout->addWidget(_canvas, 1, 1, 3, 3);
...@@ -275,7 +277,7 @@ namespace campvis { ...@@ -275,7 +277,7 @@ namespace campvis {
_canvas->getEventHandler()->clearEventListeners(); _canvas->getEventHandler()->clearEventListeners();
for (std::vector<AbstractTFGeometryManipulator*>::iterator it = _manipulators.begin(); it != _manipulators.end(); ++it) { for (std::vector<AbstractTFGeometryManipulator*>::iterator it = _manipulators.begin(); it != _manipulators.end(); ++it) {
if (WholeTFGeometryManipulator* tester = dynamic_cast<WholeTFGeometryManipulator*>(*it)) { if (WholeTFGeometryManipulator* tester = dynamic_cast<WholeTFGeometryManipulator*>(*it)) {
tester->s_selected.disconnect(this); tester->s_selected.disconnect(this);
} }
delete *it; delete *it;
} }
......
...@@ -63,8 +63,6 @@ namespace campvis { ...@@ -63,8 +63,6 @@ namespace campvis {
Geometry2DTransferFunctionEditor::~Geometry2DTransferFunctionEditor() { Geometry2DTransferFunctionEditor::~Geometry2DTransferFunctionEditor() {
disconnectFromTf(); disconnectFromTf();
if (OpenGLJobProcessor::isInited())
GLJobProc.deregisterContext(_canvas);
if (tgt::GlContextManager::isInited()) if (tgt::GlContextManager::isInited())
tgt::GlContextManager::getRef().removeContext(_canvas); tgt::GlContextManager::getRef().removeContext(_canvas);
} }
...@@ -161,9 +159,11 @@ namespace campvis { ...@@ -161,9 +159,11 @@ namespace campvis {
} }
void Geometry2DTransferFunctionEditor::sizeChanged(const tgt::ivec2& size) { void Geometry2DTransferFunctionEditor::sizeChanged(const tgt::ivec2& size) {
tbb::mutex::scoped_lock lock(_localMutex); {
for (std::vector<AbstractTFGeometryManipulator*>::iterator it = _manipulators.begin(); it != _manipulators.end(); ++it) { tbb::mutex::scoped_lock lock(_localMutex);
(*it)->setViewportSize(size); for (std::vector<AbstractTFGeometryManipulator*>::iterator it = _manipulators.begin(); it != _manipulators.end(); ++it) {
(*it)->setViewportSize(size);
}
} }
invalidate(); invalidate();
} }
...@@ -198,7 +198,9 @@ namespace campvis { ...@@ -198,7 +198,9 @@ namespace campvis {
} }
void Geometry2DTransferFunctionEditor::invalidate() { void Geometry2DTransferFunctionEditor::invalidate() {
GLJobProc.enqueueJob(_canvas, makeJobOnHeap(this, &Geometry2DTransferFunctionEditor::paint), OpenGLJobProcessor::PaintJob); // TODO: check, whether this should be done in an extra thread
tgt::GLContextScopedLock lock(_canvas);
paint();
} }
void Geometry2DTransferFunctionEditor::setupGUI() { void Geometry2DTransferFunctionEditor::setupGUI() {
...@@ -215,8 +217,8 @@ namespace campvis { ...@@ -215,8 +217,8 @@ namespace campvis {
_layout->addWidget(lblOpacityBottom, 3, 0, 1, 1, Qt::AlignRight); _layout->addWidget(lblOpacityBottom, 3, 0, 1, 1, Qt::AlignRight);
_canvas = new tgt::QtThreadedCanvas("", tgt::ivec2(256, 128), tgt::GLCanvas::RGBA_BUFFER, 0, false); _canvas = new tgt::QtThreadedCanvas("", tgt::ivec2(256, 128), tgt::GLCanvas::RGBA_BUFFER, 0, false);
GLJobProc.registerContext(_canvas); GLCtxtMgr.registerContextAndInitGlew(_canvas, "Geometry2DTransferFunctionEditor");
GLJobProc.enqueueJob(_canvas, makeJobOnHeap<tgt::GlContextManager, tgt::GLCanvas*>(tgt::GlContextManager::getPtr(), &tgt::GlContextManager::registerContextAndInitGlew, _canvas), OpenGLJobProcessor::SerialJob); GLCtxtMgr.releaseContext(_canvas, false);
_canvas->setPainter(this, false); _canvas->setPainter(this, false);
_layout->addWidget(_canvas, 1, 1, 3, 3); _layout->addWidget(_canvas, 1, 1, 3, 3);
......
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#include "tgt/exception.h" #include "tgt/exception.h"
#include "tgt/glcanvas.h" #include "tgt/glcanvas.h"
#include "tgt/glcontextmanager.h"
#include "tgt/painter.h"
#include "tgt/tgt_gl.h" #include "tgt/tgt_gl.h"
#include "core/pipeline/visualizationprocessor.h" #include "core/pipeline/visualizationprocessor.h"
...@@ -78,17 +80,18 @@ namespace campvis { ...@@ -78,17 +80,18 @@ namespace campvis {
tgtAssert(_data != 0, "Pointer to the DataContainer for this pipeline must not be 0!"); tgtAssert(_data != 0, "Pointer to the DataContainer for this pipeline must not be 0!");
_enabled = false; _enabled = false;
_pipelineDirty = true;
addProperty(_renderTargetID); addProperty(_renderTargetID);
addProperty(_canvasSize); addProperty(_canvasSize);
} }
AbstractPipeline::~AbstractPipeline() { AbstractPipeline::~AbstractPipeline() {
} }
void AbstractPipeline::init() { void AbstractPipeline::init() {
_renderTargetID.s_changed.connect<AbstractPipeline>(this, &AbstractPipeline::onPropertyChanged); _renderTargetID.s_changed.connect<AbstractPipeline>(this, &AbstractPipeline::onPropertyChanged);
_data->s_dataAdded.connect(this, &AbstractPipeline::onDataContainerDataAdded);
initAllProperties(); initAllProperties();
...@@ -104,6 +107,8 @@ namespace campvis { ...@@ -104,6 +107,8 @@ namespace campvis {
} }
void AbstractPipeline::deinit() { void AbstractPipeline::deinit() {
stop();
deinitAllProperties(); deinitAllProperties();
// deinitialize all processors: // deinitialize all processors:
...@@ -117,18 +122,51 @@ namespace campvis { ...@@ -117,18 +122,51 @@ namespace campvis {
} }
} }
_data->s_dataAdded.disconnect(this);
_renderTargetID.s_changed.disconnect(this); _renderTargetID.s_changed.disconnect(this);
// clear DataContainer // clear DataContainer
_data->clear(); _data->clear();
} }
void AbstractPipeline::run() {
std::unique_lock<std::mutex> lock(*tgt::GlContextManager::getRef().getGlMutexForContext(_canvas));
tgt::GlContextManager::getRef().acquireContext(_canvas, false);
while (! _stopExecution) {
if (_enabled && _pipelineDirty) {
// mark pipeline as not dirty
_pipelineDirty = false;
// execute pipeline
executePipeline();
// paint on canvas
// FIXME: clean up the whole painter crap...
_canvas->getPainter()->paint();
}
if (!_enabled || !_pipelineDirty) {
tgt::GlContextManager::getRef().releaseContext(_canvas, false);
_evaluationCondition.wait(lock);
tgt::GlContextManager::getRef().acquireContext(_canvas, false);
}
}
tgt::GlContextManager::getRef().releaseContext(_canvas, false);
}
void AbstractPipeline::stop() {
_stopExecution = true;
_evaluationCondition.notify_all();
Runnable::stop();
}
void AbstractPipeline::onPropertyChanged(const AbstractProperty* prop) { void AbstractPipeline::onPropertyChanged(const AbstractProperty* prop) {
if (prop == &_renderTargetID) { if (prop == &_renderTargetID) {
s_renderTargetChanged.emitSignal(); setPipelineDirty();
} }
else if (prop == &_canvasSize && _canvas != 0 && !_ignoreCanvasSizeUpdate) { else if (prop == &_canvasSize && _canvas != nullptr && !_ignoreCanvasSizeUpdate) {
if (_canvasSize.getValue() != _canvas->getSize()) { if (_canvasSize.getValue() != _canvas->getSize()) {
_ignoreCanvasSizeUpdate = true; _ignoreCanvasSizeUpdate = true;
_canvas->setSize(_canvasSize.getValue()); _canvas->setSize(_canvasSize.getValue());
...@@ -173,6 +211,30 @@ namespace campvis { ...@@ -173,6 +211,30 @@ namespace campvis {
} }
} }
void AbstractPipeline::executeProcessorAndCheckOpenGLState(AbstractProcessor* processor) {
AbstractPipeline::executeProcessor(processor);
#ifdef CAMPVIS_DEBUG
tgtAssert(getGlBool(GL_DEPTH_TEST) == false, "Invalid OpenGL state after processor execution, GL_DEPTH_TEST != false.");
tgtAssert(getGlBool(GL_SCISSOR_TEST) == false, "Invalid OpenGL state after processor execution, GL_SCISSOR_TEST != false.");
tgtAssert(getGlInt(GL_CULL_FACE_MODE) == GL_BACK, "Invalid OpenGL state after processor execution, GL_CULL_FACE_MODE != GL_BACk.");
tgtAssert(getGlInt(GL_DEPTH_FUNC) == GL_LESS, "Invalid OpenGL state after processor execution, GL_DEPTH_FUNC != GL_LESS.");
tgtAssert(getGlFloat(GL_DEPTH_CLEAR_VALUE) == 1.f, "Invalid OpenGL state after processor execution, GL_DEPTH_CLEAR_VALUE != 1.f.");
tgtAssert(getGlFloat(GL_RED_SCALE) == 1.f, "Invalid OpenGL state after processor execution, GL_RED_SCALE != 1.f.");
tgtAssert(getGlFloat(GL_GREEN_SCALE) == 1.f, "Invalid OpenGL state after processor execution, GL_GREEN_SCALE != 1.f.");
tgtAssert(getGlFloat(GL_BLUE_SCALE) == 1.f, "Invalid OpenGL state after processor execution, GL_BLUE_SCALE != 1.f.");
tgtAssert(getGlFloat(GL_ALPHA_SCALE) == 1.f, "Invalid OpenGL state after processor execution, GL_ALPHA_SCALE != 1.f.");
tgtAssert(getGlFloat(GL_RED_BIAS) == 0.f, "Invalid OpenGL state after processor execution, GL_RED_BIAS != 0.f.");
tgtAssert(getGlFloat(GL_GREEN_BIAS) == 0.f, "Invalid OpenGL state after processor execution, GL_GREEN_BIAS != 0.f.");
tgtAssert(getGlFloat(GL_BLUE_BIAS) == 0.f, "Invalid OpenGL state after processor execution, GL_BLUE_BIAS != 0.f.");
tgtAssert(getGlFloat(GL_ALPHA_BIAS) == 0.f, "Invalid OpenGL state after processor execution, GL_ALPHA_BIAS != 0.f.");
#endif
}
const std::vector<AbstractProcessor*>& AbstractPipeline::getProcessors() const { const std::vector<AbstractProcessor*>& AbstractPipeline::getProcessors() const {
return _processors; return _processors;
} }
...@@ -183,6 +245,7 @@ namespace campvis { ...@@ -183,6 +245,7 @@ namespace campvis {
void AbstractPipeline::setEnabled(bool enabled) { void AbstractPipeline::setEnabled(bool enabled) {
_enabled = enabled; _enabled = enabled;
setPipelineDirty();
} }
void AbstractPipeline::onEvent(tgt::Event* e) { void AbstractPipeline::onEvent(tgt::Event* e) {
...@@ -225,44 +288,10 @@ namespace campvis { ...@@ -225,44 +288,10 @@ namespace campvis {
_processors.push_back(processor); _processors.push_back(processor);
} }
void AbstractPipeline::lockGLContextAndExecuteProcessor(AbstractProcessor* processor) { void AbstractPipeline::setPipelineDirty() {
tgtAssert(_canvas != 0, "Set a valid canvas before calling this method!"); _pipelineDirty = true;
GLJobProc.enqueueJob(
_canvas,
makeJobOnHeap<AbstractPipeline, AbstractProcessor*>(this, &AbstractPipeline::executeProcessor, processor),
OpenGLJobProcessor::SerialJob);
}
void AbstractPipeline::executeProcessorAndCheckOpenGLState(AbstractProcessor* processor) {
AbstractPipeline::executeProcessor(processor);
#ifdef CAMPVIS_DEBUG
tgtAssert(getGlBool(GL_DEPTH_TEST) == false, "Invalid OpenGL state after processor execution, GL_DEPTH_TEST != false.");
tgtAssert(getGlBool(GL_SCISSOR_TEST) == false, "Invalid OpenGL state after processor execution, GL_SCISSOR_TEST != false.");
tgtAssert(getGlInt(GL_CULL_FACE_MODE) == GL_BACK, "Invalid OpenGL state after processor execution, GL_CULL_FACE_MODE != GL_BACk.");
tgtAssert(getGlInt(GL_DEPTH_FUNC) == GL_LESS, "Invalid OpenGL state after processor execution, GL_DEPTH_FUNC != GL_LESS.");
tgtAssert(getGlFloat(GL_DEPTH_CLEAR_VALUE) == 1.f, "Invalid OpenGL state after processor execution, GL_DEPTH_CLEAR_VALUE != 1.f.");
tgtAssert(getGlFloat(GL_RED_SCALE) == 1.f, "Invalid OpenGL state after processor execution, GL_RED_SCALE != 1.f."); if (_enabled)
tgtAssert(getGlFloat(GL_GREEN_SCALE) == 1.f, "Invalid OpenGL state after processor execution, GL_GREEN_SCALE != 1.f."); _evaluationCondition.notify_all();
tgtAssert(getGlFloat(GL_BLUE_SCALE) == 1.f, "Invalid OpenGL state after processor execution, GL_BLUE_SCALE != 1.f.");
tgtAssert(getGlFloat(GL_ALPHA_SCALE) == 1.f, "Invalid OpenGL state after processor execution, GL_ALPHA_SCALE != 1.f.");
tgtAssert(getGlFloat(GL_RED_BIAS) == 0.f, "Invalid OpenGL state after processor execution, GL_RED_BIAS != 0.f.");
tgtAssert(getGlFloat(GL_GREEN_BIAS) == 0.f, "Invalid OpenGL state after processor execution, GL_GREEN_BIAS != 0.f.");
tgtAssert(getGlFloat(GL_BLUE_BIAS) == 0.f, "Invalid OpenGL state after processor execution, GL_BLUE_BIAS != 0.f.");
tgtAssert(getGlFloat(GL_ALPHA_BIAS) == 0.f, "Invalid OpenGL state after processor execution, GL_ALPHA_BIAS != 0.f.");