#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 #include #include 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(); handle->object()->create(args); return handle; } BoundVertexBufferHandle bindVertexBuffer(BufferHandle & handle) { return this->bind(handle); } void unbindVertexBuffer(void) { BufferHandle nullHandle; this->bindVertexBuffer(nullHandle); } BoundIndexBufferHandle bindIndexBuffer(BufferHandle & handle) { return this->bind(handle); } void unbindIndexBuffer(void) { BufferHandle nullHandle; this->bindIndexBuffer(nullHandle); } BoundPixelPackBufferHandle bindPixelPackBuffer(BufferHandle & handle) { return this->bind(handle); } void unbindPixelPackBuffer(void) { BufferHandle nullHandle; this->bindPixelPackBuffer(nullHandle); } BoundPixelUnpackBufferHandle bindPixelUnpackBuffer(BufferHandle & handle) { return this->bind(handle); } void unbindPixelUnpackBuffer(void) { BufferHandle nullHandle; this->bindPixelUnpackBuffer(nullHandle); } BoundUniformBufferHandle bindUniformBuffer(BufferHandle & handle, GLuint index, GLintptr offset, GLsizeiptr size) { return this->bind(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(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(); handle->object()->create(args); return handle; } BoundRenderbufferHandle bindRenderbuffer(RenderbufferHandle & handle) { return this->bind(handle); } void unbindRenderbuffer(void) { RenderbufferHandle nullHandle; this->bindRenderbuffer(nullHandle); } VertexShaderHandle createVertexShader(const VertexShaderArguments & args) { VertexShaderHandle handle = this->createHandle(); handle->object()->create(args); return handle; } BoundVertexShaderHandle bindVertexShader(VertexShaderHandle & handle) { return this->bind(handle, VertexShaderBindingParams()); } void unbindVertexShader(void) { VertexShaderHandle nullHandle; this->bindVertexShader(nullHandle); } GeometryShaderHandle createGeometryShader(const GeometryShaderArguments & args) { GeometryShaderHandle handle = this->createHandle(); handle->object()->create(args); return handle; } BoundGeometryShaderHandle bindGeometryShader(GeometryShaderHandle & handle) { return this->bind(handle, GeometryShaderBindingParams()); } void unbindGeometryShader(void) { GeometryShaderHandle nullHandle; this->bindGeometryShader(nullHandle); } FragmentShaderHandle createFragmentShader(const FragmentShaderArguments & args) { FragmentShaderHandle handle = this->createHandle(); handle->object()->create(args); return handle; } BoundFragmentShaderHandle bindFragmentShader(FragmentShaderHandle & handle) { return this->bind(handle, FragmentShaderBindingParams()); } void unbindFragmentShader(void) { FragmentShaderHandle nullHandle; this->bindFragmentShader(nullHandle); } ProgramHandle createProgram(const ProgramArguments & args) { ProgramHandle handle = this->createHandle(); handle->object()->create(args); return handle; } BoundProgramHandle bindProgram(ProgramHandle & handle) { return this->bind(handle, ProgramBindingParams()); } void unbindProgram(void) { ProgramHandle nullHandle; this->bindProgram(nullHandle); } Texture2DHandle createTexture2D(const Texture2DArguments & args) { Texture2DHandle handle = this->createHandle(); handle->object()->create(args); return handle; } BoundTexture2DHandle bindTexture2D(Texture2DHandle & handle, GLint unit) { return this->bind(handle, Texture2DBindingParams(unit)); } void unbindTexture2D(GLint unit) { Texture2DHandle nullHandle; this->bindTexture2D(nullHandle, unit); } TextureCubeHandle createTextureCube(const TextureCubeArguments & args) { TextureCubeHandle handle = this->createHandle(); handle->object()->create(args); return handle; } BoundTextureCubeHandle bindTextureCube(TextureCubeHandle & handle, GLint unit) { return this->bind(handle, TextureCubeBindingParams(unit)); } void unbindTextureCube(GLint unit) { TextureCubeHandle nullHandle; this->bindTextureCube(nullHandle, unit); } FramebufferHandle createFramebuffer(const FramebufferArguments & args) { FramebufferHandle handle = this->createHandle(); handle->object()->create(args); return handle; } BoundReadFramebufferHandle bindReadFramebuffer(FramebufferHandle & handle) { FramebufferHandle nullHandle; this->bind(nullHandle, ReadDrawFramebufferBindingParams()); return this->bind(handle, ReadFramebufferBindingParams()); } void unbindReadFramebuffer(void) { FramebufferHandle nullHandle; this->bindReadFramebuffer(nullHandle); } BoundDrawFramebufferHandle bindDrawFramebuffer(FramebufferHandle & handle) { FramebufferHandle nullHandle; this->bind(nullHandle, ReadDrawFramebufferBindingParams()); return this->bind(handle, DrawFramebufferBindingParams()); } void unbindDrawFramebuffer(void) { FramebufferHandle nullHandle; this->bindDrawFramebuffer(nullHandle); } BoundReadDrawFramebufferHandle bindReadDrawFramebuffer(FramebufferHandle & handle) { FramebufferHandle nullHandle; this->bind(nullHandle, ReadFramebufferBindingParams()); this->bind(nullHandle, DrawFramebufferBindingParams()); return this->bind(handle, ReadDrawFramebufferBindingParams()); } void unbindReadDrawFramebuffer(void) { FramebufferHandle nullHandle; this->bindReadDrawFramebuffer(nullHandle); } private: template struct ObjectSafeFromObject { typedef typename detail::ObjectSafe::Type Type; }; template struct ObjectBoundFromObject { typedef typename detail::ObjectBound::Type Type; }; template struct ObjectFromBinding { typedef typename detail::ObjectBase::Type Type; }; template struct RefCountedPtrFromObject { typedef detail::RefCountedObject::Type>::Type, typename detail::BaseOf::Type> Type; }; template struct RefCountedSafeHandleFromObject { typedef typename ObjectSafeFromObject::Type ObjectSafeType; typedef detail::RefCountedObject::Type>::Type, typename detail::BaseOf::Type> Type; }; template struct RefCountedBindingHandleFromObject { typedef typename ObjectBoundFromObject::Type ObjectBoundType; typedef detail::RefCountedObject::Type>::Type, typename detail::BaseOf::Type> Type; }; template struct RefCountedBindingHandleFromBinding { typedef detail::RefCountedObject::Type>::Type, typename detail::BaseOf::Type> Type; }; template struct PtrFromObject { typedef detail::ObjectSharedPointer::Type>::Type, typename detail::BaseOf::Type> Type; }; template struct SafeHandleFromObject { typedef typename ObjectSafeFromObject::Type ObjectSafeType; typedef detail::ObjectSharedPointer::Type>::Type, typename detail::BaseOf::Type> Type; }; template struct BindingHandleFromObject { typedef typename ObjectBoundFromObject::Type ObjectBoundType; typedef detail::ObjectSharedPointer::Type>::Type, typename detail::BaseOf::Type> Type; }; template struct SafeHandleFromBinding { typedef typename SafeHandleFromObject::Type>::Type Type; }; template struct BindingHandleFromBinding { typedef detail::ObjectSharedPointer::Type>::Type, typename detail::BaseOf::Type> Type; }; typedef Object ObjectType; typedef RefCountedPtrFromObject::Type RefCountedPtrType; typedef std::map RefCountedPtrPtrMap; typedef RefCountedPtrPtrMap::const_iterator RefCountedPtrPtrMapConstIterator; typedef RefCountedPtrPtrMap::iterator RefCountedPtrPtrMapIterator; typedef RefCountedPtrPtrMap::value_type RefCountedPtrPtrMapValue; typedef std::pair BindingTarget; typedef BoundObjectHandle::RefCountedObjectType RefCountedBindingType; typedef std::map 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 void initializeTarget(const TBindingParams & params) { typedef TBinding BindingType; typedef typename RefCountedBindingHandleFromBinding::Type RefCountedBindingHandleType; const BindingTarget bt = BindingTarget(params.target, params.unit); RefCountedBindingHandleType * binding = 0; this->m_bindings.insert(RefCountedBindingPtrMapValue(bt, binding)); } template void terminateTarget(const TBindingParams & params) { typedef TBinding BindingType; typedef typename SafeHandleFromBinding::Type SafeHandleType; SafeHandleType nullHandle; this->bind(nullHandle, params); } void initializeTargets(void) { this->initializeTarget(VertexBufferBindingParams () ); this->initializeTarget(IndexBufferBindingParams () ); this->initializeTarget(PixelPackBufferBindingParams () ); this->initializeTarget(PixelUnpackBufferBindingParams () ); this->initializeTarget(RenderbufferBindingParams () ); this->initializeTarget(VertexShaderBindingParams () ); this->initializeTarget(GeometryShaderBindingParams () ); this->initializeTarget(FragmentShaderBindingParams () ); this->initializeTarget(ProgramBindingParams () ); this->initializeTarget(ReadFramebufferBindingParams () ); this->initializeTarget(DrawFramebufferBindingParams () ); this->initializeTarget(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; im_maxUniformBuffers; ++i) { this->initializeTarget(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; im_maxFeedbackBuffers; ++i) { this->initializeTarget(FeedbackBufferBindingParams(GLuint(i), 0, 0)); } } } { GLint texUnits = 0; glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &texUnits); this->m_maxTextureUnits = int(texUnits); for (int i=0; im_maxTextureUnits; ++i) { this->initializeTarget(Texture2DBindingParams (GLint(i))); this->initializeTarget(TextureCubeBindingParams (GLint(i))); } } } void terminateTargets(void) { this->terminateTarget(VertexBufferBindingParams () ); this->terminateTarget(IndexBufferBindingParams () ); this->terminateTarget(PixelPackBufferBindingParams () ); this->terminateTarget(PixelUnpackBufferBindingParams () ); this->terminateTarget(RenderbufferBindingParams () ); this->terminateTarget(VertexShaderBindingParams () ); this->terminateTarget(GeometryShaderBindingParams () ); this->terminateTarget(FragmentShaderBindingParams () ); this->terminateTarget(ProgramBindingParams () ); this->terminateTarget(ReadFramebufferBindingParams () ); this->terminateTarget(DrawFramebufferBindingParams () ); this->terminateTarget(ReadDrawFramebufferBindingParams () ); { for (int i=0; im_maxUniformBuffers; ++i) { this->terminateTarget(UniformBufferBindingParams(GLuint(i), 0, 0)); } this->m_maxUniformBuffers = 0; } { for (int i=0; im_maxFeedbackBuffers; ++i) { this->terminateTarget(FeedbackBufferBindingParams(GLuint(i), 0, 0)); } this->m_maxFeedbackBuffers = 0; } { for (int i=0; im_maxTextureUnits; ++i) { this->terminateTarget(Texture2DBindingParams (GLint(i))); this->terminateTarget(TextureCubeBindingParams (GLint(i))); } this->m_maxTextureUnits = 0; } } template 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 SafeHandleFromObject::Type createHandle(void) { typedef TObject ObjectType; typedef typename RefCountedPtrFromObject::Type RefCountedPtrType; typedef typename PtrFromObject::Type PtrType; typedef typename ObjectSafeFromObject::Type ObjectSafeType; typedef typename RefCountedSafeHandleFromObject::Type RefCountedSafeHandleType; typedef typename SafeHandleFromObject::Type SafeHandleType; ObjectType * object = this->createObject(); RefCountedPtrType * refCountedPtr = new RefCountedPtrType(object, typename detail::DeleterOf::Type()); PtrType ptr = PtrType(refCountedPtr); ObjectSafeType * objecSafe = new ObjectSafeType(ptr); RefCountedSafeHandleType * refCountedHandle = new RefCountedSafeHandleType(objecSafe, typename detail::DeleterOf::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 BindingHandleFromBinding::Type bind(typename SafeHandleFromBinding::Type & h, const typename detail::ParamsOf::Type & params = typename detail::ParamsOf::Type()) { typedef TBinding BindingType; typedef typename detail::ParamsOf::Type BindingParamsType; typedef typename BindingHandleFromBinding::Type BindingHandleType; typedef typename RefCountedBindingHandleFromBinding::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(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::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