]> git.tdb.fi Git - libs/gl.git/blobdiff - source/backends/opengl/pipelinestate_backend.cpp
Refactor low-level state management
[libs/gl.git] / source / backends / opengl / pipelinestate_backend.cpp
index 19ee0f58f0a1788a27b46b1a326c41eafc133ca0..9616b18be326d99cbccdfa0c30ad0f195732a60f 100644 (file)
@@ -26,37 +26,34 @@ using namespace std;
 namespace Msp {
 namespace GL {
 
-const OpenGLPipelineState *OpenGLPipelineState::last_applied = 0;
-vector<int> OpenGLPipelineState::bound_tex_targets;
-vector<char> OpenGLPipelineState::bound_uniform_blocks;
-unsigned OpenGLPipelineState::restart_index = 0;
-unsigned OpenGLPipelineState::n_clip_distances = 0;
-
-OpenGLPipelineState::OpenGLPipelineState()
-{
-       if(bound_tex_targets.empty())
-               bound_tex_targets.resize(Device::get_current().get_info().limits.max_texture_bindings);
-       if(bound_uniform_blocks.empty())
-               bound_uniform_blocks.resize(Device::get_current().get_info().limits.max_uniform_bindings);
-}
-
 OpenGLPipelineState::~OpenGLPipelineState()
 {
-       if(this==last_applied)
-               last_applied = 0;
+       if(applied_to)
+               applied_to->get_state().last_pipeline = 0;
 }
 
 void OpenGLPipelineState::apply() const
 {
-       if(!last_applied)
-               OpenGLTexture::unbind_scratch();
+       const PipelineState &self = *static_cast<const PipelineState *>(this);
+       Device &device = Device::get_current();
+       unsigned mask = changes;
 
-       apply(this==last_applied ? static_cast<const PipelineState *>(this)->changes : ~0U);
-}
+       if(applied_to && applied_to!=&device)
+       {
+               applied_to->get_state().last_pipeline = 0;
+               mask = ~0U;
+       }
 
-void OpenGLPipelineState::apply(unsigned mask) const
-{
-       const PipelineState &self = *static_cast<const PipelineState *>(this);
+       OpenGLDeviceState &dev_state = device.get_state();
+       if(!dev_state.last_pipeline)
+               OpenGLTexture::unbind_scratch();
+       
+       if(this!=dev_state.last_pipeline)
+       {
+               if(dev_state.last_pipeline)
+                       dev_state.last_pipeline->applied_to = 0;
+               mask = ~0U;
+       }
 
        if(mask&PipelineState::FRAMEBUFFER)
        {
@@ -93,16 +90,16 @@ void OpenGLPipelineState::apply(unsigned mask) const
                glUseProgram(self.shprog ? self.shprog->id : 0);
 
                unsigned ncd = (self.shprog ? self.shprog->get_n_clip_distances() : 0);
-               if(ncd!=n_clip_distances)
+               if(ncd!=dev_state.n_clip_distances)
                {
-                       for(unsigned i=0; (i<ncd || i<n_clip_distances); ++i)
+                       for(unsigned i=0; (i<ncd || i<dev_state.n_clip_distances); ++i)
                        {
                                if(i<ncd)
                                        glEnable(GL_CLIP_PLANE0+i);
                                else
                                        glDisable(GL_CLIP_PLANE0+i);
                        }
-                       n_clip_distances = ncd;
+                       dev_state.n_clip_distances = ncd;
                }
        }
 
@@ -116,7 +113,7 @@ void OpenGLPipelineState::apply(unsigned mask) const
                                        if(u.binding>=0)
                                        {
                                                glBindBufferRange(GL_UNIFORM_BUFFER, u.binding, u.block->get_buffer()->id, u.block->get_offset(), u.block->get_data_size());
-                                               bound_uniform_blocks[u.binding] = 1;
+                                               dev_state.bound_uniform_blocks[u.binding] = 1;
                                        }
                                        else if(u.binding==ReflectData::DEFAULT_BLOCK && self.shprog)
                                        {
@@ -142,12 +139,12 @@ void OpenGLPipelineState::apply(unsigned mask) const
                                        else
                                        {
                                                glActiveTexture(GL_TEXTURE0+t.binding);
-                                               if(bound_tex_targets[t.binding] && static_cast<int>(t.texture->target)!=bound_tex_targets[t.binding])
-                                                       glBindTexture(bound_tex_targets[t.binding], 0);
+                                               if(dev_state.bound_tex_targets[t.binding] && static_cast<int>(t.texture->target)!=dev_state.bound_tex_targets[t.binding])
+                                                       glBindTexture(dev_state.bound_tex_targets[t.binding], 0);
                                                glBindTexture(t.texture->target, t.texture->id);
                                        }
 
-                                       bound_tex_targets[t.binding] = t.texture->target;
+                                       dev_state.bound_tex_targets[t.binding] = t.texture->target;
 
                                        glBindSampler(t.binding, t.sampler->id);
                                        t.sampler->refresh();
@@ -167,12 +164,12 @@ void OpenGLPipelineState::apply(unsigned mask) const
 
                        vertex_setup->refresh();
                        unsigned ri = (vertex_setup->get_index_type()==UNSIGNED_INT ? 0xFFFFFFFF : 0xFFFF);
-                       if(ri!=restart_index)
+                       if(ri!=dev_state.restart_index)
                        {
-                               if(!restart_index)
+                               if(!dev_state.restart_index)
                                        glEnable(GL_PRIMITIVE_RESTART);
                                glPrimitiveRestartIndex(ri);
-                               restart_index = ri;
+                               dev_state.restart_index = ri;
                        }
                }
        }
@@ -236,39 +233,41 @@ void OpenGLPipelineState::apply(unsigned mask) const
                }
        }
 
