Commit 0be65bc3 authored by Christian Schulte zu Berge's avatar Christian Schulte zu Berge
Browse files

Merge branch 'tgt-dll' into 'development'

Tgt Dll
parents da038689 464f1ff4
......@@ -27,11 +27,11 @@
#include "tgt/assert.h"
#include "tgt/exception.h"
#include "tgt/glcanvas.h"
#include "tgt/glcontextmanager.h"
#include "tgt/gpucapabilities.h"
#include "tgt/shadermanager.h"
#include "tgt/qt/qtapplication.h"
#include "tgt/qt/qtthreadedcanvas.h"
#include "tgt/qt/qtcontextmanager.h"
#include "tbb/compat/thread"
#include "application/campvispainter.h"
......@@ -61,7 +61,7 @@ namespace campvis {
QApplication::setAttribute(Qt::AA_X11InitThreads);
_mainWindow = new MainWindow(this);
tgt::QtContextManager::init();
tgt::GlContextManager::init();
OpenGLJobProcessor::init();
SimpleJobProcessor::init();
......@@ -85,23 +85,14 @@ namespace campvis {
void CampVisApplication::init() {
tgtAssert(_initialized == false, "Tried to initialize CampVisApplication twice.");
// 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);
}
// Init TGT
tgt::InitFeature::Features featureset = tgt::InitFeature::ALL;
tgt::init(featureset);
LogMgr.getConsoleLog()->addCat("", true);
// create a local OpenGL context and init GL
_localContext = tgt::GlContextManager::getRef().createContext("AppContext", "", tgt::ivec2(16, 16));
tgtAssert(_localContext != 0, "Could not create local OpenGL context");
_localContext = new QtThreadedCanvas("", tgt::ivec2(16, 16));
tgt::GlContextManager::getRef().registerContextAndInitGlew(_localContext);
tgt::GLContextScopedLock lock(_localContext);
......@@ -143,18 +134,18 @@ namespace campvis {
LERROR("Your system does not support GLSL Shader Version 3.30, which is mandatory. CAMPVis will probably not work as intended.");
}
// init pipeline first
for (std::vector<AbstractPipeline*>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
(*it)->init();
}
GLJobProc.start();
GLJobProc.registerContext(_localContext);
// Now init painters:
for (std::vector< std::pair<AbstractPipeline*, CampVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
it->second->init();
// 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);
}
GLJobProc.start();
GLJobProc.registerContext(_localContext);
_initialized = true;
}
......@@ -188,7 +179,7 @@ namespace campvis {
OpenGLJobProcessor::deinit();
PipelineFactory::deinit();
tgt::QtContextManager::deinit();
tgt::GlContextManager::deinit();
tgt::deinit();
// MainWindow dtor needs a valid CampVisApplication, so we need to call it here instead of during destruction.
......@@ -214,30 +205,8 @@ namespace campvis {
void CampVisApplication::addPipeline(const std::string& name, AbstractPipeline* pipeline) {
tgtAssert(pipeline != 0, "Pipeline must not be 0.");
// if CAMPVis is already fully initialized, we need to temporarily shut down its
// OpenGL job processor, since we need to create a new context.
if (_initialized) {
GLJobProc.pause();
{
tgt::QtThreadedCanvas* canvas = dynamic_cast<tgt::QtThreadedCanvas*>(tgt::GlContextManager::getRef().createContext(name, "CAMPVis", tgt::ivec2(512, 512)));
tgtAssert(canvas != 0, "Dynamic cast failed. This should not be the case, since we initialized the GlContextManager singleton with a QtContextManager.");
tgt::GLContextScopedLock lock(canvas);
addPipelineImpl(canvas, name, pipeline);
}
GLJobProc.resume();
}
else {
tgt::QtThreadedCanvas* canvas = dynamic_cast<tgt::QtThreadedCanvas*>(tgt::GlContextManager::getRef().createContext(name, "CAMPVis", tgt::ivec2(512, 512)));
tgtAssert(canvas != 0, "Dynamic cast failed. This should not be the case, since we initialized the GlContextManager singleton with a QtContextManager.");
addPipelineImpl(canvas, name, pipeline);
}
s_PipelinesChanged();
}
void CampVisApplication::addPipelineImpl(tgt::QtThreadedCanvas* canvas, const std::string& name, AbstractPipeline* pipeline) {
// create canvas and painter for the pipeline and connect all together
tgt::QtThreadedCanvas* canvas = new tgt::QtThreadedCanvas("CAMPVis", tgt::ivec2(512, 512));
GLJobProc.registerContext(canvas);
canvas->init();
......@@ -248,16 +217,24 @@ namespace campvis {
_visualizations.push_back(std::make_pair(pipeline, painter));
_pipelines.push_back(pipeline);
if (_initialized) {
LGL_ERROR;
_mainWindow->addVisualizationPipelineWidget(name, canvas);
// 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;
painter->init();
canvas->getPainter()->init();
LGL_ERROR;
}
tgt::GlContextManager::getRef().releaseCurrentContext();
_mainWindow->addVisualizationPipelineWidget(name, canvas);
// enable pipeline and invalidate all processors
pipeline->setEnabled(true);
......
......@@ -130,7 +130,8 @@ namespace campvis {
sigslot::signal0<> s_DataContainersChanged;
private:
void addPipelineImpl(tgt::QtThreadedCanvas* canvas, const std::string& name, AbstractPipeline* pipeline);
void initGlContextAndPipeline(tgt::GLCanvas* canvas, AbstractPipeline* pipeline);
/// All pipelines
std::vector<AbstractPipeline*> _pipelines;
......
......@@ -29,7 +29,7 @@
#include "tgt/painter.h"
#include "tgt/event/eventlistener.h"
#include "tgt/event/mouseevent.h"
#include "tgt/qt/qtcontextmanager.h"
#include "tgt/glcontextmanager.h"
#include "tgt/qt/qtthreadedcanvas.h"
#include "tbb/mutex.h"
......
......@@ -29,8 +29,6 @@
#include "tgt/filesystem.h"
#include "tgt/shadermanager.h"
#include "tgt/textureunit.h"
#include "tgt/qt/qtcontextmanager.h"
#include "tgt/qt/qtthreadedcanvas.h"
#ifdef CAMPVIS_HAS_MODULE_DEVIL
#include <IL/il.h>
......@@ -53,7 +51,7 @@
#include "application/gui/datacontainertreewidget.h"
#include "application/gui/qtdatahandle.h"
#include "application//gui/datacontainerfileloaderwidget.h"
#include "application/gui/datacontainerfileloaderwidget.h"
#include "modules/io/processors/genericimagereader.h"
#include <QFileDialog>
......
......@@ -27,8 +27,6 @@
#include "sigslot/sigslot.h"
#include "tgt/painter.h"
#include "tgt/qt/qtcontextmanager.h"
#include "tgt/qt/qtthreadedcanvas.h"
#include "tbb/mutex.h"
#include "application/gui/qtdatahandle.h"
......
......@@ -27,8 +27,6 @@
#include "sigslot/sigslot.h"
#include "tgt/painter.h"
#include "tgt/qt/qtcontextmanager.h"
#include "tgt/qt/qtthreadedcanvas.h"
#include "tbb/mutex.h"
#include "application/tools/bufferinglog.h"
......
......@@ -248,8 +248,8 @@ namespace campvis {
QLabel* lblOpacityBottom = new QLabel(tr("0%"), this);
_layout->addWidget(lblOpacityBottom, 3, 0, 1, 1, Qt::AlignRight);
_canvas = dynamic_cast<tgt::QtThreadedCanvas*>(tgt::GlContextManager::getRef().createContext("tfcanvas", "", tgt::ivec2(256, 128), tgt::GLCanvas::RGBA_BUFFER, false));
tgtAssert(_canvas != 0, "Could not cast to QtThreadedCanvas*, something is wrong here!");
_canvas = new tgt::QtThreadedCanvas("", tgt::ivec2(256, 128), tgt::GLCanvas::RGBA_BUFFER, false);
tgt::GlContextManager::getRef().registerContextAndInitGlew(_canvas);
GLJobProc.registerContext(_canvas);
_canvas->setPainter(this, false);
......
......@@ -229,8 +229,8 @@ namespace campvis {
QLabel* lblOpacityBottom = new QLabel(tr("0%"), this);
_layout->addWidget(lblOpacityBottom, 3, 0, 1, 1, Qt::AlignRight);
_canvas = dynamic_cast<tgt::QtThreadedCanvas*>(tgt::GlContextManager::getRef().createContext("tfcanvas ", "", tgt::ivec2(256, 128), tgt::GLCanvas::RGBA_BUFFER, false));
tgtAssert(_canvas != 0, "Could not cast to QtThreadedCanvas*, something is wrong here!");
_canvas = new tgt::QtThreadedCanvas("", tgt::ivec2(256, 128), tgt::GLCanvas::RGBA_BUFFER, false);
tgt::GlContextManager::getRef().registerContextAndInitGlew(_canvas);
GLJobProc.registerContext(_canvas);
_canvas->setPainter(this, false);
......
......@@ -90,6 +90,7 @@ IF(WIN32)
LIST(APPEND CampvisGlobalDefinitions "-DNOMINMAX" "-D_CRT_SECURE_NO_DEPRECATE")
# Disable warnings for Microsoft compiler:
# C4251 class needs to have dll interface (used for std classes)
# C4290: C++ exception specification ignored except to indicate a function is
# not __declspec(nothrow)
# C4390: ';' : empty controlled statement found; is this the intent?
......@@ -97,7 +98,7 @@ IF(WIN32)
# C4503: The decorated name was longer than the compiler limit (4096), and was truncated.
# Occurs in AutoEvaluatePipeline due to some nested nested map-iterator-map. Could
# not be deactivated locally...
LIST(APPEND CampvisGlobalDefinitions /wd4290 /wd4390 /wd4503)
LIST(APPEND CampvisGlobalDefinitions /wd4251 /wd4290 /wd4390 /wd4503)
# enable parallel builds in Visual Studio
LIST(APPEND CampvisGlobalDefinitions /MP)
......@@ -112,6 +113,7 @@ IF(WIN32)
IF(CAMPVIS_SHARED_LIBS)
# Linking against Windows DLLs requires explicit instantiation of templates
LIST(APPEND CampvisGlobalDefinitions "-DDLL_TEMPLATE_INST")
LIST(APPEND CampvisGlobalDefinitions "-DCAMPVIS_DYNAMIC_LIBS")
IF(NOT CAMPVIS_GENERATE_MANIFEST)
# Do not embed manifest into binaries in debug mode (slows down incremental linking)
......
......@@ -14,6 +14,13 @@ IF(TGT_WITH_WMI)
LIST(APPEND CampvisGlobalExternalLibs "WbemUuid")
ENDIF(TGT_WITH_WMI)
IF(CAMPVIS_SHARED_LIBS)
SET(BUILD_SHARED_LIBS TRUE)
IF(MSVC)
ADD_DEFINITIONS("-DTGT_BUILD_DLL")
ENDIF()
ENDIF()
# headers
FILE(GLOB TGT_HEADERS *.h event/*.h navigation/*.h)
......@@ -74,14 +81,12 @@ IF(TGT_WITH_QT)
LIST(APPEND TGT_HEADERS
qt/qtapplication.h
qt/qtcanvas.h
qt/qtcontextmanager.h
qt/qtthreadedcanvas.h
qt/qttimer.h)
LIST(APPEND TGT_SOURCES
qt/qtapplication.cpp
qt/qtcanvas.cpp
qt/qtcontextmanager.cpp
qt/qtthreadedcanvas.cpp
qt/qttimer.cpp)
ENDIF(TGT_WITH_QT)
......@@ -92,9 +97,6 @@ ENDIF(TGT_WITH_QT)
################################################################################
ADD_LIBRARY(tgt ${TGT_SOURCES} ${TGT_HEADERS})
ADD_DEFINITIONS(${CampvisGlobalDefinitions} ${CampvisModulesDefinitions} ${QT_DEFINITIONS})
IF(CAMPVIS_SHARED_LIBS AND MSVC)
ADD_DEFINITIONS("-DTGT_BUILD_DLL")
ENDIF()
INCLUDE_DIRECTORIES(${CampvisGlobalIncludeDirs} ${CampvisModulesIncludeDirs})
TARGET_LINK_LIBRARIES(tgt ${CampvisGlobalExternalLibs} ${QT_LIBRARIES})
......
......@@ -196,7 +196,7 @@ protected:
};
/// ostream-operator
std::ostream& operator<< (std::ostream& o, const Bounds& b);
TGT_API std::ostream& operator<< (std::ostream& o, const Bounds& b);
} // namespace
......
......@@ -3,13 +3,14 @@
#include "tgt/exception.h"
#include "tgt/tgt_gl.h"
#include "tgt/types.h"
#include <set>
namespace tgt {
class VertexAttribute;
class BufferObject {
class TGT_API BufferObject {
public:
enum TargetType {
ARRAY_BUFFER = GL_ARRAY_BUFFER,
......
......@@ -194,6 +194,11 @@ public:
/// Getter
bool isInitialized() const { return initialized_; }
/// Acqures this canvas as current context
virtual void acquireAsCurrentContext() = 0;
/// Releases this canvas as current context
virtual void releaseAsCurrentContext() = 0;
protected:
/// Use the painter_ to actually paint something on the canvas
......
......@@ -4,8 +4,6 @@
namespace tgt {
GlContextManager* GlContextManager::singletonClass_ = 0;
GlContextManager::GlContextManager()
: _currentContext(0)
{
......@@ -13,22 +11,12 @@ namespace tgt {
GlContextManager::~GlContextManager()
{
for (std::map<std::string, GLCanvas*>::iterator it = _contexts.begin(); it != _contexts.end(); ++it) {
delete it->second;
for (std::set<GLCanvas*>::iterator it = _contexts.begin(); it != _contexts.end(); ++it) {
delete *it;
}
_contexts.clear();
}
GLCanvas* GlContextManager::getContextByKey(const std::string& key) {
tbb::mutex::scoped_lock lock(_localMutex);
std::map<std::string, GLCanvas*>::iterator it = _contexts.find(key);
if (it != _contexts.end())
return it->second;
else
return 0;
}
void GlContextManager::lock() {
_glMutex.lock();
}
......@@ -51,20 +39,6 @@ namespace tgt {
return _currentContext;
}
GlContextManager* GlContextManager::getPtr() {
tgtAssert( singletonClass_ != 0, "singletonClass_ has not been intitialized." );
return singletonClass_;
}
GlContextManager& GlContextManager::getRef() {
tgtAssert( singletonClass_ != 0 , "singletonClass_ has not been intitialized." );
return *singletonClass_;
}
bool GlContextManager::isInited() {
return (singletonClass_ != 0);
}
void GlContextManager::lockAndAcquire(GLCanvas* context) {
lock();
setCurrent(context);
......@@ -79,16 +53,52 @@ namespace tgt {
setCurrent(context);
}
void GlContextManager::registerContextAndInitGlew(GLCanvas* context) {
tgtAssert(context != 0, "Given context must not be 0.");
tgtAssert(_contexts.find(context) == _contexts.end(), "Tried to double register the same context.");
{
tbb::mutex::scoped_lock localLock(_localMutex);
_contexts.insert(context);
}
// Init GLEW for this context
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);
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
}
void GlContextManager::removeContext(GLCanvas* context) {
_currentContext = 0;
tbb::mutex::scoped_lock lock(_localMutex);
for (std::map<std::string, GLCanvas*>::iterator it = _contexts.begin(); it != _contexts.end(); ++it) {
if (it->second == context) {
std::set<GLCanvas*>::iterator it = _contexts.find(context);
if (it != _contexts.end()) {
_contexts.erase(it);
break;
}
}
void GlContextManager::setCurrent(GLCanvas* context) {
if (_currentContext != context) {
if (context == 0) {
// explicitely release OpenGL context
_currentContext->releaseAsCurrentContext();
_currentContext = 0;
}
else {
context->acquireAsCurrentContext();
LGL_ERROR;
_currentContext = context;
}
}
}
}
......@@ -3,19 +3,18 @@
#include "tgt/singleton.h"
#include "tgt/glcanvas.h"
#include "tgt/types.h"
#include <tbb/mutex.h> // TODO: TBB dependency in TGT is not that beautiful...
#include <map>
#include <set>
#include <string>
class QWidget;
namespace tgt {
class GLCanvas;
/**
* Manages multiple shared OpenGL contexts and offers methods to ensure that only one context is active at a time.
*/
class GlContextManager : public Singleton<GlContextManager> {
class TGT_API GlContextManager : public Singleton<GlContextManager> {
public:
/**
* Creates a new QtGLContext for the OpenGL context of \a canvas.
......@@ -29,68 +28,50 @@ namespace tgt {
virtual ~GlContextManager();
/**
* Get Pointer of the actual class
* @return Pointer of the actual class
* Registers \a canvas as new managed OpenGL context and initializes GLEW.
* \param canvas OpenGL context to register
*/
static GlContextManager* getPtr();
void registerContextAndInitGlew(GLCanvas* context);
/**
* Get reference of the actual class
* @return reference of the actual class
* Removes the OpenGL context \a context from the list of managed contexts.
* \param context Context to remove.
*/
static GlContextManager& getRef();
void removeContext(GLCanvas* context);
/**
* Has the actual class been inited?
* Returns the currently active OpenGL context.
* \return _currentContext
*/
static bool isInited();
GLCanvas* getCurrentContext() const;
/**
* Creates a new OpenGL context in a QtThreadedCanvas with the given arguments.
* Parameters are the same as in QtThreadedCanvas() but context sharing is enables per default.
*
* \note Must be called with the OpenGL mutex acquired!
*
* \note The created canvas/context is owned by this ContextManager. Hence, you may not
* delete it yourself!
*
* \param key Key of the context to create, must be unique.
* \param title Window title
* \param size Window size
* \return The newly created QtThreadedCanvas.
* Returns the mutex protecting the OpenGL context
* \return _glMutex
*/
virtual GLCanvas* createContext(
const std::string& key,
const std::string& title = "",
const ivec2& size = ivec2(GLCanvas::DEFAULT_WINDOW_WIDTH, GLCanvas::DEFAULT_WINDOW_HEIGHT),
const GLCanvas::Buffers buffers = GLCanvas::RGBADD,
bool shared = true) = 0;
tbb::mutex& getGlMutex();
/**
* Removes the OpenGL context \a context from the list of managed contexts.
* \param context Context to remove.
* Acquires \a context as current OpenGL context.
* \param context OpenGL context to acquire.
*/
virtual void removeContext(GLCanvas* context);
void acquireContext(GLCanvas* context);
/**
* Returns the OpenGL context with the given key \a key, 0 if no such context exists.
* \param key Key of the context to return.
* \return The OpenGL context with the given key \a key, 0 if no such context exists.
* Releases the currently bound OpenGL context.
*/
GLCanvas* getContextByKey(const std::string& key);
GLCanvas* getCurrentContext() const;
tbb::mutex& getGlMutex();
void acquireContext(GLCanvas* context);
void releaseCurrentContext();
/**
* Locks the OpenGL context mutex and acquires \a context as current OpenGl context.
* \param context OpenGL context to acquire.
*/
void lockAndAcquire(GLCanvas* context);
/**
* Releases the currently bound OpenGL context and also releases the OpenGL mutex.
*/
void releaseAndUnlock();
protected:
......@@ -99,7 +80,7 @@ namespace tgt {
* If \a context is already the current context, nothing will happen.
* \param context Context to set as current.
*/
virtual void setCurrent(GLCanvas* context) = 0;
void setCurrent(GLCanvas* context);
/**
* Locks the OpenGL device for other threads acessing the ContextManager.
......@@ -114,13 +95,11 @@ namespace tgt {
void unlock();
std::map<std::string, GLCanvas*> _contexts; ///< Map of all OpenGL contexts
std::set<GLCanvas*> _contexts; ///< Map of all OpenGL contexts
GLCanvas* _currentContext; ///< Current active OpenGL context
tbb::mutex _glMutex; ///< Mutex protecting OpenGL for multi-threaded access
tbb::mutex _localMutex; ///< local mutex to prodect _contexts
static GlContextManager* singletonClass_;
};
......
......@@ -44,7 +44,7 @@ namespace tgt {
around a given center (or, if you will, to rotate the camera around and focus it
on that center while it is continuously moving on a sphere).
*/
class Trackball : public Navigation {
class TGT_API Trackball : public Navigation {
public:
/// Constructor
......
......@@ -33,6 +33,7 @@
#include "tgt/tgt_gl.h"
#include "tgt/singleton.h"
#include "tgt/types.h"
#include <tbb/atomic.h>
#include <tbb/concurrent_vector.h>
#include <tbb/spin_mutex.h>
......@@ -45,7 +46,7 @@ namespace tgt {
*
* This class is to be considered as thread-safe.
*/
class OpenGLGarbageCollector : public Singleton<OpenGLGarbageCollector> {
class TGT_API OpenGLGarbageCollector : public Singleton<OpenGLGarbageCollector> {
friend class Singleton<OpenGLGarbageCollector>;
public:
......