]> git.tdb.fi Git - libs/gl.git/commitdiff
Allow applying a VertexArray in non-legacy mode
authorMikko Rasa <tdb@tdb.fi>
Fri, 17 Oct 2014 18:30:08 +0000 (21:30 +0300)
committerMikko Rasa <tdb@tdb.fi>
Fri, 17 Oct 2014 18:30:08 +0000 (21:30 +0300)
Mesh::bind now has consistent results whether or not vertex array objects
are available.  This is unlikely to be needed on full OpenGL, but is
necessary for OpenGL ES 2.0 support (ES 3.0 has VAOs).

source/mesh.cpp
source/vertexarray.cpp
source/vertexarray.h

index 3e9e118ac52e6a9eb40b47345cce0f9692d9b140..869ea671faeed0493ca4109dce4d27cddd1647e2 100644 (file)
@@ -183,7 +183,7 @@ void Mesh::bind() const
        if(!vao_id)
        {
                unbind();
-               vertices.apply();
+               vertices.apply(false);
        }
        else if(set_current(this))
        {
index 867aee7b189b71f348950741e4f2ccda6ae18921..db102ab4c355bbdb5e6a8d0e59f71021ea9d59f9 100644 (file)
@@ -11,6 +11,8 @@ using namespace std;
 namespace Msp {
 namespace GL {
 
+bool VertexArray::legacy_used = false;
+
 VertexArray::VertexArray(const VertexFormat &f)
 {
        reset(f);
@@ -29,6 +31,7 @@ void VertexArray::reset(const VertexFormat &f)
        clear();
        format = f;
        stride = get_stride(format);
+       legacy = false;
 
        arrays.clear();
 
@@ -43,6 +46,9 @@ void VertexArray::reset(const VertexFormat &f)
                arr.component = *c;
                arr.offset = offs;
 
+               if(*c<ATTRIB1)
+                       legacy = true;
+
                offs += get_component_size(*c);
        }
 }
@@ -101,7 +107,7 @@ unsigned VertexArray::get_data_size() const
        return data.size()*sizeof(float);
 }
 
-void VertexArray::bind() const
+void VertexArray::apply(bool use_legacy) const
 {
        if(format.empty())
                throw invalid_operation("VertexArray::apply");
@@ -109,6 +115,15 @@ void VertexArray::bind() const
        if(Mesh::current())
                throw invalid_operation("VertexArray::apply");
 
+       /* Unbind first if the legacy flag changes.  The logic for supporting it
+       directly in apply_arrays would get too complicated, and this also allows
+       rebinding the same array with different legacy setting. */
+       if(legacy_used!=use_legacy)
+               unbind();
+
+       if(!use_legacy)
+               static Require _req(ARB_vertex_shader);
+
        const VertexArray *old = current();
        /* If the array has been modified, apply it even if it was the last one to
        be applied.  This is necessary to get the data updated to vertex buffer, and
@@ -124,10 +139,10 @@ void VertexArray::bind() const
 
        const float *base = (vbuf ? reinterpret_cast<float *>(get_offset()) : &data[0]);
        unsigned stride_bytes = stride*sizeof(float);
-       apply_arrays(&arrays, (old ? &old->arrays : 0), base, stride_bytes);
+       apply_arrays(&arrays, (old ? &old->arrays : 0), base, stride_bytes, use_legacy);
 }
 
-void VertexArray::apply_arrays(const vector<Array> *arrays, const vector<Array> *old_arrays, const float *base, unsigned stride_bytes)
+void VertexArray::apply_arrays(const vector<Array> *arrays, const vector<Array> *old_arrays, const float *base, unsigned stride_bytes, bool use_legacy)
 {
        unsigned active_tex = 0;
        unsigned n_arrays = arrays ? arrays->size() : 0;
@@ -143,76 +158,85 @@ void VertexArray::apply_arrays(const vector<Array> *arrays, const vector<Array>
                unsigned char comp = (arr ? arr->component : old_arr->component);
                unsigned sz = get_component_size(comp);
                unsigned t = get_component_type(comp);
-               GLenum array_type = 0;
-               if(t==get_component_type(VERTEX3))
-               {
-                       if(arr)
-                               glVertexPointer(sz, GL_FLOAT, stride_bytes, base+arr->offset);
-                       array_type = GL_VERTEX_ARRAY;
-               }
-               else if(t==get_component_type(NORMAL3))
+               if(use_legacy)
                {
-                       if(arr)
-                               glNormalPointer(GL_FLOAT, stride_bytes, base+arr->offset);
-                       array_type = GL_NORMAL_ARRAY;
-               }
-               else if(t==get_component_type(COLOR4_FLOAT))
-               {
-                       if(arr)
+                       GLenum array_type = 0;
+                       if(t==get_component_type(VERTEX3))
                        {
-                               if(sz==1)
-                                       glColorPointer(4, GL_UNSIGNED_BYTE, stride_bytes, base+arr->offset);
-                               else
-                                       glColorPointer(sz, GL_FLOAT, stride_bytes, base+arr->offset);
+                               if(arr)
+                                       glVertexPointer(sz, GL_FLOAT, stride_bytes, base+arr->offset);
+                               array_type = GL_VERTEX_ARRAY;
                        }
-                       array_type = GL_COLOR_ARRAY;
-               }
-               else if(comp>=TEXCOORD1 && comp<=TEXCOORD4+12)
-               {
-                       t -= get_component_type(TEXCOORD1);
-                       if(t>0 || active_tex)
+                       else if(t==get_component_type(NORMAL3))
+                       {
+                               if(arr)
+                                       glNormalPointer(GL_FLOAT, stride_bytes, base+arr->offset);
+                               array_type = GL_NORMAL_ARRAY;
+                       }
+                       else if(t==get_component_type(COLOR4_FLOAT))
+                       {
+                               if(arr)
+                               {
+                                       if(sz==1)
+                                               glColorPointer(4, GL_UNSIGNED_BYTE, stride_bytes, base+arr->offset);
+                                       else
+                                               glColorPointer(sz, GL_FLOAT, stride_bytes, base+arr->offset);
+                               }
+                               array_type = GL_COLOR_ARRAY;
+                       }
+                       else if(comp>=TEXCOORD1 && comp<=TEXCOORD4+12)
                        {
-                               glClientActiveTexture(GL_TEXTURE0+t);
-                               active_tex = t;
+                               t -= get_component_type(TEXCOORD1);
+                               if(t>0 || active_tex)
+                               {
+                                       glClientActiveTexture(GL_TEXTURE0+t);
+                                       active_tex = t;
+                               }
+                               if(arr)
+                                       glTexCoordPointer(sz, GL_FLOAT, stride_bytes, base+arr->offset);
+                               array_type = GL_TEXTURE_COORD_ARRAY;
+                       }
+
+                       if(array_type)
+                       {
+                               // Only change enable state if needed
+                               if(arr && !old_arr)
+                                       glEnableClientState(array_type);
+                               else if(old_arr && !arr)
+                                       glDisableClientState(array_type);
+
+                               continue;
                        }
-                       if(arr)
-                               glTexCoordPointer(sz, GL_FLOAT, stride_bytes, base+arr->offset);
-                       array_type = GL_TEXTURE_COORD_ARRAY;
                }
-               else
+
+               if(t>=get_component_type(ATTRIB1))
+                       t -= get_component_type(ATTRIB1);
+               if(arr)
                {
-                       if(t>=get_component_type(ATTRIB1))
-                               t -= get_component_type(ATTRIB1);
-                       if(arr)
+                       if(arr->component==COLOR4_UBYTE)
+                               glVertexAttribPointer(t, 4, GL_UNSIGNED_BYTE, true, stride_bytes, base+arr->offset);
+                       else
                                glVertexAttribPointer(t, sz, GL_FLOAT, false, stride_bytes, base+arr->offset);
                }
 
                // Only change enable state if needed
                if(arr && !old_arr)
-               {
-                       if(array_type)
-                               glEnableClientState(array_type);
-                       else
-                               glEnableVertexAttribArray(t);
-               }
+                       glEnableVertexAttribArray(t);
                else if(old_arr && !arr)
-               {
-                       if(array_type)
-                               glDisableClientState(array_type);
-                       else
-                               glDisableVertexAttribArray(t);
-               }
+                       glDisableVertexAttribArray(t);
        }
 
        if(active_tex)
                glClientActiveTexture(GL_TEXTURE0);
+
+       legacy_used = use_legacy;
 }
 
 void VertexArray::unbind()
 {
        const VertexArray *old = current();
        if(set_current(0))
-               apply_arrays(0, &old->arrays, 0, 0);
+               apply_arrays(0, &old->arrays, 0, 0, legacy_used);
 }
 
 
index 9fa55b7117c32fdc2901c74215223b6616f9fa53..d6dee7dd59ce3a9f3c81185aed2a405fa571277a 100644 (file)
@@ -39,6 +39,9 @@ private:
        std::vector<float> data;
        unsigned stride;
        std::vector<Array> arrays;
+       bool legacy;
+
+       static bool legacy_used;
 
        VertexArray(const VertexArray &);
        VertexArray &operator=(const VertexArray &);
@@ -68,10 +71,10 @@ public:
        const std::vector<float> &get_data() const { return data; }
        const float *operator[](unsigned i) const { return &data[0]+i*stride; }
 
-       void bind() const;
-       void apply() const { bind(); }
+       void bind() const { apply(); }
+       void apply(bool = true) const;
 private:
-       static void apply_arrays(const std::vector<Array> *, const std::vector<Array> *, const float *, unsigned);
+       static void apply_arrays(const std::vector<Array> *, const std::vector<Array> *, const float *, unsigned, bool);
 public:
        static void unbind();
 };