-       last_applied = this;
-       self.changes &= ~mask;
+       applied_to = &device;
+       dev_state.last_pipeline = this;
+       changes = 0;
 }
 
 void OpenGLPipelineState::clear()
 {
-       if(last_applied)
+       OpenGLDeviceState &dev_state = Device::get_current().get_state();
+       if(dev_state.last_pipeline)
        {
                glUseProgram(0);
                glBindVertexArray(0);
 
-               for(unsigned i=0; i<n_clip_distances; ++i)
+               for(unsigned i=0; i<dev_state.n_clip_distances; ++i)
                        glDisable(GL_CLIP_PLANE0+i);
-               n_clip_distances = 0;
+               dev_state.n_clip_distances = 0;
 
-               for(unsigned i=0; i<bound_tex_targets.size(); ++i)
-                       if(bound_tex_targets[i])
+               for(unsigned i=0; i<dev_state.bound_tex_targets.size(); ++i)
+                       if(dev_state.bound_tex_targets[i])
                        {
                                if(ARB_direct_state_access)
                                        glBindTextureUnit(i, 0);
                                else
                                {
                                        glActiveTexture(GL_TEXTURE0+i);
-                                       glBindTexture(bound_tex_targets[i], 0);
+                                       glBindTexture(dev_state.bound_tex_targets[i], 0);
                                }
-                               bound_tex_targets[i] = 0;
+                               dev_state.bound_tex_targets[i] = 0;
                        }
 
-               for(unsigned i=0; i<bound_uniform_blocks.size(); ++i)
-                       if(bound_uniform_blocks[i])
+               for(unsigned i=0; i<dev_state.bound_uniform_blocks.size(); ++i)
+                       if(dev_state.bound_uniform_blocks[i])
                        {
                                glBindBufferBase(GL_UNIFORM_BUFFER, i, 0);
-                               bound_uniform_blocks[i] = 0;
+                               dev_state.bound_uniform_blocks[i] = 0;
                        }
 
                glDisable(GL_DEPTH_TEST);
@@ -276,7 +275,8 @@ void OpenGLPipelineState::clear()
                glDisable(GL_STENCIL_TEST);
                glDisable(GL_BLEND);
 
-               last_applied = 0;
+               dev_state.last_pipeline->applied_to = 0;
+               dev_state.last_pipeline = 0;
        }
 }