]> git.tdb.fi Git - libs/gl.git/blob - source/vertexarray.cpp
Remove support for legacy OpenGL features
[libs/gl.git] / source / vertexarray.cpp
1 #include <msp/gl/extensions/arb_multitexture.h>
2 #include <msp/gl/extensions/arb_vertex_shader.h>
3 #include "buffer.h"
4 #include "error.h"
5 #include "gl.h"
6 #include "mesh.h"
7 #include "vertexarray.h"
8
9 using namespace std;
10
11 namespace Msp {
12 namespace GL {
13
14 VertexArray::VertexArray(const VertexFormat &f)
15 {
16         reset(f);
17 }
18
19 VertexArray::~VertexArray()
20 {
21         /* Unbind accesses the current VertexArray, so a call from ~Bindable would
22         try to access destroyed data. */
23         if(current()==this)
24                 unbind();
25 }
26
27 void VertexArray::reset(const VertexFormat &f)
28 {
29         clear();
30         format = f;
31         stride = get_stride(format);
32
33         arrays.clear();
34
35         unsigned offs = 0;
36         for(const unsigned char *c=format.begin(); c!=format.end(); ++c)
37         {
38                 unsigned slot = get_array_slot(*c);
39                 if(slot>=arrays.size())
40                         arrays.resize(slot+1);
41
42                 Array &arr = arrays[slot];
43                 arr.component = *c;
44                 arr.offset = offs;
45
46                 offs += get_component_size(*c);
47         }
48 }
49
50 unsigned VertexArray::get_array_slot(unsigned char comp)
51 {
52         unsigned t = get_component_type(comp);
53         if(t==get_component_type(VERTEX3))
54                 return 0;
55         else if(t==get_component_type(NORMAL3))
56                 return 1;
57         else if(t==get_component_type(COLOR4_FLOAT))
58                 return 2;
59         else if(comp>=TEXCOORD1 && comp<=TEXCOORD4+12)
60         {
61                 t -= get_component_type(TEXCOORD1);
62                 if(t>0)
63                         static Require _req(ARB_multitexture);
64                 return 3+t;
65         }
66         else
67         {
68                 static Require _req(ARB_vertex_shader);
69                 if(comp>=ATTRIB1)
70                         t -= get_component_type(ATTRIB1);
71                 return 7+t;
72         }
73 }
74
75 void VertexArray::clear()
76 {
77         data.clear();
78 }
79
80 void VertexArray::reserve(unsigned n)
81 {
82         data.reserve(n*stride);
83 }
84
85 float *VertexArray::append()
86 {
87         data.insert(data.end(), stride, 0.0f);
88         update_offset();
89         dirty = true;
90         return &*(data.end()-stride);
91 }
92
93 float *VertexArray::modify(unsigned i)
94 {
95         dirty = true;
96         return &data[0]+i*stride;
97 }
98
99 unsigned VertexArray::get_data_size() const
100 {
101         return data.size()*sizeof(float);
102 }
103
104 void VertexArray::apply() const
105 {
106         if(format.empty())
107                 throw invalid_operation("VertexArray::apply");
108         // Don't mess up the vertex array object of a mesh
109         if(Mesh::current())
110                 throw invalid_operation("VertexArray::apply");
111
112         static Require _req(ARB_vertex_shader);
113
114         const VertexArray *old = current();
115         /* If the array has been modified, apply it even if it was the last one to
116         be applied.  This is necessary to get the data updated to vertex buffer, and
117         to resync things after a format change.  Radeon drivers also have some
118         problems with modifying vertex arrays without re-setting the pointers. */
119         if(!set_current(this) && !dirty)
120                 return;
121
122         const Buffer *vbuf = get_buffer();
123         Bind _bind_vbuf(vbuf, ARRAY_BUFFER);
124         if(vbuf && dirty)
125                 update_buffer();
126
127         const float *base = (vbuf ? reinterpret_cast<float *>(get_offset()) : &data[0]);
128         unsigned stride_bytes = stride*sizeof(float);
129         apply_arrays(&arrays, (old ? &old->arrays : 0), base, stride_bytes);
130 }
131
132 void VertexArray::apply_arrays(const vector<Array> *arrays, const vector<Array> *old_arrays, const float *base, unsigned stride_bytes)
133 {
134         unsigned n_arrays = arrays ? arrays->size() : 0;
135         if(old_arrays)
136                 n_arrays = max<unsigned>(n_arrays, old_arrays->size());
137         for(unsigned i=0; i<n_arrays; ++i)
138         {
139                 const Array *arr = ((arrays && i<arrays->size() && (*arrays)[i].component) ? &(*arrays)[i] : 0);
140                 const Array *old_arr = ((old_arrays && i<old_arrays->size() && (*old_arrays)[i].component) ? &(*old_arrays)[i] : 0);
141                 if(!arr && !old_arr)
142                         continue;
143
144                 unsigned char comp = (arr ? arr->component : old_arr->component);
145                 unsigned sz = get_component_size(comp);
146                 unsigned t = get_component_type(comp);
147
148                 if(t>=get_component_type(ATTRIB1))
149                         t -= get_component_type(ATTRIB1);
150                 if(arr)
151                 {
152                         if(arr->component==COLOR4_UBYTE)
153                                 glVertexAttribPointer(t, 4, GL_UNSIGNED_BYTE, true, stride_bytes, base+arr->offset);
154                         else
155                                 glVertexAttribPointer(t, sz, GL_FLOAT, false, stride_bytes, base+arr->offset);
156                 }
157
158                 // Only change enable state if needed
159                 if(arr && !old_arr)
160                         glEnableVertexAttribArray(t);
161                 else if(old_arr && !arr)
162                         glDisableVertexAttribArray(t);
163         }
164 }
165
166 void VertexArray::unbind()
167 {
168         const VertexArray *old = current();
169         if(set_current(0))
170                 apply_arrays(0, &old->arrays, 0, 0);
171 }
172
173
174 VertexArray::Array::Array():
175         component(0),
176         offset(0)
177 { }
178
179
180 VertexArray::Loader::Loader(VertexArray &a):
181         VertexArrayBuilder(a)
182 {
183         add("vertex", static_cast<void (Loader::*)(float, float)>(&Loader::vertex));
184         add("vertex", static_cast<void (Loader::*)(float, float, float)>(&Loader::vertex));
185         add("vertex", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::vertex));
186         add("normal", static_cast<void (Loader::*)(float, float, float)>(&Loader::normal));
187         add("texcoord", static_cast<void (Loader::*)(float)>(&Loader::texcoord));
188         add("texcoord", static_cast<void (Loader::*)(float, float)>(&Loader::texcoord));
189         add("texcoord", static_cast<void (Loader::*)(float, float, float)>(&Loader::texcoord));
190         add("texcoord", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::texcoord));
191         add("multitexcoord", static_cast<void (Loader::*)(unsigned, float)>(&Loader::multitexcoord));
192         add("multitexcoord", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::multitexcoord));
193         add("multitexcoord", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::multitexcoord));
194         add("multitexcoord", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::multitexcoord));
195         add("color", static_cast<void (Loader::*)(float, float, float)>(&Loader::color));
196         add("color", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::color));
197         add("attrib", static_cast<void (Loader::*)(unsigned, float)>(&Loader::attrib));
198         add("attrib", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::attrib));
199         add("attrib", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::attrib));
200         add("attrib", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::attrib));
201         add("tangent", static_cast<void (Loader::*)(float, float, float)>(&Loader::tangent));
202         add("binormal", static_cast<void (Loader::*)(float, float, float)>(&Loader::binormal));
203
204         add("vertex2",   static_cast<void (Loader::*)(float, float)>(&Loader::vertex));
205         add("vertex3",   static_cast<void (Loader::*)(float, float, float)>(&Loader::vertex));
206         add("vertex4",   static_cast<void (Loader::*)(float, float, float, float)>(&Loader::vertex));
207         add("normal3",   static_cast<void (Loader::*)(float, float, float)>(&Loader::normal));
208         add("texcoord1", static_cast<void (Loader::*)(float)>(&Loader::texcoord));
209         add("texcoord2", static_cast<void (Loader::*)(float, float)>(&Loader::texcoord));
210         add("texcoord3", static_cast<void (Loader::*)(float, float, float)>(&Loader::texcoord));
211         add("texcoord4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::texcoord));
212         add("multitexcoord1", static_cast<void (Loader::*)(unsigned, float)>(&Loader::multitexcoord));
213         add("multitexcoord2", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::multitexcoord));
214         add("multitexcoord3", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::multitexcoord));
215         add("multitexcoord4", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::multitexcoord));
216         add("color3",    static_cast<void (Loader::*)(float, float, float)>(&Loader::color));
217         add("color4",    static_cast<void (Loader::*)(float, float, float, float)>(&Loader::color));
218         add("attrib1",   static_cast<void (Loader::*)(unsigned, float)>(&Loader::attrib));
219         add("attrib2",   static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::attrib));
220         add("attrib3",   static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::attrib));
221         add("attrib4",   static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::attrib));
222         add("tangent3",  static_cast<void (Loader::*)(float, float, float)>(&Loader::tangent));
223         add("binormal3", static_cast<void (Loader::*)(float, float, float)>(&Loader::binormal));
224 }
225
226 } // namespace GL
227 } // namespace Msp