diff --git a/wrap/glw/bookkeeping.h b/wrap/glw/bookkeeping.h new file mode 100644 index 00000000..b0a554fc --- /dev/null +++ b/wrap/glw/bookkeeping.h @@ -0,0 +1,582 @@ +#ifndef GLW_BOOKKEEPING_H +#define GLW_BOOKKEEPING_H + +#include "./common.h" + +namespace glw +{ + +class Context; + +namespace detail +{ + +template +class SharedObjectBase +{ + friend class Context; + + public: + + typedef void BaseType; + typedef SharedObjectBase ThisType; + typedef TObject ObjectType; + + bool isNull(void) const + { + return (this->m_object == 0); + } + + void setNull(void) + { + this->m_object = 0; + } + + const ObjectType * object(void) const + { + return this->m_object; + } + + ObjectType * object(void) + { + return this->m_object; + } + + void ref(void) + { + this->m_refCount++; + } + + void unref(void) + { + GLW_ASSERT(this->m_refCount > 0); + this->m_refCount--; + if (this->m_refCount == 0) + { + if (this->m_object != 0) + { + this->signalDestruction(); + } + delete this; + } + } + + protected: + + Context * m_context; + ObjectType * m_object; + int m_refCount; + + SharedObjectBase(Context * Context, ObjectType * Object) + : m_context (Context) + , m_object (Object) + , m_refCount (0) + { + GLW_ASSERT(this->m_context != 0); + GLW_ASSERT(this->m_object != 0); + } + + private: + + SharedObjectBase(const ThisType & other); + ThisType & operator = (const ThisType & other); + + inline void signalDestruction(void); +}; + +template +class SharedObject; + +template +class SharedObjectTraits +{ + public: + + typedef void BaseType; + typedef SharedObjectTraits ThisType; + typedef TObject ObjectType; + typedef TObjectBase ObjectBaseType; + typedef SharedObject SharedObjectBaseType; +}; + +template +class SharedObjectTraits +{ + public: + + typedef void BaseType; + typedef SharedObjectTraits ThisType; + typedef TObject ObjectType; + typedef void ObjectBaseType; + typedef SharedObjectBase SharedObjectBaseType; +}; + +template +class SharedObject : public SharedObjectTraits::SharedObjectBaseType +{ + friend class Context; + + public: + + typedef typename SharedObjectTraits::SharedObjectBaseType BaseType; + typedef SharedObject ThisType; + typedef TObject ObjectType; + + const ObjectType * object(void) const + { + return static_cast(BaseType::object()); + } + + ObjectType * object(void) + { + return static_cast(BaseType::object()); + } + + protected: + + SharedObject(Context * Context, ObjectType * Object) + : BaseType(Context, Object) + { + ; + } + + private: + + SharedObject(const ThisType & other); + ThisType & operator = (const ThisType & other); +}; + +template +class SharedObjectBinding +{ + friend class Context; + + public: + + typedef void BaseType; + typedef SharedObjectBinding ThisType; + typedef TObject ObjectType; + typedef ObjectType UnsafeType; + + ~SharedObjectBinding(void) + { + this->detach(); + } + + bool isNull(void) const + { + if (this->m_shared == 0) return true; + return this->m_shared->isNull(); + } + + void setNull(void) + { + this->m_shared = 0; + } + + const ObjectType * object(void) const + { + GLW_ASSERT(!this->isNull()) + const ObjectType * obj = this->m_shared->object(); + obj->setBinding(this->m_target, this->m_unit); + return obj; + } + + ObjectType * object(void) + { + GLW_ASSERT(!this->isNull()); + ObjectType * obj = this->m_shared->object(); + obj->setBinding(this->m_target, this->m_unit); + return obj; + } + + GLenum target(void) const + { + return this->m_target; + } + + GLint unit(void) const + { + return this->m_target; + } + + void ref(void) + { + this->m_refCount++; + } + + void unref(void) + { + GLW_ASSERT(this->m_refCount > 0); + this->m_refCount--; + if (this->m_refCount == 0) + { + delete this; + } + } + + protected: + + typedef SharedObject SharedObjectType; + + SharedObjectBinding(SharedObjectType * shared, GLenum target, GLint unit) + : m_shared (0) + , m_refCount (0) + , m_target (target) + , m_unit (unit) + { + this->attach(shared); + } + + private: + + SharedObjectType * m_shared; + int m_refCount; + GLenum m_target; + GLint m_unit; + + SharedObjectBinding(const ThisType & other); + ThisType & operator = (const ThisType & other); + + void attach(SharedObjectType * shared) + { + this->detach(); + this->m_shared = shared; + if (this->m_shared != 0) + { + this->m_shared->ref(); + } + } + + void detach(void) + { + if (this->m_shared == 0) return; + this->m_shared->unref(); + this->m_shared = 0; + } +}; + +template +class SafeHandleBase +{ + friend class Context; + + public: + + typedef void BaseType; + typedef SafeHandleBase ThisType; + typedef TObject ObjectType; + typedef typename ObjectType::SafeType SafeType; + + SafeHandleBase(void) + : m_shared(0) + { + ; + } + + SafeHandleBase(const ThisType & other) + : m_shared(0) + { + this->attach(other.shared()); + } + + ~SafeHandleBase(void) + { + this->detach(); + } + + bool isNull(void) const + { + if (this->m_shared == 0) return true; + return this->m_shared->isNull(); + } + + void setNull(void) + { + this->detach(); + } + + const SafeType * operator -> (void) const + { + GLW_ASSERT(!this->isNull()); + return this->m_shared->object(); + } + + SafeType * operator -> (void) + { + GLW_ASSERT(!this->isNull()); + return this->m_shared->object(); + } + + ThisType & operator = (const ThisType & other) + { + this->attach(other.shared()); + return (*this); + } + + protected: + + typedef SharedObject SharedObjectType; + + SafeHandleBase(SharedObjectType * shared) + : m_shared(0) + { + this->attach(shared); + } + + const ObjectType * object(void) const + { + if (this->m_shared == 0) return 0; + return this->m_shared->object(); + } + + ObjectType * object(void) + { + if (this->m_shared == 0) return 0; + return this->m_shared->object(); + } + + SharedObjectType * shared(void) const + { + return this->m_shared; + } + + private: + + SharedObjectType * m_shared; + + void attach(SharedObjectType * shared) + { + this->detach(); + this->m_shared = shared; + if (this->m_shared != 0) + { + this->m_shared->ref(); + } + } + + void detach(void) + { + if (this->m_shared == 0) return; + this->m_shared->unref(); + this->m_shared = 0; + } +}; + +template +class SafeHandle; + +template +class SafeHandleTraits +{ + public: + + typedef void BaseType; + typedef SafeHandleTraits ThisType; + typedef TObject ObjectType; + typedef TObjectBase ObjectBaseType; + typedef SafeHandle SafeHandleBaseType; +}; + +template +class SafeHandleTraits +{ + public: + + typedef void BaseType; + typedef SafeHandleTraits ThisType; + typedef TObject ObjectType; + typedef void ObjectBaseType; + typedef SafeHandleBase SafeHandleBaseType; +}; + +template +class SafeHandle : public SafeHandleTraits::SafeHandleBaseType +{ + friend class Context; + + public: + + typedef typename SafeHandleTraits::SafeHandleBaseType BaseType; + typedef SafeHandle ThisType; + typedef TObject ObjectType; + typedef typename ObjectType::SafeType SafeType; + + SafeHandle(void) + : BaseType() + { + ; + } + + SafeHandle(const ThisType & other) + : BaseType(other) + { + ; + } + + const SafeType * operator -> (void) const + { + return dynamic_cast(BaseType:: operator ->()); + } + + SafeType * operator -> (void) + { + return dynamic_cast(BaseType:: operator ->()); + } + + /* + ThisType & operator = (const ThisType & other) + { + this->attach(other.shared()); + return (*this); + } + */ + + operator bool (void) const + { + return !this->isNull(); + } + + protected: + + typedef SharedObject SharedObjectType; + + SafeHandle(SharedObjectType * shared) + : BaseType(shared) + { + ; + } + + const ObjectType * object(void) const + { + return static_cast(BaseType::object()); + } + + ObjectType * object(void) + { + return static_cast(BaseType::object()); + } + + SharedObjectType * shared(void) const + { + return static_cast(BaseType::shared()); + } +}; + +template +class UnsafeHandle +{ + friend class Context; + + public: + + typedef void BaseType; + typedef UnsafeHandle ThisType; + typedef TObject ObjectType; + typedef ObjectType UnsafeType; + + UnsafeHandle(void) + : m_shared(0) + { + ; + } + + UnsafeHandle(const ThisType & other) + : m_shared(0) + { + this->attach(other.shared()); + } + + ~UnsafeHandle(void) + { + this->detach(); + } + + bool isNull(void) const + { + if (this->m_shared == 0) return true; + return this->m_shared->isNull(); + } + + void setNull(void) + { + this->detach(); + } + + const UnsafeType * operator -> (void) const + { + GLW_ASSERT(!this->isNull()); + return this->m_shared->object(); + } + + UnsafeType * operator -> (void) + { + GLW_ASSERT(!this->isNull()); + return this->m_shared->object(); + } + + ThisType & operator = (const ThisType & other) + { + this->attach(other.shared()); + return (*this); + } + + operator bool (void) const + { + return !this->isNull(); + } + + protected: + + typedef SharedObjectBinding SharedObjectBindingType; + + UnsafeHandle(SharedObjectBindingType * shared) + : m_shared(0) + { + this->attach(shared); + } + + const ObjectType * Object(void) const + { + if (this->m_shared == 0) return true; + return this->m_shared->object(); + } + + ObjectType * Object(void) + { + if (this->m_shared == 0) return true; + return this->m_shared->object(); + } + + private: + + SharedObjectBindingType * m_shared; + + void attach(SharedObjectBindingType * shared) + { + this->detach(); + this->m_shared = shared; + if (this->m_shared != 0) + { + this->m_shared->ref(); + } + } + + void detach(void) + { + if (this->m_shared == 0) return; + this->m_shared->unref(); + this->m_shared = 0; + } + + SharedObjectBindingType * shared(void) const + { + return this->m_shared; + } +}; + +}; + +}; + +#endif // GLW_BOOKKEEPING_H diff --git a/wrap/glw/buffer.h b/wrap/glw/buffer.h new file mode 100644 index 00000000..a39008d8 --- /dev/null +++ b/wrap/glw/buffer.h @@ -0,0 +1,210 @@ +#ifndef GLW_BUFFER_H +#define GLW_BUFFER_H + +#include "./object.h" + +namespace glw +{ + +class BufferArguments : public ObjectArguments +{ + public: + + typedef ObjectArguments BaseType; + typedef BufferArguments ThisType; + + GLsizeiptr size; + GLenum usage; + const void * data; + + BufferArguments(void) + { + this->clear(); + } + + void clear(void) + { + BaseType::clear(); + this->size = 0; + this->usage = GL_NONE; + this->data = 0; + } +}; + +class SafeBuffer : public virtual SafeObject +{ + public: + + typedef SafeObject BaseType; + typedef SafeBuffer ThisType; + + GLsizei size(void) const + { + return this->m_size; + } + + GLenum usage(void) const + { + return this->m_usage; + } + + protected: + + GLsizeiptr m_size; + GLenum m_usage; + + SafeBuffer(Context * ctx) + : BaseType (ctx) + , m_size (0) + , m_usage (GL_NONE) + { + ; + } +}; + +class Buffer : public Object, public SafeBuffer +{ + friend class Context; + friend class detail::SharedObjectBinding; + + public: + + typedef Object BaseType; + typedef SafeBuffer SafeType; + typedef Buffer ThisType; + + virtual Type type(void) const + { + return BufferType; + } + + void setData(const GLsizeiptr size, GLenum usage, const void * data) + { + GLW_ASSERT(this->isValid()); + glBufferData(this->m_target, size, data, usage); + this->m_size = size; + this->m_usage = usage; + } + + void setSubData(GLintptr offset, GLsizeiptr size, const void * data) + { + GLW_ASSERT(this->isValid()); + glBufferSubData(this->m_target, offset, size, data); + } + + void getSubData(GLintptr offset, GLsizeiptr size, void * data) + { + GLW_ASSERT(this->isValid()); + glGetBufferSubData(this->m_target, offset, size, data); + } + + void * map(GLenum access) + { + GLW_ASSERT(this->isValid()); + GLW_ASSERT(!this->isMapped()); + void * ptr = glMapBuffer(this->m_target, access); + if (ptr == 0) return 0; + this->m_mapAccess = access; + this->m_mapPtr = ptr; + return ptr; + } + + void unmap(void) + { + GLW_ASSERT(this->isValid()); + GLW_ASSERT(this->isMapped()); + glUnmapBuffer(this->m_target); + this->m_mapAccess = GL_NONE; + this->m_mapPtr = 0; + } + + GLenum mapAccess(void) const + { + return this->m_mapAccess; + } + + bool isMapped(void) const + { + return (this->m_mapAccess != GL_NONE); + } + + void * mapPointer(void) const + { + return this->m_mapPtr; + } + + void vertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * offset) + { + GLW_ASSERT(this->isValid()); + GLW_ASSERT(this->m_target == GL_ARRAY_BUFFER); + glVertexAttribPointer(index, size, type, normalized, stride, offset); + } + + protected: + + Buffer(Context * ctx) + : SafeObject (ctx) + , SafeType (ctx) + , BaseType (ctx) + , m_mapAccess (GL_NONE) + , m_mapPtr (0) + { + ; + } + + virtual ~Buffer(void) + { + this->destroy(); + } + + bool create(const BufferArguments & args) + { + this->destroy(); + + GLint boundName = 0; + glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &boundName); + + glGenBuffers(1, &(this->m_name)); + this->setBinding(GL_ARRAY_BUFFER, 0); + this->bind(); + this->setData(args.size, args.usage, args.data); + + glBindBuffer(GL_ARRAY_BUFFER, boundName); + + return true; + } + + virtual void doDestroy(Context * ctx, GLuint name) + { + (void)ctx; + if (name == 0) return; + if (this->isMapped()) this->unmap(); + this->m_size = 0; + this->m_usage = GL_NONE; + this->m_mapAccess = GL_NONE; + this->m_mapPtr = 0; + glDeleteBuffers(1, &name); + } + + virtual void doBind(void) + { + glBindBuffer(this->m_target, this->m_name); + } + + virtual void doUnbind(void) + { + glBindBuffer(this->m_target, 0); + } + + private: + + GLenum m_mapAccess; + void * m_mapPtr; +}; + +typedef detail::SafeHandle BufferHandle; +typedef detail::UnsafeHandle BoundBuffer; + +}; + +#endif // GLW_BUFFER_H diff --git a/wrap/glw/common.h b/wrap/glw/common.h new file mode 100644 index 00000000..232caaa7 --- /dev/null +++ b/wrap/glw/common.h @@ -0,0 +1,25 @@ +#ifndef GLW_COMMON_H +#define GLW_COMMON_H + +#include + +#include "./config.h" + +#define GLW_DONT_CARE (0xFFFFFFFF) +#define GLW_CARE_OF(X) ((X) != GLW_DONT_CARE) + +#define GLW_CHECK_GL_ERROR GLW_ASSERT(glGetError() == GL_NO_ERROR) +#define GLW_CHECK_GL_READ_FRAMEBUFFER_STATUS GLW_ASSERT(glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) +#define GLW_CHECK_GL_DRAW_FRAMEBUFFER_STATUS GLW_ASSERT(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) + +namespace glw +{ + +namespace detail +{ + +} + +}; + +#endif // GLW_COMMON_H diff --git a/wrap/glw/config.h b/wrap/glw/config.h new file mode 100644 index 00000000..ab0a0648 --- /dev/null +++ b/wrap/glw/config.h @@ -0,0 +1,12 @@ +#ifndef GLW_CONFIG_H +#define GLW_CONFIG_H + +#ifndef GLW_ASSERT +# define GLW_ASSERT assert +#endif + +#ifndef GLW_IMPLEMENT_CUSTOM_UNIFORMS +# define GLW_IMPLEMENT_CUSTOM_UNIFORMS +#endif + +#endif // GLW_CONFIG_H diff --git a/wrap/glw/context.h b/wrap/glw/context.h new file mode 100644 index 00000000..ef56fb0c --- /dev/null +++ b/wrap/glw/context.h @@ -0,0 +1,438 @@ +#ifndef GLW_CONTEXT_H +#define GLW_CONTEXT_H + +#include "./noncopyable.h" +#include "./buffer.h" +#include "./renderbuffer.h" +#include "./vertexshader.h" +#include "./geometryshader.h" +#include "./fragmentshader.h" +#include "./program.h" +#include "./texture2d.h" +#include "./framebuffer.h" + +#include +#include +#include + +namespace glw +{ + +class Context : public detail::NonCopyable +{ + friend class detail::SharedObjectBase; + + public: + + typedef detail::NonCopyable BaseType; + typedef Context ThisType; + + Context(void) + : m_acquired (false) + , m_textureUnits (0) + { + ; + } + + virtual ~Context(void) + { + this->release(); + } + + bool acquire(void) + { + this->release(); + this->initializeTargets(); + this->m_acquired = true; + return this->m_acquired; + } + + void release(void) + { + if (!this->isAcquired()) return; + this->m_acquired = false; + this->terminateTargets(); + this->destroyAllObjects(); + } + + 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; + } + + BoundBuffer bindVertexBuffer(BufferHandle & handle) + { + return this->bind(BindingTarget(GL_ARRAY_BUFFER, 0), handle); + } + + void unbindVertexBuffer(void) + { + BufferHandle nullHandle; + this->bindVertexBuffer(nullHandle); + } + + BoundBuffer bindIndexBuffer(BufferHandle & handle) + { + return this->bind(BindingTarget(GL_ELEMENT_ARRAY_BUFFER, 0), handle); + } + + void unbindIndexBuffer(void) + { + BufferHandle nullHandle; + this->bindIndexBuffer(nullHandle); + } + + RenderbufferHandle createRenderbuffer(const RenderbufferArguments & args) + { + RenderbufferHandle handle = this->createHandle(); + handle.object()->create(args); + return handle; + } + + BoundRenderbuffer bindRenderbuffer(RenderbufferHandle & handle) + { + return this->bind(BindingTarget(GL_RENDERBUFFER, 0), handle); + } + + void unbindRenderbuffer(void) + { + RenderbufferHandle nullHandle; + this->bindRenderbuffer(nullHandle); + } + + VertexShaderHandle createVertexShader(const VertexShaderArguments & args) + { + VertexShaderHandle handle = this->createHandle(); + handle.object()->create(args); + return handle; + } + + BoundVertexShader bindVertexShader(VertexShaderHandle & handle) + { + return this->bind(BindingTarget(GL_VERTEX_SHADER, 0), handle); + } + + void unbindVertexShader(void) + { + VertexShaderHandle nullHandle; + this->bindVertexShader(nullHandle); + } + + GeometryShaderHandle createGeometryShader(const GeometryShaderArguments & args) + { + GeometryShaderHandle handle = this->createHandle(); + handle.object()->create(args); + return handle; + } + + BoundGeometryShader bindGeometryShader(GeometryShaderHandle & handle) + { + return this->bind(BindingTarget(GL_GEOMETRY_SHADER, 0), handle); + } + + void unbindGeometryShader(void) + { + GeometryShaderHandle nullHandle; + this->bindGeometryShader(nullHandle); + } + + FragmentShaderHandle createFragmentShader(const FragmentShaderArguments & args) + { + FragmentShaderHandle handle = this->createHandle(); + handle.object()->create(args); + return handle; + } + + BoundFragmentShader bindFragmentShader(FragmentShaderHandle & handle) + { + return this->bind(BindingTarget(GL_FRAGMENT_SHADER, 0), handle); + } + + void unbindFragmentShader(void) + { + FragmentShaderHandle nullHandle; + this->bindFragmentShader(nullHandle); + } + + ProgramHandle createProgram(const ProgramArguments & args) + { + ProgramHandle handle = this->createHandle(); + handle.object()->create(args); + return handle; + } + + BoundProgram bindProgram(ProgramHandle & handle) + { + return this->bind(BindingTarget(GL_CURRENT_PROGRAM, 0), handle); + } + + void unbindProgram(void) + { + ProgramHandle nullHandle; + this->bindProgram(nullHandle); + } + + Texture2DHandle createTexture2D(const Texture2DArguments & args) + { + Texture2DHandle handle = this->createHandle(); + handle.object()->create(args); + return handle; + } + + BoundTexture2D bindTexture2D(GLint unit, Texture2DHandle & handle) + { + glActiveTexture(GL_TEXTURE0 + unit); + return this->bind(BindingTarget(GL_TEXTURE_2D, unit), handle); + } + + void unbindTexture2D(GLint unit) + { + Texture2DHandle nullHandle; + this->bindTexture2D(unit, nullHandle); + } + + FramebufferHandle createFramebuffer(const FramebufferArguments & args) + { + FramebufferHandle handle = this->createHandle(); + handle.object()->create(args); + return handle; + } + + BoundFramebuffer bindReadFramebuffer(FramebufferHandle & handle) + { + FramebufferHandle nullHandle; + this->bind(BindingTarget(GL_FRAMEBUFFER, 0), nullHandle); + return this->bind(BindingTarget(GL_READ_FRAMEBUFFER, 0), handle); + } + + void unbindReadFramebuffer(void) + { + FramebufferHandle nullHandle; + this->bindReadFramebuffer(nullHandle); + } + + BoundFramebuffer bindDrawFramebuffer(FramebufferHandle & handle) + { + FramebufferHandle nullHandle; + this->bind(BindingTarget(GL_FRAMEBUFFER, 0), nullHandle); + return this->bind(BindingTarget(GL_DRAW_FRAMEBUFFER, 0), handle); + } + + void unbindDrawFramebuffer(void) + { + FramebufferHandle nullHandle; + this->bindDrawFramebuffer(nullHandle); + } + + BoundFramebuffer bindFramebuffer(FramebufferHandle & handle) + { + FramebufferHandle nullHandle; + this->bind(BindingTarget(GL_READ_FRAMEBUFFER, 0), nullHandle); + this->bind(BindingTarget(GL_DRAW_FRAMEBUFFER, 0), nullHandle); + return this->bind(BindingTarget(GL_FRAMEBUFFER, 0), handle); + } + + void unbindFramebuffer(void) + { + FramebufferHandle nullHandle; + this->bindFramebuffer(nullHandle); + } + + private: + + typedef detail::SharedObjectBase SharedObjectType; + + typedef void * GenericPtr; + typedef std::pair BindingTarget; + + typedef std::set ShaderObjecPtrSet; + typedef ShaderObjecPtrSet::const_iterator ShaderObjecPtrSetConstIterator; + typedef ShaderObjecPtrSet::iterator ShaderObjecPtrSetIterator; + + typedef std::map SharedObjectBindingPtrMap; + typedef SharedObjectBindingPtrMap::const_iterator SharedObjectBindingPtrConstIterator; + typedef SharedObjectBindingPtrMap::iterator SharedObjectBindingPtrIterator; + typedef SharedObjectBindingPtrMap::value_type SharedObjectBindingPtrValue; + + bool m_acquired; + int m_textureUnits; + ShaderObjecPtrSet m_shareds; + SharedObjectBindingPtrMap m_bindings; + + template + void initializeTarget(BindingTarget bt) + { + typedef TObject ObjectType; + typedef detail::UnsafeHandle UnsafeObjectType; + + UnsafeObjectType * unsafeObject = 0; + this->m_bindings.insert(SharedObjectBindingPtrValue(bt, unsafeObject)); + } + + template + void terminateTarget(BindingTarget bt) + { + typedef TObject ObjectType; + typedef detail::SafeHandle SafeObjectType; + + SafeObjectType nullHandle; + this->bind(bt, nullHandle); + } + + void initializeTargets(void) + { + { + GLint texUnits = 0; + glGetIntegerv(GL_MAX_TEXTURE_UNITS, &texUnits); + this->m_textureUnits = int(texUnits); + } + + this->initializeTarget(BindingTarget(GL_ARRAY_BUFFER, 0)); + this->initializeTarget(BindingTarget(GL_ELEMENT_ARRAY_BUFFER, 0)); + this->initializeTarget(BindingTarget(GL_RENDERBUFFER, 0)); + this->initializeTarget(BindingTarget(GL_VERTEX_SHADER, 0)); + this->initializeTarget(BindingTarget(GL_GEOMETRY_SHADER, 0)); + this->initializeTarget(BindingTarget(GL_FRAGMENT_SHADER, 0)); + this->initializeTarget(BindingTarget(GL_CURRENT_PROGRAM, 0)); + for (int i=0; im_textureUnits; ++i) + { + this->initializeTarget(BindingTarget(GL_TEXTURE_2D, GLint(i))); + } + this->initializeTarget(BindingTarget(GL_READ_FRAMEBUFFER, 0)); + this->initializeTarget(BindingTarget(GL_DRAW_FRAMEBUFFER, 0)); + this->initializeTarget(BindingTarget(GL_FRAMEBUFFER, 0)); + } + + void terminateTargets(void) + { + this->terminateTarget(BindingTarget(GL_ARRAY_BUFFER, 0)); + this->terminateTarget(BindingTarget(GL_ELEMENT_ARRAY_BUFFER, 0)); + this->terminateTarget(BindingTarget(GL_RENDERBUFFER, 0)); + this->terminateTarget(BindingTarget(GL_VERTEX_SHADER, 0)); + this->terminateTarget(BindingTarget(GL_GEOMETRY_SHADER, 0)); + this->terminateTarget(BindingTarget(GL_FRAGMENT_SHADER, 0)); + this->terminateTarget(BindingTarget(GL_CURRENT_PROGRAM, 0)); + for (int i=0; im_textureUnits; ++i) + { + this->terminateTarget(BindingTarget(GL_TEXTURE_2D, GLint(i))); + } + this->terminateTarget(BindingTarget(GL_READ_FRAMEBUFFER, 0)); + this->terminateTarget(BindingTarget(GL_DRAW_FRAMEBUFFER, 0)); + this->terminateTarget(BindingTarget(GL_FRAMEBUFFER, 0)); + + this->m_textureUnits = 0; + } + + template + detail::UnsafeHandle bind(BindingTarget bt, detail::SafeHandle & h) + { + typedef TObject ObjectType; + typedef detail::SharedObjectBinding SharedObjectBindingType; + typedef detail::UnsafeHandle UnsafeObjectType; + + SharedObjectBindingPtrIterator it = this->m_bindings.find(bt); + GLW_ASSERT(it != this->m_bindings.end()); + + ObjectType * Object = h.object(); + + SharedObjectBindingType * 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(); + currentBinding->unref(); + currentBinding = 0; + it->second = 0; + } + + if (h.isNull()) return UnsafeObjectType(); + + SharedObjectBindingType * newBinding = new SharedObjectBindingType(h.shared(), bt.first, bt.second); + newBinding->ref(); + it->second = newBinding; + + Object->setBinding(bt.first, bt.second); + Object->bind(); + + return UnsafeObjectType(newBinding); + } + + 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; + } + + void removeShared(SharedObjectType * shared) + { + GLW_ASSERT(shared != 0); + GLW_ASSERT(this->m_shareds.count(shared) > 0); + this->m_shareds.erase(shared); + this->destroyObject(shared->object()); + } + + void destroyAllObjects(void) + { + for (ShaderObjecPtrSetIterator it=this->m_shareds.begin(); it!=this->m_shareds.end(); ++it) + { + SharedObjectType * shared = *it; + Object * Object = shared->object(); + shared->setNull(); + this->destroyObject(Object); + } + } + + template + detail::SafeHandle createHandle(void) + { + typedef TObject ObjectType; + typedef detail::SharedObject SharedObjectType; + typedef detail::SafeHandle SafeType; + + ObjectType * Object = new ObjectType(this); + SharedObjectType * shared = new SharedObjectType(this, Object); + + this->m_shareds.insert(shared); + + return SafeType(shared); + } +}; + +namespace detail +{ + +template +inline void SharedObjectBase::signalDestruction(void) +{ + this->m_context->removeShared(this); +} + +}; + +}; + +#endif // GLW_CONTEXT_H diff --git a/wrap/glw/fragmentshader.h b/wrap/glw/fragmentshader.h new file mode 100644 index 00000000..94ef3468 --- /dev/null +++ b/wrap/glw/fragmentshader.h @@ -0,0 +1,87 @@ +#ifndef GLW_FRAGMENTSHADER_H +#define GLW_FRAGMENTSHADER_H + +#include "./shader.h" + +namespace glw +{ + +class FragmentShaderArguments : public ShaderArguments +{ + public: + + typedef ShaderArguments BaseType; + typedef FragmentShaderArguments ThisType; + + FragmentShaderArguments(void) + { + this->clear(); + } + + void clear(void) + { + BaseType::clear(); + } +}; + +class SafeFragmentShader : public virtual SafeShader +{ + public: + + typedef SafeShader BaseType; + typedef SafeFragmentShader ThisType; + + protected: + + SafeFragmentShader(Context * ctx) + : SafeObject (ctx) + , BaseType (ctx) + { + ; + } +}; + +class FragmentShader : public Shader, public SafeFragmentShader +{ + friend class Context; + friend class detail::SharedObjectBinding; + + public: + + typedef Shader BaseType; + typedef SafeFragmentShader SafeType; + typedef FragmentShader ThisType; + + virtual Type type(void) const + { + return FragmentShaderType; + } + + protected: + + FragmentShader(Context * ctx) + : SafeObject (ctx) + , SafeShader (ctx) + , SafeType (ctx) + , BaseType (ctx) + { + ; + } + + virtual GLenum shaderType(void) const + { + return GL_FRAGMENT_SHADER; + } + + bool create(const FragmentShaderArguments & args) + { + return BaseType::create(args); + } +}; + +typedef detail::SafeHandle FragmentShaderHandle; +typedef detail::UnsafeHandle BoundFragmentShader; + +}; + +#endif // GLW_FRAGMENTSHADER_H diff --git a/wrap/glw/framebuffer.h b/wrap/glw/framebuffer.h new file mode 100644 index 00000000..4270eb7b --- /dev/null +++ b/wrap/glw/framebuffer.h @@ -0,0 +1,316 @@ +#ifndef GLW_FRAMEBUFFER_H +#define GLW_FRAMEBUFFER_H + +#include "./object.h" +#include + +namespace glw +{ + +class RenderTarget +{ + public: + + typedef void BaseType; + typedef RenderTarget ThisType; + + RenderableHandle target; + GLint level; + GLint layer; + GLenum face; + + RenderTarget(void) + { + this->clear(); + } + + RenderTarget(RenderableHandle & rTarget, GLint rLevel, GLint rLayer, GLenum rFace) + : target (rTarget) + , level (rLevel) + , layer (rLayer) + , face (rFace) + { + ; + } + + void clear(void) + { + this->target.setNull(); + this->level = 0; + this->layer = -1; + this->face = GL_NONE; + } +}; + +typedef std::vector RenderTargetVector; + +inline RenderTarget texture2DTarget(Texture2DHandle & handle, GLint level = 0) +{ + return RenderTarget(handle, level, 0, GL_NONE); +} + +inline RenderTarget renderbufferTarget(RenderbufferHandle & handle) +{ + return RenderTarget(handle, 0, 0, GL_NONE); +} + +class RenderTargetMapping +{ + public: + + typedef void BaseType; + typedef RenderTargetMapping ThisType; + + typedef std::map Map; + typedef Map::const_iterator ConstIterator; + typedef Map::iterator Iterator; + typedef Map::value_type Value; + + Map bindings; + + RenderTargetMapping(void) + { + this->clear(); + } + + void clear(void) + { + this->bindings.clear(); + } + + const RenderTarget & operator [] (GLuint attachmentIndex) const + { + return this->bindings.find(attachmentIndex)->second; + } + + RenderTarget & operator [] (GLuint attachmentIndex) + { + return this->bindings[attachmentIndex]; + } +}; + +class RenderTargetBinding +{ + public: + + typedef void BaseType; + typedef RenderTargetBinding ThisType; + + typedef std::map Map; + typedef Map::const_iterator ConstIterator; + typedef Map::iterator Iterator; + typedef Map::value_type Value; + + Map bindings; + + RenderTargetBinding(void) + { + this->clear(); + } + + void clear(void) + { + this->bindings.clear(); + } + + GLuint operator [] (GLuint attachmentIndex) const + { + return this->bindings.find(attachmentIndex)->second; + } + + GLuint & operator [] (GLuint attachmentIndex) + { + return this->bindings[attachmentIndex]; + } +}; + +class FramebufferArguments : public ObjectArguments +{ + public: + + typedef ObjectArguments BaseType; + typedef FramebufferArguments ThisType; + + RenderTargetMapping colorTargets; + RenderTarget depthTarget; + RenderTarget stencilTarget; + RenderTarget depthStencilTarget; + RenderTargetBinding targetInputs; + + FramebufferArguments(void) + { + this->clear(); + } + + void clear(void) + { + BaseType::clear(); + this->colorTargets .clear(); + this->depthTarget .clear(); + this->stencilTarget .clear(); + this->depthStencilTarget .clear(); + this->targetInputs .clear(); + } +}; + +class SafeFramebuffer : public virtual SafeObject +{ + public: + + typedef SafeObject BaseType; + typedef SafeFramebuffer ThisType; + + protected: + + SafeFramebuffer(Context * ctx) + : BaseType(ctx) + { + ; + } +}; + +class Framebuffer : public Object, public SafeFramebuffer +{ + friend class Context; + friend class detail::SharedObjectBinding; + + public: + + typedef Object BaseType; + typedef SafeFramebuffer SafeType; + typedef Framebuffer ThisType; + + virtual Type type(void) const + { + return FramebufferType; + } + + protected: + + Framebuffer(Context * ctx) + : SafeObject (ctx) + , SafeType (ctx) + , BaseType (ctx) + { + ; + } + + virtual ~Framebuffer(void) + { + this->destroy(); + } + + bool create(const FramebufferArguments & args) + { + this->destroy(); + + this->m_config = args; + + GLint boundNameDraw = 0; + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundNameDraw); + + GLint boundNameRead = 0; + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundNameRead); + + glGenFramebuffers(1, &(this->m_name)); + this->setBinding(GL_FRAMEBUFFER, 0); + this->bind(); + this->configure(); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, boundNameDraw); + glBindFramebuffer(GL_READ_FRAMEBUFFER, boundNameRead); + + return true; + } + + virtual void doDestroy(Context * ctx, GLuint name) + { + (void)ctx; + if (name == 0) return; + glDeleteFramebuffers(1, &name); + this->m_config.clear(); + } + + virtual void doBind(void) + { + glBindFramebuffer(this->m_target, this->m_name); + } + + virtual void doUnbind(void) + { + glBindFramebuffer(this->m_target, 0); + } + + private: + + FramebufferArguments m_config; + + void configure(void) + { + for (RenderTargetMapping::Iterator it=this->m_config.colorTargets.bindings.begin(); it!=this->m_config.colorTargets.bindings.end(); ++it) + { + this->attachTarget(GL_COLOR_ATTACHMENT0 + it->first, it->second); + } + + if (this->m_config.depthStencilTarget.target) + { + this->attachTarget(GL_DEPTH_ATTACHMENT, this->m_config.depthStencilTarget); + this->attachTarget(GL_STENCIL_ATTACHMENT, this->m_config.depthStencilTarget); + } + else + { + this->attachTarget(GL_DEPTH_ATTACHMENT, this->m_config.depthTarget ); + this->attachTarget(GL_STENCIL_ATTACHMENT, this->m_config.stencilTarget); + } + + if (this->m_config.colorTargets.bindings.empty()) + { + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + } + else + { + std::vector drawBuffers; + drawBuffers.reserve(this->m_config.targetInputs.bindings.size()); + for (RenderTargetBinding::Iterator it=this->m_config.targetInputs.bindings.begin(); it!=this->m_config.targetInputs.bindings.end(); ++it) + { + const GLuint fragOutput = it->second; + const GLuint attachmentIndex = GL_COLOR_ATTACHMENT0 + it->first; + if (drawBuffers.size() <= size_t(fragOutput)) + { + drawBuffers.resize(size_t(fragOutput + 1), GL_NONE); + } + drawBuffers[fragOutput] = attachmentIndex; + } + glDrawBuffers(GLsizei(drawBuffers.size()), &(drawBuffers[0])); + glReadBuffer(drawBuffers[0]); + } + } + + bool attachTarget(GLenum attachment, RenderTarget & target) + { + RenderableHandle & handle = target.target; + + if (!handle) + { + glFramebufferRenderbuffer(this->m_target, attachment, GL_RENDERBUFFER, 0); + return false; + } + + switch (handle->type()) + { + case RenderbufferType : glFramebufferRenderbuffer (this->m_target, attachment, GL_RENDERBUFFER, handle->name() ); break; + case Texture2DType : glFramebufferTexture2D (this->m_target, attachment, GL_TEXTURE_2D, handle->name(), target.level); break; + default : GLW_ASSERT(0); break; + } + + return true; + } +}; + +typedef detail::SafeHandle FramebufferHandle; +typedef detail::UnsafeHandle BoundFramebuffer; + +}; + +#endif // GLW_FRAMEBUFFER_H diff --git a/wrap/glw/geometryshader.h b/wrap/glw/geometryshader.h new file mode 100644 index 00000000..5a1d5d99 --- /dev/null +++ b/wrap/glw/geometryshader.h @@ -0,0 +1,87 @@ +#ifndef GLW_GEOMETRYSHADER_H +#define GLW_GEOMETRYSHADER_H + +#include "./shader.h" + +namespace glw +{ + +class GeometryShaderArguments : public ShaderArguments +{ + public: + + typedef ShaderArguments BaseType; + typedef GeometryShaderArguments ThisType; + + GeometryShaderArguments(void) + { + this->clear(); + } + + void clear(void) + { + BaseType::clear(); + } +}; + +class SafeGeometryShader : public virtual SafeShader +{ + public: + + typedef SafeShader BaseType; + typedef SafeGeometryShader ThisType; + + protected: + + SafeGeometryShader(Context * ctx) + : SafeObject (ctx) + , BaseType (ctx) + { + ; + } +}; + +class GeometryShader : public Shader, public SafeGeometryShader +{ + friend class Context; + friend class detail::SharedObjectBinding; + + public: + + typedef Shader BaseType; + typedef SafeGeometryShader SafeType; + typedef GeometryShader ThisType; + + virtual Type type(void) const + { + return GeometryShaderType; + } + + protected: + + GeometryShader(Context * ctx) + : SafeObject (ctx) + , SafeShader (ctx) + , SafeType (ctx) + , BaseType (ctx) + { + ; + } + + virtual GLenum shaderType(void) const + { + return GL_GEOMETRY_SHADER; + } + + bool create(const GeometryShaderArguments & args) + { + return BaseType::create(args); + } +}; + +typedef detail::SafeHandle GeometryShaderHandle; +typedef detail::UnsafeHandle BoundGeometryShader; + +}; + +#endif // GLW_GEOMETRYSHADER_H diff --git a/wrap/glw/glheaders.h b/wrap/glw/glheaders.h new file mode 100644 index 00000000..b49892e4 --- /dev/null +++ b/wrap/glw/glheaders.h @@ -0,0 +1,6 @@ +#ifndef GLW_GLHEADERS_H +#define GLW_GLHEADERS_H + +#include + +#endif // GLW_GLHEADERS_H diff --git a/wrap/glw/glw.h b/wrap/glw/glw.h new file mode 100644 index 00000000..12359c6f --- /dev/null +++ b/wrap/glw/glw.h @@ -0,0 +1,7 @@ +#ifndef GLW_GLW_H +#define GLW_GLW_H + +#include "./context.h" +#include "./utility.h" + +#endif // GLW_GLW_H diff --git a/wrap/glw/noncopyable.h b/wrap/glw/noncopyable.h new file mode 100644 index 00000000..702b0f51 --- /dev/null +++ b/wrap/glw/noncopyable.h @@ -0,0 +1,42 @@ +#ifndef GLW_NONCOPYABLE_H +#define GLW_NONCOPYABLE_H + +#include "./common.h" + +namespace glw +{ + +namespace detail +{ + +class NonCopyable +{ + public: + + typedef void BaseType; + typedef NonCopyable ThisType; + + NonCopyable(void) + { + ; + } + + private: + + NonCopyable(const ThisType & that) + { + (void)that; + } + + ThisType & operator = (const ThisType & that) + { + (void)that; + return (*this); + } +}; + +}; + +}; + +#endif // GLW_NONCOPYABLE_H diff --git a/wrap/glw/object.h b/wrap/glw/object.h new file mode 100644 index 00000000..8cf2cda0 --- /dev/null +++ b/wrap/glw/object.h @@ -0,0 +1,143 @@ +#ifndef GLW_OBJECT_H +#define GLW_OBJECT_H + +#include "./bookkeeping.h" +#include "./noncopyable.h" +#include "./type.h" +#include "./glheaders.h" + +namespace glw +{ + +class Context; + +class ObjectArguments +{ + public: + + typedef void BaseType; + typedef ObjectArguments ThisType; + + ObjectArguments(void) + { + this->clear(); + } + + void clear(void) + { + ; + } +}; + +class SafeObject +{ + friend class Object; + + public: + + typedef void BaseType; + typedef SafeObject ThisType; + + bool isValid(void) const + { + return (this->m_name != 0); + } + + Context * context(void) + { + return this->m_context; + } + + const Context * context(void) const + { + return this->m_context; + } + + GLuint name(void) const + { + return this->m_name; + } + + virtual Type type(void) const = 0; + + protected: + + Context * m_context; + GLuint m_name; + + SafeObject(Context * ctx) + : m_context (ctx) + , m_name (0) + { + ; + } + + virtual ~SafeObject(void) + { + ; + } +}; + +class Object : public detail::NonCopyable, public virtual SafeObject +{ + friend class Context; + + public: + + typedef void BaseType; + typedef SafeObject SafeType; + typedef Object ThisType; + + protected: + + GLenum m_target; + GLint m_unit; + + Object(Context * ctx) + : SafeType (ctx) + , m_target (GL_NONE) + , m_unit (0) + { + ; + } + + void destroy(void) + { + if (!this->isValid()) return; + + this->doDestroy(this->m_context, this->m_name); + + this->m_context = 0; + this->m_name = 0; + } + + void setBinding(GLenum target, GLint unit) const + { + ThisType * that = const_cast(this); + that->m_target = target; + that->m_unit = unit; + } + + void bind(void) + { + GLW_ASSERT(this->isValid()); + this->doBind(); + } + + void unbind(void) + { + GLW_ASSERT(this->isValid()); + this->doUnbind(); + } + + virtual void doDestroy (Context * ctx, GLuint name) = 0; + virtual void doBind (void) = 0; + virtual void doUnbind (void) = 0; +}; + +typedef detail::SafeHandle ObjectHandle; +typedef detail::UnsafeHandle BoundObject; + +}; + +#endif // GLW_OBJECT_H diff --git a/wrap/glw/program.h b/wrap/glw/program.h new file mode 100644 index 00000000..9f79e63d --- /dev/null +++ b/wrap/glw/program.h @@ -0,0 +1,504 @@ +#ifndef GLW_PROGRAM_H +#define GLW_PROGRAM_H + +#include + +#include +#include +#include + +#include "./vertexshader.h" +#include "./geometryshader.h" +#include "./fragmentshader.h" + +namespace glw +{ + +typedef std::vector ShaderHandleVector; + +class VertexAttributeBinding +{ + public: + + typedef void BaseType; + typedef VertexAttributeBinding ThisType; + + typedef std::map Map; + typedef Map::const_iterator ConstIterator; + typedef Map::iterator Iterator; + typedef Map::value_type Value; + + Map bindings; + + VertexAttributeBinding(void) + { + this->clear(); + } + + void clear(void) + { + this->bindings.clear(); + } + + GLuint operator [] (const std::string & attributeName) const + { + return this->bindings.find(attributeName)->second; + } + + GLuint & operator [] (const std::string & attributeName) + { + return this->bindings[attributeName]; + } +}; + +class GeometryStage +{ + public: + + typedef void BaseType; + typedef GeometryStage ThisType; + + /* + GLenum inputPrimitiveType; + GLenum outputPrimitiveType; + GLint maxOutputVertices; + */ + + GeometryStage(void) + { + this->clear(); + } + + void clear(void) + { + /* + this->inputPrimitiveType = GLW_DONT_CARE; + this->outputPrimitiveType = GLW_DONT_CARE; + this->maxOutputVertices = GLW_DONT_CARE; + */ + } +}; + +class TransformFeedbackStream +{ + public: + + typedef void BaseType; + typedef TransformFeedbackStream ThisType; + + typedef std::vector VaryingVector; + + VaryingVector varyings; + GLenum bufferMode; + + TransformFeedbackStream(void) + { + this->clear(); + } + + void clear(void) + { + this->varyings.clear(); + this->bufferMode = GL_INTERLEAVED_ATTRIBS; + } +}; + +class RasterizerSettings +{ + public: + + typedef void BaseType; + typedef RasterizerSettings ThisType; + + enum RasterizerExecution + { + DontCare = 0, + Autodetect, + ForceEnabled, + ForceDisabled + }; + + // TODO + //RasterizerExecution execution; + + RasterizerSettings(void) + { + this->clear(); + } + + void clear(void) + { + //this->execution = ThisType::Autodetect; + } +}; + +class FragmentOutputBinding +{ + public: + + typedef void BaseType; + typedef FragmentOutputBinding ThisType; + + typedef std::map Map; + typedef Map::const_iterator ConstIterator; + typedef Map::iterator Iterator; + typedef Map::value_type Value; + + Map bindings; + + FragmentOutputBinding(void) + { + this->clear(); + } + + void clear(void) + { + this->bindings.clear(); + } + + GLuint operator [] (const std::string & outName) const + { + return this->bindings.find(outName)->second; + } + + GLuint & operator [] (const std::string & outName) + { + return this->bindings[outName]; + } +}; + +class ProgramArguments : public ObjectArguments +{ + public: + + typedef ObjectArguments BaseType; + typedef ProgramArguments ThisType; + + ShaderHandleVector shaders; + VertexAttributeBinding vertexInputs; + GeometryStage geometryStage; + TransformFeedbackStream feedbackStream; + RasterizerSettings rasterSettings; + FragmentOutputBinding fragmentOutputs; + + ProgramArguments(void) + { + this->clear(); + } + + void clear(void) + { + BaseType::clear(); + this->shaders .clear(); + this->vertexInputs .clear(); + this->geometryStage .clear(); + this->feedbackStream .clear(); + this->rasterSettings .clear(); + this->fragmentOutputs .clear(); + } +}; + +class SafeProgram : public virtual SafeObject +{ + public: + + typedef SafeObject BaseType; + typedef SafeProgram ThisType; + + const ProgramArguments & arguments(void) const + { + return this->m_arguments; + } + + const std::string & log(void) const + { + return this->m_log; + } + + bool isLinked(void) const + { + return this->m_linked; + } + + protected: + + ProgramArguments m_arguments; + std::string m_log; + bool m_linked; + + SafeProgram(Context * ctx) + : BaseType (ctx) + , m_linked (false) + { + ; + } +}; + +class Program : public Object, public SafeProgram +{ + friend class Context; + friend class detail::SharedObjectBinding; + + public: + + typedef Object BaseType; + typedef SafeProgram SafeType; + typedef Program ThisType; + + virtual Type type(void) const + { + return ProgramType; + } + + GLint getUniformLocation(const std::string & name) const + { + GLW_ASSERT(this->m_uniforms.count(name) > 0); + return this->m_uniforms.find(name)->second.location; + } + +#define _GLW_IMPLEMENT_SCALAR_UNIFORM_(TYPE, FUNCION_SUFFIX) \ + void setUniform (const std::string & name, TYPE x ) { glUniform1 ## FUNCION_SUFFIX (this->getUniformLocation(name), x ); } \ + void setUniform (const std::string & name, TYPE x, TYPE y ) { glUniform2 ## FUNCION_SUFFIX (this->getUniformLocation(name), x, y ); } \ + void setUniform (const std::string & name, TYPE x, TYPE y, TYPE z ) { glUniform3 ## FUNCION_SUFFIX (this->getUniformLocation(name), x, y, z ); } \ + void setUniform (const std::string & name, TYPE x, TYPE y, TYPE z, TYPE w ) { glUniform4 ## FUNCION_SUFFIX (this->getUniformLocation(name), x, y, z, w); } + +#define _GLW_IMPLEMENT_VECTOR_UNIFORM_(TYPE, FUNCION_SUFFIX) \ + void setUniform1 (const std::string & name, const TYPE * v, int count = 1) { glUniform1 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), v ); } \ + void setUniform2 (const std::string & name, const TYPE * v, int count = 1) { glUniform2 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), v ); } \ + void setUniform3 (const std::string & name, const TYPE * v, int count = 1) { glUniform3 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), v ); } \ + void setUniform4 (const std::string & name, const TYPE * v, int count = 1) { glUniform4 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), v ); } + +#define _GLW_IMPLEMENT_MATRIX_UNIFORM_(TYPE, FUNCION_SUFFIX) \ + void setUniform2x2 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix2 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \ + void setUniform2x3 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix2x3 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \ + void setUniform2x4 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix2x4 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \ + void setUniform3x2 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix3x2 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \ + void setUniform3x3 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix3 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \ + void setUniform3x4 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix3x4 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \ + void setUniform4x2 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix4x2 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \ + void setUniform4x3 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix4x3 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \ + void setUniform4x4 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix4 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } + + _GLW_IMPLEMENT_SCALAR_UNIFORM_(int, i ) + _GLW_IMPLEMENT_SCALAR_UNIFORM_(unsigned int, ui) + _GLW_IMPLEMENT_SCALAR_UNIFORM_(float, f ) + _GLW_IMPLEMENT_VECTOR_UNIFORM_(int, i ) + _GLW_IMPLEMENT_VECTOR_UNIFORM_(unsigned int, ui) + _GLW_IMPLEMENT_VECTOR_UNIFORM_(float, f ) + _GLW_IMPLEMENT_MATRIX_UNIFORM_(float, f ) + + GLW_IMPLEMENT_CUSTOM_UNIFORMS; + +#undef _GLW_IMPLEMENT_SCALAR_UNIFORM_ +#undef _GLW_IMPLEMENT_VECTOR_UNIFORM_ +#undef _GLW_IMPLEMENT_MATRIX_UNIFORM_ + + protected: + + Program(Context * ctx) + : SafeObject (ctx) + , SafeType (ctx) + , BaseType (ctx) + { + ; + } + + virtual ~Program(void) + { + this->destroy(); + } + + bool create(const ProgramArguments & args) + { + this->destroy(); + + this->m_arguments = args; + + GLint boundName = 0; + glGetIntegerv(GL_CURRENT_PROGRAM, &boundName); + + this->m_name = glCreateProgram(); + + // shaders + { + for (size_t i=0; im_arguments.shaders.size(); ++i) + { + const ShaderHandle & shader = this->m_arguments.shaders[i]; + if (!shader) continue; + if (!shader->isCompiled()) continue; + glAttachShader(this->m_name, shader->name()); + } + } + + // vertex + { + for (VertexAttributeBinding::ConstIterator it=this->m_arguments.vertexInputs.bindings.begin(); it!=this->m_arguments.vertexInputs.bindings.end(); ++it) + { + glBindAttribLocation(this->m_name, it->second, it->first.c_str()); + } + } + + // geometry + { + ; + } + + // transform feedback + { + const size_t count = this->m_arguments.feedbackStream.varyings.size(); + if (count > 0) + { + const char ** varyings = new const char * [count]; + for (size_t i=0; im_arguments.feedbackStream.varyings[i].c_str(); + } + glTransformFeedbackVaryings(this->m_name, GLsizei(count), varyings, this->m_arguments.feedbackStream.bufferMode); + delete [] varyings; + } + } + + // TODO + // rasterizer + { + ; + } + + // fragment + { + for (FragmentOutputBinding::ConstIterator it=this->m_arguments.fragmentOutputs.bindings.begin(); it!=this->m_arguments.fragmentOutputs.bindings.end(); ++it) + { + glBindFragDataLocation(this->m_name, it->second, it->first.c_str()); + } + } + + glLinkProgram(this->m_name); + + GLint linkStatus = 0; + glGetProgramiv(this->m_name, GL_LINK_STATUS, &linkStatus); + + this->m_log = ThisType::getInfoLog(this->m_name); + this->m_linked = (linkStatus != GL_FALSE); + + if (this->m_linked) + { + this->postLink(); + } + + this->setBinding(GL_CURRENT_PROGRAM, 0); + this->bind(); + // TODO + // ... nothing to do ... + + glUseProgram(boundName); + + return this->m_linked; + } + + virtual void doDestroy(Context * ctx, GLuint name) + { + (void)ctx; + if (name == 0) return; + glDeleteProgram(name); + } + + virtual void doBind(void) + { + glUseProgram(this->m_name); + } + + virtual void doUnbind(void) + { + glUseProgram(0); + } + + private: + + class UniformInfo + { + public: + + typedef void BaseType; + typedef UniformInfo ThisType; + + std::string name; + GLint location; + GLenum type; + GLint size; + + UniformInfo(void) + : location (-1) + , type (GL_NONE) + , size (0) + { + ; + } + }; + + typedef std::map UniformMap; + typedef UniformMap::const_iterator UniformMapConstIterator; + typedef UniformMap::iterator UniformMapIterator; + typedef UniformMap::value_type UniformMapValue; + + UniformMap m_uniforms; + + static std::string getInfoLog(GLuint Program) + { + std::string log; + GLint logLen = 0; + glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &logLen); + if (logLen > 0) + { + char * sLog = new char[logLen + 1]; + glGetProgramInfoLog(Program, logLen, &logLen, sLog); + if (logLen > 0) + { + if (sLog[0] != '\0') + { + sLog[logLen - 1] = '\0'; + log = sLog; + } + } + delete [] sLog; + } + return log; + } + + void setupUniforms(void) + { + this->m_uniforms.clear(); + + GLint ucount = 0; + glGetProgramiv(this->m_name, GL_ACTIVE_UNIFORMS, &ucount); + if (ucount <= 0) return; + + GLint ulen = 0; + glGetProgramiv(this->m_name, GL_ACTIVE_UNIFORM_MAX_LENGTH, &ulen); + ulen++; // according to specs, +1 (for null) is already accounted, but some implementations are broken. + if (ulen <= 0) return; + + UniformInfo info; + GLchar * uname = new GLchar [ulen + 1]; + for (int i=0; im_name, GLuint(i), GLsizei(ulen), &length, &(info.size), &(info.type), uname); + info.name = uname; + info.location = glGetUniformLocation(this->m_name, uname); + this->m_uniforms.insert(UniformMapValue(info.name, info)); + } + delete [] uname; + } + + void postLink(void) + { + this->setupUniforms(); + } +}; + +typedef detail::SafeHandle ProgramHandle; +typedef detail::UnsafeHandle BoundProgram; + +}; + +#endif // GLW_PROGRAM_H diff --git a/wrap/glw/renderable.h b/wrap/glw/renderable.h new file mode 100644 index 00000000..129a859a --- /dev/null +++ b/wrap/glw/renderable.h @@ -0,0 +1,83 @@ +#ifndef GLW_RENDERABLE_H +#define GLW_RENDERABLE_H + +#include + +#include "./object.h" + +namespace glw +{ + +class RenderableArguments : public ObjectArguments +{ + public: + + typedef ObjectArguments BaseType; + typedef RenderableArguments ThisType; + + GLenum format; + + RenderableArguments(void) + { + this->clear(); + } + + void clear(void) + { + BaseType::clear(); + this->format = GL_NONE; + } +}; + +class SafeRenderable : public virtual SafeObject +{ + public: + + typedef SafeObject BaseType; + typedef SafeRenderable ThisType; + + GLenum format(void) const + { + return this->m_format; + } + + virtual int imageDimensions (void) const = 0; + virtual bool isArray (void) const = 0; + + protected: + + GLenum m_format; + + SafeRenderable(Context * ctx) + : BaseType (ctx) + , m_format (GL_NONE) + { + ; + } +}; + +class Renderable : public Object, public virtual SafeRenderable +{ + public: + + typedef Object BaseType; + typedef SafeRenderable SafeType; + typedef Renderable ThisType; + + protected: + + Renderable(Context * ctx) + : SafeObject (ctx) + , SafeType (ctx) + , BaseType (ctx) + { + ; + } +}; + +typedef detail::SafeHandle RenderableHandle; +typedef detail::UnsafeHandle BoundRenderable; + +}; + +#endif // GLW_RENDERABLE_H diff --git a/wrap/glw/renderbuffer.h b/wrap/glw/renderbuffer.h new file mode 100644 index 00000000..43c359e4 --- /dev/null +++ b/wrap/glw/renderbuffer.h @@ -0,0 +1,158 @@ +#ifndef GLW_RENDERBUFFER_H +#define GLW_RENDERBUFFER_H + +#include "./renderable.h" + +namespace glw +{ + +class RenderbufferArguments : public RenderableArguments +{ + public: + + typedef RenderableArguments BaseType; + typedef RenderbufferArguments ThisType; + + GLsizei width; + GLsizei height; + + RenderbufferArguments(void) + { + this->clear(); + } + + void clear(void) + { + BaseType::clear(); + this->width = 0; + this->height = 0; + } +}; + +class SafeRenderbuffer : public virtual SafeRenderable +{ + public: + + typedef SafeRenderable BaseType; + typedef SafeRenderbuffer ThisType; + + GLsizei width(void) const + { + return this->m_width; + } + + GLsizei height(void) const + { + return this->m_height; + } + + protected: + + GLsizei m_width; + GLsizei m_height; + + SafeRenderbuffer(Context * ctx) + : SafeObject (ctx) + , BaseType (ctx) + , m_width (0) + , m_height (0) + { + ; + } +}; + +class Renderbuffer : public Renderable, public SafeRenderbuffer +{ + friend class Context; + friend class detail::SharedObjectBinding; + + public: + + typedef Renderable BaseType; + typedef SafeRenderbuffer SafeType; + typedef Renderbuffer ThisType; + + virtual Type type(void) const + { + return RenderbufferType; + } + + virtual int imageDimensions(void) const + { + return 2; + } + + virtual bool isArray(void) const + { + return false; + } + + protected: + + Renderbuffer(Context * ctx) + : SafeObject (ctx) + , SafeRenderable (ctx) + , SafeType (ctx) + , BaseType (ctx) + { + ; + } + + virtual ~Renderbuffer(void) + { + this->destroy(); + } + + bool create(const RenderbufferArguments & args) + { + this->destroy(); + + GLint boundName = 0; + glGetIntegerv(GL_RENDERBUFFER_BINDING, &boundName); + + glGenRenderbuffers(1, &(this->m_name)); + this->setBinding(GL_RENDERBUFFER_BINDING, 0); + this->bind(); + this->allocate(args.format, args.width, args.height); + + glBindRenderbuffer(GL_RENDERBUFFER, boundName); + + return true; + } + + virtual void doDestroy(Context * ctx, GLuint name) + { + (void)ctx; + if (name == 0) return; + this->m_format = GL_NONE; + this->m_width = 0; + this->m_height = 0; + glDeleteRenderbuffers(1, &name); + } + + virtual void doBind(void) + { + glBindRenderbuffer(this->m_target, this->m_name); + } + + virtual void doUnbind(void) + { + glBindRenderbuffer(this->m_target, 0); + } + + void allocate(GLenum format, GLsizei width, GLsizei height) + { + GLW_ASSERT(this->isValid()); + glRenderbufferStorage(this->m_target, format, width, height); + this->m_format = format; + this->m_width = width; + this->m_height = height; + } +}; + +typedef detail::SafeHandle RenderbufferHandle; +typedef detail::UnsafeHandle BoundRenderbuffer; + +}; + +#endif // GLW_RENDERBUFFER_H diff --git a/wrap/glw/shader.h b/wrap/glw/shader.h new file mode 100644 index 00000000..f03b85b1 --- /dev/null +++ b/wrap/glw/shader.h @@ -0,0 +1,174 @@ +#ifndef GLW_SHADER_H +#define GLW_SHADER_H + +#include + +#include "./object.h" + +namespace glw +{ + +class ShaderArguments : public ObjectArguments +{ + public: + + typedef ObjectArguments BaseType; + typedef ShaderArguments ThisType; + + std::string source; + + ShaderArguments(void) + { + this->clear(); + } + + void clear(void) + { + BaseType::clear(); + this->source.clear(); + } +}; + +class SafeShader : public virtual SafeObject +{ + public: + + typedef SafeObject BaseType; + typedef SafeShader ThisType; + + const std::string & source(void) const + { + return this->m_source; + } + + const std::string & log(void) const + { + return this->m_log; + } + + bool isCompiled(void) const + { + return this->m_compiled; + } + + protected: + + std::string m_source; + std::string m_log; + bool m_compiled; + + SafeShader(Context * ctx) + : BaseType (ctx) + , m_compiled (false) + { + ; + } +}; + +class Shader : public Object, public virtual SafeShader +{ + public: + + typedef Object BaseType; + typedef SafeShader SafeType; + typedef Shader ThisType; + + protected: + + Shader(Context * ctx) + : SafeObject (ctx) + , BaseType (ctx) + , SafeType (ctx) + { + ; + } + + virtual ~Shader(void) + { + this->destroy(); + } + + virtual GLenum shaderType(void) const = 0; + + bool create(const ShaderArguments & args) + { + this->destroy(); + + const GLenum shType = this->shaderType(); + + this->m_name = glCreateShader(shType); + this->setBinding(shType, 0); + this->bind(); + this->compile(args.source); + + return this->m_compiled; + } + + virtual void doDestroy(Context * ctx, GLuint name) + { + (void)ctx; + if (name == 0) return; + this->m_source.clear(); + this->m_log.clear(); + this->m_compiled = false; + glDeleteShader(name); + } + + virtual void doBind(void) + { + ; + } + + virtual void doUnbind(void) + { + ; + } + + void compile(const std::string & source) + { + GLW_ASSERT(this->isValid()); + + const char * src = source.c_str(); + glShaderSource(this->m_name, 1, &src, 0); + glCompileShader(this->m_name); + + GLint compileStatus = 0; + glGetShaderiv(this->m_name, GL_COMPILE_STATUS, &compileStatus); + + this->m_source = source; + this->m_log = ThisType::getInfoLog(this->m_name); + this->m_compiled = (compileStatus != GL_FALSE); + } + + private: + + static std::string getInfoLog(GLuint Shader) + { + std::string log; + + GLint logLen = 0; + glGetShaderiv(Shader, GL_INFO_LOG_LENGTH, &logLen); + if (logLen > 0) + { + char * sLog = new char[logLen + 1]; + glGetShaderInfoLog(Shader, logLen, &logLen, sLog); + if (logLen > 0) + { + if (sLog[0] != '\0') + { + sLog[logLen - 1] = '\0'; + log = sLog; + } + } + delete [] sLog; + } + return log; + } +}; + +typedef detail::SafeHandle ShaderHandle; +typedef detail::UnsafeHandle BoundShader; + +}; + +#endif // GLW_SHADER_H diff --git a/wrap/glw/texture.h b/wrap/glw/texture.h new file mode 100644 index 00000000..a5e6b871 --- /dev/null +++ b/wrap/glw/texture.h @@ -0,0 +1,136 @@ +#ifndef GLW_TEXTURE_H +#define GLW_TEXTURE_H + +#include "./renderable.h" + +namespace glw +{ + +class TextureSampleMode +{ + public: + + typedef void BaseType; + typedef TextureSampleMode ThisType; + + GLenum minFilter; + GLenum magFilter; + GLenum wrapS; + GLenum wrapT; + GLenum wrapR; + + TextureSampleMode(void) + { + this->clear(); + } + + TextureSampleMode(GLenum rMinFilter, GLenum rMagFilter, GLenum rWrapS, GLenum rWrapT, GLenum rWrapR) + : minFilter (rMinFilter) + , magFilter (rMagFilter) + , wrapS (rWrapS) + , wrapT (rWrapT) + , wrapR (rWrapR) + { + ; + } + + void clear(void) + { + this->minFilter = GLW_DONT_CARE; + this->magFilter = GLW_DONT_CARE; + this->wrapS = GLW_DONT_CARE; + this->wrapT = GLW_DONT_CARE; + this->wrapR = GLW_DONT_CARE; + } +}; + +inline TextureSampleMode texSampleMode(GLenum minFilter = GLW_DONT_CARE, GLenum magFilter = GLW_DONT_CARE, GLenum wrapS = GLW_DONT_CARE, GLenum wrapT = GLW_DONT_CARE, GLenum wrapR = GLW_DONT_CARE) +{ + return TextureSampleMode(minFilter, magFilter, wrapS, wrapT, wrapR); +} + +class TextureArguments : public RenderableArguments +{ + public: + + typedef RenderableArguments BaseType; + typedef TextureArguments ThisType; + + TextureArguments(void) + { + this->clear(); + } + + void clear(void) + { + BaseType::clear(); + } +}; + +class SafeTexture : public virtual SafeRenderable +{ + public: + + typedef SafeRenderable BaseType; + typedef SafeTexture ThisType; + + protected: + + SafeTexture(Context * ctx) + : SafeObject (ctx) + , BaseType (ctx) + { + ; + } +}; + +class Texture : public Renderable, public virtual SafeTexture +{ + public: + + typedef Renderable BaseType; + typedef SafeTexture SafeType; + typedef Texture ThisType; + + protected: + + Texture(Context * ctx) + : SafeObject (ctx) + , SafeRenderable (ctx) + , SafeType (ctx) + , BaseType (ctx) + { + ; + } + + virtual ~Texture(void) + { + this->destroy(); + } + + virtual void doDestroy(Context * ctx, GLuint name) + { + (void)ctx; + if (name == 0) return; + glDeleteTextures(1, &name); + } + + virtual void doBind(void) + { + glActiveTexture(GL_TEXTURE0 + this->m_unit); + glBindTexture(this->m_target, this->m_name); + } + + virtual void doUnbind(void) + { + glActiveTexture(GL_TEXTURE0 + this->m_unit); + glBindTexture(this->m_target, 0); + } +}; + +typedef detail::SafeHandle TextureHandle; +typedef detail::UnsafeHandle BoundTexture; + +}; + +#endif // GLW_TEXTURE_H diff --git a/wrap/glw/texture2d.h b/wrap/glw/texture2d.h new file mode 100644 index 00000000..9f371b5e --- /dev/null +++ b/wrap/glw/texture2d.h @@ -0,0 +1,175 @@ +#ifndef GLW_TEXTURE2D_H +#define GLW_TEXTURE2D_H + +#include "./texture.h" + +namespace glw +{ + +class Texture2DArguments : public TextureArguments +{ + public: + + typedef TextureArguments BaseType; + typedef Texture2DArguments ThisType; + + GLsizei width; + GLsizei height; + GLenum dataFormat; + GLenum dataType; + const void * data; + TextureSampleMode sampler; + + Texture2DArguments(void) + { + this->clear(); + } + + void clear(void) + { + BaseType::clear(); + this->width = 0; + this->height = 0; + this->dataFormat = GL_NONE; + this->dataType = GL_NONE; + this->data = 0; + this->sampler.clear(); + } +}; + +class SafeTexture2D : public virtual SafeTexture +{ + public: + + typedef SafeTexture BaseType; + typedef SafeTexture2D ThisType; + + GLsizei width(void) const + { + return this->m_width; + } + + GLsizei height(void) const + { + return this->m_height; + } + + protected: + + GLsizei m_width; + GLsizei m_height; + + SafeTexture2D(Context * ctx) + : SafeObject (ctx) + , SafeRenderable (ctx) + , BaseType (ctx) + , m_width (0) + , m_height (0) + { + ; + } +}; + +class Texture2D : public Texture, public SafeTexture2D +{ + friend class Context; + friend class detail::SharedObjectBinding; + + public: + + typedef Texture BaseType; + typedef SafeTexture2D SafeType; + typedef Texture ThisType; + + virtual Type type(void) const + { + return Texture2DType; + } + + virtual int imageDimensions(void) const + { + return 2; + } + + virtual bool isArray(void) const + { + return false; + } + + void allocateLevel(GLint level, GLsizei width, GLsizei height, GLenum dataFormat, GLenum dataType, const void * data) + { + GLW_ASSERT(this->isValid()); + glTexImage2D(this->m_target, level, this->m_format, width, height, 0, dataFormat, dataType, data); + } + + void setSubImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum dataFormat, GLenum dataType, const void * data) + { + GLW_ASSERT(this->isValid()); + glTexSubImage2D(this->m_target, level, xoffset, yoffset, width, height, dataFormat, dataType, data); + } + + void generateMipmap(void) + { + GLW_ASSERT(this->isValid()); + glGenerateMipmap(this->m_target); + } + + void setSampleMode(const TextureSampleMode & sampler) + { + GLW_ASSERT(this->isValid()); + if (GLW_CARE_OF(sampler.minFilter)) glTexParameteri(this->m_target, GL_TEXTURE_MIN_FILTER, sampler.minFilter); + if (GLW_CARE_OF(sampler.magFilter)) glTexParameteri(this->m_target, GL_TEXTURE_MAG_FILTER, sampler.magFilter); + if (GLW_CARE_OF(sampler.wrapS )) glTexParameteri(this->m_target, GL_TEXTURE_WRAP_S, sampler.wrapS ); + if (GLW_CARE_OF(sampler.wrapT )) glTexParameteri(this->m_target, GL_TEXTURE_WRAP_T, sampler.wrapT ); + } + + protected: + + Texture2D(Context * ctx) + : SafeObject (ctx) + , SafeRenderable (ctx) + , SafeTexture (ctx) + , SafeType (ctx) + , BaseType (ctx) + { + ; + } + + bool create(const Texture2DArguments & args) + { + this->destroy(); + + GLint activeUnit = 0; + glGetIntegerv(GL_ACTIVE_TEXTURE, &activeUnit); + + GLint boundName = 0; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundName); + + glGenRenderbuffers(1, &(this->m_name)); + this->setBinding(GL_TEXTURE_2D, 0); + this->bind(); + this->allocate(args.format, args.width, args.height, args.dataFormat, args.dataType, args.data); + this->setSampleMode(args.sampler); + + glActiveTexture(activeUnit); + glBindTexture(GL_TEXTURE_2D, boundName); + + return true; + } + + void allocate(GLenum format, GLsizei width, GLsizei height, GLenum dataFormat, GLenum dataType, const void * data) + { + GLW_ASSERT(this->isValid()); + glTexImage2D(this->m_target, 0, format, width, height, 0, dataFormat, dataType, data); + this->m_format = format; + this->m_width = width; + this->m_height = height; + } +}; + +typedef detail::SafeHandle Texture2DHandle; +typedef detail::UnsafeHandle BoundTexture2D; + +}; + +#endif // GLW_TEXTURE2D_H diff --git a/wrap/glw/type.h b/wrap/glw/type.h new file mode 100644 index 00000000..ccd936c5 --- /dev/null +++ b/wrap/glw/type.h @@ -0,0 +1,24 @@ +#ifndef GLW_TYPE_H +#define GLW_TYPE_H + +#include "./common.h" + +namespace glw +{ + +enum Type +{ + NoType = 0, + BufferType, + RenderbufferType, + VertexShaderType, + GeometryShaderType, + FragmentShaderType, + ProgramType, + Texture2DType, + FramebufferType +}; + +}; + +#endif // GLW_TYPE_H diff --git a/wrap/glw/utility.h b/wrap/glw/utility.h new file mode 100644 index 00000000..0353e054 --- /dev/null +++ b/wrap/glw/utility.h @@ -0,0 +1,288 @@ +#ifndef GLW_UTILITY_H +#define GLW_UTILITY_H + +#include +#include + +#include +#include +#include +#include + +#include "./context.h" + +#define GLW_STRINGFY(S) #S +#define GLW_OFFSET_OF(TYPE, MEMBER) ((const void *)(offsetof(TYPE, MEMBER))) + +namespace glw +{ + +class ShaderHeaderBuilder +{ + public: + + typedef void BaseType; + typedef ShaderHeaderBuilder ThisType; + + void clear(void) + { + this->m_version .clear(); + this->m_extensions .clear(); + this->m_defines .clear(); + this->m_texts .clear(); + } + + ThisType & version(const std::string & v) + { + this->m_version = v; + return (*this); + } + + ThisType & enableExtension(const std::string & ext) + { + this->m_extensions[ext] = ThisType::Enable; + return (*this); + } + + ThisType & disableExtension(const std::string & ext) + { + this->m_extensions[ext] = ThisType::Disable; + return (*this); + } + + ThisType & requireExtension(const std::string & ext) + { + this->m_extensions[ext] = ThisType::Require; + return (*this); + } + + ThisType & define(const std::string & name, const std::string & value) + { + this->m_defines[name] = value; + return (*this); + } + + ThisType & text(const std::string & txt) + { + this->m_texts.push_back(txt); + return (*this); + } + + std::string toString(void) const + { + const char * extModeMap[] = + { + "", + "enable", + "disable", + "require" + }; + + std::ostringstream res; + + if (!this->m_version.empty()) + { + res << "#version " << this->m_version << std::endl; + res << std::endl; + } + + if (!this->m_extensions.empty()) + { + for (ExtensionMapConstIterator it=this->m_extensions.begin(); it!=this->m_extensions.end(); ++it) + { + if (it->second == ThisType::DontCare) continue; + res << "#extension " << it->first << " : " << extModeMap[it->second] << std::endl; + } + res << std::endl; + } + + if (!this->m_defines.empty()) + { + for (DefineMapConstIterator it=this->m_defines.begin(); it!=this->m_defines.end(); ++it) + { + res << "#define " << it->first << " " << it->second << std::endl; + } + res << std::endl; + } + + if (!this->m_texts.empty()) + { + for (size_t i=0; im_texts.size(); ++i) + { + res << this->m_texts[i] << std::endl; + } + res << std::endl; + } + + return res.str(); + } + + protected: + + enum ExtensionMode + { + DontCare = 0, + Enable, + Disable, + Require + }; + + typedef std::map ExtensionMap; + typedef ExtensionMap::const_iterator ExtensionMapConstIterator; + typedef ExtensionMap::iterator ExtensionMapIterator; + typedef ExtensionMap::value_type ExtensionMapValue; + + typedef std::map DefineMap; + typedef DefineMap::const_iterator DefineMapConstIterator; + typedef DefineMap::iterator DefineMapIterator; + typedef DefineMap::value_type DefineMapValue; + + typedef std::vector TextVector; + + std::string m_version; + ExtensionMap m_extensions; + DefineMap m_defines; + TextVector m_texts; +}; + +inline std::string readTextFile(const char * fileName) +{ + std::string r; + if (fileName == 0) return r; + + FILE * f = fopen(fileName, "rb"); + if (f == 0) return r; + + fseek(f, 0, SEEK_END); + const size_t sz = size_t(ftell(f)); + rewind(f); + + char * str = new char [sz + 1]; + fread(str, sizeof(char), sz / sizeof(char), f); + fclose(f); + + str[sz] = '\0'; + r = str; + delete [] str; + + return r; +} + +inline std::string readTextFile(const std::string & fileName) +{ + return readTextFile(fileName.c_str()); +} + +inline BufferHandle createBuffer(Context & ctx, GLsizeiptr size, const void * data = 0, GLenum usage = GL_STATIC_DRAW) +{ + BufferArguments args; + args.size = size; + args.usage = usage; + args.data = data; + return ctx.createBuffer(args); +} + +template +inline BufferHandle createBuffer(Context & ctx, const std::vector & data, GLenum usage = GL_STATIC_DRAW) +{ + return createBuffer(ctx, GLsizeiptr(sizeof(TValue) * data.size()), ((!data.empty()) ? (&(data[0])) : (0)), usage); +} + +inline RenderbufferHandle createRenderbuffer(Context & ctx, GLenum format, GLsizei width, GLsizei height) +{ + RenderbufferArguments args; + args.format = format; + args.width = width; + args.height = height; + return ctx.createRenderbuffer(args); +} + +inline Texture2DHandle createTexture2D(Context & ctx, GLenum format, GLsizei width, GLsizei height, GLenum dataFormat, GLenum dataType, const void * data = 0, const TextureSampleMode & sampler = TextureSampleMode()) +{ + Texture2DArguments args; + args.format = format; + args.width = width; + args.height = height; + args.dataFormat = dataFormat; + args.dataType = dataType; + args.data = data; + args.sampler = sampler; + return ctx.createTexture2D(args); +} + +inline FramebufferHandle createFramebuffer +( + Context & ctx, + RenderTarget & depthTarget , + RenderTarget & colorTarget0 = RenderTarget(), + RenderTarget & colorTarget1 = RenderTarget(), + RenderTarget & colorTarget2 = RenderTarget(), + RenderTarget & colorTarget3 = RenderTarget(), + RenderTarget & colorTarget4 = RenderTarget(), + RenderTarget & colorTarget5 = RenderTarget(), + RenderTarget & colorTarget6 = RenderTarget(), + RenderTarget & colorTarget7 = RenderTarget() +) +{ + FramebufferArguments args; + + args.depthTarget = depthTarget; + + if (colorTarget0.target) { args.colorTargets[0] = colorTarget0; args.targetInputs[0] = 0; } + if (colorTarget1.target) { args.colorTargets[1] = colorTarget1; args.targetInputs[1] = 1; } + if (colorTarget2.target) { args.colorTargets[2] = colorTarget2; args.targetInputs[2] = 2; } + if (colorTarget3.target) { args.colorTargets[3] = colorTarget3; args.targetInputs[3] = 3; } + if (colorTarget4.target) { args.colorTargets[4] = colorTarget4; args.targetInputs[4] = 4; } + if (colorTarget5.target) { args.colorTargets[5] = colorTarget5; args.targetInputs[5] = 5; } + if (colorTarget6.target) { args.colorTargets[6] = colorTarget6; args.targetInputs[6] = 6; } + if (colorTarget7.target) { args.colorTargets[7] = colorTarget7; args.targetInputs[7] = 7; } + + return ctx.createFramebuffer(args); +} + +inline ProgramHandle createProgram(Context & ctx, const std::string & srcPrefix, const std::string & vertexSrc, const std::string & geometrySrc, const std::string & fragmentSrc, const ProgramArguments & args = ProgramArguments()) +{ + ProgramArguments pArgs = args; + + if (!vertexSrc.empty()) + { + VertexShaderArguments args; + args.source = srcPrefix + vertexSrc; + pArgs.shaders.push_back(ctx.createVertexShader(args)); + } + + if (!geometrySrc.empty()) + { + GeometryShaderArguments args; + args.source = srcPrefix + geometrySrc; + pArgs.shaders.push_back(ctx.createGeometryShader(args)); + } + + if (!fragmentSrc.empty()) + { + FragmentShaderArguments args; + args.source = srcPrefix + fragmentSrc; + pArgs.shaders.push_back(ctx.createFragmentShader(args)); + } + + return ctx.createProgram(pArgs); +} + +inline ProgramHandle createProgram(Context & ctx, const std::string & srcPrefix, const std::string & vertexSrc, const std::string & fragmentSrc, const ProgramArguments & args = ProgramArguments()) +{ + return createProgram(ctx, srcPrefix, vertexSrc, "", fragmentSrc, args); +} + +inline ProgramHandle loadProgram(Context & ctx, const std::string & srcPrefix, const std::string & vertexFile, const std::string & geometryFile, const std::string & fragmentFile, const ProgramArguments & args = ProgramArguments()) +{ + return createProgram(ctx, srcPrefix, readTextFile(vertexFile), readTextFile(geometryFile), readTextFile(fragmentFile), args); +} + +inline ProgramHandle loadProgram(Context & ctx, const std::string & srcPrefix, const std::string & vertexFile, const std::string & fragmentFile, const ProgramArguments & args = ProgramArguments()) +{ + return loadProgram(ctx, srcPrefix, vertexFile, "", fragmentFile.c_str(), args); +} + +}; + +#endif // GLW_UTILITY_H diff --git a/wrap/glw/vertexshader.h b/wrap/glw/vertexshader.h new file mode 100644 index 00000000..c6a1885d --- /dev/null +++ b/wrap/glw/vertexshader.h @@ -0,0 +1,87 @@ +#ifndef GLW_VERTEXSHADER_H +#define GLW_VERTEXSHADER_H + +#include "./shader.h" + +namespace glw +{ + +class VertexShaderArguments : public ShaderArguments +{ + public: + + typedef ShaderArguments BaseType; + typedef VertexShaderArguments ThisType; + + VertexShaderArguments(void) + { + this->clear(); + } + + void clear(void) + { + BaseType::clear(); + } +}; + +class SafeVertexShader : public virtual SafeShader +{ + public: + + typedef SafeShader BaseType; + typedef SafeVertexShader ThisType; + + protected: + + SafeVertexShader(Context * ctx) + : SafeObject (ctx) + , BaseType (ctx) + { + ; + } +}; + +class VertexShader : public Shader, public SafeVertexShader +{ + friend class Context; + friend class detail::SharedObjectBinding; + + public: + + typedef Shader BaseType; + typedef SafeVertexShader SafeType; + typedef VertexShader ThisType; + + virtual Type type(void) const + { + return VertexShaderType; + } + + protected: + + VertexShader(Context * ctx) + : SafeObject (ctx) + , SafeShader (ctx) + , SafeType (ctx) + , BaseType (ctx) + { + ; + } + + virtual GLenum shaderType(void) const + { + return GL_VERTEX_SHADER; + } + + bool create(const VertexShaderArguments & args) + { + return BaseType::create(args); + } +}; + +typedef detail::SafeHandle VertexShaderHandle; +typedef detail::UnsafeHandle BoundVertexShader; + +}; + +#endif // GLW_VERTEXSHADER_H