vcglib/wrap/glw/context.h

652 lines
23 KiB
C++

#ifndef GLW_CONTEXT_H
#define GLW_CONTEXT_H
#include "./noncopyable.h"
#include "./objectdeleter.h"
#include "./buffer.h"
#include "./vertexshader.h"
#include "./geometryshader.h"
#include "./fragmentshader.h"
#include "./program.h"
#include "./renderbuffer.h"
#include "./texture2d.h"
#include "./texturecube.h"
#include "./framebuffer.h"
#include <string>
#include <set>
#include <map>
namespace glw
{
class Context : public detail::NonCopyable
{
friend class detail::ObjectDeleter;
public:
typedef detail::NonCopyable BaseType;
typedef Context ThisType;
Context(void)
: m_acquired (false)
, m_maxUniformBuffers (0)
, m_maxFeedbackBuffers (0)
, m_maxTextureUnits (0)
{
;
}
virtual ~Context(void)
{
this->release();
}
bool acquire(void)
{
//
this->release();
//
this->initializeTargets();
//
this->m_acquired = true;
(void)glGetError();
return this->m_acquired;
}
void release(void)
{
if (!this->isAcquired()) return;
this->m_acquired = false;
this->terminateTargets();
this->invalidateReferencesToAllObjects();
(void)glGetError();
}
bool isAcquired(void) const
{
return this->m_acquired;
}
bool isValid(void) const
{
return this->isAcquired();
}
BufferHandle createBuffer(const BufferArguments & args)
{
BufferHandle handle = this->createHandle<Buffer>();
handle->object()->create(args);
return handle;
}
BoundVertexBufferHandle bindVertexBuffer(BufferHandle & handle)
{
return this->bind<BoundVertexBuffer>(handle);
}
void unbindVertexBuffer(void)
{
BufferHandle nullHandle;
this->bindVertexBuffer(nullHandle);
}
BoundIndexBufferHandle bindIndexBuffer(BufferHandle & handle)
{
return this->bind<BoundIndexBuffer>(handle);
}
void unbindIndexBuffer(void)
{
BufferHandle nullHandle;
this->bindIndexBuffer(nullHandle);
}
BoundPixelPackBufferHandle bindPixelPackBuffer(BufferHandle & handle)
{
return this->bind<BoundPixelPackBuffer>(handle);
}
void unbindPixelPackBuffer(void)
{
BufferHandle nullHandle;
this->bindPixelPackBuffer(nullHandle);
}
BoundPixelUnpackBufferHandle bindPixelUnpackBuffer(BufferHandle & handle)
{
return this->bind<BoundPixelUnpackBuffer>(handle);
}
void unbindPixelUnpackBuffer(void)
{
BufferHandle nullHandle;
this->bindPixelUnpackBuffer(nullHandle);
}
BoundUniformBufferHandle bindUniformBuffer(BufferHandle & handle, GLuint index, GLintptr offset, GLsizeiptr size)
{
return this->bind<BoundUniformBuffer>(handle, UniformBufferBindingParams(index, offset, size));
}
void unbindUniformBuffer(GLuint index)
{
BufferHandle nullHandle;
this->bindUniformBuffer(nullHandle, index, 0, 0);
}
BoundFeedbackBufferHandle bindFeedbackBuffer(BufferHandle & handle, GLuint index, GLintptr offset, GLsizeiptr size)
{
return this->bind<BoundFeedbackBuffer>(handle, FeedbackBufferBindingParams(index, offset, size));
}
void unbindFeedbackBuffer(GLuint index)
{
BufferHandle nullHandle;
this->bindFeedbackBuffer(nullHandle, index, 0, 0);
}
RenderbufferHandle createRenderbuffer(const RenderbufferArguments & args)
{
RenderbufferHandle handle = this->createHandle<Renderbuffer>();
handle->object()->create(args);
return handle;
}
BoundRenderbufferHandle bindRenderbuffer(RenderbufferHandle & handle)
{
return this->bind<BoundRenderbuffer>(handle);
}
void unbindRenderbuffer(void)
{
RenderbufferHandle nullHandle;
this->bindRenderbuffer(nullHandle);
}
VertexShaderHandle createVertexShader(const VertexShaderArguments & args)
{
VertexShaderHandle handle = this->createHandle<VertexShader>();
handle->object()->create(args);
return handle;
}
BoundVertexShaderHandle bindVertexShader(VertexShaderHandle & handle)
{
return this->bind<BoundVertexShader>(handle, VertexShaderBindingParams());
}
void unbindVertexShader(void)
{
VertexShaderHandle nullHandle;
this->bindVertexShader(nullHandle);
}
GeometryShaderHandle createGeometryShader(const GeometryShaderArguments & args)
{
GeometryShaderHandle handle = this->createHandle<GeometryShader>();
handle->object()->create(args);
return handle;
}
BoundGeometryShaderHandle bindGeometryShader(GeometryShaderHandle & handle)
{
return this->bind<BoundGeometryShader>(handle, GeometryShaderBindingParams());
}
void unbindGeometryShader(void)
{
GeometryShaderHandle nullHandle;
this->bindGeometryShader(nullHandle);
}
FragmentShaderHandle createFragmentShader(const FragmentShaderArguments & args)
{
FragmentShaderHandle handle = this->createHandle<FragmentShader>();
handle->object()->create(args);
return handle;
}
BoundFragmentShaderHandle bindFragmentShader(FragmentShaderHandle & handle)
{
return this->bind<BoundFragmentShader>(handle, FragmentShaderBindingParams());
}
void unbindFragmentShader(void)
{
FragmentShaderHandle nullHandle;
this->bindFragmentShader(nullHandle);
}
ProgramHandle createProgram(const ProgramArguments & args)
{
ProgramHandle handle = this->createHandle<Program>();
handle->object()->create(args);
return handle;
}
BoundProgramHandle bindProgram(ProgramHandle & handle)
{
return this->bind<BoundProgram>(handle, ProgramBindingParams());
}
void unbindProgram(void)
{
ProgramHandle nullHandle;
this->bindProgram(nullHandle);
}
Texture2DHandle createTexture2D(const Texture2DArguments & args)
{
Texture2DHandle handle = this->createHandle<Texture2D>();
handle->object()->create(args);
return handle;
}
BoundTexture2DHandle bindTexture2D(Texture2DHandle & handle, GLint unit)
{
return this->bind<BoundTexture2D>(handle, Texture2DBindingParams(unit));
}
void unbindTexture2D(GLint unit)
{
Texture2DHandle nullHandle;
this->bindTexture2D(nullHandle, unit);
}
TextureCubeHandle createTextureCube(const TextureCubeArguments & args)
{
TextureCubeHandle handle = this->createHandle<TextureCube>();
handle->object()->create(args);
return handle;
}
BoundTextureCubeHandle bindTextureCube(TextureCubeHandle & handle, GLint unit)
{
return this->bind<BoundTextureCube>(handle, TextureCubeBindingParams(unit));
}
void unbindTextureCube(GLint unit)
{
TextureCubeHandle nullHandle;
this->bindTextureCube(nullHandle, unit);
}
FramebufferHandle createFramebuffer(const FramebufferArguments & args)
{
FramebufferHandle handle = this->createHandle<Framebuffer>();
handle->object()->create(args);
return handle;
}
BoundReadFramebufferHandle bindReadFramebuffer(FramebufferHandle & handle)
{
FramebufferHandle nullHandle;
this->bind<BoundReadDrawFramebuffer>(nullHandle, ReadDrawFramebufferBindingParams());
return this->bind<BoundReadFramebuffer>(handle, ReadFramebufferBindingParams());
}
void unbindReadFramebuffer(void)
{
FramebufferHandle nullHandle;
this->bindReadFramebuffer(nullHandle);
}
BoundDrawFramebufferHandle bindDrawFramebuffer(FramebufferHandle & handle)
{
FramebufferHandle nullHandle;
this->bind<BoundReadDrawFramebuffer>(nullHandle, ReadDrawFramebufferBindingParams());
return this->bind<BoundDrawFramebuffer>(handle, DrawFramebufferBindingParams());
}
void unbindDrawFramebuffer(void)
{
FramebufferHandle nullHandle;
this->bindDrawFramebuffer(nullHandle);
}
BoundReadDrawFramebufferHandle bindReadDrawFramebuffer(FramebufferHandle & handle)
{
FramebufferHandle nullHandle;
this->bind<BoundReadFramebuffer>(nullHandle, ReadFramebufferBindingParams());
this->bind<BoundDrawFramebuffer>(nullHandle, DrawFramebufferBindingParams());
return this->bind<BoundReadDrawFramebuffer>(handle, ReadDrawFramebufferBindingParams());
}
void unbindReadDrawFramebuffer(void)
{
FramebufferHandle nullHandle;
this->bindReadDrawFramebuffer(nullHandle);
}
private:
template <typename TObject>
struct ObjectSafeFromObject
{
typedef typename detail::ObjectSafe<TObject>::Type Type;
};
template <typename TObject>
struct ObjectBoundFromObject
{
typedef typename detail::ObjectBound<TObject>::Type Type;
};
template <typename TBinding>
struct ObjectFromBinding
{
typedef typename detail::ObjectBase<TBinding>::Type Type;
};
template <typename TObject>
struct RefCountedPtrFromObject
{
typedef detail::RefCountedObject<TObject, typename detail::DeleterOf<typename detail::RootOf<TObject>::Type>::Type, typename detail::BaseOf<TObject>::Type> Type;
};
template <typename TObject>
struct RefCountedSafeHandleFromObject
{
typedef typename ObjectSafeFromObject<TObject>::Type ObjectSafeType;
typedef detail::RefCountedObject<ObjectSafeType, typename detail::DeleterOf<typename detail::RootOf<ObjectSafeType>::Type>::Type, typename detail::BaseOf<ObjectSafeType>::Type> Type;
};
template <typename TObject>
struct RefCountedBindingHandleFromObject
{
typedef typename ObjectBoundFromObject<TObject>::Type ObjectBoundType;
typedef detail::RefCountedObject<ObjectBoundType, typename detail::DeleterOf<typename detail::RootOf<ObjectBoundType>::Type>::Type, typename detail::BaseOf<ObjectBoundType>::Type> Type;
};
template <typename TBinding>
struct RefCountedBindingHandleFromBinding
{
typedef detail::RefCountedObject<TBinding, typename detail::DeleterOf<typename detail::RootOf<TBinding>::Type>::Type, typename detail::BaseOf<TBinding>::Type> Type;
};
template <typename TObject>
struct PtrFromObject
{
typedef detail::ObjectSharedPointer<TObject, typename detail::DeleterOf<typename detail::RootOf<TObject>::Type>::Type, typename detail::BaseOf<TObject>::Type> Type;
};
template <typename TObject>
struct SafeHandleFromObject
{
typedef typename ObjectSafeFromObject<TObject>::Type ObjectSafeType;
typedef detail::ObjectSharedPointer<ObjectSafeType, typename detail::DeleterOf<typename detail::RootOf<ObjectSafeType>::Type>::Type, typename detail::BaseOf<ObjectSafeType>::Type> Type;
};
template <typename TObject>
struct BindingHandleFromObject
{
typedef typename ObjectBoundFromObject<TObject>::Type ObjectBoundType;
typedef detail::ObjectSharedPointer<ObjectBoundType, typename detail::DeleterOf<typename detail::RootOf<ObjectBoundType>::Type>::Type, typename detail::BaseOf<ObjectBoundType>::Type> Type;
};
template <typename TBinding>
struct SafeHandleFromBinding
{
typedef typename SafeHandleFromObject<typename ObjectFromBinding<TBinding>::Type>::Type Type;
};
template <typename TBinding>
struct BindingHandleFromBinding
{
typedef detail::ObjectSharedPointer<TBinding, typename detail::DeleterOf<typename detail::RootOf<TBinding>::Type>::Type, typename detail::BaseOf<TBinding>::Type> Type;
};
typedef Object ObjectType;
typedef RefCountedPtrFromObject<ObjectType>::Type RefCountedPtrType;
typedef std::map<Object *, RefCountedPtrType *> RefCountedPtrPtrMap;
typedef RefCountedPtrPtrMap::const_iterator RefCountedPtrPtrMapConstIterator;
typedef RefCountedPtrPtrMap::iterator RefCountedPtrPtrMapIterator;
typedef RefCountedPtrPtrMap::value_type RefCountedPtrPtrMapValue;
typedef std::pair<GLenum, GLint> BindingTarget;
typedef BoundObjectHandle::RefCountedObjectType RefCountedBindingType;
typedef std::map<BindingTarget, RefCountedBindingType *> RefCountedBindingPtrMap;
typedef RefCountedBindingPtrMap::const_iterator RefCountedBindingPtrMapConstIterator;
typedef RefCountedBindingPtrMap::iterator RefCountedBindingPtrMapIterator;
typedef RefCountedBindingPtrMap::value_type RefCountedBindingPtrMapValue;
bool m_acquired;
int m_maxUniformBuffers;
int m_maxFeedbackBuffers;
int m_maxTextureUnits;
RefCountedPtrPtrMap m_objects;
RefCountedBindingPtrMap m_bindings;
template <typename TBinding, typename TBindingParams>
void initializeTarget(const TBindingParams & params)
{
typedef TBinding BindingType;
typedef typename RefCountedBindingHandleFromBinding<BindingType>::Type RefCountedBindingHandleType;
const BindingTarget bt = BindingTarget(params.target, params.unit);
RefCountedBindingHandleType * binding = 0;
this->m_bindings.insert(RefCountedBindingPtrMapValue(bt, binding));
}
template <typename TBinding, typename TBindingParams>
void terminateTarget(const TBindingParams & params)
{
typedef TBinding BindingType;
typedef typename SafeHandleFromBinding<BindingType>::Type SafeHandleType;
SafeHandleType nullHandle;
this->bind<BindingType>(nullHandle, params);
}
void initializeTargets(void)
{
this->initializeTarget<BoundVertexBuffer, VertexBufferBindingParams >(VertexBufferBindingParams () );
this->initializeTarget<BoundIndexBuffer, IndexBufferBindingParams >(IndexBufferBindingParams () );
this->initializeTarget<BoundPixelPackBuffer, PixelPackBufferBindingParams >(PixelPackBufferBindingParams () );
this->initializeTarget<BoundPixelUnpackBuffer, PixelUnpackBufferBindingParams >(PixelUnpackBufferBindingParams () );
this->initializeTarget<BoundRenderbuffer, RenderbufferBindingParams >(RenderbufferBindingParams () );
this->initializeTarget<BoundVertexShader, VertexShaderBindingParams >(VertexShaderBindingParams () );
this->initializeTarget<BoundGeometryShader, GeometryShaderBindingParams >(GeometryShaderBindingParams () );
this->initializeTarget<BoundFragmentShader, FragmentShaderBindingParams >(FragmentShaderBindingParams () );
this->initializeTarget<BoundProgram, ProgramBindingParams >(ProgramBindingParams () );
this->initializeTarget<BoundReadFramebuffer, ReadFramebufferBindingParams >(ReadFramebufferBindingParams () );
this->initializeTarget<BoundDrawFramebuffer, DrawFramebufferBindingParams >(DrawFramebufferBindingParams () );
this->initializeTarget<BoundReadDrawFramebuffer, ReadDrawFramebufferBindingParams >(ReadDrawFramebufferBindingParams () );
{
this->m_maxUniformBuffers = 0;
if (GLEW_ARB_uniform_buffer_object)
{
GLint uniformBuffers = 0;
glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &uniformBuffers);
this->m_maxUniformBuffers = int(uniformBuffers);
for (int i=0; i<this->m_maxUniformBuffers; ++i)
{
this->initializeTarget<BoundUniformBuffer, UniformBufferBindingParams>(UniformBufferBindingParams(GLuint(i), 0, 0));
}
}
}
{
this->m_maxFeedbackBuffers = 0;
if (GLEW_EXT_transform_feedback)
{
GLint feedbackBuffers = 0;
glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &feedbackBuffers);
this->m_maxFeedbackBuffers = int(feedbackBuffers);
for (int i=0; i<this->m_maxFeedbackBuffers; ++i)
{
this->initializeTarget<BoundFeedbackBuffer, FeedbackBufferBindingParams>(FeedbackBufferBindingParams(GLuint(i), 0, 0));
}
}
}
{
GLint texUnits = 0;
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &texUnits);
this->m_maxTextureUnits = int(texUnits);
for (int i=0; i<this->m_maxTextureUnits; ++i)
{
this->initializeTarget<BoundTexture2D >(Texture2DBindingParams (GLint(i)));
this->initializeTarget<BoundTextureCube>(TextureCubeBindingParams (GLint(i)));
}
}
}
void terminateTargets(void)
{
this->terminateTarget<BoundVertexBuffer, VertexBufferBindingParams >(VertexBufferBindingParams () );
this->terminateTarget<BoundIndexBuffer, IndexBufferBindingParams >(IndexBufferBindingParams () );
this->terminateTarget<BoundPixelPackBuffer, PixelPackBufferBindingParams >(PixelPackBufferBindingParams () );
this->terminateTarget<BoundPixelUnpackBuffer, PixelUnpackBufferBindingParams >(PixelUnpackBufferBindingParams () );
this->terminateTarget<BoundRenderbuffer, RenderbufferBindingParams >(RenderbufferBindingParams () );
this->terminateTarget<BoundVertexShader, VertexShaderBindingParams >(VertexShaderBindingParams () );
this->terminateTarget<BoundGeometryShader, GeometryShaderBindingParams >(GeometryShaderBindingParams () );
this->terminateTarget<BoundFragmentShader, FragmentShaderBindingParams >(FragmentShaderBindingParams () );
this->terminateTarget<BoundProgram, ProgramBindingParams >(ProgramBindingParams () );
this->terminateTarget<BoundReadFramebuffer, ReadFramebufferBindingParams >(ReadFramebufferBindingParams () );
this->terminateTarget<BoundDrawFramebuffer, DrawFramebufferBindingParams >(DrawFramebufferBindingParams () );
this->terminateTarget<BoundReadDrawFramebuffer, ReadDrawFramebufferBindingParams >(ReadDrawFramebufferBindingParams () );
{
for (int i=0; i<this->m_maxUniformBuffers; ++i)
{
this->terminateTarget<BoundUniformBuffer, UniformBufferBindingParams>(UniformBufferBindingParams(GLuint(i), 0, 0));
}
this->m_maxUniformBuffers = 0;
}
{
for (int i=0; i<this->m_maxFeedbackBuffers; ++i)
{
this->terminateTarget<BoundFeedbackBuffer, FeedbackBufferBindingParams>(FeedbackBufferBindingParams(GLuint(i), 0, 0));
}
this->m_maxFeedbackBuffers = 0;
}
{
for (int i=0; i<this->m_maxTextureUnits; ++i)
{
this->terminateTarget<BoundTexture2D >(Texture2DBindingParams (GLint(i)));
this->terminateTarget<BoundTextureCube>(TextureCubeBindingParams (GLint(i)));
}
this->m_maxTextureUnits = 0;
}
}
template <typename TObject>
TObject * createObject(void)
{
typedef TObject ObjectType;
ObjectType * object = new ObjectType(this);
return object;
}
void destroyObject(Object * object)
{
GLW_ASSERT(object != 0);
object->destroy();
delete object;
}
template <typename TObject>
typename SafeHandleFromObject<TObject>::Type createHandle(void)
{
typedef TObject ObjectType;
typedef typename RefCountedPtrFromObject<ObjectType>::Type RefCountedPtrType;
typedef typename PtrFromObject<ObjectType>::Type PtrType;
typedef typename ObjectSafeFromObject<ObjectType>::Type ObjectSafeType;
typedef typename RefCountedSafeHandleFromObject<ObjectType>::Type RefCountedSafeHandleType;
typedef typename SafeHandleFromObject<TObject>::Type SafeHandleType;
ObjectType * object = this->createObject<ObjectType>();
RefCountedPtrType * refCountedPtr = new RefCountedPtrType(object, typename detail::DeleterOf<Object>::Type());
PtrType ptr = PtrType(refCountedPtr);
ObjectSafeType * objecSafe = new ObjectSafeType(ptr);
RefCountedSafeHandleType * refCountedHandle = new RefCountedSafeHandleType(objecSafe, typename detail::DeleterOf<ObjectSafeType>::Type());
SafeHandleType handle = SafeHandleType(refCountedHandle);
this->m_objects.insert(RefCountedPtrPtrMapValue(object, refCountedPtr));
return handle;
}
void noMoreReferencesTo(Object * object)
{
GLW_ASSERT(object != 0);
RefCountedPtrPtrMapIterator it = this->m_objects.find(object);
GLW_ASSERT(it != this->m_objects.end());
this->m_objects.erase(it);
this->destroyObject(object);
}
void invalidateReferencesToAllObjects(void)
{
for (RefCountedPtrPtrMapIterator it=this->m_objects.begin(); it!=this->m_objects.end(); ++it)
{
Object * object = it->first;
RefCountedPtrType * refPtr = it->second;
refPtr->setNull(false);
this->destroyObject(object);
}
}
template <typename TBinding>
typename BindingHandleFromBinding<TBinding>::Type bind(typename SafeHandleFromBinding<TBinding>::Type & h, const typename detail::ParamsOf<TBinding>::Type & params = typename detail::ParamsOf<TBinding>::Type())
{
typedef TBinding BindingType;
typedef typename detail::ParamsOf<TBinding>::Type BindingParamsType;
typedef typename BindingHandleFromBinding<BindingType>::Type BindingHandleType;
typedef typename RefCountedBindingHandleFromBinding<BindingType>::Type RefCountedBindingHandleType;
const BindingTarget bt = BindingTarget(params.target, params.unit);
RefCountedBindingPtrMapIterator it = this->m_bindings.find(bt);
GLW_ASSERT(it != this->m_bindings.end());
RefCountedBindingHandleType * currentBinding = static_cast<RefCountedBindingHandleType *>(it->second);
if (currentBinding != 0)
{
GLW_ASSERT(!currentBinding->isNull());
// WARNING: as state could have been changed outside GLW, uncommenting the following line may prevent correct binding.
//if (currentBinding->object() == Object) return UnsafeObjectType(currentBinding);
if (h.isNull()) currentBinding->object()->unbind();
currentBinding->setNull(true);
currentBinding->unref();
currentBinding = 0;
it->second = 0;
}
if (h.isNull()) return BindingHandleType();
BindingType * binding = new BindingType(h, params);
RefCountedBindingHandleType * newBinding = new RefCountedBindingHandleType(binding, typename detail::DeleterOf<BindingType>::Type());
newBinding->ref();
newBinding->object()->bind();
it->second = newBinding;
return BindingHandleType(newBinding);
}
};
namespace detail
{
inline void ObjectDeleter :: operator () (Object * object) const
{
if (object == 0) return;
object->context()->noMoreReferencesTo(object);
}
};
};
#endif // GLW_CONTEXT_H