From 42ace9ac1350d3ae009bdd2fb335ac1e57d1b36b Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 8 Jun 2010 17:22:30 +0000 Subject: [PATCH] Rework Bind and enable it to restore the old binding Derive all simple bindable classes from Bindable Some logic corrections in RenderPass --- source/bindable.h | 65 ++++++++++++++++++++++++++++++++++------- source/framebuffer.cpp | 40 ++++++++++--------------- source/framebuffer.h | 5 ++-- source/lighting.cpp | 41 ++++++++++++-------------- source/lighting.h | 5 ++-- source/material.cpp | 7 ++--- source/material.h | 5 ++-- source/object.cpp | 6 ++-- source/object.h | 2 +- source/program.cpp | 19 ++++-------- source/program.h | 8 ++--- source/renderbuffer.cpp | 17 +++++++---- source/renderbuffer.h | 7 +++-- source/renderpass.cpp | 31 +++++++++----------- source/renderpass.h | 5 ++-- source/tests.h | 2 -- 16 files changed, 141 insertions(+), 124 deletions(-) diff --git a/source/bindable.h b/source/bindable.h index e26840fa..d85ec78d 100644 --- a/source/bindable.h +++ b/source/bindable.h @@ -29,7 +29,7 @@ protected: } public: - const T *current() const { return cur_obj; } + static const T *current() { return cur_obj; } }; template @@ -39,7 +39,7 @@ const T *Bindable::cur_obj; /** RAII class for binding things. Binds the thing upon construction and unbinds it upon destruction. If a null pointer is given, unbinds upon construction and -does nothing upon destruction. +does nothing upon destruction. Optionally can restore the previous binding. */ class Bind { @@ -50,22 +50,58 @@ private: }; template - struct Binder: Base + struct Binder1: Base { - const T &obj; + const T *obj; + + Binder1(const T *o): + obj(o) + { + if(obj) + obj->bind(); + else + T::unbind(); + } + + ~Binder1() + { + if(obj) + obj->unbind(); + } + }; - Binder(const T &o): obj(o) { obj.bind(); } - ~Binder() { obj.unbind(); } + template + struct Binder2: Base + { + const T *obj; + const U *old; + + Binder2(const T *o, const U *l): + obj(o), + old(l) + { + if(obj) + obj->bind(); + else + T::unbind(); + } + + ~Binder2() + { + if(old) + old->bind(); + else if(obj) + obj->unbind(); + } }; Base *binder; public: template - Bind(const T &o): binder(new Binder(o)) { } - - template - Bind(const T *o): binder(o ? new Binder(*o) : 0) { if(!o) T::unbind(); } + Bind(const T *o, bool r = false): + binder(r ? create(o, T::current()) : create(o)) + { } private: Bind(const Bind &); @@ -73,6 +109,15 @@ private: public: ~Bind() { delete binder; } + +private: + template + Base *create(const T *o) + { return new Binder1(o); } + + template + Base *create(const T *o, const U *l) + { return new Binder2(o, l); } }; } // namespace GL diff --git a/source/framebuffer.cpp b/source/framebuffer.cpp index 6941c034..cf3761d0 100644 --- a/source/framebuffer.cpp +++ b/source/framebuffer.cpp @@ -34,17 +34,20 @@ Framebuffer::~Framebuffer() void Framebuffer::bind() const { - if(!cur_fbo) - get(GL_VIEWPORT, sys_viewport); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id); - cur_fbo = this; - if(width && height) - viewport(0, 0, width, height); + const Framebuffer *old = current(); + if(set_current(this)) + { + if(!old) + get(GL_VIEWPORT, sys_viewport); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id); + if(width && height) + viewport(0, 0, width, height); + } } void Framebuffer::attach(FramebufferAttachment attch, Renderbuffer &rbuf) { - maybe_bind(); + bind(); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attch, GL_RENDERBUFFER_EXT, rbuf.get_id()); get_or_create_attachment(attch) = rbuf; check_size(); @@ -52,7 +55,7 @@ void Framebuffer::attach(FramebufferAttachment attch, Renderbuffer &rbuf) void Framebuffer::attach(FramebufferAttachment attch, Texture2D &tex, int level) { - maybe_bind(); + bind(); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attch, tex.get_target(), tex.get_id(), level); get_or_create_attachment(attch) = tex; check_size(); @@ -60,7 +63,7 @@ void Framebuffer::attach(FramebufferAttachment attch, Texture2D &tex, int level) void Framebuffer::detach(FramebufferAttachment attch) { - maybe_bind(); + bind(); for(vector::iterator i=attachments.begin(); i!=attachments.end(); ++i) if(i->attachment==attch) { @@ -76,31 +79,19 @@ void Framebuffer::detach(FramebufferAttachment attch) FramebufferStatus Framebuffer::check_status() const { - maybe_bind(); + bind(); return static_cast(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); } -const Framebuffer *Framebuffer::current() -{ - return cur_fbo; -} - void Framebuffer::unbind() { - if(cur_fbo) + if(set_current(0)) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - cur_fbo = 0; viewport(sys_viewport[0], sys_viewport[1], sys_viewport[2], sys_viewport[3]); } } -void Framebuffer::maybe_bind() const -{ - if(cur_fbo!=this) - bind(); -} - Framebuffer::Attachment &Framebuffer::get_or_create_attachment(FramebufferAttachment attch) { for(vector::iterator i=attachments.begin(); i!=attachments.end(); ++i) @@ -126,12 +117,11 @@ void Framebuffer::check_size() width = tex->get_width(); height = tex->get_height(); } - if(cur_fbo==this) + if(current()==this) viewport(0, 0, width, height); } } -const Framebuffer *Framebuffer::cur_fbo = 0; int Framebuffer::sys_viewport[4] = { 0, 0, 1, 1 }; diff --git a/source/framebuffer.h b/source/framebuffer.h index 7c88b4cd..b4f43f77 100644 --- a/source/framebuffer.h +++ b/source/framebuffer.h @@ -9,6 +9,7 @@ Distributed under the LGPL #define MSP_GL_FRAMEBUFFER_H_ #include +#include "bindable.h" #include "gl.h" namespace Msp { @@ -73,7 +74,7 @@ least one image must be attached for the framebuffer to be usable. Requires the GL_EXT_framebuffer_object extension. */ -class Framebuffer +class Framebuffer: public Bindable { private: struct Attachment @@ -96,7 +97,6 @@ private: unsigned width; unsigned height; - static const Framebuffer *cur_fbo; static int sys_viewport[4]; public: @@ -116,7 +116,6 @@ public: */ FramebufferStatus check_status() const; - static const Framebuffer *current(); static void unbind(); private: void maybe_bind() const; diff --git a/source/lighting.cpp b/source/lighting.cpp index 0d6e7dc4..44a01a5e 100644 --- a/source/lighting.cpp +++ b/source/lighting.cpp @@ -39,33 +39,30 @@ void Lighting::detach(unsigned i) void Lighting::bind() const { - if(current!=this) - { - enable(LIGHTING); - glLightModelfv(GL_LIGHT_MODEL_AMBIENT, &ambient.r); - for(unsigned i=0; ibind_to(i); - current = this; - } + if(!set_current(this)) + return; + + enable(LIGHTING); + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, &ambient.r); + for(unsigned i=0; ibind_to(i); } void Lighting::unbind() { - if(current) - { - for(unsigned i=0; ilights.size(); ++i) - if(current->lights[i]) - { - Light::activate(i); - Light::unbind(); - } - disable(LIGHTING); - current = 0; - } -} + const Lighting *old = current(); + if(!set_current(0)) + return; -const Lighting *Lighting::current = 0; + for(unsigned i=0; ilights.size(); ++i) + if(old->lights[i]) + { + Light::activate(i); + Light::unbind(); + } + disable(LIGHTING); +} } // namespace GL } // namespace Msp diff --git a/source/lighting.h b/source/lighting.h index 85d5fb04..31e75a44 100644 --- a/source/lighting.h +++ b/source/lighting.h @@ -9,6 +9,7 @@ Distributed under the LGPL #define MSP_GL_LIGHTING_H_ #include +#include "bindable.h" #include "color.h" #include "gl.h" @@ -25,14 +26,12 @@ enum /** Encapsulates global lighting parameters and a number of individual lights. */ -class Lighting +class Lighting: public Bindable { private: Color ambient; std::vector lights; - static const Lighting *current; - public: Lighting(); diff --git a/source/material.cpp b/source/material.cpp index eee1ebc6..989bb12e 100644 --- a/source/material.cpp +++ b/source/material.cpp @@ -46,24 +46,21 @@ void Material::set_shininess(float s) void Material::bind() const { - if(current!=this) + if(set_current(this)) { glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, &ambient.r); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, &diffuse.r); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r); glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &emission.r); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess); - current = this; } } void Material::unbind() { - current = 0; + set_current(0); } -const Material *Material::current = 0; - Material::Loader::Loader(Material &m): DataFile::ObjectLoader(m) diff --git a/source/material.h b/source/material.h index 6614aeea..fa1612e1 100644 --- a/source/material.h +++ b/source/material.h @@ -9,6 +9,7 @@ Distributed under the LGPL #define MSP_GL_MATERIAL_H_ #include +#include "bindable.h" #include "color.h" namespace Msp { @@ -18,7 +19,7 @@ namespace GL { Stores OpenGL material properties. Since OpenGL does not support material objects, application of material is done with several calls to glMaterial. */ -class Material +class Material: public Bindable { public: class Loader: public DataFile::ObjectLoader @@ -55,8 +56,6 @@ public: void bind() const; static void unbind(); -private: - static const Material *current; }; } // namespace GL diff --git a/source/object.cpp b/source/object.cpp index 938e83f9..5ae04feb 100644 --- a/source/object.cpp +++ b/source/object.cpp @@ -44,7 +44,7 @@ void Object::render(const Tag &tag) const if(!pass) return; - Bind bind(*pass); + Bind bind(pass); meshes[0]->draw(); } @@ -54,14 +54,14 @@ void Object::render(const ObjectInstance &inst, const Tag &tag) const if(!pass) return; - Bind bind(*pass); + Bind bind(pass); render_instance(inst, tag); meshes[0]->draw(); } const RenderPass *Object::get_pass(const Tag &tag) const { - if(!technique->has_pass(tag)) + if(!technique || !technique->has_pass(tag)) return 0; return &technique->get_pass(tag); } diff --git a/source/object.h b/source/object.h index bff41bf1..2b5f4a85 100644 --- a/source/object.h +++ b/source/object.h @@ -82,7 +82,7 @@ public: if(!pass) return; - Bind bind(*pass); + Bind bind(pass); for(Iter i=begin; i!=end; ++i) render_instance(**i, tag); } diff --git a/source/program.cpp b/source/program.cpp index ef1f4c8a..1f28e956 100644 --- a/source/program.cpp +++ b/source/program.cpp @@ -113,8 +113,10 @@ void Program::bind() const if(!linked) throw InvalidState("Program is not linked"); + if(!set_current(this)) + return; + glUseProgramObjectARB(id); - cur_prog = this; } int Program::get_uniform_location(const string &n) const @@ -124,21 +126,12 @@ int Program::get_uniform_location(const string &n) const void Program::unbind() { - if(cur_prog) - { - glUseProgramObjectARB(0); - cur_prog = 0; - } -} + if(!set_current(0)) + return; -void Program::maybe_bind() -{ - if(cur_prog!=this) - bind(); + glUseProgramObjectARB(0); } -const Program *Program::cur_prog = 0; - Program::Loader::Loader(Program &p): DataFile::ObjectLoader(p) diff --git a/source/program.h b/source/program.h index af506fe8..63d43e0f 100644 --- a/source/program.h +++ b/source/program.h @@ -11,6 +11,7 @@ Distributed under the LGPL #include #include #include +#include "bindable.h" #include "gl.h" namespace Msp { @@ -18,7 +19,7 @@ namespace GL { class Shader; -class Program +class Program: public Bindable { private: unsigned id; @@ -26,8 +27,6 @@ private: bool del_shaders; bool linked; - static const Program *cur_prog; - public: class Loader: public DataFile::ObjectLoader { @@ -61,9 +60,6 @@ public: int get_uniform_location(const std::string &) const; static void unbind(); - -private: - void maybe_bind(); }; } // namespace GL diff --git a/source/renderbuffer.cpp b/source/renderbuffer.cpp index 31a623ea..0d3a76b5 100644 --- a/source/renderbuffer.cpp +++ b/source/renderbuffer.cpp @@ -25,11 +25,6 @@ Renderbuffer::~Renderbuffer() glDeleteRenderbuffersEXT(1, &id); } -void Renderbuffer::bind() const -{ - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, id); -} - void Renderbuffer::storage(PixelFormat fmt, unsigned w, unsigned h) { bind(); @@ -38,5 +33,17 @@ void Renderbuffer::storage(PixelFormat fmt, unsigned w, unsigned h) glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, fmt, width, height); } +void Renderbuffer::bind() const +{ + if(set_current(this)) + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, id); +} + +void Renderbuffer::unbind() +{ + if(set_current(0)) + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); +} + } // namespace GL } // namespace Msp diff --git a/source/renderbuffer.h b/source/renderbuffer.h index b7320929..b88db17a 100644 --- a/source/renderbuffer.h +++ b/source/renderbuffer.h @@ -8,6 +8,7 @@ Distributed under the LGPL #ifndef MSP_GL_RENDERBUFFER_H_ #define MSP_GL_RENDERBUFFER_H_ +#include "bindable.h" #include "pixelformat.h" namespace Msp { @@ -20,7 +21,7 @@ correctly but that is not needed as a texture later. Requires the GL_EXT_framebuffer_object extension. */ -class Renderbuffer +class Renderbuffer: public Bindable { private: unsigned id; @@ -35,9 +36,11 @@ public: unsigned get_width() const { return width; } unsigned get_height() const { return height; } + void storage(PixelFormat fmt, unsigned width, unsigned height); + void bind() const; - void storage(PixelFormat fmt, unsigned width, unsigned height); + static void unbind(); }; } // namespace GL diff --git a/source/renderpass.cpp b/source/renderpass.cpp index 4aa41dba..70fa546a 100644 --- a/source/renderpass.cpp +++ b/source/renderpass.cpp @@ -19,8 +19,6 @@ using namespace std; namespace Msp { namespace GL { -const RenderPass *RenderPass::current = 0; - RenderPass::RenderPass(): shprog(0), shdata(0), @@ -64,23 +62,21 @@ void RenderPass::set_texture(const string &slot, const Texture *tex) void RenderPass::bind() const { - if(this==current) + const RenderPass *old = current(); + if(!set_current(this)) return; - const RenderPass *old = current; - current = this; - if(shprog) { shprog->bind(); shdata->apply(); } - else if(old && !old->shprog) + else if(old && old->shprog) GL::Program::unbind(); if(material) material->bind(); - else if(old && !old->material) + else if(old && old->material) GL::Material::unbind(); for(unsigned i=0; ishprog) - GL::Program::unbind(); + const RenderPass *old = current(); + if(!set_current(0)) + return; - if(current->material) - GL::Material::unbind(); + if(old->shprog) + GL::Program::unbind(); - for(unsigned i=current->textures.size(); i--; ) - GL::Texture::unbind_from(i); + if(old->material) + GL::Material::unbind(); - current = 0; - } + for(unsigned i=old->textures.size(); i--; ) + GL::Texture::unbind_from(i); } diff --git a/source/renderpass.h b/source/renderpass.h index 94c6bc02..e2ea4c97 100644 --- a/source/renderpass.h +++ b/source/renderpass.h @@ -9,6 +9,7 @@ Distributed under the LGPL #define MSP_GL_RENDERPASS_H_ #include +#include "bindable.h" namespace Msp { namespace GL { @@ -22,7 +23,7 @@ class Texture; Encapsulates the data that determines the appearance of a rendered surface. This includes shader and data for it, material and textures. */ -class RenderPass +class RenderPass: public Bindable { public: class Loader: public DataFile::CollectionObjectLoader @@ -61,8 +62,6 @@ private: const Material *material; std::vector textures; - static const RenderPass *current; - RenderPass &operator=(const RenderPass &); public: RenderPass(); diff --git a/source/tests.h b/source/tests.h index 622834dc..75d15036 100644 --- a/source/tests.h +++ b/source/tests.h @@ -54,8 +54,6 @@ private: bool write; Predicate pred; - static const DepthTest *current; - public: DepthTest(); DepthTest(Predicate, bool = true); -- 2.45.2