From 02feac06937ec4e8e122a833b4903ccf0bd6d030 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 21 Dec 2013 11:58:57 +0200 Subject: [PATCH] Add support for multiple binding points in the RAII binders --- source/bindable.h | 69 +++++++++++++++++++++++++++++++++++++++---- source/bufferable.cpp | 8 ++--- source/mesh.cpp | 3 +- 3 files changed, 66 insertions(+), 14 deletions(-) diff --git a/source/bindable.h b/source/bindable.h index f534d7af..8651c70e 100644 --- a/source/bindable.h +++ b/source/bindable.h @@ -71,8 +71,9 @@ does nothing upon destruction. class Bind { private: - typedef void CleanupFunc(); + typedef void CleanupFunc(int); + int slot; CleanupFunc *cleanup; public: @@ -85,6 +86,15 @@ public: template Bind(const T &o) { init(&o); } + template + Bind(T *o, S s) { init(o, s); } + + template + Bind(const T *o, S s) { init(o, s); } + + template + Bind(const T &o, S s) { init(&o, s); } + private: template void init(const T *o) @@ -96,14 +106,29 @@ private: T::unbind(); } + template + void init(const T *o, S s) + { + cleanup = (o ? &unbind_from : 0); + slot = s; + if(o) + o->bind_to(s); + else + T::unbind_from(s); + } + public: ~Bind() - { if(cleanup) cleanup(); } + { if(cleanup) cleanup(slot); } private: template - static void unbind() + static void unbind(int) { T::unbind(); } + + template + static void unbind_from(int s) + { T::unbind_from(static_cast(s)); } }; @@ -113,9 +138,10 @@ Similar to Bind, but restores previous binding upon destruction. class BindRestore { private: - typedef void CleanupFunc(const void *); + typedef void CleanupFunc(const void *, int); const void *old; + int slot; CleanupFunc *cleanup; public: @@ -128,6 +154,15 @@ public: template BindRestore(const T &o) { init(&o); } + template + BindRestore(T *o, S s) { init(o, s); } + + template + BindRestore(const T *o, S s) { init(o, s); } + + template + BindRestore(const T &o, S s) { init(&o, s); } + private: template void init(T *o) @@ -140,19 +175,41 @@ private: T::unbind(); } + template + void init(T *o, S s) + { + old = T::current(s); + slot = s; + cleanup = (o!=old ? &restore_to : 0); + if(o) + o->bind_to(s); + else if(old) + T::unbind_from(s); + } + public: ~BindRestore() - { if(cleanup) cleanup(old); } + { if(cleanup) cleanup(old, slot); } private: template - static void restore(const void *o) + static void restore(const void *o, int) { if(o) reinterpret_cast(o)->bind(); else T::unbind(); } + + template + static void restore_to(const void *o, int si) + { + S s = static_cast(si); + if(o) + reinterpret_cast(o)->bind_to(s); + else + T::unbind_from(s); + } }; } // namespace GL diff --git a/source/bufferable.cpp b/source/bufferable.cpp index 1f6122e0..eb3f1c00 100644 --- a/source/bufferable.cpp +++ b/source/bufferable.cpp @@ -1,4 +1,5 @@ #include +#include "bindable.h" #include "buffer.h" #include "bufferable.h" @@ -81,8 +82,7 @@ void Bufferable::update_offset() void Bufferable::update_buffer() const { - const Buffer *old_buffer = Buffer::current(buffer->get_type()); - buffer->bind(); + BindRestore bind(buffer, buffer->get_type()); if(offset+get_data_size()>=buffer->get_size()) { const Bufferable *last = this; @@ -102,10 +102,6 @@ void Bufferable::update_buffer() const } upload_data(); - if(old_buffer) - old_buffer->bind_to(buffer->get_type()); - else - buffer->unbind(); dirty = false; } diff --git a/source/mesh.cpp b/source/mesh.cpp index 26d66044..c9819ae9 100644 --- a/source/mesh.cpp +++ b/source/mesh.cpp @@ -88,8 +88,7 @@ void Mesh::refresh() const if(dirty&2) { glBindVertexArray(vao_id); - BufferAlias vbuf_alias(*vbuf); - Bind bind_vbuf(vbuf_alias); + Bind bind_vbuf(vbuf, ARRAY_BUFFER); const VertexFormat &fmt = vertices.get_format(); unsigned stride = get_stride(fmt)*sizeof(float); -- 2.43.0