In January 2021 we will introduce a 10 GB quota for project repositories. Higher limits for individual projects will be available on request. Please see https://doku.lrz.de/display/PUBLIC/GitLab for more information.

Commit c56f094b authored by Jakob Weiss's avatar Jakob Weiss

minor fixes and clarifications regarding ScopedTypedData

parent ce377bcc
...@@ -44,10 +44,10 @@ namespace campvis { ...@@ -44,10 +44,10 @@ namespace campvis {
DataHandle DataContainer::addData(const std::string& name, AbstractData* data) { DataHandle DataContainer::addData(const std::string& name, AbstractData* data) {
if (name.empty()) { if (name.empty()) {
LERROR("Tried to add data with empty name to DataContainer."); LERROR("Tried to add data with empty name to DataContainer.");
return DataHandle(0); return DataHandle(nullptr);
} }
cgtAssert(data != 0, "The Data must not be 0."); cgtAssert(data != nullptr, "The Data must not be 0.");
cgtAssert(!name.empty(), "The data's name must not be empty."); cgtAssert(!name.empty(), "The data's name must not be empty.");
DataHandle dh(data); DataHandle dh(data);
...@@ -61,7 +61,7 @@ namespace campvis { ...@@ -61,7 +61,7 @@ namespace campvis {
return; return;
} }
cgtAssert(dh.getData() != 0, "The data in the DataHandle must not be 0!"); cgtAssert(dh, "The data in the DataHandle must not be 0!");
cgtAssert(!name.empty(), "The data's name must not be empty."); cgtAssert(!name.empty(), "The data's name must not be empty.");
_handles.erase(name); _handles.erase(name);
_handles.insert(std::make_pair(name, dh)); _handles.insert(std::make_pair(name, dh));
...@@ -81,7 +81,7 @@ namespace campvis { ...@@ -81,7 +81,7 @@ namespace campvis {
return a->second; return a->second;
} }
else { else {
return DataHandle(0); return DataHandle(nullptr);
} }
} }
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include "core/datastructures/abstractdata.h" #include "core/datastructures/abstractdata.h"
namespace campvis { namespace campvis {
DataHandle::DataHandle(AbstractData* data) DataHandle::DataHandle(AbstractData* data)
: _timestamp(clock()) : _timestamp(clock())
{ {
if (data) { if (data) {
...@@ -42,7 +42,7 @@ namespace campvis { ...@@ -42,7 +42,7 @@ namespace campvis {
} }
} }
DataHandle::DataHandle(const DataHandle& rhs) DataHandle::DataHandle(const DataHandle& rhs)
: _ptr(rhs._ptr) : _ptr(rhs._ptr)
, _timestamp(rhs._timestamp) , _timestamp(rhs._timestamp)
{ {
......
...@@ -36,18 +36,17 @@ namespace campvis { ...@@ -36,18 +36,17 @@ namespace campvis {
/** /**
* A DataHandle is responsible to manage the lifetime of an AbstractData instance. * A DataHandle is responsible to manage the lifetime of an AbstractData instance.
* Therefore, it implements a reference counting technique in cooperation with AbstractData. * Therefore, it implements a reference counting technique and automatically deletes instances when
* * no other references exist anymore.
* This class can be considered as thread safe under the following conditions: *
* * A single DataHandle instance must not be accessed from different threads. * This class can be considered as thread safe, since through the getData() and getWritableData() thread-safe
* * Concurrent access to the same AbstractData instance via different DataHandles is safe. * access is ensured.
* *
* \note For clarity: An AbstractData instance can be referenced by multiple DataHandles. As soon * \note For clarity: An AbstractData instance can be referenced by multiple DataHandles. As soon
* as it is afterwards reference by 0 DataHandles, the AbstractData instance will be destroyed. * as it is afterwards reference by 0 DataHandles, the AbstractData instance will be destroyed.
* Also remember that a DataHandle takes ownership of the given AbstractData instance. So do * Also remember that a DataHandle takes ownership of the given AbstractData instance. So do
* not delete it once it has been assigned to a DataHandle (respectively DataContainer) or mess * not delete it once it has been assigned to a DataHandle (respectively DataContainer) or mess
* with its reference counting! * with its reference counting!
* \note Reference counting implementation inspired from Scott Meyers: More Effective C++, Item 29
*/ */
class CAMPVIS_CORE_API DataHandle { class CAMPVIS_CORE_API DataHandle {
template<class T, bool isWritable> friend class ScopedTypedData; template<class T, bool isWritable> friend class ScopedTypedData;
...@@ -83,7 +82,7 @@ namespace campvis { ...@@ -83,7 +82,7 @@ namespace campvis {
/** /**
* Grants const access to the managed AbstractData instance. * Grants const access to the managed AbstractData instance.
* \return _data; * \return const pointer proxy class managing access
*/ */
template <class T = AbstractData> template <class T = AbstractData>
ScopedTypedData<T, false> getData() const { ScopedTypedData<T, false> getData() const {
...@@ -91,8 +90,8 @@ namespace campvis { ...@@ -91,8 +90,8 @@ namespace campvis {
} }
/** /**
* Grants const access to the managed AbstractData instance. * Grants writable access to the managed AbstractData instance.
* \return _data; * \return non-const pointer proxy class managing the access
*/ */
template <class T = AbstractData> template <class T = AbstractData>
ScopedTypedData<T, true> getWritableData() { ScopedTypedData<T, true> getWritableData() {
...@@ -113,11 +112,11 @@ namespace campvis { ...@@ -113,11 +112,11 @@ namespace campvis {
} }
/** /**
* Explicit cast to bool, returns true if pointer is valid. Allows to check DataHandles * Explicit cast to bool, returns true if pointer is valid. Allows to check DataHandles
* conveniently using an if(dh) { [DataHandle is valid] } statement. * conveniently using an if(dh) { [DataHandle is valid] } statement.
* \return !empty() * \return !empty()
*/ */
operator bool() const { explicit operator bool() const {
return !empty(); return !empty();
} }
......
This diff is collapsed.
...@@ -72,23 +72,26 @@ namespace campvis { ...@@ -72,23 +72,26 @@ namespace campvis {
void VisualizationProcessor::createAndAttachTexture(GLint internalFormat, GLenum attachment, ScopedTypedData<RenderData, true>* renderData /*= nullptr*/) { void VisualizationProcessor::createAndAttachTexture(GLint internalFormat, GLenum attachment, ScopedTypedData<RenderData, true>* renderData /*= nullptr*/) {
cgtAssert(_fbo->isActive(), "Trying to attach a texture while FBO is not bound!"); cgtAssert(_fbo->isActive(), "Trying to attach a texture while FBO is not bound!");
// acqiure a new TextureUnit, so that we don't mess with other currently bound textures during texture upload... // acquire a new TextureUnit, so that we don't mess with other currently bound textures during texture upload...
cgt::TextureUnit rtUnit; cgt::TextureUnit rtUnit;
rtUnit.activate(); rtUnit.activate();
// Set OpenGL pixel alignment to 1 to avoid problems with NPOT textures // Set OpenGL pixel alignment to 1 to avoid problems with NPOT textures
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Check the render data if we can reuse a texture
cgt::Texture* tex = nullptr; cgt::Texture* tex = nullptr;
if (renderData) { if (renderData) {`
// check if we can get a GL representation of the desired texture
ImageRepresentationGL* glRep; ImageRepresentationGL* glRep;
if (attachment == GL_DEPTH_ATTACHMENT) if (attachment == GL_DEPTH_ATTACHMENT)
if(auto id = (*renderData)->getDepthTexture()) if(auto id = (*renderData)->getDepthTexture())
glRep = const_cast<ImageRepresentationGL*>(id->getRepresentation<ImageRepresentationGL>(false)); glRep = const_cast<ImageRepresentationGL*>(id->getRepresentation<ImageRepresentationGL>(false));
else else
if(auto id =(*renderData)->getColorTexture(_fbo->getNumColorAttachments())) if(auto id =(*renderData)->getColorTexture(_fbo->getNumColorAttachments())) //_fbo->getNumColorAttachments() is the index of the texture that is to be created
glRep = const_cast<ImageRepresentationGL*>(id->getRepresentation<ImageRepresentationGL>(false)); glRep = const_cast<ImageRepresentationGL*>(id->getRepresentation<ImageRepresentationGL>(false));
// check if the texture is compatible with what we want, and in that case detach from the old RenderTargetData
if (glRep) { if (glRep) {
tex = const_cast<cgt::Texture*>(glRep->getTexture()); tex = const_cast<cgt::Texture*>(glRep->getTexture());
if (tex->getType() != GL_TEXTURE_2D || tex->getDimensions() != getRenderTargetSize() if (tex->getType() != GL_TEXTURE_2D || tex->getDimensions() != getRenderTargetSize()
...@@ -96,13 +99,15 @@ namespace campvis { ...@@ -96,13 +99,15 @@ namespace campvis {
tex = nullptr; tex = nullptr;
else { else {
// somehow detach the cgt::Texture from the ImageRepresentationGL // somehow detach the cgt::Texture from the ImageRepresentationGL
// yes this is horrible code // yes this is horrible - however, we know that renderData has write access, ergo
// we can safely do this const_cast
const_cast<ImageData*>(glRep->getParent())->removeRepresentationUnsafe<ImageRepresentationGL>(); const_cast<ImageData*>(glRep->getParent())->removeRepresentationUnsafe<ImageRepresentationGL>();
} }
} }
} }
// if we could not get the texture from a previous render target, create a new one
if (!tex) { if (!tex) {
// create texture // create texture
tex = new cgt::Texture(GL_TEXTURE_2D, getRenderTargetSize(), internalFormat, cgt::Texture::LINEAR); tex = new cgt::Texture(GL_TEXTURE_2D, getRenderTargetSize(), internalFormat, cgt::Texture::LINEAR);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment